Отображение unicode символов в собственном контроле

Тема в разделе "WASM.WIN32", создана пользователем weiv, 19 сен 2005.

  1. weiv

    weiv New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2003
    Сообщения:
    25
    Адрес:
    Новосибирск
    Такая ситуация. Имеется текстовый файл, где текст хранится в Unicode.

    Нужно прочитать этот файл и в окне нарисовать все символы с помощью функции

    TextOutW. Пусть в текстовом файле будут например 3 символа кириллицы,

    потом 3 китайских иероглифа, потом 3 символа из арабского алфавита.

    Так вот, чтобы с помощью TextOutW нарисовать символ, в контекст устройства

    нужно выбрать нужный шрифт - шрифт, который содержит нужные нам символы.

    Вот такие шрифты как Courier New, Arial, Times New Roman содержат

    символы кириллицы, иврита, арабского и т.д., но иероглифы китайского

    или японского содержатся в других шрифтах. Так вот перед рисованием

    нам нужно как-то перечислять шрифты в системе и обнаруживать, есть

    ли в них к примеру рисуемый в данный момент символ кириллицы или

    китайский иероглиф.



    И еще, как прочитав unicode код символа из файла, определить к каким

    символам он относится - к кириллице, арабского или китайскому и т.д.



    Мне все это нужно, чтобы рисовать текст в своем контроле, я не хочу

    использовать уже готовые, как edit.



    Я хочу узнать, как это делается по-человески.



    Пока свое решение такое:

    -----------------------

    1. Перечислять шрифты в системе с помощью функции EnumFontFamiliesEx.

    2. С помощью таблицы "Unicode Subset Bitfields" определять к какому

    диапазону относится код символа.



    Небольшой кусок этой таблицы:

    9, 0x0400, 0x04FF, "Cyrillic"

    10, 0x0530, 0x058F, "Armenian"

    11, 0x0590, 0x05FF, "Basic Hebrew"

    12, 0x0, 0x0, "Reserved"

    13, 0x0600, 0x06FF, "Basic Arabic"



    3. Искать в каждом шрифте unicode код нужного символа с помощью

    функции GetTextCharsetInfo и индекса, соответствующего диапазону

    символов из той же таблицы "Unicode Subset Bitfields". Например,

    для кириллицы этот индекс 9, как видно в первом поле в таблице выше.



    4. Если шрифт содержит нужный код символа, то рисовать символ

    функцией TextOutW с использованием найденного шрифта.



    5. Выбирать следующий символ из файла и проверять если ли он в

    текущем шрифте, а если нет, то все начиная с пункта 1.
     
  2. weiv

    weiv New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2003
    Сообщения:
    25
    Адрес:
    Новосибирск
    Мое решение, которые я предложил в предыдущем сообщении,

    на практике не совсем работает.

    Например, перебирая шрифты с помощью EnumFontFamiliesEx,

    и потом проверяя их с помощью GetTextCharsetInfo узнаем,

    что шрифт Gulimche.ttf поддерживает кучу диапазонов -

    там и кириллица, и хирагана, и катакана, и корейский, и китайский

    (поле fsUsb[4] структуры FONTSIGNATURE), а кодовая страница только

    936 корейская (поле fsCsb[2] структуры FONTSIGNATURE).



    Поэтому если опираться только на fsUsb, получаются всякие косяки -

    для части китайских символов в Gulimche.ttf нет отображения,

    а символы кириллицы этим шрифтом выглядят как-то совсем эпически :)



    И таких ситуаций очень много, когда вроде диапазон unicode поддерживается,

    но на самом деле вместо символов рисуются квадратики.



    В общем, вот здесь привожу текстовый файл для примера, из которого

    в идеале нужно получить такую картинку (размер шрифтов для наглядности большой).

    Так получается, если в системе есть универсальный шрифт как arialuni.ttf (23 Мб).

    [​IMG] _1342854207__testunichar.zip
     
  3. weiv

    weiv New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2003
    Сообщения:
    25
    Адрес:
    Новосибирск
    Интересно было бы посмотреть в связи с этим текст утилиты CHARMAP (Таблица символов) или оконную процедуру контрола EDIT. Может кто поделится, у кого есть исходники Windows 2000?
     
  4. SDragon

    SDragon New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2005
    Сообщения:
    133
    Адрес:
    Siberia
    Есть функция GetFontUnicodeRanges, но она доступна только в Win 2000/XP. Поэтому имхо нужно использовать эту функцию, если она есть (проверить LoadLibrary и GetProcAddress). Если нет, выкручиваться тем способом, который ты предложил.



    Под Win 9x тот алгоритм, который ты описал - это практически единственный вариант. Microsoft в презентации по RichEdit'у упоминает, что наличие отдельных символов в шрифте можно проверить с помощью какой-то cmap (насколько я понял, это внутренняя структура в True Type-файле). Но никакой API-функции для работы с этой cmap я не нашел.



    То есть проверить под Win 9x, есть ли отдельный символ в шрифте, сложно или вообще невозможно; можно лишь выполнить GetTextCharsetInfo и узнать, что шрифт поддерживает определенную кодировку или диапазон Unicode. При этом, как ты говоришь, совсем не факт, что в диапазоне Unicode содержатся абсолютно все символы (этого вообще никто не может гарантировать, потому что в каждой новой версии стандарта Unicode в существующие диапазоны добавляются новые символы).



    А что ты пишешь, если не секрет? Я пару лет занимался созданием своего текстового редактора, может, сможем помочь друг другу? Внешне твое творение слегка смахивает на charmap.
     
  5. weiv

    weiv New Member

    Публикаций:
    0
    Регистрация:
    2 ноя 2003
    Сообщения:
    25
    Адрес:
    Новосибирск
    наличие отдельных символов в шрифте можно проверить с помощью какой-то cmap

    (насколько я понял, это внутренняя структура в True Type-файле).

    Но никакой API-функции для работы с этой cmap я не нашел.




    Видел GetFontData для работы со всякими cmap и т.д.

    А вообще cmap и другие таблицы описаны в "True Type Font Specification" от Microsoft.



    Кстати, в CHARMAP тоже используется GetFontData и как раз читается таблица

    'cmap', но в реверсинге я не силен.



    А что ты пишешь, если не секрет? Я пару лет занимался созданием своего

    текстового редактора, может, сможем помочь друг другу?

    Внешне твое творение слегка смахивает на charmap.




    Да ничего не пишу, а скорее учусь, пытаюсь что-то понять.

    Просто хочу чтобы были свои контролы под Win9x с поддержкой Unicode,

    но это только мечты пока.



    Посмотрел исходные тексты ReactOS, а именно контрол EDIT,

    но там все рисуется одним шрифтом, ничего не подбирается.
     
  6. SDragon

    SDragon New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2005
    Сообщения:
    133
    Адрес:
    Siberia
    Почему мечта? Собственно ты уже знаешь все, что нужно для того, чтобы проверить, существует ли символ в шрифте. Осталось написать программу. Юзай GetFontData(cmap) и двоичный поиск нужного диапазона в Win 9x, а в Win 2000/XP - GetFontUnicodeRanges.



    Посмотри еще вот эту страницу:

    http://www.microsoft.com/globaldev/getwr/steps/wrg_font.mspx
     
  7. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Вообще-то есть ещё такая штука как FontLink. К примеру, "Microsoft Sans Serif" по умолчанию прилинкован к MS UI Gothic, Gulim, SimSun и PMingLiU. Т.е., хоть этот шрифт формально и не поддерживает восточноазиатские языки, при выводе они будут вполне нормально отображаться. Так же можно посмотреть в сторону IMLangFontLink.