[cairo-commit] cairo/src cairo-ft-font.c,1.65,1.66
Owen Taylor
commit at pdx.freedesktop.org
Fri Jun 24 15:06:45 PDT 2005
- Previous message: [cairo-commit] cairo-artwork ChangeLog, 1.11,
1.12 cairo-artwork_defs.svg, 1.3, 1.4 cairo_banner.png, 1.5,
1.6 cairo_banner.svg, 1.4, 1.5 cairo_logo.png, 1.4,
1.5 cairo_logo.svg, 1.3, 1.4 cairo_logo_with_text.png, 1.4,
1.5 cairo_logo_with_text.svg, 1.3, 1.4
- Next message: [cairo-commit] cairo ChangeLog,1.684,1.685
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv8451/src
Modified Files:
cairo-ft-font.c
Log Message:
2005-06-24 Owen Taylor <otaylor at redhat.com>
* src/cairo-ft-font.c (_render_glyph_bitmap): Handle rendering
bitmap glyphslots as well as outline glyphslots.
* src/cairo-ft-font.c (_ft_unscaled_font_set_scale): When setting
the scale for a non-scalable font, use the nearest available
size (FreeType won't set the glyph metrics otherwise.)
Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- cairo-ft-font.c 15 Jun 2005 23:04:19 -0000 1.65
+++ cairo-ft-font.c 24 Jun 2005 22:06:41 -0000 1.66
@@ -34,6 +34,8 @@
* Owen Taylor <otaylor at redhat.com>
*/
+#include <float.h>
+
#include "cairo-ft-private.h"
#include <fontconfig/fontconfig.h>
@@ -448,6 +450,7 @@
{
ft_font_transform_t sf;
FT_Matrix mat;
+ FT_UInt pixel_width, pixel_height;
assert (unscaled->face != NULL);
@@ -472,10 +475,29 @@
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);
+
+ if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
+ pixel_width = sf.x_scale;
+ pixel_height = sf.y_scale;
+ } else {
+ double min_distance = DBL_MAX;
+ int i;
+
+ pixel_width = pixel_height = 0;
+
+ for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
+ double size = unscaled->face->available_sizes[i].y_ppem / 64.;
+ double distance = fabs (size - sf.y_scale);
+
+ if (distance <= min_distance) {
+ min_distance = distance;
+ pixel_width = unscaled->face->available_sizes[i].x_ppem >> 6;
+ pixel_height = unscaled->face->available_sizes[i].y_ppem >> 6;
+ }
+ }
+ }
+
+ FT_Set_Pixel_Sizes (unscaled->face, pixel_width, pixel_height);
}
static void
@@ -515,59 +537,32 @@
}
}
-static cairo_status_t
-_cairo_ft_unscaled_font_create_glyph (void *abstract_font,
- cairo_image_glyph_cache_entry_t *val)
+/* Converts an outline FT_GlyphSlot into an image
+ *
+ * This could go through _render_glyph_bitmap as well, letting
+ * FreeType convert the outline to a bitmap, but doing it ourselves
+ * has two minor advantages: first, we save a copy of the bitmap
+ * buffer: we can directly use the buffer that FreeType renders
+ * into.
+ *
+ * Second, it may help when we add support for subpixel
+ * rendering: the Xft code does it this way. (Keith thinks that
+ * it may also be possible to get the subpixel rendering with
+ * FT_Render_Glyph: something worth looking into in more detail
+ * when we add subpixel support. If so, we may want to eliminate
+ * this version of the code path entirely.
+ */
+static cairo_status_t
+_render_glyph_outline (FT_Face face,
+ cairo_image_glyph_cache_entry_t *val)
{
- ft_unscaled_font_t *unscaled = abstract_font;
- FT_GlyphSlot glyphslot;
+ FT_GlyphSlot glyphslot = face->glyph;
+ FT_Outline *outline = &glyphslot->outline;
unsigned int width, height, stride;
- FT_Face face;
- FT_Outline *outline;
- FT_BBox cbox;
FT_Bitmap bitmap;
- FT_Glyph_Metrics *metrics;
+ FT_BBox cbox;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- face = _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);
-
- 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;
@@ -583,7 +578,7 @@
val->image = NULL;
} else {
- bitmap.pixel_mode = ft_pixel_mode_grays;
+ bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
bitmap.num_grays = 256;
bitmap.width = width;
bitmap.rows = height;
@@ -591,16 +586,14 @@
bitmap.buffer = calloc (1, stride * height);
if (bitmap.buffer == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
+ return CAIRO_STATUS_NO_MEMORY;
}
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;
+ return CAIRO_STATUS_NO_MEMORY;
}
val->image = (cairo_image_surface_t *)
@@ -609,8 +602,7 @@
width, height, stride);
if (val->image == NULL) {
free (bitmap.buffer);
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
+ return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (val->image);
@@ -625,10 +617,167 @@
val->size.height = (unsigned short) height;
val->size.x = (short) (cbox.xMin >> 6);
val->size.y = - (short) (cbox.yMax >> 6);
+
+ return status;
+}
+
+/* Converts a bitmap (or other) FT_GlyphSlot into an image
+ *
+ * This could go through _render_glyph_bitmap as well, letting
+ * FreeType convert the outline to a bitmap, but doing it ourselves
+ * has two minor advantages: first, we save a copy of the bitmap
+ * buffer: we can directly use the buffer that FreeType renders
+ * into.
+ *
+ * Second, it may help when we add support for subpixel
+ * rendering: the Xft code does it this way. (Keith thinks that
+ * it may also be possible to get the subpixel rendering with
+ * FT_Render_Glyph: something worth looking into in more detail
+ * when we add subpixel support. If so, we may want to eliminate
+ * this version of the code path entirely.
+ */
+static cairo_status_t
+_render_glyph_bitmap (FT_Face face,
+ cairo_image_glyph_cache_entry_t *val)
+{
+ FT_GlyphSlot glyphslot = face->glyph;
+ FT_Bitmap *bitmap;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ int width, height, stride;
+ unsigned char *data;
+ FT_Error error;
+ int i, j;
+
+ /* According to the FreeType docs, glyphslot->format could be
+ * something other than FT_GLYPH_FORMAT_OUTLINE or
+ * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
+ * the opportunity to convert such to
+ * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
+ * we avoid the FT_LOAD_NO_RECURSE flag.
+ */
+ error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
+ if (error)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ bitmap = &glyphslot->bitmap;
+
+ width = bitmap->width;
+ height = bitmap->rows;
+
+ if (width * height == 0) {
+ val->image = NULL;
+ } else {
+ switch (bitmap->pixel_mode) {
+ case FT_PIXEL_MODE_MONO:
+ stride = (width + 3) & ~3;
+ data = calloc (stride * height, 1);
+ if (!data)
+ return CAIRO_STATUS_NO_MEMORY;
+ for (j = 0; j < height; j++) {
+ const unsigned char *p = bitmap->buffer + j * bitmap->pitch;
+ unsigned char *q = data + j * stride;
+ for (i = 0; i < width; i++) {
+ /* FreeType bitmaps are always stored MSB */
+ unsigned char byte = p[i >> 3];
+ unsigned char bit = 1 << (7 - (i % 8));
+
+ if (byte & bit)
+ q[i] = 0xff;
+ }
+ }
+ break;
+ case FT_PIXEL_MODE_GRAY:
+ stride = bitmap->pitch;
+ data = malloc (stride * height);
+ if (!data)
+ return CAIRO_STATUS_NO_MEMORY;
+ memcpy (data, bitmap->buffer, stride * height);
+ break;
+ case FT_PIXEL_MODE_GRAY2:
+ case FT_PIXEL_MODE_GRAY4:
+ /* These could be triggered by very rare types of TrueType fonts */
+ case FT_PIXEL_MODE_LCD:
+ case FT_PIXEL_MODE_LCD_V:
+ /* These should never be triggered unless we ask for them */
+ default:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ val->image = (cairo_image_surface_t *)
+ cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_A8,
+ width, height, stride);
+ if (val->image == NULL) {
+ free (data);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ _cairo_image_surface_assume_ownership_of_data (val->image);
+ }
+
+ val->size.width = width;
+ val->size.height = height;
+ val->size.x = - glyphslot->bitmap_left;
+ val->size.y = - glyphslot->bitmap_top;
+
+ return status;
+}
+
+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;
+ FT_GlyphSlot glyphslot;
+ FT_Face face;
+ FT_Glyph_Metrics *metrics;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ face = _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);
+
+ 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;
+
+ if (glyphslot->format == FT_GLYPH_FORMAT_OUTLINE)
+ status = _render_glyph_outline (face, val);
+ else
+ status = _render_glyph_bitmap (face, val);
FAIL:
_ft_unscaled_font_unlock_face (unscaled);
-
+
return status;
}
- Previous message: [cairo-commit] cairo-artwork ChangeLog, 1.11,
1.12 cairo-artwork_defs.svg, 1.3, 1.4 cairo_banner.png, 1.5,
1.6 cairo_banner.svg, 1.4, 1.5 cairo_logo.png, 1.4,
1.5 cairo_logo.svg, 1.3, 1.4 cairo_logo_with_text.png, 1.4,
1.5 cairo_logo_with_text.svg, 1.3, 1.4
- Next message: [cairo-commit] cairo ChangeLog,1.684,1.685
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list