[Cairo] [Fwd: PATCH - text extents]

Soorya Kuloor skuloor at verano.com
Wed Dec 3 12:15:53 PST 2003


Hi John,

I tried the patch that you provided for text extents and am having some
problems calculating the text bounding box from the extents. As long as
the text is horizontal the bounding box seems to fit the text exactly.
However, if the text is rotated the bounding box does not look right.
The attached test program reproduces the problem.

Am I doing something stupid in my bounding box calculation? Is it wrong
to calculate bounding box from extents?

Thanks for any help.
-- Soorya

On Tue, 2003-12-02 at 15:00, John Ellson wrote:
> [
>   I understand that the cairo list server has been down and that if I 
> resend this it should get through.
>   Apologies to anyone that receives it more than once.
> 
>   John
> ]
> 
> 
> -------- Original Message --------
> Subject: 	PATCH - text extents
> Date: 	Sat, 29 Nov 2003 11:01:27 -0500
> From: 	John Ellson <ellson at research.att.com>
> To: 	cairo at cairographics.org
> 
> 
> 
> Please find attached new patches to cairo and libxsvg to implement text 
> extents
> and support text-anchor="middle".
> 
> This patch is against current CVS (11/19/03 10.40am)  and is 
> in-replacement-of
> (not on-top-of) my earlier extents patch.
> 
> This patch improves on the earlier one by multiplying the returned extents
> by ctm_inverse in cairo_gstate.c.  
> 
> libxsvg is changed to use the (possibly rotated) advance distance to
> calculate the x,y offsets to the middle or end of the string.
> 
> John
> 
> 
> 
> 
> 
> ______________________________________________________________________
> Index: src/cairo.c
> ===================================================================
> RCS file: /cvs/cairo/cairo/src/cairo.c,v
> retrieving revision 1.29
> diff -r1.29 cairo.c
> 710d709
> < /* XXX: NYI
> 734d732
> < */
> Index: src/cairo.h
> ===================================================================
> RCS file: /cvs/cairo/cairo/src/cairo.h,v
> retrieving revision 1.30
> diff -r1.30 cairo.h
> 385,387d384
> < 
> < /* XXX: NYI
> < 
> 398a396,397
> > /* XXX: NYI
> > 
> Index: src/cairo_ft_font.c
> ===================================================================
> RCS file: /cvs/cairo/cairo/src/cairo_ft_font.c,v
> retrieving revision 1.7
> diff -r1.7 cairo_ft_font.c
> 43,48c43,46
> < #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 63.0))
> < #define DOUBLE_FROM_26_6(t) (((double)((t) >> 6)) \
> < 			     + ((double)((t) & 0x3F) / 63.0))
> < #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65535.0))
> < #define DOUBLE_FROM_16_16(t) (((double)((t) >> 16)) \
> < 			      + ((double)((t) & 0xFFFF) / 65535.0))
> ---
> > #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
> > #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
> > #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
> > #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
> 324c322
> <     cairo_ft_font_t *ft;
> ---
> >     FT_Face face;
> 332c330
> <     ft = (cairo_ft_font_t *)font;
> ---
> >     face = ((cairo_ft_font_t *)font)->face;
> 346c344
> <     _install_font_matrix (&font->matrix, ft->face);
> ---
> >     _install_font_matrix (&font->matrix, face);
> 350c348
> <         (*glyphs)[i].index = FT_Get_Char_Index (ft->face, ucs4[i]);
> ---
> >         (*glyphs)[i].index = FT_Get_Char_Index (face, ucs4[i]);
> 354c352
> <         FT_Load_Glyph (ft->face, (*glyphs)[i].index, FT_LOAD_DEFAULT);
> ---
> >         FT_Load_Glyph (face, (*glyphs)[i].index, FT_LOAD_DEFAULT);
> 356,357c354,355
> <         x += DOUBLE_FROM_26_6 (ft->face->glyph->advance.x);
> <         y -= DOUBLE_FROM_26_6 (ft->face->glyph->advance.y);
> ---
> >         x += DOUBLE_FROM_26_6(face->glyph->advance.x);
> >         y -= DOUBLE_FROM_26_6(face->glyph->advance.y);
> 368,370c366
> <     double scale_x, scale_y;
> <     cairo_ft_font_t *ft = (cairo_ft_font_t *)font;
> <     cairo_status_t status = CAIRO_STATUS_SUCCESS;
> ---
> >     FT_Face face; 
> 372c368
> <     _get_scale_factors(&font->matrix, &scale_x, &scale_y);
> ---
> >     face = ((cairo_ft_font_t *)font)->face;
> 374c370,374
> < #define FONT_UNIT_TO_DEV(x) ((double)(x) / (double)(ft->face->units_per_EM))
> ---
> >     extents->ascent =        DOUBLE_FROM_26_6(face->ascender);
> >     extents->descent =       DOUBLE_FROM_26_6(face->descender);
> >     extents->height =        DOUBLE_FROM_26_6(face->height);
> >     extents->max_x_advance = DOUBLE_FROM_26_6(face->max_advance_width);
> >     extents->max_y_advance = DOUBLE_FROM_26_6(face->max_advance_height);
> 376,381c376
> <     extents->ascent = FONT_UNIT_TO_DEV(ft->face->ascender) * scale_y;
> <     extents->descent = FONT_UNIT_TO_DEV(ft->face->descender) * scale_y;
> <     extents->height = FONT_UNIT_TO_DEV(ft->face->height) * scale_y;
> <     extents->max_x_advance = FONT_UNIT_TO_DEV(ft->face->max_advance_width) * scale_x;
> <     extents->max_y_advance = FONT_UNIT_TO_DEV(ft->face->max_advance_height) * scale_y;
> <     return status;
> ---
> >     return CAIRO_STATUS_SUCCESS;
> 390,391c385,395
> <     cairo_ft_font_t *ft;
> <     cairo_status_t status = CAIRO_STATUS_SUCCESS;
> ---
> >     FT_Face		face;
> >     FT_GlyphSlot	glyphslot;
> >     int                 i, gcount;
> >     /* horizontal text (either direction) */
> >     FT_F26Dot6		X, Y;
> >     FT_F26Dot6		Left, Right, Top, Bottom;
> >     FT_F26Dot6		overall_Left, overall_Right;
> >     FT_F26Dot6		overall_Top, overall_Bottom;
> >                                                                                           
> >     if (font == NULL || glyphs == NULL || extents == NULL)
> >         return CAIRO_STATUS_NO_MEMORY;
> 393c397,398
> <     ft = (cairo_ft_font_t *)font;
> ---
> >     face = ((cairo_ft_font_t *)font)->face;
> >     glyphslot = face->glyph;
> 395d399
> <     /* FIXME: lift code from xft to do this */
> 397c401,477
> <     return status;
> ---
> >     gcount =
> >       overall_Left = overall_Right =
> >       overall_Top = overall_Bottom = 0;
> >     
> > #define HORIZONTAL 1   /* FIXME  - get cuurent vertical/horizontal mode from Fc???? */
> >     if (HORIZONTAL)
> >     {
> >         for (i = 0; i < num_glyphs; i++)
> >         {
> >             FT_Load_Glyph (face, glyphs[i].index, FT_LOAD_DEFAULT);
> >     
> > 	    X = DOUBLE_TO_26_6(glyphs[i].x);
> > 	    Y = DOUBLE_TO_26_6(glyphs[i].y);
> >     
> >             Left = X - glyphslot->metrics.horiBearingX;
> >             Top = Y - glyphslot->metrics.horiBearingY;
> >             Right = Left + glyphslot->metrics.width;
> >             Bottom = Top + glyphslot->metrics.height;
> >     
> >             if (++gcount == 1)
> >             {
> >                 overall_Left = Left;
> >                 overall_Top = Top;
> >                 overall_Right = Right;
> >                 overall_Bottom = Bottom;
> >             }
> >             else
> >             {
> >                 if (Left < overall_Left) overall_Left = Left;
> >                 if (Top < overall_Top) overall_Top = Top;
> >                 if (Right > overall_Right) overall_Right = Right;
> >                 if (Bottom > overall_Bottom) overall_Bottom = Bottom;
> >             }
> >     
> > 	    X += glyphslot->metrics.horiAdvance;
> >         }
> >     }
> >     else
> >     {
> >         for (i = 0; i < num_glyphs; i++)
> >         {
> >             FT_Load_Glyph (face, glyphs[i].index, FT_LOAD_DEFAULT);
> >     
> > 	    X = DOUBLE_TO_26_6(glyphs[i].x);
> > 	    Y = DOUBLE_TO_26_6(glyphs[i].y);
> >     
> >             Left = X - glyphslot->metrics.vertBearingX;
> >             Top = Y - glyphslot->metrics.vertBearingY;
> >             Right = Left + glyphslot->metrics.width;
> >             Bottom = Top + glyphslot->metrics.height;
> >     
> >             if (++gcount == 1)
> >             {
> >                 overall_Left = Left;
> >                 overall_Top = Top;
> >                 overall_Right = Right;
> >                 overall_Bottom = Bottom;
> >             }
> >             else
> >             {
> >                 if (Left < overall_Left) overall_Left = Left;
> >                 if (Top < overall_Top) overall_Top = Top;
> >                 if (Right > overall_Right) overall_Right = Right;
> >                 if (Bottom > overall_Bottom) overall_Bottom = Bottom;
> >             }
> >     
> > 	    Y += glyphslot->metrics.vertAdvance;
> >         }
> >     }
> >     extents->left_side_bearing  = DOUBLE_FROM_26_6(overall_Left);
> >     extents->right_side_bearing = DOUBLE_FROM_26_6(overall_Right);
> >     extents->ascent             = DOUBLE_FROM_26_6(overall_Top);
> >     extents->descent            = DOUBLE_FROM_26_6(overall_Bottom);
> >     extents->x_advance          = DOUBLE_FROM_26_6(X);
> >     extents->y_advance          = DOUBLE_FROM_26_6(Y);
> > 
> >     return CAIRO_STATUS_SUCCESS;
> 399a480
> > 
> 558c639
> <     /* FIXME: lift code from xft to do this */
> ---
> >     /* XXX: lift code from xft to do this */
> Index: src/cairo_gstate.c
> ===================================================================
> RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
> retrieving revision 1.33
> diff -r1.33 cairo_gstate.c
> 1595a1596
> >     double dummy_x;
> 1602a1604,1619
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->max_x_advance),
> >                                      &(extents->max_y_advance));
> >     /* XXX - is this sensible? */
> >     dummy_x = 0.0;
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(dummy_x),
> >                                      &(extents->ascent));
> >     dummy_x = 0.0;
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(dummy_x),
> >                                      &(extents->descent));
> >     dummy_x = 0.0;
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(dummy_x),
> >                                      &(extents->height));
> 1632a1650,1658
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->x_advance),
> >                                      &(extents->y_advance));
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->left_side_bearing),
> >                                      &(extents->descent));
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->right_side_bearing),
> >                                      &(extents->ascent));
> 1667c1693,1701
> < 
> ---
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->x_advance),
> >                                      &(extents->y_advance));
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->left_side_bearing),
> >                                      &(extents->descent));
> >     cairo_matrix_transform_distance (&gstate->ctm_inverse,
> >                                      &(extents->right_side_bearing),
> >                                      &(extents->ascent));
> 
> 
> ______________________________________________________________________
> Index: src/xsvg.c
> ===================================================================
> RCS file: /cvs/xsvg/libxsvg/src/xsvg.c,v
> retrieving revision 1.21
> diff -r1.21 xsvg.c
> 1122a1123,1125
> >     cairo_text_extents_t extents;
> > 
> >     _xsvg_select_font (xsvg);
> 1126a1130,1144
> >     if (xsvg->state->text_anchor != SVG_TEXT_ANCHOR_START)
> >     {
> > 	cairo_text_extents (xsvg->cr, utf8, &extents);
> > 	if (xsvg->state->text_anchor == SVG_TEXT_ANCHOR_END)
> > 	{
> > 	    x -= extents.x_advance;
> > 	    y -= extents.y_advance;
> > 	}
> > 	else if (xsvg->state->text_anchor == SVG_TEXT_ANCHOR_MIDDLE)
> > 	{
> > 	    x -= extents.x_advance/2.0;
> > 	    y -= extents.y_advance/2.0;
> > 	}
> >     }
> > 
> 1137,1149d1154
> < /* XXX: Temporarily disable since cairo_text_extents is currently not working
> < 
> <     if (xsvg->state->text_anchor != SVG_TEXT_ANCHOR_START) {
> < 	double x, y, width, height, dx, dy;
> < 	cairo_text_extents (xsvg->cr, utf8, &x, &y, &width, &height, &dx, &dy);
> < 	if (xsvg->state->text_anchor == SVG_TEXT_ANCHOR_END)
> < 	    cairo_rel_move_to (xsvg->cr, -dx, -dy);
> < 	else if (xsvg->state->text_anchor == SVG_TEXT_ANCHOR_MIDDLE)
> < 	    cairo_rel_move_to (xsvg->cr, -dx / 2, -dy / 2);
> <     }
> < */
> < 
> <     _xsvg_select_font (xsvg);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: text-bounds.c
Type: text/x-c
Size: 5377 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20031203/f5db6870/text-bounds.bin


More information about the cairo mailing list