[cairo] PDF show glyphs
Adrian Johnson
ajohnson at redneon.com
Sun Feb 11 06:20:08 PST 2007
Behdad Esfahbod wrote:
> Do you want to get this in for or past 1.4? If 1.4, go ahead and commit
> it so we get a bit of testing.
I've done some more testing and updated the patch however I have not
committed it because it breaks three tests. These tests print a string
of glyphs. The test failures are the result of one or two glyphs
shifting left or right by 1 pixel.
-------------- next part --------------
>From 7502af0e8b1cb2900e78804dd4c746610b7534d3 Mon Sep 17 00:00:00 2001
From: Adrian Johnson <ajohnson at redneon.com>
Date: Mon, 12 Feb 2007 00:16:55 +1030
Subject: [PATCH] PDF: Use TJ for showing glyphs
cairo-scale-font-subsets looks up the x_advance for
each glyph added to the subset. The x_advance is
returned to the PDF surface via the map_glyphs function.
The PDF surface looks for two or more glyphs with the same
Y coordinate and used the TJ operater to emit a single
string of glyphs without needing to reposition between
each glyph.
---
src/cairo-pdf-surface.c | 113 ++++++++++++++++++++++++++-----
src/cairo-ps-surface.c | 4 +-
src/cairo-scaled-font-subsets-private.h | 4 +-
src/cairo-scaled-font-subsets.c | 29 +++++++--
src/cairo-svg-surface.c | 4 +-
5 files changed, 130 insertions(+), 24 deletions(-)
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 1e5e521..cfea723 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -2835,6 +2835,8 @@ _cairo_pdf_surface_fill (void *abstrac
return status;
}
+#define GLYPH_POSITION_TOLERANCE 0.001
+
static cairo_int_status_t
_cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
@@ -2846,8 +2848,11 @@ _cairo_pdf_surface_show_glyphs (void *
cairo_pdf_surface_t *surface = abstract_surface;
unsigned int current_subset_id = (unsigned int)-1;
unsigned int font_id, subset_id, subset_glyph_index;
- cairo_bool_t diagonal;
+ cairo_bool_t diagonal, in_TJ;
cairo_status_t status;
+ double x_advance;
+ double Tlm_x = 0, Tlm_y = 0;
+ double Tm_x = 0;
int i;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -2868,34 +2873,110 @@ _cairo_pdf_surface_show_glyphs (void *
else
diagonal = FALSE;
+ in_TJ = FALSE;
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);
+ status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+ scaled_font, glyphs[i].index,
+ &font_id, &subset_id, &subset_glyph_index,
+ &x_advance);
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);
+ if (subset_id != current_subset_id) {
+ if (in_TJ) {
+ _cairo_output_stream_printf (surface->output, ">] TJ\r\n");
+ in_TJ = FALSE;
+ }
+ _cairo_output_stream_printf (surface->output,
+ "/CairoFont-%d-%d 1 Tf\r\n",
+ font_id, subset_id);
+ }
if (subset_id != current_subset_id || !diagonal) {
_cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f Tm <%02x> Tj\r\n",
+ "%f %f %f %f %f %f Tm\r\n",
scaled_font->scale.xx,
scaled_font->scale.yx,
-scaled_font->scale.xy,
-scaled_font->scale.yy,
glyphs[i].x,
- glyphs[i].y,
- subset_glyph_index);
- current_subset_id = subset_id;
+ glyphs[i].y);
+ current_subset_id = subset_id;
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+
+ if (diagonal) {
+ if (i < num_glyphs - 1 &&
+ fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
+ fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10) {
+ if (!in_TJ) {
+ if (i != 0) {
+ _cairo_output_stream_printf (surface->output,
+ "%f %f Td\r\n",
+ (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+ (glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+ _cairo_output_stream_printf (surface->output,
+ "[<%02x",
+ subset_glyph_index);
+ Tm_x += x_advance;
+ in_TJ = TRUE;
+ } else {
+ if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE)
+ {
+ double delta = glyphs[i].x - Tm_x;
+
+ _cairo_output_stream_printf (surface->output,
+ "> %f <",
+ -1000.0*delta/scaled_font->scale.xx);
+ Tm_x += delta;
+ }
+ _cairo_output_stream_printf (surface->output,
+ "%02x",
+ subset_glyph_index);
+ Tm_x += x_advance;
+ }
+ }
+ else {
+ if (in_TJ) {
+ if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE)
+ {
+ double delta = glyphs[i].x - Tm_x;
+
+ _cairo_output_stream_printf (surface->output,
+ "> %f <",
+ -1000.0*delta/scaled_font->scale.xx);
+ Tm_x += delta;
+ }
+ _cairo_output_stream_printf (surface->output,
+ "%02x>] TJ\r\n",
+ subset_glyph_index);
+ Tm_x += x_advance;
+ in_TJ = FALSE;
+ } else {
+ if (i != 0) {
+ _cairo_output_stream_printf (surface->output,
+ "%f %f Td ",
+ (glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
+ (glyphs[i].y - Tlm_x)/-scaled_font->scale.yy);
+ Tlm_x = glyphs[i].x;
+ Tlm_y = glyphs[i].y;
+ Tm_x = Tlm_x;
+ }
+ _cairo_output_stream_printf (surface->output,
+ "<%02x> Tj ",
+ subset_glyph_index);
+ Tm_x += x_advance;
+ }
+ }
} else {
_cairo_output_stream_printf (surface->output,
- "%f %f Td <%02x> Tj\r\n",
- (glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
- (glyphs[i].y - glyphs[i-1].y)/-scaled_font->scale.yy,
+ "<%02x> Tj\r\n",
subset_glyph_index);
}
}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 3da530e..4b8b124 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2150,6 +2150,7 @@ _cairo_ps_surface_show_glyphs (void
unsigned int num_glyphs_unsigned, i, j, last, end;
cairo_bool_t vertical, horizontal;
cairo_output_stream_t *word_wrap;
+ double x_advance;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _analyze_operation (surface, op, source);
@@ -2174,7 +2175,8 @@ _cairo_ps_surface_show_glyphs (void
scaled_font, glyphs[i].index,
&font_id,
&(glyph_ids[i].subset_id),
- &(glyph_ids[i].glyph_id));
+ &(glyph_ids[i].glyph_id),
+ &x_advance);
if (status)
goto fail;
}
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 88dbfbb..9b7e28d 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -78,6 +78,7 @@ _cairo_scaled_font_subsets_destroy (cair
* @font_id_ret: return value giving the font ID of the mapped glyph
* @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
* @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
+ * @x_advance_ret: return value giving the user space X advance of the glyph
*
* Map a glyph from a #cairo_scaled_font to a new index within a
* subset of that font. The mapping performed is from the tuple:
@@ -126,7 +127,8 @@ _cairo_scaled_font_subsets_map_glyph (ca
unsigned long scaled_font_glyph_index,
unsigned int *font_id_ret,
unsigned int *subset_id_ret,
- unsigned int *subset_glyph_index_ret);
+ unsigned int *subset_glyph_index_ret,
+ double *x_advance_ret);
typedef void
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 68a662a..d6e6404 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -69,6 +69,7 @@ typedef struct _cairo_sub_font_glyph {
unsigned int subset_id;
unsigned int subset_glyph_index;
+ double x_advance;
} cairo_sub_font_glyph_t;
typedef struct _cairo_sub_font_collection {
@@ -102,7 +103,8 @@ _cairo_sub_font_glyphs_equal (const void
static cairo_sub_font_glyph_t *
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
unsigned int subset_id,
- unsigned int subset_glyph_index)
+ unsigned int subset_glyph_index,
+ double x_advance)
{
cairo_sub_font_glyph_t *sub_font_glyph;
@@ -113,6 +115,7 @@ _cairo_sub_font_glyph_create (unsigned l
_cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
sub_font_glyph->subset_id = subset_id;
sub_font_glyph->subset_glyph_index = subset_glyph_index;
+ sub_font_glyph->x_advance = x_advance;
return sub_font_glyph;
}
@@ -230,10 +233,13 @@ static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
unsigned int *subset_id,
- unsigned int *subset_glyph_index)
+ unsigned int *subset_glyph_index,
+ double *x_advance)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
+ cairo_scaled_glyph_t *scaled_glyph;
+ double x, y;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
@@ -246,9 +252,20 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
sub_font->num_glyphs_in_current_subset = 0;
}
+ status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
+ scaled_font_glyph_index,
+ CAIRO_SCALED_GLYPH_INFO_METRICS,
+ &scaled_glyph);
+ if (status)
+ return status;
+
+ x = scaled_glyph->metrics.x_advance;
+ y = 0;
+ cairo_matrix_transform_distance (&sub_font->scaled_font->ctm, &x, &y);
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
- sub_font->num_glyphs_in_current_subset++);
+ sub_font->num_glyphs_in_current_subset++,
+ x);
if (sub_font_glyph == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -262,6 +279,7 @@ _cairo_sub_font_map_glyph (cairo_sub_fon
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
+ *x_advance = sub_font_glyph->x_advance;
return CAIRO_STATUS_SUCCESS;
}
@@ -344,7 +362,8 @@ _cairo_scaled_font_subsets_map_glyph (ca
unsigned long scaled_font_glyph_index,
unsigned int *font_id,
unsigned int *subset_id,
- unsigned int *subset_glyph_index)
+ unsigned int *subset_glyph_index,
+ double *x_advance)
{
cairo_sub_font_t key, *sub_font;
cairo_status_t status;
@@ -368,7 +387,7 @@ _cairo_scaled_font_subsets_map_glyph (ca
*font_id = sub_font->font_id;
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
- subset_id, subset_glyph_index);
+ subset_id, subset_glyph_index, x_advance);
}
cairo_private cairo_status_t
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5f25015..6f488e2 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1618,6 +1618,7 @@ _cairo_svg_surface_show_glyphs (void *
cairo_path_fixed_t path;
cairo_status_t status;
unsigned int font_id, subset_id, subset_glyph_index;
+ double x_advance;
int i;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@@ -1641,7 +1642,8 @@ _cairo_svg_surface_show_glyphs (void *
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
scaled_font, glyphs[i].index,
- &font_id, &subset_id, &subset_glyph_index);
+ &font_id, &subset_id, &subset_glyph_index,
+ &x_advance);
if (status) {
glyphs += i;
num_glyphs -= i;
--
1.4.3.4
More information about the cairo
mailing list