[cairo-commit] 3 commits - src/cairo-cff-subset.c src/cairo-ft-font.c src/cairo.h src/cairoint.h src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h src/cairo-scaled-font-subsets-private.h src/cairo-surface.c src/cairo-truetype-subset.c src/cairo-truetype-subset-private.h src/cairo-type1-subset.c src/cairo-win32-font.c

Adrian Johnson ajohnson at kemper.freedesktop.org
Mon Nov 22 05:46:36 PST 2010


 src/cairo-cff-subset.c                  |    4 +++
 src/cairo-ft-font.c                     |   14 ++++++++++-
 src/cairo-pdf-surface-private.h         |    2 +
 src/cairo-pdf-surface.c                 |   38 ++++++++++++++++++++++++++++++--
 src/cairo-scaled-font-subsets-private.h |   23 +++++++++++++++++++
 src/cairo-surface.c                     |    8 ++++++
 src/cairo-truetype-subset-private.h     |   13 ++++++++++
 src/cairo-truetype-subset.c             |   36 ++++++++++++++++++++++++++++++
 src/cairo-type1-subset.c                |    5 ++++
 src/cairo-win32-font.c                  |   27 ++++++++++++++++++++++
 src/cairo.h                             |    1 
 src/cairoint.h                          |    3 ++
 12 files changed, 171 insertions(+), 3 deletions(-)

New commits:
commit 1effa1e8230e16c59ce5f42692095f7fb6622c99
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Nov 23 00:13:56 2010 +1030

    win32: add synthetic font subsetting support

diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 45fded9..5277394 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -714,6 +714,29 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t   *scaled_font,
 				char		     **ps_name,
 				char		     **font_name);
 
+/**
+ * _cairo_truetype_get_style:
+ * @scaled_font: the #cairo_scaled_font_t
+ * @weight: returns the font weight from the OS/2 table
+ * @bold: returns true if font is bold
+ * @italic: returns true if font is italic
+ *
+ * If the font is a truetype/opentype font with an OS/2 table, get the
+ * weight, bold, and italic data from the OS/2 table.  The weight
+ * values have the same meaning as the lfWeight field of the Windows
+ * LOGFONT structure.  Refer to the TrueType Specification for
+ * definition of the weight values.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if successful,
+ * %CAIRO_INT_STATUS_UNSUPPORTED if the font is not TrueType/OpenType
+ * or the OS/2 table is not present.
+ **/
+cairo_private cairo_int_status_t
+_cairo_truetype_get_style (cairo_scaled_font_t  	 *scaled_font,
+			   int				 *weight,
+			   cairo_bool_t			 *bold,
+			   cairo_bool_t			 *italic);
+
 #endif /* CAIRO_HAS_FONT_SUBSET */
 
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-truetype-subset-private.h b/src/cairo-truetype-subset-private.h
index aed60d0..dc95732 100644
--- a/src/cairo-truetype-subset-private.h
+++ b/src/cairo-truetype-subset-private.h
@@ -64,6 +64,7 @@
 #define TT_TAG_loca   MAKE_TT_TAG('l','o','c','a')
 #define TT_TAG_maxp   MAKE_TT_TAG('m','a','x','p')
 #define TT_TAG_name   MAKE_TT_TAG('n','a','m','e')
+#define TT_TAG_OS2    MAKE_TT_TAG('O','S','/','2')
 #define TT_TAG_post   MAKE_TT_TAG('p','o','s','t')
 #define TT_TAG_prep   MAKE_TT_TAG('p','r','e','p')
 
@@ -174,6 +175,18 @@ typedef struct _tt_name {
 } tt_name_t;
 
 
+/* bitmask for fsSelection field */
+#define TT_FS_SELECTION_ITALIC   1
+#define TT_FS_SELECTION_BOLD    32
+
+/* _unused fields are defined in TT spec but not used by cairo */
+typedef struct _tt_os2 {
+    uint16_t   _unused1[2];
+    uint16_t   usWeightClass;
+    uint16_t   _unused2[28];
+    uint16_t   fsSelection;
+    uint16_t   _unused3[11];
+} tt_os2_t;
 
 /* composite_glyph_t flags */
 #define TT_ARG_1_AND_2_ARE_WORDS     0x0001
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 7777996..a041b16 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1502,4 +1502,36 @@ fail:
     return status;
 }
 
+cairo_int_status_t
+_cairo_truetype_get_style (cairo_scaled_font_t  	 *scaled_font,
+			   int				 *weight,
+			   cairo_bool_t			 *bold,
+			   cairo_bool_t			 *italic)
+{
+    cairo_status_t status;
+    const cairo_scaled_font_backend_t *backend;
+    tt_os2_t os2;
+    unsigned long size;
+    uint16_t selection;
+
+    backend = scaled_font->backend;
+    if (!backend->load_truetype_table)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    size = sizeof (os2);
+    status = backend->load_truetype_table (scaled_font,
+					   TT_TAG_OS2, 0,
+					   (unsigned char *) &os2,
+					   &size);
+    if (status)
+	return status;
+
+    *weight = be16_to_cpu (os2.usWeightClass);
+    selection = be16_to_cpu (os2.fsSelection);
+    *bold = (selection & TT_FS_SELECTION_BOLD) ? TRUE : FALSE;
+    *italic = (selection & TT_FS_SELECTION_ITALIC) ? TRUE : FALSE;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 #endif /* CAIRO_HAS_FONT_SUBSET */
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 7af252b..fcd7b56 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -46,6 +46,7 @@
 
 #include "cairo-win32-private.h"
 #include "cairo-error-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 #include <wchar.h>
 
@@ -1623,6 +1624,31 @@ exit1:
     return status;
 }
 
+static cairo_bool_t
+_cairo_win32_scaled_font_is_synthetic (void	       *abstract_font)
+{
+    cairo_win32_scaled_font_t *scaled_font = abstract_font;
+    cairo_status_t status;
+    int	weight;
+    cairo_bool_t bold;
+    cairo_bool_t italic;
+
+    status = _cairo_truetype_get_style (&scaled_font->base,
+					&weight,
+					&bold,
+					&italic);
+    /* If this doesn't work assume it is not synthetic to avoid
+     * unneccessary subsetting fallbacks. */
+    if (status != CAIRO_STATUS_SUCCESS)
+	return FALSE;
+
+    if (scaled_font->logfont.lfWeight != weight ||
+	scaled_font->logfont.lfItalic != italic)
+	return TRUE;
+
+    return FALSE;
+}
+
 static cairo_status_t
 _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
                                              cairo_scaled_glyph_t      *scaled_glyph)
@@ -1871,6 +1897,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
     _cairo_win32_scaled_font_show_glyphs,
     _cairo_win32_scaled_font_load_truetype_table,
     _cairo_win32_scaled_font_index_to_ucs4,
+    _cairo_win32_scaled_font_is_synthetic
 };
 
 /* #cairo_win32_font_face_t */
commit 7f0029c31e15dfd34f57bdeca18f27e9e7b8f9aa
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Nov 22 22:46:54 2010 +1030

    Use fallback font for synthetic fonts
    
    If the font has been synthesized we can't use the native subsetters as
    the outlines won't be the same. Instead force the use of the fallback
    subsetters so the synthesized outlines will used to generate the font.

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index f2ec374..a01d55e 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1906,6 +1906,10 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t  *scaled_font_subset,
     if (!backend->load_truetype_table)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
+    /* We need to use a fallback font generated from the synthesized outlines. */
+    if (backend->is_synthetic (scaled_font_subset->scaled_font))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     data_length = 0;
     status = backend->load_truetype_table( scaled_font_subset->scaled_font,
                                            TT_TAG_CFF, 0, NULL, &data_length);
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 67eb275..054da25 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2418,6 +2418,17 @@ _cairo_ft_index_to_ucs4(void	        *abstract_font,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+_cairo_ft_is_synthetic (void	        *abstract_font)
+{
+    cairo_ft_scaled_font_t *scaled_font = abstract_font;
+
+    if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
+	return TRUE;
+    else
+	return FALSE;
+}
+
 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     CAIRO_FONT_TYPE_FT,
     _cairo_ft_scaled_font_fini,
@@ -2426,7 +2437,8 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
     _cairo_ft_ucs4_to_index,
     NULL,			/* show_glyphs */
     _cairo_ft_load_truetype_table,
-    _cairo_ft_index_to_ucs4
+    _cairo_ft_index_to_ucs4,
+    _cairo_ft_is_synthetic
 };
 
 /* #cairo_ft_font_face_t */
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 55f97b0..7777996 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -156,6 +156,10 @@ _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 (scaled_font_subset->scaled_font))
+       return CAIRO_INT_STATUS_UNSUPPORTED;
+
     size = sizeof (tt_head_t);
     status = backend->load_truetype_table (scaled_font_subset->scaled_font,
                                           TT_TAG_head, 0,
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index f619d74..e0b1bf8 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1151,6 +1151,11 @@ _cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
     if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font))
         return CAIRO_INT_STATUS_UNSUPPORTED;
 
+    /* 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;
+
     unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
 
     status = _cairo_type1_font_subset_init (&font, unscaled_font, scaled_font_subset, hex_encode);
diff --git a/src/cairoint.h b/src/cairoint.h
index e2946cf..5a43561 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -515,6 +515,9 @@ struct _cairo_scaled_font_backend {
     (*index_to_ucs4)(void                       *scaled_font,
 		     unsigned long               index,
                      uint32_t                   *ucs4);
+
+    cairo_warn cairo_bool_t
+    (*is_synthetic)(void                       *scaled_font);
 };
 
 struct _cairo_font_face_backend {
commit 9862c38fc71c6dcd444da3b079e5404cd14594c3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Nov 2 22:39:57 2010 +1030

    Add unique_id mime type
    
    to ensure surfaces with the same unique_id mime type are not embedded
    more than once in PDF files.

diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 221418e..5c70ef9 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -67,6 +67,8 @@ typedef struct _cairo_pdf_group_resources {
 typedef struct _cairo_pdf_source_surface_entry {
     cairo_hash_entry_t base;
     unsigned int id;
+    const unsigned char *unique_id;
+    unsigned long unique_id_length;
     cairo_bool_t interpolate;
     cairo_pdf_resource_t surface_res;
     int width;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ae70a47..f048dc8 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1039,13 +1039,24 @@ _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b)
     const cairo_pdf_source_surface_entry_t *a = key_a;
     const cairo_pdf_source_surface_entry_t *b = key_b;
 
-    return (a->id == b->id) && (a->interpolate == b->interpolate);
+    if (a->interpolate != b->interpolate)
+	return FALSE;
+
+    if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length)
+	return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0);
+
+    return (a->id == b->id);
 }
 
 static void
 _cairo_pdf_source_surface_init_key (cairo_pdf_source_surface_entry_t *key)
 {
-    key->base.hash = key->id;
+    if (key->unique_id && key->unique_id_length > 0) {
+	key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE,
+					    key->unique_id, key->unique_id_length);
+    } else {
+	key->base.hash = key->id;
+    }
 }
 
 static cairo_int_status_t
@@ -1146,6 +1157,8 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
     cairo_pdf_source_surface_entry_t *surface_entry;
     cairo_status_t status;
     cairo_bool_t interpolate;
+    const unsigned char *unique_id;
+    unsigned long unique_id_length;
 
     switch (filter) {
     default:
@@ -1163,6 +1176,8 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 
     surface_key.id  = source->unique_id;
     surface_key.interpolate = interpolate;
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_UNIQUE_ID,
+				 &surface_key.unique_id, &surface_key.unique_id_length);
     _cairo_pdf_source_surface_init_key (&surface_key);
     surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base);
     if (surface_entry) {
@@ -1179,6 +1194,22 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 
     surface_entry->id = surface_key.id;
     surface_entry->interpolate = interpolate;
+    cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_UNIQUE_ID,
+				 &unique_id, &unique_id_length);
+    if (unique_id && unique_id_length > 0) {
+	surface_entry->unique_id = malloc (unique_id_length);
+	if (surface_entry->unique_id == NULL) {
+	    cairo_surface_destroy (source);
+	    free (surface_entry);
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	}
+
+	surface_entry->unique_id_length = unique_id_length;
+	memcpy (surface_entry->unique_id, unique_id, unique_id_length);
+    } else {
+	surface_entry->unique_id = NULL;
+	surface_entry->unique_id_length = 0;
+    }
     _cairo_pdf_source_surface_init_key (surface_entry);
 
     src_surface.hash_entry = surface_entry;
@@ -1631,6 +1662,9 @@ _cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
     cairo_hash_table_t *patterns = closure;
 
     _cairo_hash_table_remove (patterns, &surface_entry->base);
+    if (surface_entry->unique_id)
+	free (surface_entry->unique_id);
+
     free (surface_entry);
 }
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 2293991..76f6447 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -892,6 +892,14 @@ _cairo_mime_data_destroy (void *ptr)
  */
 
 /**
+ * CAIRO_MIME_TYPE_UNIQUE_ID:
+ *
+ * Unique identifier for a surface (cairo specific MIME type).
+ *
+ * @Since: 1.12
+ */
+
+/**
  * cairo_surface_set_mime_data:
  * @surface: a #cairo_surface_t
  * @mime_type: the MIME type of the image data
diff --git a/src/cairo.h b/src/cairo.h
index 136c5db..a45bf14 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -2155,6 +2155,7 @@ cairo_surface_set_user_data (cairo_surface_t		 *surface,
 #define CAIRO_MIME_TYPE_PNG "image/png"
 #define CAIRO_MIME_TYPE_JP2 "image/jp2"
 #define CAIRO_MIME_TYPE_URI "text/x-uri"
+#define CAIRO_MIME_TYPE_UNIQUE_ID "application/x-cairo.uuid"
 
 cairo_public void
 cairo_surface_get_mime_data (cairo_surface_t		*surface,


More information about the cairo-commit mailing list