[cairo-commit] 3 commits - src/cairo-debug.c src/cairoint.h src/cairo-mutex-list-private.h src/cairo-ps-surface.c src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/cairo-win32-private.h src/cairo-win32-surface.c
Adrian Johnson
ajohnson at kemper.freedesktop.org
Tue Nov 16 05:42:35 PST 2010
src/cairo-debug.c | 4
src/cairo-mutex-list-private.h | 4
src/cairo-ps-surface.c | 5 -
src/cairo-win32-font.c | 163 +++++++++++++++++++++++++++++++++++--
src/cairo-win32-printing-surface.c | 157 +++++++++++++++++++++--------------
src/cairo-win32-private.h | 11 ++
src/cairo-win32-surface.c | 54 +++++++-----
src/cairoint.h | 3
8 files changed, 313 insertions(+), 88 deletions(-)
New commits:
commit 653ceb517fe756b042a3cf8322a36cbfe71ddbd8
Author: Koji Otani <sho at bbr.jp>
Date: Wed Nov 17 00:07:03 2010 +1030
PS: fix embedding of grayscale jpegs
https://bugs.freedesktop.org/show_bug.cgi?id=31632
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 71d8398..0be68bf 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2377,11 +2377,12 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface,
" /Width %d def\n"
" /Height %d def\n"
" /BitsPerComponent %d def\n"
- " /Decode [ 0 1 0 1 0 1 ] def\n",
+ " /Decode [ %s ] def\n",
info.num_components == 1 ? "DeviceGray" : "DeviceRGB",
info.width,
info.height,
- info.bits_per_component);
+ info.bits_per_component,
+ info.num_components == 1 ? "0 1" : "0 1 0 1 0 1");
if (surface->use_string_datasource) {
_cairo_output_stream_printf (surface->stream,
commit d5656394787c29daf31fff085639066287b0f7b7
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Nov 16 23:53:05 2010 +1030
win32-print: print as unicode where possible
One of the problems identified in
https://bugzilla.mozilla.org/show_bug.cgi?id=454532 is that there are
some older printer drivers that do not work with ExtTextOut and the
ETO_GLYPH_INDEX option.
Fix this by where possible mapping glyph indices back to unicode and
calling ExtTextOut without ETO_GLYPH_INDEX. Glyphs that can not be
mapped back to unicode are printed with ETO_GLYPH_INDEX.
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 1e8bd26..806cab8 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1431,6 +1431,94 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
}
static cairo_int_status_t
+_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ cairo_clip_t *clip,
+ int *remaining_glyphs)
+{
+ cairo_matrix_t ctm;
+ cairo_glyph_t *unicode_glyphs;
+ cairo_scaled_font_subsets_glyph_t subset_glyph;
+ int i, first;
+ cairo_bool_t sequence_is_unicode;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ /* Where possible reverse the glyph indices back to unicode
+ * characters. Strings of glyphs that could not be reversed to
+ * unicode will be printed with ETO_GLYPH_INDEX.
+ *
+ * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
+ * operation, the font subsetting function
+ * _cairo_scaled_font_subsets_map_glyph() is used to obtain
+ * the unicode value because it caches the reverse mapping in
+ * the subsets.
+ */
+
+ if (surface->has_ctm) {
+ for (i = 0; i < num_glyphs; i++)
+ cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y);
+ cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm);
+ scaled_font = cairo_scaled_font_create (scaled_font->font_face,
+ &scaled_font->font_matrix,
+ &ctm,
+ &scaled_font->options);
+ }
+
+ unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+ if (unicode_glyphs == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (unicode_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
+ for (i = 0; i < num_glyphs; i++) {
+ status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
+ scaled_font,
+ glyphs[i].index,
+ NULL, 0,
+ &subset_glyph);
+ if (status)
+ goto fail;
+
+ unicode_glyphs[i].index = subset_glyph.unicode;
+ }
+
+ i = 0;
+ first = 0;
+ sequence_is_unicode = unicode_glyphs[0].index <= 0xffff;
+ while (i < num_glyphs) {
+ if (i == num_glyphs - 1 ||
+ ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode))
+ {
+ status = _cairo_win32_surface_show_glyphs_internal (
+ surface,
+ op,
+ source,
+ sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first],
+ i - first + 1,
+ scaled_font,
+ clip,
+ remaining_glyphs,
+ ! sequence_is_unicode);
+ first = i + 1;
+ if (i < num_glyphs - 1)
+ sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff;
+ }
+ i++;
+ }
+
+fail:
+ if (surface->has_ctm)
+ cairo_scaled_font_destroy (scaled_font);
+
+ free (unicode_glyphs);
+
+ return status;
+}
+
+static cairo_int_status_t
_cairo_win32_printing_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
const cairo_pattern_t *source,
@@ -1514,67 +1602,14 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
source->type == CAIRO_PATTERN_TYPE_SOLID)
{
- cairo_matrix_t ctm;
- cairo_glyph_t *type1_glyphs = NULL;
- cairo_scaled_font_subsets_glyph_t subset_glyph;
-
- /* Calling ExtTextOutW() with ETO_GLYPH_INDEX and a Type 1
- * font on a printer DC prints garbled text. The text displays
- * correctly on a display DC. When using a printer
- * DC, ExtTextOutW() only works with characters and not glyph
- * indices.
- *
- * For Type 1 fonts the glyph indices are converted back to
- * unicode characters before calling _cairo_win32_surface_show_glyphs().
- *
- * As _cairo_win32_scaled_font_index_to_ucs4() is a slow
- * operation, the font subsetting function
- * _cairo_scaled_font_subsets_map_glyph() is used to obtain
- * the unicode value because it caches the reverse mapping in
- * the subsets.
- */
- if (_cairo_win32_scaled_font_is_type1 (scaled_font)) {
- type1_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
- if (type1_glyphs == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (type1_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
- for (i = 0; i < num_glyphs; i++) {
- status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
- scaled_font,
- type1_glyphs[i].index,
- NULL, 0,
- &subset_glyph);
- if (status)
- return status;
-
- type1_glyphs[i].index = subset_glyph.unicode;
- }
- glyphs = type1_glyphs;
- }
-
- if (surface->has_ctm || surface->has_gdi_ctm) {
- cairo_matrix_multiply (&ctm, &surface->ctm, &surface->gdi_ctm);
- for (i = 0; i < num_glyphs; i++)
- cairo_matrix_transform_point (&ctm, &glyphs[i].x, &glyphs[i].y);
- cairo_matrix_multiply (&ctm, &scaled_font->ctm, &ctm);
- scaled_font = cairo_scaled_font_create (scaled_font->font_face,
- &scaled_font->font_matrix,
- &ctm,
- &scaled_font->options);
- }
- status = _cairo_win32_surface_show_glyphs (surface, op,
- source, glyphs,
- num_glyphs, scaled_font,
- clip,
- remaining_glyphs);
- if (surface->has_ctm)
- cairo_scaled_font_destroy (scaled_font);
-
- if (type1_glyphs != NULL)
- free (type1_glyphs);
-
- return status;
+ return _cairo_win32_printing_surface_emit_win32_glyphs (surface,
+ op,
+ source,
+ glyphs,
+ num_glyphs,
+ scaled_font,
+ clip,
+ remaining_glyphs);
}
#endif
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index cde27b7..efb0c1e 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -156,6 +156,17 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region);
cairo_int_status_t
+_cairo_win32_surface_show_glyphs_internal (void *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ cairo_clip_t *clip,
+ int *remaining_glyphs,
+ cairo_bool_t glyph_indices);
+
+cairo_int_status_t
_cairo_win32_surface_show_glyphs (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 660aaba..c335d97 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1494,14 +1494,15 @@ _cairo_win32_surface_flush (void *abstract_surface)
#define STACK_GLYPH_SIZE 256
cairo_int_status_t
-_cairo_win32_surface_show_glyphs (void *surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- cairo_clip_t *clip,
- int *remaining_glyphs)
+_cairo_win32_surface_show_glyphs_internal (void *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ cairo_clip_t *clip,
+ int *remaining_glyphs,
+ cairo_bool_t glyph_indexing)
{
#if CAIRO_HAS_WIN32_FONT
cairo_win32_surface_t *dst = surface;
@@ -1616,19 +1617,10 @@ _cairo_win32_surface_show_glyphs (void *surface,
}
}
- /* Using glyph indices for a Type 1 font does not work on a
- * printer DC. The win32 printing surface will convert the the
- * glyph indices of Type 1 fonts to the unicode values.
- */
- if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) &&
- _cairo_win32_scaled_font_is_type1 (scaled_font))
- {
- glyph_index_option = 0;
- }
- else
- {
+ if (glyph_indexing)
glyph_index_option = ETO_GLYPH_INDEX;
- }
+ else
+ glyph_index_option = 0;
win_result = ExtTextOutW(dst->dc,
start_x,
@@ -1656,6 +1648,28 @@ _cairo_win32_surface_show_glyphs (void *surface,
#undef STACK_GLYPH_SIZE
+cairo_int_status_t
+_cairo_win32_surface_show_glyphs (void *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ cairo_clip_t *clip,
+ int *remaining_glyphs)
+{
+ return _cairo_win32_surface_show_glyphs_internal (surface,
+ op,
+ source,
+ glyphs,
+ num_glyphs,
+ scaled_font,
+ clip,
+ remaining_glyphs,
+ TRUE);
+}
+
+
/**
* cairo_win32_surface_create:
* @hdc: the DC to create a surface for
commit eb29a25dd6dddc511388bf883c9b95843ecdb823
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Tue Nov 16 23:48:39 2010 +1030
win32: Use a font_face hash table to provide unique font faces
Similar to the freetype and toy font backends, use a hash table
to map logfont,hfont to font faces.
This fixes the multiple embedding of the same font in PDF.
https://bugs.freedesktop.org/show_bug.cgi?id=24849
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index c956753..e9e72b6 100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
@@ -69,6 +69,10 @@ cairo_debug_reset_static_data (void)
_cairo_ft_font_reset_static_data ();
#endif
+#if CAIRO_HAS_WIN32_FONT
+ _cairo_win32_font_reset_static_data ();
+#endif
+
_cairo_intern_string_reset_static_data ();
_cairo_scaled_font_reset_static_data ();
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 5827667..7d5ba02 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -51,6 +51,10 @@ CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
#endif
+#if CAIRO_HAS_WIN32_FONT
+CAIRO_MUTEX_DECLARE (_cairo_win32_font_face_mutex)
+#endif
+
#if CAIRO_HAS_XLIB_SURFACE
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
#endif
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 479c672..a585163 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -47,6 +47,8 @@
#include "cairo-win32-private.h"
#include "cairo-error-private.h"
+#include <wchar.h>
+
#ifndef SPI_GETFONTSMOOTHINGTYPE
#define SPI_GETFONTSMOOTHINGTYPE 0x200a
#endif
@@ -1934,6 +1936,120 @@ const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
_cairo_win32_font_face_scaled_font_create
};
+/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
+ * The primary purpose of this mapping is to provide unique
+ * #cairo_font_face_t values so that our cache and mapping from
+ * #cairo_font_face_t => #cairo_scaled_font_t works. Once the
+ * corresponding #cairo_font_face_t objects fall out of downstream
+ * caches, we don't need them in this hash table anymore.
+ *
+ * Modifications to this hash table are protected by
+ * _cairo_win32_font_face_mutex.
+ */
+
+static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL;
+
+static int
+_cairo_win32_font_face_keys_equal (const void *key_a,
+ const void *key_b);
+
+static void
+_cairo_win32_font_face_hash_table_destroy (void)
+{
+ cairo_win32_font_face_t *font_face;
+
+ CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
+
+ if (cairo_win32_font_face_hash_table) {
+ /* This is rather inefficient, but destroying the hash table
+ * is something we only do during debugging, (during
+ * cairo_debug_reset_static_data), when efficiency is not
+ * relevant. */
+ while (1) {
+ font_face= _cairo_hash_table_random_entry (cairo_win32_font_face_hash_table,
+ NULL);
+ if (font_face == NULL)
+ break;
+ _cairo_hash_table_remove (cairo_win32_font_face_hash_table,
+ &font_face->base.hash_entry);
+
+ cairo_font_face_destroy (&font_face->base);
+ }
+
+ _cairo_hash_table_destroy (cairo_win32_font_face_hash_table);
+
+ cairo_win32_font_face_hash_table = NULL;
+ }
+
+ CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+}
+
+static cairo_hash_table_t *
+_cairo_win32_font_face_hash_table_lock (void)
+{
+ CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex);
+
+ if (unlikely (cairo_win32_font_face_hash_table == NULL))
+ {
+ cairo_win32_font_face_hash_table =
+ _cairo_hash_table_create (_cairo_win32_font_face_keys_equal);
+
+ if (unlikely (cairo_win32_font_face_hash_table == NULL)) {
+ CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return NULL;
+ }
+ }
+
+ return cairo_win32_font_face_hash_table;
+}
+
+static void
+_cairo_win32_font_face_hash_table_unlock (void)
+{
+ CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
+}
+
+static void
+_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
+ LOGFONTW *logfont,
+ HFONT font)
+{
+ unsigned long hash = _CAIRO_HASH_INIT_VALUE;
+
+ key->logfont = *logfont;
+ key->hfont = font;
+
+ hash = _cairo_hash_bytes (0, logfont->lfFaceName, wcslen(logfont->lfFaceName));
+ hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight));
+ hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic));
+ hash = _cairo_hash_bytes (hash, &font, sizeof(font));
+
+ key->base.hash_entry.hash = hash;
+}
+
+static int
+_cairo_win32_font_face_keys_equal (const void *key_a,
+ const void *key_b)
+{
+ const cairo_win32_font_face_t *face_a = key_a;
+ const cairo_win32_font_face_t *face_b = key_b;
+
+ if (face_a->logfont.lfWeight == face_b->logfont.lfWeight &&
+ face_a->logfont.lfItalic == face_b->logfont.lfItalic &&
+ face_a->logfont.lfUnderline == face_b->logfont.lfUnderline &&
+ face_a->logfont.lfStrikeOut == face_b->logfont.lfStrikeOut &&
+ face_a->logfont.lfCharSet == face_b->logfont.lfCharSet &&
+ face_a->logfont.lfOutPrecision == face_b->logfont.lfOutPrecision &&
+ face_a->logfont.lfClipPrecision == face_b->logfont.lfClipPrecision &&
+ face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily &&
+ (wcscmp (face_a->logfont.lfFaceName, face_a->logfont.lfFaceName) == 0) &&
+ face_a->hfont == face_b->hfont)
+ return TRUE;
+ else
+ return FALSE;
+}
+
/**
* cairo_win32_font_face_create_for_logfontw_hfont:
* @logfont: A #LOGFONTW structure specifying the font to use.
@@ -1956,20 +2072,51 @@ const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
{
- cairo_win32_font_face_t *font_face;
+ cairo_win32_font_face_t *font_face, key;
+ cairo_hash_table_t *hash_table;
+ cairo_status_t status;
+
+ hash_table = _cairo_win32_font_face_hash_table_lock ();
+ if (unlikely (hash_table == NULL)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
+
+ _cairo_win32_font_face_init_key (&key, logfont, font);
+
+ /* Return existing unscaled font if it exists in the hash table. */
+ font_face = _cairo_hash_table_lookup (hash_table,
+ &key.base.hash_entry);
+ if (font_face != NULL) {
+ cairo_font_face_reference (&font_face->base);
+ goto DONE;
+ }
+ /* Otherwise create it and insert into hash table. */
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return (cairo_font_face_t *)&_cairo_font_face_nil;
+ goto FAIL;
}
- font_face->logfont = *logfont;
- font_face->hfont = font;
-
+ _cairo_win32_font_face_init_key (font_face, logfont, font);
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
+ assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash);
+ status = _cairo_hash_table_insert (hash_table,
+ &font_face->base.hash_entry);
+ if (unlikely (status))
+ goto FAIL;
+
+DONE:
+ _cairo_win32_font_face_hash_table_unlock ();
+
return &font_face->base;
+
+FAIL:
+ _cairo_win32_font_face_hash_table_unlock ();
+
+ return (cairo_font_face_t *)&_cairo_font_face_nil;
}
/**
@@ -2178,3 +2325,9 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
}
*device_to_logical = win_font->device_to_logical;
}
+
+void
+_cairo_win32_font_reset_static_data (void)
+{
+ _cairo_win32_font_face_hash_table_destroy ();
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 539d92e..e2946cf 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -407,6 +407,9 @@ _cairo_toy_font_face_reset_static_data (void);
cairo_private void
_cairo_ft_font_reset_static_data (void);
+cairo_private void
+_cairo_win32_font_reset_static_data (void);
+
/* the font backend interface */
struct _cairo_unscaled_font_backend {
More information about the cairo-commit
mailing list