Summary: | Неправильно рисуются картинки | ||
---|---|---|---|
Product: | WINE@Etersoft | Reporter: | Денис Баранов <baraka> |
Component: | Окна / фокус / перерисовка | Assignee: | Илья Шпигорь <shpigor> |
Status: | CLOSED FIXED | QA Contact: | Денис Баранов <baraka> |
Severity: | major | ||
Priority: | P2 | CC: | amorozov, lav |
Version: | 2.0 | Keywords: | TO_WINEHQ |
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All | ||
Whiteboard: | |||
Заявки RT: | Связано с: | ||
Дата напоминания: | |||
Bug Depends on: | |||
Bug Blocks: | 6433, 6743 | ||
Deadline: | 2010-12-30 | ||
Attachments: | Скриншот ошибки |
При открытии этого окна выводятся такие fixme: fixme:ole:OLEPictureImpl_set_hPal (0xa747c78)->(000013d0): stub fixme:ole:OLEPictureImpl_set_hPal (0xa747c78)->(0032ecf0): stub На gdi32 оригинального wine проблема воспроизводится. Установка dcom98 решила проблему. Скорее всего установка нативной oleaut32 тоже решает проблему. Пытался реализовать OLEPictureImpl_set_hPal. Пробовал просто установку значения палитры: This->desc.u.bmp.hpal = UlongToHandle(hpal); Пробовал копировать PALETTEENTRY из переданной в функцию палитры. SetPaletteEntries почему-то возвращает 0, т.е. функция не отработала. В обоих случаях проблема не решилась. Заметил, что This->hDCCur на момент вызова OLEPictureImpl_set_hPal равно NULL. Насколько понимаю это означает, что мы пытаемся установить логическую палитру. Есть подозрение, что OLEPictureImpl_set_hPal в этой баге не при чем. Попробовал создавать новую палитру на основе переданных данных. Ошибка все-равно воспроизводится. Возможно, в OLEPictureImpl_set_hPal уже передается битая палитра, точнее стандартная 20-ти цветная. Попробовал с oleaut32 из dcom98. Проблема не воспроизводится. Похоже что-то не то все-таки с интерфейсом IPicture. Насколько понял схему происходит следующая последовательность действий: 1. Картинка читается из IStream. При этом у картинки bpp = 8, сжатие (поле biCompression, структуры BITMAPINFOHEADER) равно BI_RGB 2. Происходит вызов OLEPictureImpl_SetBitmap 3. Картинка сохраняется в IStream 4. Из IStream читается картинка такого же размера, но с bpp = 32 и сжатием BI_BITFIELDS. 5. Вызов OLEPictureImpl_SetBitmap 6. Вызов OLEPictureImpl_set_hPal 7. Отрисовка функцией OLEPictureImpl_Render Если сломать один из Load или Save - ничего не выводится. Если поменять biCompression BI_BITFIELDS на BI_RGB в функции OLEPictureImpl_LoadDIB - картинка рисуется правильно. Вопрос: кто передает неправильный biCompression - приложение или сам wine? (В ответ на comment #8) > Если поменять biCompression BI_BITFIELDS на BI_RGB в функции > OLEPictureImpl_LoadDIB - картинка рисуется правильно. > > Вопрос: кто передает неправильный biCompression - приложение или сам wine? Видимо нужно идти в сторону теста, начав со своей программы, отображающей картинку таким способом. Тогда можно будет понять — приложение или wine. Для начала хотелось бы быстрый хак в eterhack Похоже проблема в GetDIBits. Приложение запрашивает информацию о hbitmap, передавая bpp = 0 в структуре BITMAPINFO. GetDIBits определяет, что bpp переданного в нее hbitmap больше 8 бит и делает вывод, что используется палитра (т.е. biCompression = BI_BITFIELDS). Не понятно, что за нелепое предположение. После этого приложение использует полученную от GetDIBits структуру BITMAPINFO с неправильным biCompression, что и ломает отрисовку. Нужный тест на GetDIBits уже есть. Если пропатчить GetDIBits, чтобы он не выставлял BI_BITFIELDS ломается сразу 10 тестов (в функции test_GetDIBits_BI_BITFIELDS). Под виндой все тесты естественно проходят. Отправил в рассылку временный хак на OLEPictureImpl_LoadDIB. Чтобы сделать правильно надо изучить по подробнее работу палитр для DDB и DIB. Насколько знаю есть проблема, что wine не создает DIB по-умолчанию для картинки. Т.е. всегда создается DDB и функциями X-ов что-то рисуется. Возможно, при этом происходит ошибка в работе с палитрами. Если верить тестам, то информация о картинке все-таки правильная. Отрисовка этой картинки происходит в X11DRV_DIB_SetImageBits. Там маски цветов почему-то поломанные: trace:bitmap:X11DRV_DIB_SetImageBits Dib: depth=32 r=fefe0c g=fefe0c b=fefe0a trace:bitmap:X11DRV_DIB_SetImageBits Bmp: depth=32/32 r=ff0000 g=ff00 b=ff Dib - это информация об отрисовываемом буфере Bmp - это XImage, т.е. куда Надо найти кто поломал эти маски. Пока удалось выяснить, что маски назначаются в интерфейсе IPicture, точнее извлекаются из IStream и передаются функции CreateDIBitmap. Обычна проблема с битыми масками не наблюдается, потому что biCompression равен BI_RGB (т.е. маски не используются). Я предлагаю создать тестовую программу. Необходимый код есть в shell32 (в выводе winver). Нужную растровую картинку, видимо, можно создать. Удалось найти явное противоречие в коде OLEPictureImpl_LoadDIB. Поле bfOffBits структуры BITMAPFILEHEADER (которую мы достаем из IStream) содержит смещение от начала BITMAPFILEHEADER, с которого начинается битовый буфер картинки. BITMAPINFO, используемый для создания картинки, лежит после структуры BITMAPFILEHEADER: BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf; BITMAPINFO *bi = (BITMAPINFO*)(bfh+1); Но в случае с поломанной картинкой оказывается, что адрес по которому лежит первая цветовая маска BITMAPINFO такой же, какой у начала битового буфера, согласно BITMAPFILEHEADER и его полю bfOffBits. Получается, что та маска цветов которую мы считываем, на самом деле является самим изображением. Отправил письмо с исправлением на winehq. Ответ на письмо в winehq пока не пришел. Эту багу закрываю, на дальнейшее проталкивание патча завел: http://bugs.etersoft.ru/show_bug.cgi?id=6743 Принято. |
Created attachment 2073 [details] Скриншот ошибки 1С 7.7: Помощь>Помощник начала работы, картинка отображается не естественным цветом.