Сбой CTTypesetter при работе со странными символами Unicode

Я использую CTTypesetter для компоновки сообщений, прочитанных из JSON с сервера. Однако в некоторых конкретных сообщениях происходит сбой, а именно в сообщениях с необычными символами Unicode, такими как приведенное ниже.

CFAttributedStringRef attrString = CFAttributedStringCreate(NULL, @"❝We  must  learn  to  live  together  as  brothers  or  perish  together  as  fools❞ ~Martin Luther King Jr. #HappyMLKDay", nil);
CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString(attrString);

Это падает с приведенной ниже трассировкой стека.

#0  0x33a4684e in TBaseFont::CopyCharacterSet() const ()
#1  0x33a2c0d4 in CompareCharSet(__CFCharacterSet const*, TBaseFont const*) ()
#2  0x33a2f03e in TDescriptorSource::CopyDescriptorsForRequestFromArray(__CFArray const*, __CFDictionary const*, long (*)(void const*, void const*, void*), void*, unsigned long, bool) const ()
#3  0x33a2ead0 in TDescriptorSource::CopyDescriptorsForRequest(__CFDictionary const*, __CFSet const*, long (*)(void const*, void const*, void*), void*, unsigned long) const ()
#4  0x33a2e624 in TDescriptorSource::CopyDescriptorForRequest(__CFDictionary const*, __CFSet const*, long (*)(void const*, void const*, void*), void*, unsigned long) const ()
#5  0x33a2e532 in TDescriptorSource::CopySystemWideFallbackDescriptor(CGFont*, unsigned short const*, long) const ()
#6  0x33a2e79c in TDescriptorSource::CopySystemWideFallbackDescriptor(CGFont*, __CFString const*, CFRange) const ()
#7  0x33a27c78 in TFontCascade::CreateSystemWideFallback(__CTFont const*, __CFString const*, CFRange) const ()
#8  0x33a27b28 in TFontCascade::CreateFallback(__CTFont const*, __CFString const*, CFRange) const ()
#9  0x33a185ec in TGlyphEncoder::AppendUnmappedCharRun(CTRun*, CFRange, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const&, bool) ()
#10 0x33a184b8 in TGlyphEncoder::RunUnicodeEncoderRecursively(CTRun*, adopted_t const&, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const*, bool) ()
#11 0x33a186e4 in TGlyphEncoder::AppendUnmappedCharRun(CTRun*, CFRange, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const&, bool) ()
#12 0x33a184b8 in TGlyphEncoder::RunUnicodeEncoderRecursively(CTRun*, adopted_t const&, CFRange, TGlyphList<TDeletedGlyphIndex>&, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const*, bool) ()
#13 0x33a1824c in TGlyphEncoder::RunUnicodeEncoder(CTRun*, adopted_t const&, CFRange, TGlyphList<TDeletedGlyphIndex>&, TFontCascade const*) ()
#14 0x33a07a1a in TGlyphEncoder::EncodeChars(CFRange, TAttributes const&, TGlyphList<TDeletedGlyphIndex>&, TGlyphEncoder::Fallbacks) ()
#15 0x33a0665c in TTypesetterAttrString::Initialize(__CFAttributedString const*) ()
#16 0x33a064a4 in TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*) ()
#17 0x33a06418 in TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*) ()
#18 0x33a1e78c in CTTypesetterCreateWithAttributedString ()

Я создал пустой проект, чтобы попытаться воспроизвести сбой, однако в этой среде он работает нормально.

В документации есть следующее:

Многоядерные соображения: все отдельные функции в Core Text являются потокобезопасными. Объекты шрифта (CTFont, CTFontDescriptor и связанные объекты) могут использоваться одновременно несколькими операциями, рабочими очередями или потоками. Однако объекты компоновки (CTTypesetter, CTFramesetter, CTRun, CTLine, CTFrame и связанные объекты) следует использовать в одной операции, рабочей очереди или потоке.

С этой целью я удалил все виды потоков, а именно несколько dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ...), в попытке решить эту проблему. Я не знаю, что еще я могу попытаться решить, кроме как выпотрошить то, что представляет собой проект> 20 KSLOC.

Это приводит к сбою только самого iPad (все 3 модели протестированы как с 5.0, так и с 5.1), а не с симулятором.

Что я могу попытаться решить это? Я собираюсь прибегнуть к встраиванию модифицированных версий Helvetica с максимально возможным количеством резервных шрифтов, но это далеко не оптимальное решение.


Любой вклад вообще был бы невероятно ценен, поскольку вы можете видеть, что это сводит меня с ума с января!


person Max    schedule 16.01.2012    source источник


Ответы (1)


Я только что решил это.

Я ссылался на 43 шрифта в своем info.plist. Все были действительны, все были otf или ttf в моем комплекте ресурсов. Я просто удалил несколько, и он начал работать.

Проклятый баг Apple.

person Max    schedule 21.04.2012
comment
Лучше, чем проклинать чужие ошибки, создайте минимально воспроизводимый случай и сообщите о нем, чтобы он был исправлен. - person marko; 31.01.2013