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 |