[cairo-commit] cairo/src cairo-ft-font.c,1.67,1.68
Owen Taylor
commit at pdx.freedesktop.org
Sat Jun 25 13:51:24 PDT 2005
Committed by: otaylor
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv15296/src
Modified Files:
cairo-ft-font.c
Log Message:
2005-06-24 Owen Taylor <otaylor at redhat.com>
* src/cairo-ft-font.c (_transform_glyph_bitmap): Add mostly
useless (other than perhaps 90-degree rotation) code for
transforming bitmap glyphs.
Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- cairo-ft-font.c 24 Jun 2005 22:14:31 -0000 1.67
+++ cairo-ft-font.c 25 Jun 2005 20:51:22 -0000 1.68
@@ -86,10 +86,11 @@
int id;
/* We temporarily scale the unscaled font as neede */
- int have_scale;
+ cairo_bool_t have_scale;
cairo_matrix_t current_scale;
double x_scale; /* Extracted X scale factor */
double y_scale; /* Extracted Y scale factor */
+ cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
int lock; /* count of how many times this font has been locked */
@@ -474,6 +475,11 @@
mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
+ unscaled->have_shape = (mat.xx != 0x10000 ||
+ mat.yx != 0x00000 ||
+ mat.xy != 0x00000 ||
+ mat.yy != 0x10000);
+
FT_Set_Transform(unscaled->face, &mat, NULL);
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
@@ -723,6 +729,125 @@
return status;
}
+static cairo_status_t
+_transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val)
+{
+ ft_font_transform_t sf;
+ cairo_matrix_t original_to_transformed;
+ cairo_matrix_t transformed_to_original;
+ cairo_image_surface_t *old_image;
+ cairo_surface_t *image;
+ double x[4], y[4];
+ double origin_x, origin_y;
+ int i;
+ int x_min, y_min, x_max, y_max;
+ int width, height;
+ cairo_status_t status;
+ cairo_surface_pattern_t pattern;
+
+ /* We want to compute a transform that takes the origin
+ * (val->size.x, val->size.y) to 0,0, then applies the "shape"
+ * portion of the font transform
+ */
+ _compute_transform (&sf, &val->key.scale);
+
+ cairo_matrix_init (&original_to_transformed,
+ sf.shape[0][0], sf.shape[0][1],
+ sf.shape[1][0], sf.shape[1][1],
+ 0, 0);
+
+ cairo_matrix_translate (&original_to_transformed,
+ val->size.x, val->size.y);
+
+ /* Find the bounding box of the original bitmap under that
+ * transform
+ */
+ x[0] = 0; y[0] = 0;
+ x[1] = val->size.width; y[1] = 0;
+ x[2] = val->size.width; y[2] = val->size.height;
+ x[3] = 0; y[3] = val->size.height;
+
+ for (i = 0; i < 4; i++)
+ cairo_matrix_transform_point (&original_to_transformed,
+ &x[i], &y[i]);
+
+ x_min = floor (x[0]); y_min = floor (y[0]);
+ x_max = ceil (x[0]); y_max = ceil (y[0]);
+
+ for (i = 1; i < 4; i++) {
+ if (x[i] < x_min)
+ x_min = floor (x[i]);
+ if (x[i] > x_max)
+ x_max = ceil (x[i]);
+ if (y[i] < y_min)
+ y_min = floor (y[i]);
+ if (y[i] > y_max)
+ y_max = ceil (y[i]);
+ }
+
+ /* Adjust the transform so that the bounding box starts at 0,0 ...
+ * this gives our final transform from original bitmap to transformed
+ * bitmap.
+ */
+ original_to_transformed.x0 -= x_min;
+ original_to_transformed.y0 -= y_min;
+
+ /* Create the transformed bitmap
+ */
+ width = x_max - x_min;
+ height = y_max - y_min;
+
+ transformed_to_original = original_to_transformed;
+ status = cairo_matrix_invert (&transformed_to_original);
+ if (status)
+ return status;
+
+ /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
+ width = (width + 3) & ~3;
+ image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+ if (!image)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ /* Initialize it to empty
+ */
+ _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_SOURCE,
+ CAIRO_COLOR_TRANSPARENT,
+ 0, 0,
+ width, height);
+
+ /* Draw the original bitmap transformed into the new bitmap
+ */
+ _cairo_pattern_init_for_surface (&pattern, &val->image->base);
+ cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
+
+ _cairo_surface_composite (CAIRO_OPERATOR_OVER,
+ &pattern.base, NULL, image,
+ 0, 0, 0, 0, 0, 0,
+ width,
+ height);
+
+ _cairo_pattern_fini (&pattern.base);
+
+ /* Now update the cache entry for the new bitmap, recomputing
+ * the origin based on the final transform.
+ */
+ origin_x = - val->size.x;
+ origin_y = - val->size.y;
+ cairo_matrix_transform_point (&original_to_transformed,
+ &origin_x, &origin_y);
+
+ old_image = val->image;
+ val->image = (cairo_image_surface_t *)image;
+ cairo_surface_destroy (&old_image->base);
+
+ val->size.width = width;
+ val->size.height = height;
+ val->size.x = - floor (origin_x + 0.5);
+ val->size.y = - floor (origin_y + 0.5);
+
+ return status;
+}
+
static cairo_status_t
_cairo_ft_unscaled_font_create_glyph (void *abstract_font,
cairo_image_glyph_cache_entry_t *val)
@@ -775,7 +900,16 @@
else
status = _render_glyph_bitmap (face, val);
+ if (unscaled->have_shape &&
+ (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
+ status = _transform_glyph_bitmap (val);
+
FAIL:
+ if (status && val->image) {
+ cairo_surface_destroy (&val->image->base);
+ val->image = NULL;
+ }
+
_ft_unscaled_font_unlock_face (unscaled);
return status;
More information about the cairo-commit
mailing list