summaryrefslogtreecommitdiff
path: root/src/cairo-ft-font.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r--src/cairo-ft-font.c449
1 files changed, 307 insertions, 142 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index c3e4306d7..77cf59b0d 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -25,7 +25,10 @@
#include "cairoint.h"
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
-#include <freetype/freetype.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
typedef struct {
cairo_font_t base;
@@ -39,13 +42,10 @@ typedef struct {
FcPattern *pattern;
} cairo_ft_font_t;
-
-#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)
/* implement the platform-specific interface */
@@ -101,29 +101,31 @@ cairo_ft_font_create (FT_Library ft_library, FcPattern *pattern)
}
FT_Face
-cairo_ft_font_face (cairo_font_t *font)
+cairo_ft_font_face (cairo_font_t *abstract_font)
{
+ cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
+
if (font == NULL)
return NULL;
- return ((cairo_ft_font_t *) font)->face;
+ return font->face;
}
FcPattern *
-cairo_ft_font_pattern (cairo_font_t *font)
+cairo_ft_font_pattern (cairo_font_t *abstract_font)
{
+ cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
+
if (font == NULL)
return NULL;
- return ((cairo_ft_font_t *) font)->pattern;
+ return font->pattern;
}
-
-
/* implement the backend interface */
static cairo_font_t *
-_cairo_ft_font_create (char *family,
+_cairo_ft_font_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
@@ -175,6 +177,9 @@ _cairo_ft_font_create (char *family,
}
font = cairo_ft_font_create (ft_library, pat);
+ if (font == NULL)
+ return NULL;
+
ft_font = (cairo_ft_font_t *) font;
ft_font->owns_ft_library = 1;
@@ -188,45 +193,43 @@ _cairo_ft_font_create (char *family,
return font;
}
-
static cairo_font_t *
-_cairo_ft_font_copy (cairo_font_t *font)
+_cairo_ft_font_copy (void *abstract_font)
{
- cairo_ft_font_t * ft_font_new = NULL;
- cairo_ft_font_t * ft_font = NULL;
+ cairo_ft_font_t * font_new = NULL;
+ cairo_ft_font_t * font = abstract_font;
- ft_font = (cairo_ft_font_t *)font;
+ if (font->base.backend != &cairo_ft_font_backend)
+ return NULL;
- ft_font_new = (cairo_ft_font_t *)cairo_ft_font_create_for_ft_face (ft_font->face);
- if (ft_font_new == NULL)
+ font_new = (cairo_ft_font_t *) cairo_ft_font_create_for_ft_face (font->face);
+ if (font_new == NULL)
return NULL;
- if (ft_font_new != NULL && ft_font->pattern != NULL)
- ft_font_new->pattern = FcPatternDuplicate (ft_font->pattern);
+ if (font_new != NULL && font->pattern != NULL)
+ font_new->pattern = FcPatternDuplicate (font->pattern);
- return (cairo_font_t *)ft_font_new;
+ return (cairo_font_t *) font_new;
}
static void
-_cairo_ft_font_destroy (cairo_font_t *font)
+_cairo_ft_font_destroy (void *abstract_font)
{
- cairo_ft_font_t * ft_font = NULL;
+ cairo_ft_font_t * font = abstract_font;
if (font == NULL)
return;
- ft_font = (cairo_ft_font_t *)font;
-
- if (ft_font->face != NULL && ft_font->owns_face)
- FT_Done_Face (ft_font->face);
+ if (font->face != NULL && font->owns_face)
+ FT_Done_Face (font->face);
- if (ft_font->pattern != NULL)
- FcPatternDestroy (ft_font->pattern);
+ if (font->pattern != NULL)
+ FcPatternDestroy (font->pattern);
- if (ft_font->ft_library && ft_font->owns_ft_library)
- FT_Done_FreeType (ft_font->ft_library);
+ if (font->ft_library && font->owns_ft_library)
+ FT_Done_FreeType (font->ft_library);
- free (ft_font);
+ free (font);
}
static void
@@ -260,21 +263,7 @@ _utf8_to_ucs4 (char const *utf8,
len -= step;
utf8 += step;
}
- *nchars = alloc;
-}
-
-static void
-_get_scale_factors(cairo_matrix_t *matrix, double *sx, double *sy)
-{
- double e0, e1;
- e1 = 1.; e0 = 0.;
-
- cairo_matrix_transform_distance (matrix, &e1, &e0);
- *sx = sqrt(e1*e1 + e0*e0);
-
- e1 = 1.; e0 = 0.;
- cairo_matrix_transform_distance (matrix, &e0, &e1);
- *sy = sqrt(e1*e1 + e0*e0);
+ *nchars = n;
}
static void
@@ -292,7 +281,7 @@ _install_font_matrix(cairo_matrix_t *matrix, FT_Face face)
* transformation.
*/
- _get_scale_factors(matrix, &scale_x, &scale_y);
+ _cairo_matrix_compute_scale_factors (matrix, &scale_x, &scale_y);
cairo_matrix_copy (&normalized, matrix);
@@ -314,23 +303,19 @@ _install_font_matrix(cairo_matrix_t *matrix, FT_Face face)
0, 0);
}
-
static int
-_utf8_to_glyphs (cairo_font_t *font,
- const unsigned char *utf8,
- cairo_glyph_t **glyphs,
- size_t *nglyphs)
+_utf8_to_glyphs (cairo_ft_font_t *font,
+ const unsigned char *utf8,
+ double x0,
+ double y0,
+ cairo_glyph_t **glyphs,
+ size_t *nglyphs)
{
- cairo_ft_font_t *ft;
+ FT_Face face = font->face;
double x = 0., y = 0.;
size_t i;
FT_ULong *ucs4 = NULL;
- if (font == NULL)
- return 0;
-
- ft = (cairo_ft_font_t *)font;
-
_utf8_to_ucs4 (utf8, &ucs4, nglyphs);
if (ucs4 == NULL)
@@ -343,18 +328,18 @@ _utf8_to_glyphs (cairo_font_t *font,
return 0;
}
- _install_font_matrix (&font->matrix, ft->face);
+ _install_font_matrix (&font->base.matrix, face);
for (i = 0; i < *nglyphs; i++)
{
- (*glyphs)[i].index = FT_Get_Char_Index (ft->face, ucs4[i]);
- (*glyphs)[i].x = x;
- (*glyphs)[i].y = y;
+ (*glyphs)[i].index = FT_Get_Char_Index (face, ucs4[i]);
+ (*glyphs)[i].x = x0 + x;
+ (*glyphs)[i].y = y0 + y;
- FT_Load_Glyph (ft->face, (*glyphs)[i].index, FT_LOAD_DEFAULT);
+ FT_Load_Glyph (face, (*glyphs)[i].index, FT_LOAD_DEFAULT);
- 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);
}
free (ucs4);
@@ -362,51 +347,114 @@ _utf8_to_glyphs (cairo_font_t *font,
}
static cairo_status_t
-_cairo_ft_font_font_extents (cairo_font_t *font,
- cairo_font_extents_t *extents)
+_cairo_ft_font_font_extents (void *abstract_font,
+ cairo_font_extents_t *extents)
{
+ cairo_ft_font_t *font = abstract_font;
+ FT_Face face = font->face;
double scale_x, scale_y;
- cairo_ft_font_t *ft = (cairo_ft_font_t *)font;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- _get_scale_factors(&font->matrix, &scale_x, &scale_y);
+ double upm = face->units_per_EM;
-#define FONT_UNIT_TO_DEV(x) ((double)(x) / (double)(ft->face->units_per_EM))
+ _cairo_matrix_compute_scale_factors (&font->base.matrix, &scale_x, &scale_y);
- 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;
+ extents->ascent = face->ascender / upm * scale_y;
+ extents->descent = face->descender / upm * scale_y;
+ extents->height = face->height / upm * scale_y;
+ extents->max_x_advance = face->max_advance_width / upm * scale_x;
+ extents->max_y_advance = face->max_advance_height / upm * scale_y;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_ft_font_glyph_extents (cairo_font_t *font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
+_cairo_ft_font_glyph_extents (void *abstract_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_text_extents_t *extents)
{
- cairo_ft_font_t *ft;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ int i;
+ cairo_ft_font_t *font = abstract_font;
+ cairo_point_double_t origin;
+ cairo_point_double_t glyph_min, glyph_max;
+ cairo_point_double_t total_min, total_max;
+ FT_Error error;
+ FT_Face face = font->face;
+ FT_GlyphSlot glyph = face->glyph;
+ FT_Glyph_Metrics *metrics = &glyph->metrics;
- ft = (cairo_ft_font_t *)font;
+ if (num_glyphs == 0)
+ {
+ extents->x_bearing = 0.0;
+ extents->y_bearing = 0.0;
+ extents->width = 0.0;
+ extents->height = 0.0;
+ extents->x_advance = 0.0;
+ extents->y_advance = 0.0;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
- /* FIXME: lift code from xft to do this */
+ origin.x = glyphs[0].x;
+ origin.y = glyphs[0].y;
- return status;
+ _install_font_matrix (&font->base.matrix, face);
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ error = FT_Load_Glyph (face, glyphs[i].index, FT_LOAD_DEFAULT);
+ /* XXX: What to do in this error case? */
+ if (error)
+ continue;
+
+ /* XXX: Need to add code here to check the font's FcPattern
+ for FC_VERTICAL_LAYOUT and if set get vertBearingX/Y
+ instead. This will require that
+ cairo_ft_font_create_for_ft_face accept an
+ FcPattern. */
+ glyph_min.x = glyphs[i].x + DOUBLE_FROM_26_6 (metrics->horiBearingX);
+ glyph_min.y = glyphs[i].y - DOUBLE_FROM_26_6 (metrics->horiBearingY);
+ glyph_max.x = glyph_min.x + DOUBLE_FROM_26_6 (metrics->width);
+ glyph_max.y = glyph_min.y + DOUBLE_FROM_26_6 (metrics->height);
+
+ if (i==0) {
+ total_min = glyph_min;
+ total_max = glyph_max;
+ } else {
+ if (glyph_min.x < total_min.x)
+ total_min.x = glyph_min.x;
+ if (glyph_min.y < total_min.y)
+ total_min.y = glyph_min.y;
+
+ if (glyph_max.x > total_max.x)
+ total_max.x = glyph_max.x;
+ if (glyph_max.y > total_max.y)
+ total_max.y = glyph_max.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 + DOUBLE_FROM_26_6 (metrics->horiAdvance) - origin.x;
+ extents->y_advance = glyphs[i-1].y + 0 - origin.y;
+
+ return CAIRO_STATUS_SUCCESS;
}
+
static cairo_status_t
-_cairo_ft_font_text_extents (cairo_font_t *font,
- const unsigned char *utf8,
- cairo_text_extents_t *extents)
+_cairo_ft_font_text_extents (void *abstract_font,
+ const unsigned char *utf8,
+ cairo_text_extents_t *extents)
{
+ cairo_ft_font_t *font = abstract_font;
cairo_glyph_t *glyphs;
size_t nglyphs;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- if (_utf8_to_glyphs (font, utf8, &glyphs, &nglyphs))
+ if (_utf8_to_glyphs (font, utf8, 0, 0, &glyphs, &nglyphs))
{
status = _cairo_ft_font_glyph_extents (font, glyphs, nglyphs,
extents);
@@ -414,24 +462,22 @@ _cairo_ft_font_text_extents (cairo_font_t *font,
}
return status;
}
-
-
static cairo_status_t
-_cairo_ft_font_show_glyphs (cairo_font_t *font,
+_cairo_ft_font_show_glyphs (void *abstract_font,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
- double x0,
- double y0,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
+ cairo_ft_font_t *font = abstract_font;
cairo_status_t status;
int i;
cairo_ft_font_t *ft = NULL;
FT_GlyphSlot glyphslot;
cairo_surface_t *mask = NULL;
+ cairo_point_double_t origin;
double x, y;
int width, height, stride;
@@ -444,22 +490,27 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
ft = (cairo_ft_font_t *)font;
glyphslot = ft->face->glyph;
- _install_font_matrix (&font->matrix, ft->face);
+ _install_font_matrix (&font->base.matrix, ft->face);
for (i = 0; i < num_glyphs; i++)
{
unsigned char *bitmap;
FT_Load_Glyph (ft->face, glyphs[i].index, FT_LOAD_DEFAULT);
- FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
+ FT_Render_Glyph (glyphslot, ft_render_mode_normal);
width = glyphslot->bitmap.width;
height = glyphslot->bitmap.rows;
stride = glyphslot->bitmap.pitch;
bitmap = glyphslot->bitmap.buffer;
- x = x0 + glyphs[i].x;
- y = y0 + glyphs[i].y;
+ x = glyphs[i].x;
+ y = glyphs[i].y;
+
+ if (i == 0) {
+ origin.x = x;
+ origin.y = y;
+ }
/* X gets upset with zero-sized images (such as whitespace) */
if (width * height == 0)
@@ -502,11 +553,14 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
return CAIRO_STATUS_NO_MEMORY;
}
- status = _cairo_surface_composite (operator, source, mask, surface,
- 0, 0, 0, 0,
- x + glyphslot->bitmap_left,
- y - glyphslot->bitmap_top,
- (double)width, (double)height);
+ status =
+ _cairo_surface_composite (operator, source, mask, surface,
+ -origin.x + x + glyphslot->bitmap_left,
+ -origin.y + y - glyphslot->bitmap_top,
+ 0, 0,
+ x + glyphslot->bitmap_left,
+ y - glyphslot->bitmap_top,
+ (double) width, (double) height);
cairo_surface_destroy (mask);
if (bitmap != glyphslot->bitmap.buffer)
@@ -519,7 +573,7 @@ _cairo_ft_font_show_glyphs (cairo_font_t *font,
}
static cairo_status_t
-_cairo_ft_font_show_text (cairo_font_t *font,
+_cairo_ft_font_show_text (void *abstract_font,
cairo_operator_t operator,
cairo_surface_t *source,
cairo_surface_t *surface,
@@ -527,15 +581,16 @@ _cairo_ft_font_show_text (cairo_font_t *font,
double y0,
const unsigned char *utf8)
{
+ cairo_ft_font_t *font = abstract_font;
cairo_glyph_t *glyphs;
- size_t nglyphs;
+ int num_glyphs;
- if (_utf8_to_glyphs (font, utf8, &glyphs, &nglyphs))
+ if (_utf8_to_glyphs (font, utf8, x0, y0, &glyphs, &num_glyphs))
{
cairo_status_t res;
res = _cairo_ft_font_show_glyphs (font, operator,
- source, surface, x0, y0,
- glyphs, nglyphs);
+ source, surface,
+ glyphs, num_glyphs);
free (glyphs);
return res;
}
@@ -543,35 +598,147 @@ _cairo_ft_font_show_text (cairo_font_t *font,
return CAIRO_STATUS_NO_MEMORY;
}
+static int
+_move_to (FT_Vector *to, void *closure)
+{
+ cairo_path_t *path = closure;
+ cairo_point_t point;
+
+ point.x = _cairo_fixed_from_26_6 (to->x);
+ point.y = _cairo_fixed_from_26_6 (to->y);
+
+ _cairo_path_close_path (path);
+ _cairo_path_move_to (path, &point);
+
+ return 0;
+}
+
+static int
+_line_to (FT_Vector *to, void *closure)
+{
+ cairo_path_t *path = closure;
+ cairo_point_t point;
+
+ point.x = _cairo_fixed_from_26_6 (to->x);
+ point.y = _cairo_fixed_from_26_6 (to->y);
+
+ _cairo_path_line_to (path, &point);
+
+ return 0;
+}
+
+static int
+_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
+{
+ cairo_path_t *path = closure;
+
+ cairo_point_t p0, p1, p2, p3;
+ cairo_point_t conic;
+
+ _cairo_path_current_point (path, &p0);
+
+ conic.x = _cairo_fixed_from_26_6 (control->x);
+ conic.y = _cairo_fixed_from_26_6 (control->y);
+
+ p3.x = _cairo_fixed_from_26_6 (to->x);
+ p3.y = _cairo_fixed_from_26_6 (to->y);
+
+ p1.x = p0.x + 2.0/3.0 * (conic.x - p0.x);
+ p1.y = p0.y + 2.0/3.0 * (conic.y - p0.y);
+
+ p2.x = p3.x + 2.0/3.0 * (conic.x - p3.x);
+ p2.y = p3.y + 2.0/3.0 * (conic.y - p3.y);
+
+ _cairo_path_curve_to (path,
+ &p1, &p2, &p3);
+
+ return 0;
+}
+
+static int
+_cubic_to (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *closure)
+{
+ cairo_path_t *path = closure;
+ cairo_point_t p0, p1, p2;
+
+ p0.x = _cairo_fixed_from_26_6 (control1->x);
+ p0.y = _cairo_fixed_from_26_6 (control1->y);
+
+ p1.x = _cairo_fixed_from_26_6 (control2->x);
+ p1.y = _cairo_fixed_from_26_6 (control2->y);
+
+ p2.x = _cairo_fixed_from_26_6 (to->x);
+ p2.y = _cairo_fixed_from_26_6 (to->y);
+
+ _cairo_path_curve_to (path, &p0, &p1, &p2);
+
+ return 0;
+}
static cairo_status_t
-_cairo_ft_font_glyph_path (cairo_font_t *font,
- cairo_path_t *path,
- cairo_glyph_t *glyphs,
- int num_glyphs)
+_cairo_ft_font_glyph_path (void *abstract_font,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_path_t *path)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_ft_font_t *ft;
-
- ft = (cairo_ft_font_t *)font;
-
- /* FIXME: lift code from xft to do this */
+ int i;
+ cairo_ft_font_t *font = abstract_font;
+ FT_GlyphSlot glyph;
+ FT_Error error;
+ FT_Outline_Funcs outline_funcs = {
+ _move_to,
+ _line_to,
+ _conic_to,
+ _cubic_to,
+ 0, /* shift */
+ 0, /* delta */
+ };
+
+ glyph = font->face->glyph;
+ _install_font_matrix (&font->base.matrix, font->face);
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ FT_Matrix invert_y = {
+ DOUBLE_TO_16_16 (1.0), 0,
+ 0, DOUBLE_TO_16_16 (-1.0),
+ };
+
+ error = FT_Load_Glyph (font->face, glyphs[i].index, FT_LOAD_DEFAULT);
+ /* XXX: What to do in this error case? */
+ if (error)
+ continue;
+ /* XXX: Do we want to support bitmap fonts here? */
+ if (glyph->format == ft_glyph_format_bitmap)
+ continue;
+
+ /* Font glyphs have an inverted Y axis compared to cairo. */
+ FT_Outline_Transform (&glyph->outline, &invert_y);
+ FT_Outline_Translate (&glyph->outline,
+ DOUBLE_TO_26_6(glyphs[i].x),
+ DOUBLE_TO_26_6(glyphs[i].y));
+ FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
+ }
+ _cairo_path_close_path (path);
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
-_cairo_ft_font_text_path (cairo_font_t *font,
- cairo_path_t *path,
- const unsigned char *utf8)
+_cairo_ft_font_text_path (void *abstract_font,
+ double x,
+ double y,
+ const unsigned char *utf8,
+ cairo_path_t *path)
{
+ cairo_ft_font_t *font = abstract_font;
cairo_glyph_t *glyphs;
size_t nglyphs;
- if (_utf8_to_glyphs (font, utf8, &glyphs, &nglyphs))
+ if (_utf8_to_glyphs (font, utf8, x, y, &glyphs, &nglyphs))
{
cairo_status_t res;
- res = _cairo_ft_font_glyph_path (font, path, glyphs, nglyphs);
+ res = _cairo_ft_font_glyph_path (font, glyphs, nglyphs, path);
free (glyphs);
return res;
}
@@ -579,7 +746,6 @@ _cairo_ft_font_text_path (cairo_font_t *font,
return CAIRO_STATUS_NO_MEMORY;
}
-
cairo_font_t *
cairo_ft_font_create_for_ft_face (FT_Face face)
{
@@ -602,16 +768,15 @@ cairo_ft_font_create_for_ft_face (FT_Face face)
return (cairo_font_t *) f;
}
-
const struct cairo_font_backend cairo_ft_font_backend = {
- font_extents: (void *) _cairo_ft_font_font_extents,
- text_extents: (void *) _cairo_ft_font_text_extents,
- glyph_extents: (void *) _cairo_ft_font_glyph_extents,
- show_text: (void *) _cairo_ft_font_show_text,
- show_glyphs: (void *) _cairo_ft_font_show_glyphs,
- text_path: (void *) _cairo_ft_font_text_path,
- glyph_path: (void *) _cairo_ft_font_glyph_path,
- create: (void *) _cairo_ft_font_create,
- copy: (void *) _cairo_ft_font_copy,
- destroy: (void *) _cairo_ft_font_destroy
+ _cairo_ft_font_create,
+ _cairo_ft_font_copy,
+ _cairo_ft_font_destroy,
+ _cairo_ft_font_font_extents,
+ _cairo_ft_font_text_extents,
+ _cairo_ft_font_glyph_extents,
+ _cairo_ft_font_show_text,
+ _cairo_ft_font_show_glyphs,
+ _cairo_ft_font_text_path,
+ _cairo_ft_font_glyph_path,
};