From 1e92bf5cf72665b5fec103a0a70d734340725539 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 24 Jul 2012 09:26:39 +0000 Subject: StopSpamPlus, TipperYM, TooltipNotify, TopToolBar, TranslitSwitcher, UserGuide: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1159 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/TipperYM/src/bitmap_func.cpp | 776 +++++++++++++++++++++++++++++++++++ 1 file changed, 776 insertions(+) create mode 100644 plugins/TipperYM/src/bitmap_func.cpp (limited to 'plugins/TipperYM/src/bitmap_func.cpp') diff --git a/plugins/TipperYM/src/bitmap_func.cpp b/plugins/TipperYM/src/bitmap_func.cpp new file mode 100644 index 0000000000..0a33c7b1d8 --- /dev/null +++ b/plugins/TipperYM/src/bitmap_func.cpp @@ -0,0 +1,776 @@ +/* +Copyright (C) 2006-2007 Scott Ellis +Copyright (C) 2007-2011 Jan Holub + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" +#include "options.h" +#include "bitmap_func.h" +#include "message_pump.h" + +TOOLTIPSKIN skin = {0}; + +HBITMAP CreateBitmapPart(FIBITMAP *fibSrc, int iSrcWidth, int iSrcHeight, int iDesWidth, int iDesHeight, TransformationMode transfMode) +{ + FIBITMAP *fibMem = NULL; + HBITMAP hbmpDes = NULL; + + if (!fibSrc) + return NULL; + + switch (transfMode) + { + case TM_NONE: + case TM_CENTRE: + case TM_TILE_ALL: + { + hbmpDes = fii->FI_CreateHBITMAPFromDIB(fibSrc); + break; + } + case TM_STRECH_ALL: + { + fibMem = fii->FI_Rescale(fibSrc, iDesWidth, iDesHeight, FILTER_BILINEAR); + hbmpDes = fii->FI_CreateHBITMAPFromDIB(fibMem); + break; + } + case TM_STRECH_HORIZONTAL: + case TM_TILE_VERTICAL: + { + fibMem = fii->FI_Rescale(fibSrc, iDesWidth, iSrcHeight, FILTER_BILINEAR); + hbmpDes = fii->FI_CreateHBITMAPFromDIB(fibMem); + break; + } + case TM_STRECH_VERTICAL: + case TM_TILE_HORIZONTAL: + { + fibMem = fii->FI_Rescale(fibSrc, iSrcWidth, iSrcHeight, FILTER_BILINEAR); + hbmpDes = fii->FI_CreateHBITMAPFromDIB(fibMem); + break; + } + } + + if (fibMem) fii->FI_Unload(fibMem); + return hbmpDes; +} + +void DrawBitmapPart(HDC hdcMem, HBITMAP hbmpPart, RECT *rcDes, TransformationMode transfMode) +{ + if (!hbmpPart) + return; + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = 255; + blend.AlphaFormat = AC_SRC_ALPHA; + + BITMAP bitmap; + GetObject(hbmpPart, sizeof(bitmap), &bitmap); + int iBmpWidth = bitmap.bmWidth; + int iBmpHeight = bitmap.bmHeight; + + int iDesWidth = rcDes->right - rcDes->left; + int iDesHeight = rcDes->bottom - rcDes->top; + + SelectObject(hdcMem, hbmpPart); + + switch (transfMode) + { + case TM_NONE: + case TM_STRECH_ALL: + case TM_STRECH_HORIZONTAL: + case TM_STRECH_VERTICAL: + { + AlphaBlend(skin.hdc, rcDes->left, rcDes->top, iBmpWidth, iBmpHeight, hdcMem, 0, 0, iBmpWidth, iBmpHeight, blend); + break; + } + case TM_CENTRE: + { + int iPosX = rcDes->left + ((iDesWidth - iBmpWidth) / 2); + int iPosY = rcDes->top + ((iDesHeight - iBmpHeight) / 2); + AlphaBlend(skin.hdc, iPosX, iPosY, iBmpWidth, iBmpHeight, hdcMem, 0, 0, iBmpWidth, iBmpHeight, blend); + break; + } + case TM_TILE_ALL: + { + int iRepX = iDesWidth / iBmpWidth; + int iRepY = iDesHeight / iBmpHeight; + int iEndX = iDesWidth % iBmpWidth; + int iEndY = iDesHeight % iBmpHeight; + int x,y; + + for (y = 0; y < iRepY; y++) + { + for (x = 0; x < iRepX; x++) + { + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top + (y * iBmpHeight), iBmpWidth, iBmpHeight, hdcMem, 0, 0, iBmpWidth, iBmpHeight, blend); + } + + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top + (y * iBmpHeight), iEndX, iBmpHeight, hdcMem, 0, 0, iEndX, iBmpHeight, blend); + } + + for (x = 0; x < iRepX; x++) + { + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top + (y * iBmpHeight), iBmpWidth, iEndY, hdcMem, 0, 0, iBmpWidth, iEndY, blend); + } + + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top + (y * iBmpHeight), iEndX, iEndY, hdcMem, 0, 0, iEndX, iEndY, blend); + break; + } + case TM_TILE_HORIZONTAL: + { + int iRepX = iDesWidth / iBmpWidth; + int iEndX = iDesWidth % iBmpWidth; + int x; + + for (x = 0; x < iRepX; x++) + { + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top, iBmpWidth, iDesHeight, hdcMem, 0, 0, iBmpWidth, iDesHeight, blend); + } + + AlphaBlend(skin.hdc, rcDes->left + (x * iBmpWidth), rcDes->top, iEndX, iDesHeight, hdcMem, 0, 0, iEndX, iDesHeight, blend); + break; + } + case TM_TILE_VERTICAL: + { + int iRepY = iDesHeight / iBmpHeight; + int iEndY = iDesHeight % iBmpHeight; + int y; + + for(y = 0; y < iRepY; y++) + { + AlphaBlend(skin.hdc, rcDes->left, rcDes->top + (y * iBmpHeight), iDesWidth, iBmpHeight, hdcMem, 0, 0, iDesWidth, iBmpHeight, blend); + } + + AlphaBlend(skin.hdc, rcDes->left, rcDes->top + (y * iBmpHeight), iDesWidth, iEndY, hdcMem, 0, 0, iDesWidth, iEndY, blend); + break; + } + } +} + +void CreateFromBitmaps(bool bServiceTip) +{ + int rcWidth, rcHeight; + int iCentWidth, iCentHeight; + int iBmpWidth, iBmpHeight; + int top, right, bottom, left; + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + blend.SourceConstantAlpha = 255; + blend.AlphaFormat = AC_SRC_ALPHA; + + for (int i = 0; i < SKIN_ITEMS_COUNT; i++) + { + if (i == SKIN_ITEM_SIDEBAR && (!opt.iSidebarWidth || bServiceTip)) + continue; + + TCHAR* tszFileName = opt.szImgFile[i]; + if (tszFileName && *tszFileName != 0) + { + FIBITMAP *fib = NULL; + if (!skin.bCached) + { + FIBITMAP *fibLoad = (FIBITMAP *)CallService(MS_IMG_LOAD, (WPARAM)tszFileName, (LPARAM)(IMGL_TCHAR | IMGL_RETURNDIB)); + if (!fibLoad) continue; + + if (fii->FI_GetBPP(fibLoad) != 32) + fib = fii->FI_ConvertTo32Bits(fibLoad); + else + fib = fibLoad; + + if (fib != fibLoad) + fii->FI_Unload(fibLoad); + + skin.fib[i] = fib; + } + else + { + fib = skin.fib[i]; + } + + // destination rectangle size + if (i == SKIN_ITEM_BG) + { + rcWidth = skin.iWidth; + rcHeight = skin.iHeight; + } + else if (i == SKIN_ITEM_SIDEBAR) + { + rcWidth = opt.iSidebarWidth; + rcHeight = skin.iHeight; + } + + // bitmap size + iBmpWidth = fii->FI_GetWidth(fib); + iBmpHeight = fii->FI_GetHeight(fib); + + // margins + top = opt.margins[i].top < iBmpHeight ? opt.margins[i].top : 0; + right = opt.margins[i].right < iBmpWidth ? opt.margins[i].right : 0; + bottom = opt.margins[i].bottom < iBmpHeight ? opt.margins[i].bottom : 0; + left = opt.margins[i].left < iBmpWidth ? opt.margins[i].left : 0; + + // centre area size + iCentWidth = max(rcWidth - left - right, 0); + iCentHeight = max(rcHeight - top - bottom, 0); + + FIBITMAP *fibCentre = NULL, *fibMem = NULL; + if (opt.margins[i].left || opt.margins[i].top || opt.margins[i].right || opt.margins[i].bottom) + { + // create corners bitmaps + if (!skin.bCached) + { + if (top > 0 && left > 0) // TL + { + fibMem = fii->FI_Copy(fib, 0, 0, left, top); + skin.hbmpSkinParts[i][SP_CORNER_TL] = fii->FI_CreateHBITMAPFromDIB(fibMem); + if (fibMem) fii->FI_Unload(fibMem); + } + if (top > 0 && right > 0) // TR + { + fibMem = fii->FI_Copy(fib, iBmpWidth - right, 0, iBmpWidth, top); + skin.hbmpSkinParts[i][SP_CORNER_TR] = fii->FI_CreateHBITMAPFromDIB(fibMem); + if (fibMem) fii->FI_Unload(fibMem); + } + if (bottom > 0 && right > 0) // BR + { + fibMem = fii->FI_Copy(fib, iBmpWidth - right, iBmpHeight - bottom, iBmpWidth, iBmpHeight); + skin.hbmpSkinParts[i][SP_CORNER_BR] = fii->FI_CreateHBITMAPFromDIB(fibMem); + if (fibMem) fii->FI_Unload(fibMem); + } + if (bottom > 0 && left > 0) // BL + { + fibMem = fii->FI_Copy(fib, 0, iBmpHeight - bottom, left, iBmpHeight); + skin.hbmpSkinParts[i][SP_CORNER_BL] = fii->FI_CreateHBITMAPFromDIB(fibMem); + if (fibMem) fii->FI_Unload(fibMem); + } + } + + // create edge parts bitmaps + if (top > 0 && iCentWidth > 0) // top + { + fibMem = fii->FI_Copy(fib, left, 0, iBmpWidth - right, top); + skin.hbmpSkinParts[i][SP_EDGE_TOP] = CreateBitmapPart(fibMem, iBmpWidth - left - right, top, iCentWidth, top, opt.transfMode[i]); + if (fibMem) fii->FI_Unload(fibMem); + } + if (right > 0 && iCentHeight > 0) // right + { + fibMem = fii->FI_Copy(fib, iBmpWidth - right, top, iBmpWidth, iBmpHeight - bottom); + skin.hbmpSkinParts[i][SP_EDGE_RIGHT] = CreateBitmapPart(fibMem, right, iBmpHeight - top - bottom, right, iCentHeight, opt.transfMode[i]); + if (fibMem) fii->FI_Unload(fibMem); + } + if (bottom > 0 && iCentWidth > 0) // bottom + { + fibMem = fii->FI_Copy(fib, left, iBmpHeight - bottom, iBmpWidth - right, iBmpHeight); + skin.hbmpSkinParts[i][SP_EDGE_BOTTOM] = CreateBitmapPart(fibMem, iBmpWidth - left - right, bottom, iCentWidth, bottom, opt.transfMode[i]); + if (fibMem) fii->FI_Unload(fibMem); + } + if (left > 0 && iCentHeight > 0) // left + { + fibMem = fii->FI_Copy(fib, 0, top, left, iBmpHeight - bottom); + skin.hbmpSkinParts[i][SP_EDGE_LEFT] = CreateBitmapPart(fibMem, left, iBmpHeight - top - bottom, left, iCentHeight, opt.transfMode[i]); + if (fibMem) fii->FI_Unload(fibMem); + } + + fibCentre = fii->FI_Copy(fib, left, top, iBmpWidth - right, iBmpHeight - bottom); + if (fibCentre) + { + fib = fibCentre; + iBmpWidth = fii->FI_GetWidth(fib); + iBmpHeight = fii->FI_GetHeight(fib); + } + } + + // create centre area bitmap + skin.hbmpSkinParts[i][SP_CENTRE_AREA] = CreateBitmapPart(fib, iBmpWidth, iBmpHeight, iCentWidth, iCentHeight, opt.transfMode[i]); + if (fibCentre) + fii->FI_Unload(fibCentre); + + if (i == SKIN_ITEM_SIDEBAR) + { + int limit = skin.bCached ? SP_CORNER_TL : SKIN_PARTS_COUNT; // don't premultiply corner bitmaps multiple times + for (int j = 0; j < limit; j++) + { + if (skin.hbmpSkinParts[i][j]) + fii->FI_Premultiply(skin.hbmpSkinParts[i][j]); + } + } + + HDC hdcMem = CreateCompatibleDC(0); + RECT rc = {0}; + + if (skin.hbmpSkinParts[i][SP_CENTRE_AREA]) + { + SetRect(&rc, left, top, rcWidth - right, rcHeight - bottom); + DrawBitmapPart(hdcMem, skin.hbmpSkinParts[i][SP_CENTRE_AREA], &rc, opt.transfMode[i]); + } + + if (opt.margins[i].left || opt.margins[i].top || opt.margins[i].right || opt.margins[i].bottom) + { + // draw edge parts + if (skin.hbmpSkinParts[i][SP_EDGE_TOP]) // top + { + SetRect(&rc, left, 0, rcWidth - right, top); + DrawBitmapPart(hdcMem, skin.hbmpSkinParts[i][SP_EDGE_TOP], &rc, opt.transfMode[i]); + } + if (skin.hbmpSkinParts[i][SP_EDGE_RIGHT]) // right + { + SetRect(&rc, rcWidth - right, top, rcWidth, rcHeight - bottom); + DrawBitmapPart(hdcMem, skin.hbmpSkinParts[i][SP_EDGE_RIGHT], &rc, opt.transfMode[i]); + } + if (skin.hbmpSkinParts[i][SP_EDGE_BOTTOM]) // bottom + { + SetRect(&rc, left, rcHeight - bottom, rcWidth - right, rcHeight); + DrawBitmapPart(hdcMem, skin.hbmpSkinParts[i][SP_EDGE_BOTTOM], &rc, opt.transfMode[i]); + } + if (skin.hbmpSkinParts[i][SP_EDGE_LEFT]) // left + { + SetRect(&rc, 0, top, left, rcHeight - bottom); + DrawBitmapPart(hdcMem, skin.hbmpSkinParts[i][SP_EDGE_LEFT], &rc, opt.transfMode[i]); + } + + // draw corners + if (skin.hbmpSkinParts[i][SP_CORNER_TL]) // TL + { + SelectObject(hdcMem, skin.hbmpSkinParts[i][SP_CORNER_TL]); + AlphaBlend(skin.hdc, 0, 0, left, top, hdcMem, 0, 0, left, top, blend); + } + if (skin.hbmpSkinParts[i][SP_CORNER_TR]) // TR + { + SelectObject(hdcMem, skin.hbmpSkinParts[i][SP_CORNER_TR]); + AlphaBlend(skin.hdc, rcWidth - right, 0, right, top, hdcMem, 0, 0, right, top, blend); + } + if (skin.hbmpSkinParts[i][SP_CORNER_BR]) // BR + { + SelectObject(hdcMem, skin.hbmpSkinParts[i][SP_CORNER_BR]); + AlphaBlend(skin.hdc, rcWidth - right, rcHeight - bottom, right, bottom, hdcMem, 0, 0, right, bottom, blend); + } + if (skin.hbmpSkinParts[i][SP_CORNER_BL]) // BL + { + SelectObject(hdcMem, skin.hbmpSkinParts[i][SP_CORNER_BL]); + AlphaBlend(skin.hdc, 0, rcHeight - bottom, left, bottom, hdcMem, 0, 0, left, bottom, blend); + } + } + + for (int j = 0; j < SP_CORNER_TL; j++) + { + if (skin.hbmpSkinParts[i][j]) + { + DeleteObject(skin.hbmpSkinParts[i][j]); + skin.hbmpSkinParts[i][j] = NULL; + } + } + + if (MyUpdateLayeredWindow) + skin.bNeedLayerUpdate = true; + + DeleteDC(hdcMem); + } + } + + skin.bCached = true; +} + +void SolidColorFill(bool bServiceTip) +{ + RECT rc = {0}; + rc.right = skin.iWidth; + rc.bottom = skin.iHeight; + HBRUSH hBrush = CreateSolidBrush(opt.colBg); + FillRect(skin.hdc, &rc, hBrush); + DeleteObject(hBrush); + + if (opt.iSidebarWidth > 0 && !bServiceTip) + { + rc.right = opt.iSidebarWidth; + hBrush = CreateSolidBrush(opt.colSidebar); + FillRect(skin.hdc, &rc, hBrush); + DeleteObject(hBrush); + } +} + +void CreateSkinBitmap(int iWidth, int iHeight, bool bServiceTip) +{ + if (skin.hBitmap) DeleteObject(skin.hBitmap); + if (skin.hdc) DeleteDC(skin.hdc); + skin.hBitmap = NULL; + skin.hdc = NULL; + + skin.iWidth = iWidth; + skin.iHeight = iHeight; + skin.bNeedLayerUpdate = false; + + BITMAPINFO bi; + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = skin.iWidth; + bi.bmiHeader.biHeight = -skin.iHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + skin.hBitmap = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void **)&skin.colBits, 0, 0); + + if (!skin.hBitmap) + return; + + skin.hdc = CreateCompatibleDC(0); + DeleteObject(SelectObject(skin.hdc, skin.hBitmap)); + + if (opt.skinMode == SM_COLORFILL) + { + SolidColorFill(bServiceTip); + } + else + { + CreateFromBitmaps(bServiceTip); + if (opt.iEnableColoring == 1) + ColorizeBitmap(); + } +} + +void DestroySkinBitmap() +{ + for (int i = 0; i < SKIN_ITEMS_COUNT; i++) + { + if (skin.fib[i]) + { + fii->FI_Unload(skin.fib[i]); + skin.fib[i] = NULL; + } + + for (int j = SP_CORNER_TL; j < SKIN_PARTS_COUNT; j++) + { + if (skin.hbmpSkinParts[i][j]) + { + DeleteObject(skin.hbmpSkinParts[i][j]); + skin.hbmpSkinParts[i][j] = NULL; + } + } + } + + skin.bCached = false; +} + +void SaveAlpha(LPRECT lpRect) +{ + if (skin.colSavedBits) + { + mir_free(skin.colSavedBits); + skin.colSavedBits = 0; + } + GdiFlush(); + + if (lpRect->left < 0) lpRect->left = 0; + if (lpRect->top < 0) lpRect->top = 0; + if (lpRect->right > skin.iWidth) lpRect->right = skin.iWidth; + if (lpRect->bottom > skin.iHeight) lpRect->bottom = skin.iHeight; + + int x = lpRect->left; + int y = lpRect->top; + int w = lpRect->right - lpRect->left; + int h = lpRect->bottom - lpRect->top; + + skin.colSavedBits = (COLOR32 *)mir_alloc(sizeof(COLOR32) * w * h); + COLOR32 *p1 = skin.colSavedBits; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= skin.iHeight) break; + COLOR32 *p2 = skin.colBits + (y+i)*skin.iWidth + x; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= skin.iWidth) break; + *p1++ = *p2++; + } + } +} + +void RestoreAlpha(LPRECT lpRect, BYTE alpha) +{ + if (!skin.colSavedBits) + return; + + GdiFlush(); + + if (lpRect->left < 0) lpRect->left = 0; + if (lpRect->top < 0) lpRect->top = 0; + if (lpRect->right > skin.iWidth) lpRect->right = skin.iWidth; + if (lpRect->bottom > skin.iHeight) lpRect->bottom = skin.iHeight; + + int x = lpRect->left; + int y = lpRect->top; + int w = lpRect->right - lpRect->left; + int h = lpRect->bottom - lpRect->top; + + COLOR32 *p1 = skin.colSavedBits; + + for (int i = 0; i < h; i++) + { + if (i+y < 0) continue; + if (i+y >= skin.iHeight) break; + COLOR32 *p2 = skin.colBits + (y+i)*skin.iWidth + x; + for (int j = 0; j < w; j++) + { + if (j+x < 0) continue; + if (j+x >= skin.iWidth) break; + if ((*p1&0x00ffffff) != (*p2&0x00ffffff)) + { + *p2 |= (alpha << 24); + } + else + { + *p2 = (*p2&0x00ffffff) | (*p1&0xff000000); + } + ++p1; + ++p2; + } + } + + mir_free(skin.colSavedBits); + skin.colSavedBits = 0; +} + +BOOL IsAlphaTransparent(HBITMAP hBitmap) +{ + BITMAP bmp; + DWORD dwLen; + BYTE *p; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + if (bmp.bmBitsPixel != 32) + return FALSE; + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (BYTE *)mir_alloc(dwLen); + if (p == NULL) return FALSE; + memset(p, 0, dwLen); + + GetBitmapBits(hBitmap, dwLen, p); + + for (int y = 0; y < bmp.bmHeight; y++) + { + BYTE *px = p + bmp.bmWidth * 4 * y; + for (int x = 0; x < bmp.bmWidth; x++) + { + if (px[3] != 0) + { + mir_free(p); + return TRUE; + } + + px += 4; + } + } + + mir_free(p); + return FALSE; +} + +void DrawIconExAlpha(HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags, bool bIsSmiley) +{ + bool restore = false; + + if (skin.bNeedLayerUpdate && !bIsSmiley) + { + ICONINFO icon; + if (GetIconInfo(hIcon, &icon)) + { + if (!IsAlphaTransparent(icon.hbmColor)) + { + RECT rc; + SetRect(&rc, xLeft, yTop, xLeft + cxWidth, yTop + cyWidth); + SaveAlpha(&rc); + restore = true; + } + + DeleteObject(icon.hbmColor); + DeleteObject(icon.hbmMask); + } + } + + DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hbrFlickerFreeDraw, diFlags); + + if (skin.bNeedLayerUpdate && restore) + { + RECT rc; + SetRect(&rc, xLeft, yTop, xLeft + cxWidth, yTop + cyWidth); + RestoreAlpha(&rc); + } +} + +int DrawTextAlpha(HDC hdc, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat) +{ + RECT rc; + SetRect(&rc, lpRect->left - 1, lpRect->top - 1, lpRect->right + 1, lpRect->bottom + 1); + + if (skin.bNeedLayerUpdate) SaveAlpha(&rc); + int result = DrawText(hdc, lpString, nCount, lpRect, uFormat); + if (skin.bNeedLayerUpdate) RestoreAlpha(&rc); + + return result; +} + +static __forceinline COLOR32 rgba(COLOR32 r, COLOR32 g, COLOR32 b, COLOR32 a) +{ + return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); +} + +static __forceinline COLOR32 getr(COLOR32 c) +{ + return (c >> 16) & 0xff; +} + +static __forceinline COLOR32 getg(COLOR32 c) +{ + return (c >> 8) & 0xff; +} + +static __forceinline COLOR32 getb(COLOR32 c) +{ + return c & 0xff; +} + +static __forceinline COLOR32 geta(COLOR32 c) +{ + return (c >> 24) & 0xff; +} + +void PremultipleChannels() +{ + for (int i = 0; i < skin.iWidth * skin.iHeight; i++) + skin.colBits[i] = rgba( getr(skin.colBits[i])*geta(skin.colBits[i])/255, + getg(skin.colBits[i])*geta(skin.colBits[i])/255, + getb(skin.colBits[i])*geta(skin.colBits[i])/255, + geta(skin.colBits[i])); +} + +#define PU_DIV255(x) ((x)/255) + +void ColorizeBitmap() +{ + if (!skin.colBits) + return; + + GdiFlush(); + + int w = skin.iWidth; + int h = skin.iHeight; + + // we should swap B and R channels when working with win32 COLORREF + float koef1r = (255 - getb(opt.colBg)) / 128.0; + float koef1g = (255 - getg(opt.colBg)) / 128.0; + float koef1b = (255 - getr(opt.colBg)) / 128.0; + + int br = - 255 + 2 * getb(opt.colBg); + int bg = - 255 + 2 * getg(opt.colBg); + int bb = - 255 + 2 * getr(opt.colBg); + + float koef2r = (getb(opt.colBg)) / 128.0; + float koef2g = (getg(opt.colBg)) / 128.0; + float koef2b = (getr(opt.colBg)) / 128.0; + + for (int i = 0; i < w * h; i++) + { + long alpha = geta(skin.colBits[i]); + COLOR32 cl = alpha ? getr(skin.colBits[i])*255/alpha : 0; + + skin.colBits[i] = (cl > 128) ? + rgba( + PU_DIV255((koef1r * cl + br)*alpha), + PU_DIV255((koef1g * cl + bg)*alpha), + PU_DIV255((koef1b * cl + bb)*alpha), + alpha): + rgba( + PU_DIV255(koef2r * cl * alpha), + PU_DIV255(koef2g * cl * alpha), + PU_DIV255(koef2b * cl * alpha), + alpha); + } +} + +// code from Clist Modern by FYR +HRGN CreateOpaqueRgn(BYTE level, bool bOpaque) +{ + if (!skin.colBits) + return NULL; + + GdiFlush(); + + RGBQUAD *buff = (RGBQUAD *)skin.colBits; + + int x,y; + unsigned int cRect = 64; + PRGNDATA pRgnData = (PRGNDATA)malloc(sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + memset(pRgnData, 0, sizeof(RGNDATAHEADER)); + pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); + pRgnData->rdh.iType = RDH_RECTANGLES; + + for (y = 0; y < skin.iHeight; ++y) + { + bool inside = false; + bool lastin = false; + unsigned int entry = 0; + + for (x = 0; x < skin.iWidth; ++x) + { + inside = bOpaque ? (buff->rgbReserved > level) : (buff->rgbReserved < level); + ++buff; + + if (inside != lastin) + { + if (inside) + { + lastin = true; + entry = x; + } + else + { + if (pRgnData->rdh.nCount == cRect) + { + cRect = cRect + 64; + pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + } + + SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, skin.iHeight - y, x, skin.iHeight - y + 1); + pRgnData->rdh.nCount++; + lastin = false; + } + } + } + + if (lastin) + { + if (pRgnData->rdh.nCount == cRect) + { + cRect = cRect + 64; + pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT)); + } + + SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, skin.iHeight - y, x, skin.iHeight - y + 1); + pRgnData->rdh.nCount++; + } + } + + HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData); + free(pRgnData); + return hRgn; +} \ No newline at end of file -- cgit v1.2.3