📄 render.cpp
字号:
LineTo (_hdc, xRight, yBot - 1);
}
h = 0;
for(LONG i = 0; i <= _pPF->cTabCount; i++)
{
MoveToEx(_hdc, x + h, yTop, NULL);
LineTo (_hdc, x + h, yBot);
h = LXtoDX(GetTabPos(_pPF->rgxTabs[i])) - dx;
}
if(pen)
SelectPen(_hdc, pen);
}
}
if (hdcSave)
{
RenderOffScreenBitmap(_osdc, hdcSave, xAdj, yAdj, yRcIgnored);
}
// Handle setting background color. We need to do this for each line
// because we return the background color to the default after each
// line so that opaquing will work correctly.
if (_crBackground != _crCurBackground)
{
// Tell the window the background color
SetBkColor(_hdc, _crBackground);
}
Advance(cch);
// erase to right of render rect if necessary
LONG xExtent = _fClipRightToView
? min(_rcView.right, _rcRender.right)
: _rcRender.right;
if(_fErase && ((_ptCur.x < xExtent) || _fFirstChunk))
{
SetClipLeftRight(xExtent - _ptCur.x);
EraseTextOut(_hdc, &_rc);
_ptCur.x = xExtent;
}
// increment y position to next line
_ptCur.y = _rc.bottom;
// return whether we rendered everything yet
return _ptCur.y < BottomOfRender(_rcView, _rcRender);
}
/*
* CRenderer::UpdatePalette (pobj)
*
* @mfunc
* Stores palette information so that we can render any OLE objects
* correctly in a bitmap.
*
* @rdesc
* None.
*/
void CRenderer::UpdatePalette(
COleObject *pobj) //@parm OLE object wrapper.
{
#ifndef PEGASUS
LOGPALETTE *plogpalette = NULL;
LOGPALETTE *plogpaletteMerged;
IViewObject *pviewobj;
// Get IViewObject interface information so we can build a palette
// to render the object correctly.
if (((pobj->GetIUnknown())->QueryInterface(IID_IViewObject,
(void **) &pviewobj)) != NOERROR)
{
// Couldn't get it, so we will pretend this didn't happen
return;
}
// Get the logical palette information from the object
if ((pviewobj->GetColorSet(DVASPECT_CONTENT, -1, NULL, NULL,
NULL, &plogpalette) != NOERROR)
|| (NULL == plogpalette))
{
// Couldn't get it, so we will pretend this didn't happen
goto CleanUp;
}
// Do we have any palette entries yet?
if (NULL == _plogpalette)
{
// No - just use the one returned.
_plogpalette = plogpalette;
goto CleanUp;
}
// We have had other palette entries. We just reallocate the table
// and put the newest entry on the end. This is crude, we might
// sweep the table and actually merge it. However, this code
// should be executed relatively infrequently and therefore, crude
// should be good enough.
// Allocate a new table - Note the " - 1" in the end has to do with
// the fact that LOGPALETTE is defined to have one entry already.
plogpaletteMerged = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) *
(_plogpalette->palNumEntries + plogpalette->palNumEntries - 1)];
if (NULL == plogpaletteMerged)
{
// Memory allocation failed. Just pretend it didn't happen.
goto CleanTempPalette;
}
// Copy in original table.
memcpy(&plogpaletteMerged->palPalEntry[0], &_plogpalette->palPalEntry[0],
_plogpalette->palNumEntries * sizeof(PALETTEENTRY));
// Put new data at the end.
memcpy(&plogpaletteMerged->palPalEntry[_plogpalette->palNumEntries],
&plogpalette->palPalEntry[0],
plogpalette->palNumEntries * sizeof(PALETTEENTRY));
// Replace the current palette table with the merged table.
delete _plogpalette;
_plogpalette = plogpaletteMerged;
CleanTempPalette:
delete plogpalette;
CleanUp:
// Release the object we got since we don't need it any more.
pviewobj->Release();
#endif
}
/*
* CRenderer::RenderChunk (&cchChunk, pstrToRender, cch)
*
* @mfunc
* Virtual methods allowing to reduce the length of the chunk
* (number of character rendered in one TextOut) and to render
* items interleaved in the text.
*
* Arguments:
* cchChunk in: current length of the chunk
* out: # of chars rendered if TRUE is returned
* # of chars yet to render in the chunk if FALSE if returned
*
* @rdesc
* TRUE if this method actually rendered the chunk,
* FALSE if it just updated cchChunk and rendering is still needed
*/
INLINE BOOL CRenderer::RenderChunk(
LONG& cchChunk, //@parm in: chunk cch; out: # chars rendered
// if return TRUE; else # chars yet to render
const WCHAR *pstrToRender, //@parm String to render up to cchChunk chars
LONG cch) //@parm # chars left to render on line
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::RenderChunk");
LONG cchT;
const TCHAR *pchT;
COleObject *pobj = NULL;
CObjectMgr *pobjmgr = NULL;
LONG cchvalid, i;
LONG objwidth, objheight;
// If line has objects, reduce cchChunk to go to next object only
if(_bFlags & fliHasOle)
{
pchT = pstrToRender;
cchvalid = cchChunk;
// Search for object in chunk
for( i = 0; i < cchvalid && *pchT != WCH_EMBEDDING; i++ )
pchT++;
if( i == 0 )
{
// First character is the object so display the object
pobjmgr = GetPed()->GetObjectMgr();
if (pobjmgr)
{
pobj = pobjmgr->GetObjectFromCp(GetCp());
}
if( pobj )
{
pobj->MeasureObj(GetDp(), objwidth, objheight, _yDescent);
SetClipLeftRight(_xWidth + objwidth);
if (sysparam.FUsePalette()
&& (_bFlags & fliUseOffScreenDC)
&& _pdp->IsMain())
{
// Keep track of the palette we need for rendering
// the bit map.
UpdatePalette(pobj);
}
pobj->DrawObj(_pdp, _hdc, _pdp->IsMetafile(), &_ptCur, &_rc);
_ptCur.x += objwidth;
_xWidth += objwidth;
}
cchChunk = 1;
// Both tabs and object code need to advance the run pointer past
// each character processed.
Advance(1);
_fFirstChunk = FALSE;
return TRUE;
}
else
{
// Limit chunk to character before object
cchChunk -= cchvalid - i;
}
}
// if line has tabs, reduce cchChunk
if(_bFlags & fliHasTabs)
{
for(cchT = 0, pchT = pstrToRender;
cchT < cchChunk && *pchT != TAB && *pchT != CELL
#ifdef SOFTHYPHEN
&& *pchT != SOFTHYPHEN
#endif
; pchT++, cchT++)
{
// this loop body intentionally left blank
}
if(!cchT)
{
// first char is a tab, render it and any that follow
#ifdef SOFTHYPHEN
if(*pchT == SOFTHYPHEN)
{
if(cch == 1) // Caller should render
return FALSE; // soft hyphen at EOL
Advance(1); // Skip those within line
cchChunk = 1;
}
else
#endif
cchChunk = RenderTabs(cchChunk);
Assert (cchChunk > 0);
return TRUE;
}
cchChunk = cchT; // Update cchChunk not to incl trailing tabs
}
#ifdef PWD_JUPITER
// GuyBark Jupiter 33730:
// CRLF in tables are stored internally as a speical character
// followed by a space. Display the special character as a space
// in WordPad. When the document is streamed out later, we
// replace the two characters with CRLF again.
if(_pPF->InTable())
{
// We're in a table.
pchT = pstrToRender;
cchvalid = cchChunk;
// Try to find the special character.
for(i = 0; i < cchvalid && *pchT != PWD_CRLFINCELL; i++)
{
pchT++;
}
// The CRLF is at the start of this chunk.
if( i == 0 )
{
TCHAR sz[2];
sz[0] = ' ';
sz[1] = '\0';
// GuyBark Jupiter 38743:
// TextOut needs to know if this is the last chunk of text on the line.
// Given that we always output two spaces for the secret CRLF, then the
// first space cannot be the last chunk.
_fLastChunk = FALSE;
// Display the special character as a space now.
TextOut(sz, 1, FALSE);
// Now move along with similar action to object processing above.
cchChunk = 1;
Advance(1);
_fFirstChunk = FALSE;
return TRUE;
}
else
{
// Limit chunk to characters before CR.
cchChunk -= cchvalid - i;
}
}
#endif // PWD_JUPITER
return FALSE;
}
/*
* CRenderer::SetClipLeftRight (xWidth)
*
* @mfunc
* Helper to sets left and right of clipping/erase rect.
*
* @rdesc
* Sets _rc left and right
*/
void CRenderer::SetClipLeftRight(
LONG xWidth) //@parm Width of chunk to render
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::SetClipLeftRight");
// Compute left of render/clip rect
// a priori = left of render rect
_rc.left = _rcRender.left;
// limit to left of view rect if clip to view, selected
// or line starts left of that point
if(_rc.left < _rcView.left &&
(_fClipLeftToView || _fSelected || _fBackgroundColor
|| _ptCur.x < _rcView.left))
{
_rc.left = _rcView.left;
_fClipLeftToView = TRUE;
}
// limit to start of chunk if it's inside view
if(_ptCur.x > _rcView.left)
{
if (!_fFirstChunk)
{
_rc.left = max(_ptCur.x, _rc.left);
}
else
{
// Tell TextOut that it should not invert the entire rectangle
// since we are clearing the line for paragraph justification.
_fRecalcRectForInvert = TRUE;
}
}
// We have set the rc.left for the first write so now we can ignore the
// problem of clearing to the beginning of the line.
_fFirstChunk = FALSE;
// Compute right of clipping rect
// a priori = right of rendering rect
_rc.right = _rcRender.right;
// limit to right of view rect if clip to view, selected
// or line extends beyond that point
if(_rc.right > _rcView.right &&
(_fClipRightToView || _fSelected || _fBackgroundColor
|| _ptCur.x + xWidth > _rcView.right))
{
_rc.right = _rcView.right;
_fClipRightToView = TRUE;
}
// limit to right of chunk if not last chunk or selected
if(!_fLastChunk || _fSelected || _fBackgroundColor)
_rc.right = min(_ptCur.x + xWidth, _rc.right);
}
/*
* CRenderer::TextOut (pch, cch)
*
* @mfunc
* Render text in the current context of this CRenderer
*
* @rdesc
* number of characters rendered
*
* @devnote
* Renders text only: does not do tabs or OLE objects
*/
LONG CRenderer::TextOut(
const WCHAR *pch, //@parm Text to render
LONG cch, //@parm Length of text to render
BOOL fIMEHighlight) //@parm highlight IME composition character
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::TextOut");
LONG cchT;
LONG yOffsetForChar;
// Variables used for calculating length of underline.
LONG xWidthSelPastEOL = 0;
LONG xWidthToDraw;
LONG xStart;
LONG xWidthClip;
// Colors for hightlight
COLORREF crHighlight;
COLORREF crHighlightText;
COLORREF crPrevText = 0;
COLORREF crPrevBack = 0;
CONVERTMODE cm = (CONVERTMODE)_pccs->_bConvertMode;
// For hack around ExtTextOutW Win95 FE problems.
if (cm != CM_LOWBYTE && _fEnhancedMetafileDC &&
((VER_PLATFORM_WIN32_WINDOWS == dwPlatformId) ||
(VER_PLATFORM_WIN32_MACINTOSH == dwPlatformId)))
{
cm = CM_WCTMB;
}
else if (cm != CM_LOWBYTE && _pdp->IsMetafile() &&
OnWinNTFE())
{
// FE NT metafile ExtTextOutW hack.
cm = CM_WCTMB;
}
else if( (VER_PLATFORM_WIN32_WINDOWS == dwPlatformId) &&
_pdp->IsMetafile() && !_fEnhancedMetafileDC )
{
//Win95 can't handle TextOutW to regular metafiles
cm = CM_WCTMB;
}
// Options for ExtTextOut - assume render line of same format
UINT fuOptions = ETO_CLIPPED | ETO_OPAQUE;
LONG xEraseMin = 0;
LONG xWidth;
LONG tempwidth;
int bkModeOld = 0;
// Note the clipping depends on type of output. Default to clip rectangle
// calculated by SetClipLeftRight - this is used by both regular rendering
// and off screen rendering.
RECT * prcForClip = &_rc;
// Rectangle used for clipping when a transparent render.
RECT rcClipTransparent;
if (!_fErase)
{
if (_crBackground == _crCurBackground)
{
// Assume this is off screen - don't need to clip at all
fuOptions = 0;
if (!_fUseOffScreenDC)
{
// Transparent render. We need to clip to the total view.
fuOptions = ETO_CLIPPED;
}
}
}
else if (_fLastLine && (_crBackground != _crCurBackground))
{
// We want to make sure that we don't use the background color for
// the text to opqaue anything but the current line so...
if (_rc.bottom > _ptCur.y + _yHeight)
{
_rc.bottom = _ptCur.y + _yHeight;
}
}
// Trim all nondisplayable linebreaking chars off end
while(cch && IsASCIIEOP(pch[cch - 1]))
cch--;
if( !_fLastChunk || _xWidthLine == -1 )
{
// Measure width of text to write so next point to write can be
// calculated.
xWidth = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -