diff options
author | Carl Worth <cworth@cworth.org> | 2006-02-13 16:46:47 -0800 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2006-02-13 16:46:47 -0800 |
commit | 0b5ac24b1522b3287903c04fb894bfae4fc67403 (patch) | |
tree | b8256ae476f183ba07c4f4ef031d31bc31927910 /src/cairo-ft-font.c | |
parent | db163fcc882251188e0ce63d0b9606cb59664da0 (diff) | |
parent | 90689370267f3c02d6be62e3e8c85cccdad6f577 (diff) |
Remove pixman and revert tessellation bug from SNAPSHOT_0_3_0SNAPSHOT_0_3_0
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r-- | src/cairo-ft-font.c | 176 |
1 files changed, 136 insertions, 40 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index f757db09c..b928b04fc 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -23,6 +23,8 @@ */ #include "cairoint.h" +#include "cairo-ft.h" + #include <fontconfig/fontconfig.h> #include <fontconfig/fcfreetype.h> @@ -50,6 +52,16 @@ typedef struct { } ft_font_val_t; +/* + * The simple 2x2 matrix is converted into separate scale and shape + * factors so that hinting works right + */ + +typedef struct { + double x_scale, y_scale; + double shape[2][2]; +} ft_font_transform_t; + static ft_font_val_t * _create_from_face (FT_Face face, int owns_face) { @@ -246,7 +258,7 @@ _ft_font_cache_destroy_cache (void *cache) free (fc); } -const struct cairo_cache_backend _ft_font_cache_backend = { +static const cairo_cache_backend_t _ft_font_cache_backend = { _ft_font_cache_hash, _ft_font_cache_keys_equal, _ft_font_cache_create_entry, @@ -254,7 +266,6 @@ const struct cairo_cache_backend _ft_font_cache_backend = { _ft_font_cache_destroy_cache }; - static ft_cache_t *_global_ft_cache = NULL; static void @@ -297,7 +308,7 @@ _get_global_ft_cache (void) /* implement the backend interface */ -const struct cairo_font_backend cairo_ft_font_backend; +const cairo_font_backend_t cairo_ft_font_backend; static cairo_unscaled_font_t * _cairo_ft_font_create (const char *family, @@ -402,10 +413,10 @@ _cairo_ft_font_destroy (void *abstract_font) static void _utf8_to_ucs4 (char const *utf8, FT_ULong **ucs4, - size_t *nchars) + int *nchars) { int len = 0, step = 0; - size_t n = 0, alloc = 0; + int n = 0, alloc = 0; FcChar32 u = 0; if (utf8 == NULL || ucs4 == NULL || nchars == NULL) @@ -433,11 +444,67 @@ _utf8_to_ucs4 (char const *utf8, *nchars = n; } +/* + * Split a matrix into the component pieces of scale and shape + */ + +static void +_cairo_ft_font_compute_transform (ft_font_transform_t *sf, cairo_font_scale_t *sc) +{ + cairo_matrix_t normalized; + double tx, ty; + + /* The font matrix has x and y "scale" components which we extract and + * use as character scale values. These influence the way freetype + * chooses hints, as well as selecting different bitmaps in + * hand-rendered fonts. We also copy the normalized matrix to + * freetype's transformation. + */ + + cairo_matrix_set_affine (&normalized, + sc->matrix[0][0], + sc->matrix[0][1], + sc->matrix[1][0], + sc->matrix[1][1], + 0, 0); + + _cairo_matrix_compute_scale_factors (&normalized, + &sf->x_scale, &sf->y_scale, + /* XXX */ 1); + cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale); + cairo_matrix_get_affine (&normalized, + &sf->shape[0][0], &sf->shape[0][1], + &sf->shape[1][0], &sf->shape[1][1], + &tx, &ty); +} + +/* + * Set the font transformation + */ + +static void +_cairo_ft_font_install_transform (ft_font_transform_t *sf, FT_Face face) +{ + FT_Matrix mat; + + mat.xx = DOUBLE_TO_16_16(sf->shape[0][0]); + mat.yx = -DOUBLE_TO_16_16(sf->shape[0][1]); + mat.xy = -DOUBLE_TO_16_16(sf->shape[1][0]); + mat.yy = DOUBLE_TO_16_16(sf->shape[1][1]); + + FT_Set_Transform(face, &mat, NULL); + + FT_Set_Char_Size(face, + (FT_F26Dot6) (sf->x_scale * 64.0), + (FT_F26Dot6) (sf->y_scale * 64.0), + 0, 0); +} + static void _install_font_scale (cairo_font_scale_t *sc, FT_Face face) { cairo_matrix_t normalized; - double scale_x, scale_y; + double x_scale, y_scale; double xx, xy, yx, yy, tx, ty; FT_Matrix mat; @@ -455,8 +522,9 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face) sc->matrix[1][1], 0, 0); - _cairo_matrix_compute_scale_factors (&normalized, &scale_x, &scale_y); - cairo_matrix_scale (&normalized, 1.0 / scale_x, 1.0 / scale_y); + _cairo_matrix_compute_scale_factors (&normalized, &x_scale, &y_scale, + /* XXX */ 1); + cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale); cairo_matrix_get_affine (&normalized, &xx /* 00 */ , &yx /* 01 */, &xy /* 10 */, &yy /* 11 */, @@ -470,8 +538,8 @@ _install_font_scale (cairo_font_scale_t *sc, FT_Face face) FT_Set_Transform(face, &mat, NULL); FT_Set_Pixel_Sizes(face, - (FT_UInt) scale_x, - (FT_UInt) scale_y); + (FT_UInt) x_scale, + (FT_UInt) y_scale); } static cairo_status_t @@ -481,6 +549,9 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font, cairo_glyph_t **glyphs, int *nglyphs) { + double x = 0., y = 0.; + size_t i; + FT_ULong *ucs4 = NULL; cairo_ft_font_t *font = abstract_font; FT_Face face = font->val->face; cairo_glyph_cache_key_t key; @@ -490,10 +561,6 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font, key.unscaled = &font->base; key.scale = *sc; - double x = 0., y = 0.; - size_t i; - FT_ULong *ucs4 = NULL; - _utf8_to_ucs4 (utf8, &ucs4, nglyphs); if (ucs4 == NULL) @@ -527,7 +594,7 @@ _cairo_ft_font_text_to_glyphs (void *abstract_font, continue; x += val->extents.x_advance; - y -= val->extents.y_advance; + y += val->extents.y_advance; } _cairo_unlock_global_image_glyph_cache (); @@ -544,13 +611,19 @@ _cairo_ft_font_font_extents (void *abstract_font, cairo_ft_font_t *font = abstract_font; FT_Face face = font->val->face; FT_Size_Metrics *metrics = &face->size->metrics; + ft_font_transform_t sf; - _install_font_scale (sc, face); + _cairo_ft_font_compute_transform (&sf, sc); + _cairo_ft_font_install_transform (&sf, face); - extents->ascent = DOUBLE_FROM_26_6(metrics->ascender); - extents->descent = DOUBLE_FROM_26_6(metrics->descender); - extents->height = DOUBLE_FROM_26_6(metrics->height); - extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance); + /* + * Get to unscaled metrics so that the upper level can get back to + * user space + */ + extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / sf.y_scale; + extents->descent = DOUBLE_FROM_26_6(metrics->descender) / sf.y_scale; + extents->height = DOUBLE_FROM_26_6(metrics->height) / sf.y_scale; + extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / sf.x_scale; /* FIXME: this doesn't do vertical layout atm. */ extents->max_y_advance = 0.0; @@ -614,7 +687,7 @@ _cairo_ft_font_glyph_extents (void *abstract_font, cairo_ft_font_create_for_ft_face accept an FcPattern. */ glyph_min.x = glyphs[i].x + img->extents.x_bearing; - glyph_min.y = glyphs[i].y - img->extents.y_bearing; + glyph_min.y = glyphs[i].y + img->extents.y_bearing; glyph_max.x = glyph_min.x + img->extents.width; glyph_max.y = glyph_min.y + img->extents.height; @@ -635,12 +708,12 @@ _cairo_ft_font_glyph_extents (void *abstract_font, } _cairo_unlock_global_image_glyph_cache (); - extents->x_bearing = total_min.x - origin.x; - extents->y_bearing = total_min.y - origin.y; - extents->width = total_max.x - total_min.x; - extents->height = total_max.y - total_min.y; + extents->x_bearing = (total_min.x - origin.x); + extents->y_bearing = (total_min.y - origin.y); + extents->width = (total_max.x - total_min.x); + extents->height = (total_max.y - total_min.y); extents->x_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x; - extents->y_advance = glyphs[i-1].y + 0 - origin.y; + extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y; return CAIRO_STATUS_SUCCESS; } @@ -688,7 +761,7 @@ _cairo_ft_font_glyph_bbox (void *abstract_font, continue; x1 = _cairo_fixed_from_double (glyphs[i].x + img->size.x); - y1 = _cairo_fixed_from_double (glyphs[i].y - img->size.y); + y1 = _cairo_fixed_from_double (glyphs[i].y + img->size.y); x2 = x1 + _cairo_fixed_from_double (img->size.width); y2 = y1 + _cairo_fixed_from_double (img->size.height); @@ -763,10 +836,10 @@ _cairo_ft_font_show_glyphs (void *abstract_font, &(img->image->base), surface, source_x + x + img->size.x, - source_y + y - img->size.y, + source_y + y + img->size.y, 0, 0, x + img->size.x, - y - img->size.y, + y + img->size.y, (double) img->size.width, (double) img->size.height); @@ -919,21 +992,39 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val) FT_BBox cbox; FT_Bitmap bitmap; FT_Glyph_Metrics *metrics; + ft_font_transform_t sf; glyphslot = font->val->face->glyph; metrics = &glyphslot->metrics; - _install_font_scale (&val->key.scale, font->val->face); + _cairo_ft_font_compute_transform (&sf, &val->key.scale); + _cairo_ft_font_install_transform (&sf, font->val->face); if (FT_Load_Glyph (font->val->face, val->key.index, FT_LOAD_DEFAULT) != 0) return CAIRO_STATUS_NO_MEMORY; - val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX); - val->extents.y_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingY); - val->extents.width = DOUBLE_FROM_26_6 (metrics->width); - val->extents.height = DOUBLE_FROM_26_6 (metrics->height); - val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.x); - val->extents.y_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->advance.y); + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinates of the bearing and advance need to be negated. + * + * Scale metrics back to glyph space from the scaled glyph space returned + * by FreeType + */ + + val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) / sf.x_scale; + val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / sf.y_scale; + + val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / sf.x_scale; + val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / sf.y_scale; + + /* + * use untransformed advance values + * XXX uses horizontal advance only at present; + should provide FT_LOAD_VERTICAL_LAYOUT + */ + + val->extents.x_advance = DOUBLE_FROM_26_6 (font->val->face->glyph->metrics.horiAdvance) / sf.x_scale; + val->extents.y_advance = 0 / sf.y_scale; outline = &glyphslot->outline; @@ -982,16 +1073,21 @@ _cairo_ft_font_create_glyph(cairo_image_glyph_cache_entry_t *val) _cairo_image_surface_assume_ownership_of_data (val->image); } - + + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinate of the control box needs to be negated. + */ + val->size.width = (unsigned short) width; val->size.height = (unsigned short) height; - val->size.x = (short) (cbox.xMin >> 6); - val->size.y = (short) (cbox.yMax >> 6); + val->size.x = (short) (cbox.xMin >> 6); + val->size.y = - (short) (cbox.yMax >> 6); return CAIRO_STATUS_SUCCESS; } -const struct cairo_font_backend cairo_ft_font_backend = { +const cairo_font_backend_t cairo_ft_font_backend = { _cairo_ft_font_create, _cairo_ft_font_destroy, _cairo_ft_font_font_extents, |