From e166e34948678364d983e72b5b83d48dc417fb03 Mon Sep 17 00:00:00 2001 From: spx Date: Sat, 22 Oct 2011 20:28:15 +0000 Subject: [PATCH] - Fixed Background=*.png issue: http://rainmeter.net/forum/viewtopic.php?f=5&t=8596 - Performance improvement on BitmapToRegion function. --- Library/Litestep.cpp | 117 ++++++++++++++++++++-------------------- Library/Litestep.h | 2 +- Library/MeterWindow.cpp | 20 +++++-- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/Library/Litestep.cpp b/Library/Litestep.cpp index a21aefea..154ea11d 100644 --- a/Library/Litestep.cpp +++ b/Library/Litestep.cpp @@ -46,11 +46,9 @@ void FinalizeLitestep() DeleteCriticalSection(&g_CsLogDelay); } -HRGN BitmapToRegion(HBITMAP hbm, COLORREF clrTransp, COLORREF clrTolerance, int xoffset, int yoffset) +HRGN BitmapToRegion(HBITMAP hbm, COLORREF clrTransp, COLORREF clrTolerance) { - // start with a completely transparent rgn - // this is more correct as no bmp, should render a transparent background - HRGN hRgn = CreateRectRgn(0, 0, 0, 0); + HRGN hRgn = NULL; if (hbm) { @@ -58,26 +56,25 @@ HRGN BitmapToRegion(HBITMAP hbm, COLORREF clrTransp, COLORREF clrTolerance, int HDC hdcMem = CreateCompatibleDC(NULL); if (hdcMem) { - VOID *pbits32; - HBITMAP hbm32; - BITMAP bm; // get the size + BITMAP bm; GetObject(hbm, sizeof(BITMAP), &bm); BITMAPINFOHEADER bmpInfo32; - bmpInfo32.biSize = sizeof(BITMAPINFOHEADER); - bmpInfo32.biWidth = bm.bmWidth; - bmpInfo32.biHeight = bm.bmHeight; - bmpInfo32.biPlanes = 1; - bmpInfo32.biBitCount = 32; - bmpInfo32.biCompression = BI_RGB; - bmpInfo32.biSizeImage = 0; - bmpInfo32.biXPelsPerMeter = 0; - bmpInfo32.biYPelsPerMeter = 0; - bmpInfo32.biClrUsed = 0; - bmpInfo32.biClrImportant = 0; + bmpInfo32.biSize = sizeof(BITMAPINFOHEADER); + bmpInfo32.biWidth = bm.bmWidth; + bmpInfo32.biHeight = bm.bmHeight; + bmpInfo32.biPlanes = 1; + bmpInfo32.biBitCount = 32; + bmpInfo32.biCompression = BI_RGB; + bmpInfo32.biSizeImage = 0; + bmpInfo32.biXPelsPerMeter = 0; + bmpInfo32.biYPelsPerMeter = 0; + bmpInfo32.biClrUsed = 0; + bmpInfo32.biClrImportant = 0; - hbm32 = CreateDIBSection(hdcMem, (BITMAPINFO *) & bmpInfo32, DIB_RGB_COLORS, &pbits32, NULL, 0); + VOID* pbits32; + HBITMAP hbm32 = CreateDIBSection(hdcMem, (BITMAPINFO *) & bmpInfo32, DIB_RGB_COLORS, &pbits32, NULL, 0); if (hbm32) { HBITMAP hbmOld32 = (HBITMAP)SelectObject(hdcMem, hbm32); @@ -87,11 +84,14 @@ HRGN BitmapToRegion(HBITMAP hbm, COLORREF clrTransp, COLORREF clrTolerance, int if (hdcTmp) { // Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits - int y = 0; BITMAP bm32; GetObject(hbm32, sizeof(bm32), &bm32); while (bm32.bmWidthBytes % 4) - bm32.bmWidthBytes++; + ++bm32.bmWidthBytes; + + // Copy the bitmap into the memory D + HBITMAP hbmOld = (HBITMAP)SelectObject(hdcTmp, hbm); + BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcTmp, 0, 0, SRCCOPY); // get the limits for the colors BYTE clrHiR = ( 0xff - GetRValue( clrTolerance ) > GetRValue( clrTransp ) ) ? GetRValue( clrTransp ) + GetRValue( clrTolerance ) : 0xff; @@ -101,68 +101,67 @@ HRGN BitmapToRegion(HBITMAP hbm, COLORREF clrTransp, COLORREF clrTolerance, int BYTE clrLoG = ( GetGValue( clrTolerance ) < GetGValue( clrTransp ) ) ? GetGValue( clrTransp ) - GetGValue( clrTolerance ) : 0x00; BYTE clrLoB = ( GetBValue( clrTolerance ) < GetBValue( clrTransp ) ) ? GetBValue( clrTransp ) - GetBValue( clrTolerance ) : 0x00; - // Copy the bitmap into the memory D - HBITMAP hbmOld = (HBITMAP)SelectObject(hdcTmp, hbm); - - BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcTmp, 0, 0, SRCCOPY); + // Allocate initial RGNDATA buffer + #define ALLOC_UNIT 100 + DWORD maxRects = ALLOC_UNIT; + HANDLE hRgnData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects)); + RGNDATA* pRgnData = (RGNDATA*)GlobalLock(hRgnData); + pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER); + pRgnData->rdh.iType = RDH_RECTANGLES; + pRgnData->rdh.nCount = pRgnData->rdh.nRgnSize = 0; + SetRect(&pRgnData->rdh.rcBound, 0, 0, bm.bmWidth, bm.bmHeight); // Scan each bitmap row from bottom to top (the bitmap is inverted vertically - BYTE *p; - BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes; - while (y < bm.bmHeight) + BYTE* p32 = (BYTE*)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes; + for (int y = 0; y < bm.bmHeight; ++y) { - int x = 0; - while ( x < bm.bmWidth ) + for (int x = 0; x < bm.bmWidth; ++x) { - int x0 = 0; - // loop through all transparent pixels... - while ( x < bm.bmWidth ) - { - p = p32 + 4 * x; - // if the pixel is non-transparent - if (*p < clrLoB || *p > clrHiB) - break; - p++; - if (*p < clrLoG || *p > clrHiG) - break; - p++; - if (*p < clrLoR || *p > clrHiR) - break; + int x0 = x; - x++; - } - // set first non transparent pixel - x0 = x; // loop through all non transparent pixels - while ( x < bm.bmWidth ) + while (x < bm.bmWidth) { - p = p32 + 4 * x; + BYTE* p = p32 + 4 * x; // if the pixel is transparent, then break if (*p >= clrLoB && *p <= clrHiB) { - p++; + ++p; if (*p >= clrLoG && *p <= clrHiG) { - p++; + ++p; if (*p >= clrLoR && *p <= clrHiR) break; } } - x++; + ++x; } + // if found one or more non-transparent pixels in a row, add them to the rgn... - if (x != x0) + if (x > x0) { - HRGN hTempRgn = CreateRectRgn(x0 + xoffset, y + yoffset, x + xoffset, y + 1 + yoffset); - CombineRgn(hRgn, hRgn, hTempRgn, RGN_OR); - DeleteObject(hTempRgn); + if (pRgnData->rdh.nCount >= maxRects) + { + // Reallocate RGNDATA buffer + GlobalUnlock(hRgnData); + maxRects += ALLOC_UNIT; + hRgnData = GlobalReAlloc(hRgnData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE); + pRgnData = (RGNDATA*)GlobalLock(hRgnData); + } + + SetRect(((RECT*)pRgnData->Buffer) + pRgnData->rdh.nCount, x0, y, x, y + 1); + ++pRgnData->rdh.nCount; } - x++; } - y++; p32 -= bm32.bmWidthBytes; } + + // Create the region with the collected rectangles + hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pRgnData); + // Clean up + GlobalUnlock(hRgnData); + GlobalFree(hRgnData); SelectObject(hdcTmp, hbmOld); DeleteDC(hdcTmp); } diff --git a/Library/Litestep.h b/Library/Litestep.h index fa2bd8c1..051888aa 100644 --- a/Library/Litestep.h +++ b/Library/Litestep.h @@ -30,7 +30,7 @@ void FinalizeLitestep(); void ResetLoggingFlag(); -HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance, int xoffset, int yoffset); +HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance); std::string ConvertToAscii(LPCTSTR str); std::wstring ConvertToWide(LPCSTR str); diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 0a10ffc8..43fcfd19 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -399,8 +399,8 @@ void CMeterWindow::Refresh(bool init, bool all) // Set the window region CreateRegion(true); // Clear the region + if (init) ShowWindow(m_Window, SW_SHOWNOACTIVATE); Update(false); - CreateRegion(false); if (m_KeepOnScreen) { @@ -2652,10 +2652,18 @@ void CMeterWindow::CreateRegion(bool clear) m_DoubleBuffer->GetHBITMAP(Color(255,0,255), &background); if (background) { - HRGN region = BitmapToRegion(background, RGB(255,0,255), 0x101010, 0, 0); + HRGN region = BitmapToRegion(background, RGB(255,0,255), 0x101010); SetWindowRgn(m_Window, region, TRUE); DeleteObject(background); } + else + { + SetWindowRgn(m_Window, NULL, TRUE); + } + } + else + { + SetWindowRgn(m_Window, NULL, TRUE); } } } @@ -2672,7 +2680,6 @@ void CMeterWindow::Redraw() if (m_ResetRegion) { ResizeWindow(false); - CreateRegion(true); } // Create or clear the doublebuffer @@ -2768,8 +2775,11 @@ void CMeterWindow::Redraw() } } - if (m_ResetRegion) CreateRegion(false); - m_ResetRegion = false; + if (m_ResetRegion || !m_BackgroundName.empty()) + { + CreateRegion(false); + m_ResetRegion = false; + } UpdateTransparency(m_TransparencyValue, false);