[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