PDF: Use the TJ operator to show glyphs

This commit is contained in:
Adrian Johnson 2007-03-23 23:08:46 +10:30
parent 820341b4c5
commit e9a2696648
5 changed files with 201 additions and 50 deletions

View file

@ -2860,6 +2860,8 @@ _cairo_pdf_surface_fill (void *abstract_surface,
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,
@ -2870,9 +2872,11 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
{
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_scaled_font_subsets_glyph_t subset_glyph;
cairo_bool_t diagonal, in_TJ;
cairo_status_t status;
double Tlm_x = 0, Tlm_y = 0;
double Tm_x = 0, y;
int i;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -2893,35 +2897,118 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
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,
&subset_glyph);
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_glyph.is_scaled == FALSE) {
y = 0.0;
cairo_matrix_transform_distance (&scaled_font->scale,
&subset_glyph.x_advance,
&y);
}
if (subset_id != current_subset_id || !diagonal) {
if (subset_glyph.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,
"%f %f %f %f %f %f Tm <%02x> Tj\r\n",
"/CairoFont-%d-%d 1 Tf\r\n",
subset_glyph.font_id,
subset_glyph.subset_id);
}
if (subset_glyph.subset_id != current_subset_id || !diagonal) {
_cairo_output_stream_printf (surface->output,
"%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_glyph.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.subset_glyph_index);
Tm_x += subset_glyph.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.subset_glyph_index);
Tm_x += subset_glyph.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.subset_glyph_index);
Tm_x += subset_glyph.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.subset_glyph_index);
Tm_x += subset_glyph.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,
subset_glyph_index);
"<%02x> Tj\r\n",
subset_glyph.subset_glyph_index);
}
}

View file

@ -2200,12 +2200,13 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
unsigned int current_subset_id = -1;
unsigned int font_id;
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_ps_glyph_id_t *glyph_ids;
cairo_status_t status;
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 _cairo_ps_surface_analyze_operation (surface, op, source);
@ -2228,11 +2229,11 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
for (i = 0; i < num_glyphs_unsigned; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
&font_id,
&(glyph_ids[i].subset_id),
&(glyph_ids[i].glyph_id));
&subset_glyph);
if (status)
goto fail;
glyph_ids[i].subset_id = subset_glyph.subset_id;
glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index;
}
i = 0;
@ -2242,7 +2243,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
"/CairoFont-%d-%d findfont\n"
"[ %f %f %f %f 0 0 ] makefont\n"
"setfont\n",
font_id,
subset_glyph.font_id,
glyph_ids[i].subset_id,
scaled_font->scale.xx,
scaled_font->scale.yx,

View file

@ -41,6 +41,14 @@
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
typedef struct _cairo_scaled_font_subsets_glyph {
unsigned int font_id;
unsigned int subset_id;
unsigned int subset_glyph_index;
cairo_bool_t is_scaled;
double x_advance;
} cairo_scaled_font_subsets_glyph_t;
/**
* _cairo_scaled_font_subsets_create:
*
@ -85,6 +93,8 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* @font_subsets: a #cairo_scaled_font_subsets_t
* @scaled_font: the font of the glyph to be mapped
* @scaled_font_glyph_index: the index of the glyph to be mapped
* @subset_glyph_ret: return structure containing subset font and glyph id
*
* @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
@ -126,6 +136,17 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* used by #cairo_scaled_font_subset_t as provided by
* _cairo_scaled_font_subsets_foreach.
*
* The returned values in the cairo_scaled_font_subsets_glyph_t struct are:
*
* @font_id: The font ID of the mapped glyph
* @subset_id : The subset ID of the mapped glyph within the @font_id
* @subset_glyph_index: The index of the mapped glyph within the @subset_id subset
* @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.
*
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* CAIRO_STATUS_NO_MEMORY.
@ -134,9 +155,7 @@ 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,
unsigned int *font_id_ret,
unsigned int *subset_id_ret,
unsigned int *subset_glyph_index_ret);
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
typedef void
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,

View file

@ -74,6 +74,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 {
@ -107,7 +108,8 @@ _cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
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;
@ -118,6 +120,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
_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;
}
@ -207,7 +210,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
_cairo_sub_font_init_key (sub_font, scaled_font);
sub_font->parent = parent;
sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
sub_font->scaled_font = scaled_font;
sub_font->font_id = font_id;
sub_font->current_subset = 0;
@ -248,7 +251,8 @@ static cairo_status_t
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
unsigned int *subset_glyph_index,
double *x_advance)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@ -258,6 +262,7 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
{
*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;
}
@ -269,10 +274,12 @@ 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;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
@ -284,9 +291,17 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
sub_font->num_glyphs_in_current_subset = 0;
}
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
return status;
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++,
scaled_glyph->metrics.x_advance);
if (sub_font_glyph == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -308,6 +323,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
*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;
}
@ -404,12 +420,14 @@ cairo_private 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,
unsigned int *font_id,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_t key, *sub_font;
cairo_scaled_glyph_t *scaled_glyph;
cairo_font_face_t *font_face;
cairo_matrix_t identity;
cairo_font_options_t font_options;
cairo_scaled_font_t *unscaled_font;
cairo_status_t status;
/* Lookup glyph in unscaled subsets */
@ -419,10 +437,14 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
&subset_glyph->subset_id,
&subset_glyph->subset_glyph_index,
&subset_glyph->x_advance);
if (status == CAIRO_STATUS_SUCCESS) {
*font_id = sub_font->font_id;
subset_glyph->font_id = sub_font->font_id;
subset_glyph->is_scaled = FALSE;
return CAIRO_STATUS_SUCCESS;
}
}
@ -435,10 +457,14 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
&subset_glyph->subset_id,
&subset_glyph->subset_glyph_index,
&subset_glyph->x_advance);
if (status == CAIRO_STATUS_SUCCESS) {
*font_id = sub_font->font_id;
subset_glyph->font_id = sub_font->font_id;
subset_glyph->is_scaled = TRUE;
return CAIRO_STATUS_SUCCESS;
}
}
@ -457,7 +483,18 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
sub_font = _cairo_sub_font_create (subsets, scaled_font,
font_face = cairo_scaled_font_get_font_face (scaled_font);
cairo_matrix_init_identity (&identity);
_cairo_font_options_init_default (&font_options);
cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
unscaled_font = cairo_scaled_font_create (font_face,
&identity,
&identity,
&font_options);
sub_font = _cairo_sub_font_create (subsets,
unscaled_font,
subsets->num_sub_fonts++,
subsets->max_glyphs_per_unscaled_subset_limit,
FALSE);
@ -469,6 +506,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (status)
return status;
}
subset_glyph->is_scaled = FALSE;
} else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
/* No path available. Add to scaled subset. */
key.is_scaled = TRUE;
@ -476,7 +514,8 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
sub_font = _cairo_sub_font_create (subsets, scaled_font,
sub_font = _cairo_sub_font_create (subsets,
cairo_scaled_font_reference (scaled_font),
subsets->num_sub_fonts++,
subsets->max_glyphs_per_scaled_subset_limit,
TRUE);
@ -488,13 +527,17 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
if (status)
return status;
}
subset_glyph->is_scaled = TRUE;
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
*font_id = sub_font->font_id;
subset_glyph->font_id = sub_font->font_id;
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
&subset_glyph->subset_id,
&subset_glyph->subset_glyph_index,
&subset_glyph->x_advance);
}
static cairo_status_t

View file

@ -1877,7 +1877,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
cairo_svg_document_t *document = surface->document;
cairo_path_fixed_t path;
cairo_status_t status;
unsigned int font_id, subset_id, subset_glyph_index;
cairo_scaled_font_subsets_glyph_t subset_glyph;
int i;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -1901,7 +1901,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,
&font_id, &subset_id, &subset_glyph_index);
&subset_glyph);
if (status) {
glyphs += i;
num_glyphs -= i;
@ -1911,7 +1911,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
_cairo_output_stream_printf (surface->xml_node,
" <use xlink:href=\"#glyph%d-%d\" "
"x=\"%f\" y=\"%f\"/>\n",
font_id, subset_glyph_index,
subset_glyph.font_id,
subset_glyph.subset_glyph_index,
glyphs[i].x, glyphs[i].y);
}