[Cairo] [Fwd: PATCH - text extents]

John Ellson ellson at research.att.com
Tue Dec 2 14:00:34 PST 2003


[
  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




-------------- next part --------------
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));

-------------- next part --------------
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);



More information about the cairo mailing list