[cairo] PDF show glyphs

Behdad Esfahbod behdad at behdad.org
Thu Feb 8 15:24:08 PST 2007


On Mon, 2007-02-05 at 09:22 -0500, Adrian Johnson wrote:
> I've been putting together a patch to get the PDF backend to write out
> strings using the TJ operator similar to what is described in bug 2713.

Nice work.

> The current issues with the patch are:
> 
> - It currently does a _cairo_scaled_glyph_lookup() for every glyph.
>   I'm thinking of moving this into _cairo_sub_font_glyph_create()
>   and returning the x_advance it via
>   cairo_scaled_font_subsets_map_glyph().

Makes sense.  Another idea is to totally ignore the default advance of
the glyph and use the advance of the first occurrence of the glyph as
its default advance.  This way you don't need to look the glyph up.  Has
its own problems though.

> - The gnome-print-pdf.c patch referenced in bug 2713 allows
>   a 0.001*font_scale error when comparing glyph positions. I haven't
>   done this although it seems to work.

That's probably a good idea, given doubles.

> - If the x coordinate of the next glyph in a sequence is > 10*font_scale
>   I terminate the string and reposition before starting a new string.
>   I'm not sure if this is necessary.

Sounds like a good idea too.

> - Should I limit the maximum string length to prevent the accumulation
>   of rounding errors?

I won't worry about that.  Is there any limitation on the max length of
the string in the standard?

> - It needs more testing.

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.

behdad

> plain text document attachment (patch_pdf_show_glyphs)
> diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
> index 18f79ca..b31403d 100644
> --- a/src/cairo-pdf-surface.c
> +++ b/src/cairo-pdf-surface.c
> @@ -2796,8 +2796,12 @@ _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;
> +    cairo_scaled_glyph_t *scaled_glyph;
> +    double x_advance;
> +    double Tlm_x, Tlm_y;
> +    double Tm_x;
>      int i;
>  
>      if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
> @@ -2818,38 +2822,110 @@ _cairo_pdf_surface_show_glyphs (void			*
>      else
>          diagonal = FALSE;
>  
> +    in_TJ = FALSE;
>      for (i = 0; i < num_glyphs; i++) {
> +        status = _cairo_scaled_glyph_lookup (scaled_font,
> +                                             glyphs[i].index,
> +                                             CAIRO_SCALED_GLYPH_INFO_METRICS,
> +                                             &scaled_glyph);
> +	if (status)
> +	    return status;
> +        x_advance = scaled_glyph->metrics.x_advance;
> +        
>  	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
>  						       scaled_font, glyphs[i].index,
>  						       &font_id, &subset_id, &subset_glyph_index);
> -	if (status)
> +        if (status)
>  	    return status;
>  
> -	if (subset_id != current_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);
> +                                         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 &&
> +                glyphs[i].y == glyphs[i+1].y &&
> +                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_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",
> +                                                 subset_glyph_index);
> +                    Tm_x += x_advance;
> +                    in_TJ = TRUE;
> +                } else {
> +                    if (glyphs[i].x != Tm_x) {
> +                        double delta = (long)(1000.0*(glyphs[i].x - Tm_x));
> +                        
> +                        _cairo_output_stream_printf (surface->output,
> +                                                     "> %f <",
> +                                                     -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) {
> +                    _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);
>          }
>      }
> -
>      _cairo_output_stream_printf (surface->output,
>  				 "ET\r\n");
>  
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://cairographics.org/cgi-bin/mailman/listinfo/cairo
-- 
behdad
http://behdad.org/

"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759





More information about the cairo mailing list