[cairo-commit] 7 commits - src/cairo-cff-subset.c src/cairoint.h
src/cairo-output-stream.c 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-svg-surface.c src/cairo-truetype-subset.c
src/cairo-type1-fallback.c src/cairo-type1-subset.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Fri Apr 20 08:28:40 PDT 2007
src/cairo-cff-subset.c | 1075 ++++++++++++++++++++++----------
src/cairo-output-stream.c | 27
src/cairo-pdf-surface.c | 312 +++++----
src/cairo-ps-surface.c | 13
src/cairo-scaled-font-subsets-private.h | 138 +++-
src/cairo-scaled-font-subsets.c | 188 +++--
src/cairo-svg-surface.c | 2
src/cairo-truetype-subset.c | 21
src/cairo-type1-fallback.c | 215 ++++--
src/cairo-type1-subset.c | 30
src/cairoint.h | 1
11 files changed, 1424 insertions(+), 598 deletions(-)
New commits:
diff-tree fc455c53ecb0aa496915b1eae68dc0275af78e09 (from 9d8eb42c013d197b3365af88e372d1c2c1617173)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sat Apr 21 00:26:25 2007 +0930
Ensure _cairo_scaled_font_subsets_map_glyph() returns correct values
The CID font subsetting exposed a bug where the subset_glyph->is_scaled
return argument of _cairo_scaled_font_subsets_map_glyph() is sometimes
not assigned a value.
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index b0521e3..fa5a8b4 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -265,11 +265,9 @@ _cairo_sub_font_pluck (void *entry, void
}
static cairo_status_t
-_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
- unsigned long scaled_font_glyph_index,
- unsigned int *subset_id,
- unsigned int *subset_glyph_index,
- double *x_advance)
+_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
+ unsigned long scaled_font_glyph_index,
+ cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -277,9 +275,12 @@ _cairo_sub_font_lookup_glyph (cairo_sub_
if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
(cairo_hash_entry_t **) &sub_font_glyph))
{
- *subset_id = sub_font_glyph->subset_id;
- *subset_glyph_index = sub_font_glyph->subset_glyph_index;
- *x_advance = sub_font_glyph->x_advance;
+ subset_glyph->font_id = sub_font->font_id;
+ subset_glyph->subset_id = sub_font_glyph->subset_id;
+ subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+ subset_glyph->is_scaled = sub_font->is_scaled;
+ subset_glyph->is_composite = sub_font->is_composite;
+ subset_glyph->x_advance = sub_font_glyph->x_advance;
return CAIRO_STATUS_SUCCESS;
}
@@ -290,9 +291,7 @@ _cairo_sub_font_lookup_glyph (cairo_sub_
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
- unsigned int *subset_id,
- unsigned int *subset_glyph_index,
- double *x_advance)
+ cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
@@ -343,9 +342,12 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
return status;
}
- *subset_id = sub_font_glyph->subset_id;
- *subset_glyph_index = sub_font_glyph->subset_glyph_index;
- *x_advance = sub_font_glyph->x_advance;
+ subset_glyph->font_id = sub_font->font_id;
+ subset_glyph->subset_id = sub_font_glyph->subset_id;
+ subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
+ subset_glyph->is_scaled = sub_font->is_scaled;
+ subset_glyph->is_composite = sub_font->is_composite;
+ subset_glyph->x_advance = sub_font_glyph->x_advance;
return CAIRO_STATUS_SUCCESS;
}
@@ -485,15 +487,9 @@ _cairo_scaled_font_subsets_map_glyph (ca
{
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
- &subset_glyph->subset_id,
- &subset_glyph->subset_glyph_index,
- &subset_glyph->x_advance);
- if (status == CAIRO_STATUS_SUCCESS) {
- subset_glyph->font_id = sub_font->font_id;
- subset_glyph->is_scaled = FALSE;
- subset_glyph->is_composite = sub_font->is_composite;
+ subset_glyph);
+ if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
- }
}
}
@@ -505,15 +501,9 @@ _cairo_scaled_font_subsets_map_glyph (ca
{
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
- &subset_glyph->subset_id,
- &subset_glyph->subset_glyph_index,
- &subset_glyph->x_advance);
- if (status == CAIRO_STATUS_SUCCESS) {
- subset_glyph->font_id = sub_font->font_id;
- subset_glyph->is_scaled = TRUE;
- subset_glyph->is_composite = sub_font->is_composite;
+ subset_glyph);
+ if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
- }
}
/* Glyph not found. Determine whether the glyph is outline or
@@ -598,13 +588,10 @@ _cairo_scaled_font_subsets_map_glyph (ca
return status;
}
}
- subset_glyph->font_id = sub_font->font_id;
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
- &subset_glyph->subset_id,
- &subset_glyph->subset_glyph_index,
- &subset_glyph->x_advance);
+ subset_glyph);
}
static cairo_status_t
diff-tree 9d8eb42c013d197b3365af88e372d1c2c1617173 (from 56ad56263b86a9678387fe8dd994e77c183c6328)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:45:12 2007 +0930
Exclude Type1 fonts from CID subsets
Make cairo-scaled-font-subsets.c limit Type1 font subsets to
256 glyphs. This allows Type1 subsetting to be enabled again
with type1-fallback as the fallback option for Type1 fonts.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index b2128d0..f4e6f90 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2493,31 +2493,29 @@ _cairo_pdf_surface_emit_unscaled_font_su
cairo_pdf_surface_t *surface = closure;
cairo_status_t status;
- status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return;
-
+ if (font_subset->is_composite) {
+ status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
+
+ status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
+
+ status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
+ } else {
#if CAIRO_HAS_FT_FONT
-#if 0
- status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return;
-#endif
+ status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
#endif
- status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return;
-
- status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return;
-
-#if 0
- status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return;
-#endif
+ status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
+ }
}
static void
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 03076c8..e4e320c 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -97,7 +97,7 @@ _cairo_scaled_font_subsets_create_simple
*
* Glyphs with an outline path available will be mapped to one font
* subset for each font face. Each unscaled subset has a maximum of
- * 65536 glyphs.
+ * 65536 glyphs except for Type1 fonts which have a maximum of 256 glyphs.
*
* Glyphs from bitmap fonts will mapped to separate font subsets for
* each cairo_scaled_font_t object. Each unscaled subset has a maximum
@@ -425,6 +425,15 @@ cairo_private void
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
/**
+ * _cairo_type1_scaled_font_is_type1:
+ * @scaled_font: a #cairo_scaled_font_t
+ *
+ * Return TRUE if @scaled_font is a Type 1 font, otherwise return FALSE.
+ **/
+cairo_private cairo_bool_t
+_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
+
+/**
* _cairo_type1_fallback_init_binary:
* @type1_subset: a #cairo_type1_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 47260c8..b0521e3 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -67,6 +67,7 @@ typedef struct _cairo_sub_font {
cairo_hash_entry_t base;
cairo_bool_t is_scaled;
+ cairo_bool_t is_composite;
cairo_scaled_font_subsets_t *parent;
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
@@ -207,7 +208,8 @@ _cairo_sub_font_create (cairo_scaled_fon
cairo_scaled_font_t *scaled_font,
unsigned int font_id,
int max_glyphs_per_subset,
- cairo_bool_t is_scaled)
+ cairo_bool_t is_scaled,
+ cairo_bool_t is_composite)
{
cairo_sub_font_t *sub_font;
@@ -216,6 +218,7 @@ _cairo_sub_font_create (cairo_scaled_fon
return NULL;
sub_font->is_scaled = is_scaled;
+ sub_font->is_composite = is_composite;
_cairo_sub_font_init_key (sub_font, scaled_font);
sub_font->parent = parent;
@@ -376,6 +379,7 @@ _cairo_sub_font_collect (void *entry, vo
assert (collection->num_glyphs == collection->max_glyph + 1);
subset.scaled_font = sub_font->scaled_font;
+ subset.is_composite = sub_font->is_composite;
subset.font_id = sub_font->font_id;
subset.subset_id = i;
subset.glyphs = collection->glyphs;
@@ -470,6 +474,7 @@ _cairo_scaled_font_subsets_map_glyph (ca
cairo_scaled_font_t *unscaled_font;
cairo_status_t status;
int max_glyphs;
+ cairo_bool_t type1_font;
/* Lookup glyph in unscaled subsets */
if (subsets->type != CAIRO_SUBSETS_SCALED) {
@@ -486,6 +491,7 @@ _cairo_scaled_font_subsets_map_glyph (ca
if (status == CAIRO_STATUS_SUCCESS) {
subset_glyph->font_id = sub_font->font_id;
subset_glyph->is_scaled = FALSE;
+ subset_glyph->is_composite = sub_font->is_composite;
return CAIRO_STATUS_SUCCESS;
}
}
@@ -505,6 +511,7 @@ _cairo_scaled_font_subsets_map_glyph (ca
if (status == CAIRO_STATUS_SUCCESS) {
subset_glyph->font_id = sub_font->font_id;
subset_glyph->is_scaled = TRUE;
+ subset_glyph->is_composite = sub_font->is_composite;
return CAIRO_STATUS_SUCCESS;
}
}
@@ -535,16 +542,25 @@ _cairo_scaled_font_subsets_map_glyph (ca
&identity,
&font_options);
- if (subsets->type == CAIRO_SUBSETS_COMPOSITE)
+ subset_glyph->is_scaled = FALSE;
+ type1_font = FALSE;
+#if CAIRO_HAS_FT_FONT
+ type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
+#endif
+ if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
- else
+ subset_glyph->is_composite = TRUE;
+ } else {
max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
+ subset_glyph->is_composite = FALSE;
+ }
sub_font = _cairo_sub_font_create (subsets,
unscaled_font,
subsets->num_sub_fonts++,
max_glyphs,
- FALSE);
+ subset_glyph->is_scaled,
+ subset_glyph->is_composite);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -553,11 +569,6 @@ _cairo_scaled_font_subsets_map_glyph (ca
if (status)
return status;
}
- subset_glyph->is_scaled = FALSE;
- if (subsets->type == CAIRO_SUBSETS_COMPOSITE)
- subset_glyph->is_composite = TRUE;
- else
- subset_glyph->is_composite = FALSE;
} else {
/* No path available. Add to scaled subset. */
key.is_scaled = TRUE;
@@ -565,6 +576,8 @@ _cairo_scaled_font_subsets_map_glyph (ca
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
+ subset_glyph->is_scaled = TRUE;
+ subset_glyph->is_composite = FALSE;
if (subsets->type == CAIRO_SUBSETS_SCALED)
max_glyphs = INT_MAX;
else
@@ -574,7 +587,8 @@ _cairo_scaled_font_subsets_map_glyph (ca
cairo_scaled_font_reference (scaled_font),
subsets->num_sub_fonts++,
max_glyphs,
- TRUE);
+ subset_glyph->is_scaled,
+ subset_glyph->is_composite);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -583,8 +597,6 @@ _cairo_scaled_font_subsets_map_glyph (ca
if (status)
return status;
}
- subset_glyph->is_scaled = TRUE;
- subset_glyph->is_composite = FALSE;
}
subset_glyph->font_id = sub_font->font_id;
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 40c212e..2b07dfe 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1192,3 +1192,30 @@ _cairo_type1_subset_fini (cairo_type1_su
free (subset->widths);
free (subset->data);
}
+
+cairo_bool_t
+_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
+{
+ cairo_ft_unscaled_font_t *unscaled;
+ FT_Face face;
+ PS_FontInfoRec font_info;
+ cairo_bool_t is_type1 = FALSE;
+
+ unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
+ face = _cairo_ft_unscaled_font_lock_face (unscaled);
+ if (!face)
+ return FALSE;
+
+ if (FT_Get_PS_Font_Info(face, &font_info) == 0)
+ is_type1 = TRUE;
+
+ /* OpenType/CFF fonts also have a PS_FontInfoRec */
+#if HAVE_FT_LOAD_SFNT_TABLE
+ if (FT_IS_SFNT (face))
+ is_type1 = FALSE;
+#endif
+
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+ return is_type1;
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 76397e2..549cc51 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -640,6 +640,7 @@ typedef struct _cairo_scaled_font_subset
unsigned long *glyphs;
unsigned long *to_unicode;
unsigned int num_glyphs;
+ cairo_bool_t is_composite;
} cairo_scaled_font_subset_t;
struct _cairo_scaled_font_backend {
diff-tree 56ad56263b86a9678387fe8dd994e77c183c6328 (from ca3662d6fc630e5390b3a8f8dbaa1d65aebc3fe8)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:44:04 2007 +0930
Enable embedding of CID fonts in PDF
Update cairo-pdf-surface.c to embed CFF and TrueType fonts
as CID fonts. Update the ToUnicode CMap to handle CID fonts.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 7a164e0..b2128d0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -277,7 +277,7 @@ _cairo_pdf_surface_create_for_stream_int
_cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->alphas, sizeof (double));
- surface->font_subsets = _cairo_scaled_font_subsets_create_simple();
+ surface->font_subsets = _cairo_scaled_font_subsets_create_composite ();
if (! surface->font_subsets) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
free (surface);
@@ -1681,11 +1681,12 @@ _cairo_pdf_surface_write_pages (cairo_pd
static cairo_pdf_resource_t
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
- cairo_scaled_font_subset_t *font_subset)
+ cairo_scaled_font_subset_t *font_subset,
+ cairo_bool_t is_composite)
{
const cairo_scaled_font_backend_t *backend;
cairo_pdf_resource_t stream;
- unsigned int i;
+ unsigned int i, num_bfchar;
cairo_status_t status;
if (font_subset->to_unicode == NULL) {
@@ -1708,50 +1709,54 @@ _cairo_pdf_surface_emit_to_unicode_strea
"12 dict begin\r\n"
"begincmap\r\n"
"/CIDSystemInfo\r\n"
- "<< /Registry (Cairo)\r\n"
- " /Ordering (ToUnicode-%d-%d)\r\n"
+ "<< /Registry (Adobe)\r\n"
+ " /Ordering (UCS)\r\n"
" /Supplement 0\r\n"
">> def\r\n"
- "/CMapName /Cairo-ToUnicode-%d-%d def\r\n"
+ "/CMapName /Adobe-Identity-UCS def\r\n"
"/CMapType 2 def\r\n"
- "1 begincodespacerange\r\n"
- "<00> <ff>\r\n"
- "endcodespacerange\r\n",
- font_subset->font_id,
- font_subset->subset_id,
- font_subset->font_id,
- font_subset->subset_id);
+ "1 begincodespacerange\r\n");
+
+ if (is_composite) {
+ _cairo_output_stream_printf (surface->output,
+ "<0000> <ffff>\r\n");
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "<00> <ff>\r\n");
+ }
+
+ _cairo_output_stream_printf (surface->output,
+ "endcodespacerange\r\n");
+ num_bfchar = font_subset->num_glyphs - 1;
/* The CMap specification has a limit of 100 characters per beginbfchar operator */
_cairo_output_stream_printf (surface->output,
"%d beginbfchar\r\n",
- font_subset->num_glyphs > 100 ? 100 : font_subset->num_glyphs);
- for (i = 0; i < font_subset->num_glyphs; i++) {
+ num_bfchar > 100 ? 100 : num_bfchar);
+ for (i = 0; i < num_bfchar; i++) {
if (i != 0 && i % 100 == 0) {
_cairo_output_stream_printf (surface->output,
"endbfchar\r\n"
"%d beginbfchar\r\n",
- font_subset->num_glyphs - i > 100 ? 100 : font_subset->num_glyphs - i);
+ num_bfchar - i > 100 ? 100 : num_bfchar - i);
+ }
+ if (is_composite) {
+ _cairo_output_stream_printf (surface->output,
+ "<%04x> <%04x>\r\n",
+ i + 1, font_subset->to_unicode[i + 1]);
+ } else {
+ _cairo_output_stream_printf (surface->output,
+ "<%02x> <%04x>\r\n",
+ i + 1, font_subset->to_unicode[i + 1]);
}
- _cairo_output_stream_printf (surface->output,
- "<%02x> <%04x>\r\n",
- i, font_subset->to_unicode[i]);
}
_cairo_output_stream_printf (surface->output,
"endbfchar\r\n");
- if (font_subset->num_glyphs < 256) {
- _cairo_output_stream_printf (surface->output,
- "1 beginnotdefrange\r\n"
- "<%02x> <ff> 0\r\n"
- "endnotdefrange\r\n",
- font_subset->num_glyphs);
- }
-
_cairo_output_stream_printf (surface->output,
- "endcmap\r\n"
- "CMapName currentdict /CMap defineresource pop\r\n"
- "end\r\n"
+ "endcmap\r\n"
+ "CMapName currentdict /CMap defineresource pop\r\n"
+ "end\r\n"
"end\r\n");
status = _cairo_pdf_surface_close_stream (surface);
@@ -1762,36 +1767,28 @@ _cairo_pdf_surface_emit_to_unicode_strea
}
static cairo_status_t
-_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
- cairo_scaled_font_subset_t *font_subset)
+_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
+ cairo_scaled_font_subset_t *font_subset,
+ cairo_cff_subset_t *subset)
{
- cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
- cairo_status_t status;
+ cairo_pdf_resource_t stream, descriptor, cidfont_dict;
+ cairo_pdf_resource_t subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
- cairo_cff_subset_t subset;
unsigned long compressed_length;
char *compressed;
unsigned int i;
- char name[64];
-
- snprintf (name, sizeof name, "CairoFont-%d-%d",
- font_subset->font_id, font_subset->subset_id);
- status = _cairo_cff_subset_init (&subset, name, font_subset);
- if (status)
- return status;
+ cairo_status_t status;
- compressed = compress_dup (subset.data, subset.data_length, &compressed_length);
- if (compressed == NULL) {
- _cairo_cff_subset_fini (&subset);
+ compressed = compress_dup (subset->data, subset->data_length, &compressed_length);
+ if (compressed == NULL)
return CAIRO_STATUS_NO_MEMORY;
- }
stream = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Filter /FlateDecode\r\n"
" /Length %lu\r\n"
- " /Subtype /Type1C\r\n"
+ " /Subtype /CIDFontType0C\r\n"
">>\r\n"
"stream\r\n",
stream.id,
@@ -1803,7 +1800,7 @@ _cairo_pdf_surface_emit_cff_font_subset
"endobj\r\n");
free (compressed);
- to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset);
+ to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset, TRUE);
descriptor = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
@@ -1822,41 +1819,57 @@ _cairo_pdf_surface_emit_cff_font_subset
">>\r\n"
"endobj\r\n",
descriptor.id,
- subset.base_font,
- subset.x_min,
- subset.y_min,
- subset.x_max,
- subset.y_max,
- subset.ascent,
- subset.descent,
+ subset->base_font,
+ subset->x_min,
+ subset->y_min,
+ subset->x_max,
+ subset->y_max,
+ subset->ascent,
+ subset->descent,
stream.id);
- subset_resource = _cairo_pdf_surface_new_object (surface);
+ cidfont_dict = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Type /Font\r\n"
- " /Subtype /Type1\r\n"
- " /BaseFont /%s\r\n"
- " /FirstChar 0\r\n"
- " /LastChar %d\r\n"
- " /FontDescriptor %d 0 R\r\n"
- " /Widths [",
- subset_resource.id,
- subset.base_font,
- font_subset->num_glyphs - 1,
- descriptor.id);
+ "%d 0 obj\r\n"
+ "<< /Type /Font\r\n"
+ " /Subtype /CIDFontType0\r\n"
+ " /BaseFont /%s\r\n"
+ " /CIDSystemInfo\r\n"
+ " << /Registry (Adobe)\r\n"
+ " /Ordering (Identity)\r\n"
+ " /Supplement 0\r\n"
+ " >>\r\n"
+ " /FontDescriptor %d 0 R\r\n"
+ " /W [0 [",
+ cidfont_dict.id,
+ subset->base_font,
+ descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %d",
- subset.widths[i]);
+ subset->widths[i]);
_cairo_output_stream_printf (surface->output,
- " ]\r\n");
+ " ]]\r\n"
+ ">>\r\n"
+ "endobj\r\n");
+
+ subset_resource = _cairo_pdf_surface_new_object (surface);
+ _cairo_output_stream_printf (surface->output,
+ "%d 0 obj\r\n"
+ "<< /Type /Font\r\n"
+ " /Subtype /Type0\r\n"
+ " /BaseFont /%s\r\n"
+ " /Encoding /Identity-H\r\n"
+ " /DescendantFonts [ %d 0 R]\r\n",
+ subset_resource.id,
+ subset->base_font,
+ cidfont_dict.id);
if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
- " /ToUnicode %d 0 R\r\n",
+ " /ToUnicode %d 0 R\r\n",
to_unicode_stream.id);
_cairo_output_stream_printf (surface->output,
@@ -1868,12 +1881,52 @@ _cairo_pdf_surface_emit_cff_font_subset
font.subset_resource = subset_resource;
status = _cairo_array_append (&surface->fonts, &font);
+ return status;
+}
+
+static cairo_status_t
+_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ cairo_status_t status;
+ cairo_cff_subset_t subset;
+ char name[64];
+
+ snprintf (name, sizeof name, "CairoFont-%d-%d",
+ font_subset->font_id, font_subset->subset_id);
+ status = _cairo_cff_subset_init (&subset, name, font_subset);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
+
_cairo_cff_subset_fini (&subset);
return status;
}
static cairo_status_t
+_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ cairo_status_t status;
+ cairo_cff_subset_t subset;
+ char name[64];
+
+ snprintf (name, sizeof name, "CairoFont-%d-%d",
+ font_subset->font_id, font_subset->subset_id);
+ status = _cairo_cff_fallback_init (&subset, name, font_subset);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_surface_emit_cff_font (surface, font_subset, &subset);
+
+ _cairo_cff_fallback_fini (&subset);
+
+ return status;
+}
+
+static cairo_status_t
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_type1_subset_t *subset)
@@ -1912,7 +1965,7 @@ _cairo_pdf_surface_emit_type1_font (cair
"endobj\r\n");
free (compressed);
- to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset);
+ to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset, FALSE);
descriptor = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
@@ -2026,7 +2079,8 @@ static cairo_status_t
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_pdf_resource_t stream, descriptor, encoding, subset_resource, to_unicode_stream;
+ cairo_pdf_resource_t stream, descriptor, cidfont_dict;
+ cairo_pdf_resource_t subset_resource, to_unicode_stream;
cairo_status_t status;
cairo_pdf_font_t font;
cairo_truetype_subset_t subset;
@@ -2063,7 +2117,7 @@ _cairo_pdf_surface_emit_truetype_font_su
"endobj\r\n");
free (compressed);
- to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset);
+ to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset, TRUE);
descriptor = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
@@ -2092,18 +2146,30 @@ _cairo_pdf_surface_emit_truetype_font_su
(long)(subset.y_max*PDF_UNITS_PER_EM),
stream.id);
- encoding = _cairo_pdf_surface_new_object (surface);
+ cidfont_dict = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
- "%d 0 obj\r\n"
- "<< /Type /Encoding\r\n"
- " /Differences [0 ",
- encoding.id);
+ "%d 0 obj\r\n"
+ "<< /Type /Font\r\n"
+ " /Subtype /CIDFontType2\r\n"
+ " /BaseFont /%s\r\n"
+ " /CIDSystemInfo\r\n"
+ " << /Registry (Adobe)\r\n"
+ " /Ordering (Identity)\r\n"
+ " /Supplement 0\r\n"
+ " >>\r\n"
+ " /FontDescriptor %d 0 R\r\n"
+ " /W [0 [",
+ cidfont_dict.id,
+ subset.base_font,
+ descriptor.id);
for (i = 0; i < font_subset->num_glyphs; i++)
- _cairo_output_stream_printf (surface->output, "/g%d ", i);
+ _cairo_output_stream_printf (surface->output,
+ " %ld",
+ (long)(subset.widths[i]*PDF_UNITS_PER_EM));
_cairo_output_stream_printf (surface->output,
- " ]\r\n"
+ " ]]\r\n"
">>\r\n"
"endobj\r\n");
@@ -2111,30 +2177,17 @@ _cairo_pdf_surface_emit_truetype_font_su
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /Font\r\n"
- " /Subtype /TrueType\r\n"
+ " /Subtype /Type0\r\n"
" /BaseFont /%s\r\n"
- " /FirstChar 0\r\n"
- " /LastChar %d\r\n"
- " /FontDescriptor %d 0 R\r\n"
- " /Encoding %d 0 R\r\n"
- " /Widths [",
+ " /Encoding /Identity-H\r\n"
+ " /DescendantFonts [ %d 0 R]\r\n",
subset_resource.id,
subset.base_font,
- font_subset->num_glyphs - 1,
- descriptor.id,
- encoding.id);
-
- 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,
- " ]\r\n");
+ cidfont_dict.id);
if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
- " /ToUnicode %d 0 R\r\n",
+ " /ToUnicode %d 0 R\r\n",
to_unicode_stream.id);
_cairo_output_stream_printf (surface->output,
@@ -2380,7 +2433,7 @@ _cairo_pdf_surface_emit_type3_font_subse
free (glyphs);
- to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset);
+ to_unicode_stream = _cairo_pdf_surface_emit_to_unicode_stream (surface, font_subset, FALSE);
subset_resource = _cairo_pdf_surface_new_object (surface);
matrix = font_subset->scaled_font->scale;
@@ -2440,25 +2493,31 @@ _cairo_pdf_surface_emit_unscaled_font_su
cairo_pdf_surface_t *surface = closure;
cairo_status_t status;
-#if 0
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
-#endif
#if CAIRO_HAS_FT_FONT
+#if 0
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
#endif
+#endif
status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
+ status = _cairo_pdf_surface_emit_cff_fallback_font (surface, font_subset);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return;
+
+#if 0
status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
+#endif
}
static void
@@ -2922,7 +2981,7 @@ _cairo_pdf_surface_show_glyphs (void *
cairo_status_t status;
double Tlm_x = 0, Tlm_y = 0;
double Tm_x = 0, y;
- int i;
+ int i, hex_width;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -2950,6 +3009,11 @@ _cairo_pdf_surface_show_glyphs (void *
if (status)
return status;
+ if (subset_glyph.is_composite)
+ hex_width = 4;
+ else
+ hex_width = 2;
+
if (subset_glyph.is_scaled == FALSE) {
y = 0.0;
cairo_matrix_transform_distance (&scaled_font->scale,
@@ -2999,7 +3063,8 @@ _cairo_pdf_surface_show_glyphs (void *
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (surface->output,
- "[<%02x",
+ "[<%0*x",
+ hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = TRUE;
@@ -3013,7 +3078,8 @@ _cairo_pdf_surface_show_glyphs (void *
Tm_x += delta;
}
_cairo_output_stream_printf (surface->output,
- "%02x",
+ "%0*x",
+ hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
@@ -3030,7 +3096,8 @@ _cairo_pdf_surface_show_glyphs (void *
Tm_x += delta;
}
_cairo_output_stream_printf (surface->output,
- "%02x>] TJ\r\n",
+ "%0*x>] TJ\r\n",
+ hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
in_TJ = FALSE;
@@ -3045,14 +3112,16 @@ _cairo_pdf_surface_show_glyphs (void *
Tm_x = Tlm_x;
}
_cairo_output_stream_printf (surface->output,
- "<%02x> Tj ",
+ "<%0*x> Tj ",
+ hex_width,
subset_glyph.subset_glyph_index);
Tm_x += subset_glyph.x_advance;
}
}
} else {
_cairo_output_stream_printf (surface->output,
- "<%02x> Tj\r\n",
+ "<%0*x> Tj\r\n",
+ hex_width,
subset_glyph.subset_glyph_index);
}
}
diff-tree ca3662d6fc630e5390b3a8f8dbaa1d65aebc3fe8 (from 0c2a653033e0b631a1cb6591263cbd6125ccc00c)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:43:37 2007 +0930
Make cairo-output-stream.c accept variable width printf fields
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index 4401c5b..b9f0d38 100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -281,7 +281,8 @@ _cairo_output_stream_vprintf (cairo_outp
int single_fmt_length;
char *p;
const char *f, *start;
- int length_modifier;
+ int length_modifier, width;
+ cairo_bool_t var_width;
if (stream->status)
return;
@@ -305,6 +306,12 @@ _cairo_output_stream_vprintf (cairo_outp
if (*f == '0')
f++;
+ var_width = FALSE;
+ if (*f == '*') {
+ var_width = TRUE;
+ f++;
+ }
+
while (isdigit (*f))
f++;
@@ -341,15 +348,27 @@ _cairo_output_stream_vprintf (cairo_outp
case 'o':
case 'x':
case 'X':
- snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
+ if (var_width) {
+ width = va_arg (ap, int);
+ snprintf (buffer, sizeof buffer,
+ single_fmt, width, va_arg (ap, int));
+ } else {
+ snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
+ }
break;
case 'd' | LENGTH_MODIFIER_LONG:
case 'u' | LENGTH_MODIFIER_LONG:
case 'o' | LENGTH_MODIFIER_LONG:
case 'x' | LENGTH_MODIFIER_LONG:
case 'X' | LENGTH_MODIFIER_LONG:
- snprintf (buffer, sizeof buffer,
- single_fmt, va_arg (ap, long int));
+ if (var_width) {
+ width = va_arg (ap, int);
+ snprintf (buffer, sizeof buffer,
+ single_fmt, width, va_arg (ap, long int));
+ } else {
+ snprintf (buffer, sizeof buffer,
+ single_fmt, va_arg (ap, long int));
+ }
break;
case 's':
snprintf (buffer, sizeof buffer,
diff-tree 0c2a653033e0b631a1cb6591263cbd6125ccc00c (from c68a2389f51880b0fa9df6750abdd840258666fc)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:30:55 2007 +0930
Add CFF CID Fallback
Switching to CID font embedding requires a fallback font for
the case where CFF CID or TrueType CID subsetting fails.
The new function _cairo_type2_charstrings_init() added to
cairo-type1-fallback.c creates Type2 charstrings from glyph
paths. _cairo_cff_fallback_init() in cairo-cff-subset.c
wraps these charstrings in a CFF CID font.
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index e4c8cfc..a448e37 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -1915,3 +1915,215 @@ _cairo_cff_subset_fini (cairo_cff_subset
free (subset->widths);
free (subset->data);
}
+
+static cairo_int_status_t
+_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
+ cairo_cff_font_t **font_return,
+ const char *subset_name)
+{
+ cairo_status_t status;
+ cairo_cff_font_t *font;
+
+ font = malloc (sizeof (cairo_cff_font_t));
+ if (font == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->backend = NULL;
+ font->scaled_font_subset = scaled_font_subset;
+
+ _cairo_array_init (&font->output, sizeof (char));
+ status = _cairo_array_grow_by (&font->output, 4096);
+ if (status)
+ goto fail1;
+
+ font->subset_font_name = strdup (subset_name);
+ if (font->subset_font_name == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail2;
+ }
+
+ font->font_name = strdup (subset_name);
+ if (font->subset_font_name == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail3;
+ }
+
+ font->x_min = 0;
+ font->y_min = 0;
+ font->x_max = 0;
+ font->y_max = 0;
+ font->ascent = 0;
+ font->descent = 0;
+
+ font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
+ if (font->widths == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail4;
+ }
+
+ font->data_length = 0;
+ font->data = NULL;
+ font->data_end = 0;
+
+ cff_dict_init (&font->top_dict);
+ cff_dict_init (&font->private_dict);
+ cff_index_init (&font->strings_index);
+ cff_index_init (&font->charstrings_index);
+ cff_index_init (&font->global_sub_index);
+ cff_index_init (&font->local_sub_index);
+ cff_index_init (&font->charstrings_subset_index);
+ cff_index_init (&font->strings_subset_index);
+ font->fdselect = NULL;
+ font->fd_dict = NULL;
+ font->fd_private_dict = NULL;
+ font->fd_local_sub_index = NULL;
+ font->fdselect_subset = NULL;
+ font->fd_subset_map = NULL;
+ font->private_dict_offset = NULL;
+
+ *font_return = font;
+
+ return CAIRO_STATUS_SUCCESS;
+
+fail4:
+ free (font->font_name);
+fail3:
+ free (font->subset_font_name);
+fail2:
+ _cairo_array_fini (&font->output);
+fail1:
+ free (font);
+ return status;
+}
+
+static cairo_int_status_t
+cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
+ cairo_type2_charstrings_t *type2_subset,
+ const char **data,
+ unsigned long *length)
+{
+ cairo_int_status_t status;
+ cff_header_t header;
+ cairo_array_t *charstring;
+ unsigned char buf[40];
+ unsigned char *end_buf;
+ unsigned int i;
+
+ /* Create header */
+ header.major = 1;
+ header.minor = 0;
+ header.header_size = 4;
+ header.offset_size = 4;
+ font->header = &header;
+
+ /* Create Top Dict */
+ font->is_cid = FALSE;
+ 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);
+ end_buf = encode_integer (end_buf, type2_subset->y_max);
+ cff_dict_set_operands (font->top_dict, FONTBBOX_OP, buf, end_buf - buf);
+ end_buf = encode_integer_max (buf, 0);
+ cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
+ cairo_cff_font_set_ros_strings (font);
+
+ /* Create CID FD dictionary */
+ cairo_cff_font_create_cid_fontdict (font);
+
+ /* Create charstrings */
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ charstring = _cairo_array_index(&type2_subset->charstrings, i);
+
+ status = cff_index_append (&font->charstrings_subset_index,
+ _cairo_array_index (charstring, 0),
+ _cairo_array_num_elements (charstring));
+
+ if (status)
+ return status;
+ }
+
+ status = cairo_cff_font_write_subset (font);
+ if (status)
+ return status;
+
+ *data = _cairo_array_index (&font->output, 0);
+ *length = _cairo_array_num_elements (&font->output);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
+ const char *subset_name,
+ cairo_scaled_font_subset_t *font_subset)
+{
+ cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
+ cairo_status_t status;
+ const char *data = NULL; /* squelch bogus compiler warning */
+ unsigned long length = 0; /* squelch bogus compiler warning */
+ unsigned int i;
+ cairo_type2_charstrings_t type2_subset;
+
+ status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
+ if (status)
+ return status;
+
+ status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
+ if (status)
+ goto fail1;
+
+ status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
+ if (status)
+ goto fail1;
+
+ cff_subset->base_font = strdup (font->font_name);
+ if (cff_subset->base_font == NULL)
+ goto fail1;
+
+ cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+ if (cff_subset->widths == NULL)
+ goto fail2;
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
+ cff_subset->widths[i] = type2_subset.widths[i];
+
+ cff_subset->x_min = type2_subset.x_min;
+ cff_subset->y_min = type2_subset.y_min;
+ cff_subset->x_max = type2_subset.x_max;
+ cff_subset->y_max = type2_subset.y_max;
+ cff_subset->ascent = type2_subset.y_max;
+ cff_subset->descent = type2_subset.y_min;
+
+ _cairo_type2_charstrings_fini (&type2_subset);
+
+ cff_subset->data = malloc (length);
+ if (cff_subset->data == NULL)
+ goto fail3;
+
+ memcpy (cff_subset->data, data, length);
+ cff_subset->data_length = length;
+ cff_subset->data_length = length;
+
+ cairo_cff_font_destroy (font);
+
+ return CAIRO_STATUS_SUCCESS;
+
+ fail3:
+ free (cff_subset->widths);
+ fail2:
+ free (cff_subset->base_font);
+ fail1:
+ cairo_cff_font_destroy (font);
+
+ return status;
+}
+
+void
+_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
+{
+ free (subset->base_font);
+ free (subset->widths);
+ free (subset->data);
+}
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 4c8221e..03076c8 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -305,6 +305,37 @@ _cairo_cff_subset_init (cairo_cff_subset
cairo_private void
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
+/**
+ * _cairo_cff_fallback_init:
+ * @cff_subset: a #cairo_cff_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate a cff
+ * file corresponding to @font_subset and initialize @cff_subset
+ * with information about the subset and the cff data.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
+ * cff file, or an non-zero value indicating an error. Possible
+ * errors include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
+ const char *name,
+ cairo_scaled_font_subset_t *font_subset);
+
+/**
+ * _cairo_cff_fallback_fini:
+ * @cff_subset: a #cairo_cff_subset_t
+ *
+ * Free all resources associated with @cff_subset. After this
+ * call, @cff_subset should not be used again without a
+ * subsequent call to _cairo_cff_subset_init() again first.
+ **/
+cairo_private void
+_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
+
typedef struct _cairo_truetype_subset {
char *base_font;
double *widths;
@@ -446,6 +477,43 @@ _cairo_type1_fallback_init_hex (cairo_ty
cairo_private void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
+typedef struct _cairo_type2_charstrings {
+ int *widths;
+ long x_min, y_min, x_max, y_max;
+ long ascent, descent;
+ cairo_array_t charstrings;
+} cairo_type2_charstrings_t;
+
+/**
+ * _cairo_type2_charstrings_init:
+ * @type2_subset: a #cairo_type2_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate type2
+ * charstrings to @font_subset and initialize @type2_subset
+ * with information about the subset.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
+ * charstrings, or an non-zero value indicating an error. Possible errors
+ * include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_type2_charstrings_init (cairo_type2_charstrings_t *charstrings,
+ cairo_scaled_font_subset_t *font_subset);
+
+/**
+ * _cairo_type2_charstrings_fini:
+ * @subset: a #cairo_type2_charstrings_t
+ *
+ * Free all resources associated with @type2_charstring. After this call,
+ * @type2_charstring should not be used again without a subsequent call to
+ * _cairo_type2_charstring_init() again first.
+ **/
+cairo_private void
+_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
+
/**
* _cairo_truetype_create_glyph_to_unicode_map:
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index dcf55f4..3a0bd12 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -39,6 +39,11 @@
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
+typedef enum {
+ CAIRO_CHARSTRING_TYPE1,
+ CAIRO_CHARSTRING_TYPE2,
+} cairo_charstring_type_t;
+
typedef struct _cairo_type1_font {
int *widths;
@@ -90,7 +95,7 @@ cairo_type1_font_create (cairo_scaled_fo
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
- cairo_matrix_init_scale (&font_matrix, 1000, 1000);
+ cairo_matrix_init_scale (&font_matrix, 1000, -1000);
cairo_matrix_init_identity (&ctm);
_cairo_font_options_init_default (&font_options);
@@ -156,7 +161,9 @@ charstring_encode_command (cairo_array_t
* bytes that will be used is 5.
*/
static void
-charstring_encode_integer (cairo_array_t *data, int i)
+charstring_encode_integer (cairo_array_t *data,
+ int i,
+ cairo_charstring_type_t type)
{
cairo_status_t status;
int orig_size;
@@ -174,11 +181,19 @@ charstring_encode_integer (cairo_array_t
*p++ = (i >> 8)+ 251;
*p++ = i & 0xff;
} else {
- *p++ = 0xff;
- *p++ = i >> 24;
- *p++ = (i >> 16) & 0xff;
- *p++ = (i >> 8) & 0xff;
- *p++ = i & 0xff;
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ *p++ = 0xff;
+ *p++ = i >> 24;
+ *p++ = (i >> 16) & 0xff;
+ *p++ = (i >> 8) & 0xff;
+ *p++ = i & 0xff;
+ } else {
+ *p++ = 0xff;
+ *p++ = (i >> 8) & 0xff;
+ *p++ = i & 0xff;
+ *p++ = 0;
+ *p++ = 0;
+ }
}
/* Ensure the array doesn't grow, which allows this function to
@@ -193,6 +208,7 @@ charstring_encode_integer (cairo_array_t
typedef struct _ps_path_info {
cairo_array_t *data;
int current_x, current_y;
+ cairo_charstring_type_t type;
} t1_path_info_t;
static cairo_status_t
@@ -209,8 +225,8 @@ _charstring_move_to (void *clos
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
- charstring_encode_integer (path_info->data, dx);
- charstring_encode_integer (path_info->data, dy);
+ charstring_encode_integer (path_info->data, dx, path_info->type);
+ charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@@ -233,8 +249,8 @@ _charstring_line_to (void *clos
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
- charstring_encode_integer (path_info->data, dx);
- charstring_encode_integer (path_info->data, dy);
+ charstring_encode_integer (path_info->data, dx, path_info->type);
+ charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@@ -263,12 +279,12 @@ _charstring_curve_to (void *closure,
dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
- charstring_encode_integer (path_info->data, dx1);
- charstring_encode_integer (path_info->data, dy1);
- charstring_encode_integer (path_info->data, dx2);
- charstring_encode_integer (path_info->data, dy2);
- charstring_encode_integer (path_info->data, dx3);
- charstring_encode_integer (path_info->data, dy3);
+ charstring_encode_integer (path_info->data, dx1, path_info->type);
+ charstring_encode_integer (path_info->data, dy1, path_info->type);
+ charstring_encode_integer (path_info->data, dx2, path_info->type);
+ charstring_encode_integer (path_info->data, dy2, path_info->type);
+ charstring_encode_integer (path_info->data, dx3, path_info->type);
+ charstring_encode_integer (path_info->data, dy3, path_info->type);
path_info->current_x += dx1 + dx2 + dx3;
path_info->current_y += dy1 + dy2 + dy3;
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
@@ -282,6 +298,9 @@ _charstring_close_path (void *closure)
cairo_status_t status;
t1_path_info_t *path_info = (t1_path_info_t *) closure;
+ if (path_info->type == CAIRO_CHARSTRING_TYPE2)
+ return CAIRO_STATUS_SUCCESS;
+
status = _cairo_array_grow_by (path_info->data, 2);
if (status)
return status;
@@ -309,7 +328,7 @@ charstring_encrypt (cairo_array_t *data)
}
static cairo_int_status_t
-create_notdef_charstring (cairo_array_t *data)
+create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
{
cairo_status_t status;
@@ -320,13 +339,15 @@ create_notdef_charstring (cairo_array_t
if (status)
return status;
- charstring_encode_integer (data, 0);
- charstring_encode_integer (data, 0);
-
- /* The width and height is arbitrary. */
- charstring_encode_integer (data, 500);
- charstring_encode_integer (data, 500);
- charstring_encode_command (data, CHARSTRING_sbw);
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ charstring_encode_integer (data, 0, type);
+ charstring_encode_integer (data, 0, type);
+
+ /* The width and height is arbitrary. */
+ charstring_encode_integer (data, 500, type);
+ charstring_encode_integer (data, 500, type);
+ charstring_encode_command (data, CHARSTRING_sbw);
+ }
charstring_encode_command (data, CHARSTRING_endchar);
@@ -334,10 +355,11 @@ create_notdef_charstring (cairo_array_t
}
static cairo_int_status_t
-cairo_type1_font_create_charstring (cairo_type1_font_t *font,
- int subset_index,
- int glyph_index,
- cairo_array_t *data)
+cairo_type1_font_create_charstring (cairo_type1_font_t *font,
+ int subset_index,
+ int glyph_index,
+ cairo_charstring_type_t type,
+ cairo_array_t *data)
{
cairo_int_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
@@ -369,21 +391,29 @@ cairo_type1_font_create_charstring (cair
if (metrics->y_bearing + metrics->height > font->y_max)
font->y_max = metrics->y_bearing + metrics->height;
}
- font->widths[subset_index] = metrics->width;
+ font->widths[subset_index] = metrics->x_advance;
status = _cairo_array_grow_by (data, 30);
if (status)
return status;
- charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.width);
- charstring_encode_integer (data, (int) scaled_glyph->metrics.height);
- charstring_encode_command (data, CHARSTRING_sbw);
+ if (type == CAIRO_CHARSTRING_TYPE1) {
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.height, type);
+ charstring_encode_command (data, CHARSTRING_sbw);
+
+ path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
+ path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
+ } else {
+ charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
+ path_info.current_x = 0;
+ path_info.current_y = 0;
+ }
path_info.data = data;
- path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
- path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
+ path_info.type = type;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
@@ -429,6 +459,7 @@ cairo_type1_font_write_charstrings (cair
goto fail;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
+ CAIRO_CHARSTRING_TYPE1,
&data);
if (status)
goto fail;
@@ -448,7 +479,7 @@ cairo_type1_font_write_charstrings (cair
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
- status = create_notdef_charstring (&data);
+ status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
if (status)
goto fail;
charstring_encrypt (&data);
@@ -464,35 +495,22 @@ fail:
return status;
}
-static cairo_status_t
+static void
cairo_type1_font_write_header (cairo_type1_font_t *font,
const char *name)
{
- cairo_matrix_t matrix;
- cairo_status_t status;
unsigned int i;
const char spaces[50] = " ";
- matrix = font->type1_scaled_font->scale;
- matrix.xy = -matrix.xy;
- matrix.yy = -matrix.yy;
- status = cairo_matrix_invert (&matrix);
- if (status)
- return status;
-
_cairo_output_stream_printf (font->output,
"%%!FontType1-1.1 %s 1.0\n"
"11 dict begin\n"
"/FontName /%s def\n"
"/PaintType 0 def\n"
"/FontType 1 def\n"
- "/FontMatrix [%f %f %f %f 0 0] readonly def\n",
- name,
+ "/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
name,
- matrix.xx,
- matrix.yx,
- matrix.xy,
- matrix.yy);
+ name);
/* We don't know the bbox values until after the charstrings have
* been generated. Reserve some space and fill in the bbox
@@ -515,8 +533,6 @@ cairo_type1_font_write_header (cairo_typ
"readonly def\n"
"currentdict end\n"
"currentfile eexec\n");
-
- return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@@ -640,10 +656,7 @@ cairo_type1_font_write (cairo_type1_font
{
cairo_int_status_t status;
- status = cairo_type1_font_write_header (font, name);
- if (status)
- return status;
-
+ cairo_type1_font_write_header (font, name);
font->header_size = _cairo_output_stream_get_position (font->output);
status = cairo_type1_font_write_private_dict (font, name);
@@ -798,3 +811,83 @@ _cairo_type1_fallback_fini (cairo_type1_
free (subset->widths);
free (subset->data);
}
+
+cairo_status_t
+_cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
+ cairo_scaled_font_subset_t *scaled_font_subset)
+{
+ cairo_type1_font_t *font;
+ cairo_status_t status;
+ unsigned int i;
+ cairo_array_t charstring;
+
+ status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
+ if (status)
+ return status;
+
+ _cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
+
+ type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
+ if (type2_subset->widths == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail1;
+ }
+
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ _cairo_array_init (&charstring, sizeof (unsigned char));
+ status = _cairo_array_grow_by (&charstring, 32);
+ if (status)
+ goto fail2;
+
+ if (i == 0) {
+ status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
+ } else {
+ status = cairo_type1_font_create_charstring (font, i,
+ font->scaled_font_subset->glyphs[i],
+ CAIRO_CHARSTRING_TYPE2,
+ &charstring);
+ }
+ if (status)
+ goto fail2;
+
+ status = _cairo_array_append (&type2_subset->charstrings, &charstring);
+ if (status)
+ goto fail2;
+ }
+
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
+ type2_subset->widths[i] = font->widths[i];
+
+ type2_subset->x_min = (int) font->x_min;
+ type2_subset->y_min = (int) font->y_min;
+ type2_subset->x_max = (int) font->x_max;
+ type2_subset->y_max = (int) font->y_max;
+ type2_subset->ascent = (int) font->y_max;
+ type2_subset->descent = (int) font->y_min;
+
+ cairo_type1_font_destroy (font);
+ return CAIRO_STATUS_SUCCESS;
+
+fail2:
+ _cairo_array_fini (&charstring);
+ _cairo_type2_charstrings_fini (type2_subset);
+fail1:
+ cairo_type1_font_destroy (font);
+ return status;
+}
+
+void
+_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
+{
+ unsigned int i, num_charstrings;
+ cairo_array_t *charstring;
+
+ num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
+ for (i = 0; i < num_charstrings; i++) {
+ charstring = _cairo_array_index (&type2_subset->charstrings, i);
+ _cairo_array_fini (charstring);
+ }
+ _cairo_array_fini (&type2_subset->charstrings);
+
+ free (type2_subset->widths);
+}
diff-tree c68a2389f51880b0fa9df6750abdd840258666fc (from 073fce5a85ab90b1bc6915e41d6a420a47e540e6)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:30:05 2007 +0930
Make CFF Subsetting create CID subsets
OpenType/CFF fonts come in two types: CID and non CID.
CFF CID font subsetting was previously disabled in cairo
due 1) to the need to embed CFF CID fonts in PDF as a CID fonts
and 2) there is no easy way to convert CFF CID to CFF non CID.
With the switch to CID fonts cairo-cff-subset.c has been
updated to subset CID fonts and to covert non CID fonts to
CID. A further advantage of converting non CID CFF fonts
to CID is the reduction in size due to not embedding the
name of each glyph in the font subset.
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index b0158fe..e4c8cfc 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -37,15 +37,20 @@
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-truetype-subset-private.h"
+#include <string.h>
/* CFF Dict Operators. If the high byte is 0 the command is encoded
* with a single byte. */
#define BASEFONTNAME_OP 0x0c16
+#define CIDCOUNT_OP 0x0c22
#define CHARSET_OP 0x000f
#define CHARSTRINGS_OP 0x0011
#define COPYRIGHT_OP 0x0c00
#define ENCODING_OP 0x0010
#define FAMILYNAME_OP 0x0003
+#define FDARRAY_OP 0x0c24
+#define FDSELECT_OP 0x0c25
+#define FONTBBOX_OP 0x0005
#define FONTNAME_OP 0x0c26
#define FULLNAME_OP 0x0002
#define LOCAL_SUB_OP 0x0013
@@ -80,13 +85,6 @@ typedef struct _cff_dict_operator {
int operand_offset;
} cff_dict_operator_t;
-typedef struct _cff_charset {
- cairo_bool_t is_builtin;
- const uint16_t *sids;
- const unsigned char *data;
- int length;
-} cff_charset_t;
-
typedef struct _cairo_cff_font {
cairo_scaled_font_subset_t *scaled_font_subset;
@@ -106,14 +104,23 @@ typedef struct _cairo_cff_font {
cairo_array_t global_sub_index;
cairo_array_t local_sub_index;
int num_glyphs;
- cff_charset_t charset;
- int charset_offset;
+ cairo_bool_t is_cid;
+
+ /* CID Font Data */
+ int *fdselect;
+ unsigned int num_fontdicts;
+ cairo_hash_table_t **fd_dict;
+ cairo_hash_table_t **fd_private_dict;
+ cairo_array_t *fd_local_sub_index;
/* Subsetted Font Data */
char *subset_font_name;
cairo_array_t charstrings_subset_index;
cairo_array_t strings_subset_index;
- cairo_array_t charset_subset;
+ int *fdselect_subset;
+ unsigned int num_subset_fontdicts;
+ int *fd_subset_map;
+ int *private_dict_offset;
cairo_array_t output;
/* Subset Metrics */
@@ -345,7 +352,6 @@ cff_index_write (cairo_array_t *index, c
status = _cairo_array_append_multiple (output, buf, offset_size);
if (status)
return status;
-
}
for (i = 0; i < num_elem; i++) {
@@ -372,7 +378,9 @@ cff_index_append (cairo_array_t *index,
}
static cairo_status_t
-cff_index_append_copy (cairo_array_t *index, unsigned char *object , int length)
+cff_index_append_copy (cairo_array_t *index,
+ const unsigned char *object,
+ unsigned int length)
{
cff_index_element_t element;
@@ -486,6 +494,21 @@ fail:
return status;
}
+static void
+cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
+{
+ cff_dict_operator_t key, *op;
+
+ _cairo_dict_init_key (&key, operator);
+ if (_cairo_hash_table_lookup (dict, &key.base,
+ (cairo_hash_entry_t **) &op))
+ {
+ free (op->operand);
+ _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
+ free (op);
+ }
+}
+
static unsigned char *
cff_dict_get_operands (cairo_hash_table_t *dict,
unsigned short operator,
@@ -561,19 +584,12 @@ typedef struct _dict_write_info {
} dict_write_info_t;
static void
-_cairo_dict_collect (void *entry, void *closure)
+cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
{
- dict_write_info_t *write_info = closure;
- cff_dict_operator_t *op = entry;
unsigned char data;
- if (write_info->status)
- return;
-
op->operand_offset = _cairo_array_num_elements (write_info->output);
- write_info->status = _cairo_array_append_multiple (write_info->output,
- op->operand,
- op->operand_length);
+ write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
if (write_info->status)
return;
@@ -587,13 +603,36 @@ _cairo_dict_collect (void *entry, void *
write_info->status = _cairo_array_append (write_info->output, &data);
}
+static void
+_cairo_dict_collect (void *entry, void *closure)
+{
+ dict_write_info_t *write_info = closure;
+ cff_dict_operator_t *op = entry;
+
+ if (write_info->status)
+ return;
+
+ /* The ROS operator is handled separately in cff_dict_write() */
+ if (op->operator != ROS_OP)
+ cairo_dict_write_operator (op, write_info);
+}
+
static cairo_status_t
cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
{
dict_write_info_t write_info;
+ cff_dict_operator_t key, *op;
write_info.output = output;
write_info.status = CAIRO_STATUS_SUCCESS;
+
+ /* The CFF specification requires that the Top Dict of CID fonts
+ * begin with the ROS operator. */
+ _cairo_dict_init_key (&key, ROS_OP);
+ if (_cairo_hash_table_lookup (dict, &key.base,
+ (cairo_hash_entry_t **) &op))
+ cairo_dict_write_operator (op, &write_info);
+
_cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
return write_info.status;
@@ -644,6 +683,8 @@ cairo_cff_font_read_name (cairo_cff_font
static cairo_int_status_t
cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
+ cairo_hash_table_t *private_dict,
+ cairo_array_t *local_sub_index,
unsigned char *ptr,
int size)
{
@@ -654,22 +695,141 @@ cairo_cff_font_read_private_dict (cairo_
unsigned char *operand;
unsigned char *p;
- cff_dict_read (font->private_dict, ptr, size);
- operand = cff_dict_get_operands (font->private_dict, LOCAL_SUB_OP, &i);
+ cff_dict_read (private_dict, ptr, size);
+ operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
if (operand) {
decode_integer (operand, &offset);
p = ptr + offset;
- cff_index_read (&font->local_sub_index, &p, font->data_end);
+ cff_index_read (local_sub_index, &p, font->data_end);
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
- cff_dict_set_operands (font->private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
+ cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
+cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
+{
+ int type, num_ranges, first, last, fd, i, j;
+
+ font->fdselect = calloc (font->num_glyphs, sizeof (int));
+ if (font->fdselect == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ type = *p++;
+ if (type == 0)
+ {
+ for (i = 0; i < font->num_glyphs; i++)
+ font->fdselect[i] = *p++;
+ } else if (type == 3) {
+ num_ranges = be16_to_cpu( *((uint16_t *)p) );
+ p += 2;
+ for (i = 0; i < num_ranges; i++)
+ {
+ first = be16_to_cpu( *((uint16_t *)p) );
+ p += 2;
+ fd = *p++;
+ last = be16_to_cpu( *((uint16_t *)p) );
+ for (j = first; j < last; j++)
+ font->fdselect[j] = fd;
+ }
+ } else {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
+{
+ cairo_array_t index;
+ cff_index_element_t *element;
+ unsigned int i;
+ int size;
+ unsigned char *operand;
+ int offset;
+ cairo_int_status_t status;
+ unsigned char buf[100];
+ unsigned char *end_buf;
+
+ cff_index_init (&index);
+ status = cff_index_read (&index, &ptr, font->data_end);
+ if (status)
+ goto fail;
+
+ font->num_fontdicts = _cairo_array_num_elements (&index);
+
+ font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
+ if (font->fd_dict == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
+ if (font->fd_private_dict == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
+ if (font->fd_local_sub_index == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ for (i = 0; i < font->num_fontdicts; i++) {
+ cff_dict_init (&font->fd_dict[i]);
+ if (font->fd_dict[i] == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ element = _cairo_array_index (&index, i);
+ status = cff_dict_read (font->fd_dict[i], element->data, element->length);
+ if (status)
+ goto fail;
+
+ operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
+ if (operand == NULL) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto fail;
+ }
+ operand = decode_integer (operand, &size);
+ decode_integer (operand, &offset);
+ cff_dict_init (&font->fd_private_dict[i]);
+ if (font->fd_private_dict[i] == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto fail;
+ }
+ cff_index_init (&font->fd_local_sub_index[i]);
+ status = cairo_cff_font_read_private_dict (font,
+ font->fd_private_dict[i],
+ &font->fd_local_sub_index[i],
+ font->data + offset,
+ size);
+ if (status)
+ goto fail;
+ /* Set integer operand to max value to use max size encoding to reserve
+ * space for any value later */
+ end_buf = encode_integer_max (buf, 0);
+ end_buf = encode_integer_max (end_buf, 0);
+ status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
+ if (status)
+ goto fail;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+fail:
+ cff_index_fini (&index);
+
+ return status;
+}
+
+static cairo_int_status_t
cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
{
cairo_array_t index;
@@ -688,13 +848,14 @@ cairo_cff_font_read_top_dict (cairo_cff_
goto fail;
element = _cairo_array_index (&index, 0);
- cff_dict_read (font->top_dict, element->data, element->length);
-
- /* CID fonts are NYI */
- if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL) {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
+ status = cff_dict_read (font->top_dict, element->data, element->length);
+ if (status)
goto fail;
- }
+
+ if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
+ font->is_cid = TRUE;
+ else
+ font->is_cid = FALSE;
operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
decode_integer (operand, &offset);
@@ -704,27 +865,34 @@ cairo_cff_font_read_top_dict (cairo_cff_
goto fail;
font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
- operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
- operand = decode_integer (operand, &size);
- decode_integer (operand, &offset);
- cairo_cff_font_read_private_dict (font, font->data + offset, size);
+ if (font->is_cid) {
+ operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
+ decode_integer (operand, &offset);
+ cairo_cff_font_read_fdselect (font, font->data + offset);
- operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size);
- if (!operand)
- font->charset_offset = 0;
- else {
- decode_integer (operand, &offset);
- font->charset_offset = offset;
+ operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
+ decode_integer (operand, &offset);
+ cairo_cff_font_read_cid_fontdict (font, font->data + offset);
+ } else {
+ operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
+ operand = decode_integer (operand, &size);
+ decode_integer (operand, &offset);
+ cairo_cff_font_read_private_dict (font,
+ font->private_dict,
+ &font->local_sub_index,
+ font->data + offset,
+ size);
}
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, ENCODING_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
- /* 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);
+
+ cff_dict_remove (font->top_dict, ENCODING_OP);
+ cff_dict_remove (font->top_dict, PRIVATE_OP);
fail:
cff_index_fini (&index);
@@ -744,138 +912,6 @@ cairo_cff_font_read_global_subroutines (
return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
}
-static cairo_int_status_t
-cff_charset_read_data (cff_charset_t *charset, const unsigned char *data,
- const unsigned char *data_end, int num_glyphs)
-{
- const unsigned char *p = data;
-
- num_glyphs -= 1; /* do not count .notdef */
-
- if (p + 1 > data_end)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- switch (*p++) {
- case 0:
- if (p + num_glyphs*2 > data_end)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- charset->is_builtin = FALSE;
- charset->data = data;
- charset->length = num_glyphs * 2 + 1;
- break;
- case 1:
- while (num_glyphs > 0) {
- if (p + 3 > data_end)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- num_glyphs -= p[2] + 1;
- p += 3;
- }
- if (num_glyphs < 0)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- charset->is_builtin = FALSE;
- charset->data = data;
- charset->length = p - data;
- break;
- case 2:
- while (num_glyphs > 0) {
- if (p + 4 > data_end)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- num_glyphs -= be16_to_cpu(*(uint16_t *)(p + 2)) + 1;
- p += 4;
- }
- if (num_glyphs < 0)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- charset->is_builtin = FALSE;
- charset->data = data;
- charset->length = p - data;
- break;
- default:
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static const uint16_t ISOAdobe_charset[] = {
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
- 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
- 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
- 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
- 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
- 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
- 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
- 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
- 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
- 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
- 222, 223, 224, 225, 226, 227, 228,
-};
-
-static const uint16_t Expert_charset[] = {
- 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13,
- 14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247,
- 248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257,
- 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
- 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
- 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
- 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
- 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
- 311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163,
- 319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169,
- 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
- 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
- 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
- 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
- 371, 372, 373, 374, 375, 376, 377, 378,
-};
-
-static const uint16_t ExpertSubset_charset[] = {
- 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240,
- 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
- 251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
- 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
- 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321,
- 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
- 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
- 341, 342, 343, 344, 345, 346,
-};
-
-static cairo_int_status_t
-cairo_cff_font_read_charset (cairo_cff_font_t *font)
-{
- switch (font->charset_offset) {
- case 0:
- /* ISOAdobe charset */
- font->charset.is_builtin = TRUE;
- font->charset.sids = ISOAdobe_charset;
- font->charset.length = sizeof (ISOAdobe_charset);
- return CAIRO_STATUS_SUCCESS;
- case 1:
- /* Expert charset */
- font->charset.is_builtin = TRUE;
- font->charset.sids = Expert_charset;
- font->charset.length = sizeof (Expert_charset);
- return CAIRO_STATUS_SUCCESS;
- case 2:
- /* ExpertSubset charset */;
- font->charset.is_builtin = TRUE;
- font->charset.sids = ExpertSubset_charset;
- font->charset.length = sizeof (ExpertSubset_charset);
- return CAIRO_STATUS_SUCCESS;
- default:
- break;
- }
- return cff_charset_read_data (&font->charset, font->data + (unsigned)font->charset_offset,
- font->data_end, font->num_glyphs);
-}
-
typedef cairo_int_status_t
(*font_read_t) (cairo_cff_font_t *font);
@@ -885,8 +921,6 @@ static const font_read_t font_read_funcs
cairo_cff_font_read_top_dict,
cairo_cff_font_read_strings,
cairo_cff_font_read_global_subroutines,
- /* non-contiguous */
- cairo_cff_font_read_charset,
};
static cairo_int_status_t
@@ -904,6 +938,34 @@ cairo_cff_font_read_font (cairo_cff_font
return CAIRO_STATUS_SUCCESS;
}
+static void
+cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
+{
+ unsigned char buf[30];
+ unsigned char *p;
+ int sid1, sid2;
+ const char *registry = "Adobe";
+ const char *ordering = "Identity";
+
+ sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+ cff_index_append_copy (&font->strings_subset_index,
+ (unsigned char *)registry,
+ strlen(registry));
+
+ sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+ cff_index_append_copy (&font->strings_subset_index,
+ (unsigned char *)ordering,
+ strlen(ordering));
+
+ p = encode_integer (buf, sid1);
+ p = encode_integer (p, sid2);
+ p = encode_integer (p, 0);
+ cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
+
+ p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
+ cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
+}
+
static cairo_status_t
cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
cairo_hash_table_t *dict,
@@ -965,29 +1027,12 @@ cairo_cff_font_subset_dict_strings (cair
}
static cairo_status_t
-cairo_cff_font_subset_strings (cairo_cff_font_t *font)
-{
- cairo_status_t status;
-
- status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
- if (status)
- return status;
-
- status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
-
- return status;
-}
-
-static cairo_status_t
cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
{
cff_index_element_t *element;
unsigned int i;
cairo_status_t status;
- if (status)
- return status;
-
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
element = _cairo_array_index (&font->charstrings_index,
font->scaled_font_subset->glyphs[i]);
@@ -1001,78 +1046,105 @@ cairo_cff_font_subset_charstrings (cairo
return CAIRO_STATUS_SUCCESS;
}
-static uint16_t
-cff_sid_from_gid (const cff_charset_t *charset, int gid)
+static cairo_status_t
+cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
{
- const uint16_t *sids;
- const unsigned char *p;
- int prev_glyph;
-
- if (charset->is_builtin) {
- if (gid - 1 < charset->length / 2)
- return charset->sids[gid - 1];
- }
- else {
- /* no need to check sizes here, this was done during reading */
- switch (charset->data[0]) {
- case 0:
- sids = (const uint16_t *)(charset->data + 1);
- return be16_to_cpu(sids[gid - 1]);
- case 1:
- prev_glyph = 1;
- for (p = charset->data + 1; p < charset->data + charset->length; p += 3) {
- if (gid <= prev_glyph + p[2]) {
- uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
- return sid + gid - prev_glyph;
- }
- prev_glyph += p[2] + 1;
- }
- break;
- case 2:
- prev_glyph = 1;
- for (p = charset->data + 1; p < charset->data + charset->length; p += 4) {
- uint16_t nLeft = be16_to_cpu(*(const uint16_t *)(p + 2));
- if (gid <= prev_glyph + nLeft) {
- uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
- return sid + gid - prev_glyph;
- }
- prev_glyph += nLeft + 1;
- }
- break;
- default:
- break;
- }
+ unsigned int i;
+ int fd;
+ int *reverse_map;
+
+ font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
+ sizeof (int));
+ if (font->fdselect_subset == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
+ if (font->fd_subset_map == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
+ if (font->private_dict_offset == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ reverse_map = calloc (font->num_fontdicts, sizeof (int));
+ if (reverse_map == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ for (i = 0; i < font->num_fontdicts; i++)
+ reverse_map[i] = -1;
+
+ font->num_subset_fontdicts = 0;
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
+ if (reverse_map[fd] < 0) {
+ font->fd_subset_map[font->num_subset_fontdicts] = fd;
+ reverse_map[fd] = font->num_subset_fontdicts++;
+ }
+ font->fdselect_subset[i] = reverse_map[fd];
}
- return 0;
+
+ free (reverse_map);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
+{
+ unsigned char buf[100];
+ unsigned char *end_buf;
+
+ font->num_fontdicts = 1;
+ font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
+ if (font->fd_dict == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ cff_dict_init (&font->fd_dict[0]);
+
+ font->fd_subset_map = malloc (sizeof (int));
+ if (font->fd_subset_map == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->private_dict_offset = malloc (sizeof (int));
+ if (font->private_dict_offset == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ font->fd_subset_map[0] = 0;
+ font->num_subset_fontdicts = 1;
+
+ /* Set integer operand to max value to use max size encoding to reserve
+ * space for any value later */
+ end_buf = encode_integer_max (buf, 0);
+ end_buf = encode_integer_max (end_buf, 0);
+ cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-cairo_cff_font_subset_charset (cairo_cff_font_t *font)
+cairo_cff_font_subset_strings (cairo_cff_font_t *font)
{
+ cairo_status_t status;
unsigned int i;
- for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
- int gid = font->scaled_font_subset->glyphs[i];
- uint16_t original_sid = cff_sid_from_gid(&font->charset, gid);
- uint16_t new_sid;
- cff_index_element_t *element;
- cairo_status_t status;
-
- if (original_sid >= NUM_STD_STRINGS) {
- element = _cairo_array_index (&font->strings_index, original_sid - NUM_STD_STRINGS);
- new_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
- status = cff_index_append (&font->strings_subset_index, element->data, element->length);
- if (status)
- return status;
- }
- else
- new_sid = original_sid;
+ status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
+ if (status)
+ return status;
+ if (font->is_cid) {
+ for (i = 0; i < font->num_subset_fontdicts; i++) {
+ status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
+ if (status)
+ return status;
- status = _cairo_array_append(&font->charset_subset, &new_sid);
- if (status)
- return status;
+ status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
+ if (status)
+ return status;
+ }
+ } else {
+ status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
}
- return CAIRO_STATUS_SUCCESS;
+
+ return status;
}
static cairo_status_t
@@ -1080,17 +1152,20 @@ cairo_cff_font_subset_font (cairo_cff_fo
{
cairo_status_t status;
- /* TODO: subset subroutines */
+ cairo_cff_font_set_ros_strings (font);
- status = cairo_cff_font_subset_strings (font);
+ status = cairo_cff_font_subset_charstrings (font);
if (status)
return status;
- status = cairo_cff_font_subset_charstrings (font);
- if (status)
- return status;
+ if (font->is_cid)
+ cairo_cff_font_subset_fontdict (font);
+ else
+ cairo_cff_font_create_cid_fontdict (font);
- status = cairo_cff_font_subset_charset (font);
+ status = cairo_cff_font_subset_strings (font);
+ if (status)
+ return status;
return status;
}
@@ -1205,38 +1280,82 @@ cairo_cff_font_write_global_subrs (cairo
}
static cairo_status_t
-cairo_cff_font_write_encoding (cairo_cff_font_t *font)
+cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
{
- unsigned char buf[10];
+ unsigned char data;
+ unsigned int i;
+ cairo_int_status_t status;
+
+ cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
+
+ if (font->is_cid) {
+ data = 0;
+ status = _cairo_array_append (&font->output, &data);
+ if (status)
+ return status;
+
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ data = font->fdselect_subset[i];
+ status = _cairo_array_append (&font->output, &data);
+ if (status)
+ return status;
+ }
+ } else {
+ unsigned char byte;
+ uint16_t word;
+
+ status = _cairo_array_grow_by (&font->output, 9);
+ if (status)
+ return status;
- cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP);
- buf[0] = 1; /* Format 1 */
- buf[1] = 1; /* Number of ranges */
- buf[2] = 0; /* First code in range */
- /* Codes left in range excluding first */
- buf[3] = font->scaled_font_subset->num_glyphs - 1;
+ byte = 3;
+ status = _cairo_array_append (&font->output, &byte);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ word = cpu_to_be16 (1);
+ status = _cairo_array_append_multiple (&font->output, &word, 2);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ word = cpu_to_be16 (0);
+ status = _cairo_array_append_multiple (&font->output, &word, 2);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ byte = 0;
+ status = _cairo_array_append (&font->output, &byte);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
+ status = _cairo_array_append_multiple (&font->output, &word, 2);
+ assert (status == CAIRO_STATUS_SUCCESS);
+ }
- return _cairo_array_append_multiple (&font->output, buf, 4);
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_charset (cairo_cff_font_t *font)
{
- unsigned char format = 0;
- unsigned int i;
+ unsigned char byte;
+ uint16_t word;
cairo_status_t status;
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
- status = _cairo_array_append (&font->output, &format);
+ status = _cairo_array_grow_by (&font->output, 5);
if (status)
- return status;
+ return status;
+
+ byte = 2;
+ status = _cairo_array_append (&font->output, &byte);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ word = cpu_to_be16 (1);
+ status = _cairo_array_append_multiple (&font->output, &word, 2);
+ assert (status == CAIRO_STATUS_SUCCESS);
+
+ word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
+ status = _cairo_array_append_multiple (&font->output, &word, 2);
+ assert (status == CAIRO_STATUS_SUCCESS);
- for (i = 0; i < (unsigned)_cairo_array_num_elements(&font->charset_subset); i++) {
- uint16_t sid = cpu_to_be16(*(uint16_t *)_cairo_array_index(&font->charset_subset, i));
- status = _cairo_array_append_multiple (&font->output, &sid, sizeof(sid));
- if (status)
- return status;
- }
return CAIRO_STATUS_SUCCESS;
}
@@ -1249,9 +1368,48 @@ cairo_cff_font_write_charstrings (cairo_
}
static cairo_status_t
-cairo_cff_font_write_private_dict_and_local_sub (cairo_cff_font_t *font)
+cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
{
- int offset, private_dict_offset;
+ unsigned int i;
+ cairo_int_status_t status;
+ uint32_t *offset_array;
+ int offset_base;
+ uint16_t count;
+ uint8_t offset_size = 4;
+
+ cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
+ count = cpu_to_be16 (font->num_subset_fontdicts);
+ status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
+ if (status)
+ return status;
+ status = _cairo_array_append (&font->output, &offset_size);
+ if (status)
+ return status;
+ status = _cairo_array_allocate (&font->output,
+ (font->num_subset_fontdicts + 1)*offset_size,
+ (void **) &offset_array);
+ if (status)
+ return status;
+ offset_base = _cairo_array_num_elements (&font->output) - 1;
+ *offset_array++ = cpu_to_be32(1);
+ for (i = 0; i < font->num_subset_fontdicts; i++) {
+ status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
+ &font->output);
+ if (status)
+ return status;
+ *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+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 offset;
int size;
unsigned char buf[10];
unsigned char *buf_end;
@@ -1259,30 +1417,46 @@ cairo_cff_font_write_private_dict_and_lo
cairo_status_t status;
/* Write private dict and update offset and size in top dict */
- private_dict_offset = _cairo_array_num_elements (&font->output);
- status = cff_dict_write (font->private_dict, &font->output);
+ font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
+ status = cff_dict_write (private_dict, &font->output);
if (status)
return status;
- size = _cairo_array_num_elements (&font->output) - private_dict_offset;
+ size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
/* private entry has two operands - size and offset */
buf_end = encode_integer_max (buf, size);
- buf_end = encode_integer_max (buf_end, private_dict_offset);
- offset = cff_dict_get_location (font->top_dict, PRIVATE_OP, &size);
+ buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
+ offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
assert (offset > 0);
p = _cairo_array_index (&font->output, offset);
memcpy (p, buf, buf_end - buf);
- if (_cairo_array_num_elements (&font->local_sub_index) > 0) {
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+cairo_cff_font_write_local_sub (cairo_cff_font_t *font,
+ int dict_num,
+ cairo_hash_table_t *private_dict,
+ cairo_array_t *local_sub_index)
+{
+ int offset;
+ int size;
+ unsigned char buf[10];
+ unsigned char *buf_end;
+ unsigned char *p;
+ cairo_status_t status;
+
+ if (_cairo_array_num_elements (local_sub_index) > 0) {
/* Write local subroutines and update offset in private
* dict. Local subroutines offset is relative to start of
* private dict */
- offset = _cairo_array_num_elements (&font->output) - private_dict_offset;
+ offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
buf_end = encode_integer_max (buf, offset);
- offset = cff_dict_get_location (font->private_dict, LOCAL_SUB_OP, &size);
+ offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
assert (offset > 0);
p = _cairo_array_index (&font->output, offset);
memcpy (p, buf, buf_end - buf);
- status = cff_index_write (&font->local_sub_index, &font->output);
+ status = cff_index_write (local_sub_index, &font->output);
if (status)
return status;
}
@@ -1290,6 +1464,47 @@ cairo_cff_font_write_private_dict_and_lo
return CAIRO_STATUS_SUCCESS;
}
+
+static cairo_status_t
+cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
+{
+ unsigned int i;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+ if (font->is_cid) {
+ for (i = 0; i < font->num_subset_fontdicts; i++) {
+ status = cairo_cff_font_write_private_dict (
+ font,
+ i,
+ font->fd_dict[font->fd_subset_map[i]],
+ font->fd_private_dict[font->fd_subset_map[i]]);
+ if (status)
+ return status;
+ }
+
+ for (i = 0; i < font->num_subset_fontdicts; i++) {
+ status = cairo_cff_font_write_local_sub (
+ font,
+ i,
+ font->fd_private_dict[font->fd_subset_map[i]],
+ &font->fd_local_sub_index[font->fd_subset_map[i]]);
+ if (status)
+ return status;
+ }
+ } else {
+ status = cairo_cff_font_write_private_dict (font,
+ 0,
+ font->fd_dict[0],
+ font->private_dict);
+ status = cairo_cff_font_write_local_sub (font,
+ 0,
+ font->private_dict,
+ &font->local_sub_index);
+ }
+
+ return status;
+}
+
typedef cairo_status_t
(*font_write_t) (cairo_cff_font_t *font);
@@ -1299,10 +1514,11 @@ static const font_write_t font_write_fun
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_fdselect,
cairo_cff_font_write_charset,
cairo_cff_font_write_charstrings,
- cairo_cff_font_write_private_dict_and_local_sub,
+ cairo_cff_font_write_cid_fontdict,
+ cairo_cff_font_write_cid_private_dict_and_local_sub,
};
static cairo_status_t
@@ -1548,7 +1764,13 @@ _cairo_cff_font_create (cairo_scaled_fon
cff_index_init (&font->local_sub_index);
cff_index_init (&font->charstrings_subset_index);
cff_index_init (&font->strings_subset_index);
- _cairo_array_init (&font->charset_subset, sizeof(uint16_t));
+ font->fdselect = NULL;
+ font->fd_dict = NULL;
+ font->fd_private_dict = NULL;
+ font->fd_local_sub_index = NULL;
+ font->fdselect_subset = NULL;
+ font->fd_subset_map = NULL;
+ font->private_dict_offset = NULL;
free (name);
*font_return = font;
@@ -1575,6 +1797,8 @@ fail1:
static void
cairo_cff_font_destroy (cairo_cff_font_t *font)
{
+ unsigned int i;
+
free (font->widths);
free (font->font_name);
free (font->subset_font_name);
@@ -1587,7 +1811,43 @@ cairo_cff_font_destroy (cairo_cff_font_t
cff_index_fini (&font->local_sub_index);
cff_index_fini (&font->charstrings_subset_index);
cff_index_fini (&font->strings_subset_index);
- _cairo_array_fini (&font->charset_subset);
+
+ /* If we bailed out early as a result of an error some of the
+ * following cairo_cff_font_t members may still be NULL */
+ if (font->fd_dict) {
+ for (i = 0; i < font->num_fontdicts; i++) {
+ if (font->fd_dict[i])
+ cff_dict_fini (font->fd_dict[i]);
+ }
+ free (font->fd_dict);
+ }
+ if (font->fd_subset_map)
+ free (font->fd_subset_map);
+ if (font->private_dict_offset)
+ free (font->private_dict_offset);
+
+ if (font->is_cid) {
+ if (font->fdselect)
+ free (font->fdselect);
+ if (font->fdselect_subset)
+ free (font->fdselect_subset);
+ if (font->fd_private_dict) {
+ for (i = 0; i < font->num_fontdicts; i++) {
+ if (font->fd_private_dict[i])
+ cff_dict_fini (font->fd_private_dict[i]);
+ }
+ free (font->fd_private_dict);
+ }
+ if (font->fd_local_sub_index) {
+ for (i = 0; i < font->num_fontdicts; i++)
+ cff_index_fini (&font->fd_local_sub_index[i]);
+ free (font->fd_local_sub_index);
+ }
+ }
+
+ if (font->data)
+ free (font->data);
+
free (font);
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index d6c1f8f..7a164e0 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2440,9 +2440,11 @@ _cairo_pdf_surface_emit_unscaled_font_su
cairo_pdf_surface_t *surface = closure;
cairo_status_t status;
+#if 0
status = _cairo_pdf_surface_emit_cff_font_subset (surface, font_subset);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return;
+#endif
#if CAIRO_HAS_FT_FONT
status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
diff-tree 073fce5a85ab90b1bc6915e41d6a420a47e540e6 (from bf957ee0f29ff49970b4791718eccdb92f3d6886)
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Fri Apr 20 22:29:41 2007 +0930
Add support for creating CID/composite font subsets
cairo-scaled-font-subsets.c now provides three functions for creating subsets:
_cairo_scaled_font_subsets_create_scaled()
Create a subset for each scaled font with maximum size INT_MAX.
_cairo_scaled_font_subsets_create_simple()
Create subsets suitable for embedding as simple fonts in PS/PDF.
_cairo_scaled_font_subsets_create_composite()
Create subsets suitable for embedding as composite fonts in PS/PDF.
The _create_simple() and _create_composite() functions both merge
scaled fonts with the same face and an outline path available into
the same subset. _create_composite() has a maximum subset size of
65536 for outline fonts. Bitmap fonts have a separate subset for
each scale with a maximum subset size of 256.
The _create_simple() and _create_composite() functions both reserve
the first glyph in the subset for the .notdef glyph. CID fonts require
CID 0 to be .notdef.
Update Type1, TrueType and CFF subsetting to expect glyph 0 of each
subset to be the .notdef.
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index ab61ae2..b0158fe 100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -985,11 +985,6 @@ cairo_cff_font_subset_charstrings (cairo
unsigned int i;
cairo_status_t status;
- /* add .notdef */
- element = _cairo_array_index (&font->charstrings_index, 0);
- status = cff_index_append (&font->charstrings_subset_index,
- element->data,
- element->length);
if (status)
return status;
@@ -1056,7 +1051,7 @@ cairo_cff_font_subset_charset (cairo_cff
{
unsigned int i;
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
int gid = font->scaled_font_subset->glyphs[i];
uint16_t original_sid = cff_sid_from_gid(&font->charset, gid);
uint16_t new_sid;
@@ -1371,7 +1366,7 @@ cairo_cff_font_create_set_widths (cairo_
return status;
num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
glyph_index = font->scaled_font_subset->glyphs[i];
long_entry_size = 2 * sizeof (int16_t);
short_entry_size = sizeof (int16_t);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 2cfad5c..d6c1f8f 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -138,8 +138,6 @@ typedef struct _cairo_pdf_surface {
cairo_paginated_mode_t paginated_mode;
} cairo_pdf_surface_t;
-#define PDF_SURFACE_MAX_GLYPHS_PER_FONT 256
-
static cairo_pdf_resource_t
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface);
@@ -279,8 +277,7 @@ _cairo_pdf_surface_create_for_stream_int
_cairo_array_init (&surface->streams, sizeof (cairo_pdf_resource_t));
_cairo_array_init (&surface->alphas, sizeof (double));
- surface->font_subsets = _cairo_scaled_font_subsets_create (PDF_SURFACE_MAX_GLYPHS_PER_FONT,
- PDF_SURFACE_MAX_GLYPHS_PER_FONT);
+ surface->font_subsets = _cairo_scaled_font_subsets_create_simple();
if (! surface->font_subsets) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
free (surface);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index d725c53..520c404 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -84,8 +84,6 @@ typedef struct cairo_ps_surface {
} cairo_ps_surface_t;
-#define PS_SURFACE_MAX_GLYPHS_PER_FONT 256
-
/* A word wrap stream can be used as a filter to do word wrapping on
* top of an existing output stream. The word wrapping is quite
* simple, using isspace to determine characters that separate
@@ -486,18 +484,18 @@ _cairo_ps_surface_emit_truetype_font_sub
/* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
- for (i = 0; i < font_subset->num_glyphs; i++)
+ for (i = 1; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->final_stream,
"Encoding %d /g%d put\n", i, i);
_cairo_output_stream_printf (surface->final_stream,
"/CharStrings %d dict dup begin\n"
"/.notdef 0 def\n",
- font_subset->num_glyphs + 1);
+ font_subset->num_glyphs);
- for (i = 0; i < font_subset->num_glyphs; i++)
+ for (i = 1; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->final_stream,
- "/g%d %d def\n", i, i + 1);
+ "/g%d %d def\n", i, i);
_cairo_output_stream_printf (surface->final_stream,
"end readonly def\n");
@@ -814,8 +812,7 @@ _cairo_ps_surface_create_for_stream_inte
if (status)
goto CLEANUP_TMPFILE;
- surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
- PS_SURFACE_MAX_GLYPHS_PER_FONT);
+ surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
if (! surface->font_subsets)
goto CLEANUP_OUTPUT_STREAM;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index db655f7..4c8221e 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -46,20 +46,12 @@ typedef struct _cairo_scaled_font_subset
unsigned int subset_id;
unsigned int subset_glyph_index;
cairo_bool_t is_scaled;
+ cairo_bool_t is_composite;
double x_advance;
} cairo_scaled_font_subsets_glyph_t;
/**
- * _cairo_scaled_font_subsets_create:
- *
- * @max_glyphs_per_unscaled_subset: the maximum number of glyphs that
- * should appear in any unscaled subset. A value of 0 indicates that
- * no unscaled subset will be created. All glyphs will mapped to
- * scaled subsets.
- *
- * @max_glyphs_per_scaled_subset: the maximum number of glyphs that
- * should appear in any scaled subset. A value of 0 indicates that
- * no scaled subset will be created.
+ * _cairo_scaled_font_subsets_create_scaled:
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create subsets of any number of cairo_scaled_font_t
@@ -68,16 +60,57 @@ typedef struct _cairo_scaled_font_subset
* subsets with glyph indices packed into the range
* [0 .. max_glyphs_per_subset).
*
- * @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset
- * cannot both be 0.
+ * Return value: a pointer to the newly creates font subsets. The
+ * caller owns this object and should call
+ * _cairo_scaled_font_subsets_destroy() when done with it.
+ **/
+cairo_private cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_scaled (void);
+
+/**
+ * _cairo_scaled_font_subsets_create_simple:
+ *
+ * Create a new #cairo_scaled_font_subsets_t object which can be used
+ * to create font subsets suitable for embedding as Postscript or PDF
+ * simple fonts.
+ *
+ * Glyphs with an outline path available will be mapped to one font
+ * subset for each font face. Glyphs from bitmap fonts will mapped to
+ * separate font subsets for each cairo_scaled_font_t object.
+ *
+ * The maximum number of glyphs per subset is 256. Each subset
+ * reserves the first glyph for the .notdef glyph.
+ *
+ * Return value: a pointer to the newly creates font subsets. The
+ * caller owns this object and should call
+ * _cairo_scaled_font_subsets_destroy() when done with it.
+ **/
+cairo_private cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_simple (void);
+
+/**
+ * _cairo_scaled_font_subsets_create_composite:
+ *
+ * Create a new #cairo_scaled_font_subsets_t object which can be used
+ * to create font subsets suitable for embedding as Postscript or PDF
+ * composite fonts.
+ *
+ * Glyphs with an outline path available will be mapped to one font
+ * subset for each font face. Each unscaled subset has a maximum of
+ * 65536 glyphs.
+ *
+ * Glyphs from bitmap fonts will mapped to separate font subsets for
+ * each cairo_scaled_font_t object. Each unscaled subset has a maximum
+ * of 256 glyphs.
+ *
+ * Each subset reserves the first glyph for the .notdef glyph.
*
* Return value: a pointer to the newly creates font subsets. The
* caller owns this object and should call
* _cairo_scaled_font_subsets_destroy() when done with it.
**/
cairo_private cairo_scaled_font_subsets_t *
-_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset,
- int max_glyphs_scaled_per_subset);
+_cairo_scaled_font_subsets_create_composite (void);
/**
* _cairo_scaled_font_subsets_destroy:
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 974aebb..47260c8 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -42,12 +42,21 @@
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
+#define MAX_GLYPHS_PER_SIMPLE_FONT 256
+#define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
+
+typedef enum {
+ CAIRO_SUBSETS_SCALED,
+ CAIRO_SUBSETS_SIMPLE,
+ CAIRO_SUBSETS_COMPOSITE
+} cairo_subsets_type_t;
+
struct _cairo_scaled_font_subsets {
- int max_glyphs_per_unscaled_subset_limit;
+ cairo_subsets_type_t type;
+
int max_glyphs_per_unscaled_subset_used;
cairo_hash_table_t *unscaled_sub_fonts;
- int max_glyphs_per_scaled_subset_limit;
int max_glyphs_per_scaled_subset_used;
cairo_hash_table_t *scaled_sub_fonts;
@@ -223,6 +232,11 @@ _cairo_sub_font_create (cairo_scaled_fon
return NULL;
}
+ if (parent->type != CAIRO_SUBSETS_SCALED) {
+ /* Reserve first glyph in subset for the .notdef glyph */
+ sub_font->num_glyphs_in_current_subset++;
+ }
+
return sub_font;
}
@@ -289,6 +303,11 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
{
sub_font->current_subset++;
sub_font->num_glyphs_in_current_subset = 0;
+
+ if (sub_font->parent->type != CAIRO_SUBSETS_SCALED) {
+ /* Reserve first glyph in subset for the .notdef glyph */
+ sub_font->num_glyphs_in_current_subset++;
+ }
}
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
@@ -340,13 +359,20 @@ _cairo_sub_font_collect (void *entry, vo
for (i = 0; i <= sub_font->current_subset; i++) {
collection->subset_id = i;
- collection->num_glyphs = 0;
- collection->max_glyph = 0;
+ if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) {
+ collection->num_glyphs = 0;
+ collection->max_glyph = 0;
+ } else {
+ /* Assign .notdef glyph to the first glyph in the subset */
+ collection->glyphs[0] = 0;
+ collection->num_glyphs = 1;
+ collection->max_glyph = 0;
+ }
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
_cairo_sub_font_glyph_collect, collection);
- /* Ensure the resulting array has no uninitialized holes */
+ /* Ensure the resulting array has no uninitialized holes */
assert (collection->num_glyphs == collection->max_glyph + 1);
subset.scaled_font = sub_font->scaled_font;
@@ -371,9 +397,8 @@ _cairo_sub_font_collect (void *entry, vo
}
}
-cairo_scaled_font_subsets_t *
-_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
- int max_glyphs_per_scaled_subset)
+static cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
{
cairo_scaled_font_subsets_t *subsets;
@@ -381,12 +406,9 @@ _cairo_scaled_font_subsets_create (int m
if (subsets == NULL)
return NULL;
- subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
+ subsets->type = type;
subsets->max_glyphs_per_unscaled_subset_used = 0;
-
- subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset;
subsets->max_glyphs_per_scaled_subset_used = 0;
-
subsets->num_sub_fonts = 0;
subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
@@ -405,6 +427,24 @@ _cairo_scaled_font_subsets_create (int m
return subsets;
}
+cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_scaled (void)
+{
+ return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SCALED);
+}
+
+cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_simple (void)
+{
+ return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SIMPLE);
+}
+
+cairo_scaled_font_subsets_t *
+_cairo_scaled_font_subsets_create_composite (void)
+{
+ return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_COMPOSITE);
+}
+
void
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
{
@@ -429,9 +469,10 @@ _cairo_scaled_font_subsets_map_glyph (ca
cairo_font_options_t font_options;
cairo_scaled_font_t *unscaled_font;
cairo_status_t status;
+ int max_glyphs;
/* Lookup glyph in unscaled subsets */
- if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
+ if (subsets->type != CAIRO_SUBSETS_SCALED) {
key.is_scaled = FALSE;
_cairo_sub_font_init_key (&key, scaled_font);
if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
@@ -451,22 +492,20 @@ _cairo_scaled_font_subsets_map_glyph (ca
}
/* Lookup glyph in scaled subsets */
- if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
- key.is_scaled = TRUE;
- _cairo_sub_font_init_key (&key, scaled_font);
- if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
- (cairo_hash_entry_t **) &sub_font))
- {
- status = _cairo_sub_font_lookup_glyph (sub_font,
- scaled_font_glyph_index,
- &subset_glyph->subset_id,
- &subset_glyph->subset_glyph_index,
- &subset_glyph->x_advance);
- if (status == CAIRO_STATUS_SUCCESS) {
- subset_glyph->font_id = sub_font->font_id;
- subset_glyph->is_scaled = TRUE;
- return CAIRO_STATUS_SUCCESS;
- }
+ key.is_scaled = TRUE;
+ _cairo_sub_font_init_key (&key, scaled_font);
+ if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
+ (cairo_hash_entry_t **) &sub_font))
+ {
+ status = _cairo_sub_font_lookup_glyph (sub_font,
+ scaled_font_glyph_index,
+ &subset_glyph->subset_id,
+ &subset_glyph->subset_glyph_index,
+ &subset_glyph->x_advance);
+ if (status == CAIRO_STATUS_SUCCESS) {
+ subset_glyph->font_id = sub_font->font_id;
+ subset_glyph->is_scaled = TRUE;
+ return CAIRO_STATUS_SUCCESS;
}
}
@@ -476,7 +515,10 @@ _cairo_scaled_font_subsets_map_glyph (ca
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
- if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
+ if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
/* Path available. Add to unscaled subset. */
key.is_scaled = FALSE;
_cairo_sub_font_init_key (&key, scaled_font);
@@ -493,10 +535,15 @@ _cairo_scaled_font_subsets_map_glyph (ca
&identity,
&font_options);
+ if (subsets->type == CAIRO_SUBSETS_COMPOSITE)
+ max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
+ else
+ max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
+
sub_font = _cairo_sub_font_create (subsets,
unscaled_font,
subsets->num_sub_fonts++,
- subsets->max_glyphs_per_unscaled_subset_limit,
+ max_glyphs,
FALSE);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -507,17 +554,26 @@ _cairo_scaled_font_subsets_map_glyph (ca
return status;
}
subset_glyph->is_scaled = FALSE;
- } else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
+ if (subsets->type == CAIRO_SUBSETS_COMPOSITE)
+ subset_glyph->is_composite = TRUE;
+ else
+ subset_glyph->is_composite = FALSE;
+ } else {
/* No path available. Add to scaled subset. */
key.is_scaled = TRUE;
_cairo_sub_font_init_key (&key, scaled_font);
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
+ if (subsets->type == CAIRO_SUBSETS_SCALED)
+ max_glyphs = INT_MAX;
+ else
+ max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
+
sub_font = _cairo_sub_font_create (subsets,
cairo_scaled_font_reference (scaled_font),
subsets->num_sub_fonts++,
- subsets->max_glyphs_per_scaled_subset_limit,
+ max_glyphs,
TRUE);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -528,8 +584,7 @@ _cairo_scaled_font_subsets_map_glyph (ca
return status;
}
subset_glyph->is_scaled = TRUE;
- } else {
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ subset_glyph->is_composite = FALSE;
}
subset_glyph->font_id = sub_font->font_id;
@@ -583,7 +638,7 @@ _cairo_scaled_font_subsets_foreach_scale
}
cairo_private cairo_status_t
-_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
+_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure)
{
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 3fb6b79..a582de3 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2092,7 +2092,7 @@ _cairo_svg_document_create (cairo_output
}
/* The use of defs for font glyphs imposes no per-subset limit. */
- document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
+ document->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
if (document->font_subsets == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
free (document);
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index d791c63..91e618c 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -385,12 +385,12 @@ cairo_truetype_font_write_cmap_table (ca
cairo_truetype_font_write_be16 (font, 4); /* searchrange */
cairo_truetype_font_write_be16 (font, 1); /* entry selector */
cairo_truetype_font_write_be16 (font, 0); /* rangeshift */
- cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* end count[0] */
+ cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */
cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */
cairo_truetype_font_write_be16 (font, 0); /* reserved */
cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */
cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */
- cairo_truetype_font_write_be16 (font, 0x1001); /* delta[0] */
+ cairo_truetype_font_write_be16 (font, 0x1000); /* delta[0] */
cairo_truetype_font_write_be16 (font, 1); /* delta[1] */
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */
@@ -398,12 +398,12 @@ cairo_truetype_font_write_cmap_table (ca
/* Output a format 6 encoding table. */
cairo_truetype_font_write_be16 (font, 6);
- cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
+ cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs);
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be16 (font, 0); /* First character */
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
for (i = 0; i < font->base.num_glyphs; i++)
- cairo_truetype_font_write_be16 (font, i + 1);
+ cairo_truetype_font_write_be16 (font, i);
return font->status;
}
@@ -928,10 +928,6 @@ _cairo_truetype_subset_init (cairo_truet
if (status)
return status;
- /* Add the notdef glyph. This is required at glyph index 0
- * in the subsetted font. */
- cairo_truetype_font_use_glyph (font, 0);
-
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
parent_glyph = font->scaled_font_subset->glyphs[i];
cairo_truetype_font_use_glyph (font, parent_glyph);
@@ -946,16 +942,15 @@ _cairo_truetype_subset_init (cairo_truet
if (truetype_subset->base_font == NULL)
goto fail1;
- /* The widths array returned must contain only widths for
- * the glyphs in font_subset. The notdef glyph at index 0
- * and any subglyphs appended after font_subset->num_glyphs
- * are omitted. */
+ /* The widths array returned must contain only widths for the
+ * glyphs in font_subset. Any subglyphs appended after
+ * font_subset->num_glyphs are omitted. */
truetype_subset->widths = calloc (sizeof (double),
font->scaled_font_subset->num_glyphs);
if (truetype_subset->widths == NULL)
goto fail2;
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
- truetype_subset->widths[i] = (double)font->base.widths[i + 1]/font->base.units_per_em;
+ truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index a8f88df..dcf55f4 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -421,7 +421,7 @@ cairo_type1_font_write_charstrings (cair
"2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1);
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index e4f5015..40c212e 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1133,9 +1133,6 @@ _cairo_type1_subset_init (cairo_type1_su
cairo_type1_font_subset_use_glyph (font, parent_glyph);
}
- /* Pull in the .notdef glyph */
- cairo_type1_font_subset_use_glyph (font, 0);
-
status = cairo_type1_font_subset_generate (font, name);
if (status)
goto fail1;
More information about the cairo-commit
mailing list