[cairo-commit] 4 commits - src/cairo-quartz-font.c src/cairo-unicode.c src/cairoint.h test/Makefile.sources test/reference test/smp-glyph.c
Andrea Canciani
ranma42 at kemper.freedesktop.org
Tue Apr 25 16:06:57 UTC 2017
dev/null |binary
src/cairo-quartz-font.c | 25 +++++------
src/cairo-unicode.c | 39 ++++++++++++++---
src/cairoint.h | 4 +
test/Makefile.sources | 1
test/reference/smp-glyph.ref.png |binary
test/reference/smp-glyph.script.ref.png |binary
test/reference/text-glyph-range.quartz.ref.png |binary
test/smp-glyph.c | 56 +++++++++++++++++++++++++
9 files changed, 107 insertions(+), 18 deletions(-)
New commits:
commit a3cc46d2ccba44a538d05f0c5870b1a82f046350
Author: Andrea Canciani <ranma42 at gmail.com>
Date: Sun Mar 19 21:48:11 2017 +0100
quartz-font: Fix text-glyph-range
The index 0 is a legitimate index used for character codes that do not
correspond to any glyph in the font. Instead, the API reserves 0xFFFF
(kCGFontIndexInvalid) as the invalid index and defines 0xFFFE
(kCGFontIndexMax = kCGGlyphMax) as the maximum legal index.
Fixes text-glyph-range.
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 34ae87e7..47221421 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -106,6 +106,10 @@ static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL;
static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
+/* Defined in 10.11 */
+#define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */
+#define CGGLYPH_INVALID ((CGGlyph) 0xFFFF) /* kCGFontIndexInvalid */
+
static void
quartz_font_ensure_symbols(void)
{
@@ -403,14 +407,10 @@ _cairo_quartz_scaled_font_fini(void *abstract_font)
{
}
-#define INVALID_GLYPH 0x00
-
static inline CGGlyph
_cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
- if (index > 0xffff)
- return INVALID_GLYPH;
- return (CGGlyph) index;
+ return index <= CGGLYPH_MAX ? index : CGGLYPH_INVALID;
}
static cairo_int_status_t
@@ -427,7 +427,7 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
double xmin, ymin, xmax, ymax;
- if (glyph == INVALID_GLYPH)
+ if (unlikely (glyph == CGGLYPH_INVALID))
goto FAIL;
if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
@@ -561,7 +561,7 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
CGPathRef glyphPath;
cairo_path_fixed_t *path;
- if (glyph == INVALID_GLYPH) {
+ if (unlikely (glyph == CGGLYPH_INVALID)) {
_cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create());
return CAIRO_STATUS_SUCCESS;
}
@@ -627,7 +627,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
* Maybe we should draw a better missing-glyph slug or something,
* but this is ok for now.
*/
- if (glyph == INVALID_GLYPH) {
+ if (unlikely (glyph == CGGLYPH_INVALID)) {
surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
status = cairo_surface_status ((cairo_surface_t *) surface);
if (status)
diff --git a/test/reference/text-glyph-range.quartz.ref.png b/test/reference/text-glyph-range.quartz.ref.png
new file mode 100644
index 00000000..31d2a941
Binary files /dev/null and b/test/reference/text-glyph-range.quartz.ref.png differ
diff --git a/test/reference/text-glyph-range.quartz.xfail.png b/test/reference/text-glyph-range.quartz.xfail.png
deleted file mode 100644
index 9dcc7562..00000000
Binary files a/test/reference/text-glyph-range.quartz.xfail.png and /dev/null differ
commit fcb0a8ef36c9a84f586d38bd409d6a0e881890a7
Author: Andrea Canciani <ranma42 at gmail.com>
Date: Sat Mar 18 10:20:07 2017 +0100
quartz-font: Correct handling of SMP Unicode characters
Truncating the UCS4 representation to 16 bits only works for the Basic
Multilingual Plane, the other characters must be translated to a
surrogate pair.
Fixes smp-glyph.
Reported-by: Clerk Ma <clerkma at gmail.com>
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 897b2d01..34ae87e7 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -766,12 +766,13 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
{
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font;
cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font);
- UniChar u = (UniChar) ucs4;
- CGGlyph glyph;
+ CGGlyph glyph[2];
+ UniChar utf16[2];
- CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1);
+ int len = _cairo_ucs4_to_utf16 (ucs4, utf16);
+ CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, utf16, glyph, len);
- return glyph;
+ return glyph[0];
}
static cairo_int_status_t
commit 5584bf755c98703653eef06670abaeb4873f9ee5
Author: Andrea Canciani <ranma42 at gmail.com>
Date: Sat Mar 18 08:55:11 2017 +0100
unicode: Extract the UCS4 to UTF-16 conversion to a separate function
Reuse the function for the UTF-8 to UTF-16 conversion, but also make
it available for internal use by cairo.
diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c
index 88de3951..7933d12a 100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
@@ -342,6 +342,38 @@ _cairo_ucs4_to_utf8 (uint32_t unicode,
return bytes;
}
+/**
+ * _cairo_ucs4_to_utf16:
+ * @unicode: a UCS-4 character
+ * @utf16: buffer to write utf16 string into. Must have at least 2
+ * elements. Or %NULL.
+ *
+ * This space left intentionally blank.
+ *
+ * Return value: Number of elements in the utf16 string or 0 if an
+ * invalid unicode character
+ **/
+int
+_cairo_ucs4_to_utf16 (uint32_t unicode,
+ uint16_t *utf16)
+{
+ int len;
+
+ if (unicode < 0x10000) {
+ if (utf16)
+ utf16[0] = unicode;
+ return 1;
+ } else if (unicode < 0x110000) {
+ if (utf16) {
+ utf16[0] = (unicode - 0x10000) / 0x400 + 0xd800;
+ utf16[1] = (unicode - 0x10000) % 0x400 + 0xdc00;
+ }
+ return 2;
+ } else {
+ return 0;
+ }
+}
+
#if CAIRO_HAS_UTF8_TO_UTF16
/**
* _cairo_utf8_to_utf16:
@@ -401,12 +433,7 @@ _cairo_utf8_to_utf16 (const char *str,
for (i = 0; i < n16;) {
uint32_t wc = _utf8_get_char (in);
- if (wc < 0x10000) {
- str16[i++] = wc;
- } else {
- str16[i++] = (wc - 0x10000) / 0x400 + 0xd800;
- str16[i++] = (wc - 0x10000) % 0x400 + 0xdc00;
- }
+ i += _cairo_ucs4_to_utf16 (wc, str16 + i);
in = UTF8_NEXT_CHAR (in);
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 493d4610..1ae045c9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1872,6 +1872,10 @@ cairo_private int
_cairo_ucs4_to_utf8 (uint32_t unicode,
char *utf8);
+cairo_private int
+_cairo_ucs4_to_utf16 (uint32_t unicode,
+ uint16_t *utf16);
+
#if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS
# define CAIRO_HAS_UTF8_TO_UTF16 1
#endif
commit cb9f6273780bb2ffc710d2efdd4224d9096972cb
Author: Andrea Canciani <ranma42 at gmail.com>
Date: Sun Mar 19 10:37:36 2017 +0100
test: Add a test for characters in the SMP
Unicode characters in the Supplementary Multilingual Plane are encoded
as surrogate pairs in UTF-16. This test tries to verify that backends
do not perform UCS4 to UTF-16 conversion by truncation.
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 5ead2316..1ae62464 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -323,6 +323,7 @@ test_sources = \
smask-paint.c \
smask-stroke.c \
smask-text.c \
+ smp-glyph.c \
solid-pattern-cache-stress.c \
source-clip.c \
source-clip-scale.c \
diff --git a/test/reference/smp-glyph.ref.png b/test/reference/smp-glyph.ref.png
new file mode 100644
index 00000000..260332d3
Binary files /dev/null and b/test/reference/smp-glyph.ref.png differ
diff --git a/test/reference/smp-glyph.script.ref.png b/test/reference/smp-glyph.script.ref.png
new file mode 100644
index 00000000..d15848ce
Binary files /dev/null and b/test/reference/smp-glyph.script.ref.png differ
diff --git a/test/smp-glyph.c b/test/smp-glyph.c
new file mode 100644
index 00000000..486c43eb
--- /dev/null
+++ b/test/smp-glyph.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2017 Andrea Canciani
+ *
+ * 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
+ * Andrea Canciani not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Andrea Canciani makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * ANDREA CANCIANI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL ANDREA CANCIANI 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.
+ *
+ * Author: Andrea Canciani <ranma42 at gmail.com>
+ */
+
+#include "cairo-test.h"
+
+#define TEXT_SIZE 42
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0, 0, 0); /* black */
+
+ cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+
+ cairo_set_font_size (cr, TEXT_SIZE);
+ cairo_translate (cr, 0, TEXT_SIZE);
+
+ /* U+1F030, DOMINO TILE HORIZONTAL BACK */
+ cairo_show_text (cr, "\xf0\x9f\x80\xb0");
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (smp_glyph,
+ "Test glyphs for symbols in the Supplementary Multilingual Plane",
+ "text, glyphs", /* keywords */
+ NULL, /* requirements */
+ 64, 64,
+ NULL, draw)
More information about the cairo-commit
mailing list