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.c1538
1 files changed, 0 insertions, 1538 deletions
diff --git a/src/cairo_ft_font.c b/src/cairo_ft_font.c
deleted file mode 100644
index 44e1b0e84..000000000
--- a/src/cairo_ft_font.c
+++ /dev/null
@@ -1,1538 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2005 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- * Graydon Hoare <graydon@redhat.com>
- * Owen Taylor <otaylor@redhat.com>
- */
-
-#include "cairo-ft-private.h"
-
-#include <fontconfig/fontconfig.h>
-#include <fontconfig/fcfreetype.h>
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_OUTLINE_H
-#include FT_IMAGE_H
-
-#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)
-
-/* This is the max number of FT_face objects we keep open at once
- */
-#define MAX_OPEN_FACES 10
-
-/*
- * 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;
-
-/*
- * We create an object that corresponds to a single font on the disk;
- * (identified by a filename/id pair) these are shared between all
- * fonts using that file. For cairo_ft_font_create_for_ft_face(), we
- * just create a one-off version with a permanent face value.
- */
-
-typedef struct {
- cairo_unscaled_font_t base;
-
- int from_face; /* from cairo_ft_font_create_for_ft_face()? */
- FT_Face face; /* provided or cached face */
-
- /* only set if from_face is false */
- FT_Library library;
- char *filename;
- int id;
-
- /* We temporarily scale the unscaled font as neede */
- int have_scale;
- cairo_font_scale_t current_scale;
- double x_scale; /* Extracted X scale factor */
- double y_scale; /* Extracted Y scale factor */
-
- int lock; /* count of how many times this font has been locked */
-} ft_unscaled_font_t;
-
-const cairo_font_backend_t cairo_ft_font_backend;
-
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_face (FT_Face face)
-{
- ft_unscaled_font_t *unscaled = malloc (sizeof(ft_unscaled_font_t));
- if (!unscaled)
- return NULL;
-
- unscaled->from_face = 1;
- unscaled->face = face;
-
- unscaled->library = NULL;
- unscaled->filename = NULL;
- unscaled->id = 0;
-
- unscaled->have_scale = 0;
- unscaled->lock = 0;
-
- _cairo_unscaled_font_init ((cairo_unscaled_font_t *)unscaled,
- &cairo_ft_font_backend);
- return unscaled;
-}
-
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_filename (FT_Library library,
- const char *filename,
- int id)
-{
- ft_unscaled_font_t *unscaled;
- char *new_filename;
-
- new_filename = strdup (filename);
- if (!new_filename)
- return NULL;
-
- unscaled = malloc (sizeof (ft_unscaled_font_t));
- if (!unscaled) {
- free (new_filename);
- return NULL;
- }
-
- unscaled->from_face = 0;
- unscaled->face = NULL;
-
- unscaled->library = library;
- unscaled->filename = new_filename;
- unscaled->id = id;
-
- unscaled->have_scale = 0;
- unscaled->lock = 0;
-
- _cairo_unscaled_font_init ((cairo_unscaled_font_t *)unscaled,
- &cairo_ft_font_backend);
- return unscaled;
-}
-
-/*
- * We keep a global cache from [file/id] => [ft_unscaled_font_t]. This
- * hash isn't limited in size. However, we limit the number of
- * FT_Face objects we keep around; when we've exceeeded that
- * limit and need to create a new FT_Face, we dump the FT_Face from
- * a random ft_unscaled_font_t.
- */
-
-typedef struct {
- cairo_cache_entry_base_t base;
- char *filename;
- int id;
-} cairo_ft_cache_key_t;
-
-typedef struct {
- cairo_ft_cache_key_t key;
- ft_unscaled_font_t *unscaled;
-} cairo_ft_cache_entry_t;
-
-typedef struct {
- cairo_cache_t base;
- FT_Library lib;
- int n_faces; /* Number of open FT_Face objects */
-} ft_cache_t;
-
-static unsigned long
-_ft_font_cache_hash (void *cache, void *key)
-{
- cairo_ft_cache_key_t *in = (cairo_ft_cache_key_t *) key;
- unsigned long hash;
-
- /* 1607 is just a random prime. */
- hash = _cairo_hash_string (in->filename);
- hash += ((unsigned long) in->id) * 1607;
-
- return hash;
-}
-
-static int
-_ft_font_cache_keys_equal (void *cache,
- void *k1,
- void *k2)
-{
- cairo_ft_cache_key_t *a;
- cairo_ft_cache_key_t *b;
- a = (cairo_ft_cache_key_t *) k1;
- b = (cairo_ft_cache_key_t *) k2;
-
- return strcmp (a->filename, b->filename) == 0 &&
- a->id == b->id;
-}
-
-static cairo_status_t
-_ft_font_cache_create_entry (void *cache,
- void *key,
- void **return_entry)
-{
- ft_cache_t *ftcache = (ft_cache_t *) cache;
- cairo_ft_cache_key_t *k = (cairo_ft_cache_key_t *) key;
- cairo_ft_cache_entry_t *entry;
-
- entry = malloc (sizeof (cairo_ft_cache_entry_t));
- if (entry == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- entry->unscaled = _ft_unscaled_font_create_from_filename (ftcache->lib,
- k->filename,
- k->id);
- if (!entry->unscaled) {
- free (entry);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- entry->key.base.memory = 0;
- entry->key.filename = entry->unscaled->filename;
- entry->key.id = entry->unscaled->id;
-
- *return_entry = entry;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Entries are never spontaneously destroyed; but only when
- * we remove them from the cache specifically. We free entry->unscaled
- * in the code that removes the entry from the cache
- */
-static void
-_ft_font_cache_destroy_entry (void *cache,
- void *entry)
-{
- cairo_ft_cache_entry_t *e = (cairo_ft_cache_entry_t *) entry;
-
- free (e);
-}
-
-static void
-_ft_font_cache_destroy_cache (void *cache)
-{
- ft_cache_t *fc = (ft_cache_t *) cache;
- FT_Done_FreeType (fc->lib);
- free (fc);
-}
-
-static const cairo_cache_backend_t _ft_font_cache_backend = {
- _ft_font_cache_hash,
- _ft_font_cache_keys_equal,
- _ft_font_cache_create_entry,
- _ft_font_cache_destroy_entry,
- _ft_font_cache_destroy_cache
-};
-
-static ft_cache_t *_global_ft_cache = NULL;
-
-static void
-_lock_global_ft_cache (void)
-{
- /* FIXME: Perform locking here. */
-}
-
-static void
-_unlock_global_ft_cache (void)
-{
- /* FIXME: Perform locking here. */
-}
-
-static cairo_cache_t *
-_get_global_ft_cache (void)
-{
- if (_global_ft_cache == NULL)
- {
- _global_ft_cache = malloc (sizeof(ft_cache_t));
- if (!_global_ft_cache)
- goto FAIL;
-
- if (_cairo_cache_init (&_global_ft_cache->base,
- &_ft_font_cache_backend,
- 0)) /* No memory limit */
- goto FAIL;
-
- if (FT_Init_FreeType (&_global_ft_cache->lib))
- goto FAIL;
- _global_ft_cache->n_faces = 0;
- }
- return &_global_ft_cache->base;
-
- FAIL:
- if (_global_ft_cache)
- free (_global_ft_cache);
- _global_ft_cache = NULL;
- return NULL;
-}
-
-/* Finds or creates a ft_unscaled_font for the filename/id from pattern.
- * Returns a new reference to the unscaled font.
- */
-static ft_unscaled_font_t *
-_ft_unscaled_font_get_for_pattern (FcPattern *pattern)
-{
- cairo_ft_cache_entry_t *entry;
- cairo_ft_cache_key_t key;
- cairo_cache_t *cache;
- cairo_status_t status;
- FcChar8 *filename;
- int created_entry;
-
- if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch)
- return NULL;
- key.filename = (char *)filename;
-
- if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
- return NULL;
-
- _lock_global_ft_cache ();
- cache = _get_global_ft_cache ();
- if (cache == NULL) {
- _unlock_global_ft_cache ();
- return NULL;
- }
-
- status = _cairo_cache_lookup (cache, &key, (void **) &entry, &created_entry);
- _unlock_global_ft_cache ();
- if (status)
- return NULL;
-
- if (!created_entry)
- _cairo_unscaled_font_reference ((cairo_unscaled_font_t *)entry->unscaled);
-
- return entry->unscaled;
-}
-
-static int
-_has_unlocked_face (void *entry)
-{
- cairo_ft_cache_entry_t *e = entry;
-
- return (e->unscaled->lock == 0 && e->unscaled->face);
-}
-
-/* Ensures that an unscaled font has a face object. If we exceed
- * MAX_OPEN_FACES, try to close some.
- */
-static FT_Face
-_ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled)
-{
- ft_cache_t *ftcache;
- FT_Face face = NULL;
-
- if (unscaled->face) {
- unscaled->lock++;
- return unscaled->face;
- }
-
- assert (!unscaled->from_face);
-
- _lock_global_ft_cache ();
- ftcache = (ft_cache_t *) _get_global_ft_cache ();
- assert (ftcache != NULL);
-
- while (ftcache->n_faces >= MAX_OPEN_FACES) {
- cairo_ft_cache_entry_t *entry;
-
- entry = _cairo_cache_random_entry ((cairo_cache_t *)ftcache, _has_unlocked_face);
- if (entry) {
- FT_Done_Face (entry->unscaled->face);
- entry->unscaled->face = NULL;
- entry->unscaled->have_scale = 0;
- ftcache->n_faces--;
- } else {
- break;
- }
- }
-
- if (FT_New_Face (ftcache->lib,
- unscaled->filename,
- unscaled->id,
- &face) != FT_Err_Ok)
- goto FAIL;
-
- unscaled->face = face;
- unscaled->lock++;
- ftcache->n_faces++;
-
- FAIL:
- _unlock_global_ft_cache ();
- return face;
-}
-
-/* Unlock unscaled font locked with _ft_unscaled_font_lock_face
- */
-static void
-_ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
-{
- assert (unscaled->lock > 0);
-
- unscaled->lock--;
-}
-
-static void
-_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);
-}
-
-/* Temporarily scales an unscaled font to the give scale. We catch
- * scaling to the same size, since changing a FT_Face is expensive.
- */
-static void
-_ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
- cairo_font_scale_t *scale)
-{
- ft_font_transform_t sf;
- FT_Matrix mat;
-
- assert (unscaled->face != NULL);
-
- if (unscaled->have_scale &&
- scale->matrix[0][0] == unscaled->current_scale.matrix[0][0] &&
- scale->matrix[0][1] == unscaled->current_scale.matrix[0][1] &&
- scale->matrix[1][0] == unscaled->current_scale.matrix[1][0] &&
- scale->matrix[1][1] == unscaled->current_scale.matrix[1][1])
- return;
-
- unscaled->have_scale = 1;
- unscaled->current_scale = *scale;
-
- _compute_transform (&sf, scale);
-
- unscaled->x_scale = sf.x_scale;
- unscaled->y_scale = sf.y_scale;
-
- 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(unscaled->face, &mat, NULL);
-
- FT_Set_Pixel_Sizes(unscaled->face,
- (FT_UInt) sf.x_scale,
- (FT_UInt) sf.y_scale);
-}
-
-/* implement the font backend interface */
-
-typedef struct {
- cairo_font_t base;
- FcPattern *pattern;
- int load_flags;
- ft_unscaled_font_t *unscaled;
-} cairo_ft_font_t;
-
-/* for compatibility with older freetype versions */
-#ifndef FT_LOAD_TARGET_MONO
-#define FT_LOAD_TARGET_MONO FT_LOAD_MONOCHROME
-#endif
-
-/* The load flags passed to FT_Load_Glyph control aspects like hinting and
- * antialiasing. Here we compute them from the fields of a FcPattern.
- */
-static int
-_get_load_flags (FcPattern *pattern)
-{
- FcBool antialias, hinting, autohint;
-#ifdef FC_HINT_STYLE
- int hintstyle;
-#endif
- int load_flags = 0;
-
- /* disable antialiasing if requested */
- if (FcPatternGetBool (pattern,
- FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
- antialias = FcTrue;
-
- if (antialias)
- load_flags |= FT_LOAD_NO_BITMAP;
- else
- load_flags |= FT_LOAD_TARGET_MONO;
-
- /* disable hinting if requested */
- if (FcPatternGetBool (pattern,
- FC_HINTING, 0, &hinting) != FcResultMatch)
- hinting = FcTrue;
-
-#ifdef FC_HINT_STYLE
- if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
- hintstyle = FC_HINT_FULL;
-
- if (!hinting || hintstyle == FC_HINT_NONE)
- load_flags |= FT_LOAD_NO_HINTING;
-
- switch (hintstyle) {
- case FC_HINT_SLIGHT:
- case FC_HINT_MEDIUM:
- load_flags |= FT_LOAD_TARGET_LIGHT;
- break;
- default:
- load_flags |= FT_LOAD_TARGET_NORMAL;
- break;
- }
-#else /* !FC_HINT_STYLE */
- if (!hinting)
- load_flags |= FT_LOAD_NO_HINTING;
-#endif /* FC_FHINT_STYLE */
-
- /* force autohinting if requested */
- if (FcPatternGetBool (pattern,
- FC_AUTOHINT, 0, &autohint) != FcResultMatch)
- autohint = FcFalse;
-
- if (autohint)
- load_flags |= FT_LOAD_FORCE_AUTOHINT;
-
- return load_flags;
-}
-
-/* Like the public cairo_ft_font_create, but takes a cairo_font_scale_t,
- * rather than a cairo_font_t
- */
-static cairo_font_t *
-_ft_font_create (FcPattern *pattern,
- cairo_font_scale_t *scale)
-{
- cairo_ft_font_t *f = NULL;
- ft_unscaled_font_t *unscaled = NULL;
-
- unscaled = _ft_unscaled_font_get_for_pattern (pattern);
- if (unscaled == NULL)
- return NULL;
-
- f = malloc (sizeof(cairo_ft_font_t));
- if (f == NULL)
- goto FREE_UNSCALED;
-
- f->unscaled = unscaled;
- f->pattern = pattern;
- FcPatternReference (pattern);
- f->load_flags = _get_load_flags (pattern);
-
- _cairo_font_init ((cairo_font_t *)f, scale, &cairo_ft_font_backend);
-
- return (cairo_font_t *)f;
-
- FREE_UNSCALED:
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)unscaled);
-
- return NULL;
-}
-
-static cairo_status_t
-_cairo_ft_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- cairo_font_scale_t *scale,
- cairo_font_t **font)
-{
- FcPattern *pattern, *resolved;
- cairo_font_t *new_font;
- FcResult result;
- int fcslant;
- int fcweight;
- ft_font_transform_t sf;
-
- pattern = FcPatternCreate ();
- if (!pattern)
- return CAIRO_STATUS_NO_MEMORY;
-
- switch (weight)
- {
- case CAIRO_FONT_WEIGHT_BOLD:
- fcweight = FC_WEIGHT_BOLD;
- break;
- case CAIRO_FONT_WEIGHT_NORMAL:
- default:
- fcweight = FC_WEIGHT_MEDIUM;
- break;
- }
-
- switch (slant)
- {
- case CAIRO_FONT_SLANT_ITALIC:
- fcslant = FC_SLANT_ITALIC;
- break;
- case CAIRO_FONT_SLANT_OBLIQUE:
- fcslant = FC_SLANT_OBLIQUE;
- break;
- case CAIRO_FONT_SLANT_NORMAL:
- default:
- fcslant = FC_SLANT_ROMAN;
- break;
- }
-
- if (!FcPatternAddString (pattern, FC_FAMILY, family))
- goto FREE_PATTERN;
- if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant))
- goto FREE_PATTERN;
- if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight))
- goto FREE_PATTERN;
-
- _compute_transform (&sf, scale);
-
- FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale);
-
- FcConfigSubstitute (NULL, pattern, FcMatchPattern);
- FcDefaultSubstitute (pattern);
-
- resolved = FcFontMatch (NULL, pattern, &result);
- if (!resolved)
- goto FREE_PATTERN;
-
- new_font = _ft_font_create (resolved, scale);
-
- FcPatternDestroy (resolved);
- FcPatternDestroy (pattern);
-
- if (new_font) {
- *font = new_font;
- return CAIRO_STATUS_SUCCESS;
- } else {
- return CAIRO_STATUS_NO_MEMORY; /* A guess */
- }
-
- FREE_PATTERN:
- FcPatternDestroy (pattern);
-
- return CAIRO_STATUS_NO_MEMORY;
-}
-
-static void
-_cairo_ft_font_destroy_font (void *abstract_font)
-{
- cairo_ft_font_t * font = abstract_font;
-
- if (font == NULL)
- return;
-
- if (font->pattern != NULL)
- FcPatternDestroy (font->pattern);
-
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)font->unscaled);
-
- free (font);
-}
-
-static void
-_cairo_ft_font_destroy_unscaled_font (void *abstract_font)
-{
- ft_unscaled_font_t *unscaled = abstract_font;
-
- if (!unscaled->from_face) {
- cairo_cache_t *cache;
- cairo_ft_cache_key_t key;
-
- _lock_global_ft_cache ();
- cache = _get_global_ft_cache ();
- assert (cache);
-
- key.filename = unscaled->filename;
- key.id = unscaled->id;
-
- _cairo_cache_remove (cache, &key);
-
- _unlock_global_ft_cache ();
- }
-
- if (unscaled == NULL)
- return;
-
- if (!unscaled->from_face && unscaled->face)
- FT_Done_Face (unscaled->face);
-
- if (unscaled->filename)
- free (unscaled->filename);
-
- free (unscaled);
-}
-
-static void
-_cairo_ft_font_get_glyph_cache_key (void *abstract_font,
- cairo_glyph_cache_key_t *key)
-{
- cairo_ft_font_t *font = abstract_font;
-
- key->unscaled = (cairo_unscaled_font_t *)font->unscaled;
- key->scale = font->base.scale;
- key->flags = font->load_flags;
-}
-
-static cairo_status_t
-_cairo_ft_font_text_to_glyphs (void *abstract_font,
- const unsigned char *utf8,
- cairo_glyph_t **glyphs,
- int *nglyphs)
-{
- double x = 0., y = 0.;
- size_t i;
- uint32_t *ucs4 = NULL;
- cairo_ft_font_t *font = abstract_font;
- FT_Face face;
- cairo_glyph_cache_key_t key;
- cairo_image_glyph_cache_entry_t *val;
- cairo_cache_t *cache = NULL;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- _cairo_ft_font_get_glyph_cache_key (font, &key);
-
- status = _cairo_utf8_to_ucs4 (utf8, -1, &ucs4, nglyphs);
- if (!CAIRO_OK (status))
- return status;
-
- face = cairo_ft_font_lock_face ((cairo_font_t *)font);
- if (!face) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL1;
- }
-
- _cairo_lock_global_image_glyph_cache ();
- cache = _cairo_get_global_image_glyph_cache ();
- if (cache == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL2;
- }
-
- *glyphs = (cairo_glyph_t *) malloc ((*nglyphs) * (sizeof (cairo_glyph_t)));
- if (*glyphs == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL2;
- }
-
- for (i = 0; i < *nglyphs; i++)
- {
- (*glyphs)[i].index = FT_Get_Char_Index (face, ucs4[i]);
- (*glyphs)[i].x = x;
- (*glyphs)[i].y = y;
-
- val = NULL;
- key.index = (*glyphs)[i].index;
-
- if (_cairo_cache_lookup (cache, &key, (void **) &val, NULL)
- != CAIRO_STATUS_SUCCESS || val == NULL)
- continue;
-
- x += val->extents.x_advance;
- y += val->extents.y_advance;
- }
-
- FAIL2:
- if (cache)
- _cairo_unlock_global_image_glyph_cache ();
-
- cairo_ft_font_unlock_face ((cairo_font_t *)font);
-
- FAIL1:
- free (ucs4);
-
- return status;
-}
-
-
-static cairo_status_t
-_cairo_ft_font_font_extents (void *abstract_font,
- cairo_font_extents_t *extents)
-{
- cairo_ft_font_t *font = abstract_font;
- FT_Face face;
- FT_Size_Metrics *metrics;
-
- face = _ft_unscaled_font_lock_face (font->unscaled);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
-
- metrics = &face->size->metrics;
-
- _ft_unscaled_font_set_scale (font->unscaled, &font->base.scale);
-
- /*
- * Get to unscaled metrics so that the upper level can get back to
- * user space
- */
- extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) / font->unscaled->y_scale;
- extents->descent = DOUBLE_FROM_26_6(metrics->descender) / font->unscaled->y_scale;
- extents->height = DOUBLE_FROM_26_6(metrics->height) / font->unscaled->y_scale;
- extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) / font->unscaled->x_scale;
-
- /* FIXME: this doesn't do vertical layout atm. */
- extents->max_y_advance = 0.0;
-
- _ft_unscaled_font_unlock_face (font->unscaled);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_ft_font_glyph_extents (void *abstract_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_text_extents_t *extents)
-{
- 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;
-
- cairo_image_glyph_cache_entry_t *img = NULL;
- cairo_cache_t *cache;
- cairo_glyph_cache_key_t key;
-
- 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;
- }
-
- origin.x = glyphs[0].x;
- origin.y = glyphs[0].y;
-
- _cairo_lock_global_image_glyph_cache ();
- cache = _cairo_get_global_image_glyph_cache ();
- if (cache == NULL) {
- _cairo_unlock_global_image_glyph_cache ();
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- _cairo_ft_font_get_glyph_cache_key (font, &key);
-
- for (i = 0; i < num_glyphs; i++)
- {
- img = NULL;
- key.index = glyphs[i].index;
- if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL)
- != CAIRO_STATUS_SUCCESS || img == NULL)
- 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 + img->extents.x_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;
-
- 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;
- }
- }
- _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_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x;
- extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-static cairo_status_t
-_cairo_ft_font_glyph_bbox (void *abstract_font,
- const cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_box_t *bbox)
-{
- cairo_image_glyph_cache_entry_t *img;
- cairo_cache_t *cache;
- cairo_glyph_cache_key_t key;
- cairo_ft_font_t *font = abstract_font;
-
- cairo_fixed_t x1, y1, x2, y2;
- int i;
-
- bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
- bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
-
- _cairo_lock_global_image_glyph_cache ();
- cache = _cairo_get_global_image_glyph_cache();
-
- if (cache == NULL
- || font == NULL
- || glyphs == NULL) {
- _cairo_unlock_global_image_glyph_cache ();
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- _cairo_ft_font_get_glyph_cache_key (font, &key);
-
- for (i = 0; i < num_glyphs; i++)
- {
-
- img = NULL;
- key.index = glyphs[i].index;
-
- if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL)
- != CAIRO_STATUS_SUCCESS || img == NULL)
- continue;
-
- x1 = _cairo_fixed_from_double (glyphs[i].x + img->size.x);
- 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);
-
- if (x1 < bbox->p1.x)
- bbox->p1.x = x1;
-
- if (y1 < bbox->p1.y)
- bbox->p1.y = y1;
-
- if (x2 > bbox->p2.x)
- bbox->p2.x = x2;
-
- if (y2 > bbox->p2.y)
- bbox->p2.y = y2;
- }
- _cairo_unlock_global_image_glyph_cache ();
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-static cairo_status_t
-_cairo_ft_font_show_glyphs (void *abstract_font,
- cairo_operator_t operator,
- cairo_pattern_t *pattern,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- int dest_x,
- int dest_y,
- unsigned int width,
- unsigned int height,
- const cairo_glyph_t *glyphs,
- int num_glyphs)
-{
- cairo_image_glyph_cache_entry_t *img;
- cairo_cache_t *cache;
- cairo_glyph_cache_key_t key;
- cairo_ft_font_t *font = abstract_font;
- cairo_surface_pattern_t glyph_pattern;
- cairo_status_t status;
- int x, y;
- int i;
-
- _cairo_lock_global_image_glyph_cache ();
- cache = _cairo_get_global_image_glyph_cache();
-
- if (cache == NULL
- || font == NULL
- || pattern == NULL
- || surface == NULL
- || glyphs == NULL) {
- _cairo_unlock_global_image_glyph_cache ();
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- key.unscaled = (cairo_unscaled_font_t *)font->unscaled;
- key.scale = font->base.scale;
- key.flags = font->load_flags;
-
- for (i = 0; i < num_glyphs; i++)
- {
- img = NULL;
- key.index = glyphs[i].index;
-
- if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL)
- != CAIRO_STATUS_SUCCESS
- || img == NULL
- || img->image == NULL)
- continue;
-
- x = (int) floor (glyphs[i].x + 0.5);
- y = (int) floor (glyphs[i].y + 0.5);
-
- _cairo_pattern_init_for_surface (&glyph_pattern, &(img->image->base));
-
- status = _cairo_surface_composite (operator, pattern,
- &glyph_pattern.base,
- surface,
- x + img->size.x,
- y + img->size.y,
- 0, 0,
- x + img->size.x,
- y + img->size.y,
- (double) img->size.width,
- (double) img->size.height);
-
- _cairo_pattern_fini (&glyph_pattern.base);
-
- if (status) {
- _cairo_unlock_global_image_glyph_cache ();
- return status;
- }
- }
-
- _cairo_unlock_global_image_glyph_cache ();
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-
-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 (void *abstract_font,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_path_t *path)
-{
- int i;
- cairo_ft_font_t *font = abstract_font;
- FT_GlyphSlot glyph;
- FT_Face face;
- FT_Error error;
- FT_Outline_Funcs outline_funcs = {
- _move_to,
- _line_to,
- _conic_to,
- _cubic_to,
- 0, /* shift */
- 0, /* delta */
- };
-
- face = cairo_ft_font_lock_face (abstract_font);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
-
- glyph = face->glyph;
-
- 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->unscaled->face, glyphs[i].index, font->load_flags | FT_LOAD_NO_BITMAP);
- /* 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);
-
- cairo_ft_font_unlock_face (abstract_font);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_ft_font_create_glyph (cairo_image_glyph_cache_entry_t *val)
-{
- ft_unscaled_font_t *unscaled = (ft_unscaled_font_t *)val->key.unscaled;
- FT_GlyphSlot glyphslot;
- unsigned int width, height, stride;
- FT_Face face;
- FT_Outline *outline;
- FT_BBox cbox;
- FT_Bitmap bitmap;
- FT_Glyph_Metrics *metrics;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- glyphslot = unscaled->face->glyph;
- metrics = &glyphslot->metrics;
-
- face = _ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
-
- _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
-
- if (FT_Load_Glyph (face, val->key.index, val->key.flags) != 0) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- /*
- * 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) / unscaled->x_scale;
- val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) / unscaled->y_scale;
-
- val->extents.width = DOUBLE_FROM_26_6 (metrics->width) / unscaled->x_scale;
- val->extents.height = DOUBLE_FROM_26_6 (metrics->height) / unscaled->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 (face->glyph->metrics.horiAdvance) / unscaled->x_scale;
- val->extents.y_advance = 0 / unscaled->y_scale;
-
- outline = &glyphslot->outline;
-
- FT_Outline_Get_CBox (outline, &cbox);
-
- cbox.xMin &= -64;
- cbox.yMin &= -64;
- cbox.xMax = (cbox.xMax + 63) & -64;
- cbox.yMax = (cbox.yMax + 63) & -64;
-
- width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
- height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
- stride = (width + 3) & -4;
-
- if (width * height == 0)
- val->image = NULL;
- else
- {
-
- bitmap.pixel_mode = ft_pixel_mode_grays;
- bitmap.num_grays = 256;
- bitmap.width = width;
- bitmap.rows = height;
- bitmap.pitch = stride;
- bitmap.buffer = calloc (1, stride * height);
-
- if (bitmap.buffer == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
-
- if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
- free (bitmap.buffer);
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- val->image = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data ((char *) bitmap.buffer,
- CAIRO_FORMAT_A8,
- width, height, stride);
- if (val->image == NULL) {
- free (bitmap.buffer);
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- _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);
-
- FAIL:
- _ft_unscaled_font_unlock_face (unscaled);
-
- return status;
-}
-
-const cairo_font_backend_t cairo_ft_font_backend = {
- _cairo_ft_font_create,
- _cairo_ft_font_destroy_font,
- _cairo_ft_font_destroy_unscaled_font,
- _cairo_ft_font_font_extents,
- _cairo_ft_font_text_to_glyphs,
- _cairo_ft_font_glyph_extents,
- _cairo_ft_font_glyph_bbox,
- _cairo_ft_font_show_glyphs,
- _cairo_ft_font_glyph_path,
- _cairo_ft_font_get_glyph_cache_key,
- _cairo_ft_font_create_glyph
-};
-
-/* implement the platform-specific interface */
-
-/**
- * cairo_ft_font_create:
- * @pattern: A fully resolved fontconfig
- * pattern. A pattern can be resolved, by, among other things, calling
- * FcConfigSubstitute(), FcDefaultSubstitute(), then
- * FcFontMatch(). Cairo will call FcPatternReference() on this
- * pattern, so you should not further modify the pattern, but you can
- * release your reference to the pattern with FcPatternDestroy() if
- * you no longer need to access it.
- * @scale: The scale at which this font will be used. The
- * scale is given by multiplying the font matrix (see
- * cairo_transform_font()) by the current transformation matrix.
- * The translation elements of the resulting matrix are ignored.
- *
- * Creates a new font for the FreeType font backend based on a
- * fontconfig pattern. This font can then be used with
- * cairo_set_font(), cairo_font_glyph_extents(), or FreeType backend
- * specific functions like cairo_ft_font_lock_face().
- *
- * Return value: a newly created #cairo_font_t. Free with
- * cairo_font_destroy() when you are done using it.
- **/
-cairo_font_t *
-cairo_ft_font_create (FcPattern *pattern,
- cairo_matrix_t *scale)
-{
- cairo_font_scale_t sc;
- double tx, ty;
-
- cairo_matrix_get_affine (scale,
- &sc.matrix[0][0], &sc.matrix[0][1],
- &sc.matrix[1][0], &sc.matrix[1][1],
- &tx, &ty);
-
- return _ft_font_create (pattern, &sc);
-}
-
-/**
- * cairo_ft_font_create_for_ft_face:
- * @face: A FreeType face object, already opened. This must
- * be kept around until the font object's refcount drops to
- * zero and it is freed. The font object can be kept alive by
- * internal caching, so it's safest to keep the face object
- * around forever.
- * @load_flags: The flags to pass to FT_Load_Glyph when loading
- * glyphs from the font. These flags control aspects of
- * rendering such as hinting and antialiasing. See the FreeType
- * docs for full information.
- * @scale: The scale at which this font will be used. The
- * scale is given by multiplying the font matrix (see
- * cairo_transform_font()) by the current transformation matrix.
- * The translation elements of the resulting matrix are ignored.
- *
- * Creates a new font forthe FreeType font backend from a pre-opened
- * FreeType face. This font can then be used with cairo_set_font(),
- * cairo_font_glyph_extents(), or FreeType backend specific
- * functions like cairo_ft_font_lock_face() Cairo will determine the
- * pixel size and transformation from the @scale parameter and call
- * FT_Set_Transform() and FT_Set_Pixel_Sizes().
- *
- * Return value: a newly created #cairo_font_t. Free with
- * cairo_font_destroy() when you are done using it.
- **/
-cairo_font_t *
-cairo_ft_font_create_for_ft_face (FT_Face face,
- int load_flags,
- cairo_matrix_t *scale)
-{
- cairo_ft_font_t *f = NULL;
- ft_unscaled_font_t *unscaled = NULL;
- cairo_font_scale_t sc;
- double tx, ty;
-
- unscaled = _ft_unscaled_font_create_from_face (face);
- if (unscaled == NULL)
- return NULL;
-
- f = malloc (sizeof(cairo_ft_font_t));
- if (f == NULL)
- goto FREE_UNSCALED;
-
- f->unscaled = unscaled;
- f->pattern = NULL;
- f->load_flags = load_flags;
-
- cairo_matrix_get_affine (scale,
- &sc.matrix[0][0], &sc.matrix[0][1],
- &sc.matrix[1][0], &sc.matrix[1][1],
- &tx, &ty);
-
- _cairo_font_init ((cairo_font_t *)f, &sc, &cairo_ft_font_backend);
-
- return (cairo_font_t *)f;
-
- FREE_UNSCALED:
- _cairo_unscaled_font_destroy ((cairo_unscaled_font_t *)unscaled);
-
- return NULL;
-}
-
-
-/**
- * cairo_ft_font_lock_face:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
- *
- * cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
- * backend font and scales it appropriately for the font. You must
- * release the face with cairo_ft_font_unlock_face()
- * when you are done using it. Since the #FT_Face object can be
- * shared between multiple #cairo_font_t objects, you must not
- * lock any other font objects until you unlock this one. A count is
- * kept of the number of times cairo_ft_font_lock_face() is
- * called. cairo_ft_font_unlock_face() must be called the same number
- * of times.
- *
- * You must be careful when using this function in a library or in a
- * threaded application, because other threads may lock faces that
- * share the same #FT_Face object. For this reason, you must call
- * cairo_ft_lock() before locking any face objects, and
- * cairo_ft_unlock() after you are done. (These functions are not yet
- * implemented, so this function cannot be currently safely used in a
- * threaded application.)
-
- * Return value: The #FT_Face object for @font, scaled appropriately.
- **/
-FT_Face
-cairo_ft_font_lock_face (cairo_font_t *abstract_font)
-{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
- FT_Face face;
-
- face = _ft_unscaled_font_lock_face (font->unscaled);
- if (!face)
- return NULL;
-
- _ft_unscaled_font_set_scale (font->unscaled, &font->base.scale);
-
- return face;
-}
-
-/**
- * cairo_ft_font_unlock_face:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
- *
- * Releases a face obtained with cairo_ft_font_lock_face(). See the
- * documentation for that function for full details.
- **/
-void
-cairo_ft_font_unlock_face (cairo_font_t *abstract_font)
-{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
-
- _ft_unscaled_font_unlock_face (font->unscaled);
-}
-
-/**
- * cairo_ft_font_get_pattern:
- * @ft_font: A #cairo_font_t from the FreeType font backend. Such an
- * object can be created with cairo_ft_font_create() or
- * cairo_ft_font_create_for_ft_face(). On some platforms the font from
- * cairo_current_font() will also be a FreeType font, but using this
- * functionality with fonts you don't create yourself is not
- * recommended.
- *
- * cairo_ft_font_get_pattern() gets the #FcPattern for a FreeType
- * backend font.
-
- * Return value: The #FcPattenr for @font. The return value is owned
- * by the font, so you must not modify it, and must call
- * FcPatternReference() to keep a persistant reference to the
- * pattern. If the font was created with cairo_ft_font_create_for_ft_face()
- * returns %NULL.
- **/
-FcPattern *
-cairo_ft_font_get_pattern (cairo_font_t *abstract_font)
-{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
-
- if (font == NULL)
- return NULL;
-
- return font->pattern;
-}
-
-/* We expose our unscaled font implementation internally for the the
- * PDF backend, which needs to keep track of the the different
- * fonts-on-disk used by a document, so it can embed them.
- */
-cairo_unscaled_font_t *
-_cairo_ft_font_get_unscaled_font (cairo_font_t *abstract_font)
-{
- cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font;
-
- return (cairo_unscaled_font_t *)font->unscaled;
-}
-
-/* This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
- * set the scale on the face, but just returns it at the last scale.
- */
-FT_Face
-_cairo_ft_unscaled_font_lock_face (cairo_unscaled_font_t *unscaled_font)
-{
- return _ft_unscaled_font_lock_face ((ft_unscaled_font_t *)unscaled_font);
-}
-
-void
-_cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font)
-{
- _ft_unscaled_font_unlock_face ((ft_unscaled_font_t *)unscaled_font);
-}