[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, ¤t_ptr, data_end);
+ cff_index_fini (&index);
+
+ if (status)
+ goto fail1;
+
+ /* read top dict */
+ cff_index_init (&index);
+ status = cff_index_read (&index, ¤t_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