Re: Correction of '_cairo_quartz_ucs4_to_index'.

Andrea Canciani <[email protected]>
Newsgroups gmane.comp.lib.cairo
Message-ID <CAN_5=BAu_AOTFMNEe6TipNf=c0wBGuguYkjBeZEZvcQ9tNUGUA@mail.gmail.com>
On Wed, Mar 15, 2017 at 12:14 PM, Clerk Ma <[email protected]> wrote:

> I found that '_cairo_quartz_ucs4_to_index' in cairo-quartz-font.c was
> broken
> (ucs4 was cast to uint16_t/UniChar). A workable patch is here:
>
> static unsigned long
> _cairo_quartz_ucs4_to_index (void *abstract_font,
>                  uint32_t ucs4)
> {
>     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);
>     CGGlyph glyph[2];
>     UniChar utf16[2];
>
>     size_t len = CFStringGetSurrogatePairForLongCharacter (ucs4, utf16) ?
> 2 : 1;
>     CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, utf16, glyph, len);
>
>     return glyph[0];
> }
>

The lack of documentation on CGFontGetGlyphsForUnichars() (and its older
implementation CGFontGetGlyphsForUnicodes()) left me wondering if it is
actually able to handle surrogate pairs or not.
I wrote a test (attached) that confirms they both work as expected :D
Even on 10.4 you can get the glyphs for surrogate pairs using
CGFontGetGlyphsForUnicodes()

Unfortunately CFStringGetSurrogatePairForLongCharacter() is only available
since 10.6.
Luckily it is easy to refactor the UCS4 to UTF16 conversion from
cairo-unicode.c into a separate function and reuse it :)

I published a branch that should fix this at
https://cgit.freedesktop.org/~ranma42/cairo/log/?h=quartz-ucs4-to-utf16
Can you confirm it fixes the issue?

A better fix would probably involve CTFontGetGlyphsForCharacters(), but
that is probably best suited for the (much desired, but not really a high
priority in my todo-list) CoreText-based font backend.

Andrea

-- 
cairo mailing list
[email protected]
https://lists.cairographics.org/mailman/listinfo/cairo
minitest.c (text/x-csrc, 1 KB)
/*

Assuming that the Sazanami-Hanazono·Mincho font is installed, this
test can be compiled and run as follows:

cc -Xlinker -framework -Xlinker ApplicationServices -undefined dynamic_lookup -Wall minitest.c
./a.out

*/

#include <ApplicationServices/ApplicationServices.h>

extern CGFontRef CGFontCreateWithName (const char *) __attribute__((weak_import));
extern void CGFontGetGlyphsForUnichars (CGFontRef, const UniChar[], const CGGlyph[], size_t) __attribute__((weak_import));
extern void CGFontGetGlyphsForUnicodes (CGFontRef, const UniChar[], const CGGlyph[], size_t) __attribute__((weak_import));

int main()
{
	UniChar utf16[2] = { 0xD840, 0xDC40 };
	CGGlyph glyphs[2];
	CGFontRef cgFont = CGFontCreateWithName ("Sazanami-Hanazono Mincho");

	printf ("font: %p\n", cgFont);

	CGFontGetGlyphsForUnicodes (cgFont, utf16, glyphs, 2);
	printf ("CGFontGetGlyphsForUnicodes: %04X %04X\n", glyphs[0], glyphs[1]);

	CGFontGetGlyphsForUnichars (cgFont, utf16, glyphs, 2);
	printf ("CGFontGetGlyphsForUnichars: %04X %04X\n", glyphs[0], glyphs[1]);

	return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.