diff options
Diffstat (limited to 'plugins/Clist_modern/src/modern_skinengine.cpp')
-rw-r--r-- | plugins/Clist_modern/src/modern_skinengine.cpp | 169 |
1 files changed, 166 insertions, 3 deletions
diff --git a/plugins/Clist_modern/src/modern_skinengine.cpp b/plugins/Clist_modern/src/modern_skinengine.cpp index d24d5c82e2..f0d0cd173e 100644 --- a/plugins/Clist_modern/src/modern_skinengine.cpp +++ b/plugins/Clist_modern/src/modern_skinengine.cpp @@ -36,8 +36,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "hdr/modern_skinengine.h" #include "hdr/modern_commonprototypes.h" #include "hdr/modern_sync.h" + //Implementation +#pragma pack(push, 1)
+/* tga header */
+struct tga_header_t
+{
+ BYTE id_lenght; /* size of image id */
+ BYTE colormap_type; /* 1 is has a colormap */
+ BYTE image_type; /* compression type */
+
+ short cm_first_entry; /* colormap origin */
+ short cm_length; /* colormap length */
+ BYTE cm_size; /* colormap size */
+
+ short x_origin; /* bottom left x coord origin */
+ short y_origin; /* bottom left y coord origin */
+
+ short width; /* picture width (in pixels) */
+ short height; /* picture height (in pixels) */
+
+ BYTE pixel_depth; /* bits per pixel: 8, 16, 24 or 32 */
+ BYTE image_descriptor; /* 24 bits = 0x00; 32 bits = 0x80 */
+};
+#pragma pack(pop)
+ /* Global variables */ SKINOBJECTSLIST g_SkinObjectList = { 0 }; @@ -1476,19 +1500,158 @@ int ske_GetFullFilename(TCHAR *buf, const TCHAR *file, TCHAR *skinfolder, BOOL m return 0; } +/* +This function is required to load TGA to dib buffer myself +Major part of routines is from http://tfcduke.developpez.com/tutoriel/format/tga/fichiers/tga.c +*/ + +static BOOL ske_ReadTGAImageData(void * From, DWORD fromSize, BYTE * destBuf, DWORD bufSize, BOOL RLE) +{ + BYTE * pos = destBuf; + BYTE * from = fromSize ? (BYTE*)From : NULL; + FILE * fp = !fromSize ? (FILE*)From : NULL; + DWORD destCount = 0; + DWORD fromCount = 0; + if (!RLE) { + while (((from && fromCount < fromSize) || (fp && fromCount < bufSize)) + && (destCount < bufSize)) { + BYTE r = from ? from[fromCount++] : (BYTE)fgetc(fp); + BYTE g = from ? from[fromCount++] : (BYTE)fgetc(fp); + BYTE b = from ? from[fromCount++] : (BYTE)fgetc(fp); + BYTE a = from ? from[fromCount++] : (BYTE)fgetc(fp); + pos[destCount++] = r; + pos[destCount++] = g; + pos[destCount++] = b; + pos[destCount++] = a; + + if (destCount > bufSize) break; + if (from) if (fromCount < fromSize) break; + } + } + else { + BYTE rgba[4]; + BYTE packet_header; + BYTE *ptr = pos; + BYTE size; + int i; + while (ptr < pos + bufSize) { + /* read first byte */ + packet_header = from ? from[fromCount] : (BYTE)fgetc(fp); + if (from) from++; + size = 1 + (packet_header & 0x7f); + if (packet_header & 0x80) { + /* run-length packet */ + if (from) { + *((DWORD*)rgba) = *((DWORD*)(from + fromCount)); + fromCount += 4; + } + else fread(rgba, sizeof(BYTE), 4, fp); + for (i = 0; i < size; ++i, ptr += 4) { + ptr[2] = rgba[2]; + ptr[1] = rgba[1]; + ptr[0] = rgba[0]; + ptr[3] = rgba[3]; + } + } + else { /* not run-length packet */ + for (i = 0; i < size; ++i, ptr += 4) { + ptr[0] = from ? from[fromCount++] : (BYTE)fgetc(fp); + ptr[1] = from ? from[fromCount++] : (BYTE)fgetc(fp); + ptr[2] = from ? from[fromCount++] : (BYTE)fgetc(fp); + ptr[3] = from ? from[fromCount++] : (BYTE)fgetc(fp); + } + } + } + } + return TRUE; +} + +static HBITMAP ske_LoadGlyphImage_TGA(const TCHAR *szFilename) +{ + BYTE *colormap = NULL; + int cx = 0, cy = 0; + BOOL err = FALSE; + tga_header_t header; + if (!szFilename) return NULL; + if (!wildcmpit(szFilename, _T("*\\*%.tga"))) { + //Loading TGA image from file + FILE *fp = _tfopen(szFilename, _T("rb")); + if (!fp) { + TRACEVAR("error: couldn't open \"%s\"!\n", szFilename); + return NULL; + } + /* read header */ + fread(&header, sizeof(tga_header_t), 1, fp); + if ((header.pixel_depth != 32) || ((header.image_type != 10) && (header.image_type != 2))) { + fclose(fp); + return NULL; + } + + /*memory allocation */ + colormap = (BYTE*)malloc(header.width*header.height * 4); + cx = header.width; + cy = header.height; + fseek(fp, header.id_lenght, SEEK_CUR); + fseek(fp, header.cm_length, SEEK_CUR); + err = !ske_ReadTGAImageData((void*)fp, 0, colormap, header.width*header.height * 4, header.image_type == 10); + fclose(fp); + } + else { + /* reading from resources IDR_TGA_DEFAULT_SKIN */ + HRSRC hRSrc = FindResourceA(g_hInst, MAKEINTRESOURCEA(IDR_TGA_DEFAULT_SKIN), "TGA"); + if (!hRSrc) return NULL; + HGLOBAL hRes = LoadResource(g_hInst, hRSrc); + if (!hRes) return NULL; + DWORD size = SizeofResource(g_hInst, hRSrc); + BYTE *mem = (BYTE*)LockResource(hRes); + if (size > sizeof(header)) { + tga_header_t * header = (tga_header_t *)mem; + if (header->pixel_depth == 32 && (header->image_type == 2 || header->image_type == 10)) { + colormap = (BYTE*)malloc(header->width*header->height * 4); + cx = header->width; + cy = header->height; + ske_ReadTGAImageData((void*)(mem + sizeof(tga_header_t) + header->id_lenght + header->cm_length), size - (sizeof(tga_header_t) + header->id_lenght + header->cm_length), colormap, cx*cy * 4, header->image_type == 10); + } + } + FreeResource(hRes); + } + + if (colormap) { //create dib section + BYTE * pt; + HBITMAP hbmp = ske_CreateDIB32Point(cx, cy, (void**)&pt); + if (hbmp) + memcpy(pt, colormap, cx*cy * 4); + free(colormap); + return hbmp; + } + return NULL; +} + static HBITMAP ske_LoadGlyphImageByDecoders(const TCHAR *tszFileName) { if (!_tcschr(tszFileName, '%') && !PathFileExists(tszFileName)) return NULL; - HBITMAP hBitmap = Bitmap_Load(tszFileName); - if (hBitmap == NULL) + const TCHAR *ext = _tcsrchr(tszFileName, '.'); + if (ext == NULL) return NULL; BITMAP bmpInfo; + HBITMAP hBitmap; + bool f = false; + + if (!mir_tstrcmpi(ext, _T(".tga"))) { + hBitmap = ske_LoadGlyphImage_TGA(tszFileName); + f = true; + } + else hBitmap = Bitmap_Load(tszFileName); + + if (hBitmap == NULL) + return NULL; + GetObject(hBitmap, sizeof(BITMAP), &bmpInfo); if (bmpInfo.bmBitsPixel == 32) - ske_PreMultiplyChannels(hBitmap, 0); + ske_PreMultiplyChannels(hBitmap, f); else { HDC dc32 = CreateCompatibleDC(NULL); HDC dc24 = CreateCompatibleDC(NULL); |