[cairo-commit] 12 commits - doc/public src/cairo-gstate.c src/cairo.h src/cairoint.h src/cairo-pattern.c src/cairo-scaled-font.c src/cairo-scaled-font-private.h src/cairo-surface.c src/cairo-user-font.c src/cairo-xlib-surface.c test/Makefile.am test/surface-finish-twice.c test/user-font-proxy.c test/user-font-proxy-ps-ref.png test/user-font-proxy-ref.png test/user-font-proxy-svg-ref.png
Behdad Esfahbod
behdad at kemper.freedesktop.org
Sat May 24 17:56:45 PDT 2008
doc/public/cairo-sections.txt | 1
doc/public/tmpl/cairo-scaled-font.sgml | 9 +
src/cairo-gstate.c | 93 +++++++++++++---
src/cairo-pattern.c | 17 ++
src/cairo-scaled-font-private.h | 1
src/cairo-scaled-font.c | 70 ++++++++++--
src/cairo-surface.c | 7 -
src/cairo-user-font.c | 5
src/cairo-xlib-surface.c | 2
src/cairo.h | 4
src/cairoint.h | 43 ++++---
test/Makefile.am | 4
test/surface-finish-twice.c | 6 -
test/user-font-proxy-ps-ref.png |binary
test/user-font-proxy-ref.png |binary
test/user-font-proxy-svg-ref.png |binary
test/user-font-proxy.c | 190 +++++++++++++++++++++++++++++++++
17 files changed, 392 insertions(+), 60 deletions(-)
New commits:
commit 4c1c9d33b1b89d8098c06bbb4d430811947ed86c
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 20:48:38 2008 -0400
[user-font] Release fontmap lock around user callback
This makes the user-font-proxy to work now.
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index df2a18c..886250a 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -326,9 +326,12 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
return status;
}
- if (font_face->scaled_font_methods.init != NULL)
+ if (font_face->scaled_font_methods.init != NULL) {
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
status = font_face->scaled_font_methods.init (&user_scaled_font->base,
&font_extents);
+ CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
+ }
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
commit 127c4b8e643560c029818509e20fc5ca87408611
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 20:48:07 2008 -0400
[src/cairo-scaled-font] Only take fontmap mutex if touching it
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index b2f0c14..5cafbfe 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -811,20 +811,24 @@ slim_hidden_def (cairo_scaled_font_reference);
void
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
{
- cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *lru = NULL;
if (scaled_font == NULL ||
CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
return;
- font_map = _cairo_scaled_font_map_lock ();
- assert (font_map != NULL);
-
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
if (_cairo_reference_count_dec_and_test (&scaled_font->ref_count)) {
- if (scaled_font->hash_entry.hash != ZOMBIE) {
+ cairo_scaled_font_map_t *font_map;
+
+ /* don't use _cairo_scaled_font_map_lock() to not create it if it's
+ * NULL. if font_map is NULL, it means we are in the process of
+ * destructing it. don't err and continue */
+ CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
+ font_map = cairo_scaled_font_map;
+
+ if (font_map && scaled_font->hash_entry.hash != ZOMBIE) {
/* Rather than immediately destroying this object, we put it into
* the font_map->holdovers array in case it will get used again
* soon (and is why we must hold the lock over the atomic op on
@@ -849,8 +853,9 @@ cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
font_map->num_holdovers++;
} else
lru = scaled_font;
+
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
}
- _cairo_scaled_font_map_unlock ();
/* If we pulled an item from the holdovers array, (while the font
* map lock was held, of course), then there is no way that anyone
commit a715671c6f3bd2f6f692b79cba7d7f7bc49f06f9
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 20:34:41 2008 -0400
[test/user-font-proxy] New test using fonts inside a user-font
PDF fails and needs some fixes in the PDF surface instead of a new
ref image IMO.
diff --git a/test/Makefile.am b/test/Makefile.am
index 0723c23..f8256b4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -159,6 +159,7 @@ unantialiased-shapes$(EXEEXT) \
unbounded-operator$(EXEEXT) \
user-data$(EXEEXT) \
user-font$(EXEEXT) \
+user-font-proxy$(EXEEXT) \
zero-alpha$(EXEEXT)
# XXX: Here are some existing tests that are currently disabled for
@@ -701,6 +702,9 @@ REFERENCE_IMAGES = \
user-font-ref.png \
user-font-pdf-ref.png \
user-font-svg-ref.png \
+ user-font-proxy-ref.png \
+ user-font-proxy-ps-ref.png \
+ user-font-proxy-svg-ref.png \
unbounded-operator-quartz-ref.png \
unbounded-operator-quartz-rgb24-ref.png \
xlib-expose-event-ref.png \
diff --git a/test/user-font-proxy-ps-ref.png b/test/user-font-proxy-ps-ref.png
new file mode 100644
index 0000000..78bee6c
Binary files /dev/null and b/test/user-font-proxy-ps-ref.png differ
diff --git a/test/user-font-proxy-ref.png b/test/user-font-proxy-ref.png
new file mode 100644
index 0000000..ebd9719
Binary files /dev/null and b/test/user-font-proxy-ref.png differ
diff --git a/test/user-font-proxy-svg-ref.png b/test/user-font-proxy-svg-ref.png
new file mode 100644
index 0000000..e5e9e9a
Binary files /dev/null and b/test/user-font-proxy-svg-ref.png differ
diff --git a/test/user-font-proxy.c b/test/user-font-proxy.c
new file mode 100644
index 0000000..f54139c
--- /dev/null
+++ b/test/user-font-proxy.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright © 2006, 2008 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Contributor(s):
+ * Kristian Høgsberg <krh at redhat.com>
+ * Behdad Esfahbod <behdad at behdad.org>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "cairo-test.h"
+
+/*#define ROTATED 1*/
+
+#define BORDER 10
+#define TEXT_SIZE 64
+#define WIDTH (TEXT_SIZE * 12 + 2*BORDER)
+#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+#define TEXT "geez... cairo user-font"
+
+static cairo_test_draw_function_t draw;
+
+cairo_test_t test = {
+ "user-font-proxy",
+ "Tests a user-font using a native font in its render_glyph",
+#ifndef ROTATED
+ WIDTH, HEIGHT,
+#else
+ WIDTH, WIDTH,
+#endif
+ draw
+};
+
+static cairo_user_data_key_t fallback_scaled_font_key;
+
+static cairo_status_t
+test_scaled_font_init (cairo_scaled_font_t *scaled_font,
+ cairo_font_extents_t *extents)
+{
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ cairo_matrix_t ctm;
+ cairo_font_options_t *font_options;
+ cairo_scaled_font_t *fallback_scaled_font;
+
+ /* painful way to get default font face used by toy api */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 0, 0);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+
+ cairo_set_font_size (cr, 1.);
+ cairo_scaled_font_get_scale_matrix (scaled_font, &ctm);
+ cairo_set_matrix (cr, &ctm);
+
+ font_options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (scaled_font, font_options);
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ fallback_scaled_font = cairo_scaled_font_reference (cairo_get_scaled_font (cr)),
+ cairo_scaled_font_set_user_data (scaled_font,
+ &fallback_scaled_font_key,
+ fallback_scaled_font,
+ cairo_scaled_font_destroy);
+
+ cairo_destroy (cr);
+
+ cairo_scaled_font_extents (fallback_scaled_font, extents);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *extents)
+{
+ char text[2] = "\0";
+
+ /* XXX only works for ASCII. need ucs4_to_utf8 :( */
+ text[0] = glyph;
+
+ cairo_set_scaled_font (cr,
+ cairo_scaled_font_get_user_data (scaled_font,
+ &fallback_scaled_font_key));
+ cairo_show_text (cr, text);
+ cairo_text_extents (cr, text, extents);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_font_face_t *
+get_user_font_face (void)
+{
+ static cairo_font_face_t *user_font_face = NULL;
+
+ if (!user_font_face) {
+ user_font_face = cairo_user_font_face_create ();
+ cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
+ cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
+ }
+
+ return user_font_face;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ const char text[] = TEXT;
+ cairo_font_extents_t font_extents;
+ cairo_text_extents_t extents;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+
+#ifdef ROTATED
+ cairo_translate (cr, TEXT_SIZE, 0);
+ cairo_rotate (cr, .6);
+#endif
+
+ cairo_set_font_face (cr, get_user_font_face ());
+ cairo_set_font_size (cr, TEXT_SIZE);
+
+ cairo_font_extents (cr, &font_extents);
+ cairo_text_extents (cr, text, &extents);
+
+ /* logical boundaries in red */
+ cairo_move_to (cr, 0, BORDER);
+ cairo_rel_line_to (cr, WIDTH, 0);
+ cairo_move_to (cr, 0, BORDER + font_extents.ascent);
+ cairo_rel_line_to (cr, WIDTH, 0);
+ cairo_move_to (cr, 0, BORDER + font_extents.ascent + font_extents.descent);
+ cairo_rel_line_to (cr, WIDTH, 0);
+ cairo_move_to (cr, BORDER, 0);
+ cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
+ cairo_move_to (cr, BORDER + extents.x_advance, 0);
+ cairo_rel_line_to (cr, 0, 2*BORDER + TEXT_SIZE);
+ cairo_set_source_rgb (cr, 1, 0, 0);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+
+ /* ink boundaries in green */
+ cairo_rectangle (cr,
+ BORDER + extents.x_bearing, BORDER + font_extents.ascent + extents.y_bearing,
+ extents.width, extents.height);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke (cr);
+
+ /* text in gray */
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
+ cairo_show_text (cr, text);
+
+
+ /* filled version of text in light blue */
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_move_to (cr, BORDER, BORDER + font_extents.height + BORDER + font_extents.ascent);
+ cairo_text_path (cr, text);
+ cairo_fill (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test);
+}
commit c914377f35e1e3396571fc027b7f53854db7d896
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 20:33:15 2008 -0400
Add public API cairo_scaled_font_get_scale_matrix()
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index b71b97a..c6d5287 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -278,6 +278,7 @@ cairo_scaled_font_get_font_face
cairo_scaled_font_get_font_options
cairo_scaled_font_get_font_matrix
cairo_scaled_font_get_ctm
+cairo_scaled_font_get_scale_matrix
cairo_scaled_font_get_type
cairo_scaled_font_get_reference_count
cairo_scaled_font_set_user_data
diff --git a/doc/public/tmpl/cairo-scaled-font.sgml b/doc/public/tmpl/cairo-scaled-font.sgml
index 4c8ee6c..97922ef 100644
--- a/doc/public/tmpl/cairo-scaled-font.sgml
+++ b/doc/public/tmpl/cairo-scaled-font.sgml
@@ -155,6 +155,15 @@ size and transformation and a certain set of font options.
@ctm:
+<!-- ##### FUNCTION cairo_scaled_font_get_scale_matrix ##### -->
+<para>
+
+</para>
+
+ at scaled_font:
+ at scale_matrix:
+
+
<!-- ##### FUNCTION cairo_scaled_font_get_type ##### -->
<para>
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 8104d05..b2f0c14 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1990,6 +1990,30 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font,
slim_hidden_def (cairo_scaled_font_get_ctm);
/**
+ * cairo_scaled_font_get_scale_matrix:
+ * @scaled_font: a #cairo_scaled_font_t
+ * @scale_matrix: return value for the matrix
+ *
+ * Stores the scale matrix of @scaled_font into @matrix.
+ * The scale matrix is product of the font matrix and the ctm
+ * associated with the scaled font, and hence is the matrix mapping from
+ * font space to device space.
+ *
+ * Since: 1.8
+ **/
+void
+cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font,
+ cairo_matrix_t *scale_matrix)
+{
+ if (scaled_font->status) {
+ cairo_matrix_init_identity (scale_matrix);
+ return;
+ }
+
+ *scale_matrix = scaled_font->scale;
+}
+
+/**
* cairo_scaled_font_get_font_options:
* @scaled_font: a #cairo_scaled_font_t
* @options: return value for the font options
diff --git a/src/cairo.h b/src/cairo.h
index 19ef7f0..179c45f 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1276,6 +1276,10 @@ cairo_scaled_font_get_ctm (cairo_scaled_font_t *scaled_font,
cairo_matrix_t *ctm);
cairo_public void
+cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font,
+ cairo_matrix_t *scale_matrix);
+
+cairo_public void
cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
cairo_font_options_t *options);
commit 90d62a0d33cd9e0736bb747d7f025a0fb1025732
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 20:31:24 2008 -0400
[src] Make make check pass
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 1cb0f40..86aeff9 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -662,6 +662,7 @@ cairo_surface_flush (cairo_surface_t *surface)
status = _cairo_surface_set_error (surface, status);
}
}
+slim_hidden_def (cairo_surface_flush);
/**
* cairo_surface_mark_dirty:
diff --git a/src/cairoint.h b/src/cairoint.h
index 841fe58..54cd0d8 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2375,6 +2375,7 @@ slim_hidden_proto (cairo_stroke_preserve);
slim_hidden_proto (cairo_surface_create_similar);
slim_hidden_proto (cairo_surface_destroy);
slim_hidden_proto (cairo_surface_finish);
+slim_hidden_proto (cairo_surface_flush);
slim_hidden_proto (cairo_surface_get_content);
slim_hidden_proto (cairo_surface_get_device_offset);
slim_hidden_proto (cairo_surface_get_font_options);
commit 9cc147a142e98b49b7f8289a340f2e498970ef99
Author: Jeff Muizelaar <jeff at infidigm.net>
Date: Sat May 24 20:17:38 2008 -0400
Avoid deadlock when clearing caches
cairo_surface_destroy and _cairo_scaled_font_fini will call destroy closures
which may call functions that attempt to acquire the mutex resulting in a
deadlock. We fix this by releasing the lock for the call to
cairo_surface_destroy or _cairo_scaled_font_fini.
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index c0bfbaf..2685d49 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1516,13 +1516,20 @@ UNLOCK:
static void
_cairo_pattern_reset_solid_surface_cache (void)
{
- int i;
-
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
- for (i = 0; i < solid_surface_cache.size; i++)
- cairo_surface_destroy (solid_surface_cache.cache[i].surface);
- solid_surface_cache.size = 0;
+ /* remove surfaces starting from the end so that solid_surface_cache.cache
+ * is always in a consistent state when we release the mutex. */
+ while (solid_surface_cache.size) {
+ cairo_surface_t *surface = solid_surface_cache.cache[solid_surface_cache.size-1].surface;
+ solid_surface_cache.size--;
+
+ /* release the lock to avoid the possibility of a recursive
+ * deadlock when the scaled font destroy closure gets called */
+ CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
+ cairo_surface_destroy (surface);
+ CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
+ }
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
}
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index b46f8dc..8104d05 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -347,7 +347,6 @@ _cairo_scaled_font_map_unlock (void)
void
_cairo_scaled_font_map_destroy (void)
{
- int i;
cairo_scaled_font_map_t *font_map;
cairo_scaled_font_t *scaled_font;
@@ -358,15 +357,23 @@ _cairo_scaled_font_map_destroy (void)
goto CLEANUP_MUTEX_LOCK;
}
- for (i = 0; i < font_map->num_holdovers; i++) {
- scaled_font = font_map->holdovers[i];
- /* We should only get here through the reset_static_data path
- * and there had better not be any active references at that
- * point. */
+ /* remove scaled_fonts starting from the end so that font_map->holdovers
+ * is always in a consistent state when we release the mutex. */
+ while (font_map->num_holdovers) {
+ scaled_font = font_map->holdovers[font_map->num_holdovers-1];
+
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
_cairo_hash_table_remove (font_map->hash_table,
&scaled_font->hash_entry);
+
+ font_map->num_holdovers--;
+
+ /* release the lock to avoid the possibility of a recursive
+ * deadlock when the scaled font destroy closure gets called */
+ CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_fini (scaled_font);
+ CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
+
free (scaled_font);
}
commit 4957a7894741f5a1941dcc06cc5a3a0551afcdad
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 15:16:44 2008 -0400
[test/surface-finish-twice.c] Adapt to recent change that multiple finish is ok
diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index 62acf71..3751939 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -63,7 +63,11 @@ draw (cairo_t *cr, int width, int height)
return CAIRO_TEST_FAILURE;
cairo_surface_finish (surface);
- if (cairo_surface_status (surface) != CAIRO_STATUS_SURFACE_FINISHED)
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+ return CAIRO_TEST_FAILURE;
+
+ cairo_surface_finish (surface);
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
return CAIRO_TEST_FAILURE;
cairo_surface_destroy (surface);
commit a30209402c7160af257e1ea027e9e2cdab5b5aec
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 14:57:56 2008 -0400
[cairo-gstate] Drop glyphs out of surface boundaries in show_glyphs()
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0f35b7f..fc69661 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -64,7 +64,8 @@ static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_glyph_t *transformed_glyphs);
+ cairo_glyph_t *transformed_glyphs,
+ int *num_transformed_glyphs);
cairo_status_t
_cairo_gstate_init (cairo_gstate_t *gstate,
@@ -1543,7 +1544,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
- transformed_glyphs);
+ transformed_glyphs, &num_glyphs);
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
@@ -1587,7 +1588,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
- transformed_glyphs);
+ transformed_glyphs, NULL);
CAIRO_MUTEX_LOCK (gstate->scaled_font->mutex);
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
@@ -1623,39 +1624,94 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
* @num_glyphs: the number of elements in @glyphs
* @transformed_glyphs: a pre-allocated array of at least @num_glyphs
* #cairo_glyph_t objects
+ * @num_transformed_glyphs: the number of elements in @transformed_glyphs
+ * after dropping out of bounds glyphs, or %NULL if glyphs shouldn't be
+ * dropped
*
* Transform an array of glyphs to backend space by first adding the offset
* of the font matrix, then transforming from user space to backend space.
* The result of the transformation is placed in @transformed_glyphs.
+ *
+ * This also uses information from the scaled font and the surface to
+ * cull/drop glyphs that will not be visible.
**/
static void
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs,
- cairo_glyph_t *transformed_glyphs)
+ cairo_glyph_t *transformed_glyphs,
+ int *num_transformed_glyphs)
{
- int i;
+ int i, j;
cairo_matrix_t *ctm = &gstate->ctm;
+ cairo_matrix_t *font_matrix = &gstate->font_matrix;
cairo_matrix_t *device_transform = &gstate->target->device_transform;
+ cairo_bool_t drop = FALSE;
+ double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+
+ if (num_transformed_glyphs != NULL) {
+ cairo_rectangle_int_t surface_extents;
+ double scale = _cairo_scaled_font_get_max_scale (gstate->scaled_font);
+
+ drop = TRUE;
+
+ if (_cairo_surface_get_extents (gstate->target, &surface_extents))
+ drop = FALSE; /* unbounded surface */
+ else {
+ /* XXX We currently drop any glyphs that has its position outside
+ * of the surface boundaries by a safety margin depending on the
+ * font scale. This however can fail in extreme cases where the
+ * font has really long swashes for example... We can correctly
+ * handle that by looking the glyph up and using its device bbox
+ * to device if it's going to be visible, but I'm not inclined to
+ * do that now.
+ */
+ x1 = surface_extents.x - 2*scale;
+ y1 = surface_extents.y - 2*scale;
+ x2 = surface_extents.x + surface_extents.width + scale;
+ y2 = surface_extents.y + surface_extents.height + scale;
+ }
+
+ if (!drop)
+ *num_transformed_glyphs = num_glyphs;
+ } else
+ num_transformed_glyphs = &j;
+
+#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
if (_cairo_matrix_is_identity (ctm) &&
_cairo_matrix_is_identity (device_transform) &&
- gstate->font_matrix.x0 == 0 && gstate->font_matrix.y0 == 0)
+ font_matrix->x0 == 0 && font_matrix->y0 == 0)
{
- memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+ if (!drop)
+ memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+ else {
+ for (j = 0, i = 0; i < num_glyphs; i++)
+ {
+ transformed_glyphs[j].index = glyphs[i].index;
+ transformed_glyphs[j].x = glyphs[i].x;
+ transformed_glyphs[j].y = glyphs[i].y;
+ if (KEEP_GLYPH (transformed_glyphs[j]))
+ j++;
+ }
+ *num_transformed_glyphs = j;
+ }
}
else if (_cairo_matrix_is_translation (ctm) &&
_cairo_matrix_is_translation (device_transform))
{
- double tx = gstate->font_matrix.x0 + ctm->x0 + device_transform->x0;
- double ty = gstate->font_matrix.y0 + ctm->y0 + device_transform->y0;
+ double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
+ double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
- for (i = 0; i < num_glyphs; i++)
+ for (j = 0, i = 0; i < num_glyphs; i++)
{
- transformed_glyphs[i].index = glyphs[i].index;
- transformed_glyphs[i].x = glyphs[i].x + tx;
- transformed_glyphs[i].y = glyphs[i].y + ty;
+ transformed_glyphs[j].index = glyphs[i].index;
+ transformed_glyphs[j].x = glyphs[i].x + tx;
+ transformed_glyphs[j].y = glyphs[i].y + ty;
+ if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+ j++;
}
+ *num_transformed_glyphs = j;
}
else
{
@@ -1669,12 +1725,15 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
cairo_matrix_multiply (&aggregate_transform,
&aggregate_transform, device_transform);
- for (i = 0; i < num_glyphs; i++)
+ for (j = 0, i = 0; i < num_glyphs; i++)
{
- transformed_glyphs[i] = glyphs[i];
+ transformed_glyphs[j] = glyphs[i];
cairo_matrix_transform_point (&aggregate_transform,
- &transformed_glyphs[i].x,
- &transformed_glyphs[i].y);
+ &transformed_glyphs[j].x,
+ &transformed_glyphs[j].y);
+ if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+ j++;
}
+ *num_transformed_glyphs = j;
}
}
commit 1b5e2144fb77ffeb0626dff558d9d82351279e0b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 14:57:31 2008 -0400
[cairo-scaled-font] Implement _cairo_scaled_font_get_max_scale()
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 4cf6a37..86fbec6 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -94,6 +94,7 @@ struct _cairo_scaled_font {
/* "live" scaled_font members */
cairo_matrix_t scale; /* font space => device space */
cairo_matrix_t scale_inverse; /* device space => font space */
+ double max_scale; /* maximum x/y expansion of scale */
cairo_font_extents_t extents; /* user space */
/* The mutex protects modification to all subsequent fields. */
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index b4c1ad3..b46f8dc 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -195,6 +195,7 @@ static const cairo_scaled_font_t _cairo_scaled_font_nil = {
TRUE, /* finished */
{ 1., 0., 0., 1., 0, 0}, /* scale */
{ 1., 0., 0., 1., 0, 0}, /* scale_inverse */
+ 1., /* max_scale */
{ 0., 0., 0., 0., 0. }, /* extents */
CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
NULL, /* glyphs */
@@ -480,6 +481,8 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
&scaled_font->font_matrix,
&scaled_font->ctm);
+ scaled_font->max_scale = MAX (fabs (scaled_font->scale.xx) + fabs (scaled_font->scale.xy),
+ fabs (scaled_font->scale.yx) + fabs (scaled_font->scale.yy));
scaled_font->scale_inverse = scaled_font->scale;
status = cairo_matrix_invert (&scaled_font->scale_inverse);
if (status) {
@@ -1906,6 +1909,13 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
return status;
}
+double
+_cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font)
+{
+ return scaled_font->max_scale;
+}
+
+
/**
* cairo_scaled_font_get_font_face:
* @scaled_font: a #cairo_scaled_font_t
diff --git a/src/cairoint.h b/src/cairoint.h
index 2a7356e..841fe58 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1551,6 +1551,9 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_info_t info,
cairo_scaled_glyph_t **scaled_glyph_ret);
+cairo_private double
+_cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font);
+
cairo_private void
_cairo_scaled_font_map_destroy (void);
commit 479936ecea5d0e7cf3eee1aad6b016067f63e20b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 14:57:06 2008 -0400
[cairoint] Sort prototypes
diff --git a/src/cairoint.h b/src/cairoint.h
index bf85e64..2a7356e 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1267,25 +1267,6 @@ _cairo_color_equal (const cairo_color_t *color_a,
/* cairo-font-face.c */
-cairo_private void
-_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font);
-
-cairo_private void
-_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font);
-
-cairo_private void
-_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font);
-
-cairo_private cairo_status_t
-_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
- cairo_status_t status);
-
-cairo_private cairo_scaled_font_t *
-_cairo_scaled_font_create_in_error (cairo_status_t status);
-
-cairo_private void
-_cairo_scaled_font_reset_static_data (void);
-
extern const cairo_private cairo_font_face_t _cairo_font_face_nil;
cairo_private void
@@ -1471,6 +1452,26 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
/* cairo-scaled-font.c */
+cairo_private void
+_cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font);
+
+cairo_private void
+_cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font);
+
+cairo_private void
+_cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font);
+
+cairo_private cairo_status_t
+_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
+ cairo_status_t status);
+
+cairo_private cairo_scaled_font_t *
+_cairo_scaled_font_create_in_error (cairo_status_t status);
+
+cairo_private void
+_cairo_scaled_font_reset_static_data (void);
+
+
cairo_private cairo_status_t
_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
cairo_font_face_t *font_face,
commit e638e7652f8be552b50927bd332e9f46dcd92ab7
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 14:25:13 2008 -0400
[cairo-xlib] Fix bug introduced in yesterday's code shuffling. Oops.
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 20dc969..ec66c4d 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -3424,7 +3424,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
}
if (num_elts)
- status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
+ status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
scaled_font, op, src, attributes,
num_elts, width, glyphset_info);
commit 31c68e708f18c1f81efc3590346eeb684ef3702d
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sat May 24 13:17:31 2008 -0400
[cairo-surface] Minor code reshuffling
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 7ded02d..1cb0f40 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2131,7 +2131,6 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
cairo_status_t status;
cairo_scaled_font_t *dev_scaled_font = scaled_font;
cairo_pattern_t *dev_source;
- cairo_matrix_t font_matrix;
assert (! surface->is_snapshot);
@@ -2147,14 +2146,13 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (status)
return _cairo_surface_set_error (surface, status);
- cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
-
if (_cairo_surface_has_device_transform (surface) &&
! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
{
cairo_font_options_t font_options;
- cairo_matrix_t dev_ctm;
+ cairo_matrix_t dev_ctm, font_matrix;
+ cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
cairo_scaled_font_get_font_options (scaled_font, &font_options);
More information about the cairo-commit
mailing list