1. Запустить КОМПАС 2. Создать текстовый документ 3. Вставка - Символ 4. В диалоге Символ в контроле Шрифт выбрать Symbol Type A - в сетке не отображается ни одного символа. Если диалог в таком состоянии закрыть а потом снова вызвать Вставка - Символ то КОМПАС виснет.
На текущей версии воспроизводится. В консоли следующее: fixme:font:get_font_unicode_ranges encoding 1937337698 not supported fixme:font:get_font_unicode_ranges encoding 1937337698 not supported fixme:font:get_font_unicode_ranges encoding 1937337698 not supported Видимо просто нет такого шрифта. wine-etersoft-sql-1.0.9-alt0.M41.13 libwine-1.0.9-alt0.M41.35 wine-1.0.9-alt0.M41.35 libwine-gl-1.0.9-alt0.M41.35
Проваливается это условие: if (face->charmap->encoding == FT_ENCODING_UNICODE && pFT_Get_First_Char) Надо посмотреть, что там вообще за история. Понятно, что в шрифте Symbol A нормальных букв нет. Но возможно в нём какая-то ошибка, или он не Юникодный?
Первые строки бактрейса Backtrace: =>1 0x00eee91c in kted (+0x7e91c) (0x0032e848) 2 0x7ee20f5d call_dialog_proc+0x65(hwnd=<register EDI not in topmost frame>, msg=272, wp=0, lp=0, result=0x32e8b8, arg=0x5f80557b) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:482] in user32 (0x0032e888) 3 0x7ee24b62 WINPROC_CallDlgProcW+0x54(func=0xffff002b, hwnd=<register EDI not in topmost frame>, msg=272, wParam=0, lParam=0) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:2427] in user32 (0x0032e8c8) 4 0x7edae92a DefDlgProcW+0x7d(hwnd=<register ESI not in topmost frame>, msg=<register EDI not in topmost frame>, wParam=0, lParam=0) [/srv/vitperov/Projects/wine-dev/dlls/user32/defdlg.c:488] in user32 (0x0032e8f8) 5 0x7ee20cda WINPROC_wrapper+0x1a() in user32 (0x0032e928) 6 0x7ee210bf call_window_proc+0x61(hwnd=<register EDI not in topmost frame>, msg=<register ESI not in topmost frame>, wp=0, lp=0, result=0x32e9a0, arg=0x7edae8ad) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:461] in user32 (0x0032e968) 7 0x7ee24c6c CallWindowProcW+0x52(func=0x7edae8ad, hwnd=0x150364, msg=272, wParam=0, lParam=0) [/srv/vitperov/Projects/wine-dev/dlls/user32/winproc.c:2344] in user32 (0x0032e9a8) 8 0x5f801d93 in mfc42u (+0x1d93) (0x0032e9c8) 9 0x5f801dbd in mfc42u (+0x1dbd) (0x0032ea68) 10 0x5f8019d1 in mfc42u (+0x19d1) (0x0032ea88) Ничего полезного не говорят
Проверил. Не выполняется именно условие face->charmap->encoding == FT_ENCODING_UNICODE
Изначально вызывается: WINAPI GetFontUnicodeRanges Далее: WineEngGetFontUnicodeRanges затем get_font_unicode_ranges Вызывает подозрение WineEngGetFontUnicodeRanges: даже если get_font_unicode_ranges вернула num_ranges=0 - всё -равно заполняется выходная структура, и в WINAPI GetFontUnicodeRanges возвращается size, не равный 0. В этоге функция завершается успешно и возвращает 16 - количество записанных байт.
Попробовал в функции WineEngGetFontUnicodeRanges если num_ranges==0, то принудительно возвращать size = 0 и ничего не писать в структуру. В итоге ничего не изменилось. Программа также падает
Пробовал удалять растровый шрифт. Загружается только векторный. Почему он не юникодный я не знаю. Проверил: font->charset = 2, font->codepage = 42 (42 соответствует CP_SYMBOL)
Написал тест. На winxp возвращается num_ranges=0. Но строка символов на winxp имеет одни символы, а вот при запуске теста через ww - символы совсем другие.
Функция вызывалась с неверными параметрами. Результаты повторного тестирования: 1) ww (функция изменена) num_ranges = 0; 2) wine num_ranges = 16; 3) winxp num_ranges = 120; Текст перестал прорисовываться!!!
Нашёл ошибку: Оказывается размер структуры может меняться Сначала надо вызывать функцию с нулевым указателем, чтобы получить размер структуры, выделять требуемую память, а затем снова вызывать для получения требуемых данных. При указанных исправлениях текст стал прорисовываться. При запуске на winxp пишется 120 байт. Возвращается 26 диапазонов
Переписал тест. Вместо отдельной графической программы добавил его в /gdi21/tests/font.c Возникли проблемы с проверкой существования шрифта. при вызове is_truetype_font_installed("Symbol A") возвращается false, хотя шрифт находится в папке windows/fonts. Если проверку убрать, то тест работает, но это крайне нежелательно
Ну так в is_truetype_font_installed есть проверка if (type != TRUETYPE_FONTTYPE) return 1; возможно, она опять для этого шрифта не проходит?
Нашёл причину. Проверять надо существование не "Symbol A" а "Symbol type A"
Проверил аналогичное со шрифтом Аrial: Результаты: 1) от самого fontFace работа GetFontUnicodeRanges не зависит. Если взять Arial, и поставить кодировку CP_SYMBOL, то функция тоже перестаёт работать. 2) Всё зависит от кодировки. Если CP_SYMBOL не ставить, то на оба шрифта GetFontUnicodeRanges выдаёт 155 найденых диапазонов (в windows 141 диапазон) 3)Кодировка важна! Если взять шрифт SymbolA, то без указание кодировки он возвращает 141 диапазон, при указании CP_SYMBOL количество диапазонов = 26
Появилось частичное решение: Если вообще удалить проверку кодировки (т.е строчку face->charmap->encoding == FT_ENCODING_UNICODE), то программа начинает работать немного лучше. Отображаются не пустые клетки, а квадраты, притом символы вставляются, при повторной вставке программа больше не падает. Получается, что падение происходило потому, что программа не проверяла возвращаемый размер, она просто выделяла буфер и начинала в него писать. Даже если возвращался размер 0 - всё-равно было падение. Если убрать проверку на юникодную кодировку, то функция всё-таки находит диапазоны (в случае с Arial было найдено 2 диапазона), записывает их в структуру, и возвращает нужный размер. И программа не падает!
функция get_font_unicode_ranges работает следующим образом: с помощью функций pFT_Get_First_Char(face, &glyph_code) и pFT_Get_Next_Char в цикле перебираются все glyph_code. Если между двумя соседними glyph_code имеется разрыв (char_code - char_code_prev > 1), то создаётся новый диапазон. Пока я не нашёл где в коде может учитываться выбранная кодировка. как устроены функции pFT_Get_First_Char и pFT_Get_Next_Char выяснить не удалось. они определены как pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0); можно посмотреть wine_dlsym. Там вызывается dlsym, которая просто объявлена как extern. Дальше выяснить не удалось.
Делаешь rpmgp libfreetype и смотришь в исходниках библиотеки freetype в ~/RPM/SOURCES
Если я привильно понял, в шрифт добавляются символы на этапе создания. (Например при вызове CreateFontIndirect). К моменту вызова GetFontUnicodeRanges там, по идее, должен быть определённый набор символов. И к этому моменту по идее не должно существовать такого понятия, как кодировка.
Что-то я не совсем понимаю где что происходит. При вызове CreateFontIndirect выделяется память под структуру FONTOBJ, и там заполняются соответствующие поля описания шрифта. Создания отдельных символов там не происходит
инициализация происходит на этапе SelectObject. При этом вызывается WineEngCreateFontInstance. Трейс для CP_SYMBOL: font.c:1550: Test failed: ---------BEFORE SELECT------------ trace:font:WineEngCreateFontInstance L"Arial", h=0, it=0, weight=0, PandF=00, charset=2 orient 0 escapement 0 trace:font:WineEngCreateFontInstance DC transform 1.000000 0.000000 0.000000 1.000000 trace:font:WineEngCreateFontInstance not in cache trace:font:WineEngCreateFontInstance (it=0, bd=0) is selected for (it=0, bd=0) trace:font:WineEngCreateFontInstance Chosen: L"Marlett" L"Regular" (/srv/vitperov/Projects/wine-dev/loader/../fonts//marlett.ttf/(nil):0) trace:font:WineEngCreateFontInstance font scale y: 1.000000 trace:font:OpenFontFace "/srv/vitperov/Projects/wine-dev/loader/../fonts//marlett.ttf"/(nil), 0, 0 x 0 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x0, buf=0x32f6bc, cbData=0x6 trace:font:WineEngGetFontData Can't find table VDMX trace:font:OpenFontFace height 0 => ppem 16 trace:font:select_charmap found cmap with platform_id 3, encoding_id 0 trace:font:WineEngCreateFontInstance caching: gdiFont=0x12e270 hfont=0x1050 trace:font:X11DRV_SelectFont hdc=0x33c, hfont=0x1050 trace:font:X11DRV_SelectFont gdiFont = 0x12e270 font.c:1552: Test failed: ---------AFTER SELECT------------- Трейс при не заданной кодировке: font.c:1550: Test failed: ---------BEFORE SELECT------------ trace:font:WineEngCreateFontInstance L"Arial", h=0, it=0, weight=0, PandF=00, charset=0 orient 0 escapement 0 trace:font:WineEngCreateFontInstance DC transform 1.000000 0.000000 0.000000 1.000000 trace:font:WineEngCreateFontInstance not in cache trace:font:WineEngCreateFontInstance (it=0, bd=0) is selected for (it=0, bd=0) trace:font:WineEngCreateFontInstance Chosen: L"Arial" L"Regular" (/usr/share/fonts/ttf/ms/arial.ttf/(nil):0) trace:font:WineEngCreateFontInstance font scale y: 1.000000 trace:font:OpenFontFace "/usr/share/fonts/ttf/ms/arial.ttf"/(nil), 0, 0 x 0 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x0, buf=0x32f6bc, cbData=0x6 trace:font:load_VDMX numRecs = 3 numRatios = 3 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x6, buf=0x32f71c, cbData=0x4 trace:font:load_VDMX Ratios[0] 1 1 : 1 -> 1 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x12, buf=0x32f72a, cbData=0x2 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x18, buf=0x32f720, cbData=0x4 trace:font:load_VDMX recs=248 startsz=8 endsz=255 trace:font:WineEngGetFontData font=0x12e270, table=VDMX, offset=0x1c, buf=0x1332b8, cbData=0x5d0 trace:font:OpenFontFace height 0 => ppem 14 trace:font:select_charmap found cmap with platform_id 0, encoding_id 3 trace:font:select_charmap found cmap with platform_id 3, encoding_id 1 trace:font:WineEngCreateFontInstance caching: gdiFont=0x12e270 hfont=0x1050 trace:font:X11DRV_SelectFont hdc=0x33c, hfont=0x1050 trace:font:X11DRV_SelectFont gdiFont = 0x12e270 font.c:1552: Test failed: ---------AFTER SELECT------------- Первое, что бросается в глаза - это сообщение: trace:font:WineEngGetFontData Can't find table VDMX Оно возникает при возврате ошибки функцией load_sfnt_table Эта функция должна загружать таблицу шрифта в клиентскую память.
WineEngGetFontData возвращает код ошибки 0х8е, что соответствует FT_Err_Table_Missing. Примерный Backtrace: 1)WineEngCreateFontInstance 2) 3648: OpenFontFace 3) load_VDMX 4) WineEngGetFontData
WineEngCreateFontInstance: 3659 if (ret->charset == SYMBOL_CHARSET && select_charmap(ret->ft_face, FT_ENCODING_MS_SYMBOL)) { /* No ops */ } else if (select_charmap(ret->ft_face, FT_ENCODING_UNICODE)) { /* No ops */ } else { select_charmap(ret->ft_face, FT_ENCODING_APPLE_ROMAN); } Поэтому при выборе символьной кодовой страницы ставится кодировка FT_ENCODING_MS_SYMBOL если убрать верхнюю строчку, то выбор юникодной кодировки проваливается, и GetFontUnicodeRanges находит уже 6 диапазонов
Установил, что в шрифте содержится 2 кодировки (ft_face->charmaps[i]->encoding) [0]->1634889070 (FT_ENCODING_APPLE_ROMAN) [1]->1937337698 (FT_ENCODING_MS_SYMBOL)
в случае, если не выбирать кодовую страницу CP_SYMBOL, то в шрифте 3 таблицы символов с кодировками: [0]->1970170211 (FT_ENCODING_UNICODE) [1]->1634889070 (FT_ENCODING_APPLE_ROMAN) [2]->1970170211 (FT_ENCODING_UNICODE)
На начальном этапе выполнения в функции WineEngCreateFontInstance заполняется с помощью функции TranslateCharsetInfo структура CHARSETINFO csi; В качестве параметра функции передаётся исходная кодировка lf.lfCharSet В структуре CHARSETINFO есть интересное поле FONTSIGNATURE fs; /* * The FONTSIGNATURE tells which Unicode ranges and which code pages * have glyphs in a font. * * fsUsb 128-bit bitmap. The most significant bits are 10 (magic number). * The remaining 126 bits map the Unicode ISO 10646 subranges * for which the font provides glyphs. * * fsCsb 64-bit bitmap. The low 32 bits map the Windows codepages for * which the font provides glyphs. The high 32 bits are for * non Windows codepages. */ typedef struct { DWORD fsUsb[4]; DWORD fsCsb[2]; функция TranslateCharsetInfo перебирает все значения в статической таблице FONT_tci, поко не найдет соответствие lf.lfCharSet== FONT_tci[index].ciCharset В данном случае она должна выбрать из таблицы строчку: { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} } Так вот. Немного позже, после вызова TranslateCharsetInfo идёт перебор всех Family (ищется семейство, содержащие заданный пользователем фрифт) А ещё дальше идёт перебор всех шрифтов в семействе. Ищется тот, который содержит символы данной кодировки: if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) В итоге для семейства Arial не находится при выборе кодировки f.lfCharSet = SYMBOL_CHARSET функция не может найти ни одного шрифта. для FontFace "Symbol type A" аналогично не находится ни одного шрифта
Был не прав. Тестировать всё же следовало не "Аrial", а "Symbol type A". На первый взгляд они мало отличаются по поведению. Но "Symbol type A" содержит толко 1 шрифт со стилем StyleName = L"Symbol". Он также содержит 3 charmap: FT_ENCODING_UNICODE, FT_ENCODING_MS_SYMBOL и FT_ENCODING_APPLE_ROMAN При выборе FT_ENCODING_MS_SYMBOL функция находит 14 диапазонов При выборе FT_ENCODING_UNICODE функция находит 0 диапазонов. Компас падает. При выборе FT_ENCODING_APPLE_ROMAN функция также находит 0 диапазонов.
GetFontUnicodeRanges Проверка возвращаемой структуры: Wine: font.c:1565: 000 wcLow 0020 cGlyphs 2 font.c:1565: 001 wcLow 0023 cGlyphs 4 font.c:1565: 002 wcLow 0028 cGlyphs 3 font.c:1565: 003 wcLow 0030 cGlyphs 15 font.c:1565: 004 wcLow 0040 cGlyphs 22 font.c:1565: 005 wcLow 0057 cGlyphs 4 font.c:1565: 006 wcLow 005e cGlyphs 1 font.c:1565: 007 wcLow 0061 cGlyphs 21 font.c:1565: 008 wcLow 0077 cGlyphs 4 font.c:1565: 009 wcLow 00a0 cGlyphs 1 font.c:1565: 010 wcLow 00ac cGlyphs 1 font.c:1565: 011 wcLow 00b5 cGlyphs 3 font.c:1565: 012 wcLow 00bc cGlyphs 68 font.c:1565: 013 wcLow 2219 cGlyphs 1 font.c:1567: found 14 ranges font.c:1567: flAccel = 1114296 font.c:1568: GlyphsSupported = 150 Windows: font.c:1565: 000 wcLow 0000 cGlyphs 128 font.c:1565: 001 wcLow 0098 cGlyphs 1 font.c:1565: 002 wcLow 00a0 cGlyphs 1 font.c:1565: 003 wcLow 00a4 cGlyphs 1 font.c:1565: 004 wcLow 00a6 cGlyphs 2 font.c:1565: 005 wcLow 00a9 cGlyphs 1 font.c:1565: 006 wcLow 00ab cGlyphs 4 font.c:1565: 007 wcLow 00b0 cGlyphs 2 font.c:1565: 008 wcLow 00b5 cGlyphs 3 font.c:1565: 009 wcLow 00bb cGlyphs 1 font.c:1565: 010 wcLow 0401 cGlyphs 12 font.c:1565: 011 wcLow 040e cGlyphs 66 font.c:1565: 012 wcLow 0451 cGlyphs 12 font.c:1565: 013 wcLow 045e cGlyphs 2 font.c:1565: 014 wcLow 0490 cGlyphs 2 font.c:1565: 015 wcLow 2013 cGlyphs 2 font.c:1565: 016 wcLow 2018 cGlyphs 3 font.c:1565: 017 wcLow 201c cGlyphs 3 font.c:1565: 018 wcLow 2020 cGlyphs 3 font.c:1565: 019 wcLow 2026 cGlyphs 1 font.c:1565: 020 wcLow 2030 cGlyphs 1 font.c:1565: 021 wcLow 2039 cGlyphs 2 font.c:1565: 022 wcLow 20ac cGlyphs 1 font.c:1565: 023 wcLow 2116 cGlyphs 1 font.c:1565: 024 wcLow 2122 cGlyphs 1 font.c:1565: 025 wcLow f020 cGlyphs 224 font.c:1567: found 26 ranges font.c:1567: flAccel = 0 font.c:1568: GlyphsSupported = 480 Тестирование на шрифте Arial Wine font.c:1567: found 155 ranges font.c:1568: flAccel = 1114376 font.c:1569: GlyphsSupported = 1186 Windows: font.c:1567: found 141 ranges font.c:1568: flAccel = 0 font.c:1569: GlyphsSupported = 1419 Диапазоны приводить не буду, их слишком много. Отмечу лишь, что таблица диапазонов почти полностью совпадает.
с использованием функции определил, что таблица начинается с first glyph 3, first char 0020 почему не с 0 я не знаю.
В связи с появлением патча: Jon Parshall : fonts: Add the Symbol font. решил проверить ещё раз. Ничего не изменилось
Вставка не имеет отношения к отображению.
WINE@Etersoft CAD eter1.1/eter2 fixme:font:get_font_unicode_ranges encoding 1937337698 not supported fixme:font:get_font_unicode_ranges encoding 1937337698 not supported fixme:font:get_font_unicode_ranges encoding 1937337698 not supported
(In reply to comment #15) > Появилось частичное решение: > Если вообще удалить проверку кодировки (т.е > строчку face->charmap->encoding == FT_ENCODING_UNICODE), то > программа начинает работать немного лучше. > Отображаются не пустые клетки, а квадраты, > притом символы вставляются, при повторной > вставке программа больше не падает. Квадраты отображаются из-за того, что в get_glyph_index() к коду символа прибавляется 0xf000. Если этого не делать, то вместо квадратов будут отображаться символы.
Написал тестовую программу, выводящую информацию о диапазонах символов в шрифте "Symbol type A", а также первые 16 символов из каждого диапазона. Положил в wine-etersoft-devel/fonts/uncd_ranges
Created attachment 1271 [details] Win 2003
Created attachment 1272 [details] WINE с патчем, описанным в комментариях #15 и #32
При использовании хака, описанного в комментариях #15 и #32, возникает проблема: глифы соответствуют не тем кодам символов, что в Windows.
Не знаю, поможет это чем-то или нет, но на всякий случай напишу. Для неюникодных шрифтов windows делает определенные преобразования в соответствии с текущей локалью + весь шрифт отображается в область личных символов путем добавления к исходному коду символа f0. В последнем случае код символа будет одинаковым в любой локали и именно поэтому в КОМПАС-овом диалоге вставки символа для этих шрифтов просматривается только диапазон личных символов (в V10SP0 просматривались все диапазоны, но в SP1 это перекрыли).
> Для неюникодных > шрифтов windows делает определенные > преобразования в соответствии с текущей > локалью + весь шрифт отображается в область > личных символов путем добавления к > исходному коду символа f0. А можно где-нибдуь про это почитать поподробнее?
например здесь http://shlimazl.nm.ru/rus/fonts_ttf.htm это было найдено во времена разработки V10. Есть ли информация новее сразу сказать не могу.
Реализовал отображение символов из 0x0000-0x00ff в 0xf000-0xf0ff. Сделал под WINE документ с некоторыми символами из "Symbol type A". В Windows личные символы (0xf000-0xf0ff) отобразились без каких-либо проблем, а те, которые ниже 0xf000 - частично в виде квадратиков. Насколько я понял из комментария #37, с переносом документов, созданных в V10SP1, проблемы быть вообще не должно.
Добился почти полного соответствия с выводом тестовой программы на Windows. Единстенное отличие: появление диапазона, состоящего из одного символа с кодом 8729, которому соответствует квадратик. Коды символов, соответствующие шрифту, получаются следующим образом. Коды 0x00 - 0xff перекодируются из CP_ACP в WCHAR, а 0x20 - 0xff ещё и из CP_SYMBOL в WCHAR (что соответствует добавлению 0xf000). Таким образом получаем 2 набора кодов символов, которые объединяются с кодами символов из 0x100 - 0xffff.
Патч исправил проблему.
Текущее исправление откачено из-за https://bugs.etersoft.ru/show_bug.cgi?id=6558 Откатывающий коммит (для eter-2.1) commit 03364924f4c38c168fc34fca6e6f0550c368443f Author: Sergey Guralnik <serhio@etersoft.ru> Date: Thu Feb 28 13:32:47 2013 +0200 Revert "gdi32: Fix problems with "Symbol type A" font (eterbug #2609)." This reverts commit bb0a75c31d26cd0781672ef8aa819dd07f41c45e. Conflicts: dlls/gdi32/freetype.c После реверта описанная здесь проблема не наблюдается.
Проблемы нет. swine -h eter-2.1 kompas/v14 WINE@Etersoft SQL 2.1.2/2.1.0-eter4/2