Created attachment 2073 [details] Скриншот ошибки 1С 7.7: Помощь>Помощник начала работы, картинка отображается не естественным цветом.
При открытии этого окна выводятся такие 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
Принято.