winemenubuilder: Remove legacy PNG and XPM conversion code.

This commit is contained in:
Damjan Jovanovic 2010-07-22 21:41:35 +02:00 committed by Alexandre Julliard
parent 74a2d8e351
commit 1a1ef6e091
2 changed files with 7 additions and 463 deletions

View File

@ -6,7 +6,6 @@ VPATH = @srcdir@
MODULE = winemenubuilder.exe
APPMODE = -mwindows -municode
IMPORTS = uuid windowscodecs shell32 shlwapi ole32 user32 advapi32
EXTRAINCL = @PNGINCL@
C_SRCS = \
winemenubuilder.c

View File

@ -98,11 +98,6 @@
#include "wine/library.h"
#include "wine/list.h"
#ifdef HAVE_PNG_H
#undef FAR
#include <png.h>
#endif
WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
#define in_desktop_dir(csidl) ((csidl)==CSIDL_DESKTOPDIRECTORY || \
@ -182,345 +177,6 @@ static char *extract_icon(LPCWSTR path, int index, const char *destFilename, BOO
* FIXME: should not use stdio
*/
#define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
/* PNG-specific code */
#ifdef SONAME_LIBPNG
static void *libpng_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(png_create_info_struct);
MAKE_FUNCPTR(png_create_write_struct);
MAKE_FUNCPTR(png_destroy_write_struct);
MAKE_FUNCPTR(png_get_error_ptr);
MAKE_FUNCPTR(png_init_io);
MAKE_FUNCPTR(png_set_bgr);
MAKE_FUNCPTR(png_set_error_fn);
MAKE_FUNCPTR(png_set_text);
MAKE_FUNCPTR(png_set_IHDR);
MAKE_FUNCPTR(png_write_end);
MAKE_FUNCPTR(png_write_info);
MAKE_FUNCPTR(png_write_row);
#undef MAKE_FUNCPTR
static void *load_libpng(void)
{
if ((libpng_handle = wine_dlopen(SONAME_LIBPNG, RTLD_NOW, NULL, 0)) != NULL)
{
#define LOAD_FUNCPTR(f) \
if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
libpng_handle = NULL; \
return NULL; \
}
LOAD_FUNCPTR(png_create_info_struct);
LOAD_FUNCPTR(png_create_write_struct);
LOAD_FUNCPTR(png_destroy_write_struct);
LOAD_FUNCPTR(png_get_error_ptr);
LOAD_FUNCPTR(png_init_io);
LOAD_FUNCPTR(png_set_bgr);
LOAD_FUNCPTR(png_set_error_fn);
LOAD_FUNCPTR(png_set_IHDR);
LOAD_FUNCPTR(png_set_text);
LOAD_FUNCPTR(png_write_end);
LOAD_FUNCPTR(png_write_info);
LOAD_FUNCPTR(png_write_row);
#undef LOAD_FUNCPTR
}
return libpng_handle;
}
static void user_error_fn(png_structp png_ptr, png_const_charp error_message)
{
jmp_buf *pjmpbuf;
/* This uses setjmp/longjmp just like the default. We can't use the
* default because there's no way to access the jmp buffer in the png_struct
* that works in 1.2 and 1.4 and allows us to dynamically load libpng. */
WINE_ERR("PNG error: %s\n", wine_dbgstr_an(error_message, -1));
pjmpbuf = ppng_get_error_ptr(png_ptr);
longjmp(*pjmpbuf, 1);
}
static void user_warning_fn(png_structp png_ptr, png_const_charp warning_message)
{
WINE_WARN("PNG warning: %s\n", wine_dbgstr_an(warning_message, -1));
}
static BOOL SaveTrueColorIconResAsPNG(const BITMAPINFO *pIcon, const char *png_filename, LPCWSTR commentW)
{
static const char comment_key[] = "Created from";
FILE *fp;
png_structp png_ptr;
png_infop info_ptr;
png_text comment;
int nXORWidthBytes, nANDWidthBytes, color_type = 0, i, j;
BYTE *row, *copy = NULL;
const BYTE *pXOR, *pAND = NULL;
int nWidth = pIcon->bmiHeader.biWidth;
int nHeight = pIcon->bmiHeader.biHeight;
int nBpp = pIcon->bmiHeader.biBitCount;
jmp_buf jmpbuf;
switch (nBpp)
{
case 32:
color_type |= PNG_COLOR_MASK_ALPHA;
/* fall through */
case 24:
color_type |= PNG_COLOR_MASK_COLOR;
break;
default:
return FALSE;
}
if (!libpng_handle && !load_libpng())
{
WINE_WARN("Unable to load libpng\n");
return FALSE;
}
if (!(fp = fopen(png_filename, "w")))
{
WINE_ERR("unable to open '%s' for writing: %s\n", png_filename, strerror(errno));
return FALSE;
}
nXORWidthBytes = 4 * ((nWidth * nBpp + 31) / 32);
nANDWidthBytes = 4 * ((nWidth + 31 ) / 32);
pXOR = (const BYTE*) pIcon + sizeof(BITMAPINFOHEADER) + pIcon->bmiHeader.biClrUsed * sizeof(RGBQUAD);
if (nHeight > nWidth)
{
nHeight /= 2;
pAND = pXOR + nHeight * nXORWidthBytes;
}
/* Apply mask if present */
if (pAND)
{
RGBQUAD bgColor;
/* copy bytes before modifying them */
copy = HeapAlloc( GetProcessHeap(), 0, nHeight * nXORWidthBytes );
memcpy( copy, pXOR, nHeight * nXORWidthBytes );
pXOR = copy;
/* image and mask are upside down reversed */
row = copy + (nHeight - 1) * nXORWidthBytes;
/* top left corner */
bgColor.rgbRed = row[0];
bgColor.rgbGreen = row[1];
bgColor.rgbBlue = row[2];
bgColor.rgbReserved = 0;
for (i = 0; i < nHeight; i++, row -= nXORWidthBytes)
for (j = 0; j < nWidth; j++, row += nBpp >> 3)
if (MASK(j, i))
{
RGBQUAD *pixel = (RGBQUAD *)row;
pixel->rgbBlue = bgColor.rgbBlue;
pixel->rgbGreen = bgColor.rgbGreen;
pixel->rgbRed = bgColor.rgbRed;
if (nBpp == 32)
pixel->rgbReserved = bgColor.rgbReserved;
}
}
comment.text = NULL;
if (!(png_ptr = ppng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) ||
!(info_ptr = ppng_create_info_struct(png_ptr)))
goto error;
if (setjmp(jmpbuf))
{
/* All future errors jump here */
goto error;
}
ppng_set_error_fn(png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
ppng_init_io(png_ptr, fp);
ppng_set_IHDR(png_ptr, info_ptr, nWidth, nHeight, 8,
color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Set comment */
comment.compression = PNG_TEXT_COMPRESSION_NONE;
comment.key = (png_charp)comment_key;
i = WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, NULL, 0, NULL, NULL);
comment.text = HeapAlloc(GetProcessHeap(), 0, i);
WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, comment.text, i, NULL, NULL);
comment.text_length = i - 1;
ppng_set_text(png_ptr, info_ptr, &comment, 1);
ppng_write_info(png_ptr, info_ptr);
ppng_set_bgr(png_ptr);
for (i = nHeight - 1; i >= 0 ; i--)
ppng_write_row(png_ptr, (png_bytep)pXOR + nXORWidthBytes * i);
ppng_write_end(png_ptr, info_ptr);
ppng_destroy_write_struct(&png_ptr, &info_ptr);
if (png_ptr) ppng_destroy_write_struct(&png_ptr, NULL);
fclose(fp);
HeapFree(GetProcessHeap(), 0, copy);
HeapFree(GetProcessHeap(), 0, comment.text);
return TRUE;
error:
if (png_ptr) ppng_destroy_write_struct(&png_ptr, NULL);
fclose(fp);
unlink(png_filename);
HeapFree(GetProcessHeap(), 0, copy);
HeapFree(GetProcessHeap(), 0, comment.text);
return FALSE;
}
static BOOL SavePalettedIconResAsPNG(const BITMAPINFO *pIcon, const char *png_filename, LPCWSTR commentW)
{
static const char comment_key[] = "Created from";
FILE *pngFile = NULL;
int i, j;
int nHeight;
int nXORWidthBytes;
int nANDWidthBytes;
BOOL b8BitColors;
int nColors;
const BYTE *pXOR;
const BYTE *pAND;
png_structp png_ptr;
png_infop info_ptr;
png_text comment;
jmp_buf jmpbuf;
unsigned char *row = NULL;
BOOL ret = FALSE;
comment.text = NULL;
if (!((pIcon->bmiHeader.biBitCount == 4) || (pIcon->bmiHeader.biBitCount == 8)))
{
WINE_FIXME("Unsupported color depth %d-bit\n", pIcon->bmiHeader.biBitCount);
goto done;
}
if (!(pngFile = fopen(png_filename, "w")))
{
WINE_TRACE("Unable to open '%s' for writing: %s\n", png_filename, strerror(errno));
goto done;
}
nHeight = pIcon->bmiHeader.biHeight / 2;
nXORWidthBytes = 4 * ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount / 32)
+ ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount % 32) > 0));
nANDWidthBytes = 4 * ((pIcon->bmiHeader.biWidth / 32)
+ ((pIcon->bmiHeader.biWidth % 32) > 0));
b8BitColors = pIcon->bmiHeader.biBitCount == 8;
nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed
: 1 << pIcon->bmiHeader.biBitCount;
pXOR = (const BYTE*) pIcon + sizeof (BITMAPINFOHEADER) + (nColors * sizeof (RGBQUAD));
pAND = pXOR + nHeight * nXORWidthBytes;
row = HeapAlloc(GetProcessHeap(), 0, 4 * pIcon->bmiHeader.biWidth);
if (row == NULL)
{
WINE_ERR("out of memory\n");
goto done;
}
if (!libpng_handle && !load_libpng())
{
WINE_WARN("Unable to load libpng\n");
goto done;
}
if (!(png_ptr = ppng_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) ||
!(info_ptr = ppng_create_info_struct(png_ptr)))
goto done;
if (setjmp(jmpbuf))
{
/* All future errors jump here */
goto done;
}
ppng_set_error_fn(png_ptr, &jmpbuf, user_error_fn, user_warning_fn);
ppng_init_io(png_ptr, pngFile);
ppng_set_IHDR(png_ptr, info_ptr, pIcon->bmiHeader.biWidth, nHeight, 8,
PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Set comment */
comment.compression = PNG_TEXT_COMPRESSION_NONE;
comment.key = (png_charp)comment_key;
i = WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, NULL, 0, NULL, NULL);
comment.text = HeapAlloc(GetProcessHeap(), 0, i);
if (comment.text == NULL)
{
WINE_ERR("out of memory\n");
goto done;
}
WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, comment.text, i, NULL, NULL);
comment.text_length = i - 1;
ppng_set_text(png_ptr, info_ptr, &comment, 1);
ppng_write_info(png_ptr, info_ptr);
for (i = 0; i < nHeight; i++)
{
unsigned char *p = row;
for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
{
if MASK(j,i)
{
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
else
{
#define COLOR(x,y) (b8BitColors ? pXOR[(x) + (nHeight - (y) - 1) * nXORWidthBytes] : (x) % 2 ? pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF : (pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF0) >> 4)
*p++ = pIcon->bmiColors[COLOR(j,i)].rgbRed;
*p++ = pIcon->bmiColors[COLOR(j,i)].rgbGreen;
*p++ = pIcon->bmiColors[COLOR(j,i)].rgbBlue;
*p++ = 0xFF;
#undef COLOR
}
}
ppng_write_row(png_ptr, (png_bytep)row);
}
ppng_write_end(png_ptr, info_ptr);
ret = TRUE;
done:
ppng_destroy_write_struct(&png_ptr, &info_ptr);
if (pngFile != NULL)
fclose(pngFile);
HeapFree(GetProcessHeap(), 0, comment.text);
HeapFree(GetProcessHeap(), 0, row);
return ret;
}
static BOOL SaveIconResAsPNG(const BITMAPINFO *pIcon, const char *png_filename, LPCWSTR commentW)
{
switch (pIcon->bmiHeader.biBitCount)
{
case 4:
case 8:
return SavePalettedIconResAsPNG(pIcon, png_filename, commentW);
case 24:
case 32:
return SaveTrueColorIconResAsPNG(pIcon, png_filename, commentW);
default:
WINE_FIXME("unsupported bpp %d, please report\n", pIcon->bmiHeader.biBitCount);
return FALSE;
}
}
#endif /* SONAME_LIBPNG */
static BOOL SaveIconStreamAsPNG(IStream *icoFile, int index, const char *pngFileName, LPCWSTR commentW)
{
WCHAR *dosPNGFileName = NULL;
@ -645,110 +301,6 @@ end:
return SUCCEEDED(hr);
}
static BOOL SaveIconResAsXPM(const BITMAPINFO *pIcon, const char *szXPMFileName, LPCWSTR commentW)
{
FILE *fXPMFile;
int nHeight;
int nXORWidthBytes;
int nANDWidthBytes;
BOOL b8BitColors;
int nColors;
const BYTE *pXOR;
const BYTE *pAND;
BOOL aColorUsed[256] = {0};
int nColorsUsed = 0;
int i,j;
char *comment;
if (!((pIcon->bmiHeader.biBitCount == 4) || (pIcon->bmiHeader.biBitCount == 8)))
{
WINE_FIXME("Unsupported color depth %d-bit\n", pIcon->bmiHeader.biBitCount);
return FALSE;
}
if (!(fXPMFile = fopen(szXPMFileName, "w")))
{
WINE_TRACE("unable to open '%s' for writing: %s\n", szXPMFileName, strerror(errno));
return FALSE;
}
i = WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, NULL, 0, NULL, NULL);
comment = HeapAlloc(GetProcessHeap(), 0, i);
WideCharToMultiByte(CP_UNIXCP, 0, commentW, -1, comment, i, NULL, NULL);
nHeight = pIcon->bmiHeader.biHeight / 2;
nXORWidthBytes = 4 * ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount / 32)
+ ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount % 32) > 0));
nANDWidthBytes = 4 * ((pIcon->bmiHeader.biWidth / 32)
+ ((pIcon->bmiHeader.biWidth % 32) > 0));
b8BitColors = pIcon->bmiHeader.biBitCount == 8;
nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed
: 1 << pIcon->bmiHeader.biBitCount;
pXOR = (const BYTE*) pIcon + sizeof (BITMAPINFOHEADER) + (nColors * sizeof (RGBQUAD));
pAND = pXOR + nHeight * nXORWidthBytes;
#define COLOR(x,y) (b8BitColors ? pXOR[(x) + (nHeight - (y) - 1) * nXORWidthBytes] : (x) % 2 ? pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF : (pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF0) >> 4)
for (i = 0; i < nHeight; i++) {
for (j = 0; j < pIcon->bmiHeader.biWidth; j++) {
if (!aColorUsed[COLOR(j,i)] && !MASK(j,i))
{
aColorUsed[COLOR(j,i)] = TRUE;
nColorsUsed++;
}
}
}
if (fprintf(fXPMFile, "/* XPM */\n/* %s */\nstatic char *icon[] = {\n", comment) <= 0)
goto error;
if (fprintf(fXPMFile, "\"%d %d %d %d\",\n",
(int) pIcon->bmiHeader.biWidth, nHeight, nColorsUsed + 1, 2) <=0)
goto error;
for (i = 0; i < nColors; i++) {
if (aColorUsed[i])
if (fprintf(fXPMFile, "\"%.2X c #%.2X%.2X%.2X\",\n", i, pIcon->bmiColors[i].rgbRed,
pIcon->bmiColors[i].rgbGreen, pIcon->bmiColors[i].rgbBlue) <= 0)
goto error;
}
if (fprintf(fXPMFile, "\" c None\"") <= 0)
goto error;
for (i = 0; i < nHeight; i++)
{
if (fprintf(fXPMFile, ",\n\"") <= 0)
goto error;
for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
{
if MASK(j,i)
{
if (fprintf(fXPMFile, " ") <= 0)
goto error;
}
else
if (fprintf(fXPMFile, "%.2X", COLOR(j,i)) <= 0)
goto error;
}
if (fprintf(fXPMFile, "\"") <= 0)
goto error;
}
if (fprintf(fXPMFile, "};\n") <= 0)
goto error;
#undef MASK
#undef COLOR
HeapFree(GetProcessHeap(), 0, comment);
fclose(fXPMFile);
return TRUE;
error:
HeapFree(GetProcessHeap(), 0, comment);
fclose(fXPMFile);
unlink( szXPMFileName );
return FALSE;
}
static BOOL reassemble_and_save_to_png(GRPICONDIRENTRY *grpIconDirEntry, BITMAPINFO *pIcon,
const char *pngFileName, LPCWSTR commentW)
{
@ -871,10 +423,6 @@ static BOOL extract_icon32(LPCWSTR szFileName, int nIndex, char *szXPMFileName)
lpName = MAKEINTRESOURCEW(pIconDir->idEntries[0].nID); /* default to first entry */
for (i = 0; i < pIconDir->idCount; i++)
{
#ifndef SONAME_LIBPNG
if (pIconDir->idEntries[i].wBitCount != 4 && pIconDir->idEntries[i].wBitCount != 8)
continue;
#endif
if (pIconDir->idEntries[i].wBitCount >= nMaxBits)
{
if ((pIconDir->idEntries[i].bHeight * pIconDir->idEntries[i].bWidth) >= nMax)
@ -907,11 +455,7 @@ static BOOL extract_icon32(LPCWSTR szFileName, int nIndex, char *szXPMFileName)
if (reassemble_and_save_to_png(&iconDirEntry, pIcon, szXPMFileName, szFileName))
ret = TRUE;
else
{
memcpy(szXPMFileName + strlen(szXPMFileName) - 3, "xpm", 3);
if (SaveIconResAsXPM(pIcon, szXPMFileName, szFileName))
ret = TRUE;
}
ret = FALSE;
}
FreeResource(hResData);
@ -986,14 +530,15 @@ static int ExtractFromICO(LPCWSTR szFileName, char *szXPMFileName)
hr = SHCreateStreamOnFileW(szFileName, STGM_READ, &icoStream);
/* Prefer PNG over XPM */
if (FAILED(hr) || !SaveIconStreamAsPNG(icoStream, nIndex, szXPMFileName, szFileName))
if (FAILED(hr))
{
memcpy(szXPMFileName + strlen(szXPMFileName) - 3, "xpm", 3);
if (!SaveIconResAsXPM(pIcon, szXPMFileName, szFileName))
WINE_ERR("error 0x%08X creating icon stream\n", hr);
goto error;
}
if (!SaveIconStreamAsPNG(icoStream, nIndex, szXPMFileName, szFileName))
goto error;
HeapFree(GetProcessHeap(), 0, pIcon);
HeapFree(GetProcessHeap(), 0, pIconDirEntry);
HeapFree(GetProcessHeap(), 0, filename);