summaryrefslogtreecommitdiff
path: root/src/cairo-ft-font.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r--[-rwxr-xr-x]src/cairo-ft-font.c232
1 files changed, 138 insertions, 94 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 43df78e0b..868ccc2c8 100755..100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -45,6 +45,7 @@
#include "cairo-image-surface-private.h"
#include "cairo-ft-private.h"
#include "cairo-pattern-private.h"
+#include "cairo-pixman-private.h"
#include <float.h>
@@ -54,11 +55,11 @@
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_IMAGE_H
+#include FT_BITMAP_H
#include FT_TRUETYPE_TABLES_H
#include FT_XFREE86_H
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
#include FT_SYNTHESIS_H
-#define USE_FT_OUTLINE_EMBOLDEN 1
#endif
#if HAVE_FT_LIBRARY_SETLCDFILTER
@@ -587,23 +588,20 @@ _cairo_ft_unscaled_font_create_from_face (FT_Face face,
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out);
}
-static void
+static cairo_bool_t
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
cairo_ft_unscaled_font_t *unscaled = abstract_font;
cairo_ft_unscaled_font_map_t *font_map;
- if (unscaled == NULL)
- return;
-
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
- if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
+ if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)) {
/* somebody recreated the font whilst we waited for the lock */
_cairo_ft_unscaled_font_map_unlock ();
- return;
+ return FALSE;
}
_cairo_hash_table_remove (font_map->hash_table,
@@ -625,6 +623,7 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
_cairo_ft_unscaled_font_map_unlock ();
_cairo_ft_unscaled_font_fini (unscaled);
+ return TRUE;
}
static cairo_bool_t
@@ -740,19 +739,26 @@ _compute_transform (cairo_ft_font_transform_t *sf,
if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
double min_distance = DBL_MAX;
+ cairo_bool_t magnify = TRUE;
int i;
- int best_i = 0;
double best_x_size = 0;
double best_y_size = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
- double x_size = unscaled->face->available_sizes[i].y_ppem / 64.;
+ double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
- double distance = fabs (y_size - y_scale);
+ double distance = y_size - y_scale;
+
+ /*
+ * distance is positive if current strike is larger than desired
+ * size, and negative if smaller.
+ *
+ * We like to prefer down-scaling to upscaling.
+ */
- if (distance <= min_distance) {
- min_distance = distance;
- best_i = i;
+ if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
+ magnify = distance < 0;
+ min_distance = fabs (distance);
best_x_size = x_size;
best_y_size = y_size;
}
@@ -1114,15 +1120,17 @@ _fill_xrender_bitmap(FT_Bitmap *target,
*/
static cairo_status_t
_get_bitmap_surface (FT_Bitmap *bitmap,
+ FT_Library library,
cairo_bool_t own_buffer,
cairo_font_options_t *font_options,
cairo_image_surface_t **surface)
{
- int width, height, stride;
+ unsigned int width, height;
unsigned char *data;
int format = CAIRO_FORMAT_A8;
+ int stride;
cairo_image_surface_t *image;
- cairo_bool_t component_alpha = TRUE;
+ cairo_bool_t component_alpha = TRUE;
width = bitmap->width;
height = bitmap->rows;
@@ -1179,8 +1187,18 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_GRAY:
- if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
+ if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL ||
+ bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
+ {
stride = bitmap->pitch;
+
+ /* We don't support stride not multiple of 4. */
+ if (stride & 3)
+ {
+ assert (!own_buffer);
+ goto convert;
+ }
+
if (own_buffer) {
data = bitmap->buffer;
} else {
@@ -1193,49 +1211,91 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
format = CAIRO_FORMAT_A8;
} else {
- /* color glyph is rendered as bitmap, does not come from
- * _fill_xrender_bitmap */
- if (! own_buffer) {
- stride = bitmap->pitch;
- data = _cairo_malloc_ab (height, stride);
- if (!data)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (data, bitmap->buffer, stride * height);
- format = CAIRO_FORMAT_A8;
- } else {
- /* if we get there, the data from the source bitmap
- * really comes from _fill_xrender_bitmap, and is
- * made of 32-bit ARGB or ABGR values */
- assert (own_buffer != 0);
- assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
-
- data = bitmap->buffer;
- stride = bitmap->pitch;
- format = CAIRO_FORMAT_ARGB32;
- }
- }
- break;
- // color font
- /*
- case FT_PIXEL_MODE_BGRA:
+ /* color glyph is rendered as bitmap, does not come from
+ * _fill_xrender_bitmap */
+ if (! own_buffer) {
stride = bitmap->pitch;
- if (own_buffer) {
- data = bitmap->buffer;
- } else {
- data = _cairo_malloc_ab (height, stride);
- if (!data)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (data, bitmap->buffer, stride * height);
- }
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (data, bitmap->buffer, stride * height);
+ format = CAIRO_FORMAT_A8;
+ } else {
+ /* if we get there, the data from the source bitmap
+ * really comes from _fill_xrender_bitmap, and is
+ * made of 32-bit ARGB or ABGR values */
+ assert (own_buffer != 0);
+ assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
+ data = bitmap->buffer;
+ stride = bitmap->pitch;
format = CAIRO_FORMAT_ARGB32;
- component_alpha = FALSE;
+ }
+ }
break;
- */
+ // color font
+ #if 0 // TODO(suyambu.rm) Build error for Tizen 3.0
+ case FT_PIXEL_MODE_BGRA:
+ stride = bitmap->pitch;
+
+ if (own_buffer) {
+ data = bitmap->buffer;
+ } else {
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (data, bitmap->buffer, stride * height);
+ }
+
+ format = CAIRO_FORMAT_ARGB32;
+ component_alpha = FALSE;
+ break;
+ #endif
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
+ convert:
+ if (!own_buffer && library)
+ {
+ /* This is pretty much the only case that we can get in here. */
+ /* Convert to 8bit grayscale. */
+
+ FT_Bitmap tmp;
+ FT_Int align;
+
+ format = CAIRO_FORMAT_A8;
+
+ align = cairo_format_stride_for_width (format, bitmap->width);
+
+ FT_Bitmap_New( &tmp );
+
+ if (FT_Bitmap_Convert( library, bitmap, &tmp, align ))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ FT_Bitmap_Done( library, bitmap );
+ *bitmap = tmp;
+
+ stride = bitmap->pitch;
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ if (bitmap->num_grays != 256)
+ {
+ unsigned int x, y;
+ unsigned int mul = 255 / (bitmap->num_grays - 1);
+ FT_Byte *p = bitmap->buffer;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++)
+ p[x] *= mul;
+ p += bitmap->pitch;
+ }
+ }
+
+ memcpy (data, bitmap->buffer, stride * height);
+ break;
+ }
/* These could be triggered by very rare types of TrueType fonts */
default:
if (own_buffer)
@@ -1429,7 +1489,7 @@ _render_glyph_outline (FT_Face face,
/* Note:
* _get_bitmap_surface will free bitmap.buffer if there is an error
*/
- status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
+ status = _get_bitmap_surface (&bitmap, NULL, TRUE, font_options, surface);
if (unlikely (status))
return status;
@@ -1470,6 +1530,7 @@ _render_glyph_bitmap (FT_Face face,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _get_bitmap_surface (&glyphslot->bitmap,
+ glyphslot->library,
FALSE, font_options,
surface);
if (unlikely (status))
@@ -1511,7 +1572,7 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
* the "shape" portion of the font transform
*/
original_to_transformed = *shape;
-
+
cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
orig_width = (*surface)->width;
orig_height = (*surface)->height;
@@ -2193,10 +2254,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
vertical_layout = TRUE;
}
- #ifdef FT_LOAD_COLOR
- /*Color-glyph support */
- load_flags |= FT_LOAD_COLOR;
- #endif
+#ifdef FT_LOAD_COLOR
+ /* Color-glyph support:
+ *
+ * This flags needs plumbing through fontconfig (does it?), and
+ * maybe we should cache color and grayscale bitmaps separately
+ * such that users of the font (ie. the surface) can choose which
+ * version to use based on target content type.
+ *
+ * Moreover, none of our backends and compositors currently support
+ * color glyphs. As such, this is currently disabled.
+ */
+ /* load_flags |= FT_LOAD_COLOR; */
+
+ /* Color-glyph support */
+ if (scaled_font->ft_options.base.color == CAIRO_FONT_COLOR_DEFAULT)
+ load_flags |= FT_LOAD_COLOR;
+#endif
error = FT_Load_Glyph (face,
_cairo_scaled_glyph_index(scaled_glyph),
@@ -2215,22 +2289,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
*/
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
-#if USE_FT_OUTLINE_EMBOLDEN
- {
- /*UX team request us to use 64 instead 34*/
- FT_Pos xstr;
- if(face && face->size)
- xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64;
- else
- goto FAIL;
- if(face->glyph)
- FT_Outline_Embolden(&face->glyph->outline, xstr);
- else
- goto FAIL;
- }
-#else
FT_GlyphSlot_Embolden (glyph);
-#endif // USE_FT_OUTLINE_EMBOLDEN
#endif
#if HAVE_FT_GLYPHSLOT_OBLIQUE
@@ -2384,22 +2443,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
}
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
-#if USE_FT_OUTLINE_EMBOLDEN
- {
- /*UX team request us to use 64 instead 34*/
- FT_Pos xstr;
- if(face && face->size)
- xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64;
- else
- goto FAIL;
- if(face->glyph)
- FT_Outline_Embolden(&face->glyph->outline, xstr);
- else
- goto FAIL;
- }
-#else
- FT_GlyphSlot_Embolden (glyph);
-#endif // USE_FT_OUTLINE_EMBOLDEN
+ FT_GlyphSlot_Embolden (glyph);
#endif
#if HAVE_FT_GLYPHSLOT_OBLIQUE
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
@@ -2752,7 +2796,7 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
}
#endif
-static void
+static cairo_bool_t
_cairo_ft_font_face_destroy (void *abstract_face)
{
cairo_ft_font_face_t *font_face = abstract_face;
@@ -2778,12 +2822,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
font_face->unscaled->faces == font_face &&
CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
{
- cairo_font_face_reference (&font_face->base);
-
_cairo_unscaled_font_destroy (&font_face->unscaled->base);
font_face->unscaled = NULL;
- return;
+ return FALSE;
}
if (font_face->unscaled) {
@@ -2815,6 +2857,8 @@ _cairo_ft_font_face_destroy (void *abstract_face)
cairo_font_face_destroy (font_face->resolved_font_face);
}
#endif
+
+ return TRUE;
}
static cairo_font_face_t *