From 13a05830f5e524cd69b75796888c7a99ba9ce106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 16:42:44 -0400 Subject: [PATCH 1/9] Update pdf font emit code to try to emit a truetype subset before type3. --- src/cairo-pdf-surface.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index a37a5404e..8cde5e4d1 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1663,6 +1663,13 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) "endobj\r\n"); } +static cairo_status_t +_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + static void _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, cairo_scaled_font_t *scaled_font, @@ -1722,11 +1729,10 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, _cairo_surface_set_error (&surface->base, status); } -static void -_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) +static cairo_status_t +_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) { - cairo_pdf_surface_t *surface = closure; cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource; cairo_pdf_font_t font; int i; @@ -1734,7 +1740,7 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t)); if (glyphs == NULL) { _cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY); - return; + return CAIRO_STATUS_NO_MEMORY; } for (i = 0; i < font_subset->num_glyphs; i++) { @@ -1800,6 +1806,24 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, font.subset_id = font_subset->subset_id; font.subset_resource = subset_resource; _cairo_array_append (&surface->fonts, &font); + + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) +{ + cairo_pdf_surface_t *surface = closure; + cairo_status_t status; + + status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; + + status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; } static cairo_status_t From f4f11eba5b6daa6f82b967dcb21715b7f16d9719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 19:01:15 -0400 Subject: [PATCH 2/9] Output pdf dicts for truetype subset fonts. --- src/cairo-font-subset.c | 21 ++++++ src/cairo-pdf-surface.c | 97 ++++++++++++++++++++++++- src/cairo-scaled-font-subsets-private.h | 41 +++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-) diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c index c504f2e0a..5a1fcd170 100644 --- a/src/cairo-font-subset.c +++ b/src/cairo-font-subset.c @@ -35,6 +35,7 @@ #include "cairoint.h" #include "cairo-font-subset-private.h" +#include "cairo-scaled-font-subsets-private.h" /* XXX: Eventually, we need to handle other font backends */ #include "cairo-ft-private.h" @@ -755,3 +756,23 @@ static cairo_font_subset_backend_t cairo_pdf_ft_font_backend = { cairo_pdf_ft_font_generate, cairo_pdf_ft_font_destroy }; + +cairo_private cairo_status_t +_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, + cairo_scaled_font_subset_t *font_subset) +{ + cairo_unscaled_font_t *unscaled; + + unscaled = _cairo_ft_scaled_font_get_unscaled_font (font_subset->scaled_font); + + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +cairo_private void +_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) +{ + free (subset->base_font); + free (subset->widths); + free (subset->data); +} + diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 8cde5e4d1..30ae914ec 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1667,7 +1667,102 @@ static cairo_status_t _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) { - return CAIRO_INT_STATUS_UNSUPPORTED; + cairo_pdf_resource_t stream, descriptor, subset_resource; + cairo_status_t status; + cairo_pdf_font_t font; + cairo_truetype_subset_t subset; + unsigned long compressed_length; + char *compressed; + int i; + + status = _cairo_truetype_subset_init (&subset, font_subset); + if (status) + return status; + + compressed = compress_dup (subset.data, subset.data_length, + &compressed_length); + if (compressed == NULL) { + _cairo_truetype_subset_fini (&subset); + 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" + " /Length1 %lu\r\n" + ">>\r\n" + "stream\r\n", + stream.id, + compressed_length, + subset.data_length); + _cairo_output_stream_write (surface->output, compressed, compressed_length); + _cairo_output_stream_printf (surface->output, + "\r\n" + "endstream\r\n" + "endobj\r\n"); + free (compressed); + + descriptor = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Type /FontDescriptor\r\n" + " /FontName /7%s\r\n" + " /Flags 4\r\n" + " /FontBBox [ %ld %ld %ld %ld ]\r\n" + " /ItalicAngle 0\r\n" + " /Ascent %ld\r\n" + " /Descent %ld\r\n" + " /CapHeight 500\r\n" + " /StemV 80\r\n" + " /StemH 80\r\n" + " /FontFile2 %u 0 R\r\n" + ">>\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, + stream.id); + + subset_resource = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<< /Type /Font\r\n" + " /Subtype /TrueType\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, + descriptor.id); + + for (i = 0; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->output, + " %d", + subset.widths[i]); + + _cairo_output_stream_printf (surface->output, + " ]\r\n" + ">>\r\n" + "endobj\r\n"); + + font.font_id = font_subset->font_id; + font.subset_id = font_subset->subset_id; + font.subset_resource = subset_resource; + _cairo_array_append (&surface->fonts, &font); + + _cairo_truetype_subset_fini (&subset); + + return CAIRO_STATUS_SUCCESS; } static void diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h index aed01a306..a0b0dbcc7 100644 --- a/src/cairo-scaled-font-subsets-private.h +++ b/src/cairo-scaled-font-subsets-private.h @@ -179,4 +179,45 @@ _cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets, cairo_scaled_font_subset_callback_func_t font_subset_callback, void *closure); + +typedef struct _cairo_truetype_subset { + char *base_font; + int *widths; + long x_min, y_min, x_max, y_max; + long ascent, descent; + char *data; + unsigned long data_length; +} cairo_truetype_subset_t; + +/** + * _cairo_truetype_subset_init: + * @truetype_subset: a #cairo_truetype_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 + * truetype file corresponding to @font_subset and initialize + * @truetype_subset with information about the subset and the truetype + * data. + * + * Return value: CAIRO_STATUS_SUCCESS if successful, + * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a + * truetype file, or an non-zero value indicating an error. Possible + * errors include CAIRO_STATUS_NO_MEMORY. + **/ +cairo_private cairo_status_t +_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, + cairo_scaled_font_subset_t *font_subset); + +/** + * _cairo_truetype_subset_fini: + * @truetype_subset: a #cairo_truetype_subset_t + * + * Free all resources associated with @truetype_subset. After this + * call, @truetype_subset should not be used again without a + * subsequent call to _cairo_truetype_subset_init() again first. + **/ +cairo_private void +_cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset); + #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */ From e846dca44e8c60bf45ab84d7adaf7eefe3088f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 21:41:07 -0400 Subject: [PATCH 3/9] Hook _cairo_truetype_subset_init() up to existing truetype subset code. This is a minimal first change to get things working. The truetype subset code still needs to be renamed and moved around a bit. --- src/cairo-font-subset.c | 151 ++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 60 deletions(-) diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c index 5a1fcd170..6841e9820 100644 --- a/src/cairo-font-subset.c +++ b/src/cairo-font-subset.c @@ -52,29 +52,31 @@ struct ft_subset_glyph { unsigned long location; }; -struct cairo_font_subset_backend { - int (*use_glyph) (void *abstract_font, - int glyph); - cairo_status_t (*generate) (void *abstract_font, - const char **data, - unsigned long *length); - void (*destroy) (void *abstract_font); -}; +typedef struct _cairo_ft_font { + + cairo_scaled_font_subset_t *scaled_font_subset; + + struct { + cairo_unscaled_font_t *unscaled_font; + unsigned int font_id; + char *base_font; + int num_glyphs; + int *widths; + long x_min, y_min, x_max, y_max; + long ascent, descent; + } base; -typedef struct cairo_pdf_ft_font cairo_pdf_ft_font_t; -struct cairo_pdf_ft_font { - cairo_font_subset_t base; ft_subset_glyph_t *glyphs; FT_Face face; int checksum_index; cairo_array_t output; int *parent_to_subset; cairo_status_t status; -}; + +} cairo_pdf_ft_font_t; static int -cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph); - +cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph); #define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) ) @@ -115,56 +117,44 @@ be32_to_cpu(unsigned long v) #endif -static cairo_font_subset_backend_t cairo_pdf_ft_font_backend; - -int -_cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph) -{ - return font->backend->use_glyph (font, glyph); -} - -cairo_status_t -_cairo_font_subset_generate (cairo_font_subset_t *font, - const char **data, unsigned long *length) -{ - return font->backend->generate (font, data, length); -} - -void -_cairo_font_subset_destroy (cairo_font_subset_t *font) -{ - font->backend->destroy (font); -} - -cairo_font_subset_t * -_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font) +static cairo_status_t +_cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset, + cairo_pdf_ft_font_t **font_return) { + cairo_unscaled_font_t *unscaled_font; cairo_ft_unscaled_font_t *ft_unscaled_font; - FT_Face face; + cairo_status_t status = CAIRO_STATUS_NO_MEMORY; cairo_pdf_ft_font_t *font; + FT_Face face; unsigned long size; int i, j; /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ - if (! _cairo_unscaled_font_is_ft (unscaled_font)) - return NULL; + if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); + if (face == NULL) + /* Assume out of memory */ + return CAIRO_STATUS_NO_MEMORY; /* We currently only support freetype truetype fonts. */ size = 0; if (!FT_IS_SFNT (face) || FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0) - return NULL; + return CAIRO_INT_STATUS_UNSUPPORTED; font = malloc (sizeof (cairo_pdf_ft_font_t)); if (font == NULL) - return NULL; + return CAIRO_STATUS_NO_MEMORY; + + font->scaled_font_subset = scaled_font_subset; font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); - font->base.backend = &cairo_pdf_ft_font_backend; _cairo_array_init (&font->output, sizeof (char)); if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS) @@ -204,7 +194,9 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font) font->status = CAIRO_STATUS_SUCCESS; - return &font->base; + *font_return = font; + + return CAIRO_STATUS_SUCCESS; fail5: free (font->base.base_font); @@ -216,14 +208,13 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font) _cairo_array_fini (&font->output); fail1: free (font); - return NULL; + + return status; } static void -cairo_pdf_ft_font_destroy (void *abstract_font) +cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font) { - cairo_pdf_ft_font_t *font = abstract_font; - _cairo_unscaled_font_destroy (font->base.unscaled_font); free (font->base.base_font); free (font->parent_to_subset); @@ -738,10 +729,8 @@ cairo_pdf_ft_font_generate (void *abstract_font, } static int -cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph) +cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph) { - cairo_pdf_ft_font_t *font = abstract_font; - if (font->parent_to_subset[glyph] == 0) { font->parent_to_subset[glyph] = font->base.num_glyphs; font->glyphs[font->base.num_glyphs].parent_index = glyph; @@ -751,21 +740,63 @@ cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph) return font->parent_to_subset[glyph]; } -static cairo_font_subset_backend_t cairo_pdf_ft_font_backend = { - cairo_pdf_ft_font_use_glyph, - cairo_pdf_ft_font_generate, - cairo_pdf_ft_font_destroy -}; - cairo_private cairo_status_t _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, cairo_scaled_font_subset_t *font_subset) { - cairo_unscaled_font_t *unscaled; + cairo_pdf_ft_font_t *font; + cairo_status_t status; + const char *data; + unsigned long length, parent_glyph; + int i; - unscaled = _cairo_ft_scaled_font_get_unscaled_font (font_subset->scaled_font); + status = _cairo_pdf_ft_font_create (font_subset, &font); + if (status) + return status; - return CAIRO_INT_STATUS_UNSUPPORTED; + for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { + parent_glyph = font->scaled_font_subset->glyphs[i]; + cairo_pdf_ft_font_use_glyph (font, parent_glyph); + } + + status = cairo_pdf_ft_font_generate (font, &data, &length); + if (status) + goto fail1; + + truetype_subset->base_font = strdup (font->base.base_font); + if (truetype_subset->base_font == NULL) + goto fail1; + + truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs); + if (truetype_subset->widths == NULL) + goto fail2; + for (i = 0; i < font->base.num_glyphs; i++) + truetype_subset->widths[i] = font->base.widths[i]; + + truetype_subset->x_min = font->base.x_min; + truetype_subset->y_min = font->base.y_min; + truetype_subset->x_max = font->base.x_max; + truetype_subset->y_max = font->base.y_max; + truetype_subset->ascent = font->base.ascent; + truetype_subset->descent = font->base.descent; + + truetype_subset->data = malloc (length); + if (truetype_subset->data == NULL) + goto fail3; + + memcpy (truetype_subset->data, data, length); + truetype_subset->data_length = length; + + return CAIRO_STATUS_SUCCESS; + + fail3: + free (truetype_subset->widths); + fail2: + free (truetype_subset->base_font); + fail1: + cairo_pdf_ft_font_destroy (font); + + return status; } cairo_private void From 2c6e799ee64cfc00145ecbe0d0b93256c237dcf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 22:53:05 -0400 Subject: [PATCH 4/9] Switch to using Tm for text positioning and scale type3 fonts to unit size. This change changes the text output code to use the Tm operator for positioning the glyphs. This allows us to set the scale matrix from the cairo_scaled_font_t so truetype glyphs get transformed correctly. However, we now need to scale type3 glyph to unity to compensate. Longer term we should just only output one unit sized type3 subset for a cairo_font_face_t and use that for all cairo_scaled_font_t's coming from that font face. Also, this fixes a num_glyphs initialization bug. --- src/cairo-font-subset.c | 2 +- src/cairo-pdf-surface.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c index 6841e9820..6ff93e5fb 100644 --- a/src/cairo-font-subset.c +++ b/src/cairo-font-subset.c @@ -168,7 +168,7 @@ _cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset, if (font->parent_to_subset == NULL) goto fail3; - font->base.num_glyphs = 1; + font->base.num_glyphs = 0; font->base.x_min = face->bbox.xMin; font->base.y_min = face->bbox.yMin; font->base.x_max = face->bbox.xMax; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 30ae914ec..3ab2d89d0 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -1830,6 +1830,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, { cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource; cairo_pdf_font_t font; + cairo_matrix_t matrix; int i; glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t)); @@ -1871,17 +1872,23 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, "endobj\r\n"); subset_resource = _cairo_pdf_surface_new_object (surface); + matrix = font_subset->scaled_font->scale; + cairo_matrix_invert (&matrix); _cairo_output_stream_printf (surface->output, "%d 0 obj\r\n" "<< /Type /Font\r\n" " /Subtype /Type3\r\n" " /FontBBox [0 0 0 0]\r\n" - " /FontMatrix\t[1 0 0 1 0 0]\r\n" + " /FontMatrix [ %f %f %f %f 0 0 ]\r\n" " /Encoding %d 0 R\r\n" " /CharProcs %d 0 R\r\n" " /FirstChar 0\r\n" " /LastChar %d\r\n", subset_resource.id, + matrix.xx, + matrix.yx, + -matrix.xy, + -matrix.yy, encoding.id, char_procs.id, font_subset->num_glyphs - 1); @@ -2465,6 +2472,9 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, if (status) return status; + _cairo_output_stream_printf (surface->output, + "BT\r\n"); + for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, scaled_font, glyphs[i].index, @@ -2478,13 +2488,22 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, font_id, subset_id); current_subset_id = subset_id; } + _cairo_output_stream_printf (surface->output, - "BT %f %f Td <%c%c> Tj ET\r\n", - glyphs[i].x, glyphs[i].y, + "%f %f %f %f %f %f Tm <%c%c> Tj\r\n", + scaled_font->scale.xx, + scaled_font->scale.yx, + -scaled_font->scale.xy, + -scaled_font->scale.yy, + glyphs[i].x, + glyphs[i].y, hex_digit (subset_glyph_index >> 4), hex_digit (subset_glyph_index)); } + _cairo_output_stream_printf (surface->output, + "ET\r\n"); + return _cairo_output_stream_get_status (surface->output); } From 3975d7f8a26b53d4d2c7d587fbcfe9ed6ddf78d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 23:20:08 -0400 Subject: [PATCH 5/9] Add support for truetype subset to ps backend. Same story as for the pdf backend: try to output a truetype subset if possible, otherwise fall back to a type3 font. Ajdust text output code to scale font accordingly and scale type3 fonts to unity. --- src/cairo-ps-surface.c | 113 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 8 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index fb8935b4e..4e718ac7d 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -211,6 +211,68 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) } } +static cairo_status_t +_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) + + +{ + cairo_truetype_subset_t subset; + cairo_status_t status; + int i; + + status = _cairo_truetype_subset_init (&subset, font_subset); + if (status) + return status; + + /* FIXME: Figure out document structure convention for fonts */ + + _cairo_output_stream_printf (surface->final_stream, + "11 dict begin\n" + "/FontType 42 def\n" + "/FontName /CairoFont-%d-%d def\n" + "/PaintType 0 def\n" + "/FontMatrix [ 1 0 0 1 0 0 ] def\n" + "/FontBBox [ 0 0 0 0 ] def\n" + "/Encoding 256 array def\n" + "0 1 255 { Encoding exch /.notdef put } for\n", + font_subset->font_id, + font_subset->subset_id); + + /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */ + + 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); + + for (i = 1; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->final_stream, + "/g%d %d def\n", i, i); + + _cairo_output_stream_printf (surface->final_stream, + "end readonly def\n"); + + /* FIXME: We need to break up fonts bigger than 64k so we don't + * exceed string size limitation. At glyph boundaries. Stupid + * postscript. */ + _cairo_output_stream_printf (surface->final_stream, + "/sfnts [<"); + + _cairo_output_stream_write_hex_string (surface->final_stream, + subset.data, subset.data_length); + + _cairo_output_stream_printf (surface->final_stream, + ">] def\n" + "FontName currentdict end definefont pop\n"); + + return CAIRO_STATUS_SUCCESS; +} + static void _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, @@ -267,11 +329,13 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, "\t\t}\n"); } -static void -_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, - void *closure) +static cairo_status_t +_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, + cairo_scaled_font_subset_t *font_subset) + + { - cairo_ps_surface_t *surface = closure; + cairo_matrix_t matrix; int i; _cairo_output_stream_printf (surface->final_stream, @@ -282,12 +346,18 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, font_subset->font_id, font_subset->subset_id); + matrix = font_subset->scaled_font->scale; + cairo_matrix_invert (&matrix); _cairo_output_stream_printf (surface->final_stream, "\t/FontType\t3\n" - "\t/FontMatrix\t[1 0 0 1 0 0]\n" + "\t/FontMatrix\t[%f %f %f %f 0 0]\n" "\t/Encoding\t[0]\n" "\t/FontBBox\t[0 0 10 10]\n" - "\t/Glyphs [\n"); + "\t/Glyphs [\n", + matrix.xx, + matrix.yx, + -matrix.xy, + -matrix.yy); for (i = 0; i < font_subset->num_glyphs; i++) { _cairo_ps_surface_emit_glyph (surface, @@ -302,6 +372,25 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, "\t\texch get exec\n" "\t}\n" ">> definefont pop\n"); + + return CAIRO_STATUS_SUCCESS; +} + + +static void +_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) +{ + cairo_ps_surface_t *surface = closure; + cairo_status_t status; + + status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; + + status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return; } static cairo_status_t @@ -1757,10 +1846,18 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, if (subset_id != current_subset_id) { _cairo_output_stream_printf (surface->stream, - "/CairoFont-%d-%d 1 selectfont\n", - font_id, subset_id); + "/CairoFont-%d-%d findfont\n" + "[ %f %f %f %f 0 0 ] makefont\n" + "setfont\n", + font_id, + subset_id, + scaled_font->scale.xx, + scaled_font->scale.yx, + -scaled_font->scale.xy, + -scaled_font->scale.yy); current_subset_id = subset_id; } + _cairo_output_stream_printf (surface->stream, "%f %f M <%c%c> S\n", glyphs[i].x, glyphs[i].y, From f3209660c33bc128c58ec487c51440271f30a923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 23:24:09 -0400 Subject: [PATCH 6/9] Print out ps comment in the truetype emit code and update type3 ps comment. --- src/cairo-ps-surface.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 4e718ac7d..f92da8327 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -227,6 +227,9 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, /* FIXME: Figure out document structure convention for fonts */ + _cairo_output_stream_printf (surface->final_stream, + "%% _cairo_ps_surface_emit_truetype_font_subset\n"); + _cairo_output_stream_printf (surface->final_stream, "11 dict begin\n" "/FontType 42 def\n" @@ -339,7 +342,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, int i; _cairo_output_stream_printf (surface->final_stream, - "%% _cairo_ps_surface_emit_font_subset\n"); + "%% _cairo_ps_surface_emit_type3_font_subset\n"); _cairo_output_stream_printf (surface->final_stream, "/CairoFont-%d-%d <<\n", From d42b2c7a89451e95e6e9ec6bc439f06855c66802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 16 May 2006 23:56:38 -0400 Subject: [PATCH 7/9] Remember to destroy cairo_pdf_ft_font_t once we've generated the subset. Also, remove cairo_private from function definitions. --- src/cairo-font-subset.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c index 6ff93e5fb..ef0a22559 100644 --- a/src/cairo-font-subset.c +++ b/src/cairo-font-subset.c @@ -740,7 +740,7 @@ cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph) return font->parent_to_subset[glyph]; } -cairo_private cairo_status_t +cairo_status_t _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, cairo_scaled_font_subset_t *font_subset) { @@ -787,6 +787,8 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, memcpy (truetype_subset->data, data, length); truetype_subset->data_length = length; + cairo_pdf_ft_font_destroy (font); + return CAIRO_STATUS_SUCCESS; fail3: @@ -799,7 +801,7 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, return status; } -cairo_private void +void _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset) { free (subset->base_font); From b16c29ff0c38b8fa8e5753770bb93ad9ff084579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 17 May 2006 01:30:43 -0400 Subject: [PATCH 8/9] Set libcairo_font_subset_sources for ps, pdf, and svg backends. Backends that use the font subsetting code should add the font subsetting sources to the build. This is dont by setting libcairo_font_subset_sources, in the conditional section for each backend. If any one is enabled, the sources will be added to the build. --- src/Makefile.am | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 6390d3290..bf1068aee 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,14 +1,19 @@ +font_subset_sources = \ + cairo-font-subset.c \ + cairo-font-subset-private.h \ + cairo-scaled-font-subsets.c \ + cairo-scaled-font-subsets-private.h if CAIRO_HAS_PS_SURFACE libcairo_ps_headers = cairo-ps.h -libcairo_ps_sources = cairo-ps-surface.c cairo-scaled-font-subsets.c cairo-scaled-font-subsets-private.h -libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h +libcairo_ps_sources = cairo-ps-surface.c +libcairo_font_subset_sources = $(font_subset_sources) endif if CAIRO_HAS_PDF_SURFACE libcairo_pdf_headers = cairo-pdf.h libcairo_pdf_sources = cairo-pdf-surface.c -libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h +libcairo_font_subset_sources = $(font_subset_sources) endif if CAIRO_HAS_PNG_FUNCTIONS @@ -18,6 +23,7 @@ endif if CAIRO_HAS_SVG_SURFACE libcairo_svg_headers = cairo-svg.h libcairo_svg_sources = cairo-svg-surface.c +libcairo_font_subset_sources = $(font_subset_sources) endif if CAIRO_HAS_TEST_SURFACES From 127fab4695ef849364e755e10c2b960add78782b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 18 May 2006 02:12:06 -0400 Subject: [PATCH 9/9] Remember to call _cairo_truetype_subset_fini() after outputting subset. --- src/cairo-ps-surface.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index f92da8327..eaf4924f2 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -249,7 +249,7 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, "Encoding %d /g%d put\n", i, i); _cairo_output_stream_printf (surface->final_stream, - "/CharStrings %d dict dup begin\n" + "/CharStrings %d dict dup begin\n" "/.notdef 0 def\n", font_subset->num_glyphs); @@ -270,9 +270,11 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, subset.data, subset.data_length); _cairo_output_stream_printf (surface->final_stream, - ">] def\n" + ">] def\n" "FontName currentdict end definefont pop\n"); + _cairo_truetype_subset_fini (&subset); + return CAIRO_STATUS_SUCCESS; }