317 lines
6.2 KiB
C++
317 lines
6.2 KiB
C++
#include "main.h"
|
|
#include "./graphics.h"
|
|
|
|
BYTE
|
|
Graphics_GetSysFontQuality()
|
|
{
|
|
BOOL smoothingEnabled;
|
|
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHING, 0, &smoothingEnabled, 0) ||
|
|
FALSE == smoothingEnabled)
|
|
{
|
|
return DEFAULT_QUALITY;
|
|
}
|
|
|
|
OSVERSIONINFOW vi;
|
|
vi.dwOSVersionInfoSize = sizeof(vi);
|
|
if (FALSE == GetVersionExW(&vi))
|
|
return DEFAULT_QUALITY;
|
|
|
|
if (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion >= 1))
|
|
{
|
|
UINT smootingType;
|
|
if (FALSE == SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &smootingType, 0))
|
|
return DEFAULT_QUALITY;
|
|
|
|
if (FE_FONTSMOOTHINGCLEARTYPE == smootingType)
|
|
return CLEARTYPE_NATURAL_QUALITY/*CLEARTYPE_QUALITY*/;
|
|
}
|
|
|
|
return ANTIALIASED_QUALITY;
|
|
}
|
|
|
|
HFONT
|
|
Graphics_CreateSysFont()
|
|
{
|
|
LOGFONTW lf;
|
|
HFONT font;
|
|
|
|
if (FALSE == SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0))
|
|
return NULL;
|
|
|
|
lf.lfQuality = Graphics_GetSysFontQuality();
|
|
font = CreateFontIndirectW(&lf);
|
|
|
|
return font;
|
|
}
|
|
|
|
HFONT
|
|
Graphics_DuplicateFont(HFONT sourceFont, INT heightDeltaPt, BOOL forceBold, BOOL systemQuality)
|
|
{
|
|
LOGFONTW lf;
|
|
|
|
if (NULL == sourceFont)
|
|
return NULL;
|
|
|
|
|
|
if (sizeof(lf) != GetObjectW(sourceFont, sizeof(lf), &lf))
|
|
return NULL;
|
|
|
|
if (0 != heightDeltaPt)
|
|
{
|
|
HDC hdc, hdcTmp;
|
|
|
|
hdc = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE | DCX_NORESETATTRS);
|
|
hdcTmp = NULL;
|
|
|
|
if (NULL != hdc)
|
|
{
|
|
hdcTmp = CreateCompatibleDC(hdc);
|
|
ReleaseDC(NULL, hdc);
|
|
}
|
|
|
|
if (NULL == hdcTmp)
|
|
return NULL;
|
|
|
|
LONG pixelsY = GetDeviceCaps(hdcTmp, LOGPIXELSY);
|
|
HFONT prevFont = SelectFont(hdcTmp, sourceFont);
|
|
|
|
TEXTMETRICW tm;
|
|
if (FALSE != GetTextMetricsW(hdcTmp, &tm))
|
|
{
|
|
INT basePt = MulDiv(tm.tmHeight - tm.tmInternalLeading, 72, pixelsY);
|
|
lf.lfHeight = -MulDiv((basePt + heightDeltaPt), pixelsY, 72);
|
|
|
|
}
|
|
|
|
SelectObject(hdcTmp, prevFont);
|
|
DeleteDC(hdcTmp);
|
|
}
|
|
|
|
if (FALSE != systemQuality)
|
|
lf.lfQuality = Graphics_GetSysFontQuality();
|
|
if (FALSE != forceBold && lf.lfWeight < FW_BOLD)
|
|
lf.lfWeight = FW_BOLD;
|
|
|
|
return CreateFontIndirectW(&lf);
|
|
}
|
|
|
|
long
|
|
Graphics_GetFontHeight(HDC hdc)
|
|
{
|
|
TEXTMETRICW tm;
|
|
if (FALSE == GetTextMetricsW(hdc, &tm))
|
|
return 0;
|
|
|
|
return tm.tmHeight;
|
|
}
|
|
|
|
long
|
|
Graphics_GetAveStrWidth(HDC hdc, UINT cchLen)
|
|
{
|
|
const char szTest[] =
|
|
{
|
|
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z',
|
|
'a','b','c','d','e','f','g','h','i','j','k','l', 'm','n','o','p','q','r','s','t','u','v','w','x','y','z'
|
|
};
|
|
|
|
SIZE textSize;
|
|
if (FALSE == GetTextExtentPointA(hdc, szTest, ARRAYSIZE(szTest) -1, &textSize))
|
|
return 0;
|
|
|
|
LONG result;
|
|
if (1 == cchLen)
|
|
{
|
|
result = (textSize.cx + ARRAYSIZE(szTest)/2)/ARRAYSIZE(szTest);
|
|
}
|
|
else
|
|
{
|
|
result = MulDiv(cchLen, textSize.cx + ARRAYSIZE(szTest)/2, ARRAYSIZE(szTest));
|
|
if (0 != result)
|
|
{
|
|
TEXTMETRICW tm;
|
|
if (FALSE != GetTextMetricsW(hdc, &tm))
|
|
result += tm.tmOverhang;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
Graphics_GetWindowBaseUnits(HWND hwnd, LONG *baseUnitX, LONG *baseUnitY)
|
|
{
|
|
BOOL result;
|
|
result = FALSE;
|
|
|
|
if (NULL != hwnd)
|
|
{
|
|
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
|
if (NULL != hdc)
|
|
{
|
|
TEXTMETRICW tm;
|
|
HFONT font, prevFont;
|
|
|
|
font = (HFONT)SNDMSG(hwnd, WM_GETFONT, 0, 0L);
|
|
prevFont = SelectFont(hdc, font);
|
|
|
|
if (FALSE != GetTextMetricsW(hdc, &tm))
|
|
{
|
|
if (NULL != baseUnitX)
|
|
*baseUnitX = Graphics_GetAveStrWidth(hdc, 1);
|
|
|
|
if (NULL != baseUnitY)
|
|
*baseUnitY = tm.tmHeight;
|
|
|
|
result = TRUE;
|
|
}
|
|
|
|
SelectFont(hdc, prevFont);
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
typedef int (*SkinColorFunc)(int idx);
|
|
|
|
COLORREF Graphics_GetSkinColor(unsigned int colorIndex)
|
|
{
|
|
static SkinColorFunc GetSkinColor = NULL;
|
|
|
|
if (NULL == GetSkinColor)
|
|
{
|
|
GetSkinColor = (SkinColorFunc)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SKIN_WADLG_GETFUNC, 1);
|
|
if (NULL == GetSkinColor)
|
|
return RGB(255, 0, 255);
|
|
}
|
|
|
|
return GetSkinColor(colorIndex);
|
|
}
|
|
|
|
COLORREF
|
|
Graphics_BlendColors(COLORREF rgbTop, COLORREF rgbBottom, INT alpha)
|
|
{
|
|
if (alpha > 254) return rgbTop;
|
|
if (alpha < 0) return rgbBottom;
|
|
|
|
WORD k = (WORD)(((255 - alpha)*255 + 127)/255);
|
|
|
|
return RGB( (GetRValue(rgbTop)*alpha + k*GetRValue(rgbBottom) + 127)/255,
|
|
(GetGValue(rgbTop)*alpha + k*GetGValue(rgbBottom) + 127)/255,
|
|
(GetBValue(rgbTop)*alpha + k*GetBValue(rgbBottom) + 127)/255);
|
|
}
|
|
|
|
INT
|
|
Graphics_GetColorDistance(COLORREF rgb1, COLORREF rgb2)
|
|
{
|
|
return (1000 * ((GetRValue(rgb1) - GetRValue(rgb2)) +
|
|
(GetGValue(rgb1) - GetGValue(rgb2)) +
|
|
(GetBValue(rgb1) - GetBValue(rgb2))))/ (3 * 255);
|
|
}
|
|
|
|
void
|
|
Graphics_ClampRect(RECT *rect, const RECT *boxRect)
|
|
{
|
|
if (rect->left < boxRect->left)
|
|
rect->left = boxRect->left;
|
|
|
|
if (rect->top < boxRect->top)
|
|
rect->top = boxRect->top;
|
|
|
|
if (rect->right > boxRect->right)
|
|
rect->right = boxRect->right;
|
|
|
|
if (rect->bottom > boxRect->bottom)
|
|
rect->bottom = boxRect->bottom;
|
|
}
|
|
|
|
void
|
|
Graphics_NormalizeRect(RECT *rect)
|
|
{
|
|
if (rect->top > rect->bottom)
|
|
rect->bottom = rect->top;
|
|
|
|
if (rect->left > rect->right)
|
|
rect->right = rect->left;
|
|
}
|
|
|
|
void
|
|
Graphics_GetRectSizeNormalized(const RECT *rect, SIZE *size)
|
|
{
|
|
size->cx = rect->right - rect->left;
|
|
if (size->cx < 0)
|
|
size->cx = 0;
|
|
|
|
size->cy = rect->bottom - rect->top;
|
|
if (size->cy < 0)
|
|
size->cy = 0;
|
|
}
|
|
|
|
BOOL
|
|
Graphics_IsRectFit(const RECT *rect, const RECT *boxRect)
|
|
{
|
|
if (rect->left < boxRect->left ||
|
|
rect->top < boxRect->top ||
|
|
rect->right > boxRect->right ||
|
|
rect->bottom > boxRect->bottom)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL SetSizeEmpty(SIZE *size)
|
|
{
|
|
if (NULL == size)
|
|
return FALSE;
|
|
|
|
ZeroMemory(size, sizeof(SIZE));
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL IsSizeEmpty(SIZE *size)
|
|
{
|
|
return (NULL == size || 0 == size->cx || 0 == size->cy);
|
|
}
|
|
|
|
BOOL SetSize(SIZE *size, long width, long height)
|
|
{
|
|
if (NULL == size)
|
|
return FALSE;
|
|
|
|
size->cx = width;
|
|
size->cy = height;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SetPoint(POINT *pt, long x, long y)
|
|
{
|
|
if (NULL == pt)
|
|
return FALSE;
|
|
|
|
pt->x = x;
|
|
pt->y = y;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MakeRectPolygon(POINT vertices[4], long left, long top, long right, long bottom)
|
|
{
|
|
if (NULL == vertices)
|
|
return FALSE;
|
|
|
|
vertices[0].x = left;
|
|
vertices[0].y = top;
|
|
vertices[1].x = right;
|
|
vertices[1].y = top;
|
|
vertices[2].x = right;
|
|
vertices[2].y = bottom;
|
|
vertices[3].x = left;
|
|
vertices[3].y = bottom;
|
|
|
|
return TRUE;
|
|
}
|