[cairo-commit] src/cairo-cff-subset.c src/cairo-ft-font.c src/cairoint.h src/cairo-truetype-subset.c src/cairo-type1-subset.c src/win32

Adrian Johnson ajohnson at kemper.freedesktop.org
Sat May 27 23:48:10 UTC 2017


 src/cairo-cff-subset.c       |   13 ++++++--
 src/cairo-ft-font.c          |   67 +++++++++++++++++++++++++++++++++++++++++--
 src/cairo-truetype-subset.c  |   13 ++++++--
 src/cairo-type1-subset.c     |   14 ++++++--
 src/cairoint.h               |    8 +++--
 src/win32/cairo-win32-font.c |   12 ++++---
 6 files changed, 107 insertions(+), 20 deletions(-)

New commits:
commit 0fd0fd0ae9ad8cfb177bb844091de98c0235917e
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun May 28 09:07:54 2017 +0930

    subsetting: support variable fonts
    
    If the font is a non default variant, fallback to creating a font from
    the outlines.

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 775ca61b..bd3bfde7 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -2788,13 +2788,20 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
 {
     const cairo_scaled_font_backend_t *backend;
     cairo_int_status_t status;
+    cairo_bool_t is_synthetic;
     cairo_cff_font_t *font;
 
     backend = scaled_font_subset->scaled_font->backend;
 
-    /* We need to use a fallback font generated from the synthesized outlines. */
-    if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    /* We need to use a fallback font if this font differs from the CFF outlines. */
+    if (backend->is_synthetic) {
+	status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+	if (unlikely (status))
+	    return status;
+
+	if (is_synthetic)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     font = calloc (1, sizeof (cairo_cff_font_t));
     if (unlikely (font == NULL))
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 74d43cc2..5b367e7b 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -58,6 +58,7 @@
 #include FT_BITMAP_H
 #include FT_TRUETYPE_TABLES_H
 #include FT_XFREE86_H
+#include FT_MULTIPLE_MASTERS_H
 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
 #include FT_SYNTHESIS_H
 #endif
@@ -2595,11 +2596,71 @@ _cairo_ft_index_to_ucs4(void	        *abstract_font,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_bool_t
-_cairo_ft_is_synthetic (void	        *abstract_font)
+static cairo_int_status_t
+_cairo_ft_is_synthetic (void	        *abstract_font,
+			cairo_bool_t    *is_synthetic)
 {
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_ft_scaled_font_t *scaled_font = abstract_font;
-    return scaled_font->ft_options.synth_flags != 0;
+    cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+    FT_Face face;
+    FT_Error error;
+
+    if (scaled_font->ft_options.synth_flags != 0) {
+	*is_synthetic = TRUE;
+	return status;
+    }
+
+    *is_synthetic = FALSE;
+    face = _cairo_ft_unscaled_font_lock_face (unscaled);
+    if (!face)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
+	FT_MM_Var *mm_var = NULL;
+	FT_Fixed *coords = NULL;
+	int num_axis, i;
+
+	/* If this is an MM or variable font we can't assume the current outlines
+	 * are the same as the font tables */
+	*is_synthetic = TRUE;
+
+	error = FT_Get_MM_Var (face, &mm_var);
+	if (error) {
+	    status = _cairo_error (_ft_to_cairo_error (error));
+	    goto cleanup;
+	}
+
+	num_axis = mm_var->num_axis;
+	coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed));
+	if (!coords) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto cleanup;
+	}
+
+#if FREETYPE_MAJOR > 2 || ( FREETYPE_MAJOR == 2 &&  FREETYPE_MINOR >= 8)
+	/* If FT_Get_Var_Design_Coordinates() is available, we can check if the
+	 * current design coordinates are the default coordinates. In this case
+	 * the current outlines match the font tables.
+	 */
+	FT_Get_Var_Design_Coordinates (face, num_axis, coords);
+	*is_synthetic = FALSE;
+	for (i = 0; i < num_axis; i++) {
+	    if (coords[i] != mm_var->axis[i].def) {
+		*is_synthetic = TRUE;
+		break;
+	    }
+	}
+#endif
+
+      cleanup:
+	free (coords);
+	free (mm_var);
+    }
+
+    _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+    return status;
 }
 
 static cairo_int_status_t
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index afd396e1..62902cf7 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -138,6 +138,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
 			     cairo_truetype_font_t      **font_return)
 {
     cairo_status_t status;
+    cairo_bool_t is_synthetic;
     cairo_truetype_font_t *font;
     const cairo_scaled_font_backend_t *backend;
     tt_head_t head;
@@ -158,9 +159,15 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
      *   return CAIRO_INT_STATUS_UNSUPPORTED;
      */
 
-    /* We need to use a fallback font generated from the synthesized outlines. */
-    if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font))
-       return CAIRO_INT_STATUS_UNSUPPORTED;
+    /* We need to use a fallback font if this font differs from the glyf outlines. */
+    if (backend->is_synthetic) {
+	status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+	if (unlikely (status))
+	    return status;
+
+	if (is_synthetic)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     size = sizeof (tt_head_t);
     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index b1566350..16f821d9 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1715,14 +1715,20 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
 {
     cairo_type1_font_subset_t font;
     cairo_status_t status;
+    cairo_bool_t is_synthetic;
     unsigned long length;
     unsigned int i;
     char buf[30];
 
-    /* We need to use a fallback font generated from the synthesized outlines. */
-    if (scaled_font_subset->scaled_font->backend->is_synthetic &&
-	scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    /* We need to use a fallback font if this font differs from the type1 outlines. */
+    if (scaled_font_subset->scaled_font->backend->is_synthetic) {
+	status = scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic);
+	if (unlikely (status))
+	    return status;
+
+	if (is_synthetic)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     status = _cairo_type1_font_subset_init (&font, scaled_font_subset, hex_encode);
     if (unlikely (status))
diff --git a/src/cairoint.h b/src/cairoint.h
index 1ae045c9..4fedf861 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -562,8 +562,12 @@ struct _cairo_scaled_font_backend {
 		     unsigned long               index,
                      uint32_t                   *ucs4);
 
-    cairo_warn cairo_bool_t
-    (*is_synthetic)(void                       *scaled_font);
+    /* Determine if this scaled font differs from the outlines in the font tables.
+     * eg synthesized bold/italic or a non default variant of a variable font.
+     */
+    cairo_warn cairo_int_status_t
+    (*is_synthetic)(void                       *scaled_font,
+		    cairo_bool_t               *is_synthetic);
 
     /* For type 1 fonts, return the glyph name for a given glyph index.
      * A glyph index and list of glyph names in the Type 1 fonts is provided.
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index f5bd22c3..1b86b810 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -1450,8 +1450,9 @@ exit1:
     return status;
 }
 
-static cairo_bool_t
-_cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
+static cairo_int_status_t
+_cairo_win32_scaled_font_is_synthetic (void	        *abstract_font,
+				       cairo_bool_t    *is_synthetic)
 {
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     cairo_status_t status;
@@ -1459,6 +1460,7 @@ _cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
     cairo_bool_t bold;
     cairo_bool_t italic;
 
+    *is_synthetic = FALSE;
     status = _cairo_truetype_get_style (&scaled_font->base,
 					&weight,
 					&bold,
@@ -1466,13 +1468,13 @@ _cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
     /* If this doesn't work assume it is not synthetic to avoid
      * unnecessary subsetting fallbacks. */
     if (status != CAIRO_STATUS_SUCCESS)
-	return FALSE;
+	return CAIRO_STATUS_SUCCESS;
 
     if (scaled_font->logfont.lfWeight != weight ||
 	scaled_font->logfont.lfItalic != italic)
-	return TRUE;
+	*is_synthetic = TRUE;
 
-    return FALSE;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t


More information about the cairo-commit mailing list