408 lines
12 KiB
C++
408 lines
12 KiB
C++
|
//-------------------------------------------------------------------------
|
||
|
// NtlEng.cpp - support for Native Theme Language runtime graphics engine
|
||
|
//-------------------------------------------------------------------------
|
||
|
#include "stdafx.h"
|
||
|
#include "ntleng.h"
|
||
|
//---------------------------------------------------------------------------
|
||
|
#define COLORNULL 0xff000000
|
||
|
//---------------------------------------------------------------------------
|
||
|
POINT TranslateLogPoint(POINT &pt, RECT &rcLogRect, RECT &rcCaller)
|
||
|
{
|
||
|
POINT ptNew;
|
||
|
|
||
|
ptNew.x = rcCaller.left + (WIDTH(rcCaller) * (pt.x - rcLogRect.left))/WIDTH(rcLogRect);
|
||
|
ptNew.y = rcCaller.top + (HEIGHT(rcCaller) * (pt.y - rcLogRect.top))/HEIGHT(rcLogRect);
|
||
|
|
||
|
return ptNew;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
int TranslateLogSize(int iSize, RECT &rcLogRect, RECT &rcCaller)
|
||
|
{
|
||
|
//---- "iSize" is somewhere between width & height ----
|
||
|
int iWidthSize = (WIDTH(rcCaller) * iSize)/WIDTH(rcLogRect);
|
||
|
int iHeightSize = (HEIGHT(rcCaller) * iSize)/HEIGHT(rcLogRect);
|
||
|
|
||
|
return min(iWidthSize, iHeightSize);
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
COLORREF GetParamColor(MIXEDPTRS &u)
|
||
|
{
|
||
|
COLORREF crVal = 0;
|
||
|
|
||
|
if (*u.pb == PT_COLORREF)
|
||
|
crVal = *u.pi++;
|
||
|
else if (*u.pb == PT_SYSCOLORINDEX)
|
||
|
crVal = GetSysColor(*u.ps++);
|
||
|
else if (*u.pb == PT_COLORNULL)
|
||
|
crVal = COLORNULL;
|
||
|
else
|
||
|
{
|
||
|
Log(LOG_ERROR, L"Bad color param value in NTL stream: 0x%0x", *u.pb);
|
||
|
}
|
||
|
|
||
|
return crVal;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
int GetParamInt(MIXEDPTRS &u)
|
||
|
{
|
||
|
int iVal;
|
||
|
|
||
|
if (*u.pb == PT_INT)
|
||
|
iVal = *u.pi++;
|
||
|
else
|
||
|
iVal = ClassicGetSystemMetrics(*u.ps++);
|
||
|
|
||
|
return iVal;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
POINT GetParamPoint(MIXEDPTRS &u, RECT &rcCaller, RECT &rcLogRect)
|
||
|
{
|
||
|
POINT pt = *u.ppt++;
|
||
|
pt = TranslateLogPoint(pt, rcCaller, rcLogRect);
|
||
|
|
||
|
return pt;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
void SetPen(HDC hdc, HPEN &hPen, COLORREF crLine, int iLineWidth)
|
||
|
{
|
||
|
DeleteObject(hPen);
|
||
|
|
||
|
if (crLine == COLORNULL)
|
||
|
hPen = (HPEN)GetStockObject(NULL_PEN);
|
||
|
else
|
||
|
hPen = CreatePen(PS_SOLID, iLineWidth, crLine);
|
||
|
|
||
|
SelectObject(hdc, hPen);
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
HRESULT GetImageBrush(HDC hdc, int iPartId, int iStateId, int iIndex,
|
||
|
INtlEngCallBack *pCallBack, HBRUSH *phbr)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (! pCallBack)
|
||
|
{
|
||
|
Log(LOG_ERROR, L"No callback for NtlRun specified");
|
||
|
hr = MakeError32(ERROR_INTERNAL_ERROR);
|
||
|
}
|
||
|
else
|
||
|
hr = pCallBack->CreateImageBrush(hdc, iPartId, iStateId, iIndex, phbr);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
HRESULT GetFillBrush(HDC hdc, MIXEDPTRS &u, int iPartId, int iStateId,
|
||
|
INtlEngCallBack *pCallBack, HBRUSH *phbr)
|
||
|
{
|
||
|
HBRUSH hbr = NULL;
|
||
|
BYTE bIndex;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
switch (*u.pb)
|
||
|
{
|
||
|
case PT_IMAGEFILE:
|
||
|
bIndex = *u.pb++;
|
||
|
hr = GetImageBrush(hdc, iPartId, iStateId, bIndex, pCallBack, &hbr);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
COLORREF crVal = GetParamColor(u);
|
||
|
if (crVal == COLORNULL)
|
||
|
hbr = (HBRUSH)GetStockObject(NULL_BRUSH);
|
||
|
else
|
||
|
hbr = CreateSolidBrush(crVal);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
*phbr = hbr;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
void DrawRect(HDC hdc, MIXEDPTRS &u, RECT &rcCaller)
|
||
|
{
|
||
|
int iVals[4];
|
||
|
COLORREF crVals[4];
|
||
|
|
||
|
//---- get int params ----
|
||
|
for (int i=0; i < 4; i++)
|
||
|
{
|
||
|
if ((*u.pb != PT_INT) && (*u.pb != PT_SYSMETRICINDEX))
|
||
|
break;
|
||
|
iVals[i] = GetParamInt(u);
|
||
|
}
|
||
|
|
||
|
int cInts = i;
|
||
|
|
||
|
//---- get color param s----
|
||
|
for (i=0; i < 4; i++)
|
||
|
{
|
||
|
if ((*u.pb != PT_COLORREF) && (*u.pb != PT_COLORNULL)
|
||
|
&& (*u.pb != PT_SYSCOLORINDEX))
|
||
|
break;
|
||
|
crVals[i] = GetParamColor(u);
|
||
|
}
|
||
|
|
||
|
int cColors = i;
|
||
|
|
||
|
if ((cInts == 1) && (cColors == 1)) // single size/color for all 4 sides
|
||
|
{
|
||
|
if (crVals[0] != COLORNULL)
|
||
|
{
|
||
|
HPEN hpen = CreatePen(PS_SOLID | PS_INSIDEFRAME, iVals[0], crVals[0]);
|
||
|
HPEN hpenOld = (HPEN)SelectObject(hdc, hpen);
|
||
|
|
||
|
HBRUSH hbrOld = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
|
||
|
|
||
|
Rectangle(hdc, rcCaller.left, rcCaller.top, rcCaller.right, rcCaller.bottom);
|
||
|
|
||
|
SelectObject(hdc, hpenOld);
|
||
|
SelectObject(hdc, hbrOld);
|
||
|
|
||
|
DeleteObject(hpen);
|
||
|
}
|
||
|
|
||
|
InflateRect(&rcCaller, -iVals[0], -iVals[0]);
|
||
|
}
|
||
|
else // need to draw each side one at a time
|
||
|
{
|
||
|
//---- expand int's into 4 values ----
|
||
|
if (cInts == 1)
|
||
|
{
|
||
|
iVals[1] = iVals[2] = iVals[3] = iVals[0];
|
||
|
}
|
||
|
else if (cInts == 2)
|
||
|
{
|
||
|
iVals[2] = iVals[0];
|
||
|
iVals[3] = iVals[1];
|
||
|
}
|
||
|
|
||
|
//---- expand colors's into 4 values ----
|
||
|
if (cColors == 1)
|
||
|
{
|
||
|
crVals[1] = crVals[2] = crVals[3] = crVals[0];
|
||
|
}
|
||
|
else if (cColors == 2)
|
||
|
{
|
||
|
crVals[2] = crVals[0];
|
||
|
crVals[3] = crVals[1];
|
||
|
}
|
||
|
|
||
|
HBRUSH hbrOld = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
|
||
|
HBRUSH hbr = NULL;
|
||
|
|
||
|
//---- left ----
|
||
|
if ((crVals[0] != COLORNULL) && (iVals[0]))
|
||
|
{
|
||
|
hbr = CreateSolidBrush(crVals[0]);
|
||
|
SelectObject(hdc, hbr);
|
||
|
|
||
|
PatBlt(hdc, rcCaller.left, rcCaller.top, iVals[0], HEIGHT(rcCaller), PATCOPY);
|
||
|
}
|
||
|
rcCaller.left += iVals[0];
|
||
|
|
||
|
//---- top ----
|
||
|
if ((crVals[1] != COLORNULL) && (iVals[1]))
|
||
|
{
|
||
|
if (crVals[1] != crVals[0]) // need new brush
|
||
|
{
|
||
|
hbr = CreateSolidBrush(crVals[1]);
|
||
|
SelectObject(hdc, hbr);
|
||
|
}
|
||
|
|
||
|
PatBlt(hdc, rcCaller.left, rcCaller.top, WIDTH(rcCaller), iVals[0], PATCOPY);
|
||
|
}
|
||
|
rcCaller.top += iVals[1];
|
||
|
|
||
|
//---- right ----
|
||
|
if ((crVals[2] != COLORNULL) && (iVals[2]))
|
||
|
{
|
||
|
if (crVals[2] != crVals[1]) // need new brush
|
||
|
{
|
||
|
hbr = CreateSolidBrush(crVals[2]);
|
||
|
SelectObject(hdc, hbr);
|
||
|
}
|
||
|
|
||
|
PatBlt(hdc, rcCaller.right - iVals[0], rcCaller.top, iVals[0], HEIGHT(rcCaller), PATCOPY);
|
||
|
}
|
||
|
rcCaller.right -= iVals[2];
|
||
|
|
||
|
//---- bottom ----
|
||
|
if ((crVals[3] != COLORNULL) && (iVals[3]))
|
||
|
{
|
||
|
if (crVals[3] != crVals[2]) // need new brush
|
||
|
{
|
||
|
hbr = CreateSolidBrush(crVals[3]);
|
||
|
SelectObject(hdc, hbr);
|
||
|
}
|
||
|
|
||
|
PatBlt(hdc, rcCaller.left, rcCaller.bottom - iVals[0], WIDTH(rcCaller), iVals[0], PATCOPY);
|
||
|
}
|
||
|
rcCaller.bottom -= iVals[3];
|
||
|
|
||
|
SelectObject(hdc, hbrOld);
|
||
|
DeleteObject(hbr);
|
||
|
}
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
HRESULT RunNtl(HDC hdc, RECT &rcCaller, HBRUSH hbrBkDefault, DWORD dwOptions,
|
||
|
int iPartId, int iStateId, BYTE *pbCode, int iCodeLen, INtlEngCallBack *pCallBack)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
MIXEDPTRS u;
|
||
|
u.pb = pbCode;
|
||
|
RECT rcLogRect = {0, 0, 1000, 1000};
|
||
|
|
||
|
RESOURCE HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);
|
||
|
RESOURCE HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
|
||
|
BOOL fDeleteBrush = FALSE;
|
||
|
|
||
|
if (hbrBkDefault)
|
||
|
hBrush = hbrBkDefault;
|
||
|
|
||
|
RESOURCE HBRUSH hbrOld = (HBRUSH)SelectObject(hdc, hBrush);
|
||
|
RESOURCE HPEN hpenOld = (HPEN)SelectObject(hdc, hPen);
|
||
|
|
||
|
while (*u.pb != NTL_RETURN)
|
||
|
{
|
||
|
switch (*u.pb)
|
||
|
{
|
||
|
case NTL_STATEJUMPTABLE:
|
||
|
{
|
||
|
BYTE bStateCount = *u.pb++;
|
||
|
if ((iStateId < 1) || (iStateId > bStateCount))
|
||
|
iStateId = 1;
|
||
|
u.pb = pbCode + u.pi[iStateId-1];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_JMPON:
|
||
|
{
|
||
|
BYTE bBitNum = *u.pb++;
|
||
|
int iOffset = *u.pi++;
|
||
|
if (dwOptions & (1 << bBitNum))
|
||
|
u.pb = pbCode + iOffset;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_JMPOFF:
|
||
|
{
|
||
|
BYTE bBitNum = *u.pb++;
|
||
|
int iOffset = *u.pi++;
|
||
|
if (! (dwOptions & (1 << bBitNum)))
|
||
|
u.pb = pbCode + iOffset;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_JMP:
|
||
|
{
|
||
|
int iOffset = *u.pi++;
|
||
|
u.pb = pbCode + iOffset;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_LOGRECT:
|
||
|
rcLogRect = *u.prc++;
|
||
|
break;
|
||
|
|
||
|
case NTL_LINEBRUSH:
|
||
|
{
|
||
|
COLORREF crLine = GetParamColor(u);
|
||
|
int iLineWidth = GetParamInt(u);
|
||
|
BOOL fLogWidth = *u.pb++;
|
||
|
if (fLogWidth)
|
||
|
iLineWidth = TranslateLogSize(iLineWidth, rcCaller, rcLogRect);
|
||
|
SetPen(hdc, hPen, crLine, iLineWidth);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_FILLBRUSH:
|
||
|
{
|
||
|
HBRUSH hbr;
|
||
|
|
||
|
hr = GetFillBrush(hdc, u, iPartId, iStateId, pCallBack, &hbr);
|
||
|
if (FAILED(hr))
|
||
|
goto exit;
|
||
|
|
||
|
SelectObject(hdc, hbr);
|
||
|
if (fDeleteBrush)
|
||
|
DeleteObject(hBrush);
|
||
|
hBrush = hbr;
|
||
|
fDeleteBrush = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_MOVETO:
|
||
|
{
|
||
|
POINT pt = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
MoveToEx(hdc, pt.x, pt.y, NULL);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_LINETO:
|
||
|
{
|
||
|
POINT pt = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
LineTo(hdc, pt.x, pt.y);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_CURVETO:
|
||
|
{
|
||
|
POINT pts[3];
|
||
|
pts[0] = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
pts[1] = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
pts[2] = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
PolyBezierTo(hdc, pts, 3);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_SHAPE:
|
||
|
{
|
||
|
POINT pt = GetParamPoint(u, rcCaller, rcLogRect);
|
||
|
BeginPath(hdc);
|
||
|
MoveToEx(hdc, pt.x, pt.y, NULL);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_ENDSHAPE:
|
||
|
{
|
||
|
EndPath(hdc);
|
||
|
StrokeAndFillPath(hdc);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_DRAWRECT:
|
||
|
{
|
||
|
DrawRect(hdc, u, rcCaller);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NTL_FILLRECT:
|
||
|
{
|
||
|
HBRUSH hbr;
|
||
|
|
||
|
hr = GetFillBrush(hdc, u, iPartId, iStateId, pCallBack, &hbr);
|
||
|
if (FAILED(hr))
|
||
|
goto exit;
|
||
|
|
||
|
FillRect(hdc, &rcCaller, hbr);
|
||
|
DeleteObject(hbr);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
SelectObject(hdc, hbrOld);
|
||
|
SelectObject(hdc, hpenOld);
|
||
|
|
||
|
DeleteObject(hPen);
|
||
|
|
||
|
if (fDeleteBrush)
|
||
|
DeleteObject(hBrush);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|