//------------------------------------------------------------------------- // 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; } //---------------------------------------------------------------------------