📄 render.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* @doc INTERNAL
*
* @module - RENDER.C |
* CRenderer class
*
* Authors:
* Original RichEdit code: David R. Fulmer
* Christian Fortini
* Murray Sargent
*
*/
#include "_common.h"
#include "_render.h"
#include "_font.h"
#include "_disp.h"
#include "_edit.h"
#include "_select.h"
#include "_objmgr.h"
#include "_coleobj.h"
#include "_ime.h"
// Default colors for background and text on window's host printer
const COLORREF RGB_WHITE = RGB(255, 255, 255);
const COLORREF RGB_BLACK = RGB(0, 0, 0);
ASSERTDATA
static HBITMAP g_hbitmapSubtext = 0;
static HBITMAP g_hbitmapExpandedHeading = 0;
static HBITMAP g_hbitmapCollapsedHeading = 0;
static HBITMAP g_hbitmapEmptyHeading = 0;
// GuyBark 34205: Added the small bitmap handling.
static HBITMAP g_hbitmapExpandedSmallHeading = 0;
static HBITMAP g_hbitmapCollapsedSmallHeading = 0;
static HBITMAP g_hbitmapEmptySmallHeading = 0;
HRESULT InitializeOutlineBitmaps()
{
g_hbitmapSubtext =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_SUBTEXT));
g_hbitmapExpandedHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_EXPANDED_HEADING));
g_hbitmapCollapsedHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_COLLAPSED_HEADING));
g_hbitmapEmptyHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_EMPTY_HEADING));
// GuyBark Jupiter 34205: The above bitmaps look pretty bad when the zoom
// stretches them smaller. There is no SetStretchBltMode() on the device,
// to help preserve the black at the expense of the white. So load up some
// bitmaps with thicker black lines, to use if the current zoom is < 100%.
// Not an ideal solution, but probably the only thing we can do to make
// the outline view look a little nicer at low zoom levels.
g_hbitmapExpandedSmallHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_EXPANDEDSM_HEADING));
g_hbitmapCollapsedSmallHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_COLLAPSEDSM_HEADING));
g_hbitmapEmptySmallHeading =
LoadBitmap(hinstRE, MAKEINTRESOURCE(BITMAP_ID_EMPTYSM_HEADING));
if (!g_hbitmapSubtext ||
!g_hbitmapExpandedHeading ||
!g_hbitmapCollapsedHeading ||
!g_hbitmapEmptyHeading ||
!g_hbitmapExpandedSmallHeading ||
!g_hbitmapCollapsedSmallHeading ||
!g_hbitmapEmptySmallHeading)
{
return ERROR_FILE_NOT_FOUND; // REVIEW: better error?
}
return NOERROR;
}
/*
* IsEnhancedMetafileDC( hDC )
*
* @mfunc
* Check if hDC is a Enhanced Metafile DC.
* There is work around the Win95 FE ::GetObjectType() bug.
*
* @rdesc
* Returns TRUE for EMF DC.
*/
BOOL IsEnhancedMetafileDC (
HDC hDC) //@parm handle to device context
{
return W32->IsEnhancedMetafileDC( hDC );
}
CRenderer::CRenderer (const CDisplay * const pdp) :
CMeasurer (pdp)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::CRenderer");
Init();
}
CRenderer::CRenderer (const CDisplay * const pdp, const CRchTxtPtr &tp) :
CMeasurer (pdp, tp)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::CRenderer");
Init();
}
/*
* CRenderer::Init
*
* @mfunc
* initialize everything to zero
*/
void CRenderer::Init()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::Init");
static RECT zrect = { 0, 0, 0, 0 };
_rcView = zrect;
_rcRender = zrect;
_rc = zrect;
_xWidthLine = 0;
_dwFlags = 0;
_ptCur.x = 0;
_ptCur.y = 0;
_crBackground = CLR_INVALID;
CTxtSelection *psel = GetPed()->GetSel();
_fRenderSelection = psel && psel->GetShowSelection();
// Get accelerator offset if any
_cpAccelerator = GetPed()->GetCpAccelerator();
_plogpalette = NULL;
}
INLINE void EraseTextOut(HDC hdc, const RECT *prc)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "EraseTextOut");
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prc, NULL, 0, NULL);
}
/*
* CRenderer::StartRender (&rcView, &rcRender, yHeightBitmap)
*
* @mfunc
* Prepare this renderer for rendering operations
*
* @rdesc
* FALSE if nothing to render, TRUE otherwise
*/
BOOL CRenderer::StartRender (
const RECT &rcView, //@parm View rectangle
const RECT &rcRender, //@parm Rectangle to render
const LONG yHeightBitmap) //@parm Height of bitmap for offscreen DC
{
BOOL fTransparent;
CTxtEdit *ped = GetPed();
BOOL fInOurHost = ped->fInOurHost();
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::StartRender");
// If this a metafile or a transparent control we better not be trying to
// render off screen. Therefore, the bit map height must be 0.
AssertSz(!((_pdp->IsMetafile() || ped->_fTransparent)
&& (yHeightBitmap != 0)),
"CRenderer::StartRender metafile and request for off screen DC");
if(!_hdc)
{
_hdc = _pdp->GetDC();
_hdcMeasure = _pdp->GetMeasureDC(&_yMeasurePerInch);
}
AssertSz(_hdc, "CRenderer::StartRender() - No rendering DC");
// Set view and rendering rects
_rcView = rcView;
_rcRender = rcRender;
// Init flags indicating whether to erase around each side
// of the view rect.
_fClipLeftToView =
_fClipRightToView =
_fClipTopToView =
_fClipBottomToView = FALSE;
fTransparent = ped->_fTransparent;
if (!fInOurHost || !_pdp->IsPrinter())
{
// If we are displaying to a window, or we are not in the window's
// host, we use the colors specified by the host. For text and
// foreground.
_crBackground = ped->TxGetBackColor();
_crTextColor = ped->TxGetForeColor();
}
else
{
// When the window's host is printing, the default colors are white
// for the background and black for the text.
_crBackground = RGB_WHITE;
_crTextColor = RGB_BLACK;
}
SetBkColor(_hdc, _crBackground);
SetTextColor(_hdc, _crTextColor);
if (!_pdp->IsMetafile() && _pdp->IsMain())
{
// This isn't a metafile so we do the usual thing.
// Set flag indicating whether we can safely erase the background
_fErase = !fTransparent;
}
else
{
// This is a metafile or a printer so clear the render rectangle
// and then pretend we are transparent.
// NOTE: we do this special behavior for printer's because Win95
// seems to have a bug where it cannot render bitmaps to printers.
_fErase = FALSE;
if (!fTransparent)
{
// If the control is not transparent we clear the display.
EraseTextOut(_hdc, &rcRender);
}
fTransparent = TRUE;
}
// Set background mode and color
SetBkMode(_hdc, fTransparent ? TRANSPARENT : OPAQUE);
// Set text alignement
// Note: here we want the alignment to be top and left, which is usually
// what the default of the DC is. Performance testing showed that if we
// set base line alignment, the first call to set base line alignment
// takes ALOT of time. So, its better to compute where the base line
// should go and draw top left, than it is to figure where the top left
// is and draw base line.
if (GetTextAlign( _hdcMeasure ) != (TA_TOP | TA_LEFT))
SetTextAlign(_hdc, TA_TOP | TA_LEFT);
// Since we haven't had a chance to set the background color
// assume that the default and the current are the same.
_crCurBackground = _crBackground;
// Assume that we won't use an offscreen DC
_fUseOffScreenDC = FALSE;
AssertSz((yHeightBitmap == 0) || !fTransparent,
"CRenderer::StartRender off screen requested with transparent");
if (yHeightBitmap != 0)
{
HPALETTE hpal = fInOurHost
? ped->TxGetPalette()
: (HPALETTE) GetCurrentObject(_hdcMeasure, OBJ_PAL);
// Create an off screen DC for rendering
if (_osdc.Init(
_hdcMeasure,
_rcRender.right - _rcRender.left,
yHeightBitmap,
_crBackground) == NULL)
{
return FALSE;
}
_osdc.SelectPalette(hpal);
// We are using off screen rendering
_fUseOffScreenDC = TRUE;
}
// If this is not the main display or it is a metafile
// we want to ignore the logic to render selections
if (!_pdp->IsMain() || _pdp->IsMetafile())
{
_fRenderSelection = FALSE;
}
// For hack around ExtTextOutW Win95FE Font and EMF problems.
_fEnhancedMetafileDC = ((VER_PLATFORM_WIN32_WINDOWS == dwPlatformId) && IsEnhancedMetafileDC(_hdc));
return TRUE;
}
void CRenderer::EndRender()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::EndRender");
_rc = _rcRender;
AssertSz(_hdc, "CRenderer::EndRender() - No rendering DC");
if(_fErase)
{
if(_ptCur.y < _rcRender.bottom)
{
_rc.top = _ptCur.y;
EraseTextOut(_hdc, &_rc);
_rc.top = _rcRender.top;
}
if(_fClipLeftToView && _rc.left < _rcView.left)
{
_rc.right = _rcView.left;
EraseTextOut(_hdc, &_rc);
_rc.right = _rcRender.right;
}
if (_fClipTopToView && _rc.top < _rcView.top)
{
_rc.bottom = _rcView.top;
EraseTextOut(_hdc, &_rc);
_rc.bottom = _rcRender.bottom;
}
if (_fClipRightToView && _rc.right > _rcView.right)
{
_rc.left = _rcView.right;
EraseTextOut(_hdc, &_rc);
_rc.left = _rcRender.left;
}
}
// We need to dump the font - Done here because methods in CMeasurer will (should)
// never select the font.
if (_pccs && _hdc)
{
HFONT hfontOld = (HFONT)SelectObject(_hdc, GetStockObject(SYSTEM_FONT));
Assert(hfontOld == _pccs->_hfont);
// Drop _pccs
_pccs->Release();
// End further processing on the font reference.
_pccs = NULL;
}
}
/*
* CRenderer::NewLine (&li)
*
* @mfunc
* Init this CRenderer for rendering the specified line
*/
void CRenderer::NewLine (const CLine &li)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CRenderer::NewLine");
*this = li;
Assert(GetCp() + _cch <= (DWORD)GetTextLength());
_xWidthLine = _xWidth;
_xWidth = 0;
_ptCur.x = _xLeft + _rcView.left - _pdp->GetXScroll();
_fFirstChunk = TRUE;
_fRecalcRectForInvert = FALSE;
_fSelected = FALSE;
}
/*
* CRenderer::CalcHeightBitmap(yHeightToRender)
*
* @mfunc
* Calculate the height of the bitmap needed for rendering
*
* @rdesc
* Height of bitmap needed for rendering
*
* @devnote
* Common code to calculate the size of a bitmap needed. It takes
* a parameter because it is useful for one of the caller routines
* to calculate this value.
*/
LONG CRenderer::CalcHeightBitmap(
LONG yHeightToRender)
{
LONG yHeightOfBitmap = min(_yHeight, yHeightToRender);
if (_rc.top < _ptCur.y)
{
// If the top of the area to render is above the starting point
// of where to render, we add that in so that that area will get
// cleared out by the bitblt as well rather than having an extra
// call to ExtTextOut to do so.
yHeightOfBitmap += (_ptCur.y - _rc.top);
}
return yHeightOfBitmap;
}
/*
* CRenderer::SetUpOffScreenDC(osdc, xAdj, yAdj, yRcIgnored)
*
* @mfunc
* Setup the renderer for using an off screen DC
*
* @rdesc
* NULL - an error occurred<nl>
* ~NULL - DC to save
*
* @devnote
* This is inline because it is only called in one place. If for some
* reason this becomes generally useful, please remove the inline.
*/
INLINE HDC CRenderer::SetUpOffScreenDC(
COffScreenDC& osdc, //@parm off screen DC object
LONG& xAdj, //@parm offset to x
LONG& yAdj, //@parm offset to y
LONG& yRcIgnored) //@parm part of display rectangle that not processed
{
// Save the render DC
HDC hdcSave = _hdc;
LONG yHeightRC = _rc.bottom - _rc.top;
LONG yHeightOfBitmap = CalcHeightBitmap(yHeightRC);
#ifdef PWD_JUPITER
// GuyBark Jupiter 35187:
// Get the current text color for the current render dc.
COLORREF colText = GetTextColor(_hdc);
#endif // PWD_JUPITER
// Replace the render DC with an off screen DC
_hdc = _osdc.GetDC();
if (NULL == _hdc)
{
// There is no off screen renderer
// This better be a line marked for a one time off screen rendering
// that wasn't. Note: standard cases for this happening are a line
// that would have been displayed is scrolled off the screen
// because an update of the selection.
AssertSz((_bFlags & fliOffScreenOnce) != 0,
"CRenderer::SetUpOffScreenDC Unexpected off screen DC failure");
_hdc = hdcSave;
return NULL;
}
AssertSz(!GetPed()->_fTransparent,
"CRenderer::SetUpOffScreenDC off screen render of tranparent control");
if (_pccs != NULL)
{
// There is current a character format for the run so we need to
// get in sync with that since the off screen DC isn't necessarily
// set to that font.
// Get the character format
const CCharFormat *pcf = GetCF();
// Set up the font.
SetFontAndColor(pcf);
}
// We are rendering to a tranparent background
_fErase = FALSE;
// Prepare for clear
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -