| Summary: | В эскизе КОМПАСа некорректно располагается размерный текст | ||
|---|---|---|---|
| Product: | [Поддержка проектов] КОМПАС-3D | Reporter: | Виталий Булгаков <bulgakov> |
| Component: | Тестирование | Assignee: | Константин Кондратюк <kondratyuk> |
| Status: | CLOSED FIXED | QA Contact: | Денис Баранов <baraka> |
| Severity: | critical | ||
| Priority: | P2 | CC: | kondratyuk, lav, mais, mibori, mx |
| Version: | v10 | ||
| Target Milestone: | — | ||
| Hardware: | PC | ||
| OS: | All | ||
| Whiteboard: | |||
| Заявки RT: | Связано с: | ||
| Дата напоминания: | |||
| Bug Depends on: | |||
| Bug Blocks: | 753, 1733, 2608, 3106, 4039 | ||
| Attachments: |
скриншот
скриншот архив с тестом Скриншот теста в windows и в wine тест (Etersoft edition) тест (Etersoft edition) Отображение после исправлений Скриншот с развернутой плоскостью эскиза Разворот подсветки текста условного обозначения тест SetWorldTransform |
||
|
Description
Виталий Булгаков
2008-11-24 13:58:09 MSK
Created attachment 916 [details]
скриншот
Created attachment 917 [details]
скриншот
вероятно, неправильно работает WorldTransform. Добавил тест. Текст в тесте вращается курсорными клавишами (влево-вправо). Created attachment 982 [details]
архив с тестом
Да, SetWorldTransform действительно работает странно. Такое ощущение, что в зависимости от угла поворота меняется что угодно - фон текста, ширина и размер символов, положение строки, наличие её на экране и даже буквы в тексте! :) Не понимаю пока, как такое может быть, но это явно не нарушение восприятия :) Created attachment 983 [details]
Скриншот теста в windows и в wine
Всё-таки перестал игнорировать GM_ADVANCED в вайновской функции - и сразу появилась стабильность (неправильных) результатов.
Вот скриншоты повёрнутого на один угол текста в Windows и в Wine - Очень похоже на нашу 2999 багу (по углу расхождения).
Created attachment 984 [details]
тест (Etersoft edition)
Тест хоть и кривоват, но простой до невозможности. Не придумывая ничего нового используем формулы поворота из начального теста, взяв за основу программы наш WinAPISkel.
Ещё, из обычных наблюдений по тесту: угол наклона строки зависит от _модуля_ угла поворота, то есть строка при -40 и при 40 повёрнута и отрисована одинаково. Отличия - в стартовой точке, откуда рисуется строка. Created attachment 985 [details]
тест (Etersoft edition)
Test with makefile and recources
Отрисовка прямоугольника тоже неправильна, но это связано с тем, что функция рисования прямоугольника не умеет поворачивать его в соответствии с матрицей преобразования. Текст, выводимый TextOut'ом поворачивается, но не правильно. Считаем матрицы... проверил умножение матриц в CombineTransform
оно в точности соответствует опеределению
C = A x B
A = ||aij||, i = 1..m, j = 1..n
B = ||bij||, i = 1..n, j = 1..p
C = ||cij||, i = 1..m, j = 1..p
cij = sum(k = 1..n) (aik * bkj)
с учетом, что
(a13, a23, b13, b23) = 0
(a33, b33) = 1
в функции BOOL DC_InvertXform производится вычисление преобразования, обратного тому, что передается в SetWorldTransform я не нашел формулу обратного преобразования в функции преобразование ведется по такому алгориму: для преобразования A обратное к нему будет являться A' , где A = ||aij||, A'=||a'ij||, при (a13, a23, a'13, a'23) = 0 и (a33, a'33) = 1 det A = a11 * a22 - a12 * a21 a'11 = a22 / det A; a'12 = - a12 / det A a'12 = - a21 / det A; a'22 = a11 / det A a'31 = - a31 * a11 - a32 * a21 a'32 = - a31 * a12 - a32 * a22 можно считать, что верно, т.к. это соответствует, тому что я прочитал в книжке по линейной алгебре (если бы мы имели зависимость реальных координат (x, y) от преобразованных (x', y') через матрицу их преобразования A): x = x' * a22 / det A - y' * a12 / det A - (a13 * a12 - a23 * a22) / det A y = - x' * a21 / det A + y' * a11 / det A - (a11 * a22 - a21 * a13) / det A верность показывают коэффициэнты при 1/det A пока нужно отложить разбор SetWorldTransform, и копать TextOut. При отключении в X11DRV_XRender_ExtTextOut
возможности невыполнения условия
if(!lpDx)
то есть делаем
if (!lpDx)
получаем корректное отображение, но с неверным (как будто по модулю) углом наклона.
> в X11DRV_XRender_ExtTextOut
заметил, что при каждом повороте на один TextOut (тот самый, который отрисовывает надпись под наклоном), X11DRV_XRender_ExtTextOut вызывается дважды:
theta = 0.00 ->
X11DRV_XRender_ExtTextOut(..., x=0, y=0, flags=2, lprect{left=150, top=150, right=237, bottom=168}, {(null)}, lpDx=0)
X11DRV_XRender_ExtTextOut(..., x=150, y=165, flags=4112, lprect{left=4210809, top=12, right=1219208, bottom=12}, {L"7H[W5RWDWLRQ"}, lpDx=0)
theta = -15.00 ->
X11DRV_XRender_ExtTextOut(..., x=0, y=0, flags=2, lprect{left=150, top=150, right=231, bottom=167}, {(null)}, lpDx=0)
X11DRV_XRender_ExtTextOut(..., x=150, y=164, flags=4112, lprect{left=4210809, top=12, right=1224376, bottom=12}, {L"7H[W5RWDWLRQ"}, lpDx=0)
theta = -30.00 ->
X11DRV_XRender_ExtTextOut(..., x=0, y=0, flags=2, lprect{left=150, top=150, right=210, bottom=163}, {(null)}, lpDx=0)
X11DRV_XRender_ExtTextOut(..., x=150, y=160, flags=4112, lprect{left=4210809, top=12, right=1231952, bottom=12}, {L"7H[W5RWDWLRQ"}, lpDx=0)
...
вывод строчки theta = ... -> в консоль и предворяет каждую отрисовку TextOut'ом
надо посмотреть какой в этом смысл
Обнаружил, что если трейсить WineEngGetGlyphOutline
то, например, при +15 градусах происходит некоторый пересчет (вызов WineEngGetGlyphOutline) инициируемый функцией X11DRV_XRender_ExtTextOut
затем, при -15 градусах такого пересчета не происходит.
Если упасть в момент этого пересчета, то получаем следующий бэктрейс:
Backtrace:
=>0 0x7ebb5f49 WineEngGetGlyphOutline+0x192(incoming_font=0x129b60, glyph=55, format=255, lpgm=0x66f220, buflen=0, buf=(nil), lpmat=(nil)) [/srv/mibori/Projects/wine/dlls/gdi32/freetype.c:4417] in gdi32 (0x0066f148)
1 0x7eba5a45 GetGlyphOutlineW+0xf1(hdc=0x1e4, uChar=55, fuFormat=255, lpgm=0x66f220, cbBuffer=0, lpBuffer=(nil), lpmat2=(nil)) [/srv/mibori/Projects/wine/dlls/gdi32/font.c:2398] in gdi32 (0x0066f198)
2 0x7e80af3f UploadGlyph+0x12f(physDev=0x127790, glyph=55, format=AA_Grey) [/srv/mibori/Projects/wine/dlls/winex11.drv/xrender.c:627] in winex11 (0x0066f3e8)
3 0x7e80cc91 X11DRV_XRender_ExtTextOut+0x746(physDev=0x127790, x=150, y=164, flags=4112, lprect=0x66f9a8, wstr=0x12aef8, count=12, lpDx=(nil)) [/srv/mibori/Projects/wine/dlls/winex11.drv/xrender.c:1266] in winex11 (0x0066f6f8)
4 0x7e7ec2e8 X11DRV_ExtTextOut+0x80(physDev=0x127790, x=150, y=164, flags=4112, lprect=0x66f9a8, wstr=0x12aef8, count=12, lpDx=(nil)) [/home/mibori/Projects/wine/dlls/winex11.drv/text.c:55] in winex11 (0x0066f7e8)
5 0x7eba445d ExtTextOutW+0x1757(hdc=0x1e4, x=150, y=164, flags=4112, lprect=(nil), str=0x12aeb8, count=12, lpDx=(nil)) [/srv/mibori/Projects/wine/dlls/gdi32/font.c:1994] in gdi32 (0x0066fa88)
6 0x7eba2cac ExtTextOutA+0x1c7(hdc=0x1e4, x=0, y=0, flags=0, lprect=(nil), str="TextRotation", count=12, lpDx=(nil)) [/srv/mibori/Projects/wine/dlls/gdi32/font.c:1609] in gdi32 (0x0066fae8)
7 0x7eba510e TextOutA+0x51(hdc=0x1e4, x=0, y=0, str="TextRotation", count=12) [/srv/mibori/Projects/wine/dlls/gdi32/font.c:2125] in gdi32 (0x0066fb18)
8 0x004017f9 in main (+0x17f9) (0x0066fc38)
9 0x0040151f in main (+0x151f) (0x0066fc68)
10 0x7e9392be WINPROC_wrapper+0x1a() in user32 (0x0066fc98)
11 0x7e939962 call_window_proc+0xca(hwnd=0x10028, msg=15, wp=0, lp=0, result=0x66fd78, arg=0x4014a4) [/home/mibori/Projects/wine/dlls/user32/winproc.c:461] in user32 (0x0066fce8)
12 0x7e93ff56 WINPROC_call_window+0x1db(hwnd=0x10028, msg=15, wParam=0, lParam=0, result=0x66fd78, unicode=0, mapping=WMCHAR_MAP_DISPATCHMESSAGE) [/home/mibori/Projects/wine/dlls/user32/winproc.c:2215] in user32 (0x0066fd38)
13 0x7e8fa362 DispatchMessageA+0x103(msg=0x66fdd0) [/home/mibori/Projects/wine/dlls/user32/message.c:3062] in user32 (0x0066fd88)
14 0x00401482 in main (+0x1482) (0x0066fe38)
15 0x004019b4 in main (+0x19b4) (0x0066feb8)
16 0x0040122f in main (+0x122f) (0x0066fee8)
17 0x00401275 in main (+0x1275) (0x0066fef8)
18 0x7b880891 start_process+0xe4(arg=(nil)) [/home/mibori/Projects/wine/dlls/kernel32/process.c:912] in kernel32 (0x0066ffe8)
19 0xb7eb1cc7 wine_switch_to_stack+0x17() in libwine.so.1 (0x00000000)
Получается, что при несохраненном в кеш значении, происходит вложенные вызовы X11DRV_XRender_ExtTextOut{UploadGlyph{GetGlyphOutlineW{WineEngGetGlyphOutline(падение при +15 градусах)}}}
а при сохраненном (по мнению функции X11DRV_XRender_ExtTextOut), таких вызовов не происходят.
Чтобы понять в каком месте искать условие при котором не происходит такой последовательности вызовов, нужно потрейсить UploadGlyph и GetGlyphOutlineW на предмет запуска их в случае повторного пересчета.
> Чтобы понять в каком месте искать условие
> при котором не происходит такой
> последовательности вызовов, нужно
> потрейсить UploadGlyph и GetGlyphOutlineW на предмет
> запуска их в случае повторного пересчета.
По дебаглогам у меня получается, что при повторном пересчете (когда X11DRV_XRender_ExtTextOut считает, что совершенно новый угол это старый, хранящийся в кеше) не происходит вызова UploadGlyph непосредственно из X11DRV_XRender_ExtTextOut.
Получается, что UploadGlyph не вызывается, когда она должна быть вызвана.
Т. е. теперь необходимо найти вызов UploadGlyph в теле X11DRV_XRender_ExtTextOut и посмотреть при каких условиях он работает, а при каких нет.
Ошибка происходила из-за кэширования в функции UploadGlyph (при сравнении formatEntry->realized[wstr[idx]] == FALSE). Временно исправлено, далее нужно улучшить сравнение при выборке из кэша. commit 8702aa58bad421bbcfbc5c76d46d63a7e7992c50 Author: Vitaly Lipatov <lav@etersoft.ru> Date: Thu Dec 25 12:49:59 2008 +0300 disable glyph cache for non 1C application (see eterbug #3101) Итак, проблема в повороте зелёного текста состояла в неверном преобразовании матрицы worldtransform (был неверный знак поворота). Поворачивался он через SetWorldTransform. Исправление в сборке eter39 Created attachment 989 [details]
Отображение после исправлений
Чем ближе мы приближаем надпись, тем более совпадают буквы. Очевидно, у чёрной буквы неверно вычисляется ширина.
Поскольку после наших исправлений отрисовка чёрной буквы не изменилась, делаем вывод, что она выводится без использования SetWorldTransofrm, в отличие от зелёной.
Надписи, поворачивающиеся с использованием SetWorldTransform, отображаются корректно. Проблема была в противоположном градусе поворота при использовании SetWorldTransorm. Исправили. commit fa26aeee5c6d8a40b881d5a778e3670f04f407cb Author: Konstantin Kondratyuk <kondratyuk@etersoft.ru> Date: Thu Dec 25 13:23:08 2008 +0300 gdi32: correct order of transformation matrix elements diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 5a48c33..a0c3eb1 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -4468,8 +4468,8 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, { FT_Matrix worldMat; worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11); - worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM21); - worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM12); + worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12); + worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21); worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22); Исправлено не до конца. Сервис - Параметры - Система - Редактор моделей - Размеры и обозначения - выключить Оптимизировать отображение - Ок. При повороте плоскости эскиза (например, зажав среднюю кнопку мыши) размерный текст трансформируется неправильно. Его плоскость как бы пересекает плоскость эскиза. См. прилагаемый скриншот. Created attachment 990 [details]
Скриншот с развернутой плоскостью эскиза
Для определения причин неправильной трансформации как бы в 3D режиме нужно видеть код, или тест от АСКОНа, показывающий проблему. Как выяснилось, чёрный текст и зелёный выводятся принципиально разными способами, это видно даже по форме букв (чёрный, через GL, имеет незакруглённые углы, видно что он построен другими сплайнами). Created attachment 996 [details]
Разворот подсветки текста условного обозначения
ROTATE по SetWorldTransform выполняется корректно. Есть ли уверенность ,что корректно выполняются остальные возможные преобразования (SCALE, SHEAR и т.д.)? Проверил Scaling, Shear и Reflection - работает корректно, идентично Windows. Запросил у программистов уточненный тест. Как будет готов приложу сюда. Пока считаем приостановленной... Created attachment 1057 [details]
тест SetWorldTransform
тест
добавлен тест SetWorldTransform. После запуска курсорными клавишами влево-вправо вызывается трансформация текстов. В правой колонке трансформация выполняется наоборот (верхняя меняется с нижней) по отношению к тому, как это происходит под windows. Воспроизводится моим тестом из репозитория wine-etersoft-devel: gdi/setworldtransform/textshear.*
Опытным путём установлено, что разницу в выполнении дают преобразования, выполняемые в функции WineEngGetGlyphOutline (блок помечен комментарием "World transform")
Поведение становится идентичным Windows, если в матрицу преобразования внести такие изменения:
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -4517,8 +4517,8 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
{
FT_Matrix worldMat;
worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
- worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM12);
- worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM21);
+ worldMat.xy = FT_FixedFromFloat(-font->font_desc.matrix.eM21);
+ worldMat.yx = FT_FixedFromFloat(-font->font_desc.matrix.eM12);
worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
pFT_Matrix_Multiply(&worldMat, &transMat);
pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
Проверил Rotation и Scaling/Reflection - с ними всё в порядке, да и не может ничего в них сломаться, потому что изменённая пара коэффициентов участвует только в shear-преобразовании
Путаница с горизонтальным и вертикальным преобразованиями вносится моим же декабрьским патчем. Видимо, Тимошков изменил где-то код так, что его первоначальные строки стали более актуальны, а мой патч - неправильным. Свой патч откатил. Теперь есть проблема с направлением преобразования. Для идентичности Windows поменял знаки коэввициентов M12 и M21. Патч в рассылке. На приложенном к баге тесте поведение соответствует поведению теста в Windows. (In reply to comment #17) > Ошибка происходила из-за кэширования в > функции UploadGlyph > (при сравнении formatEntry->realized[wstr[idx]] == FALSE). > Временно исправлено, далее нужно улучшить > сравнение при выборке из кэша. > > commit 8702aa58bad421bbcfbc5c76d46d63a7e7992c50 > Author: Vitaly Lipatov <lav@etersoft.ru> > Date: Thu Dec 25 12:49:59 2008 +0300 > > disable glyph cache for non 1C application (see eterbug #3101) > Откачен, так как ломает работу Консультанта (#4039) Кажется, неправильное поведение кэша уже исправлено Тимошковым. Принято WINE@Etersoft CAD eter2.1/eter2 Тест одинаково себя ведет на Windows и Linux |