diff --git a/modules/basic/.libs/basic-coretext.o b/modules/basic/.libs/basic-coretext.o index 13cce67..80c3268 100644 Binary files a/modules/basic/.libs/basic-coretext.o and b/modules/basic/.libs/basic-coretext.o differ diff --git a/modules/basic/.libs/pango-basic-coretext.so b/modules/basic/.libs/pango-basic-coretext.so index 70bb117..d0940c4 100755 Binary files a/modules/basic/.libs/pango-basic-coretext.so and b/modules/basic/.libs/pango-basic-coretext.so differ diff --git a/modules/basic/basic-coretext.c b/modules/basic/basic-coretext.c index c34460a..46d83ff 100644 --- a/modules/basic/basic-coretext.c +++ b/modules/basic/basic-coretext.c @@ -92,6 +92,7 @@ struct RunIterator CTRunRef current_run; CFIndex *current_indices; const CGGlyph *current_cgglyphs; + CGGlyph *current_cgglyphs_buffer; CTRunStatus current_run_status; }; @@ -101,6 +102,9 @@ run_iterator_free_current_run (struct RunIterator *iter) iter->current_run_number = -1; iter->current_run = NULL; iter->current_cgglyphs = NULL; + if (iter->current_cgglyphs_buffer) + free (iter->current_cgglyphs_buffer); + iter->current_cgglyphs_buffer = NULL; if (iter->current_indices) free (iter->current_indices); iter->current_indices = NULL; @@ -116,10 +120,18 @@ run_iterator_set_current_run (struct RunIterator *iter, iter->current_run_number = run_number; iter->current_run = CFArrayGetValueAtIndex (iter->runs, run_number); + ct_glyph_count = CTRunGetGlyphCount (iter->current_run); + iter->current_run_status = CTRunGetStatus (iter->current_run); iter->current_cgglyphs = CTRunGetGlyphsPtr (iter->current_run); + if (!iter->current_cgglyphs) + { + iter->current_cgglyphs_buffer = (CGGlyph *)malloc (sizeof (CGGlyph) * ct_glyph_count); + CTRunGetGlyphs (iter->current_run, CFRangeMake (0, ct_glyph_count), + iter->current_cgglyphs_buffer); + iter->current_cgglyphs = iter->current_cgglyphs_buffer; + } - ct_glyph_count = CTRunGetGlyphCount (iter->current_run); iter->current_indices = malloc (sizeof (CFIndex *) * ct_glyph_count); CTRunGetStringIndices (iter->current_run, CFRangeMake (0, ct_glyph_count), iter->current_indices); @@ -237,6 +249,7 @@ run_iterator_create (struct RunIterator *iter, iter->current_run = NULL; iter->current_indices = NULL; iter->current_cgglyphs = NULL; + iter->current_cgglyphs_buffer = NULL; /* Create CTLine */ attributes = CFDictionaryCreate (kCFAllocatorDefault, diff --git a/modules/basic/basic-coretext.c.orig b/modules/basic/basic-coretext.c.orig index 0a2c27f..c34460a 100644 --- a/modules/basic/basic-coretext.c.orig +++ b/modules/basic/basic-coretext.c.orig @@ -166,7 +166,42 @@ run_iterator_run_is_non_monotonic (struct RunIterator *iter) static gunichar run_iterator_get_character (struct RunIterator *iter) { - return CFStringGetCharacterAtIndex (iter->cstr, iter->current_indices[iter->ct_i]); + int lower, upper; + + lower = iter->current_indices[iter->ct_i]; + if (iter->ct_i + 1 < CTRunGetGlyphCount (iter->current_run)) + upper = iter->current_indices[iter->ct_i + 1]; + else + { + CFRange range = CTRunGetStringRange (iter->current_run); + upper = range.location + range.length; + } + + if (upper - lower == 1) + return CFStringGetCharacterAtIndex (iter->cstr, lower); + if (upper - lower == 2) + { + /* Character is encoded in two UTF16 code points. */ + gunichar *ch; + gunichar retval; + gunichar2 orig[2]; + + orig[0] = CFStringGetCharacterAtIndex (iter->cstr, lower); + orig[1] = CFStringGetCharacterAtIndex (iter->cstr, lower + 1); + + ch = g_utf16_to_ucs4 (orig, 2, NULL, NULL, NULL); + retval = *ch; + g_free (ch); + + return retval; + } + + /* This should not be reached, because other cases cannot occur. Instead + * of crashing, return the first character which will likely be displayed + * as unknown glyph. + */ + + return CFStringGetCharacterAtIndex (iter->cstr, lower); } static CGGlyph @@ -175,12 +210,6 @@ run_iterator_get_cgglyph (struct RunIterator *iter) return iter->current_cgglyphs[iter->ct_i]; } -static CFIndex -run_iterator_get_index (struct RunIterator *iter) -{ - return iter->current_indices[iter->ct_i]; -} - static gboolean run_iterator_create (struct RunIterator *iter, const char *text, @@ -190,13 +219,17 @@ run_iterator_create (struct RunIterator *iter, char *copy; CFDictionaryRef attributes; CFAttributedStringRef attstr; + int val = 0; + CFNumberRef number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &val); CFTypeRef keys[] = { - (CFTypeRef) kCTFontAttributeName + (CFTypeRef) kCTFontAttributeName, + kCTLigatureAttributeName }; CFTypeRef values[] = { - ctfont + ctfont, + number }; /* Initialize RunIterator structure */ @@ -209,7 +242,7 @@ run_iterator_create (struct RunIterator *iter, attributes = CFDictionaryCreate (kCFAllocatorDefault, (const void **)keys, (const void **)values, - 1, + sizeof (keys) / sizeof (keys[0]), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -233,6 +266,7 @@ run_iterator_create (struct RunIterator *iter, iter->line = CTLineCreateWithAttributedString (attstr); iter->runs = CTLineGetGlyphRuns (iter->line); + CFRelease (number); CFRelease (attstr); CFRelease (attributes); @@ -336,7 +370,7 @@ create_core_text_glyph_list (const char *text, struct GlyphInfo *gi; gi = g_slice_new (struct GlyphInfo); - gi->index = run_iterator_get_index (&riter); + gi->index = riter.total_ct_i; gi->cgglyph = run_iterator_get_cgglyph (&riter); gi->wc = run_iterator_get_character (&riter); @@ -378,9 +412,8 @@ basic_engine_shape (PangoEngineShape *engine, * glyph sequence generated by the CoreText typesetter: * # E.g. zero-width spaces do not end up in the CoreText glyph sequence. We have * to manually account for the gap in the character indices. - * # Sometimes, CoreText generates two glyph for the same character index. We - * currently handle this "properly" as in we do not crash or corrupt memory, - * but that's about it. + * # Sometimes, CoreText generates two glyph for the same character index. These + * are properly composed into a single 32-bit gunichar. * # Due to mismatches in size, the CoreText glyph sequence can either be longer or * shorter than the PangoGlyphString. Note that the size of the PangoGlyphString * should match the number of characters in "text". @@ -392,11 +425,6 @@ basic_engine_shape (PangoEngineShape *engine, * increasing/decreasing. * * FIXME items for future fixing: - * # CoreText strings are UTF16, and the indices *often* refer to characters, - * but not *always*. Notable exception is when a character is encoded using - * two UTF16 code points. This are two characters in a CFString. At this point - * advancing a single character in the CFString and advancing a single character - * using g_utf8_next_char in the const char string goes out of sync. * # We currently don't bother about LTR, Pango core appears to fix this up for us. * (Even when we cared warnings were generated that strings were in the wrong * order, this should be investigated).