From e2c03d51daa60bf18b66ace148e6f8df7c454e2c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 09:28:32 -0700 Subject: [PATCH 01/10] Change scaled_font_subsets_callback to have return type of void. The return of status from this callback was misleading. The function actually calling the callback was also a hash table callback function, which itself is void---so any status value returned was being lost. Instead, we now stash any errors that occur during the fallback into surface->status. --- src/cairo-ps-surface.c | 30 ++++++++++++------------- src/cairo-scaled-font-subsets-private.h | 2 +- src/cairo-svg-surface.c | 25 +++++++++------------ 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 42196b0c3..a91a10706 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -211,7 +211,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) } } -static cairo_status_t +static void _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, @@ -220,9 +220,6 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; - _cairo_output_stream_printf (surface->final_stream, - "\t\t{ %% %d\n", subset_glyph_index); - status = _cairo_scaled_glyph_lookup (scaled_font, scaled_font_glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS| @@ -238,13 +235,16 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (status) { - _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); - return status; + _cairo_surface_set_error (&surface->base, status); + return; } /* XXX: Need to actually use the image not the path if that's all * we could get... */ + _cairo_output_stream_printf (surface->final_stream, + "\t\t{ %% %d\n", subset_glyph_index); + _cairo_output_stream_printf (surface->final_stream, "%f %f %f %f 0 0 setcachedevice\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), @@ -265,10 +265,9 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); - return CAIRO_STATUS_SUCCESS; } -static cairo_status_t +static void _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, void *closure) { @@ -303,22 +302,23 @@ _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_output_stream_get_status (surface->final_stream); } - -static void +static cairo_status_t _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) { + cairo_status_t status; + _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_font_subsets\n"); - _cairo_scaled_font_subsets_foreach (surface->font_subsets, - _cairo_ps_surface_emit_font_subset, - surface); + status = _cairo_scaled_font_subsets_foreach (surface->font_subsets, + _cairo_ps_surface_emit_font_subset, + surface); _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; + + return status; } static void diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h index d4137d436..aed01a306 100644 --- a/src/cairo-scaled-font-subsets-private.h +++ b/src/cairo-scaled-font-subsets-private.h @@ -140,7 +140,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets, unsigned int *subset_id_ret, unsigned int *subset_glyph_index_ret); -typedef cairo_status_t +typedef void (*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset, void *closure); diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 3bd51218f..8a0fd97f0 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -545,7 +545,7 @@ _cairo_svg_path_close_path (void *closure) return CAIRO_STATUS_SUCCESS; } -static cairo_status_t +static void _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, @@ -572,8 +572,10 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); - if (status) - return status; + if (status) { + _cairo_surface_set_error (document->owner, status); + return; + } info.document = document; info.path = xmlBufferCreate (); @@ -597,28 +599,21 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, xmlSetProp (child, CC2XML ("style"), CC2XML ("stroke: none;")); xmlBufferFree (info.path); - - return CAIRO_STATUS_SUCCESS; } -static cairo_status_t +static void _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset, void *closure) { cairo_svg_document_t *document = closure; - cairo_status_t status; int i; for (i = 0; i < font_subset->num_glyphs; i++) { - status = _cairo_svg_document_emit_glyph (document, - font_subset->scaled_font, - font_subset->glyphs[i], - font_subset->font_id, i); - if (status) - return status; + _cairo_svg_document_emit_glyph (document, + font_subset->scaled_font, + font_subset->glyphs[i], + font_subset->font_id, i); } - - return CAIRO_STATUS_SUCCESS; } static void From cb32b41a4e24df612dc0cabbe1e22098584759e9 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 09:39:16 -0700 Subject: [PATCH 02/10] PS: Fix arguments to setcachedevice Since we are only ever displaying a single glyph at a time we don't care about the width values passed to setcachedevice at all---we only care about the bounding box. That's what the code was trying to do before, but the arguments were misaligned and we were instead passing bounding-box values for the widths and hard-coding half of the bounding-box values as 0. --- src/cairo-ps-surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index a91a10706..3ba42b416 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -246,7 +246,7 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, "\t\t{ %% %d\n", subset_glyph_index); _cairo_output_stream_printf (surface->final_stream, - "%f %f %f %f 0 0 setcachedevice\n", + "0 0 %f %f %f %f setcachedevice\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), From 45d0540c3375bfdb09973a809c08b5dec1ae2219 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 09:41:36 -0700 Subject: [PATCH 03/10] PS: Remove the fallback case from _cairo_ps_surface_show_glyphs The only expected errors that would lead to this fallback are serious problems such as out of memory. There's no reason to go to heroic efforts to draw as much as possible in face of an error like that. Prefer simpler code instead. --- src/cairo-ps-surface.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 3ba42b416..fb8935b4e 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1732,11 +1732,10 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, { cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; - cairo_int_status_t status; - cairo_path_fixed_t *path; - int i; int current_subset_id = -1; unsigned int font_id, subset_id, subset_glyph_index; + cairo_status_t status; + int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -1753,11 +1752,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, scaled_font, glyphs[i].index, &font_id, &subset_id, &subset_glyph_index); - if (status) { - glyphs += i; - num_glyphs -= i; - goto fallback; - } + if (status) + return status; + if (subset_id != current_subset_id) { _cairo_output_stream_printf (surface->stream, "/CairoFont-%d-%d 1 selectfont\n", @@ -1770,19 +1767,8 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface, hex_digit (subset_glyph_index >> 4), hex_digit (subset_glyph_index)); } - - return CAIRO_STATUS_SUCCESS; -fallback: - - path = _cairo_path_fixed_create (); - _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, path); - status = _cairo_ps_surface_fill (abstract_surface, op, source, - path, CAIRO_FILL_RULE_WINDING, - 0.1, scaled_font->options.antialias); - _cairo_path_fixed_destroy (path); - - return CAIRO_STATUS_SUCCESS; + return _cairo_output_stream_get_status (surface->stream); } static void From 049100fb870bee89b28bd14a9625add33f38a2bd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 09:52:57 -0700 Subject: [PATCH 04/10] PDF: Use consistent style for typedef struct and macro naming. --- src/cairo-pdf-surface.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 2746cd07c..f96a06daf 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -86,19 +86,15 @@ * instead of outputting the cm operator in every page. */ -typedef struct cairo_pdf_object cairo_pdf_object_t; -typedef struct cairo_pdf_resource cairo_pdf_resource_t; -typedef struct cairo_pdf_surface cairo_pdf_surface_t; - -struct cairo_pdf_object { +typedef struct _cairo_pdf_object { long offset; -}; +} cairo_pdf_object_t; -struct cairo_pdf_resource { +typedef struct _cairo_pdf_resource { unsigned int id; -}; +} cairo_pdf_resource_t; -struct cairo_pdf_surface { +typedef struct _cairo_pdf_surface { cairo_surface_t base; /* Prefer the name "output" here to avoid confusion over the @@ -130,9 +126,9 @@ struct cairo_pdf_surface { cairo_bool_t has_clip; cairo_paginated_mode_t paginated_mode; -}; +} cairo_pdf_surface_t; -#define DEFAULT_DPI 300 +#define PDF_SURFACE_DPI_DEFAULT 300 static cairo_pdf_resource_t _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); @@ -258,8 +254,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface->width = width; surface->height = height; - surface->x_dpi = DEFAULT_DPI; - surface->y_dpi = DEFAULT_DPI; + surface->x_dpi = PDF_SURFACE_DPI_DEFAULT; + surface->y_dpi = PDF_SURFACE_DPI_DEFAULT; _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t)); _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t)); From 6f417fed51672ccca305b7fcc8b1bc3af7609534 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 10:00:18 -0700 Subject: [PATCH 05/10] PDF: Move Resources dictionary up from Page objects to Pages object. This allows for more sharing of resource objects. It also avoids some confusion in trying to set independent resources at a global and a per-page level, (which doesn't work since the inheritance only works for an entire resources object---it can only be overriden in its entirety, not for subsets of the resources). --- src/cairo-pdf-surface.c | 118 ++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index f96a06daf..f55db0466 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -455,9 +455,6 @@ static void _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) { _cairo_array_truncate (&surface->streams, 0); - _cairo_array_truncate (&surface->patterns, 0); - _cairo_array_truncate (&surface->xobjects, 0); - _cairo_array_truncate (&surface->alphas, 0); } static cairo_surface_t * @@ -1543,8 +1540,10 @@ _cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface) static void _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) { - cairo_pdf_resource_t page; + cairo_pdf_resource_t page, *res; int num_pages, i; + int num_alphas, num_resources; + double alpha; _cairo_pdf_surface_update_object (surface, surface->pages_resource); _cairo_output_stream_printf (surface->output, @@ -1562,6 +1561,60 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) _cairo_output_stream_printf (surface->output, "]\r\n"); _cairo_output_stream_printf (surface->output, " /Count %d\r\n", num_pages); + _cairo_output_stream_printf (surface->output, " /Resources <<\r\n"); + + num_alphas = _cairo_array_num_elements (&surface->alphas); + if (num_alphas > 0) { + _cairo_output_stream_printf (surface->output, + " /ExtGState <<\r\n"); + + for (i = 0; i < num_alphas; i++) { + /* With some work, we could separate the stroking + * or non-stroking alpha here as actually needed. */ + _cairo_array_copy_element (&surface->alphas, i, &alpha); + _cairo_output_stream_printf (surface->output, + " /a%d << /CA %f /ca %f >>\r\n", + i, alpha, alpha); + } + + _cairo_output_stream_printf (surface->output, + " >>\r\n"); + } + + num_resources = _cairo_array_num_elements (&surface->patterns); + if (num_resources > 0) { + _cairo_output_stream_printf (surface->output, + " /Pattern <<"); + for (i = 0; i < num_resources; i++) { + res = _cairo_array_index (&surface->patterns, i); + _cairo_output_stream_printf (surface->output, + " /res%d %d 0 R", + res->id, res->id); + } + + _cairo_output_stream_printf (surface->output, + " >>\r\n"); + } + + num_resources = _cairo_array_num_elements (&surface->xobjects); + if (num_resources > 0) { + _cairo_output_stream_printf (surface->output, + " /XObject <<"); + + for (i = 0; i < num_resources; i++) { + res = _cairo_array_index (&surface->xobjects, i); + _cairo_output_stream_printf (surface->output, + " /res%d %d 0 R", + res->id, res->id); + } + + _cairo_output_stream_printf (surface->output, + " >>\r\n"); + } + + _cairo_output_stream_printf (surface->output, + " >>\r\n"); + /* TODO: Figure out wich other defaults to be inherited by /Page * objects. */ _cairo_output_stream_printf (surface->output, @@ -1730,11 +1783,9 @@ static cairo_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) { cairo_status_t status; - cairo_pdf_resource_t *res; cairo_pdf_resource_t page; - double alpha; cairo_pdf_resource_t stream; - int num_streams, num_alphas, num_resources, i; + int num_streams, i; if (surface->has_clip) { _cairo_output_stream_printf (surface->output, "Q\r\n"); @@ -1773,59 +1824,6 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) " ]\r\n"); _cairo_output_stream_printf (surface->output, - " /Resources <<\r\n"); - - num_alphas = _cairo_array_num_elements (&surface->alphas); - if (num_alphas > 0) { - _cairo_output_stream_printf (surface->output, - " /ExtGState <<\r\n"); - - for (i = 0; i < num_alphas; i++) { - /* With some work, we could separate the stroking - * or non-stroking alpha here as actually needed. */ - _cairo_array_copy_element (&surface->alphas, i, &alpha); - _cairo_output_stream_printf (surface->output, - " /a%d << /CA %f /ca %f >>\r\n", - i, alpha, alpha); - } - - _cairo_output_stream_printf (surface->output, - " >>\r\n"); - } - - num_resources = _cairo_array_num_elements (&surface->patterns); - if (num_resources > 0) { - _cairo_output_stream_printf (surface->output, - " /Pattern <<"); - for (i = 0; i < num_resources; i++) { - res = _cairo_array_index (&surface->patterns, i); - _cairo_output_stream_printf (surface->output, - " /res%d %d 0 R", - res->id, res->id); - } - - _cairo_output_stream_printf (surface->output, - " >>\r\n"); - } - - num_resources = _cairo_array_num_elements (&surface->xobjects); - if (num_resources > 0) { - _cairo_output_stream_printf (surface->output, - " /XObject <<"); - - for (i = 0; i < num_resources; i++) { - res = _cairo_array_index (&surface->xobjects, i); - _cairo_output_stream_printf (surface->output, - " /res%d %d 0 R", - res->id, res->id); - } - - _cairo_output_stream_printf (surface->output, - " >>\r\n"); - } - - _cairo_output_stream_printf (surface->output, - " >>\r\n" ">>\r\n" "endobj\r\n"); From bf2ab0de927dae4a1dd67a0cbacefabaf0e4255b Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 10:04:53 -0700 Subject: [PATCH 06/10] PDF: Add Type3 font support to PDF output. This uses the recently added cairo-scaled-font-subsets interface in a style very similar to what the PS surface does. --- src/cairo-pdf-surface.c | 242 +++++++++++++++++++++-- test/select-font-face-pdf-argb32-ref.png | Bin 2781 -> 2782 bytes 2 files changed, 231 insertions(+), 11 deletions(-) diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index f55db0466..a48182d28 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -38,7 +38,7 @@ #include "cairoint.h" #include "cairo-pdf.h" -#include "cairo-font-subset-private.h" +#include "cairo-scaled-font-subsets-private.h" #include "cairo-ft-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-path-fixed-private.h" @@ -94,6 +94,12 @@ typedef struct _cairo_pdf_resource { unsigned int id; } cairo_pdf_resource_t; +typedef struct _cairo_pdf_font { + unsigned int font_id; + unsigned int subset_id; + cairo_pdf_resource_t subset_resource; +} cairo_pdf_font_t; + typedef struct _cairo_pdf_surface { cairo_surface_t base; @@ -113,6 +119,9 @@ typedef struct _cairo_pdf_surface { cairo_array_t streams; cairo_array_t alphas; + cairo_scaled_font_subsets_t *font_subsets; + cairo_array_t fonts; + cairo_pdf_resource_t next_available_resource; cairo_pdf_resource_t pages_resource; @@ -128,7 +137,8 @@ typedef struct _cairo_pdf_surface { cairo_paginated_mode_t paginated_mode; } cairo_pdf_surface_t; -#define PDF_SURFACE_DPI_DEFAULT 300 +#define PDF_SURFACE_DPI_DEFAULT 300 +#define PDF_SURFACE_MAX_GLYPHS_PER_FONT 256 static cairo_pdf_resource_t _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); @@ -162,6 +172,9 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface); static cairo_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); +static cairo_status_t +_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface); + static const cairo_surface_backend_t cairo_pdf_surface_backend; static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend; @@ -264,6 +277,15 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _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); + if (! surface->font_subsets) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + free (surface); + return (cairo_surface_t*) &_cairo_surface_nil; + } + + _cairo_array_init (&surface->fonts, sizeof (cairo_pdf_font_t)); + surface->next_available_resource.id = 1; surface->pages_resource = _cairo_pdf_surface_new_object (surface); @@ -538,6 +560,8 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_pdf_surface_close_stream (surface); + _cairo_pdf_surface_emit_font_subsets (surface); + _cairo_pdf_surface_write_pages (surface); info = _cairo_pdf_surface_write_info (surface); @@ -570,6 +594,13 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->streams); _cairo_array_fini (&surface->alphas); + if (surface->font_subsets) { + _cairo_scaled_font_subsets_destroy (surface->font_subsets); + surface->font_subsets = NULL; + } + + _cairo_array_fini (&surface->fonts); + return status; } @@ -1541,7 +1572,8 @@ static void _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) { cairo_pdf_resource_t page, *res; - int num_pages, i; + cairo_pdf_font_t font; + int num_pages, num_fonts, i; int num_alphas, num_resources; double alpha; @@ -1612,6 +1644,15 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) " >>\r\n"); } + _cairo_output_stream_printf (surface->output," /Font <<\r\n"); + num_fonts = _cairo_array_num_elements (&surface->fonts); + for (i = 0; i < num_fonts; i++) { + _cairo_array_copy_element (&surface->fonts, i, &font); + _cairo_output_stream_printf (surface->output, " /CairoFont-%d-%d %d 0 R\r\n", + font.font_id, font.subset_id, font.subset_resource.id); + } + _cairo_output_stream_printf (surface->output, " >>\r\n"); + _cairo_output_stream_printf (surface->output, " >>\r\n"); @@ -1625,6 +1666,162 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) surface->height); } +static void +_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface, + cairo_scaled_font_t *scaled_font, + unsigned long scaled_font_glyph_index, + unsigned int subset_glyph_index, + cairo_pdf_resource_t *glyph_ret) +{ + cairo_scaled_glyph_t *scaled_glyph; + cairo_status_t status; + + status = _cairo_scaled_glyph_lookup (scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS| + CAIRO_SCALED_GLYPH_INFO_PATH, + &scaled_glyph); + /* + * If that fails, try again but ask for an image instead + */ + if (status) + status = _cairo_scaled_glyph_lookup (scaled_font, + scaled_font_glyph_index, + CAIRO_SCALED_GLYPH_INFO_METRICS| + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + if (status) { + _cairo_surface_set_error (&surface->base, status); + return; + } + + /* XXX: Need to actually use the image not the path if that's all + * we could get... */ + + *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL); + + _cairo_output_stream_printf (surface->output, + "0 0 %f %f %f %f d1\r\n" + " \r\n", + _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), + -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y), + _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), + -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); + + status = _cairo_path_fixed_interpret (scaled_glyph->path, + CAIRO_DIRECTION_FORWARD, + _cairo_pdf_path_move_to, + _cairo_pdf_path_line_to, + _cairo_pdf_path_curve_to, + _cairo_pdf_path_close_path, + surface->output); + + _cairo_output_stream_printf (surface->output, + " f"); + + _cairo_pdf_surface_close_stream (surface); + + if (status) + _cairo_surface_set_error (&surface->base, status); +} + +static void +_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset, + void *closure) +{ + cairo_pdf_surface_t *surface = closure; + cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource; + cairo_pdf_font_t font; + int i; + + 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; + } + + for (i = 0; i < font_subset->num_glyphs; i++) { + _cairo_pdf_surface_emit_glyph (surface, + font_subset->scaled_font, + font_subset->glyphs[i], i, + &glyphs[i]); + } + + encoding = _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); + for (i = 0; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->output, + " /%d", i); + _cairo_output_stream_printf (surface->output, + "]\r\n" + ">>\r\n" + "endobj\r\n"); + + char_procs = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\r\n" + "<<\r\n", char_procs.id); + for (i = 0; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->output, + " /%d %d 0 R\r\n", + i, glyphs[i].id); + _cairo_output_stream_printf (surface->output, + ">>\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 /Type3\r\n" + " /FontBBox [0 0 0 0]\r\n" + " /FontMatrix\t[1 0 0 1 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, + encoding.id, + char_procs.id, + font_subset->num_glyphs - 1); + + _cairo_output_stream_printf (surface->output, + " /Widths ["); + for (i = 0; i < font_subset->num_glyphs; i++) + _cairo_output_stream_printf (surface->output, " 0"); + _cairo_output_stream_printf (surface->output, + "]\r\n"); + + _cairo_output_stream_printf (surface->output, + ">>\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); +} + +static cairo_status_t +_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface) +{ + cairo_status_t status; + + status = _cairo_scaled_font_subsets_foreach (surface->font_subsets, + _cairo_pdf_surface_emit_font_subset, + surface); + _cairo_scaled_font_subsets_destroy (surface->font_subsets); + surface->font_subsets = NULL; + + if (status) + return status; + + return CAIRO_STATUS_SUCCESS; +} + #if 0 static cairo_status_t _cairo_pdf_surface_write_fonts (cairo_pdf_surface_t *surface) @@ -2125,6 +2322,14 @@ _cairo_pdf_surface_fill (void *abstract_surface, return status; } +static char +hex_digit (int i) +{ + i &= 0xf; + if (i < 10) return '0' + i; + return 'a' + (i - 10); +} + static cairo_int_status_t _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, @@ -2134,8 +2339,10 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, cairo_scaled_font_t *scaled_font) { cairo_pdf_surface_t *surface = abstract_surface; - cairo_path_fixed_t path; + int current_subset_id = -1; + unsigned int font_id, subset_id, subset_glyph_index; cairo_status_t status; + int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); @@ -2146,14 +2353,27 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface, if (status) return status; - _cairo_path_fixed_init (&path); - _cairo_scaled_font_glyph_path (scaled_font, glyphs, num_glyphs, &path); - status = _cairo_pdf_surface_fill (surface, op, source, - &path, CAIRO_FILL_RULE_WINDING, - 0.1, scaled_font->options.antialias); - _cairo_path_fixed_fini (&path); + for (i = 0; i < num_glyphs; i++) { + status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, + scaled_font, glyphs[i].index, + &font_id, &subset_id, &subset_glyph_index); + if (status) + return status; - return status; + if (subset_id != current_subset_id) { + _cairo_output_stream_printf (surface->output, + "/CairoFont-%d-%d 1 Tf\r\n", + 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, + hex_digit (subset_glyph_index >> 4), + hex_digit (subset_glyph_index)); + } + + return _cairo_output_stream_get_status (surface->output); } static void diff --git a/test/select-font-face-pdf-argb32-ref.png b/test/select-font-face-pdf-argb32-ref.png index b2de418273822d01d6fb90c1db7ce03ee475484b..9b8c07a465e1c4a202a24aba82d941c0dfff9a10 100644 GIT binary patch delta 2701 zcmWkwc_7pMAODi@E5Ar`6wzZLPY==_jf|3WIck^Sj*d0(&N%{@GEIP;7IB@1o=o*0u1QB%&ImLK*{ z23VnHnKZQ)FFnMiWVB&ucxe2jrSm5(y;dig(vqsmM z?bQxV8Tn(l@7q&giu}HP`#!SSmOBF1qSY_lhLy(kUX-21S)ib9(VwVRB?Ut99O`fLr@xzDTNC1Pu!d9>~DKAfxV0A@5yCG&pBo>E< zhihtRq-SJ+yli*n2YT74Y!t(nDQ%JGQpA>+T3{EImX^jfS?KErvtK#^{TvQqHrC$0 zv$gd+7K_DT1~)bkY0Qd|5Cn0u5l?n5+TEDVn3$L_Kh{ToJ+#zNU;mS~HlMpHo&;MW zc@IF_!s%OxoSdAo+He^l8^swNt;es=y?Uh|6C);(6blDp7Y9#PjXcZE)i`#{!sUH1 z<2f?ErmBi;TS!PvRaRD(JRcn`PtPc4KeejU3bI3%a8V~~Ichp(>_g{ff z*wfv;E)-rb99nY8HH%*ONF#_J-n(}TN-PjKIy-;gUOhgBsDb^XU6qjZEI`m{>#v?@edFL zt*xzneSKqN-=5d%4}y2ry?y((tjqw3+tbAp@fltI0sj8r;LuQ^Q%zkR^y5ZnmiFGg zdlM5A_X~4y$AR)NKen4$B!TX{WnTM>VkrM znK%B5_`?U39244hRb{2(p+gy(mInYbnVglCm7JUmAuO_Pd%e%nt~W11MK^G6vOb`&VmkDfI{LL9ay!Bypu zNM!MECaQ8U2a!O4;Ld#<9`2l71(in~NH~Q0?CfkxO3F9!%I?fV!^|^jO#GJMqytG? zTN~(Svs0ecd4~lC^34g=)z#bEcS<;BePI*uUAeCu7+y#fjaZ8_m(bUu=!TRzn!Hm?@HXrjl8(;s) zInzPZh`)kWekhzD(57SlrcmZ?A%fsXE+`o1oYK*eHie%(drtFLz&!SA60D0#Jub(z zCsmJxK#ba1uAR(e9u04d5H4OF9aoDJ{W~HO-3Abe+p#zt?#2ymFF|{I`&@m~_pPPk z=`UZ1qc}4SrV$zJ@;A;wqtSp5w?3M~;Xpv3)9Kg*A%}V~4ejbGah{GL5{U)19YJv7 zqeqU8joprrJt+1AEJey6-TBLA{pV^dSi^5_ZWhb+I-i$7E-GsM>(}`&Uu;D)Gk!Gm{{R~sn+mX^qH}(6 z@q=FlkYq(Q%5kh3dF@t`d-xVaZ?Bbslr^zf27n}c76F(iZa>kI4XnIy;R2J%>~qW? z9v+^W@_}L8-Q8VX*+WD8nVB`FyyZX0@A=3?-=n}hZYxbQQ5MjASl}uKi!C1r+WPkGB&hTOLg}AY)81g9+~-Mbsw)~T zS{{=DybWSj-`m;QT{+sZ8ol(1T5;`(O5ExrTkQ`C0RgEjKjgZ`e9zfQC0QxS&0DN)%Az9596-R*UkG-eww5)zkj zE?3hs(fr)GOEmPr8D!MlBW@Vh+Np5BFDSH`874S`MtS@YwwLt!C+EN>qpXU=@?r( zJ2o`NFmC-`!2FmCOwqK-=BEL|eifp+>CDQCB?5skGSVV<#hO32qP9kOQ!hI@IYCzS zTRrZ6$1G=X@JY`cWD!yP-k$%v7qOdmzkh>dJTx?vMx$Z$gNaOHEDy-a z8XZYjKLE;vPWGM9)#Yyqm!RV*po-g^5a0J4dG+emJ|X0Llx`k$IfT{jm%7X2F)|^a zFM9DpN=D|}#)g8_K!5+6d+X3NNF-A8=G;?A>VH@(w?4bFQ_`n)tfResIK(8?x0|>E zIip!_Z+G|2vU^?r9~W@V&CNlC_ytGM1d;r%g=S{f(O%8z~x0^Zt8pA)RVyXgTF1MVw``+4DDgW)SKJO5M7rZ>h>j w1E)-q-8^}kn?u_wH6M0$OAZBP@7~`9RtDN$u%`t_04N-6oUO~Od?fDv2X)PCfdBvi delta 2699 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 y@{cilh;+@5ih+EM-50xm3~cP;gM}GCPX9nUs Date: Mon, 15 May 2006 10:07:57 -0700 Subject: [PATCH 07/10] pixman: Fix build to enable warnings again --- configure.in | 2 ++ pixman/src/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index bcdb50db9..1335e4ce9 100644 --- a/configure.in +++ b/configure.in @@ -586,6 +586,8 @@ if test "x$GCC" = "xyes"; then -Wnested-externs -fno-strict-aliasing" fi +AC_SUBST(WARN_CFLAGS) + CAIRO_CFLAGS="$CAIRO_CFLAGS $WARN_CFLAGS" CAIRO_LIBS="$CAIRO_LIBS" diff --git a/pixman/src/Makefile.am b/pixman/src/Makefile.am index 376d69654..179c557bc 100644 --- a/pixman/src/Makefile.am +++ b/pixman/src/Makefile.am @@ -36,8 +36,8 @@ noinst_LTLIBRARIES += libpixman-mmx.la libpixman_mmx_la_SOURCES = \ fbmmx.c \ fbmmx.h -libpixman_mmx_la_CFLAGS = @MMX_CFLAGS@ +libpixman_mmx_la_CFLAGS = @MMX_CFLAGS@ $(WARN_CFLAGS) libpixman_la_LIBADD = libpixman-mmx.la endif -INCLUDES = -I$(top_srcdir) -I$(srcdir) $(WARN_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(srcdir) @WARN_CFLAGS@ From 636cbe5a191cf8065facfbe45f32620cea2009a5 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 10:14:39 -0700 Subject: [PATCH 08/10] pixman: Add default case to quiet compiler warning --- pixman/src/fbpict.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c index a09174009..89a2a399d 100644 --- a/pixman/src/fbpict.c +++ b/pixman/src/fbpict.c @@ -1816,6 +1816,9 @@ pixman_composite (pixman_operator_t op, } } break; + default: + /* For any operator not specifically handled above we default out to the general code. */ + func = NULL; } if (!func) { From 621ebc4726c075c183028818af1944f67a60b7ce Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 10:16:06 -0700 Subject: [PATCH 09/10] pixman: Remove unused code to quiet compiler warnings --- pixman/src/fbpict.c | 14 ---------- pixman/src/icimage.c | 66 -------------------------------------------- 2 files changed, 80 deletions(-) diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c index 89a2a399d..bdf6a4cf7 100644 --- a/pixman/src/fbpict.c +++ b/pixman/src/fbpict.c @@ -72,20 +72,6 @@ fbIn (CARD32 x, CARD8 y) return m|n|o|p; } -static CARD32 -fbIn24 (CARD32 x, CARD8 y) -{ - CARD16 a = y; - CARD16 t; - CARD32 m,n,o,p; - - m = FbInU(x,0,a,t); - n = FbInU(x,8,a,t); - o = FbInU(x,16,a,t); - p = (y << 24); - return m|n|o|p; -} - #define genericCombine24(a,b,c,d) (((a)*(c)+(b)*(d))) /* diff --git a/pixman/src/icimage.c b/pixman/src/icimage.c index 90b1bcafa..c166cfbe2 100644 --- a/pixman/src/icimage.c +++ b/pixman/src/icimage.c @@ -154,72 +154,6 @@ pixman_gradient_color (pixman_gradient_stop_t *stop1, next_color, dist)); } -static int -pixman_init_gradient_color_table (pixman_gradient_image_t *gradient, - int tableSize) -{ - int begin_pos, end_pos; - xFixed incr, dpos; - int pos, current_stop; - pixman_gradient_stop_t *stops = gradient->stops; - int nstops = gradient->nstops; - - if (gradient->colorTableSize < tableSize) - { - uint32_t *newColorTable; - - newColorTable = realloc (gradient->colorTable, - tableSize * sizeof (uint32_t)); - if (!newColorTable) - return 1; - - gradient->colorTable = newColorTable; - gradient->colorTableSize = tableSize; - } - - gradient->stopRange = tableSize; - - /* The position where the gradient begins and ends */ - begin_pos = (stops[0].x * gradient->colorTableSize) >> 16; - end_pos = (stops[nstops - 1].x * gradient->colorTableSize) >> 16; - - pos = 0; /* The position in the color table. */ - - /* Up to first point */ - while (pos <= begin_pos) { - gradient->colorTable[pos] = xRenderColorToCard32(stops[0].color); - ++pos; - } - - incr = (1<<16)/ gradient->colorTableSize; /* the double increment. */ - dpos = incr * pos; /* The position in terms of 0-1. */ - - current_stop = 0; /* We always interpolate between current and current + 1. */ - - /* Gradient area */ - while (pos < end_pos) { - gradient->colorTable[pos] = - pixman_gradient_color (&stops[current_stop], - &stops[current_stop + 1], - dpos); - - ++pos; - dpos += incr; - - if (dpos > stops[current_stop + 1].x) - ++current_stop; - } - - /* After last point */ - while (pos < gradient->colorTableSize) { - gradient->colorTable[pos] = - xRenderColorToCard32 (stops[nstops - 1].color); - ++pos; - } - - return 0; -} - static int _pixman_init_gradient (pixman_gradient_image_t *gradient, const pixman_gradient_stop_t *stops, From c7ef4cb3f3b14543842bf538dcb216d1ea51d89f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 15 May 2006 10:25:44 -0700 Subject: [PATCH 10/10] ROADMAP: Note that PDF type 3 font support is done --- ROADMAP | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ROADMAP b/ROADMAP index 9120f7afa..65a45db55 100644 --- a/ROADMAP +++ b/ROADMAP @@ -51,24 +51,26 @@ cairo-1.4 (October 2006): Better performance cairo 1.2.0 essential features We don't expect to release without these being complete. ======================================================== - PDF backend +✓PDF backend ✓1. Mark PDF backend as supported ✓a. Incorporate into test suite ✓b. Correct output for the entire test suite - 2. Reasonable, native output for common uses + ✓2. Reasonable, native output for common uses ✓a. Switch to using cairo_paginated_surface_t ✓b. Opaque text and images are all native ✓c. Translucent objects (using OVER) are also native - d. Text output uses PDF font features + ✓d. Text output uses PDF font features (type 3) + + Bug fixes with API implications + cairo_{ps,pdf}_surface_set_dpi have no effect (replace with cairo_surface_set_fallback_resolution) + cairo_set_line_width should immediately use CTM (see line-width-scale test case) Bug fixes (For each XXXX, see: https://bugs.freedesktop.org/show_bug.cgi?id=XXXX ) 4630 Fonts too large when drawing to image surface while printing 4863 stroking problems with wide dashed lines FC_GLOBAL_ADVANCE (http://lists.freedesktop.org/archives/cairo/2005-August/004893.html) ✓4705 crash at XRenderAddGlyphs - cairo_{ps,pdf}_surface_set_dpi have no effect - cairo_set_line_width should immediately use CTM _transform_glyph_bitmap http://lists.freedesktop.org/archives/cairo/2005-October/005564.html 6759 fontconfig option AntiAlias doesn't work in cairo 1.1.2 SVG/PS/PDF emit_glyph functions need to support bitmapped glyphs