summaryrefslogtreecommitdiff
path: root/src/cairo-ft-font.c
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2006-02-13 16:46:47 -0800
committerCarl Worth <cworth@cworth.org>2006-02-13 16:46:47 -0800
commit0b5ac24b1522b3287903c04fb894bfae4fc67403 (patch)
treeb8256ae476f183ba07c4f4ef031d31bc31927910 /src/cairo-ft-font.c
parentdb163fcc882251188e0ce63d0b9606cb59664da0 (diff)
parent90689370267f3c02d6be62e3e8c85cccdad6f577 (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.c176
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,