Bug 6669

Summary: Неправильно рисуются картинки
Product: WINE@Etersoft Reporter: Денис Баранов <baraka>
Component: Окна / фокус / перерисовкаAssignee: Илья Шпигорь <shpigor>
Status: CLOSED FIXED QA Contact: Денис Баранов <baraka>
Severity: major    
Priority: P2 CC: amorozov, lav
Version: 2.0Keywords: TO_WINEHQ
Target Milestone: ---   
Hardware: PC   
OS: All   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 6433, 6743    
Deadline: 2010-12-30   
Attachments: Скриншот ошибки

Description Денис Баранов 2010-12-21 18:28:46 MSK
Created attachment 2073 [details]
Скриншот ошибки

1С 7.7: Помощь>Помощник начала работы, картинка отображается не естественным цветом.
Comment 1 Илья Шпигорь 2010-12-23 12:24:54 MSK
При открытии этого окна выводятся такие fixme:

fixme:ole:OLEPictureImpl_set_hPal (0xa747c78)->(000013d0): stub
fixme:ole:OLEPictureImpl_set_hPal (0xa747c78)->(0032ecf0): stub

На gdi32 оригинального wine проблема воспроизводится.
Comment 2 Илья Шпигорь 2010-12-23 12:42:28 MSK
Установка dcom98 решила проблему.
Comment 3 Александр Морозов 2010-12-23 13:00:25 MSK
Скорее всего установка нативной oleaut32 тоже решает проблему.
Comment 4 Илья Шпигорь 2010-12-23 15:32:06 MSK
Пытался реализовать OLEPictureImpl_set_hPal.

Пробовал просто установку значения палитры:
This->desc.u.bmp.hpal = UlongToHandle(hpal);

Пробовал копировать PALETTEENTRY из переданной в функцию палитры. SetPaletteEntries почему-то возвращает 0, т.е. функция не отработала.

В обоих случаях проблема не решилась.

Заметил, что This->hDCCur на момент вызова OLEPictureImpl_set_hPal равно NULL. Насколько понимаю это означает, что мы пытаемся установить логическую палитру.
Comment 5 Илья Шпигорь 2010-12-23 18:01:19 MSK
Есть подозрение, что OLEPictureImpl_set_hPal в этой баге не при чем.

Попробовал создавать новую палитру на основе переданных данных. Ошибка все-равно воспроизводится.

Возможно, в OLEPictureImpl_set_hPal уже передается битая палитра, точнее стандартная 20-ти цветная.
Comment 6 Илья Шпигорь 2010-12-23 18:17:15 MSK
Попробовал с oleaut32 из dcom98. 
Проблема не воспроизводится.

Похоже что-то не то все-таки с интерфейсом IPicture.
Comment 7 Илья Шпигорь 2010-12-24 14:35:32 MSK
Насколько понял схему происходит следующая последовательность действий:

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 - ничего не выводится.
Comment 8 Илья Шпигорь 2010-12-24 15:11:20 MSK
Если поменять biCompression BI_BITFIELDS на BI_RGB в функции OLEPictureImpl_LoadDIB - картинка рисуется правильно.

Вопрос: кто передает неправильный biCompression - приложение или сам wine?
Comment 9 Vitaly Lipatov 2010-12-24 15:39:15 MSK
(В ответ на comment #8)
> Если поменять biCompression BI_BITFIELDS на BI_RGB в функции
> OLEPictureImpl_LoadDIB - картинка рисуется правильно.
> 
> Вопрос: кто передает неправильный biCompression - приложение или сам wine?
Видимо нужно идти в сторону теста, начав со своей программы, отображающей картинку таким способом. Тогда можно будет понять — приложение или wine.

Для начала хотелось бы быстрый хак в eterhack
Comment 10 Илья Шпигорь 2010-12-24 15:42:44 MSK
Похоже проблема в GetDIBits.

Приложение запрашивает информацию о hbitmap, передавая bpp = 0 в структуре BITMAPINFO.

GetDIBits определяет, что bpp переданного в нее hbitmap больше 8 бит и делает вывод, что используется палитра (т.е. biCompression = BI_BITFIELDS). Не понятно, что за нелепое предположение.

После этого приложение использует полученную от GetDIBits структуру BITMAPINFO с неправильным biCompression, что и ломает отрисовку.
Comment 11 Илья Шпигорь 2010-12-24 16:28:38 MSK
Нужный тест на GetDIBits уже есть.

Если пропатчить GetDIBits, чтобы он не выставлял BI_BITFIELDS ломается сразу 10 тестов (в функции test_GetDIBits_BI_BITFIELDS).

Под виндой все тесты естественно проходят.
Comment 12 Илья Шпигорь 2010-12-24 17:49:15 MSK
Отправил в рассылку временный хак на OLEPictureImpl_LoadDIB.

Чтобы сделать правильно надо изучить по подробнее работу палитр для DDB и DIB.

Насколько знаю есть проблема, что wine не создает DIB по-умолчанию для картинки. Т.е. всегда создается DDB и функциями X-ов что-то рисуется. Возможно, при этом происходит ошибка в работе с палитрами.
Comment 13 Илья Шпигорь 2010-12-28 17:18:38 MSK
Если верить тестам, то информация о картинке все-таки правильная.

Отрисовка этой картинки происходит в 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, т.е. куда

Надо найти кто поломал эти маски.
Comment 14 Илья Шпигорь 2010-12-28 18:01:56 MSK
Пока удалось выяснить, что маски назначаются в интерфейсе IPicture, точнее извлекаются из IStream и передаются функции CreateDIBitmap.

Обычна проблема с битыми масками не наблюдается, потому что biCompression равен BI_RGB (т.е. маски не используются).
Comment 15 Vitaly Lipatov 2010-12-28 18:53:26 MSK
Я предлагаю создать тестовую программу. Необходимый код есть в shell32 (в выводе winver). Нужную растровую картинку, видимо, можно создать.
Comment 16 Илья Шпигорь 2010-12-29 13:42:52 MSK
Удалось найти явное противоречие в коде OLEPictureImpl_LoadDIB.

Поле bfOffBits структуры BITMAPFILEHEADER (которую мы достаем из IStream) содержит смещение от начала BITMAPFILEHEADER, с которого начинается битовый буфер картинки.

BITMAPINFO, используемый для создания картинки, лежит после структуры BITMAPFILEHEADER:

BITMAPFILEHEADER	*bfh = (BITMAPFILEHEADER*)xbuf;
BITMAPINFO		*bi = (BITMAPINFO*)(bfh+1);

Но в случае с поломанной картинкой оказывается, что адрес по которому лежит первая цветовая маска BITMAPINFO такой же, какой у начала битового буфера, согласно BITMAPFILEHEADER и его полю bfOffBits.

Получается, что та маска цветов которую мы считываем, на самом деле является самим изображением.
Comment 17 Илья Шпигорь 2010-12-29 14:28:02 MSK
Отправил письмо с исправлением на winehq.
Comment 18 Илья Шпигорь 2010-12-30 11:21:12 MSK
Ответ на письмо в winehq пока не пришел.

Эту багу закрываю, на дальнейшее проталкивание патча завел:
http://bugs.etersoft.ru/show_bug.cgi?id=6743
Comment 19 Денис Баранов 2011-01-03 19:15:03 MSK
Принято.