[cairo-commit] 12 commits - src/cairo-ft-font.c src/cairoint.h src/cairo-pdf-operators.c src/cairo-pdf-operators-private.h src/cairo-pdf-surface.c src/cairo-pdf-surface-private.h 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-unicode.c src/cairo-win32-font.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Sun Jun 29 04:55:55 PDT 2008
src/cairo-ft-font.c | 34 +--
src/cairo-pdf-operators-private.h | 16 +
src/cairo-pdf-operators.c | 298 +++++++++++++++++++++++++-------
src/cairo-pdf-surface-private.h | 5
src/cairo-pdf-surface.c | 174 ++++++++++++++----
src/cairo-ps-surface.c | 15 +
src/cairo-scaled-font-subsets-private.h | 36 +++
src/cairo-scaled-font-subsets.c | 148 +++++++++++++--
src/cairo-svg-surface.c | 1
src/cairo-truetype-subset.c | 102 +++++-----
src/cairo-unicode.c | 39 ++++
src/cairo-win32-font.c | 47 ++---
src/cairoint.h | 14 +
13 files changed, 694 insertions(+), 235 deletions(-)
New commits:
commit 22facbe66e5fd72c6c5ce780d3699fe7a63dc7fb
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:55:41 2008 +0930
Add show_text_glyphs to PDF surface
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index 711afb5..a2962f8 100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -90,8 +90,13 @@ typedef struct _cairo_pdf_smask_group
cairo_stroke_style_t *style;
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
+ char *utf8;
+ int utf8_len;
cairo_glyph_t *glyphs;
int num_glyphs;
+ cairo_text_cluster_t *clusters;
+ int num_clusters;
+ cairo_bool_t backward;
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 87edbb1..f2f8453 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -747,8 +747,12 @@ _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
cairo_pattern_destroy (group->source);
if (group->mask)
cairo_pattern_destroy (group->mask);
+ if (group->utf8)
+ free (group->utf8);
if (group->glyphs)
free (group->glyphs);
+ if (group->clusters)
+ free (group->clusters);
if (group->scaled_font)
cairo_scaled_font_destroy (group->scaled_font);
free (group);
@@ -3960,10 +3964,10 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
break;
case PDF_SHOW_GLYPHS:
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
- NULL, 0,
+ group->utf8, group->utf8_len,
group->glyphs, group->num_glyphs,
- NULL, 0,
- FALSE,
+ group->clusters, group->num_clusters,
+ group->backward,
group->scaled_font);
break;
}
@@ -4719,14 +4723,24 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
+static cairo_bool_t
+_cairo_pdf_surface_has_show_text_glyphs (void *abstract_surface)
+{
+ return TRUE;
+}
+
static cairo_int_status_t
-_cairo_pdf_surface_show_glyphs (void *abstract_surface,
- cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- int *remaining_glyphs)
+_cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ const cairo_text_cluster_t *clusters,
+ int num_clusters,
+ cairo_bool_t backward,
+ cairo_scaled_font_t *scaled_font)
{
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
@@ -4754,13 +4768,37 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
group->operation = PDF_SHOW_GLYPHS;
group->source = cairo_pattern_reference (source);
group->source_res = pattern_res;
- group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
- if (group->glyphs == NULL) {
- _cairo_pdf_smask_group_destroy (group);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ if (utf8_len) {
+ group->utf8 = malloc(utf8_len);
+ if (group->utf8) {
+ _cairo_pdf_smask_group_destroy (group);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ memcpy (group->utf8, utf8, utf8_len);
+ }
+ group->utf8_len = utf8_len;
+
+ if (num_glyphs) {
+ group->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+ if (group->glyphs == NULL) {
+ _cairo_pdf_smask_group_destroy (group);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
}
- memcpy (group->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
group->num_glyphs = num_glyphs;
+
+ if (num_clusters) {
+ group->clusters = _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t));
+ if (group->clusters) {
+ _cairo_pdf_smask_group_destroy (group);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ memcpy (group->clusters, clusters, sizeof (cairo_text_cluster_t) * num_clusters);
+ }
+ group->num_clusters = num_clusters;
+
group->scaled_font = cairo_scaled_font_reference (scaled_font);
status = _cairo_pdf_surface_add_smask_group (surface, group);
if (status) {
@@ -4800,10 +4838,10 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
}
status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
- NULL, 0,
+ utf8, utf8_len,
glyphs, num_glyphs,
- NULL, 0,
- FALSE,
+ clusters, num_clusters,
+ backward,
scaled_font);
if (status)
return status;
@@ -4816,6 +4854,26 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
return _cairo_output_stream_get_status (surface->output);
}
+static cairo_int_status_t
+_cairo_pdf_surface_show_glyphs (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ int *remaining_glyphs)
+{
+ return _cairo_pdf_surface_show_text_glyphs (abstract_surface,
+ op,
+ source,
+ NULL, 0,
+ glyphs, num_glyphs,
+ NULL, 0,
+ FALSE,
+ scaled_font);
+}
+
+
static void
_cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
cairo_paginated_mode_t paginated_mode)
@@ -4861,6 +4919,9 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
NULL, /* is_compatible */
NULL, /* reset */
_cairo_pdf_surface_fill_stroke,
+ NULL, /* create_solid_pattern_surface */
+ _cairo_pdf_surface_has_show_text_glyphs,
+ _cairo_pdf_surface_show_text_glyphs,
};
static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
commit 770b7c9a74e3497692020255686c5c5b4e38001e
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:38:13 2008 +0930
Add show_text_glyphs to PDF operators
diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index e29834b..b482335 100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -71,10 +71,12 @@ typedef struct _cairo_pdf_operators {
cairo_bool_t in_text_object; /* inside BT/ET pair */
/* PDF text state */
+ cairo_bool_t is_new_text_object; /* text object started but matrix and font not yet selected */
unsigned int font_id;
unsigned int subset_id;
cairo_matrix_t text_matrix; /* PDF text matrix (Tlm in the PDF reference) */
cairo_matrix_t cairo_to_pdftext; /* translate cairo coords to PDF text space */
+ cairo_matrix_t font_matrix_inverse;
double cur_x; /* Current position in PDF text space (Tm in the PDF reference) */
double cur_y;
int hex_width;
@@ -134,9 +136,15 @@ _cairo_pdf_operators_fill_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_matrix_t *ctm_inverse);
cairo_private cairo_int_status_t
-_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font);
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ const cairo_text_cluster_t *clusters,
+ int num_clusters,
+ cairo_bool_t backward,
+ cairo_scaled_font_t *scaled_font);
+
#endif /* CAIRO_PDF_OPERATORS_H */
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index af8eafe..ad62cfa 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -931,7 +931,6 @@ _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators)
static cairo_status_t
_cairo_pdf_operators_add_glyph (cairo_pdf_operators_t *pdf_operators,
cairo_scaled_font_subsets_glyph_t *glyph,
- cairo_matrix_t *font_matrix_inverse,
double x_position)
{
double x, y;
@@ -939,7 +938,7 @@ _cairo_pdf_operators_add_glyph (cairo_pdf_operators_t *pdf_operators
x = glyph->x_advance;
y = glyph->y_advance;
if (glyph->is_scaled)
- cairo_matrix_transform_distance (font_matrix_inverse, &x, &y);
+ cairo_matrix_transform_distance (&pdf_operators->font_matrix_inverse, &x, &y);
pdf_operators->glyphs[pdf_operators->num_glyphs].x_position = x_position;
pdf_operators->glyphs[pdf_operators->num_glyphs].glyph_index = glyph->subset_glyph_index;
@@ -1073,7 +1072,12 @@ _cairo_pdf_operators_begin_text (cairo_pdf_operators_t *pdf_operators)
static cairo_status_t
_cairo_pdf_operators_end_text (cairo_pdf_operators_t *pdf_operators)
{
- _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ cairo_status_t status;
+
+ status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (pdf_operators->stream, "ET\n");
pdf_operators->in_text_object = FALSE;
@@ -1092,35 +1096,215 @@ _cairo_matrix_scale_equal (cairo_matrix_t *a, cairo_matrix_t *b)
a->yy == b->yy);
}
-cairo_int_status_t
-_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font)
+static cairo_status_t
+_cairo_pdf_operators_begin_actualtext (cairo_pdf_operators_t *pdf_operators,
+ const char *utf8,
+ int utf8_len)
{
- cairo_scaled_font_subsets_glyph_t subset_glyph;
+ uint16_t *utf16;
+ int utf16_len;
cairo_status_t status;
int i;
- cairo_matrix_t text_matrix, invert_y_axis, font_matrix_inverse;
+
+ _cairo_output_stream_printf (pdf_operators->stream, "/Span << /ActualText <feff");
+ if (utf8_len) {
+ status = _cairo_utf8_to_utf16 (utf8, utf8_len, &utf16, &utf16_len);
+ if (status)
+ return status;
+
+ for (i = 0; i < utf16_len; i++) {
+ _cairo_output_stream_printf (pdf_operators->stream,
+ "%04x", (int) (utf16[i]));
+ }
+ free (utf16);
+ }
+ _cairo_output_stream_printf (pdf_operators->stream, "> >> BDC\n");
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_end_actualtext (cairo_pdf_operators_t *pdf_operators)
+{
+ _cairo_output_stream_printf (pdf_operators->stream, "EMC\n");
+
+ return _cairo_output_stream_get_status (pdf_operators->stream);
+}
+
+static cairo_status_t
+_cairo_pdf_operators_emit_glyph (cairo_pdf_operators_t *pdf_operators,
+ cairo_glyph_t *glyph,
+ cairo_scaled_font_subsets_glyph_t *subset_glyph)
+{
double x, y;
- cairo_bool_t new_text_object = FALSE;
+ cairo_status_t status;
- if (num_glyphs <= 0)
- return CAIRO_STATUS_SUCCESS;
+ if (pdf_operators->is_new_text_object ||
+ pdf_operators->font_id != subset_glyph->font_id ||
+ pdf_operators->subset_id != subset_glyph->subset_id)
+ {
+ status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_operators_set_font_subset (pdf_operators, subset_glyph);
+ if (status)
+ return status;
+
+ pdf_operators->is_new_text_object = FALSE;
+ }
+
+ x = glyph->x;
+ y = glyph->y;
+ cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
+
+ /* The TJ operator for displaying text strings can only set
+ * the horizontal position of the glyphs. If the y position
+ * (in text space) changes, use the Td operator to change the
+ * current position to the next glyph. We also use the Td
+ * operator to move the current position if the horizontal
+ * position changes by more than 10 (in text space
+ * units). This is becauses the horizontal glyph positioning
+ * in the TJ operator is intended for kerning and there may be
+ * PDF consumers that do not handle very large position
+ * adjustments in TJ.
+ */
+ if (fabs(x - pdf_operators->cur_x) > 10 ||
+ fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
+ {
+ status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ if (status)
+ return status;
+
+ x = glyph->x;
+ y = glyph->y;
+ cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
+ status = _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
+ if (status)
+ return status;
- font_matrix_inverse = scaled_font->font_matrix;
- status = cairo_matrix_invert (&font_matrix_inverse);
+ x = 0.0;
+ y = 0.0;
+ }
+
+ status = _cairo_pdf_operators_add_glyph (pdf_operators,
+ subset_glyph,
+ x);
+ return status;
+}
+
+/* A utf8_len of -1 indicates no unicode text. A utf8_len = 0 is an
+ * empty string.
+ */
+static cairo_int_status_t
+_cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_bool_t backward,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_scaled_font_subsets_glyph_t subset_glyph;
+ cairo_glyph_t *cur_glyph;
+ cairo_status_t status;
+ int i;
+
+ /* If the cluster maps 1 glyph to 1 or more unicode characters, we
+ * first try _map_glyph() with the unicode string to see if it can
+ * use toUnicode to map our glyph to the unicode. This will fail
+ * if the glyph is already mapped to a different unicode string.
+ *
+ * We also go through this path if no unicode mapping was
+ * supplied (utf8_len < 0).
+ *
+ * Mapping a glyph to a zero length unicode string requires the
+ * use of ActualText.
+ */
+ if (num_glyphs == 1 && utf8_len != 0) {
+ status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+ scaled_font,
+ glyphs->index,
+ utf8,
+ utf8_len < 0 ? 0 : utf8_len,
+ &subset_glyph);
+ if (status)
+ return status;
+
+ if (subset_glyph.utf8_is_mapped || utf8_len < 0) {
+ status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+ glyphs,
+ &subset_glyph);
+ return 0;
+ }
+ }
+
+ /* Fallback to using ActualText to map zero or more glyphs to a
+ * unicode string. */
+ _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ status = _cairo_pdf_operators_begin_actualtext (pdf_operators, utf8, utf8_len);
+ cur_glyph = glyphs;
+ for (i = 0; i < num_glyphs; i++) {
+ status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
+ scaled_font,
+ cur_glyph->index,
+ NULL, 0,
+ &subset_glyph);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_operators_emit_glyph (pdf_operators,
+ cur_glyph,
+ &subset_glyph);
+ if (status)
+ return status;
+
+ if (backward)
+ cur_glyph--;
+ else
+ cur_glyph++;
+ }
+ status = _cairo_pdf_operators_flush_glyphs (pdf_operators);
+ if (status)
+ return status;
+
+ status = _cairo_pdf_operators_end_actualtext (pdf_operators);
+
+ return status;
+}
+
+cairo_int_status_t
+_cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators,
+ const char *utf8,
+ int utf8_len,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ const cairo_text_cluster_t *clusters,
+ int num_clusters,
+ cairo_bool_t backward,
+ cairo_scaled_font_t *scaled_font)
+{
+ cairo_status_t status;
+ int i;
+ cairo_matrix_t text_matrix, invert_y_axis;
+ double x, y;
+ const char *cur_text;
+ cairo_glyph_t *cur_glyph;
+
+ pdf_operators->font_matrix_inverse = scaled_font->font_matrix;
+ status = cairo_matrix_invert (&pdf_operators->font_matrix_inverse);
if (status == CAIRO_STATUS_INVALID_MATRIX)
return CAIRO_STATUS_SUCCESS;
if (status)
return status;
+ pdf_operators->is_new_text_object = FALSE;
if (pdf_operators->in_text_object == FALSE) {
_cairo_pdf_operators_begin_text (pdf_operators);
/* Force Tm and Tf to be emitted when starting a new text
* object.*/
- new_text_object = TRUE;
+ pdf_operators->is_new_text_object = TRUE;
}
cairo_matrix_init_scale (&invert_y_axis, 1, -1);
@@ -1132,7 +1316,7 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
/* Invert y axis in device space */
cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix);
- if (new_text_object ||
+ if (pdf_operators->is_new_text_object ||
! _cairo_matrix_scale_equal (&pdf_operators->text_matrix, &text_matrix))
{
_cairo_pdf_operators_flush_glyphs (pdf_operators);
@@ -1148,55 +1332,36 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
return status;
}
- for (i = 0; i < num_glyphs; i++) {
- status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
- scaled_font, glyphs[i].index,
- NULL, 0,
- &subset_glyph);
- if (status)
- return status;
-
- if (new_text_object ||
- pdf_operators->font_id != subset_glyph.font_id ||
- pdf_operators->subset_id != subset_glyph.subset_id)
- {
- _cairo_pdf_operators_flush_glyphs (pdf_operators);
- _cairo_pdf_operators_set_font_subset (pdf_operators, &subset_glyph);
- new_text_object = FALSE;
+ if (num_clusters > 0) {
+ cur_text = utf8;
+ if (backward)
+ cur_glyph = glyphs + num_glyphs - 1;
+ else
+ cur_glyph = glyphs;
+ for (i = 0; i < num_clusters; i++) {
+ status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+ cur_text,
+ clusters[i].num_bytes,
+ cur_glyph,
+ clusters[i].num_glyphs,
+ backward,
+ scaled_font);
+ cur_text += clusters[i].num_bytes;
+ if (backward)
+ cur_glyph -= clusters[i].num_glyphs;
+ else
+ cur_glyph += clusters[i].num_glyphs;
}
-
- x = glyphs[i].x;
- y = glyphs[i].y;
- cairo_matrix_transform_point (&pdf_operators->cairo_to_pdftext, &x, &y);
-
- /* The TJ operator for displaying text strings can only set
- * the horizontal position of the glyphs. If the y position
- * (in text space) changes, use the Td operator to change the
- * current position to the next glyph. We also use the Td
- * operator to move the current position if the horizontal
- * position changes by more than 10 (in text space
- * units). This is becauses the horizontal glyph positioning
- * in the TJ operator is intended for kerning and there may be
- * PDF consumers that do not handle very large position
- * adjustments in TJ.
- */
- if (fabs(x - pdf_operators->cur_x) > 10 ||
- fabs(y - pdf_operators->cur_y) > GLYPH_POSITION_TOLERANCE)
- {
- _cairo_pdf_operators_flush_glyphs (pdf_operators);
-
- x = glyphs[i].x;
- y = glyphs[i].y;
- cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &x, &y);
- _cairo_pdf_operators_set_text_position (pdf_operators, x, y);
- x = 0.0;
- y = 0.0;
+ } else {
+ for (i = 0; i < num_glyphs; i++) {
+ status = _cairo_pdf_operators_emit_cluster (pdf_operators,
+ NULL,
+ -1, /* no unicode string available */
+ &glyphs[i],
+ 1,
+ FALSE,
+ scaled_font);
}
-
- _cairo_pdf_operators_add_glyph (pdf_operators,
- &subset_glyph,
- &font_matrix_inverse,
- x);
}
return _cairo_output_stream_get_status (pdf_operators->stream);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index faef964..87edbb1 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3959,10 +3959,12 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
&group->ctm_inverse);
break;
case PDF_SHOW_GLYPHS:
- status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
- group->glyphs,
- group->num_glyphs,
- group->scaled_font);
+ status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+ NULL, 0,
+ group->glyphs, group->num_glyphs,
+ NULL, 0,
+ FALSE,
+ group->scaled_font);
break;
}
if (status)
@@ -4797,10 +4799,12 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
return status;
}
- status = _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
- glyphs,
- num_glyphs,
- scaled_font);
+ status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+ NULL, 0,
+ glyphs, num_glyphs,
+ NULL, 0,
+ FALSE,
+ scaled_font);
if (status)
return status;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a4266d2..3261247 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -175,6 +175,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/W* { eoclip } bind def\n"
"/BT { } bind def\n"
"/ET { } bind def\n"
+ "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n"
+ " { globaldict begin /?pdfmark /pop load def /pdfmark\n"
+ " /cleartomark load def end } ifelse\n"
+ "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n"
+ "/EMC { mark /EMC pdfmark } bind def\n"
"/Tj { show } bind def\n"
"/TJ {\n"
" {\n"
@@ -3091,10 +3096,12 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
if (status)
return status;
- return _cairo_pdf_operators_show_glyphs (&surface->pdf_operators,
- glyphs,
- num_glyphs,
- scaled_font);
+ return _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
+ NULL, 0,
+ glyphs, num_glyphs,
+ NULL, 0,
+ FALSE,
+ scaled_font);
}
static void
commit 55dda8c64fc38cda75878f1a34eb1f86b1a445cb
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:36:29 2008 +0930
Remove unused map_glyphs_to_unicode functions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 9c18949..4620653 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2176,40 +2176,6 @@ _cairo_ft_load_truetype_table (void *abstract_font,
}
static cairo_int_status_t
-_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
- cairo_scaled_font_subset_t *font_subset)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
- FT_Face face;
- FT_UInt glyph;
- unsigned long charcode;
- unsigned int i;
- int count;
-
- face = _cairo_ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- count = font_subset->num_glyphs;
- charcode = FT_Get_First_Char( face, &glyph);
- while (glyph != 0 && count > 0)
- {
- for (i = 0; i < font_subset->num_glyphs; i++) {
- if (font_subset->glyphs[i] == glyph) {
- font_subset->to_unicode[i] = charcode;
- count--;
- break;
- }
- }
- charcode = FT_Get_Next_Char (face, charcode, &glyph);
- }
- _cairo_ft_unscaled_font_unlock_face (unscaled);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
_cairo_ft_index_to_ucs4(void *abstract_font,
unsigned long index,
uint32_t *ucs4)
@@ -2248,7 +2214,6 @@ const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
_cairo_ft_ucs4_to_index,
NULL, /* show_glyphs */
_cairo_ft_load_truetype_table,
- _cairo_ft_map_glyphs_to_unicode,
_cairo_ft_index_to_ucs4
};
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 7b84334..5c68f07 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1457,101 +1457,6 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
return status;
}
-static cairo_int_status_t
-_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
- cairo_scaled_font_subset_t *font_subset)
-{
- cairo_win32_scaled_font_t *scaled_font = abstract_font;
- GLYPHSET *glyph_set;
- uint16_t *utf16 = NULL;
- WORD *glyph_indices = NULL;
- HDC hdc = NULL;
- int res;
- unsigned int i, j, k, count, num_glyphs;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- hdc = _get_global_font_dc ();
- if (!hdc)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
- if (status)
- return status;
-
- res = GetFontUnicodeRanges(hdc, NULL);
- if (res == 0) {
- status = _cairo_win32_print_gdi_error (
- "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
- goto fail1;
- }
-
- glyph_set = malloc (res);
- if (glyph_set == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail1;
- }
-
- res = GetFontUnicodeRanges(hdc, glyph_set);
- if (res == 0) {
- status = _cairo_win32_print_gdi_error (
- "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
- goto fail2;
- }
-
- count = font_subset->num_glyphs;
- for (i = 0; i < glyph_set->cRanges && count > 0; i++) {
- num_glyphs = glyph_set->ranges[i].cGlyphs;
-
- utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
- if (utf16 == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail2;
- }
-
- glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
- if (glyph_indices == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail2;
- }
-
- for (j = 0; j < num_glyphs; j++)
- utf16[j] = glyph_set->ranges[i].wcLow + j;
- utf16[j] = 0;
-
- if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
- status = _cairo_win32_print_gdi_error (
- "_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW");
- goto fail2;
- }
-
- for (j = 0; j < num_glyphs; j++) {
- for (k = 0; k < font_subset->num_glyphs; k++) {
- if (font_subset->glyphs[k] == glyph_indices[j]) {
- font_subset->to_unicode[k] = utf16[j];
- count--;
- break;
- }
- }
- }
-
- free (glyph_indices);
- glyph_indices = NULL;
- free (utf16);
- utf16= NULL;
- }
-
-fail2:
- if (glyph_indices)
- free (glyph_indices);
- if (utf16)
- free (utf16);
- free (glyph_set);
-fail1:
- cairo_win32_scaled_font_done_font (&scaled_font->base);
-
- return status;
-}
-
static cairo_status_t
_cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
unsigned long index,
@@ -1879,7 +1784,6 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
NULL, /* ucs4_to_index */
_cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_load_truetype_table,
- _cairo_win32_scaled_font_map_glyphs_to_unicode,
_cairo_win32_scaled_font_index_to_ucs4,
};
diff --git a/src/cairoint.h b/src/cairoint.h
index 12ccd7f..bd33c44 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -440,10 +440,6 @@ struct _cairo_scaled_font_backend {
unsigned char *buffer,
unsigned long *length);
- cairo_warn cairo_int_status_t
- (*map_glyphs_to_unicode)(void *scaled_font,
- cairo_scaled_font_subset_t *font_subset);
-
/* returns -1 if the unicode character could not be found for the glyph */
cairo_warn cairo_int_status_t
(*index_to_ucs4)(void *scaled_font,
commit 2012d4f7364f9efa0789996e7906f269d5d59d41
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:36:10 2008 +0930
Removed unused cairo_truetype_create_glyph_to_unicode_map()
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 5e4210e..53d7232 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1173,153 +1173,6 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
}
static cairo_int_status_t
-_cairo_truetype_map_glyphs_to_unicode (cairo_scaled_font_subset_t *font_subset,
- unsigned long table_offset)
-{
- cairo_status_t status;
- const cairo_scaled_font_backend_t *backend;
- tt_segment_map_t *map;
- char buf[4];
- unsigned int num_segments, i, j;
- unsigned long size;
- uint16_t *start_code;
- uint16_t *end_code;
- uint16_t *delta;
- uint16_t *range_offset;
- uint16_t *glyph_array;
- uint16_t g_id, c;
-
- backend = font_subset->scaled_font->backend;
- size = 4;
- status = backend->load_truetype_table (font_subset->scaled_font,
- TT_TAG_cmap, table_offset,
- (unsigned char *) &buf,
- &size);
- if (status)
- return status;
-
- /* All table formats have the same first two words */
- map = (tt_segment_map_t *) buf;
- if (be16_to_cpu (map->format) != 4)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- size = be16_to_cpu (map->length);
- map = malloc (size);
- if (map == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = backend->load_truetype_table (font_subset->scaled_font,
- TT_TAG_cmap, table_offset,
- (unsigned char *) map,
- &size);
- if (status)
- goto fail;
-
- num_segments = be16_to_cpu (map->segCountX2)/2;
- end_code = map->endCount;
- start_code = &(end_code[num_segments + 1]);
- delta = &(start_code[num_segments]);
- range_offset = &(delta[num_segments]);
- glyph_array = &(range_offset[num_segments]);
-
- i = 0;
- while (i < font_subset->num_glyphs) {
- g_id = (uint16_t) font_subset->glyphs[i];
-
- /* search for glyph in segments
- * with rangeOffset=0 */
- for (j = 0; j < num_segments; j++) {
- c = g_id - be16_to_cpu (delta[j]);
- if (range_offset[j] == 0 &&
- c >= be16_to_cpu (start_code[j]) &&
- c <= be16_to_cpu (end_code[j]))
- {
- font_subset->to_unicode[i] = c;
- goto next_glyph;
- }
- }
-
- /* search for glyph in segments with rangeOffset=1 */
- for (j = 0; j < num_segments; j++) {
- if (range_offset[j] != 0) {
- uint16_t *glyph_ids = &range_offset[j] + be16_to_cpu (range_offset[j])/2;
- int range_size = be16_to_cpu (end_code[j]) - be16_to_cpu (start_code[j]) + 1;
- uint16_t g_id_be = cpu_to_be16 (g_id);
- int k;
-
- for (k = 0; k < range_size; k++) {
- if (glyph_ids[k] == g_id_be) {
- font_subset->to_unicode[i] = be16_to_cpu (start_code[j]) + k;
- goto next_glyph;
- }
- }
- }
- }
-
- next_glyph:
- i++;
- }
- status = CAIRO_STATUS_SUCCESS;
-fail:
- free (map);
-
- return status;
-}
-
-cairo_int_status_t
-_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset)
-{
- cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
- const cairo_scaled_font_backend_t *backend;
- tt_cmap_t *cmap;
- char buf[4];
- int num_tables, i;
- unsigned long size;
-
- backend = font_subset->scaled_font->backend;
- if (!backend->load_truetype_table)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- size = 4;
- status = backend->load_truetype_table (font_subset->scaled_font,
- TT_TAG_cmap, 0,
- (unsigned char *) &buf,
- &size);
- if (status)
- return status;
-
- cmap = (tt_cmap_t *) buf;
- num_tables = be16_to_cpu (cmap->num_tables);
- size = 4 + num_tables*sizeof(tt_cmap_index_t);
- cmap = malloc (size);
- if (cmap == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = backend->load_truetype_table (font_subset->scaled_font,
- TT_TAG_cmap, 0,
- (unsigned char *) cmap,
- &size);
- if (status)
- goto cleanup;
-
- /* Find a table with Unicode mapping */
- for (i = 0; i < num_tables; i++) {
- if (be16_to_cpu (cmap->index[i].platform) == 3 &&
- be16_to_cpu (cmap->index[i].encoding) == 1) {
- status = _cairo_truetype_map_glyphs_to_unicode (font_subset,
- be32_to_cpu (cmap->index[i].offset));
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto cleanup;
- }
- }
-
-cleanup:
- free (cmap);
-
- return status;
-}
-
-static cairo_int_status_t
_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
unsigned long table_offset,
unsigned long index,
commit 154324f121e7aad8af474ac26e0e320cddd37579
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:35:43 2008 +0930
Use subset utf8 mapping to create the glyph names for PS fonts
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index e04e944..7be7181 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -893,29 +893,14 @@ create_string_entry (char *s, cairo_string_entry_t **entry)
cairo_int_status_t
_cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset)
{
- const cairo_scaled_font_backend_t *backend;
unsigned int i;
cairo_status_t status;
cairo_hash_table_t *names;
cairo_string_entry_t key, *entry;
char buf[30];
-
- if (subset->to_unicode == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- status = _cairo_truetype_create_glyph_to_unicode_map (subset);
- if (status) {
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- backend = subset->scaled_font->backend;
- if (backend->map_glyphs_to_unicode == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- status = backend->map_glyphs_to_unicode (subset->scaled_font, subset);
- if (status)
- return status;
- }
+ char *utf8;
+ uint16_t *utf16;
+ int utf16_len;
names = _cairo_hash_table_create (_cairo_string_equal);
if (names == NULL)
@@ -944,8 +929,17 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
}
for (i = 1; i < subset->num_glyphs; i++) {
- if (subset->to_unicode[i] <= 0xffff) {
- snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i]));
+ utf8 = subset->utf8[i];
+ utf16 = NULL;
+ utf16_len = 0;
+ if (utf8 && *utf8) {
+ status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
+ if (status && status != CAIRO_STATUS_INVALID_STRING)
+ return status; // FIXME
+ }
+
+ if (utf16_len == 1) {
+ snprintf (buf, sizeof(buf), "uni%04X", (int)(utf16[0]));
_cairo_string_init_key (&key, buf);
if (_cairo_hash_table_lookup (names, &key.base,
(cairo_hash_entry_t **) &entry)) {
@@ -954,6 +948,8 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
} else {
snprintf (buf, sizeof(buf), "g%d", i);
}
+ if (utf16)
+ free (utf16);
subset->glyph_names[i] = strdup (buf);
if (subset->glyph_names[i] == NULL) {
commit 2a21fafa078a2519dea7881b4553d74667c928f2
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:35:12 2008 +0930
Use subset utf8 mapping in PDF ToUnicode stream
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1c74376..faef964 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2839,34 +2839,54 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
"endobj\n");
}
+static cairo_status_t
+_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
+ const char *utf8)
+{
+ uint16_t *utf16 = NULL;
+ int utf16_len = 0;
+ cairo_status_t status;
+ int i;
+
+ if (utf8 && *utf8) {
+ status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &utf16_len);
+ if (status && status != CAIRO_STATUS_INVALID_STRING)
+ return status;
+ }
+
+ _cairo_output_stream_printf (surface->output, "<");
+ if (utf16 == NULL || utf16_len == 0) {
+ /* According to the "ToUnicode Mapping File Tutorial"
+ * http://www.adobe.com/devnet/acrobat/pdfs/5411.ToUnicode.pdf
+ *
+ * Glyphs that do not map to a Unicode code point must be
+ * mapped to 0xfffd "REPLACEMENT CHARACTER".
+ */
+ _cairo_output_stream_printf (surface->output,
+ "fffd");
+ } else {
+ for (i = 0; i < utf16_len; i++)
+ _cairo_output_stream_printf (surface->output,
+ "%04x", (int) (utf16[i]));
+ }
+ _cairo_output_stream_printf (surface->output, ">");
+
+ if (utf16)
+ free (utf16);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static cairo_int_status_t
_cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_bool_t is_composite,
cairo_pdf_resource_t *stream)
{
- const cairo_scaled_font_backend_t *backend;
unsigned int i, num_bfchar;
cairo_int_status_t status;
stream->id = 0;
- if (font_subset->to_unicode == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- status = _cairo_truetype_create_glyph_to_unicode_map (font_subset);
- if (status) {
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- backend = font_subset->scaled_font->backend;
- if (backend->map_glyphs_to_unicode == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- status = backend->map_glyphs_to_unicode (font_subset->scaled_font,
- font_subset);
- if (status)
- return status;
- }
status = _cairo_pdf_surface_open_stream (surface,
NULL,
@@ -2900,10 +2920,12 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
"endcodespacerange\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\n",
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,
@@ -2913,13 +2935,16 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
}
if (is_composite) {
_cairo_output_stream_printf (surface->output,
- "<%04x> <%04lx>\n",
- i + 1, font_subset->to_unicode[i + 1]);
+ "<%04x> ",
+ i + 1);
} else {
_cairo_output_stream_printf (surface->output,
- "<%02x> <%04lx>\n",
- i + 1, font_subset->to_unicode[i + 1]);
+ "<%02x> ",
+ i + 1);
}
+ _cairo_pdf_surface_emit_unicode_for_glyph (surface, font_subset->utf8[i + 1]);
+ _cairo_output_stream_printf (surface->output,
+ "\n");
}
_cairo_output_stream_printf (surface->output,
"endbfchar\n");
diff --git a/src/cairoint.h b/src/cairoint.h
index 1aa943e..12ccd7f 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2343,7 +2343,7 @@ cairo_private int
_cairo_ucs4_to_utf8 (uint32_t unicode,
char *utf8);
-#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0
+#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0 || CAIRO_HAS_PDF_SURFACE+0
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
#if CAIRO_HAS_UTF8_TO_UTF16
commit d77b04fd0635c1648bb024b5308b715c220e1e74
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:33:58 2008 +0930
Allow _cairo_scaled_font_subsets_map_glyph() to specify utf8 mapping
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 81c99e9..af8eafe 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -1151,6 +1151,7 @@ _cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
scaled_font, glyphs[i].index,
+ NULL, 0,
&subset_glyph);
if (status)
return status;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index c621235..1de3f86 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -47,6 +47,8 @@ typedef struct _cairo_scaled_font_subsets_glyph {
cairo_bool_t is_composite;
double x_advance;
double y_advance;
+ cairo_bool_t utf8_is_mapped;
+ uint32_t unicode;
} cairo_scaled_font_subsets_glyph_t;
/**
@@ -176,8 +178,14 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
* subset is created for each font scale used. If false, the outline of the mapped glyph
* is available. One font subset for each font face is created.
- * @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space.
- * When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font.
+ * @x_advance, @y_advance: When @is_scaled is true, @x_advance and @y_advance contain
+ * the x and y advance for the mapped glyph in device space.
+ * When @is_scaled is false, @x_advance and @y_advance contain the x and y advance for
+ * the the mapped glyph from an unhinted 1 point font.
+ * @utf8_is_mapped: If true the utf8 string provided to _cairo_scaled_font_subsets_map_glyph()
+ * is (or already was) the utf8 string mapped to this glyph. If false the glyph is already
+ * mapped to a different utf8 string.
+ * @unicode: the unicode character mapped to this glyph by the font backend.
*
* Return value: %CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
@@ -187,6 +195,8 @@ cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
+ const char * utf8,
+ int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
typedef cairo_status_t
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index f70d978..e04e944 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -94,10 +94,16 @@ typedef struct _cairo_sub_font_glyph {
unsigned int subset_glyph_index;
double x_advance;
double y_advance;
+
+ cairo_bool_t is_mapped;
+ uint32_t unicode;
+ char *utf8;
+ int utf8_len;
} cairo_sub_font_glyph_t;
typedef struct _cairo_sub_font_collection {
unsigned long *glyphs; /* scaled_font_glyph_index */
+ char **utf8;
unsigned int glyphs_size;
unsigned int max_glyph;
unsigned int num_glyphs;
@@ -117,6 +123,8 @@ typedef struct _cairo_string_entry {
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
+ const char * utf8,
+ int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph);
static void
@@ -155,6 +163,10 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
sub_font_glyph->subset_glyph_index = subset_glyph_index;
sub_font_glyph->x_advance = x_advance;
sub_font_glyph->y_advance = y_advance;
+ sub_font_glyph->is_mapped = FALSE;
+ sub_font_glyph->unicode = -1;
+ sub_font_glyph->utf8 = NULL;
+ sub_font_glyph->utf8_len = 0;
return sub_font_glyph;
}
@@ -193,6 +205,7 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
assert (subset_glyph_index < collection->glyphs_size);
collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
+ collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
if (subset_glyph_index > collection->max_glyph)
collection->max_glyph = subset_glyph_index;
@@ -264,7 +277,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
sub_font->next = NULL;
/* Reserve first glyph in subset for the .notdef glyph */
- status = _cairo_sub_font_map_glyph (sub_font, 0, &subset_glyph);
+ status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &subset_glyph);
if (status) {
_cairo_hash_table_destroy (sub_font->sub_font_glyphs);
free (sub_font);
@@ -296,9 +309,86 @@ _cairo_sub_font_pluck (void *entry, void *closure)
_cairo_sub_font_destroy (sub_font);
}
+static cairo_status_t
+_cairo_sub_font_glyph_lookup_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
+ cairo_scaled_font_t *scaled_font,
+ unsigned long scaled_font_glyph_index)
+{
+ uint32_t unicode;
+ char buf[8];
+ int len;
+ cairo_status_t status;
+
+ /* Do a reverse lookup on the glyph index. unicode is -1 if the
+ * index could not be mapped to a unicode character. */
+ status = _cairo_truetype_index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+ if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ unicode = -1;
+
+ if (unicode == (uint32_t)-1 && scaled_font->backend->index_to_ucs4)
+ status = scaled_font->backend->index_to_ucs4 (scaled_font, scaled_font_glyph_index, &unicode);
+
+ sub_font_glyph->unicode = unicode;
+ sub_font_glyph->utf8 = NULL;
+ sub_font_glyph->utf8_len = 0;
+ if (unicode != (uint32_t)-1) {
+ len = _cairo_ucs4_to_utf8 (unicode, buf);
+ if (len > 0) {
+ sub_font_glyph->utf8 = malloc(len + 1);
+ memcpy (sub_font_glyph->utf8, buf, len);
+ sub_font_glyph->utf8[len] = 0;
+ sub_font_glyph->utf8_len = len;
+ }
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph,
+ const char *utf8,
+ int utf8_len)
+{
+ int add_zero_byte = 0;
+
+ if (utf8 != NULL && utf8_len != 0) {
+ if (sub_font_glyph->utf8 != NULL) {
+ if (utf8_len == sub_font_glyph->utf8_len &&
+ memcmp (utf8, sub_font_glyph->utf8, utf8_len) == 0)
+ {
+ /* Requested utf8 mapping matches the existing mapping */
+ return TRUE;
+ }
+ else
+ {
+ /* Requested utf8 mapping does not match the existing mapping */
+ return FALSE;
+ }
+ } else {
+ /* No existing mapping. Use the requested mapping */
+ if (sub_font_glyph->utf8[utf8_len - 1] != 0)
+ add_zero_byte = 1;
+ sub_font_glyph->utf8 = malloc (utf8_len + add_zero_byte);
+ memcpy (sub_font_glyph->utf8, utf8, utf8_len);
+ if (add_zero_byte)
+ sub_font_glyph->utf8[utf8_len] = 0;
+ sub_font_glyph->utf8_len = utf8_len;
+ return TRUE;
+ }
+ }
+
+ /* No mapping was requested. */
+ return FALSE;
+}
+
static cairo_bool_t
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
+ const char * utf8,
+ int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -314,8 +404,10 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
subset_glyph->y_advance = sub_font_glyph->y_advance;
+ subset_glyph->utf8_is_mapped = _cairo_sub_font_glyph_map_to_unicode (sub_font_glyph, utf8, utf8_len);
+ subset_glyph->unicode = sub_font_glyph->unicode;
- return TRUE;
+ return TRUE;
}
return FALSE;
@@ -324,6 +416,8 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
+ const char * utf8,
+ int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@@ -341,7 +435,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
sub_font->num_glyphs_in_current_subset = 0;
/* Reserve first glyph in subset for the .notdef glyph */
- status = _cairo_sub_font_map_glyph (sub_font, 0, &tmp_subset_glyph);
+ status = _cairo_sub_font_map_glyph (sub_font, 0, NULL, 0, &tmp_subset_glyph);
if (status)
return status;
}
@@ -362,6 +456,10 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
if (sub_font_glyph == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_sub_font_glyph_lookup_unicode (sub_font_glyph,
+ sub_font->scaled_font,
+ scaled_font_glyph_index);
+
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
if (status) {
_cairo_sub_font_glyph_destroy (sub_font_glyph);
@@ -425,6 +523,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
subset.font_id = sub_font->font_id;
subset.subset_id = i;
subset.glyphs = collection->glyphs;
+ subset.utf8 = collection->utf8;
subset.num_glyphs = collection->num_glyphs;
subset.glyph_names = NULL;
/* No need to check for out of memory here. If to_unicode is NULL, the PDF
@@ -523,6 +622,8 @@ cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
+ const char * utf8,
+ int utf8_len,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_t key, *sub_font;
@@ -544,6 +645,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
{
if (_cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
+ utf8, utf8_len,
subset_glyph))
return CAIRO_STATUS_SUCCESS;
}
@@ -557,6 +659,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
{
if (_cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
+ utf8, utf8_len,
subset_glyph))
return CAIRO_STATUS_SUCCESS;
}
@@ -684,6 +787,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
+ utf8, utf8_len,
subset_glyph);
}
@@ -705,6 +809,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
return CAIRO_STATUS_SUCCESS;
collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
+ collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
if (collection.glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -721,6 +826,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
_cairo_sub_font_collect (sub_font, &collection);
sub_font = sub_font->next;
}
+ free (collection.utf8);
free (collection.glyphs);
return collection.status;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 93e82bc..0b0165e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2177,6 +2177,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
scaled_font, glyphs[i].index,
+ NULL, 0,
&subset_glyph);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
_cairo_output_stream_printf (surface->xml_node, "</g>\n");
diff --git a/src/cairoint.h b/src/cairoint.h
index a99c26c..1aa943e 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -379,6 +379,7 @@ typedef struct _cairo_scaled_font_subset {
*/
unsigned long *glyphs;
unsigned long *to_unicode;
+ char **utf8;
char **glyph_names;
unsigned int num_glyphs;
cairo_bool_t is_composite;
commit f4d6e714a63ab44e388a06fba8d849f2ad7f0000
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:32:19 2008 +0930
Add _cairo_ucs4_to_utf8
diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c
index c4873d5..973ef57 100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
@@ -262,6 +262,45 @@ _cairo_utf8_to_ucs4 (const char *str,
return CAIRO_STATUS_SUCCESS;
}
+/**
+ * _cairo_ucs4_to_utf8:
+ * @unicode: a UCS-4 character
+ * @utf8: buffer to write utf8 string into. Must have at least 4 bytes
+ * space available.
+ *
+ * Return value: Number of bytes in the utf8 string or 0 if an invalid
+ * unicode character
+ **/
+int
+_cairo_ucs4_to_utf8 (uint32_t unicode,
+ char *utf8)
+{
+ int bytes;
+ char *p;
+
+ if (unicode < 0x80) {
+ *utf8 = unicode;
+ return 1;
+ } else if (unicode < 0x800) {
+ bytes = 2;
+ } else if (unicode < 0x10000) {
+ bytes = 3;
+ } else if (unicode < 0x200000) {
+ bytes = 4;
+ } else {
+ return 0;
+ }
+
+ p = utf8 + bytes;
+ while (p > utf8) {
+ *--p = 0x80 | (unicode & 0x3f);
+ unicode >>= 6;
+ }
+ *p |= 0xf0 << (4 - bytes);
+
+ return bytes;
+}
+
#if CAIRO_HAS_UTF8_TO_UTF16
/**
* _cairo_utf8_to_utf16:
diff --git a/src/cairoint.h b/src/cairoint.h
index d5404f9..a99c26c 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2338,6 +2338,10 @@ _cairo_utf8_to_ucs4 (const char *str,
uint32_t **result,
int *items_written);
+cairo_private int
+_cairo_ucs4_to_utf8 (uint32_t unicode,
+ char *utf8);
+
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_QUARTZ_FONT+0
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
commit 2f99a294cd2367c4649428534b3429522448260c
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:31:47 2008 +0930
Add _cairo_truetype_index_to_ucs4()
for doing reverse cmap lookups on truetype/opentype fonts one glyph at
a time.
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index da64f7f..c621235 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -554,4 +554,26 @@ _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
cairo_private cairo_int_status_t
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset);
+/**
+ * _cairo_truetype_index_to_ucs4:
+ * @scaled_font: the #cairo_scaled_font_t
+ * @index: the glyph index
+ * @ucs4: return value for the unicode value of the glyph
+ *
+ * If possible (depending on the format of the underlying
+ * #cairo_scaled_font_t and the font backend in use) assign
+ * the unicode character of the glyph to @ucs4.
+ *
+ * If mapping glyph indices to unicode is supported but the unicode
+ * value of the specified glyph is not available, @ucs4 is set to -1.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if successful,
+ * %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode
+ * is not supported. Possible errors include %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_int_status_t
+_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
+ unsigned long index,
+ uint32_t *ucs4);
+
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index c3f0b05..5e4210e 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1318,3 +1318,154 @@ cleanup:
return status;
}
+
+static cairo_int_status_t
+_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
+ unsigned long table_offset,
+ unsigned long index,
+ uint32_t *ucs4)
+{
+ cairo_status_t status;
+ const cairo_scaled_font_backend_t *backend;
+ tt_segment_map_t *map;
+ char buf[4];
+ unsigned int num_segments, i;
+ unsigned long size;
+ uint16_t *start_code;
+ uint16_t *end_code;
+ uint16_t *delta;
+ uint16_t *range_offset;
+ uint16_t *glyph_array;
+ uint16_t c;
+
+ backend = scaled_font->backend;
+ size = 4;
+ status = backend->load_truetype_table (scaled_font,
+ TT_TAG_cmap, table_offset,
+ (unsigned char *) &buf,
+ &size);
+ if (status)
+ return status;
+
+ /* All table formats have the same first two words */
+ map = (tt_segment_map_t *) buf;
+ if (be16_to_cpu (map->format) != 4)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ size = be16_to_cpu (map->length);
+ map = malloc (size);
+ if (map == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ status = backend->load_truetype_table (scaled_font,
+ TT_TAG_cmap, table_offset,
+ (unsigned char *) map,
+ &size);
+ if (status)
+ goto fail;
+
+ num_segments = be16_to_cpu (map->segCountX2)/2;
+ end_code = map->endCount;
+ start_code = &(end_code[num_segments + 1]);
+ delta = &(start_code[num_segments]);
+ range_offset = &(delta[num_segments]);
+ glyph_array = &(range_offset[num_segments]);
+
+ /* search for glyph in segments
+ * with rangeOffset=0 */
+ for (i = 0; i < num_segments; i++) {
+ c = index - be16_to_cpu (delta[i]);
+ if (range_offset[i] == 0 &&
+ c >= be16_to_cpu (start_code[i]) &&
+ c <= be16_to_cpu (end_code[i]))
+ {
+ *ucs4 = c;
+ goto found;
+ }
+ }
+
+ /* search for glyph in segments with rangeOffset=1 */
+ for (i = 0; i < num_segments; i++) {
+ if (range_offset[i] != 0) {
+ uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
+ int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
+ uint16_t g_id_be = cpu_to_be16 (index);
+ int j;
+
+ for (j = 0; j < range_size; j++) {
+ if (glyph_ids[j] == g_id_be) {
+ *ucs4 = be16_to_cpu (start_code[i]) + j;
+ goto found;
+ }
+ }
+ }
+ }
+
+ /* glyph not found */
+ *ucs4 = -1;
+
+found:
+ status = CAIRO_STATUS_SUCCESS;
+
+fail:
+ free (map);
+
+ return status;
+}
+
+cairo_int_status_t
+_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
+ unsigned long index,
+ uint32_t *ucs4)
+{
+ cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+ const cairo_scaled_font_backend_t *backend;
+ tt_cmap_t *cmap;
+ char buf[4];
+ int num_tables, i;
+ unsigned long size;
+
+ backend = scaled_font->backend;
+ if (!backend->load_truetype_table)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ size = 4;
+ status = backend->load_truetype_table (scaled_font,
+ TT_TAG_cmap, 0,
+ (unsigned char *) &buf,
+ &size);
+ if (status)
+ return status;
+
+ cmap = (tt_cmap_t *) buf;
+ num_tables = be16_to_cpu (cmap->num_tables);
+ size = 4 + num_tables*sizeof(tt_cmap_index_t);
+ cmap = malloc (size);
+ if (cmap == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ status = backend->load_truetype_table (scaled_font,
+ TT_TAG_cmap, 0,
+ (unsigned char *) cmap,
+ &size);
+ if (status)
+ goto cleanup;
+
+ /* Find a table with Unicode mapping */
+ for (i = 0; i < num_tables; i++) {
+ if (be16_to_cpu (cmap->index[i].platform) == 3 &&
+ be16_to_cpu (cmap->index[i].encoding) == 1) {
+ status = _cairo_truetype_reverse_cmap (scaled_font,
+ be32_to_cpu (cmap->index[i].offset),
+ index,
+ ucs4);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ break;
+ }
+ }
+
+cleanup:
+ free (cmap);
+
+ return status;
+}
commit 95771d62c57c081fe350e0d33326aaa6a27139da
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:31:23 2008 +0930
Implement win32 index_to_ucs4 font backend function
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 140093b..7b84334 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1553,6 +1553,98 @@ fail1:
}
static cairo_status_t
+_cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font,
+ unsigned long index,
+ uint32_t *ucs4)
+{
+ cairo_win32_scaled_font_t *scaled_font = abstract_font;
+ GLYPHSET *glyph_set;
+ uint16_t *utf16 = NULL;
+ WORD *glyph_indices = NULL;
+ HDC hdc = NULL;
+ int res;
+ unsigned int i, j, num_glyphs;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ hdc = _get_global_font_dc ();
+ if (!hdc)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
+ if (status)
+ return status;
+
+ res = GetFontUnicodeRanges(hdc, NULL);
+ if (res == 0) {
+ status = _cairo_win32_print_gdi_error (
+ "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+ goto exit1;
+ }
+
+ glyph_set = malloc (res);
+ if (glyph_set == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto exit1;
+ }
+
+ res = GetFontUnicodeRanges(hdc, glyph_set);
+ if (res == 0) {
+ status = _cairo_win32_print_gdi_error (
+ "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges");
+ goto exit1;
+ }
+
+ for (i = 0; i < glyph_set->cRanges; i++) {
+ num_glyphs = glyph_set->ranges[i].cGlyphs;
+
+ utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
+ if (utf16 == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto exit1;
+ }
+
+ glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
+ if (glyph_indices == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto exit2;
+ }
+
+ for (j = 0; j < num_glyphs; j++)
+ utf16[j] = glyph_set->ranges[i].wcLow + j;
+ utf16[j] = 0;
+
+ if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
+ status = _cairo_win32_print_gdi_error (
+ "_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW");
+ goto exit2;
+ }
+
+ for (j = 0; j < num_glyphs; j++) {
+ if (glyph_indices[j] == index) {
+ *ucs4 = utf16[j];
+ goto exit2;
+ }
+ }
+
+ free (glyph_indices);
+ glyph_indices = NULL;
+ free (utf16);
+ utf16 = NULL;
+ }
+
+exit2:
+ if (glyph_indices)
+ free (glyph_indices);
+ if (utf16)
+ free (utf16);
+ free (glyph_set);
+exit1:
+ cairo_win32_scaled_font_done_font (&scaled_font->base);
+
+ return status;
+}
+
+static cairo_status_t
_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
@@ -1788,6 +1880,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
_cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_load_truetype_table,
_cairo_win32_scaled_font_map_glyphs_to_unicode,
+ _cairo_win32_scaled_font_index_to_ucs4,
};
/* #cairo_win32_font_face_t */
commit 4619b0b309861daa64b9c3ced9fdea20c461edf2
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:30:14 2008 +0930
Add index_to_ucs4 font backend function and FT implementation
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 7313984..9c18949 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2209,6 +2209,36 @@ _cairo_ft_map_glyphs_to_unicode (void *abstract_font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_int_status_t
+_cairo_ft_index_to_ucs4(void *abstract_font,
+ unsigned long index,
+ uint32_t *ucs4)
+{
+ cairo_ft_scaled_font_t *scaled_font = abstract_font;
+ cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
+ FT_Face face;
+ FT_ULong charcode;
+ FT_UInt gindex;
+
+ face = _cairo_ft_unscaled_font_lock_face (unscaled);
+ if (!face)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ *ucs4 = (uint32_t) -1;
+ charcode = FT_Get_First_Char(face, &gindex);
+ while (gindex != 0) {
+ charcode = FT_Get_Next_Char (face, charcode, &gindex);
+ if (gindex == index) {
+ *ucs4 = charcode;
+ break;
+ }
+ }
+
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_scaled_font_create_toy,
@@ -2219,6 +2249,7 @@ const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
NULL, /* show_glyphs */
_cairo_ft_load_truetype_table,
_cairo_ft_map_glyphs_to_unicode,
+ _cairo_ft_index_to_ucs4
};
/* #cairo_ft_font_face_t */
diff --git a/src/cairoint.h b/src/cairoint.h
index 50f5681..d5404f9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -441,8 +441,13 @@ struct _cairo_scaled_font_backend {
cairo_warn cairo_int_status_t
(*map_glyphs_to_unicode)(void *scaled_font,
- cairo_scaled_font_subset_t *font_subset);
+ cairo_scaled_font_subset_t *font_subset);
+ /* returns -1 if the unicode character could not be found for the glyph */
+ cairo_warn cairo_int_status_t
+ (*index_to_ucs4)(void *scaled_font,
+ unsigned long index,
+ uint32_t *ucs4);
};
struct _cairo_font_face_backend {
commit 54f63e7859baeff18f7345cf22630d6a9b709e1c
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jun 29 19:28:39 2008 +0930
PDF: Ensure text object is closed before emitting fill or stroke
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index 463af87..81c99e9 100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -655,6 +655,9 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
cairo_bool_t has_ctm = TRUE;
double scale = 1.0;
+ if (pdf_operators->in_text_object)
+ status = _cairo_pdf_operators_end_text (pdf_operators);
+
/* Optimize away the stroke ctm when it does not affect the
* stroke. There are other ctm cases that could be optimized
* however this is the most common.
@@ -750,6 +753,9 @@ _cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
const char *pdf_operator;
cairo_status_t status;
+ if (pdf_operators->in_text_object)
+ status = _cairo_pdf_operators_end_text (pdf_operators);
+
status = _cairo_pdf_operators_emit_path (pdf_operators,
path,
&pdf_operators->cairo_to_pdf,
More information about the cairo-commit
mailing list