[cairo-commit] 4 commits - ROADMAP src/cairo-image-surface.c
src/cairoint.h src/cairo-pdf-surface.c src/cairo-ps-surface.c
src/cairo-scaled-font.c src/cairo-svg-surface.c
test/bitmap-font.c test/bitmap-font-ref.png
test/bitmap-font-rgb24-ref.png
Carl Worth
cworth at kemper.freedesktop.org
Thu Aug 17 17:51:28 PDT 2006
ROADMAP | 4 -
src/cairo-image-surface.c | 26 +++++++++++
src/cairo-pdf-surface.c | 9 +++
src/cairo-ps-surface.c | 9 +++
src/cairo-scaled-font.c | 96 ++++++++++++++++++++++++++++++++++++++++-
src/cairo-svg-surface.c | 10 +++-
src/cairoint.h | 4 +
test/bitmap-font-ref.png |binary
test/bitmap-font-rgb24-ref.png |binary
test/bitmap-font.c | 20 +++++++-
10 files changed, 169 insertions(+), 9 deletions(-)
New commits:
diff-tree 9878a033531e6b96b5f27e69e10e90dee7440cd9 (from e4e5002c48ec9cea37b4347689f193b54439383e)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Aug 17 17:48:40 2006 -0700
Add (primitive) bitmap glyph tracing to fix bug #7889
diff --git a/ROADMAP b/ROADMAP
index 2d38d38..1c8b1c5 100644
--- a/ROADMAP
+++ b/ROADMAP
@@ -33,8 +33,8 @@ cairo-1.2.4 (August 21, 2006): Fix build
- xlib detection requires libXt
- 7744: Compile troubles on AIX
- SVG backend requires PNG
- - 7888: assertion failure with rotated bitmap glyphs
- - 7889: cairo_text_path assertion failure on bitmap fonts
+â- 7888: assertion failure with rotated bitmap glyphs
+â- 7889: cairo_text_path assertion failure on bitmap fonts
- Type1 on Windows (Adrian has a patch)
â- source-clip-scale
- PS/PDF Type1/Type3 problem with rotated font_matrices
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index e96d844..9a13fb7 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1052,6 +1052,74 @@ _scaled_glyph_path_close_path (void *abs
return _cairo_path_fixed_close_path (closure->path);
}
+
+/**
+ * _trace_mask_to_path:
+ * @bitmap: An alpha mask (either CAIRO_FORMAT_A1 or _A8)
+ * @path: An initialized path to hold the result
+ *
+ * Given a mask surface, (an alpha image), fill out the provided path
+ * so that when filled it would result in something that approximates
+ * the mask.
+ *
+ * Note: The current tracing code here is extremely primitive. It
+ * operates only on an A1 surface, (converting an A8 surface to A1 if
+ * necessary), and performs the tracing by drawing a little square
+ * around each pixel that is on in the mask. We do not pretend that
+ * this is a high-quality result. But we are leaving it up to somone
+ * who cares enough about getting a better result to implement
+ * something more sophisticated.
+ **/
+static cairo_status_t
+_trace_mask_to_path (cairo_image_surface_t *mask,
+ cairo_path_fixed_t *path)
+{
+ cairo_image_surface_t *a1_mask;
+ unsigned char *row, *byte_ptr, byte;
+ int rows, cols, bytes_per_row;
+ int x, y, bit;
+ double xoff, yoff;
+
+ if (mask->format == CAIRO_FORMAT_A1)
+ a1_mask = mask;
+ else
+ a1_mask = _cairo_image_surface_clone (mask, CAIRO_FORMAT_A1);
+
+ if (cairo_surface_status (&a1_mask->base))
+ return cairo_surface_status (&a1_mask->base);
+
+ cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
+
+ bytes_per_row = (a1_mask->width + 7) / 8;
+ for (y = 0, row = a1_mask->data, rows = a1_mask->height; rows; row += a1_mask->stride, rows--, y++) {
+ for (x = 0, byte_ptr = row, cols = (a1_mask->width + 7) / 8; cols; byte_ptr++, cols--) {
+ byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
+ for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
+ if (byte & (1 << bit)) {
+ _cairo_path_fixed_move_to (path,
+ _cairo_fixed_from_int (x + xoff),
+ _cairo_fixed_from_int (y + yoff));
+ _cairo_path_fixed_rel_line_to (path,
+ _cairo_fixed_from_int (1),
+ _cairo_fixed_from_int (0));
+ _cairo_path_fixed_rel_line_to (path,
+ _cairo_fixed_from_int (0),
+ _cairo_fixed_from_int (1));
+ _cairo_path_fixed_rel_line_to (path,
+ _cairo_fixed_from_int (-1),
+ _cairo_fixed_from_int (0));
+ _cairo_path_fixed_close_path (path);
+ }
+ }
+ }
+ }
+
+ if (a1_mask != mask)
+ cairo_surface_destroy (&a1_mask->base);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
cairo_status_t
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs,
@@ -1061,6 +1129,7 @@ _cairo_scaled_font_glyph_path (cairo_sca
cairo_status_t status;
int i;
cairo_scaled_glyph_path_closure_t closure;
+ cairo_path_fixed_t *glyph_path;
if (scaled_font->status)
return scaled_font->status;
@@ -1073,19 +1142,42 @@ _cairo_scaled_font_glyph_path (cairo_sca
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
- if (status)
+ if (status == CAIRO_STATUS_SUCCESS)
+ glyph_path = scaled_glyph->path;
+ else if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
+ /* If the font is incapable of providing a path, then we'll
+ * have to trace our own from a surface. */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ status = _cairo_scaled_glyph_lookup (scaled_font,
+ glyphs[i].index,
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ &scaled_glyph);
+
+ glyph_path = _cairo_path_fixed_create ();
+ if (glyph_path == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
+
+ status = _trace_mask_to_path (scaled_glyph->surface, glyph_path);
+ if (status) {
+ _cairo_path_fixed_destroy (glyph_path);
+ return status;
+ }
+ }
+
closure.offset.x = _cairo_fixed_from_double (glyphs[i].x);
closure.offset.y = _cairo_fixed_from_double (glyphs[i].y);
- status = _cairo_path_fixed_interpret (scaled_glyph->path,
+ status = _cairo_path_fixed_interpret (glyph_path,
CAIRO_DIRECTION_FORWARD,
_scaled_glyph_path_move_to,
_scaled_glyph_path_line_to,
_scaled_glyph_path_curve_to,
_scaled_glyph_path_close_path,
&closure);
+ if (glyph_path != scaled_glyph->path)
+ _cairo_path_fixed_destroy (glyph_path);
}
return CAIRO_STATUS_SUCCESS;
diff-tree e4e5002c48ec9cea37b4347689f193b54439383e (from 0bfa6d4f33b8ddb5dc55bbe419c15df4af856ff9)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Aug 17 17:45:14 2006 -0700
bitmap-font: Add cairo_text_path;fill to demonstrate bug #7889
diff --git a/test/bitmap-font.c b/test/bitmap-font.c
index 594e813..ef9bbb6 100644
--- a/test/bitmap-font.c
+++ b/test/bitmap-font.c
@@ -97,16 +97,23 @@ draw (cairo_t *cr, int width, int height
cairo_move_to (cr, 1, TEXT_SIZE - 3);
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
- cairo_show_text (cr, "the quick brown fox jumps over a lazy dog");
+ cairo_show_text (cr, "the quick brown fox");
- /* And test it rotated as well. */
+ /* Switch from show_text to text_path/fill to exercise bug #7889 */
+ cairo_text_path (cr, " jumps over a lazy dog");
+ cairo_fill (cr);
+
+ /* And test it rotated as well for the sake of bug #7888 */
/* XXX: The math for the vertical positioning here is all wrong,
* but it is landing where I want it. Someone who understands
* fonts at all should fix this. */
cairo_move_to (cr, width -1, 2 * (TEXT_SIZE - 5));
cairo_rotate (cr, M_PI);
- cairo_show_text (cr, "the quick brown fox jumps over a lazy dog");
+ cairo_show_text (cr, "the quick brown fox");
+
+ cairo_text_path (cr, " jumps over a lazy dog");
+ cairo_fill (cr);
return CAIRO_TEST_SUCCESS;
}
diff-tree 0bfa6d4f33b8ddb5dc55bbe419c15df4af856ff9 (from e8e7ccf602fdaa2f2e98743f96589f5b7b3faf17)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Aug 17 15:23:32 2006 -0700
Fix assertion failures in bitmap-font test by coercing A8 images to A1
There are still some problems in the resulting output:
PDF: Rotated font ends up being blurry in final PNG (not too important)
PS and SVG: There's an incorrect offset being applied somewhere.
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 7f1947e..2037c3f 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1050,3 +1050,29 @@ const cairo_surface_backend_t cairo_imag
_cairo_image_surface_get_extents,
NULL /* old_show_glyphs */
};
+
+/* A convenience function for when one needs to coerce an image
+ * surface to an alternate format. */
+cairo_image_surface_t *
+_cairo_image_surface_clone (cairo_image_surface_t *surface,
+ cairo_format_t format)
+{
+ cairo_image_surface_t *clone;
+ cairo_t *cr;
+ double x, y;
+
+ clone = (cairo_image_surface_t *)
+ cairo_image_surface_create (format,
+ surface->width, surface->height);
+
+ cr = cairo_create (&clone->base);
+ cairo_surface_get_device_offset (&surface->base, &x, &y);
+ cairo_set_source_surface (cr, &surface->base, x, y);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_set_device_offset (&clone->base, x, y);
+
+ return clone;
+}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 8665ee2..6caee3d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1858,7 +1858,11 @@ _cairo_pdf_surface_emit_bitmap_glyph (ca
return status;
image = scaled_glyph->surface;
- assert (image->format == CAIRO_FORMAT_A1);
+ if (image->format != CAIRO_FORMAT_A1) {
+ image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
+ if (cairo_surface_status (image))
+ return cairo_surface_status (image);
+ }
*glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
@@ -1900,6 +1904,9 @@ _cairo_pdf_surface_emit_bitmap_glyph (ca
_cairo_pdf_surface_close_stream (surface);
+ if (image != scaled_glyph->surface)
+ cairo_surface_destroy (&image->base);
+
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index e809064..ba8a808 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -547,7 +547,11 @@ _cairo_ps_surface_emit_bitmap_glyph_data
&scaled_glyph);
image = scaled_glyph->surface;
- assert (image->format == CAIRO_FORMAT_A1);
+ if (image->format != CAIRO_FORMAT_A1) {
+ image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
+ if (cairo_surface_status (image))
+ return cairo_surface_status (image);
+ }
_cairo_output_stream_printf (surface->final_stream,
"0 0 %f %f %f %f setcachedevice\n",
@@ -591,6 +595,9 @@ _cairo_ps_surface_emit_bitmap_glyph_data
_cairo_output_stream_printf (surface->final_stream,
"imagemask\n");
+ if (image != scaled_glyph->surface)
+ cairo_surface_destroy (&image->base);
+
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 988f98b..7c99c97 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -573,7 +573,11 @@ _cairo_svg_document_emit_bitmap_glyph_da
return status;
image = scaled_glyph->surface;
- assert (image->format == CAIRO_FORMAT_A1);
+ if (image->format != CAIRO_FORMAT_A1) {
+ image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
+ if (cairo_surface_status (image))
+ return cairo_surface_status (image);
+ }
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
@@ -592,6 +596,10 @@ _cairo_svg_document_emit_bitmap_glyph_da
}
}
_cairo_output_stream_printf (document->xml_node_glyphs, "</g>\n");
+
+ if (image != scaled_glyph->surface)
+ cairo_surface_destroy (image);
+
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 034463a..13d19b1 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2023,6 +2023,10 @@ cairo_private cairo_int_status_t
_cairo_image_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region);
+cairo_image_surface_t *
+_cairo_image_surface_clone (cairo_image_surface_t *surface,
+ cairo_format_t format);
+
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface);
diff-tree e8e7ccf602fdaa2f2e98743f96589f5b7b3faf17 (from 751ff78ff2acba36614bae17744427c385413264)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Aug 17 13:54:06 2006 -0700
Add rotation to bitmap-font to demonstrate failure of bug #7888
diff --git a/test/bitmap-font-ref.png b/test/bitmap-font-ref.png
index 886c62f..0718bf9 100644
Binary files a/test/bitmap-font-ref.png and b/test/bitmap-font-ref.png differ
diff --git a/test/bitmap-font-rgb24-ref.png b/test/bitmap-font-rgb24-ref.png
index abea9b1..8569064 100644
Binary files a/test/bitmap-font-rgb24-ref.png and b/test/bitmap-font-rgb24-ref.png differ
diff --git a/test/bitmap-font.c b/test/bitmap-font.c
index 16ad52c..594e813 100644
--- a/test/bitmap-font.c
+++ b/test/bitmap-font.c
@@ -40,7 +40,7 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"bitmap-font",
"Test drawing with a font consisting only of bitmaps",
- 246 + 1, TEXT_SIZE,
+ 246 + 1, 2 * TEXT_SIZE,
draw
};
@@ -99,6 +99,15 @@ draw (cairo_t *cr, int width, int height
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
cairo_show_text (cr, "the quick brown fox jumps over a lazy dog");
+ /* And test it rotated as well. */
+
+ /* XXX: The math for the vertical positioning here is all wrong,
+ * but it is landing where I want it. Someone who understands
+ * fonts at all should fix this. */
+ cairo_move_to (cr, width -1, 2 * (TEXT_SIZE - 5));
+ cairo_rotate (cr, M_PI);
+ cairo_show_text (cr, "the quick brown fox jumps over a lazy dog");
+
return CAIRO_TEST_SUCCESS;
}
More information about the cairo-commit
mailing list