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

Adrian Johnson ajohnson at kemper.freedesktop.org
Wed Oct 6 05:15:03 PDT 2010


 src/cairo-cff-subset.c                  |  410 +++++++++++++++++++++++++++-----
 src/cairo-pdf-surface.c                 |  142 +++++++----
 src/cairo-ps-surface.c                  |   38 ++
 src/cairo-scaled-font-subsets-private.h |    6 
 src/cairo-scaled-font-subsets.c         |   43 +--
 src/cairo-type1-subset.c                |   13 -
 src/cairoint.h                          |    2 
 7 files changed, 513 insertions(+), 141 deletions(-)

New commits:
commit 390a6aa99771615763ed7349060e493f15c1d6d3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Wed Oct 6 22:43:36 2010 +1030

    remove unused variable

diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index a019851..5987a99 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -722,21 +722,9 @@ _cairo_sub_font_collect (void *entry, void *closure)
 	    subset.latin_to_subset_glyph_index = NULL;
 	}
 
-        /* No need to check for out of memory here. If to_unicode is NULL, the PDF
-         * surface does not emit an ToUnicode stream */
-        subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long));
-        if (subset.to_unicode) {
-            for (j = 0; j < collection->num_glyphs; j++) {
-                /* default unicode character required when mapping fails */
-                subset.to_unicode[j] = 0xfffd;
-            }
-        }
         collection->status = (collection->font_subset_callback) (&subset,
 					    collection->font_subset_callback_closure);
 
-        if (subset.to_unicode != NULL)
-            free (subset.to_unicode);
-
 	if (subset.glyph_names != NULL) {
             for (j = 0; j < collection->num_glyphs; j++)
 		free (subset.glyph_names[j]);
diff --git a/src/cairoint.h b/src/cairoint.h
index 73386d1..2bb88d3 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -433,8 +433,6 @@ typedef struct _cairo_scaled_font_subset {
      * Value of glyphs array is scaled_font_glyph_index.
      */
     unsigned long *glyphs;
-
-    unsigned long *to_unicode;
     char          **utf8;
     char          **glyph_names;
     int           *to_latin_char;
commit ea45bc1b4b655b6e85be14669fdea97da2b6edae
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Aug 3 13:41:17 2010 +0930

    PS: Allow %%BoundingBox and %%PageBoundingBox to be overriden using DSC comments

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index b8f1a53..1ab5cb6 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -169,6 +169,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
     int i, num_comments;
     int level;
     const char *eps_header = "";
+    cairo_bool_t has_bbox;
 
     if (surface->has_creation_date)
 	now = surface->creation_date;
@@ -187,16 +188,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 				 "%%!PS-Adobe-3.0%s\n"
 				 "%%%%Creator: cairo %s (http://cairographics.org)\n"
 				 "%%%%CreationDate: %s"
-				 "%%%%Pages: %d\n"
-				 "%%%%BoundingBox: %d %d %d %d\n",
+				 "%%%%Pages: %d\n",
 				 eps_header,
 				 cairo_version_string (),
 				 ctime_r (&now, ctime_buf),
-				 surface->num_pages,
-				 surface->bbox_x1,
-				 surface->bbox_y1,
-				 surface->bbox_x2,
-				 surface->bbox_y2);
+				 surface->num_pages);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%DocumentData: Clean7Bit\n"
@@ -224,15 +220,28 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 	}
     }
 
+    has_bbox = FALSE;
     num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
     comments = _cairo_array_index (&surface->dsc_header_comments, 0);
     for (i = 0; i < num_comments; i++) {
 	_cairo_output_stream_printf (surface->final_stream,
 				     "%s\n", comments[i]);
+	if (strncmp (comments[i], "%%BoundingBox:", 14) == 0)
+	    has_bbox = TRUE;
+
 	free (comments[i]);
 	comments[i] = NULL;
     }
 
+    if (!has_bbox) {
+	_cairo_output_stream_printf (surface->final_stream,
+				     "%%%%BoundingBox: %d %d %d %d\n",
+				     surface->bbox_x1,
+				     surface->bbox_y1,
+				     surface->bbox_x2,
+				     surface->bbox_y2);
+    }
+
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%EndComments\n");
 
@@ -3795,7 +3804,7 @@ _cairo_ps_surface_set_bounding_box (void		*abstract_surface,
     int i, num_comments;
     char **comments;
     int x1, y1, x2, y2;
-    cairo_bool_t has_page_media;
+    cairo_bool_t has_page_media, has_page_bbox;
     const char *page_media;
 
     if (surface->eps) {
@@ -3824,6 +3833,7 @@ _cairo_ps_surface_set_bounding_box (void		*abstract_surface,
 				 "%%%%BeginPageSetup\n");
 
     has_page_media = FALSE;
+    has_page_bbox = FALSE;
     num_comments = _cairo_array_num_elements (&surface->dsc_page_setup_comments);
     comments = _cairo_array_index (&surface->dsc_page_setup_comments, 0);
     for (i = 0; i < num_comments; i++) {
@@ -3831,6 +3841,10 @@ _cairo_ps_surface_set_bounding_box (void		*abstract_surface,
 				     "%s\n", comments[i]);
 	if (strncmp (comments[i], "%%PageMedia:", 11) == 0)
 	    has_page_media = TRUE;
+
+	if (strncmp (comments[i], "%%PageBoundingBox:", 18) == 0)
+	    has_page_bbox = TRUE;
+
 	free (comments[i]);
 	comments[i] = NULL;
     }
@@ -3846,9 +3860,11 @@ _cairo_ps_surface_set_bounding_box (void		*abstract_surface,
 				     page_media);
     }
 
-    _cairo_output_stream_printf (surface->stream,
-				 "%%%%PageBoundingBox: %d %d %d %d\n",
-				 x1, y1, x2, y2);
+    if (!has_page_bbox) {
+	_cairo_output_stream_printf (surface->stream,
+				     "%%%%PageBoundingBox: %d %d %d %d\n",
+				     x1, y1, x2, y2);
+    }
 
     _cairo_output_stream_printf (surface->stream,
                                  "%%%%EndPageSetup\n"
commit b950212a2a6aca7784b637d93b13b10daef8d801
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Oct 4 23:11:56 2010 +1030

    CFF subset: add support for latin subsets

diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 48cab14..e3a0e4b 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -739,9 +739,9 @@ cairo_cff_font_read_private_dict (cairo_cff_font_t   *font,
 	if (unlikely (status))
 	    return status;
 
-        /* Use maximum sized encoding to reserve space for later modification. */
-        end_buf = encode_integer_max (buf, 0);
-        status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
+	/* Use maximum sized encoding to reserve space for later modification. */
+	end_buf = encode_integer_max (buf, 0);
+	status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
 	if (unlikely (status))
 	    return status;
     }
@@ -936,22 +936,36 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
 	goto fail;
 
     status = cff_dict_set_operands (font->top_dict,
-	                            FDSELECT_OP, buf, end_buf - buf);
+	                            CHARSET_OP, buf, end_buf - buf);
     if (unlikely (status))
 	goto fail;
 
-    status = cff_dict_set_operands (font->top_dict,
-	                            FDARRAY_OP, buf, end_buf - buf);
-    if (unlikely (status))
-	goto fail;
+    if (font->scaled_font_subset->is_latin) {
+        status = cff_dict_set_operands (font->top_dict,
+                                        ENCODING_OP, buf, end_buf - buf);
+        if (unlikely (status))
+            goto fail;
 
-    status = cff_dict_set_operands (font->top_dict,
-	                            CHARSET_OP, buf, end_buf - buf);
-    if (unlikely (status))
-	goto fail;
+	/* Private has two operands - size and offset */
+	end_buf = encode_integer_max (end_buf, 0);
+	cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
+        if (unlikely (status))
+            goto fail;
 
-    cff_dict_remove (font->top_dict, ENCODING_OP);
-    cff_dict_remove (font->top_dict, PRIVATE_OP);
+    } else {
+        status = cff_dict_set_operands (font->top_dict,
+                                        FDSELECT_OP, buf, end_buf - buf);
+        if (unlikely (status))
+            goto fail;
+
+        status = cff_dict_set_operands (font->top_dict,
+                                        FDARRAY_OP, buf, end_buf - buf);
+        if (unlikely (status))
+            goto fail;
+
+        cff_dict_remove (font->top_dict, ENCODING_OP);
+        cff_dict_remove (font->top_dict, PRIVATE_OP);
+    }
 
     /* Remove the unique identifier operators as the subsetted font is
      * not the same is the original font. */
@@ -1238,20 +1252,28 @@ cairo_cff_font_subset_font (cairo_cff_font_t  *font)
 {
     cairo_status_t status;
 
-    status = cairo_cff_font_set_ros_strings (font);
-    if (unlikely (status))
-	return status;
+    if (!font->scaled_font_subset->is_latin) {
+	status = cairo_cff_font_set_ros_strings (font);
+	if (unlikely (status))
+	    return status;
+    }
 
     status = cairo_cff_font_subset_charstrings (font);
     if (unlikely (status))
         return status;
 
-    if (font->is_cid)
-        status = cairo_cff_font_subset_fontdict (font);
-    else
-        status = cairo_cff_font_create_cid_fontdict (font);
-    if (unlikely (status))
-	return status;
+    if (!font->scaled_font_subset->is_latin) {
+	if (font->is_cid)
+	    status = cairo_cff_font_subset_fontdict (font);
+	else
+	    status = cairo_cff_font_create_cid_fontdict (font);
+	if (unlikely (status))
+	    return status;
+    }  else {
+	font->private_dict_offset = malloc (sizeof (int));
+	if (unlikely (font->private_dict_offset == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     status = cairo_cff_font_subset_strings (font);
     if (unlikely (status))
@@ -1374,6 +1396,30 @@ cairo_cff_font_write_global_subrs (cairo_cff_font_t  *font)
 }
 
 static cairo_status_t
+cairo_cff_font_write_encoding (cairo_cff_font_t  *font)
+{
+    unsigned char buf[2];
+    cairo_status_t status;
+    unsigned int i;
+
+    cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP);
+    buf[0] = 0; /* Format 0 */
+    buf[1] = font->scaled_font_subset->num_glyphs - 1;
+    status = _cairo_array_append_multiple (&font->output, buf, 2);
+    if (unlikely (status))
+	return status;
+
+    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
+	unsigned char ch = font->scaled_font_subset->to_latin_char[i];
+        status = _cairo_array_append (&font->output, &ch);
+        if (unlikely (status))
+            return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 cairo_cff_font_write_fdselect (cairo_cff_font_t  *font)
 {
     unsigned char data;
@@ -1426,8 +1472,100 @@ cairo_cff_font_write_fdselect (cairo_cff_font_t  *font)
     return CAIRO_STATUS_SUCCESS;
 }
 
+/* Winansi to CFF standard strings mapping for characters 128 to 255 */
+const int winansi_to_cff_std_string[] = {
+	/* 128 */
+      0,   0, 117, 101, 118, 121, 112, 113,
+    126, 122, 192, 107, 142,   0, 199,   0,
+	/* 144 */
+      0,  65,   8, 105, 119, 116, 111, 137,
+    127, 153, 221, 108, 148,   0, 228, 198,
+	/* 160 */
+      0,  96,  97,  98, 103, 100, 160, 102,
+    131, 170, 139, 106, 151,   0, 165, 128,
+	/* 176 */
+    161, 156, 164, 169, 125, 152, 115, 114,
+    133, 150, 143, 187, 158, 155, 163, 123,
+	/* 192 */
+    174, 171, 172, 176, 173, 175, 138, 177,
+    181, 178, 179, 180, 185, 182, 183, 184,
+	/* 208 */
+    154, 186, 190, 187, 188, 191, 189, 168,
+    141, 196, 193, 194, 195, 197, 157, 149,
+	/* 224 */
+    203, 200, 201, 205, 202, 204, 144, 206,
+    210, 207, 208, 209, 214, 211, 212, 213,
+	/* 240 */
+    167, 215, 219, 216, 217, 220, 218, 159,
+    147, 225, 222, 223, 224, 226, 162, 227,
+};
+
+static cairo_status_t
+cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t  *font, int ch, int *sid_out)
+{
+    int sid;
+    cairo_status_t status;
+    const char *euro = "Euro";
+
+    if (ch == 39) {
+	sid = 104;
+
+    } else if (ch == 96) {
+	sid = 124;
+
+    } else if (ch >= 32 && ch <= 126) {
+	sid = ch - 31;
+
+    } else if (ch == 128) {
+	sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+	status = cff_index_append_copy (&font->strings_subset_index,
+					(unsigned char *)euro, strlen(euro));
+	if (unlikely (status))
+	    return status;
+
+    } else if (ch >= 128 && ch <= 255) {
+	sid = winansi_to_cff_std_string[ch - 128];
+
+    } else {
+	sid = 0;
+    }
+
+    *sid_out = sid;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+cairo_cff_font_write_type1_charset (cairo_cff_font_t  *font)
+{
+    unsigned char format = 0;
+    unsigned int i;
+    int ch, sid;
+    cairo_status_t status;
+    uint16_t sid_be16;
+
+    cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
+    status = _cairo_array_append (&font->output, &format);
+    if (unlikely (status))
+	return status;
+
+    for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
+	ch = font->scaled_font_subset->to_latin_char[i];
+	status = cairo_cff_font_get_sid_for_winansi_char (font, ch, &sid);
+        if (unlikely (status))
+	    return status;
+
+	sid_be16 = cpu_to_be16(sid);
+	status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16));
+        if (unlikely (status))
+            return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_status_t
-cairo_cff_font_write_charset (cairo_cff_font_t  *font)
+cairo_cff_font_write_cid_charset (cairo_cff_font_t  *font)
 {
     unsigned char byte;
     uint16_t word;
@@ -1499,9 +1637,9 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
 
 static cairo_status_t
 cairo_cff_font_write_private_dict (cairo_cff_font_t   *font,
-                                   int                 dict_num,
-                                   cairo_hash_table_t *parent_dict,
-                                   cairo_hash_table_t *private_dict)
+				   int                 dict_num,
+				   cairo_hash_table_t *parent_dict,
+				   cairo_hash_table_t *private_dict)
 {
     int offset;
     int size;
@@ -1605,32 +1743,75 @@ cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t  *font)
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t  *font)
+{
+    cairo_int_status_t status;
+
+    status = cairo_cff_font_write_private_dict (font,
+						0,
+						font->top_dict,
+						font->private_dict);
+    if (unlikely (status))
+	return status;
+
+    status = cairo_cff_font_write_local_sub (font,
+					     0,
+					     font->private_dict,
+					     &font->local_sub_index);
+    if (unlikely (status))
+	return status;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
 typedef cairo_status_t
 (*font_write_t) (cairo_cff_font_t *font);
 
-static const font_write_t font_write_funcs[] = {
+static const font_write_t font_write_cid_funcs[] = {
     cairo_cff_font_write_header,
     cairo_cff_font_write_name,
     cairo_cff_font_write_top_dict,
     cairo_cff_font_write_strings,
     cairo_cff_font_write_global_subrs,
-    cairo_cff_font_write_charset,
+    cairo_cff_font_write_cid_charset,
     cairo_cff_font_write_fdselect,
     cairo_cff_font_write_charstrings,
     cairo_cff_font_write_cid_fontdict,
     cairo_cff_font_write_cid_private_dict_and_local_sub,
 };
 
+static const font_write_t font_write_type1_funcs[] = {
+    cairo_cff_font_write_header,
+    cairo_cff_font_write_name,
+    cairo_cff_font_write_top_dict,
+    cairo_cff_font_write_strings,
+    cairo_cff_font_write_global_subrs,
+    cairo_cff_font_write_encoding,
+    cairo_cff_font_write_type1_charset,
+    cairo_cff_font_write_charstrings,
+    cairo_cff_font_write_type1_private_dict_and_local_sub,
+};
+
 static cairo_status_t
 cairo_cff_font_write_subset (cairo_cff_font_t *font)
 {
     cairo_int_status_t status;
     unsigned int i;
 
-    for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
-        status = font_write_funcs[i] (font);
-        if (unlikely (status))
-            return status;
+    if (font->scaled_font_subset->is_latin) {
+        for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) {
+            status = font_write_type1_funcs[i] (font);
+            if (unlikely (status))
+                return status;
+        }
+    } else {
+        for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) {
+            status = font_write_cid_funcs[i] (font);
+            if (unlikely (status))
+                return status;
+        }
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -1984,6 +2165,12 @@ _cairo_cff_subset_init (cairo_cff_subset_t          *cff_subset,
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
 
+    {
+	FILE *f;
+	f=fopen("font.cff", "wb");
+	fwrite(data, length, 1, f);
+	fclose(f);
+    }
     cairo_cff_font_destroy (font);
 
     return CAIRO_STATUS_SUCCESS;
@@ -2012,23 +2199,90 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
 }
 
 cairo_bool_t
-_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font)
+_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
 {
     const cairo_scaled_font_backend_t *backend;
     cairo_status_t status;
+    unsigned char *data;
     unsigned long data_length;
+    unsigned char *current_ptr;
+    unsigned char *data_end;
+    cff_header_t  *header;
+    cff_index_element_t *element;
+    cairo_hash_table_t  *top_dict;
+    cairo_array_t index;
+    int size;
+    cairo_bool_t is_cid = FALSE;
 
     backend = scaled_font->backend;
     if (!backend->load_truetype_table)
 	return FALSE;
 
+    /* check for CFF font */
     data_length = 0;
     status = backend->load_truetype_table(scaled_font,
 					  TT_TAG_CFF, 0, NULL, &data_length);
     if (status)
-        return FALSE;;
+        return FALSE;
+
+    /* load CFF data */
+    data = malloc (data_length);
+    if (unlikely (data == NULL)) {
+        status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+        return FALSE;
+    }
+
+    status = backend->load_truetype_table (scaled_font, TT_TAG_CFF,
+					   0, data, &data_length);
+    if (unlikely (status))
+        goto fail1;
+
+    data_end = data + data_length;
+
+    /* skip header */
+    if (data_length < sizeof (cff_header_t))
+        goto fail1;
+
+    header = (cff_header_t *) data;
+    current_ptr = data + header->header_size;
+
+    /* skip name */
+    cff_index_init (&index);
+    status = cff_index_read (&index, &current_ptr, data_end);
+    cff_index_fini (&index);
+
+    if (status)
+        goto fail1;
+
+    /* read top dict */
+    cff_index_init (&index);
+    status = cff_index_read (&index, &current_ptr, data_end);
+    if (unlikely (status))
+        goto fail2;
+
+    status = cff_dict_init (&top_dict);
+    if (unlikely (status))
+	goto fail2;
 
-    return TRUE;
+    element = _cairo_array_index (&index, 0);
+    status = cff_dict_read (top_dict, element->data, element->length);
+    if (unlikely (status))
+        goto fail3;
+
+    /* check for ROS operator indicating a CID font */
+    if (cff_dict_get_operands (top_dict, ROS_OP, &size) != NULL)
+        is_cid = TRUE;
+
+fail3:
+    cff_dict_fini (top_dict);
+
+fail2:
+    cff_index_fini (&index);
+
+fail1:
+    free (data);
+
+    return is_cid;
 }
 
 static cairo_int_status_t
@@ -2133,8 +2387,9 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
     cff_header_t header;
     cairo_array_t *charstring;
     unsigned char buf[40];
-    unsigned char *end_buf;
+    unsigned char *end_buf, *end_buf2;
     unsigned int i;
+    int sid;
 
     /* Create header */
     header.major = 1;
@@ -2145,6 +2400,28 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
 
     /* Create Top Dict */
     font->is_cid = FALSE;
+
+    snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u",
+	     font->scaled_font_subset->font_id,
+	     font->scaled_font_subset->subset_id);
+    sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+    status = cff_index_append_copy (&font->strings_subset_index,
+                                    (unsigned char *)buf,
+                                    strlen((char*)buf));
+    if (unlikely (status))
+	return status;
+
+    end_buf = encode_integer (buf, sid);
+    status = cff_dict_set_operands (font->top_dict, FULLNAME_OP,
+				    buf, end_buf - buf);
+    if (unlikely (status))
+	return status;
+
+    status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP,
+				    buf, end_buf - buf);
+    if (unlikely (status))
+	return status;
+
     end_buf = encode_integer (buf, type2_subset->x_min);
     end_buf = encode_integer (end_buf, type2_subset->y_min);
     end_buf = encode_integer (end_buf, type2_subset->x_max);
@@ -2160,29 +2437,50 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t           *font,
     if (unlikely (status))
 	return status;
 
-    status = cff_dict_set_operands (font->top_dict,
-	                            FDSELECT_OP, buf, end_buf - buf);
-    if (unlikely (status))
-	return status;
 
-    status = cff_dict_set_operands (font->top_dict,
-	                            FDARRAY_OP, buf, end_buf - buf);
-    if (unlikely (status))
-	return status;
+    if (font->scaled_font_subset->is_latin) {
+	status = cff_dict_set_operands (font->top_dict,
+                                        ENCODING_OP, buf, end_buf - buf);
+        if (unlikely (status))
+	    return status;
+
+	/* Private has two operands - size and offset */
+	end_buf2 = encode_integer_max (end_buf, 0);
+	cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf2 - buf);
+        if (unlikely (status))
+	    return status;
+
+    } else {
+	status = cff_dict_set_operands (font->top_dict,
+					FDSELECT_OP, buf, end_buf - buf);
+	if (unlikely (status))
+	    return status;
+
+	status = cff_dict_set_operands (font->top_dict,
+					FDARRAY_OP, buf, end_buf - buf);
+	if (unlikely (status))
+	    return status;
+    }
 
     status = cff_dict_set_operands (font->top_dict,
 	                            CHARSET_OP, buf, end_buf - buf);
     if (unlikely (status))
 	return status;
 
-    status = cairo_cff_font_set_ros_strings (font);
-    if (unlikely (status))
-	return status;
+    if (!font->scaled_font_subset->is_latin) {
+	status = cairo_cff_font_set_ros_strings (font);
+	if (unlikely (status))
+	    return status;
 
-    /* Create CID FD dictionary */
-    status = cairo_cff_font_create_cid_fontdict (font);
-    if (unlikely (status))
-	return status;
+	/* Create CID FD dictionary */
+	status = cairo_cff_font_create_cid_fontdict (font);
+	if (unlikely (status))
+	    return status;
+    } else {
+	font->private_dict_offset = malloc (sizeof (int));
+	if (unlikely (font->private_dict_offset == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     /* Create charstrings */
     for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
@@ -2261,7 +2559,13 @@ _cairo_cff_fallback_init (cairo_cff_subset_t          *cff_subset,
 
     memcpy (cff_subset->data, data, length);
     cff_subset->data_length = length;
-    cff_subset->data_length = length;
+
+    {
+	FILE *f;
+	f=fopen("font.cff", "wb");
+	fwrite(data, length, 1, f);
+	fclose(f);
+    }
 
     _cairo_type2_charstrings_fini (&type2_subset);
     cairo_cff_font_destroy (font);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 7efae8b..6e377fa 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3888,7 +3888,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t		*surface,
     cairo_pdf_resource_t stream, descriptor, cidfont_dict;
     cairo_pdf_resource_t subset_resource, to_unicode_stream;
     cairo_pdf_font_t font;
-    unsigned int i;
+    unsigned int i, last_glyph;
     cairo_status_t status;
     char tag[10];
 
@@ -3903,6 +3903,8 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t		*surface,
     status = _cairo_pdf_surface_open_stream (surface,
 					     NULL,
 					     TRUE,
+					     font_subset->is_latin ?
+					     "   /Subtype /Type1C\n" :
 					     "   /Subtype /CIDFontType0C\n");
     if (unlikely (status))
 	return status;
@@ -3959,58 +3961,106 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t		*surface,
 				 (long)(subset->y_max*PDF_UNITS_PER_EM),
 				 stream.id);
 
-    cidfont_dict = _cairo_pdf_surface_new_object (surface);
-    if (cidfont_dict.id == 0)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (font_subset->is_latin) {
+	/* find last glyph used */
+	for (i = 255; i >= 32; i--)
+	    if (font_subset->latin_to_subset_glyph_index[i] > 0)
+		break;
 
-    _cairo_output_stream_printf (surface->output,
-                                 "%d 0 obj\n"
-                                 "<< /Type /Font\n"
-                                 "   /Subtype /CIDFontType0\n"
-                                 "   /BaseFont /%s+%s\n"
-                                 "   /CIDSystemInfo\n"
-                                 "   << /Registry (Adobe)\n"
-                                 "      /Ordering (Identity)\n"
-                                 "      /Supplement 0\n"
-                                 "   >>\n"
-                                 "   /FontDescriptor %d 0 R\n"
-                                 "   /W [0 [",
-                                 cidfont_dict.id,
-				 tag,
-                                 subset->ps_name,
-                                 descriptor.id);
+	last_glyph = i;
+	_cairo_pdf_surface_update_object (surface, subset_resource);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\r\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /Type1\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /FirstChar 32\n"
+				     "   /LastChar %d\n"
+				     "   /FontDescriptor %d 0 R\n"
+				     "   /Encoding /WinAnsiEncoding\n"
+				     "   /Widths [",
+				     subset_resource.id,
+				     tag,
+				     subset->ps_name,
+				     last_glyph,
+				     descriptor.id);
+
+	for (i = 32; i < last_glyph + 1; i++) {
+	    int glyph = font_subset->latin_to_subset_glyph_index[i];
+	    if (glyph > 0) {
+		_cairo_output_stream_printf (surface->output,
+					     " %ld",
+					     (long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
+	    } else {
+		_cairo_output_stream_printf (surface->output, " 0");
+	    }
+	}
 
-    for (i = 0; i < font_subset->num_glyphs; i++)
 	_cairo_output_stream_printf (surface->output,
-				     " %ld",
-                                     (long)(subset->widths[i]*PDF_UNITS_PER_EM));
+				     " ]\n");
 
-    _cairo_output_stream_printf (surface->output,
-                                 " ]]\n"
-				 ">>\n"
-				 "endobj\n");
+	if (to_unicode_stream.id != 0)
+	    _cairo_output_stream_printf (surface->output,
+					 "    /ToUnicode %d 0 R\n",
+					 to_unicode_stream.id);
 
-    _cairo_pdf_surface_update_object (surface, subset_resource);
-    _cairo_output_stream_printf (surface->output,
-				 "%d 0 obj\n"
-				 "<< /Type /Font\n"
-				 "   /Subtype /Type0\n"
-				 "   /BaseFont /%s+%s\n"
-                                 "   /Encoding /Identity-H\n"
-				 "   /DescendantFonts [ %d 0 R]\n",
-				 subset_resource.id,
-				 tag,
-				 subset->ps_name,
-				 cidfont_dict.id);
+	_cairo_output_stream_printf (surface->output,
+				     ">>\n"
+				     "endobj\n");
+    } else {
+	cidfont_dict = _cairo_pdf_surface_new_object (surface);
+	if (cidfont_dict.id == 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
-    if (to_unicode_stream.id != 0)
-        _cairo_output_stream_printf (surface->output,
-                                     "   /ToUnicode %d 0 R\n",
-                                     to_unicode_stream.id);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /CIDFontType0\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /CIDSystemInfo\n"
+				     "   << /Registry (Adobe)\n"
+				     "      /Ordering (Identity)\n"
+				     "      /Supplement 0\n"
+				     "   >>\n"
+				     "   /FontDescriptor %d 0 R\n"
+				     "   /W [0 [",
+				     cidfont_dict.id,
+				     tag,
+				     subset->ps_name,
+				     descriptor.id);
 
-    _cairo_output_stream_printf (surface->output,
-				 ">>\n"
-				 "endobj\n");
+	for (i = 0; i < font_subset->num_glyphs; i++)
+	    _cairo_output_stream_printf (surface->output,
+					 " %ld",
+					 (long)(subset->widths[i]*PDF_UNITS_PER_EM));
+
+	_cairo_output_stream_printf (surface->output,
+				     " ]]\n"
+				     ">>\n"
+				     "endobj\n");
+
+	_cairo_pdf_surface_update_object (surface, subset_resource);
+	_cairo_output_stream_printf (surface->output,
+				     "%d 0 obj\n"
+				     "<< /Type /Font\n"
+				     "   /Subtype /Type0\n"
+				     "   /BaseFont /%s+%s\n"
+				     "   /Encoding /Identity-H\n"
+				     "   /DescendantFonts [ %d 0 R]\n",
+				     subset_resource.id,
+				     tag,
+				     subset->ps_name,
+				     cidfont_dict.id);
+
+	if (to_unicode_stream.id != 0)
+	    _cairo_output_stream_printf (surface->output,
+					 "   /ToUnicode %d 0 R\n",
+					 to_unicode_stream.id);
+
+	_cairo_output_stream_printf (surface->output,
+				     ">>\n"
+				     "endobj\n");
+    }
 
     font.font_id = font_subset->font_id;
     font.subset_id = font_subset->subset_id;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 8de49fa..b1e06b7 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -387,13 +387,13 @@ cairo_private void
 _cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
 
 /**
- * _cairo_cff_scaled_font_is_cff:
+ * _cairo_cff_scaled_font_is_cid_cff:
  * @scaled_font: a #cairo_scaled_font_t
  *
- * Return %TRUE if @scaled_font is a CFF font, otherwise return %FALSE.
+ * Return %TRUE if @scaled_font is a CID CFF font, otherwise return %FALSE.
  **/
 cairo_bool_t
-_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font);
+_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font);
 
 /**
  * _cairo_cff_fallback_init:
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 79a778f..a019851 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -121,6 +121,7 @@ typedef struct _cairo_sub_font_collection {
     unsigned long *glyphs; /* scaled_font_glyph_index */
     char       **utf8;
     unsigned int glyphs_size;
+    int           *to_latin_char;
     unsigned long *latin_to_subset_glyph_index;
     unsigned int max_glyph;
     unsigned int num_glyphs;
@@ -232,6 +233,7 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
 
     collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
     collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
+    collection->to_latin_char[subset_glyph_index] = sub_font_glyph->latin_character;
     if (sub_font_glyph->is_latin)
 	collection->latin_to_subset_glyph_index[sub_font_glyph->latin_character] = subset_glyph_index;
 
@@ -296,8 +298,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t	*parent,
     sub_font->font_id = font_id;
 
     sub_font->use_latin_subset = parent->use_latin_subset;
-    if (_cairo_cff_scaled_font_is_cff (scaled_font))
-	sub_font->use_latin_subset = FALSE; /* CFF latin subsets are NYI */
+    if (_cairo_cff_scaled_font_is_cid_cff (scaled_font))
+	sub_font->use_latin_subset = FALSE; /* latin subsets of CID CFF fonts are not supported */
 
     if (sub_font->use_latin_subset)
 	sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
@@ -349,16 +351,20 @@ static unsigned int _winansi_0x80_to_0x9f[] = {
 };
 
 int
-_cairo_unicode_to_winansi (unsigned long unicode)
+_cairo_unicode_to_winansi (unsigned long uni)
 {
     int i;
 
-    if (unicode < 0x80 || (unicode >= 0xa0 && unicode <= 0xff))
-        return unicode;
+    /* exclude the extra "hyphen" at 0xad to avoid duplicate glyphnames */
+    if ((uni >= 0x20 && uni <= 0x7e) ||
+	(uni >= 0xa1 && uni <= 0xff && uni != 0xad))
+        return uni;
 
-    for (i = 0; i < 32; i++) {
-       if (_winansi_0x80_to_0x9f[i] == unicode)
-           return i + 0x80;
+    if (uni >= 0x80 && uni <= 0x9f) {
+	for (i = 0; i < 32; i++) {
+	    if (_winansi_0x80_to_0x9f[i] == uni)
+		return i + 0x80;
+	}
     }
 
     return -1;
@@ -709,8 +715,10 @@ _cairo_sub_font_collect (void *entry, void *closure)
 	subset.is_latin = FALSE;
 	if (sub_font->use_latin_subset && i == 0) {
 	    subset.is_latin = TRUE;
+	    subset.to_latin_char = collection->to_latin_char;
 	    subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
 	} else {
+	    subset.to_latin_char = NULL;
 	    subset.latin_to_subset_glyph_index = NULL;
 	}
 
@@ -1025,14 +1033,18 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
 
     collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
     collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
+    collection.to_latin_char = _cairo_malloc_ab (collection.glyphs_size, sizeof(int));
     collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long));
     if (unlikely (collection.glyphs == NULL ||
 		  collection.utf8 == NULL ||
+		  collection.to_latin_char == NULL ||
 		  collection.latin_to_subset_glyph_index == NULL)) {
 	if (collection.glyphs != NULL)
 	    free (collection.glyphs);
 	if (collection.utf8 != NULL)
 	    free (collection.utf8);
+	if (collection.to_latin_char != NULL)
+	    free (collection.to_latin_char);
 	if (collection.latin_to_subset_glyph_index != NULL)
 	    free (collection.latin_to_subset_glyph_index);
 
@@ -1056,6 +1068,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
     }
     free (collection.utf8);
     free (collection.glyphs);
+    free (collection.to_latin_char);
     free (collection.latin_to_subset_glyph_index);
 
     return collection.status;
@@ -1191,7 +1204,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
 
 	if (utf16_len == 1) {
 	    int ch = _cairo_unicode_to_winansi (utf16[0]);
-	    if (ch > 0)
+	    if (ch > 0 && _cairo_winansi_to_glyphname (ch))
 		strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf));
 	    else
 		snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]);
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 9346951..45e6e47 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -836,7 +836,7 @@ static const char *winansi_encoding[256] = {
 	NULL,		NULL,		NULL,		NULL,
 	/*  32 */
 	"space",	"exclam",	"quotedbl",	"numbersign",
-	"dollar",	"percent",	"ampersand",	"quoteright",
+	"dollar",	"percent",	"ampersand",	"quotesingle",
 	"parenleft",	"parenright",	"asterisk",	"plus",
 	"comma",	"hyphen",	"period",	"slash",
 	/*  48 */
@@ -855,7 +855,7 @@ static const char *winansi_encoding[256] = {
 	"X",		"Y",		"Z",		"bracketleft",
 	"backslash",	"bracketright",	"asciicircum",	"underscore",
 	/*  96 */
-	"quoteleft",	"a",		"b",		"c",
+	"grave",	"a",		"b",		"c",
 	"d",		"e",		"f",		"g",
 	"h",		"i",		"j",		"k",
 	"l",		"m",		"n",		"o",
@@ -868,17 +868,18 @@ static const char *winansi_encoding[256] = {
 	"Euro",		NULL,		"quotesinglbase","florin",
 	"quotedblbase", "ellipsis",	"dagger",	"daggerdbl",
 	"circumflex",	"perthousand",	"Scaron",	"guilsinglleft",
-	"OE",		"bullet",	"Zcaron",	NULL,
+	"OE",		NULL,		"Zcaron",	NULL,
 	/* 144 */
 	NULL,		"quoteleft",	"quoteright",	"quotedblleft",
 	"quotedblright","bullet",	"endash",	"emdash",
 	"tilde",	"trademark",	"scaron",	"guilsinglright",
-	"oe",		"bullet",	"zcaron",	"Ydieresis",
+	"oe",		NULL,		"zcaron",	"Ydieresis",
 	/* 160 */
-	"space",	"exclamdown",	"cent",		"sterling",
+	NULL,		"exclamdown",	"cent",		"sterling",
 	"currency",	"yen",		"brokenbar",	"section",
 	"dieresis",	"copyright",	"ordfeminine",	"guillemotleft",
-	"logicalnot",	"hyphen",	"registered",	"macron",
+	/* 173 is also "hyphen" but we leave this NULL to avoid duplicate names */
+	"logicalnot",	NULL,		"registered",	"macron",
 	/* 176 */
 	"degree",	"plusminus",	"twosuperior",	"threesuperior",
 	"acute",	"mu",		"paragraph",	"periodcentered",
diff --git a/src/cairoint.h b/src/cairoint.h
index d0ae66a..73386d1 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -433,9 +433,11 @@ typedef struct _cairo_scaled_font_subset {
      * Value of glyphs array is scaled_font_glyph_index.
      */
     unsigned long *glyphs;
+
     unsigned long *to_unicode;
     char          **utf8;
     char          **glyph_names;
+    int           *to_latin_char;
     unsigned long *latin_to_subset_glyph_index;
     unsigned int num_glyphs;
     cairo_bool_t is_composite;


More information about the cairo-commit mailing list