|
|
//---------------------------------------------------------------------------
// TextDraw.cpp - implements the drawing API for text
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "Render.h"
#include "Utils.h"
#include "TextDraw.h"
#include "info.h"
#include "DrawHelp.h"
//---------------------------------------------------------------------------
HRESULT CTextDraw::PackProperties(CRenderObj *pRender, int iPartId, int iStateId) { memset(this, 0, sizeof(CTextDraw)); // allowed because we have no vtable
//---- save off partid, stateid for debugging ----
_iSourcePartId = iPartId; _iSourceStateId = iStateId;
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_TEXTCOLOR, &_crText))) _crText = 0; // default value
//---- shadow ----
if (SUCCEEDED(pRender->GetPosition(iPartId, iStateId, TMT_TEXTSHADOWOFFSET, &_ptShadowOffset))) { if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_TEXTSHADOWCOLOR, &_crShadow))) _crShadow = RGB(0, 0, 0); // default value = black
if (FAILED(pRender->GetEnumValue(iPartId, iStateId, TMT_TEXTSHADOWTYPE, (int *)&_eShadowType))) _eShadowType = TST_NONE; // default value
}
//---- border ----
if (FAILED(pRender->GetInt(iPartId, iStateId, TMT_TEXTBORDERSIZE, &_iBorderSize))) { _iBorderSize = 0; } else { if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_TEXTBORDERCOLOR, &_crBorder))) _crBorder = RGB(0, 0, 0); // default value
}
//---- font ----
if (SUCCEEDED(pRender->GetFont(NULL, iPartId, iStateId, TMT_FONT, FALSE, &_lfFont))) _fHaveFont = TRUE;
//---- edge colors ----
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_EDGELIGHTCOLOR, &_crEdgeLight))) _crEdgeLight = RGB(192, 192, 192);
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_EDGEHIGHLIGHTCOLOR, &_crEdgeHighlight))) _crEdgeHighlight = RGB(255, 255, 255);
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_EDGESHADOWCOLOR, &_crEdgeShadow))) _crEdgeShadow = RGB(128, 128, 128);
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_EDGEDKSHADOWCOLOR, &_crEdgeDkShadow))) _crEdgeDkShadow = RGB(0, 0, 0);
if (FAILED(pRender->GetColor(iPartId, iStateId, TMT_EDGEFILLCOLOR, &_crEdgeFill))) _crEdgeFill = _crEdgeLight;
return S_OK; } //---------------------------------------------------------------------------
BOOL CTextDraw::KeyProperty(int iPropId) { BOOL fKey = FALSE;
switch (iPropId) { case TMT_TEXTCOLOR: case TMT_TEXTSHADOWOFFSET: case TMT_TEXTSHADOWCOLOR: case TMT_TEXTSHADOWTYPE: case TMT_TEXTBORDERSIZE: case TMT_TEXTBORDERCOLOR: case TMT_FONT: case TMT_EDGELIGHTCOLOR: case TMT_EDGEHIGHLIGHTCOLOR: case TMT_EDGESHADOWCOLOR: case TMT_EDGEDKSHADOWCOLOR: case TMT_EDGEFILLCOLOR: fKey = TRUE; break; }
return fKey; } //---------------------------------------------------------------------------
void CTextDraw::DumpProperties(CSimpleFile *pFile, BYTE *pbThemeData, BOOL fFullInfo) { if (fFullInfo) pFile->OutLine(L"Dump of CTextDraw at offset=0x%x", (BYTE *)this - pbThemeData); else pFile->OutLine(L"Dump of CTextDraw"); pFile->OutLine(L" _crText=0x%08x", _crText);
pFile->OutLine(L" _ptShadowOffset=(%d, %d)", _ptShadowOffset.x, _ptShadowOffset.y);
pFile->OutLine(L" _crEdgeLight=0x%08x, _crEdgeHighlight=0x%08x, _crEdgeShadow=0x%08x", _crEdgeLight, _crEdgeHighlight, _crEdgeShadow);
pFile->OutLine(L" _crEdgeDkShadow=0x%08x, _crEdgeFill=0x%08x, _crShadow=0x%08x", _crEdgeDkShadow, _crEdgeFill, _crShadow);
pFile->OutLine(L" _eShadowType, _iBorderSize=%d, _crBorder=0x%08x", _eShadowType, _iBorderSize, _crBorder);
//---- dump resolution-independent font points ----
int iFontPoints = FontPointSize(_lfFont.lfHeight);
pFile->OutLine(L" _fHaveFont=%d, font: %s, size=%d points, bold=%d, italic=%d", _fHaveFont, _lfFont.lfFaceName, iFontPoints, _lfFont.lfWeight > 400, _lfFont.lfItalic); } //---------------------------------------------------------------------------
HRESULT CTextDraw::DrawText(CRenderObj *pRender, HDC hdc, int iPartId, int iStateId, LPCWSTR _pszText, DWORD dwCharCount, DWORD dwTextFlags, const RECT *pRect, const DTTOPTS *pOptions) { Log(LOG_TM, L"DrawText(): iPartId=%d, pszText=%s", iPartId, _pszText);
int iRetVal; HFONT hFont = NULL; COLORREF oldcolor = 0;
HRESULT hr = S_OK; BOOL fOldColor = FALSE; RESOURCE HFONT oldfont = NULL;
LPWSTR pszText = (LPWSTR)_pszText; // so DrawText() calls are happy
dwTextFlags &= ~(DT_MODIFYSTRING); // we don't want to change the constant ptr
int oldmode = SetBkMode(hdc, TRANSPARENT); RECT rect;
COLORREF crText = _crText; COLORREF crBorder = _crBorder; COLORREF crShadow = _crShadow;
TEXTSHADOWTYPE eShadowType = _eShadowType; POINT ptShadowOffset = _ptShadowOffset; int iBorderSize = _iBorderSize;
if (pOptions) { DWORD dwFlags = pOptions->dwFlags;
if (dwFlags & DTT_TEXTCOLOR) crText = pOptions->crText;
if (dwFlags & DTT_BORDERCOLOR) crBorder = pOptions->crBorder;
if (dwFlags & DTT_SHADOWCOLOR) crShadow = pOptions->crShadow;
if (dwFlags & DTT_SHADOWTYPE) eShadowType = (TEXTSHADOWTYPE)pOptions->eTextShadowType;
if (dwFlags & DTT_SHADOWOFFSET) ptShadowOffset = pOptions->ptShadowOffset;
if (dwFlags & DTT_BORDERSIZE) iBorderSize = pOptions->iBorderSize; }
BOOL fShadow = (eShadowType != TST_NONE);
if (_fHaveFont) { hr = pRender->GetScaledFontHandle(hdc, &_lfFont, &hFont); if (FAILED(hr)) goto exit;
oldfont = (HFONT)SelectObject(hdc, hFont); }
//---- BLURRED shadow approach ----
if ((fShadow) && (eShadowType == TST_CONTINUOUS)) { SetRect(&rect, pRect->left, pRect->top, pRect->right, pRect->bottom);
hr = EnsureUxCtrlLoaded(); if (FAILED(hr)) goto exit;
//---- this will draw shadow & text (no outline support yet) ----
iRetVal = CCDrawShadowText(hdc, pszText, dwCharCount, &rect, dwTextFlags, crText, crShadow, ptShadowOffset.x, ptShadowOffset.y); } else //---- normal approach ----
{ //---- draw SINGLE shadow first ----
if (fShadow) { oldcolor = SetTextColor(hdc, crShadow); fOldColor = TRUE;
//---- adjust rect for drawing shadow ----
rect.left = pRect->left + ptShadowOffset.x; rect.top = pRect->top + ptShadowOffset.y; rect.right = pRect->right + ptShadowOffset.x; rect.bottom = pRect->bottom, ptShadowOffset.y;
iRetVal = DrawTextEx(hdc, pszText, dwCharCount, &rect, dwTextFlags, NULL); if (! iRetVal) { hr = MakeErrorLast(); goto exit; } } SetRect(&rect, pRect->left, pRect->top, pRect->right, pRect->bottom);
//---- draw outline, if wanted ----
if (iBorderSize) // draw outline around text
{ iRetVal = BeginPath(hdc); if (! iRetVal) { hr = MakeErrorLast(); goto exit; }
iRetVal = DrawTextEx(hdc, pszText, dwCharCount, &rect, dwTextFlags, NULL); if (! iRetVal) { AbortPath(hdc); hr = MakeErrorLast(); goto exit; }
EndPath(hdc);
HPEN pen, oldpen; HBRUSH brush, oldbrush;
pen = CreatePen(PS_SOLID, iBorderSize, crBorder); brush = CreateSolidBrush(crText); if ((pen) && (brush)) { oldpen = (HPEN)SelectObject(hdc, pen); oldbrush = (HBRUSH)SelectObject(hdc, brush);
//---- this draws both outline & normal text ---
StrokeAndFillPath(hdc);
SelectObject(hdc, oldpen); SelectObject(hdc, oldbrush); } } else // draw normal text
{ if (fOldColor) SetTextColor(hdc, crText); else { oldcolor = SetTextColor(hdc, crText); fOldColor = TRUE; }
iRetVal = DrawTextEx(hdc, pszText, dwCharCount, &rect, dwTextFlags, NULL); if (! iRetVal) { hr = MakeErrorLast(); goto exit; } } }
hr = S_OK;
exit: //---- restore hdc objects ----
SetBkMode(hdc, oldmode);
if (fOldColor) SetTextColor(hdc, oldcolor);
if (oldfont) SelectObject(hdc, oldfont);
if (hFont) pRender->ReturnFontHandle(hFont);
return hr; } //---------------------------------------------------------------------------
HRESULT CTextDraw::GetTextExtent(CRenderObj *pRender, HDC hdc, int iPartId, int iStateId, LPCWSTR _pszText, int iCharCount, DWORD dwTextFlags, const RECT *pBoundingRect, RECT *pExtentRect) { LPWSTR pszText = (LPWSTR)_pszText; // so DrawText() calls are happy
dwTextFlags &= ~(DT_MODIFYSTRING); // we don't want to change the constant ptr
Log(LOG_TM, L"GetTextExtent(): iPartId=%d, pszText=%s", iPartId, pszText);
RESOURCE HFONT oldfont = NULL; HFONT hFont = NULL; HRESULT hr = S_OK;
if (_fHaveFont) { hr = pRender->GetScaledFontHandle(hdc, &_lfFont, &hFont); if (FAILED(hr)) goto exit;
oldfont = (HFONT)SelectObject(hdc, hFont); }
RECT rect; int iRetVal;
if (pBoundingRect) rect = *pBoundingRect; else SetRect(&rect, 0, 0, 0, 0);
iRetVal = DrawTextEx(hdc, pszText, iCharCount, &rect, dwTextFlags | DT_CALCRECT, NULL); if (! iRetVal) { hr = MakeErrorLast(); goto exit; }
//----do NOT adjust for text shadow (ok if shadows overlap...) ----
*pExtentRect = rect;
exit: //---- restore hdc objects ----
if (oldfont) SelectObject(hdc, oldfont);
Log(LOG_TM, L"END Of GetTextExtent()");
if (hFont) pRender->ReturnFontHandle(hFont);
return hr; } //---------------------------------------------------------------------------
HRESULT CTextDraw::GetTextMetrics(CRenderObj *pRender, HDC hdc, int iPartId, int iStateId, TEXTMETRIC* ptm) { Log(LOG_TM, L"GetTextMetrics(): iPartId=%d, ", iPartId);
HRESULT hr = S_OK; RESOURCE HFONT hFont = NULL; RESOURCE HFONT oldfont = NULL;
if (! ptm) { hr = MakeError32(E_INVALIDARG); goto exit; }
if (_fHaveFont) { hr = pRender->GetScaledFontHandle(hdc, &_lfFont, &hFont); if (FAILED(hr)) goto exit;
oldfont = (HFONT)SelectObject(hdc, hFont); }
if (! ::GetTextMetrics(hdc, ptm)) { hr = MakeErrorLast(); goto exit; }
exit: //---- restore hdc objects ----
if (oldfont) SelectObject(hdc, oldfont);
if (hFont) pRender->ReturnFontHandle(hFont);
Log(LOG_TM, L"END Of GetTextMetrics()"); return hr; } //---------------------------------------------------------------------------
HRESULT CTextDraw::DrawEdge(CRenderObj *pRender, HDC hdc, int iPartId, int iStateId, const RECT *pDestRect, UINT uEdge, UINT uFlags, OUT RECT *pContentRect) { Log(LOG_TM, L"DrawEdge(): iPartId=%d, iStateId=%d, uEdge=0x%08x, uFlags=0x%08x", iPartId, iStateId, uEdge, uFlags); HRESULT hr = _DrawEdge(hdc, pDestRect, uEdge, uFlags, _crEdgeLight, _crEdgeHighlight, _crEdgeShadow, _crEdgeDkShadow, _crEdgeFill, pContentRect); Log(LOG_TM, L"END Of DrawEdge()"); return hr; } //---------------------------------------------------------------------------
|