summaryrefslogtreecommitdiff
path: root/plugins/Clist_nicer/src/alphablend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Clist_nicer/src/alphablend.cpp')
-rw-r--r--plugins/Clist_nicer/src/alphablend.cpp545
1 files changed, 545 insertions, 0 deletions
diff --git a/plugins/Clist_nicer/src/alphablend.cpp b/plugins/Clist_nicer/src/alphablend.cpp
new file mode 100644
index 0000000000..f81c029bad
--- /dev/null
+++ b/plugins/Clist_nicer/src/alphablend.cpp
@@ -0,0 +1,545 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "commonheaders.h"
+
+extern int g_hottrack, g_hottrack_done;
+extern BOOL g_inCLCpaint;
+extern BYTE saved_alpha;
+extern DWORD savedCORNER;
+extern StatusItems_t *StatusItems;
+extern ImageItem *g_glyphItem;
+
+BYTE __forceinline percent_to_byte(UINT32 percent)
+{
+ return(BYTE) ((FLOAT) (((FLOAT) percent) / 100) * 255);
+}
+
+COLORREF __forceinline revcolref(COLORREF colref)
+{
+ return RGB(GetBValue(colref), GetGValue(colref), GetRValue(colref));
+}
+
+DWORD __forceinline argb_from_cola(COLORREF col, UINT32 alpha)
+{
+ return((BYTE) percent_to_byte(alpha) << 24 | col);
+}
+
+
+void __forceinline DrawBorderStyle(HDC hdcwnd, RECT *rc, DWORD BORDERSTYLE)
+{
+ if(BORDERSTYLE >= 0) {
+ HPEN hPenOld = 0;
+ POINT pt;
+
+ switch(BORDERSTYLE) {
+ case BDR_RAISEDOUTER: // raised
+ MoveToEx(hdcwnd, rc->left, rc->bottom - 1, &pt);
+ hPenOld = reinterpret_cast<HPEN>(SelectObject(hdcwnd, cfg::dat.hPen3DBright));
+ LineTo(hdcwnd, rc->left, rc->top);
+ LineTo(hdcwnd, rc->right, rc->top);
+ SelectObject(hdcwnd, cfg::dat.hPen3DDark);
+ MoveToEx(hdcwnd, rc->right - 1, rc->top + 1, &pt);
+ LineTo(hdcwnd, rc->right - 1, rc->bottom - 1);
+ LineTo(hdcwnd, rc->left - 1, rc->bottom - 1);
+ break;
+ case BDR_SUNKENINNER:
+ MoveToEx(hdcwnd, rc->left, rc->bottom - 1, &pt);
+ hPenOld = reinterpret_cast<HPEN>(SelectObject(hdcwnd, cfg::dat.hPen3DDark));
+ LineTo(hdcwnd, rc->left, rc->top);
+ LineTo(hdcwnd, rc->right, rc->top);
+ MoveToEx(hdcwnd, rc->right - 1, rc->top + 1, &pt);
+ SelectObject(hdcwnd, cfg::dat.hPen3DBright);
+ LineTo(hdcwnd, rc->right - 1, rc->bottom - 1);
+ LineTo(hdcwnd, rc->left, rc->bottom - 1);
+ break;
+ default:
+ DrawEdge(hdcwnd, rc, BORDERSTYLE, BF_RECT | BF_SOFT);
+ break;
+ }
+ if(hPenOld)
+ SelectObject(hdcwnd, hPenOld);
+ }
+}
+void DrawAlpha(HDC hdcwnd, PRECT rc, DWORD basecolor, int alpha, DWORD basecolor2, BOOL transparent, BYTE FLG_GRADIENT, BYTE FLG_CORNER, DWORD BORDERSTYLE, ImageItem *imageItem)
+{
+ HBRUSH BrMask;
+ HBRUSH holdbrush;
+ HDC hdc;
+ BLENDFUNCTION bf;
+ HBITMAP hbitmap;
+ HBITMAP holdbitmap;
+ BITMAPINFO bmi;
+ VOID *pvBits;
+ UINT32 x, y;
+ ULONG ulBitmapWidth, ulBitmapHeight;
+ UCHAR ubAlpha = 0xFF;
+ UCHAR ubRedFinal = 0xFF;
+ UCHAR ubGreenFinal = 0xFF;
+ UCHAR ubBlueFinal = 0xFF;
+ UCHAR ubRed;
+ UCHAR ubGreen;
+ UCHAR ubBlue;
+ UCHAR ubRed2;
+ UCHAR ubGreen2;
+ UCHAR ubBlue2;
+
+ int realx;
+
+ FLOAT fAlphaFactor;
+ LONG realHeight = (rc->bottom - rc->top);
+ LONG realWidth = (rc->right - rc->left);
+ LONG realHeightHalf = realHeight >> 1;
+
+ if (g_hottrack && g_inCLCpaint) {
+ StatusItems_t *ht = &StatusItems[ID_EXTBKHOTTRACK - ID_STATUS_OFFLINE];
+ if (ht->IGNORED == 0) {
+ basecolor = ht->COLOR;
+ basecolor2 = ht->COLOR2;
+ alpha = ht->ALPHA;
+ FLG_GRADIENT = ht->GRADIENT;
+ transparent = ht->COLOR2_TRANSPARENT;
+ BORDERSTYLE = ht->BORDERSTYLE;
+ imageItem = ht->imageItem;
+ }
+ g_hottrack_done = 1;
+ }
+
+ if(imageItem) {
+ IMG_RenderImageItem(hdcwnd, imageItem, rc);
+ return;
+ }
+
+ if (rc == NULL)
+ return;
+
+ if (rc->right < rc->left || rc->bottom < rc->top || (realHeight <= 0) || (realWidth <= 0))
+ return;
+
+ if(cfg::dat.bUseFastGradients && !(FLG_CORNER & CORNER_ACTIVE)) {
+ GRADIENT_RECT grect;
+ TRIVERTEX tvtx[2];
+ int orig = 1, dest = 0;
+
+ if (!(FLG_GRADIENT & GRADIENT_ACTIVE)) {
+ tvtx[0].Red = tvtx[1].Red = (COLOR16)GetRValue(basecolor) << 8;
+ tvtx[0].Blue = tvtx[1].Blue = (COLOR16)GetBValue(basecolor) << 8;
+ tvtx[0].Green = tvtx[1].Green = (COLOR16)GetGValue(basecolor) << 8;
+ tvtx[0].Alpha = tvtx[1].Alpha = 0;
+ }
+ else {
+ if(FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_TB) {
+ orig = 0;
+ dest = 1;
+ }
+
+ tvtx[orig].Red = (COLOR16)GetRValue(basecolor) << 8;
+ tvtx[orig].Blue = (COLOR16)GetBValue(basecolor) << 8;
+ tvtx[orig].Green = (COLOR16)GetGValue(basecolor) << 8;
+ tvtx[orig].Alpha = (COLOR16)0;
+
+ tvtx[dest].Red = (COLOR16)GetRValue(basecolor2) << 8;
+ tvtx[dest].Blue = (COLOR16)GetBValue(basecolor2) << 8;
+ tvtx[dest].Green = (COLOR16)GetGValue(basecolor2) << 8;
+ tvtx[dest].Alpha = (COLOR16)0;
+ }
+ grect.UpperLeft = 0;
+ grect.LowerRight = 1;
+
+ saved_alpha = (UCHAR) (basecolor >> 24);
+
+ if(alpha < 100) {
+ BLENDFUNCTION bf;
+ HDC hdc;
+ HBITMAP hbm, hbmOld;
+ LONG width = rc->right - rc->left, height = rc->bottom - rc->top;
+
+ tvtx[0].x = tvtx[0].y = 0;
+ tvtx[1].x = width;
+ tvtx[1].y = height;
+
+ basecolor = argb_from_cola(revcolref(basecolor), alpha);
+ basecolor2 = argb_from_cola(revcolref(basecolor2), alpha);
+ bf.BlendOp = AC_SRC_OVER;
+ bf.BlendFlags = 0;
+ bf.SourceConstantAlpha = percent_to_byte((UINT32)alpha);
+ bf.AlphaFormat = 0; // so it will use our specified alpha value
+ hdc = CreateCompatibleDC(hdcwnd);
+ if (!hdc)
+ return;
+ hbm = CreateCompatibleBitmap(hdcwnd, width, height);
+ hbmOld = reinterpret_cast<HBITMAP>(SelectObject(hdc, hbm));
+ API::pfnGradientFill(hdc, tvtx, 2, &grect, 1, (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
+ API::pfnAlphaBlend(hdcwnd, rc->left, rc->top, width, height, hdc, 0, 0, width, height, bf);
+
+ SelectObject(hdc, hbmOld);
+ DeleteObject(hbm);
+ DeleteDC(hdc);
+ }
+ else {
+ tvtx[0].x = rc->left;
+ tvtx[0].y = rc->top;
+ tvtx[1].x = rc->right;
+ tvtx[1].y = rc->bottom;
+ API::pfnGradientFill(hdcwnd, tvtx, 2, &grect, 1, (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT) ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H);
+ }
+ DrawBorderStyle(hdcwnd, rc, BORDERSTYLE);
+ //_DebugPopup(0, "using gradient fill");
+ return;
+ }
+
+ hdc = CreateCompatibleDC(hdcwnd);
+ if (!hdc)
+ return;
+
+ ZeroMemory(&bmi, sizeof(BITMAPINFO));
+
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+
+ if (FLG_GRADIENT & GRADIENT_ACTIVE && (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL)) {
+ bmi.bmiHeader.biWidth = ulBitmapWidth = realWidth;
+ bmi.bmiHeader.biHeight = ulBitmapHeight = 1;
+ } else if (FLG_GRADIENT & GRADIENT_ACTIVE && (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT)) {
+ bmi.bmiHeader.biWidth = ulBitmapWidth = 1;
+ bmi.bmiHeader.biHeight = ulBitmapHeight = realHeight;
+ } else {
+ bmi.bmiHeader.biWidth = ulBitmapWidth = 1;
+ bmi.bmiHeader.biHeight = ulBitmapHeight = 1;
+ }
+
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4;
+
+ if (ulBitmapWidth <= 0 || ulBitmapHeight <= 0)
+ return;
+
+ hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
+ if (hbitmap == NULL || pvBits == NULL) {
+ DeleteDC(hdc);
+ return;
+ }
+
+ holdbitmap = reinterpret_cast<HBITMAP>(SelectObject(hdc, hbitmap));
+
+ // convert basecolor to RGB and then merge alpha so its ARGB
+ basecolor = argb_from_cola(revcolref(basecolor), alpha);
+ basecolor2 = argb_from_cola(revcolref(basecolor2), alpha);
+
+ ubRed = (UCHAR) (basecolor >> 16);
+ ubGreen = (UCHAR) (basecolor >> 8);
+ ubBlue = (UCHAR) basecolor;
+
+ ubRed2 = (UCHAR) (basecolor2 >> 16);
+ ubGreen2 = (UCHAR) (basecolor2 >> 8);
+ ubBlue2 = (UCHAR) basecolor2;
+
+ //DRAW BASE - make corner space 100% transparent
+ for (y = 0; y < ulBitmapHeight; y++) {
+ for (x = 0 ; x < ulBitmapWidth ; x++) {
+ if (FLG_GRADIENT & GRADIENT_ACTIVE) {
+ if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL) {
+ realx = x + realHeightHalf;
+ realx = (ULONG) realx > ulBitmapWidth ? ulBitmapWidth : realx;
+ gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, realx, &ubAlpha);
+ } else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT)
+ gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha);
+
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ } else {
+ ubAlpha = percent_to_byte(alpha);
+ ubRedFinal = ubRed;
+ ubGreenFinal = ubGreen;
+ ubBlueFinal = ubBlue;
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ }
+ }
+ }
+ bf.BlendOp = AC_SRC_OVER;
+ bf.BlendFlags = 0;
+ bf.SourceConstantAlpha = (UCHAR) (basecolor >> 24);
+ bf.AlphaFormat = AC_SRC_ALPHA; // so it will use our specified alpha value
+
+ API::pfnAlphaBlend(hdcwnd, rc->left + realHeightHalf, rc->top, (realWidth - realHeightHalf * 2), realHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf);
+
+ SelectObject(hdc, holdbitmap);
+ DeleteObject(hbitmap);
+
+ saved_alpha = (UCHAR) (basecolor >> 24);
+
+ // corners
+ BrMask = CreateSolidBrush(RGB(0xFF, 0x00, 0xFF));
+ {
+ bmi.bmiHeader.biWidth = ulBitmapWidth = realHeightHalf;
+ bmi.bmiHeader.biHeight = ulBitmapHeight = realHeight;
+ bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4;
+
+ if (ulBitmapWidth <= 0 || ulBitmapHeight <= 0) {
+ DeleteDC(hdc);
+ DeleteObject(BrMask);
+ return;
+ }
+
+ // TL+BL CORNER
+ hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
+
+ if(hbitmap == 0 || pvBits == NULL) {
+ DeleteObject(BrMask);
+ DeleteDC(hdc);
+ return;
+ }
+
+ holdbrush = reinterpret_cast<HBRUSH>(SelectObject(hdc, BrMask));
+ holdbitmap = reinterpret_cast<HBITMAP>(SelectObject(hdc, hbitmap));
+ RoundRect(hdc, -1, -1, ulBitmapWidth * 2 + 1, (realHeight + 1), cfg::dat.cornerRadius << 1, cfg::dat.cornerRadius << 1);
+
+ for (y = 0; y < ulBitmapHeight; y++) {
+ for (x = 0; x < ulBitmapWidth; x++) {
+ if (((((UINT32 *) pvBits)[x + y * ulBitmapWidth]) << 8) == 0xFF00FF00 || (y< ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_BL && FLG_CORNER & CORNER_ACTIVE)) || (y > ulBitmapHeight >> 2 && !(FLG_CORNER & CORNER_TL && FLG_CORNER & CORNER_ACTIVE))) {
+ if (FLG_GRADIENT & GRADIENT_ACTIVE) {
+ if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL)
+ gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, realWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, x, &ubAlpha);
+ else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT)
+ gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha);
+
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ } else {
+ ubAlpha = percent_to_byte(alpha);
+ ubRedFinal = ubRed;
+ ubGreenFinal = ubGreen;
+ ubBlueFinal = ubBlue;
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ }
+ }
+ }
+ }
+ API::pfnAlphaBlend(hdcwnd, rc->left, rc->top, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf);
+ SelectObject(hdc, holdbitmap);
+ DeleteObject(hbitmap);
+
+ // TR+BR CORNER
+ hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0);
+
+ //SelectObject(hdc, BrMask); // already BrMask?
+ holdbitmap = reinterpret_cast<HBITMAP>(SelectObject(hdc, hbitmap));
+ RoundRect(hdc, -1 - ulBitmapWidth, -1, ulBitmapWidth + 1, (realHeight + 1), cfg::dat.cornerRadius << 1, cfg::dat.cornerRadius << 1);
+
+ for (y = 0; y < ulBitmapHeight; y++) {
+ for (x = 0; x < ulBitmapWidth; x++) {
+ if (((((UINT32 *) pvBits)[x + y * ulBitmapWidth]) << 8) == 0xFF00FF00 || (y< ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_BR && FLG_CORNER & CORNER_ACTIVE)) || (y > ulBitmapHeight >> 1 && !(FLG_CORNER & CORNER_TR && FLG_CORNER & CORNER_ACTIVE))) {
+ if (FLG_GRADIENT & GRADIENT_ACTIVE) {
+ if (FLG_GRADIENT & GRADIENT_LR || FLG_GRADIENT & GRADIENT_RL) {
+ realx = x + realWidth;
+ realx = realx > realWidth ? realWidth : realx;
+ gradientHorizontal(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, realWidth, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, realx, &ubAlpha);
+ } else if (FLG_GRADIENT & GRADIENT_TB || FLG_GRADIENT & GRADIENT_BT)
+ gradientVertical(&ubRedFinal, &ubGreenFinal, &ubBlueFinal, ulBitmapHeight, ubRed, ubGreen, ubBlue, ubRed2, ubGreen2, ubBlue2, FLG_GRADIENT, transparent, y, &ubAlpha);
+
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ } else {
+ ubAlpha = percent_to_byte(alpha);
+ ubRedFinal = ubRed;
+ ubGreenFinal = ubGreen;
+ ubBlueFinal = ubBlue;
+ fAlphaFactor = (float) ubAlpha / (float) 0xff;
+
+ ((UINT32 *) pvBits)[x + y * ulBitmapWidth] = (ubAlpha << 24) | ((UCHAR) (ubRedFinal * fAlphaFactor) << 16) | ((UCHAR) (ubGreenFinal * fAlphaFactor) << 8) | ((UCHAR) (ubBlueFinal * fAlphaFactor));
+ }
+ }
+ }
+ }
+ API::pfnAlphaBlend(hdcwnd, rc->right - realHeightHalf, rc->top, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf);
+ }
+ DrawBorderStyle(hdcwnd, rc, BORDERSTYLE);
+
+ SelectObject(hdc, holdbitmap);
+ DeleteObject(hbitmap);
+ SelectObject(hdc, holdbrush);
+ DeleteObject(BrMask);
+ DeleteDC(hdc);
+}
+
+void __inline gradientHorizontal(UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, ULONG ulBitmapWidth, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 x, UCHAR *ubAlpha)
+{
+ FLOAT fSolidMulti, fInvSolidMulti;
+
+ // solid to transparent
+ if (transparent) {
+ *ubAlpha = (UCHAR) ((float) x / (float) ulBitmapWidth * 255);
+ *ubAlpha = FLG_GRADIENT & GRADIENT_LR ? 0xFF - (*ubAlpha) : (*ubAlpha);
+ *ubRedFinal = ubRed; *ubGreenFinal = ubGreen; *ubBlueFinal = ubBlue;
+ } else { // solid to solid2
+ if (FLG_GRADIENT & GRADIENT_LR) {
+ fSolidMulti = ((float) x / (float) ulBitmapWidth);
+ fInvSolidMulti = 1 - fSolidMulti;
+ } else {
+ fInvSolidMulti = ((float) x / (float) ulBitmapWidth);
+ fSolidMulti = 1 - fInvSolidMulti;
+ }
+
+ *ubRedFinal = (UCHAR) (((float) ubRed * (float) fInvSolidMulti) + ((float) ubRed2 * (float) fSolidMulti));
+ *ubGreenFinal = (UCHAR) (((float) ubGreen * (float) fInvSolidMulti) + ((float) ubGreen2 * (float) fSolidMulti));
+ *ubBlueFinal = (UCHAR) (((float) ubBlue * (float) fInvSolidMulti) + ((float) ubBlue2 * (float) fSolidMulti));
+
+ *ubAlpha = 0xFF;
+ }
+}
+
+void __inline gradientVertical(UCHAR *ubRedFinal, UCHAR *ubGreenFinal, UCHAR *ubBlueFinal, ULONG ulBitmapHeight, UCHAR ubRed, UCHAR ubGreen, UCHAR ubBlue, UCHAR ubRed2, UCHAR ubGreen2, UCHAR ubBlue2, DWORD FLG_GRADIENT, BOOL transparent, UINT32 y, UCHAR *ubAlpha)
+{
+ FLOAT fSolidMulti, fInvSolidMulti;
+
+ // solid to transparent
+ if (transparent) {
+ *ubAlpha = (UCHAR) ((float) y / (float) ulBitmapHeight * 255);
+ *ubAlpha = FLG_GRADIENT & GRADIENT_BT ? 0xFF - *ubAlpha : *ubAlpha;
+ *ubRedFinal = ubRed; *ubGreenFinal = ubGreen; *ubBlueFinal = ubBlue;
+ } else { // solid to solid2
+ if (FLG_GRADIENT & GRADIENT_BT) {
+ fSolidMulti = ((float) y / (float) ulBitmapHeight);
+ fInvSolidMulti = 1 - fSolidMulti;
+ } else {
+ fInvSolidMulti = ((float) y / (float) ulBitmapHeight);
+ fSolidMulti = 1 - fInvSolidMulti;
+ }
+
+ *ubRedFinal = (UCHAR) (((float) ubRed * (float) fInvSolidMulti) + ((float) ubRed2 * (float) fSolidMulti));
+ *ubGreenFinal = (UCHAR) (((float) ubGreen * (float) fInvSolidMulti) + ((float) ubGreen2 * (float) fSolidMulti));
+ *ubBlueFinal = (UCHAR) (((float) ubBlue * (float) fInvSolidMulti) + ((float) ubBlue2 * (float) fSolidMulti));
+
+ *ubAlpha = 0xFF;
+ }
+}
+
+/*
+ * render a skin image to the given rect.
+ * all parameters are in ImageItem already pre-configured
+ */
+
+// XXX add support for more stretching options (stretch/tile divided image parts etc.
+
+void __fastcall IMG_RenderImageItem(HDC hdc, ImageItem *item, RECT *rc)
+{
+ BYTE l = item->bLeft, r = item->bRight, t = item->bTop, b = item->bBottom;
+ LONG width = rc->right - rc->left;
+ LONG height = rc->bottom - rc->top;
+ BOOL isGlyph = (item->dwFlags & IMAGE_GLYPH) && g_glyphItem;
+ HDC hdcSrc = isGlyph ? g_glyphItem->hdc : item->hdc;
+ LONG srcOrigX = isGlyph ? item->glyphMetrics[0] : 0;
+ LONG srcOrigY = isGlyph ? item->glyphMetrics[1] : 0;
+
+ if(item->dwFlags & IMAGE_FLAG_DIVIDED) {
+ // top 3 items
+
+ API::pfnAlphaBlend(hdc, rc->left, rc->top, l, t, hdcSrc, srcOrigX, srcOrigY, l, t, item->bf);
+ API::pfnAlphaBlend(hdc, rc->left + l, rc->top, width - l - r, t, hdcSrc, srcOrigX + l, srcOrigY, item->inner_width, t, item->bf);
+ API::pfnAlphaBlend(hdc, rc->right - r, rc->top, r, t, hdcSrc, srcOrigX + (item->width - r), srcOrigY, r, t, item->bf);
+
+ // middle 3 items
+
+ API::pfnAlphaBlend(hdc, rc->left, rc->top + t, l, height - t - b, hdcSrc, srcOrigX, srcOrigY + t, l, item->inner_height, item->bf);
+
+ if(item->dwFlags & IMAGE_FILLSOLID && item->fillBrush) {
+ RECT rcFill;
+ rcFill.left = rc->left + l; rcFill.top = rc->top +t;
+ rcFill.right = rc->right - r; rcFill.bottom = rc->bottom - b;
+ FillRect(hdc, &rcFill, item->fillBrush);
+ }
+ else
+ API::pfnAlphaBlend(hdc, rc->left + l, rc->top + t, width - l - r, height - t - b, hdcSrc, srcOrigX + l, srcOrigY + t, item->inner_width, item->inner_height, item->bf);
+
+ API::pfnAlphaBlend(hdc, rc->right - r, rc->top + t, r, height - t - b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + t, r, item->inner_height, item->bf);
+
+ // bottom 3 items
+
+ API::pfnAlphaBlend(hdc, rc->left, rc->bottom - b, l, b, hdcSrc, srcOrigX, srcOrigY + (item->height - b), l, b, item->bf);
+ API::pfnAlphaBlend(hdc, rc->left + l, rc->bottom - b, width - l - r, b, hdcSrc, srcOrigX + l, srcOrigY + (item->height - b), item->inner_width, b, item->bf);
+ API::pfnAlphaBlend(hdc, rc->right - r, rc->bottom - b, r, b, hdcSrc, srcOrigX + (item->width - r), srcOrigY + (item->height - b), r, b, item->bf);
+ }
+ else {
+ switch(item->bStretch) {
+ case IMAGE_STRETCH_H:
+ // tile image vertically, stretch to width
+ {
+ LONG top = rc->top;
+
+ do {
+ if(top + item->height <= rc->bottom) {
+ API::pfnAlphaBlend(hdc, rc->left, top, width, item->height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ top += item->height;
+ }
+ else {
+ API::pfnAlphaBlend(hdc, rc->left, top, width, rc->bottom - top, hdcSrc, srcOrigX, srcOrigY, item->width, rc->bottom - top, item->bf);
+ break;
+ }
+ } while (TRUE);
+ break;
+ }
+ case IMAGE_STRETCH_V:
+ // tile horizontally, stretch to height
+ {
+ LONG left = rc->left;
+
+ do {
+ if(left + item->width <= rc->right) {
+ API::pfnAlphaBlend(hdc, left, rc->top, item->width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ left += item->width;
+ }
+ else {
+ API::pfnAlphaBlend(hdc, left, rc->top, rc->right - left, height, hdcSrc, srcOrigX, srcOrigY, rc->right - left, item->height, item->bf);
+ break;
+ }
+ } while (TRUE);
+ break;
+ }
+ case IMAGE_STRETCH_B:
+ // stretch the image in both directions...
+ API::pfnAlphaBlend(hdc, rc->left, rc->top, width, height, hdcSrc, srcOrigX, srcOrigY, item->width, item->height, item->bf);
+ break;
+ /*
+ case IMAGE_STRETCH_V:
+ // stretch vertically, draw 3 horizontal tiles...
+ AlphaBlend(hdc, rc->left, rc->top, l, height, item->hdc, 0, 0, l, item->height, item->bf);
+ AlphaBlend(hdc, rc->left + l, rc->top, width - l - r, height, item->hdc, l, 0, item->inner_width, item->height, item->bf);
+ AlphaBlend(hdc, rc->right - r, rc->top, r, height, item->hdc, item->width - r, 0, r, item->height, item->bf);
+ break;
+ case IMAGE_STRETCH_H:
+ // stretch horizontally, draw 3 vertical tiles...
+ AlphaBlend(hdc, rc->left, rc->top, width, t, item->hdc, 0, 0, item->width, t, item->bf);
+ AlphaBlend(hdc, rc->left, rc->top + t, width, height - t - b, item->hdc, 0, t, item->width, item->inner_height, item->bf);
+ AlphaBlend(hdc, rc->left, rc->bottom - b, width, b, item->hdc, 0, item->height - b, item->width, b, item->bf);
+ break;
+ */
+ default:
+ break;
+ }
+ }
+}