Как DirectWrite (CreateTextFormat) выбирает резервные шрифты?

Документация для CreateTextFormat ничего не говорит о выборе резервного шрифта, но если выбрана коллекция по умолчанию (NULL = system), то DirectWrite явно реализует резервный шрифт. Например, если я добавлю два глифа, которых нет в шрифте Gabriola, в тестовую строку, используемую демонстрационным приложением DirectWrite SDK, тогда DirectWrite выберет недостающие глифы из шрифта Segoe UI Symbol. Это происходит с базовым вызовом DrawText, а также с настраиваемым средством визуализации (которое не делает ничего настраиваемого для резервного копирования шрифта), как показано ниже (единственная модификация - это тестовая строка):

введите описание изображения здесь

Галочка и белая звездочка взяты из Segoe UI Symbol, а не от Габриолы, хотя в демонстрационном приложении указана только Габриола. Итак, кто-нибудь знает, как DirectWrite (CreateTextFormat) выбирает резервные шрифты?

Обновить. Я вижу, что есть GetSystemFontFallback, который может перечислять резервные шрифты, но он доступен только в Windows 8.1 (потому что он находится в IDWriteFactory2). Думаю, они заметили пробел в API в отношении перечисления резервных шрифтов. Итак, я предполагаю, что до Windows 8.1 это невозможно сделать, но если кто-нибудь знает способ взлома / обходной путь ...

Обновление2. Цитата сотрудника MSFT:

DirectWrite имеет резервные данные, которые не считываются из реестра и не подлежат настройке. Однако в Windows 8.1 были введены API-интерфейсы, которые позволяют приложению указывать собственный откат. (Это похоже на API WPF для создания определения составного шрифта.)

Что до сих пор не объясняет точно, что такое жестко запрограммированный алгоритм / схема замены.


person Fizz    schedule 05.09.2014    source источник


Ответы (1)


IDWriteTextLayout вызывает _ 2_ для сопоставления каждого символа Юникода с упорядоченный список семейств шрифтов, которые пробуются до тех пор, пока этот символ не будет удовлетворен. Подумайте о цикле, считывающем каждый символ по одному, сопоставляя значение кодовой точки и языковой тег с диапазоном Unicode и останавливаясь на первом шрифте, который поддерживает символ в таблице cmap. Псевдокод:

for each ch in text
    if ch is a combining mark or other similar extending character
        if the previously selected font supports the combining mark too
            use the previously selected font
            continue
        endif
    endif
    find first mapping for ch within the Unicode range, which matches
        the current language and base font family too (if pertinent)
    if mapping found
        for each font in mapping (starting with first listed)
            if ch in font cmap
                use current font
            endif
        endfor
    else
        use base font and undefined (.notdef) glyph
    endif
endfor

Также существует логика для определения резервных локалей (например, для _4 _ / _ 5_ или общего ja, соответствующего более конкретному ja-jp). Он в чем-то похож (но менее запутан, чем ????) на резервный алгоритм шрифта, указанный CSS для браузеров [http://www.w3.org/TR/css3-fonts/#font-matching-algorithm], и похож на резервный алгоритм. используется WPF / XAML / Silverlight.

См. IDWriteFontFallbackBuilder::AddMapping API (Win 8.1+), используемый для создайте настраиваемый резервный список, чтобы получить представление об используемых входных данных.

См. Пример данных C: \ Windows \ Fonts \ GlobalUserInterface.CompositeFont (обратите внимание, что этот файл на самом деле предназначен для WPF, а не для того определения, которое использует DWrite).

<FontFamilyMap
    Unicode  = "3000-30FF, 31F0-31FF"
    Language = "ja"
    Target   = "Meiryo UI, Meiryo, Microsoft YaHei UI, Microsoft YaHei, MS Gothic, MingLiu, Arial Unicode MS"
    Scale    = "1.0" />
person Dwayne Robinson    schedule 02.07.2015