Bug 454532. cairo: Print as Unicode. r=jrmuizel

--HG--
extra : rebase_source : 3b10e50f3763535d7eee5aa5dcdc6ca2ad445ad3
This commit is contained in:
Adrian Johnson 2011-09-14 11:44:15 -07:00
parent 3b86f7c833
commit f1f5b007ce
5 changed files with 475 additions and 81 deletions

View File

@ -174,6 +174,8 @@ quartz-get-image-performance: Make cairo_quartz_get_image faster in the failure
lround-c99-only.patch: Only use lround in C99 programs.
unicode-printing.patch: Print as unicode (bug 454532)
==== pixman patches ====
pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.

View File

@ -1430,6 +1430,94 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
return status;
}
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,
@ -1538,67 +1626,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) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FINISH;
}
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)
goto FINISH;
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 || surface->has_gdi_ctm)
cairo_scaled_font_destroy (scaled_font);
if (type1_glyphs != NULL)
free (type1_glyphs);
status = _cairo_win32_printing_surface_emit_win32_glyphs (surface,
op,
source,
glyphs,
num_glyphs,
scaled_font,
clip,
remaining_glyphs);
goto FINISH;
}
#endif

View File

@ -161,6 +161,17 @@ cairo_status_t
_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,

View File

@ -1612,14 +1612,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)
{
#ifdef CAIRO_HAS_WIN32_FONT
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
@ -1742,19 +1743,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,
@ -1783,6 +1775,27 @@ _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);
}
static cairo_surface_t *
cairo_win32_surface_create_internal (HDC hdc, cairo_format_t format)
{

View File

@ -0,0 +1,333 @@
diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
--- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
@@ -1426,16 +1426,104 @@ _cairo_win32_printing_surface_fill (void
}
fflush(stderr);
return status;
}
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,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip,
int *remaining_glyphs)
@@ -1533,77 +1621,24 @@ _cairo_win32_printing_surface_show_glyph
}
}
#endif
#if CAIRO_HAS_WIN32_FONT
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) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FINISH;
- }
- 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)
- goto FINISH;
-
- 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 || surface->has_gdi_ctm)
- cairo_scaled_font_destroy (scaled_font);
-
- if (type1_glyphs != NULL)
- free (type1_glyphs);
-
+ status = _cairo_win32_printing_surface_emit_win32_glyphs (surface,
+ op,
+ source,
+ glyphs,
+ num_glyphs,
+ scaled_font,
+ clip,
+ remaining_glyphs);
goto FINISH;
}
#endif
SaveDC (surface->dc);
old_ctm = surface->ctm;
old_has_ctm = surface->has_ctm;
surface->has_ctm = TRUE;
diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
--- a/gfx/cairo/cairo/src/cairo-win32-private.h
+++ b/gfx/cairo/cairo/src/cairo-win32-private.h
@@ -157,16 +157,27 @@ _cairo_win32_surface_get_extents (void
uint32_t
_cairo_win32_flags_for_dc (HDC dc);
cairo_status_t
_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,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip,
int *remaining_glyphs);
diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
@@ -1607,24 +1607,25 @@ static cairo_status_t
_cairo_win32_surface_flush (void *abstract_surface)
{
return _cairo_win32_surface_set_clip_region (abstract_surface, NULL);
}
#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)
{
#ifdef CAIRO_HAS_WIN32_FONT
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
#ifdef CAIRO_HAS_DWRITE_FONT
return _cairo_dwrite_show_glyphs_on_surface(surface, op, source, glyphs, num_glyphs, scaled_font, clip);
#endif
} else {
cairo_win32_surface_t *dst = surface;
@@ -1737,29 +1738,20 @@ _cairo_win32_surface_show_glyphs (void
dxy_buf[j+1] = _cairo_lround (logical_y - next_logical_y);
/* note that GDI coordinate system is inverted */
logical_x = next_logical_x;
logical_y = next_logical_y;
}
}
- /* 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))
- {
+ if (glyph_indexing)
+ glyph_index_option = ETO_GLYPH_INDEX;
+ else
glyph_index_option = 0;
- }
- else
- {
- glyph_index_option = ETO_GLYPH_INDEX;
- }
win_result = ExtTextOutW(dst->dc,
start_x,
start_y,
glyph_index_option | ETO_PDY,
NULL,
glyph_buf,
num_glyphs,
@@ -1778,16 +1770,37 @@ _cairo_win32_surface_show_glyphs (void
}
#else
return CAIRO_INT_STATUS_UNSUPPORTED;
#endif
}
#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);
+}
+
static cairo_surface_t *
cairo_win32_surface_create_internal (HDC hdc, cairo_format_t format)
{
cairo_win32_surface_t *surface;
RECT rect;
surface = malloc (sizeof (cairo_win32_surface_t));