📄 render.cpp
字号:
const CCharFormat *pcf) //@parm Character format for colors
{
if (NULL == pcf)
{
Assert(pcf);
return;
}
COLORREF cr;
// Select font in _hdc
AssertSz(_pccs->_hfont, "CRenderer::SetFontAndColor hfont is NULL");
_fFEFontOnNonFEWin95 = FALSE;
if(IsFECharset (pcf->bCharSet) && VER_PLATFORM_WIN32_WINDOWS == dwPlatformId
&& !OnWin95FE())
_fFEFontOnNonFEWin95 = TRUE;
if (GetCurrentObject( _hdc, OBJ_FONT ) != _pccs->_hfont)
{
SelectObject(_hdc, _pccs->_hfont);
}
// Compute height and descent if not yet done
if(_yHeight == -1)
{
// Note: this assumes plain text
// Should be used only for single line control
_yHeight = _pccs->_yHeight;
_yDescent = _pccs->_yDescent;
}
// Is there a rev author?
if (0 == pcf->bRevAuthor)
{
// No - use the color field
cr = (pcf->dwEffects & CFE_AUTOCOLOR)
? _crTextColor : pcf->crTextColor;
if(cr == RGB(255,255,255))
{
const INT nTechnology = GetDeviceCaps(_hdc, TECHNOLOGY);
if(nTechnology == DT_RASPRINTER || nTechnology == DT_PLOTTER)
{
cr = RGB(0,0,0);
}
}
}
else
{
// Limit color of rev authors to 0 through 7.
cr = rgcrRevisions[(pcf->bRevAuthor - 1) & REVMASK];
}
// Save the current text color as others may need it.
_crCurTextColor = cr;
SetTextColor(_hdc, cr);
if (pcf->dwEffects & CFE_AUTOBACKCOLOR)
{
// The window should have the default behavior with respect to
// background color which is that the window is transparent
// if so requested and the background color is set to the
// host's background color.
if (GetPed()->_fTransparent)
{
SetBkMode(_hdc, TRANSPARENT);
}
cr = _crBackground;
}
else
{
// Need to set the background color
if (GetPed()->_fTransparent)
{
// The background is transparent. If we want background
// colors to show up, this better be opaque.
SetBkMode(_hdc, OPAQUE);
}
cr = pcf->crBackColor;
}
if (cr != _crCurBackground)
{
// Tell the window the background color
SetBkColor(_hdc, cr);
// Remember the current background color
_crCurBackground = cr;
// Change render settings so we won't start filling with background
// colors.
_fBackgroundColor = TRUE;
}
}
/*
* CRenderer::RenderStartLine()
*
* @mfunc
* Render possible outline symbol and bullet if at start of line
*
* @rdesc
* TRUE if this method succeeded
*/
BOOL CRenderer::RenderStartLine()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::RenderStartLine");
if(IsRich() && (_bFlags & fliFirstInPara))
{
if(IsInOutlineView())
RenderOutlineSymbol();
if(_pPF->wNumbering)
RenderBullet();
}
// Assume that there is no special background color for the line
_fBackgroundColor = FALSE;
// Handle setting background color. If the current background
// color is different than the default, we need to set the background
// to this because the end of line processing reset the color so
// that opaquing would work.
if (_crBackground != _crCurBackground)
{
// Tell the window the background color
SetBkColor(_hdc, _crCurBackground);
_fBackgroundColor = TRUE;
}
return TRUE;
}
/*
* CRenderer::RenderOutlineSymbol()
*
* @mfunc
* Render outline symbol for current paragraph
*
* @rdesc
* TRUE if outline symbol rendered
*/
BOOL CRenderer::RenderOutlineSymbol()
{
AssertSz(IsInOutlineView(),
"CRenderer::RenderOutlineSymbol called when not in outline view");
HBITMAP hbitmap;
LONG height;
LONG width;
LONG x = _ptCur.x - _xLeft + LXtoDX(lDefaultTab/2 * _pPF->bOutlineLevel);
LONG y = _ptCur.y;
RECT rc = {0, y, _ptCur.x, y + _yHeight};
COLORREF PreColBack = SetBkColor(_hdc, _crBackground);
EraseTextOut(_hdc, &rc); // Erase up to text
HDC hMemDC = CreateCompatibleDC(_hdc); // REVIEW: performance
if (!hMemDC)
return FALSE; //REVIEW: out of memory
if(!g_hbitmapSubtext && InitializeOutlineBitmaps() != NOERROR)
return FALSE;
if(_pPF->bOutlineLevel & 1) // Subtext
{
width = BITMAP_WIDTH_SUBTEXT;
height = BITMAP_HEIGHT_SUBTEXT;
hbitmap = g_hbitmapSubtext;
}
else // Heading
{
// GuyBark 34205: Added the small bitmap handling.
BOOL bZoomDown = (_pdp->GetZoomNumerator() < _pdp->GetZoomDenominator());
width = BITMAP_WIDTH_HEADING;
height = BITMAP_HEIGHT_HEADING;
hbitmap = (bZoomDown ? g_hbitmapEmptySmallHeading : g_hbitmapEmptyHeading);
CPFRunPtr rp(*this); // Check next PF for other
LONG cch = _cch; // outline symbols
if(_cch < rp.GetCchLeft()) // Set cch = count to heading
{ // EOP
CTxtPtr tp(_rpTX);
cch = tp.FindEOP(tomForward);
}
rp.AdvanceCp(cch); // Go to next paragraph
if(rp.IsCollapsed())
hbitmap = (bZoomDown ? g_hbitmapCollapsedSmallHeading : g_hbitmapCollapsedHeading);
else if(_pPF->bOutlineLevel < rp.GetOutlineLevel())
hbitmap = (bZoomDown ? g_hbitmapExpandedSmallHeading : g_hbitmapExpandedHeading);
}
if(!hbitmap)
return FALSE;
HBITMAP hbitmapDefault = (HBITMAP)SelectObject(hMemDC, hbitmap);
// REVIEW: what if the background color changes? Also, use a TT font
// for symbols
LONG h = _pdp->Zoom(height);
LONG dy = _yHeight - _yDescent - h;
if(dy > 0)
dy /= 2;
else
dy = -dy;
#ifdef PWD_JUPITER
// GuyBark: Stretch the outline symbols in the same way we stretch pictures
// before blitting them. This looks good on the screen AND when printing now.
// The sysparam values are the typical 96 per inch values. If we're printing
// now, then the _pdp values are whatever is appropriate to the printer
int xDst = MulDiv(_pdp->Zoom(width), _pdp->GetXPerInch(), sysparam.GetXPerInchScreenDC());
int yDst = MulDiv(h, _pdp->GetYPerInch(), sysparam.GetYPerInchScreenDC());
// GuyBark Jupiter 38461:
// Always draw the outline symbols in the automatic text color. Word 97 actually
// seems to be doing something else to determine the text color, but there's no
// need for us to do that.
COLORREF crColPrevious = SetTextColor(_hdc, GetPed()->TxGetForeColor());
StretchBlt(_hdc, x, y + dy, xDst, yDst,
hMemDC, 0, 0, width, height, SRCCOPY);
// Restore the previous color as this may have been set for the text following
// the outline symbol.
SetTextColor(_hdc, crColPrevious);
#else
StretchBlt(_hdc, x, y + dy, _pdp->Zoom(width), h,
hMemDC, 0, 0, width, height, SRCCOPY);
#endif // PWD_JUPITER
SetBkColor(_hdc, PreColBack);
SelectObject(hMemDC, hbitmapDefault);
DeleteDC(hMemDC);
_fFirstChunk = FALSE;
return TRUE;
}
/*
* CRenderer::RenderBullet()
*
* @mfunc
* Render bullet at start of line
*
* @rdesc
* TRUE if this method succeeded
*/
BOOL CRenderer::RenderBullet()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::RenderBullet");
AssertSz(_pPF->wNumbering,
"CRenderer::RenderBullet called for non-bullet");
// Width of the bullet character
LONG xWidth;
// FUTURE: Unicode bullet is L'\x2022' We want to migrate to this and
// other bullets
LONG cch;
CCharFormat cf;
WCHAR szBullet[CCHMAXNUMTOSTR];
CCcs *pccs = GetCcsBullet(&cf);
if(pccs == (CCcs *)(-1)) // Bullet is suppressed because
return TRUE; // preceding EOP is VT
// If we could not get a new CCss...
if(pccs)
{
if(_pccs)
_pccs->Release();
_pccs = pccs;
}
// Default to no underline
_bUnderlineType = CFU_UNDERLINENONE;
// Bullets don't get underlined Bug #15336
// if (cf.dwEffects & CFE_UNDERLINE)
// _bUnderlineType = cf.bUnderlineType;
SetFontAndColor(&cf);
BYTE bFlagSave = _bFlags;
LONG dxOffset = LXtoDX(max(_pPF->dxOffset, _pPF->wNumberingTab));
LONG xSave = _ptCur.x;
LONG xWidthLineSave = _xWidthLine;
_bFlags = 0;
// Set-up to render bullet in one chunk
Assert((_pPF->wEffects & PFE_RTLPARA) || IsInOutlineView() || _fFirstChunk);
cch = GetBullet(szBullet, _pccs, &xWidth);
dxOffset = max(dxOffset, xWidth);
_xWidthLine = dxOffset;
if(IsInOutlineView())
dxOffset = _xLeft - LXtoDX(lDefaultTab/2 * (_pPF->bOutlineLevel + 1));
_ptCur.x -= dxOffset;
// Treat bullet plus offset as one character
_xWidth = 0;
// Render bullet
_fLastChunk = TRUE;
TextOut(szBullet, cch);
// Restore render vars to continue with remainder of line.
_ptCur.x = xSave;
_xWidthLine = xWidthLineSave;
_bFlags = bFlagSave;
_xWidth = 0;
// This releases the _pccs that we put in for the bullet
SetNewFont();
return TRUE;
}
/*
* CRenderer::RenderUnderline(xStart, xWidth)
*
* @mfunc
* Render underline
*/
void CRenderer::RenderUnderline(
LONG xStart,
LONG xWidth) //@parm Width to underline
{
RECT rcT;
if (_bUnderlineType != CFU_INVERT &&
!IN_RANGE(CFU_UNDERLINEDOTTED, _bUnderlineType, CFU_UNDERLINEDASHDOTDOT))
{
// Regular single underline case
// Calculate where to put the underline
rcT.top = _ptCur.y + _yHeight - _yDescent + _pccs->_dyULOffset
- _pccs->_yOffset;
// There are some cases were this can occur - particularly with
// bullets on Japanese systems.
if (rcT.top >= _ptCur.y + _yHeight)
{
rcT.top = _ptCur.y + _yHeight - _pccs->_dyULWidth;
}
rcT.bottom = rcT.top + _pccs->_dyULWidth;
rcT.left = xStart;
rcT.right = rcT.left + xWidth;
FillRectWithTextColor(&rcT);
return;
}
// The top/left of the text to be underlined begins at the _ptCur
LONG top = _ptCur.y;
LONG left = xStart;
LONG bottom = top + _yHeight - _yDescent + _pccs->_yDescent - 1;
LONG right = left + xWidth;
if (_bUnderlineType == CFU_INVERT) // Fake selection.
{ // NOTE, not really
rcT.top = top; // how we should invert text!!
rcT.left = left; // check out IME invert.
rcT.bottom = bottom + 1;
rcT.right = right;
InvertRect(_hdc, &rcT);
return;
}
if(IN_RANGE(CFU_UNDERLINEDOTTED, _bUnderlineType, CFU_UNDERLINEDASHDOTDOT))
{
static char pen[] = {PS_DOT, PS_DASH, PS_DASHDOT, PS_DASHDOTDOT};
HPEN hPen = CreatePen(pen[_bUnderlineType - CFU_UNDERLINEDOTTED],
1, _crCurTextColor);
if(hPen)
{
HPEN hPenOld = SelectPen(_hdc, hPen);
top = _ptCur.y + _yHeight - _yDescent + _pccs->_dyULOffset;
// don't want the top go below the bottom
top = min(top, bottom);
#ifndef UNDER_CE
MoveToEx(_hdc, left, top, NULL);
LineTo(_hdc, right, top);
#else
{
POINT rgPts[2];
rgPts[0].x = left;
rgPts[0].y = top;
rgPts[1].x = right;
rgPts[1].y = top;
Polyline(_hdc, rgPts, 2);
}
#endif
if(hPenOld) // Restore original pen.
SelectPen(_hdc, hPenOld);
DeleteObject(hPen);
}
}
}
/*
* CRenderer::RenderStrikeOut(xStart, xWidth)
*
* @mfunc
* Render underline
*/
void CRenderer::RenderStrikeOut(
LONG xStart,
LONG xWidth) //@parm with to strikeout.
{
RECT rcT;
// Calculate where to put the strikeout rectangle.
rcT.top = _ptCur.y + _yHeight - _yDescent + _pccs->_dySOOffset
- _pccs->_yOffset;
rcT.bottom = rcT.top + _pccs->_dyULWidth;
rcT.left = xStart;
rcT.right = rcT.left + xWidth;
FillRectWithTextColor(&rcT);
}
/*
* CRenderer::FillRectWithTextColor(prc)
*
* @mfunc
* Fill input rectangle with current color of text
*/
void CRenderer::FillRectWithTextColor(
RECT *prc) //@parm rectangle to fill with text color
{
// Create a brush with the text color
COLORREF color = _fDisabled ? _crForeDisabled : _crCurTextColor;
HBRUSH hbrush = CreateSolidBrush(color);
HBRUSH hbrushOld;
// Note if the CreateSolidBrush fails we just ignore it since there
// isn't anything we can do about it anyway.
if (hbrush)
{
// Save the old brush
hbrushOld = (HBRUSH) SelectObject(_hdc, hbrush);
// Fill the rectangle for the underline
PatBlt(_hdc, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, PATCOPY);
// Put the old brush back
SelectObject(_hdc, hbrushOld);
// Free brush we created.
DeleteObject(hbrush);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -