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.c526
1 files changed, 329 insertions, 197 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index afe80dff..36a0c674 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -76,31 +76,31 @@
* factors so that hinting works right
*/
-typedef struct {
+typedef struct _cairo_ft_font_transform {
double x_scale, y_scale;
double shape[2][2];
-} ft_font_transform_t;
+} cairo_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_scaled_font_create_for_ft_face(), we
+ * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
* just create a one-off version with a permanent face value.
*/
-typedef struct _ft_font_face ft_font_face_t;
+typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
-typedef struct {
+struct _cairo_ft_unscaled_font {
cairo_unscaled_font_t base;
- cairo_bool_t from_face; /* from cairo_ft_scaled_font_create_for_ft_face()? */
+ cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
FT_Face face; /* provided or cached face */
/* only set if from_face is false */
char *filename;
int id;
- /* We temporarily scale the unscaled font as neede */
+ /* We temporarily scale the unscaled font as needed */
cairo_bool_t have_scale;
cairo_matrix_t current_scale;
double x_scale; /* Extracted X scale factor */
@@ -109,38 +109,91 @@ typedef struct {
int lock; /* count of how many times this font has been locked */
- ft_font_face_t *faces; /* Linked list of faces for this font */
-} ft_unscaled_font_t;
+ cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
+};
-struct _ft_font_face {
+struct _cairo_ft_font_face {
cairo_font_face_t base;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
int load_flags;
- ft_font_face_t *next_face;
+ cairo_ft_font_face_t *next;
};
const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_face (FT_Face face)
+/**
+ * _cairo_ft_unscaled_font_init:
+ *
+ * Initialize a cairo_ft_unscaled_font_t.
+ *
+ * There are two basic flavors of cairo_ft_unscaled_font_t, one
+ * created from an FT_Face and the other created from a filename/id
+ * pair. These two flavors are identified as from_face and !from_face.
+ *
+ * To initialize a from_face font, pass filename==NULL, id=0 and the
+ * desired face.
+ *
+ * To initialize a !from_face font, pass the filename/id as desired
+ * and face==NULL.
+ *
+ * Note that the code handles these two flavors in very distinct
+ * ways. For example there is a hash_table mapping
+ * filename/id->cairo_unscaled_font_t in the !from_face case, but no
+ * parallel in the from_face case, (where the calling code would have
+ * to do its own mapping to ensure similar sharing).
+ **/
+static cairo_status_t
+_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
+ const char *filename,
+ int id,
+ 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;
+ char *filename_copy = NULL;
+
+ if (filename) {
+ filename_copy = strdup (filename);
+ if (filename_copy == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ unscaled->filename = filename_copy;
+ unscaled->id = id;
+
+ if (face) {
+ unscaled->from_face = 1;
+ unscaled->face = face;
+ } else {
+ unscaled->from_face = 0;
+ unscaled->face = NULL;
+ }
- unscaled->filename = NULL;
- unscaled->id = 0;
-
unscaled->have_scale = 0;
unscaled->lock = 0;
-
+
unscaled->faces = NULL;
_cairo_unscaled_font_init (&unscaled->base,
&cairo_ft_unscaled_font_backend);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_from_face (FT_Face face)
+{
+ cairo_status_t status;
+ cairo_ft_unscaled_font_t *unscaled;
+
+ unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
+ if (unscaled == NULL)
+ return NULL;
+
+ status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
+ if (status) {
+ free (unscaled);
+ return NULL;
+ }
+
return unscaled;
}
@@ -150,36 +203,23 @@ _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
}
-static ft_unscaled_font_t *
-_ft_unscaled_font_create_from_filename (const char *filename,
- int id)
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_from_filename (const char *filename,
+ int id)
{
- ft_unscaled_font_t *unscaled;
- char *new_filename;
+ cairo_status_t status;
+ cairo_ft_unscaled_font_t *unscaled;
- new_filename = strdup (filename);
- if (!new_filename)
+ unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
+ if (unscaled == NULL)
return NULL;
- unscaled = malloc (sizeof (ft_unscaled_font_t));
- if (!unscaled) {
- free (new_filename);
+ status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
+ if (status) {
+ free (unscaled);
return NULL;
}
-
- unscaled->from_face = 0;
- unscaled->face = NULL;
-
- unscaled->filename = new_filename;
- unscaled->id = id;
-
- unscaled->have_scale = 0;
- unscaled->lock = 0;
-
- unscaled->faces = NULL;
- _cairo_unscaled_font_init (&unscaled->base,
- &cairo_ft_unscaled_font_backend);
return unscaled;
}
@@ -199,7 +239,7 @@ typedef struct {
typedef struct {
cairo_ft_cache_key_t key;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
} cairo_ft_cache_entry_t;
typedef struct {
@@ -209,7 +249,7 @@ typedef struct {
} ft_cache_t;
static unsigned long
-_ft_font_cache_hash (void *cache, void *key)
+_cairo_ft_font_cache_hash (void *cache, void *key)
{
cairo_ft_cache_key_t *in = (cairo_ft_cache_key_t *) key;
unsigned long hash;
@@ -222,9 +262,9 @@ _ft_font_cache_hash (void *cache, void *key)
}
static int
-_ft_font_cache_keys_equal (void *cache,
- void *k1,
- void *k2)
+_cairo_ft_font_cache_keys_equal (void *cache,
+ void *k1,
+ void *k2)
{
cairo_ft_cache_key_t *a;
cairo_ft_cache_key_t *b;
@@ -236,9 +276,9 @@ _ft_font_cache_keys_equal (void *cache,
}
static cairo_status_t
-_ft_font_cache_create_entry (void *cache,
- void *key,
- void **return_entry)
+_cairo_ft_font_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
{
cairo_ft_cache_key_t *k = key;
cairo_ft_cache_entry_t *entry;
@@ -247,8 +287,8 @@ _ft_font_cache_create_entry (void *cache,
if (entry == NULL)
return CAIRO_STATUS_NO_MEMORY;
- entry->unscaled = _ft_unscaled_font_create_from_filename (k->filename,
- k->id);
+ entry->unscaled = _cairo_ft_unscaled_font_create_from_filename (k->filename,
+ k->id);
if (!entry->unscaled) {
free (entry);
return CAIRO_STATUS_NO_MEMORY;
@@ -268,8 +308,8 @@ _ft_font_cache_create_entry (void *cache,
* in the code that removes the entry from the cache
*/
static void
-_ft_font_cache_destroy_entry (void *cache,
- void *entry)
+_cairo_ft_font_cache_destroy_entry (void *cache,
+ void *entry)
{
cairo_ft_cache_entry_t *e = (cairo_ft_cache_entry_t *) entry;
@@ -277,7 +317,7 @@ _ft_font_cache_destroy_entry (void *cache,
}
static void
-_ft_font_cache_destroy_cache (void *cache)
+_cairo_ft_font_cache_destroy_cache (void *cache)
{
ft_cache_t *fc = (ft_cache_t *) cache;
@@ -286,11 +326,11 @@ _ft_font_cache_destroy_cache (void *cache)
}
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
+ _cairo_ft_font_cache_hash,
+ _cairo_ft_font_cache_keys_equal,
+ _cairo_ft_font_cache_create_entry,
+ _cairo_ft_font_cache_destroy_entry,
+ _cairo_ft_font_cache_destroy_cache
};
static ft_cache_t *_global_ft_cache = NULL;
@@ -339,8 +379,8 @@ _get_global_ft_cache (void)
/* 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)
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_get_for_pattern (FcPattern *pattern)
{
cairo_ft_cache_entry_t *entry;
cairo_ft_cache_key_t key;
@@ -384,9 +424,12 @@ _has_unlocked_face (void *entry)
/* Ensures that an unscaled font has a face object. If we exceed
* MAX_OPEN_FACES, try to close some.
+ *
+ * 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.
*/
-static FT_Face
-_ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled)
+FT_Face
+_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
{
ft_cache_t *ftcache;
FT_Face face = NULL;
@@ -433,8 +476,8 @@ _ft_unscaled_font_lock_face (ft_unscaled_font_t *unscaled)
/* Unlock unscaled font locked with _ft_unscaled_font_lock_face
*/
-static void
-_ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
+void
+_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
{
assert (unscaled->lock > 0);
@@ -442,7 +485,7 @@ _ft_unscaled_font_unlock_face (ft_unscaled_font_t *unscaled)
}
static void
-_compute_transform (ft_font_transform_t *sf,
+_compute_transform (cairo_ft_font_transform_t *sf,
cairo_matrix_t *scale)
{
cairo_matrix_t normalized = *scale;
@@ -476,10 +519,10 @@ _compute_transform (ft_font_transform_t *sf,
* 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_matrix_t *scale)
+_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
+ cairo_matrix_t *scale)
{
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
FT_Matrix mat;
FT_UInt pixel_width, pixel_height;
FT_Error error;
@@ -528,7 +571,11 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
pixel_width = pixel_height = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
double size = unscaled->face->available_sizes[i].y_ppem / 64.;
+#else
+ double size = unscaled->face->available_sizes[i].height;
+#endif
double distance = fabs (size - sf.y_scale);
if (distance <= min_distance) {
@@ -536,11 +583,13 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
best_i = i;
}
}
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
error = FT_Set_Char_Size (unscaled->face,
unscaled->face->available_sizes[best_i].x_ppem,
unscaled->face->available_sizes[best_i].y_ppem,
0, 0);
- if (error )
+ if (error)
+#endif
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
@@ -552,7 +601,7 @@ _ft_unscaled_font_set_scale (ft_unscaled_font_t *unscaled,
static void
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
- ft_unscaled_font_t *unscaled = abstract_font;
+ cairo_ft_unscaled_font_t *unscaled = abstract_font;
if (unscaled == NULL)
return;
@@ -990,7 +1039,7 @@ _render_glyph_bitmap (FT_Face face,
static cairo_status_t
_transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val)
{
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
cairo_matrix_t original_to_transformed;
cairo_matrix_t transformed_to_original;
cairo_image_surface_t *old_image;
@@ -1110,21 +1159,21 @@ static cairo_status_t
_cairo_ft_unscaled_font_create_glyph (void *abstract_font,
cairo_image_glyph_cache_entry_t *val)
{
- ft_unscaled_font_t *unscaled = abstract_font;
+ cairo_ft_unscaled_font_t *unscaled = abstract_font;
FT_GlyphSlot glyphslot;
FT_Face face;
FT_Glyph_Metrics *metrics;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
double x_factor, y_factor;
- face = _ft_unscaled_font_lock_face (unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
glyphslot = face->glyph;
metrics = &glyphslot->metrics;
- _ft_unscaled_font_set_scale (unscaled, &val->key.scale);
+ _cairo_ft_unscaled_font_set_scale (unscaled, &val->key.scale);
if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) {
status = CAIRO_STATUS_NO_MEMORY;
@@ -1203,7 +1252,7 @@ _cairo_ft_unscaled_font_create_glyph (void *abstract_
val->image = NULL;
}
- _ft_unscaled_font_unlock_face (unscaled);
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
return status;
}
@@ -1215,11 +1264,10 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
/* cairo_ft_scaled_font_t */
-typedef struct {
+typedef struct _cairo_ft_scaled_font {
cairo_scaled_font_t base;
int load_flags;
- cairo_font_options_t options;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
} cairo_ft_scaled_font_t;
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
@@ -1370,31 +1418,31 @@ _get_options_load_flags (const cairo_font_options_t *options)
}
static cairo_scaled_font_t *
-_ft_scaled_font_create (ft_unscaled_font_t *unscaled,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- int load_flags)
+_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ int load_flags)
{
- cairo_ft_scaled_font_t *f = NULL;
+ cairo_ft_scaled_font_t *scaled_font = NULL;
- f = malloc (sizeof(cairo_ft_scaled_font_t));
- if (f == NULL)
+ scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
+ if (scaled_font == NULL)
return NULL;
- f->unscaled = unscaled;
+ scaled_font->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
- f->options = *options;
-
if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
load_flags |= PRIVATE_FLAG_HINT_METRICS;
- f->load_flags = load_flags;
+ scaled_font->load_flags = load_flags;
- _cairo_scaled_font_init (&f->base, font_matrix, ctm, &cairo_ft_scaled_font_backend);
+ _cairo_scaled_font_init (&scaled_font->base,
+ font_matrix, ctm, options,
+ &cairo_ft_scaled_font_backend);
- return (cairo_scaled_font_t *)f;
+ return (cairo_scaled_font_t*) scaled_font;
}
cairo_bool_t
@@ -1404,28 +1452,28 @@ _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
}
static cairo_status_t
-_cairo_ft_scaled_font_create (const char *family,
- cairo_font_slant_t slant,
- cairo_font_weight_t weight,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **font)
+_cairo_ft_scaled_font_create_toy (const cairo_toy_font_face_t *toy_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **font)
{
FcPattern *pattern, *resolved;
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_scaled_font_t *new_font;
FcResult result;
int fcslant;
int fcweight;
cairo_matrix_t scale;
- ft_font_transform_t sf;
+ cairo_ft_font_transform_t sf;
+ int load_flags;
+ unsigned char *family = (unsigned char*) toy_face->family;
pattern = FcPatternCreate ();
if (!pattern)
return CAIRO_STATUS_NO_MEMORY;
- switch (weight)
+ switch (toy_face->weight)
{
case CAIRO_FONT_WEIGHT_BOLD:
fcweight = FC_WEIGHT_BOLD;
@@ -1436,7 +1484,7 @@ _cairo_ft_scaled_font_create (const char *family,
break;
}
- switch (slant)
+ switch (toy_face->slant)
{
case CAIRO_FONT_SLANT_ITALIC:
fcslant = FC_SLANT_ITALIC;
@@ -1450,7 +1498,7 @@ _cairo_ft_scaled_font_create (const char *family,
break;
}
- if (!FcPatternAddString (pattern, FC_FAMILY, (unsigned char *) family))
+ if (!FcPatternAddString (pattern, FC_FAMILY, family))
goto FREE_PATTERN;
if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant))
goto FREE_PATTERN;
@@ -1470,13 +1518,15 @@ _cairo_ft_scaled_font_create (const char *family,
if (!resolved)
goto FREE_PATTERN;
- unscaled = _ft_unscaled_font_get_for_pattern (resolved);
+ unscaled = _cairo_ft_unscaled_font_get_for_pattern (resolved);
if (!unscaled)
goto FREE_RESOLVED;
-
- new_font = _ft_scaled_font_create (unscaled,
- font_matrix, ctm,
- options, _get_pattern_load_flags (pattern));
+
+ load_flags = _get_pattern_load_flags (pattern);
+ new_font = _cairo_ft_scaled_font_create (unscaled,
+ font_matrix, ctm,
+ options, load_flags);
+
_cairo_unscaled_font_destroy (&unscaled->base);
FcPatternDestroy (resolved);
@@ -1499,7 +1549,7 @@ _cairo_ft_scaled_font_create (const char *family,
}
static void
-_cairo_ft_scaled_font_destroy (void *abstract_font)
+_cairo_ft_scaled_font_fini (void *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
@@ -1599,19 +1649,20 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
FT_Face face;
FT_Size_Metrics *metrics;
- face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
metrics = &face->size->metrics;
- _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+ &scaled_font->base.scale);
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
- if (scaled_font->options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
+ if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
double x_factor, y_factor;
if (scaled_font->unscaled->x_scale == 0)
@@ -1640,7 +1691,7 @@ _cairo_ft_scaled_font_font_extents (void *abstract_font,
/* FIXME: this doesn't do vertical layout atm. */
extents->max_y_advance = 0.0;
- _ft_unscaled_font_unlock_face (scaled_font->unscaled);
+ _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
return CAIRO_STATUS_SUCCESS;
}
@@ -1697,7 +1748,7 @@ _cairo_ft_scaled_font_glyph_extents (void *abstract_font,
/* 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_scaled_font_create_for_ft_face accept an
+ cairo_ft_font_face_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;
@@ -1793,6 +1844,26 @@ _cairo_ft_scaled_font_glyph_bbox (void *abstract_font,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_format_t
+_select_text_mask_format (cairo_bool_t have_a1_glyphs,
+ cairo_bool_t have_a8_glyphs,
+ cairo_bool_t have_argb32_glyphs)
+{
+ if (have_a8_glyphs)
+ return CAIRO_FORMAT_A8;
+
+ if (have_a1_glyphs && have_argb32_glyphs)
+ return CAIRO_FORMAT_A8;
+
+ if (have_a1_glyphs)
+ return CAIRO_FORMAT_A1;
+
+ if (have_argb32_glyphs)
+ return CAIRO_FORMAT_ARGB32;
+
+ /* when there are no glyphs to draw, just pick something */
+ return CAIRO_FORMAT_A8;
+}
static cairo_status_t
_cairo_ft_scaled_font_show_glyphs (void *abstract_font,
@@ -1808,12 +1879,16 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
- cairo_image_glyph_cache_entry_t *img;
+ cairo_image_glyph_cache_entry_t **entries;
cairo_cache_t *cache;
cairo_glyph_cache_key_t key;
cairo_ft_scaled_font_t *scaled_font = abstract_font;
cairo_surface_pattern_t glyph_pattern;
- cairo_status_t status;
+ cairo_surface_t *mask;
+ cairo_surface_pattern_t mask_pattern;
+ cairo_format_t mask_format = CAIRO_FORMAT_A1;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_bool_t have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs;
int x, y;
int i;
@@ -1833,44 +1908,98 @@ _cairo_ft_scaled_font_show_glyphs (void *abstract_font,
key.scale = scaled_font->base.scale;
key.flags = scaled_font->load_flags;
+ entries = malloc (num_glyphs * sizeof (cairo_image_glyph_cache_entry_t));
+ if (!entries)
+ goto CLEANUP_CACHE;
+
+ have_a1_glyphs = FALSE;
+ have_a8_glyphs = FALSE;
+ have_argb32_glyphs = FALSE;
+
for (i = 0; i < num_glyphs; i++)
{
- img = NULL;
+ entries[i] = NULL;
key.index = glyphs[i].index;
- if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL)
- != CAIRO_STATUS_SUCCESS
- || img == NULL
- || img->image == NULL)
+ if (_cairo_cache_lookup (cache, &key, (void **) &entries[i], NULL) != CAIRO_STATUS_SUCCESS)
+ continue;
+
+ switch (entries[i]->image->format) {
+ case CAIRO_FORMAT_A1:
+ have_a1_glyphs = TRUE;
+ break;
+ case CAIRO_FORMAT_A8:
+ have_a8_glyphs = TRUE;
+ break;
+ case CAIRO_FORMAT_ARGB32:
+ have_argb32_glyphs = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ mask_format = _select_text_mask_format (have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs);
+
+ mask = cairo_image_surface_create (mask_format, width, height);
+ if (!mask)
+ goto CLEANUP_ENTRIES;
+
+ status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_SOURCE,
+ CAIRO_COLOR_TRANSPARENT,
+ 0, 0, width, height);
+ if (status)
+ goto CLEANUP_MASK;
+
+ for (i = 0; i < num_glyphs; i++)
+ {
+ if (entries[i] == NULL
+ || entries[i]->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));
+ _cairo_pattern_init_for_surface (&glyph_pattern, &(entries[i]->image->base));
- status = _cairo_surface_composite (operator, pattern,
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, pattern,
&glyph_pattern.base,
- surface,
- x + img->size.x,
- y + img->size.y,
+ mask,
+ x + entries[i]->size.x,
+ y + entries[i]->size.y,
0, 0,
- x + img->size.x,
- y + img->size.y,
- (double) img->size.width,
- (double) img->size.height);
+ x + entries[i]->size.x - dest_x,
+ y + entries[i]->size.y - dest_y,
+ entries[i]->size.width,
+ entries[i]->size.height);
_cairo_pattern_fini (&glyph_pattern.base);
- if (status) {
- _cairo_unlock_global_image_glyph_cache ();
- return status;
- }
- }
+ if (status)
+ goto CLEANUP_MASK;
+ }
+
+ _cairo_pattern_init_for_surface (&mask_pattern, mask);
+
+ status = _cairo_surface_composite (operator, pattern, &mask_pattern.base,
+ surface,
+ source_x, source_y,
+ 0, 0,
+ dest_x, dest_y,
+ width, height);
+
+ _cairo_pattern_fini (&mask_pattern.base);
+
+ CLEANUP_MASK:
+ cairo_surface_destroy (mask);
+
+ CLEANUP_ENTRIES:
+ free (entries);
+ CLEANUP_CACHE:
_cairo_unlock_global_image_glyph_cache ();
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
@@ -2018,26 +2147,26 @@ _cairo_ft_scaled_font_glyph_path (void *abstract_font,
}
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
- _cairo_ft_scaled_font_create,
- _cairo_ft_scaled_font_destroy,
+ _cairo_ft_scaled_font_create_toy,
+ _cairo_ft_scaled_font_fini,
_cairo_ft_scaled_font_font_extents,
_cairo_ft_scaled_font_text_to_glyphs,
_cairo_ft_scaled_font_glyph_extents,
_cairo_ft_scaled_font_glyph_bbox,
_cairo_ft_scaled_font_show_glyphs,
_cairo_ft_scaled_font_glyph_path,
- _cairo_ft_scaled_font_get_glyph_cache_key,
+ _cairo_ft_scaled_font_get_glyph_cache_key
};
/* ft_font_face_t */
static void
-_ft_font_face_destroy (void *abstract_face)
+_cairo_ft_font_face_destroy (void *abstract_face)
{
- ft_font_face_t *font_face = abstract_face;
+ cairo_ft_font_face_t *font_face = abstract_face;
- ft_font_face_t *tmp_face = NULL;
- ft_font_face_t *last_face = NULL;
+ cairo_ft_font_face_t *tmp_face = NULL;
+ cairo_ft_font_face_t *last_face = NULL;
if (font_face == NULL)
return;
@@ -2069,12 +2198,15 @@ _ft_font_face_destroy (void *abstract_face)
if (font_face->unscaled) {
/* Remove face from linked list */
- for (tmp_face = font_face->unscaled->faces; tmp_face; tmp_face = tmp_face->next_face) {
+ for (tmp_face = font_face->unscaled->faces;
+ tmp_face;
+ tmp_face = tmp_face->next)
+ {
if (tmp_face == font_face) {
if (last_face)
- last_face->next_face = tmp_face->next_face;
+ last_face->next = tmp_face->next;
else
- font_face->unscaled->faces = tmp_face->next_face;
+ font_face->unscaled->faces = tmp_face->next;
}
last_face = tmp_face;
@@ -2086,13 +2218,13 @@ _ft_font_face_destroy (void *abstract_face)
}
static cairo_status_t
-_ft_font_face_create_font (void *abstract_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **scaled_font)
+_cairo_ft_font_face_scaled_font_create (void *abstract_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **scaled_font)
{
- ft_font_face_t *font_face = abstract_face;
+ cairo_ft_font_face_t *font_face = abstract_face;
int load_flags;
/* The handling of font options is different depending on how the
@@ -2109,36 +2241,37 @@ _ft_font_face_create_font (void *abstract_face,
else
load_flags = font_face->load_flags;
- *scaled_font = _ft_scaled_font_create (font_face->unscaled,
- font_matrix, ctm,
- options, load_flags);
+ *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled,
+ font_matrix, ctm,
+ options, load_flags);
if (*scaled_font)
return CAIRO_STATUS_SUCCESS;
else
return CAIRO_STATUS_NO_MEMORY;
}
-static const cairo_font_face_backend_t _ft_font_face_backend = {
- _ft_font_face_destroy,
- _ft_font_face_create_font,
+static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
+ _cairo_ft_font_face_destroy,
+ _cairo_ft_font_face_scaled_font_create
};
static cairo_font_face_t *
-_ft_font_face_create (ft_unscaled_font_t *unscaled,
- int load_flags)
+_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
+ int load_flags)
{
- ft_font_face_t *font_face;
+ cairo_ft_font_face_t *font_face;
/* Looked for an existing matching font face */
- for (font_face = unscaled->faces; font_face; font_face = font_face->next_face) {
- if (font_face->load_flags == load_flags) {
- cairo_font_face_reference (&font_face->base);
- return &font_face->base;
- }
+ for (font_face = unscaled->faces;
+ font_face;
+ font_face = font_face->next)
+ {
+ if (font_face->load_flags == load_flags)
+ return cairo_font_face_reference (&font_face->base);
}
/* No match found, create a new one */
- font_face = malloc (sizeof (ft_font_face_t));
+ font_face = malloc (sizeof (cairo_ft_font_face_t));
if (!font_face)
return NULL;
@@ -2147,10 +2280,10 @@ _ft_font_face_create (ft_unscaled_font_t *unscaled,
font_face->load_flags = load_flags;
- font_face->next_face = unscaled->faces;
+ font_face->next = unscaled->faces;
unscaled->faces = font_face;
- _cairo_font_face_init (&font_face->base, &_ft_font_face_backend);
+ _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
return &font_face->base;
}
@@ -2272,16 +2405,17 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
cairo_font_face_t *
cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
{
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
- unscaled = _ft_unscaled_font_get_for_pattern (pattern);
+ unscaled = _cairo_ft_unscaled_font_get_for_pattern (pattern);
if (unscaled == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
- font_face = _ft_font_face_create (unscaled, _get_pattern_load_flags (pattern));
+ font_face = _cairo_ft_font_face_create (unscaled,
+ _get_pattern_load_flags (pattern));
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face)
@@ -2321,16 +2455,16 @@ cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags)
{
- ft_unscaled_font_t *unscaled;
+ cairo_ft_unscaled_font_t *unscaled;
cairo_font_face_t *font_face;
- unscaled = _ft_unscaled_font_create_from_face (face);
+ unscaled = _cairo_ft_unscaled_font_create_from_face (face);
if (unscaled == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
- font_face = _ft_font_face_create (unscaled, load_flags);
+ font_face = _cairo_ft_font_face_create (unscaled, load_flags);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face) {
@@ -2379,13 +2513,13 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
if (scaled_font->base.status)
return NULL;
- face = _ft_unscaled_font_lock_face (scaled_font->unscaled);
+ face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
if (face == NULL) {
_cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
return NULL;
}
- _ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &scaled_font->base.scale);
return face;
}
@@ -2408,7 +2542,7 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
if (scaled_font->base.status)
return;
- _ft_unscaled_font_unlock_face (scaled_font->unscaled);
+ _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
}
/* We expose our unscaled font implementation internally for the the
@@ -2423,17 +2557,15 @@ _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
return &scaled_font->unscaled->base;
}
-/* 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)
+_cairo_ft_font_reset_static_data (void)
{
- _ft_unscaled_font_unlock_face ((ft_unscaled_font_t *)unscaled_font);
+ _lock_global_ft_cache ();
+ if (_global_ft_cache) {
+ FT_Done_FreeType (_global_ft_cache->lib);
+ _global_ft_cache->lib = NULL;
+ }
+ _cairo_cache_destroy (&_global_ft_cache->base);
+ _global_ft_cache = NULL;
+ _unlock_global_ft_cache ();
}