⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 measure.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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
 *
 *	@module - MEASURE.C	  |
 *	
 *		CMeasurer class
 *	
 *	Authors:
 *		Original RichEdit code: David R. Fulmer <nl>
 *		Christian Fortini, Murray Sargent, Rick Sailor
 *
 */

#include "_common.h"
#include "_measure.h"
#include "_font.h"
#include "_disp.h"
#include "_edit.h"
#include "_frunptr.h"
#include "_objmgr.h"
#include "_coleobj.h"

ASSERTDATA

// Default character format for a bullet
const CHARFORMAT cfBullet = 
{
	sizeof(CHARFORMAT),
    0, 
	CFE_AUTOCOLOR + CFE_AUTOBACKCOLOR, 
	0, 
	0, 
	0,
    SYMBOL_CHARSET, 
	(BYTE) FF_DONTCARE, 
	TEXT("Symbol")
};

const TCHAR chBullet = TEXT('\xB7');
// Note we set this maximum length as appropriate for Win95 since Win95 GDI can 
// only handle 16 bit values. We don't special case this so that both NT and
// Win95 will behave the same way. 
// Note that the following obscure constant was empirically determined on Win95.
const LONG lMaximumWidth = (3 * (LONG) SHRT_MAX) / 4;

CMeasurer::CMeasurer (const CDisplay* const pdp) :
	CRchTxtPtr (pdp->GetED())	
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::CMeasurer");

	_pdp = pdp;
	_pdd = pdp;
	_pccs = NULL;
	_hdc = NULL;
	_hdcMeasure = NULL;
	_chPassword = GetPed()->TxGetPasswordChar();
	SetNumber(0);
}

CMeasurer::CMeasurer (const CDisplay* const pdp, const CRchTxtPtr &tp) :
	CRchTxtPtr (tp)	
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::CMeasurer");

	_pdp = pdp;
	_pdd = pdp;
	_pccs = NULL;
	_hdc = NULL;
	_hdcMeasure = NULL;
	_chPassword = GetPed()->TxGetPasswordChar();
	SetNumber(0);
}

CMeasurer::~CMeasurer()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::~CMeasurer");

	if(_pccs)
		_pccs->Release();

	// Releases the rendering dc
	if (_hdc)
	{
		_pdd->ReleaseDC(_hdc);
	}

	// Releases the measuring dc
	if (_hdcMeasure)
	{
		_pdd->ReleaseMeasureDC(_hdcMeasure);
	}
}

/*
 *	CMeasurer::NewLine (fFirstInPara)
 *
 *	@mfunc
 *		Initialize this measurer at the start of a new line
 */
void CMeasurer::NewLine(
	BOOL fFirstInPara)		//@parm Flag for setting up _bFlags
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::NewLine");

	CLine::Init();						// Zero all members
	if(fFirstInPara)
		_bFlags = fliFirstInPara;		// Need to know if first in para
}

/*
 *	CMeasurer::NewLine(&li)
 *
 *	@mfunc
 *		Initialize this measurer at the start of a given line
 */
void CMeasurer::NewLine(
	const CLine &li)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::NewLine");

	*this		= li;
	_cch		= 0;
	_cchWhite	= 0;
	_xWidth		= 0;

	// Can't calculate xLeft till we get an HDC
	_xLeft		= 0;
	if(!GetPF()->IsListNumbered())
		_bNumber = 0;

	_wNumber	= _bNumber;
}

/*
 *	CMeasurer::MaxWidth()
 *
 *	@mfunc
 *		Get maximum width for line
 *
 *	@rdesc
 *		Maximum width for a line
 */
LONG CMeasurer::MaxWidth()
{
	LONG xWidth = lMaximumWidth;

	if (_pdp->GetWordWrap() && !GetPF()->InTable())
	{
		// There is a caret only on the main display
		LONG xCaret = _pdp->IsMain() ? dxCaret : 0;

		// Calculate the width of the display
		LONG xDispWidth = _pdp->GetMaxPixelWidth();

		if (!_pdp->SameDevice(_pdd))
		{
			// xWidthMax is calculated to the size of the screen DC. If
			// there is a target device with different characteristics
			// we need to convert the width to the target device's width
			xDispWidth = _pdd->ConvertXToDev(xDispWidth, _pdp);
		}
		xWidth = xDispWidth - MeasureRightIndent() - _xLeft - xCaret;
	}
	return (xWidth > 0) ? xWidth : 0;
}

/*
 *	CMeasurer::MeasureText (cch)
 *
 *	@mfunc
 *		Measure a stretch of text from current running position.
 *
 *	@rdesc
 *		width of text (in device units), < 0 if failed
 */
LONG CMeasurer::MeasureText(
	LONG cch)		//@parm Number of characters to measure
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureText");

	LONG xWidth = _xWidth;
	
	if (Measure (0x7fffffff, cch, 0) == MRET_FAILED)
		return -1;

	LONG xMaxWidth = MaxWidth();

	return min(_xWidth - xWidth, xMaxWidth);
}

/*
 *	CMeasurer::MeasureLine (xWidthMax, cchMax, uiFlags, ppu, pliTarget)
 *
 *	@mfunc
 *		Measure a line of text from current cp and determine line break.
 *		On return *this contains line metrics for _pdd device.
 *
 *	@rdesc
 *		TRUE if success, FALSE if failed
 */
BOOL CMeasurer::MeasureLine(
	LONG xWidthMax,		//@parm max width to process (-1 uses CDisplay width)
	LONG cchMax, 		//@parm Max chars to process (-1 if no limit)
	UINT uiFlags,  		//@parm Flags controlling the process (see Measure())
	CLine *pliTarget)	//@parm Returns target-device line metrics (optional)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureLine");

	LONG lRet;
	LONG cp = GetCp();
	const CDevDesc *pddTarget = NULL;

	if (_pdp->GetWordWrap())
	{
		// Target devices are only interesting if word wrap is on because the 
		// only really interesting thing a target device can tell us is where
		// the word breaks will occur.
		pddTarget = _pdp->GetTargetDev();

		if (pddTarget != NULL)
		{
			// If there is a target device, use that device to compute line 
			// breaks. This is followed with a recompute to get the actual 
			// measurements on the rendering device.
			// ... but first releases the measuring dc
			if (_hdcMeasure)
				_pdd->ReleaseMeasureDC(_hdcMeasure);
			_hdcMeasure = pddTarget->GetDC();
			_yMeasurePerInch = GetDeviceCaps(_hdcMeasure, LOGPIXELSY);
			_pdd = pddTarget;

			if (_pccs != NULL)
			{
				_pccs->Release();
				_pccs = NULL;
			}
		}
	}

	// Compute line break
	lRet = Measure(xWidthMax, cchMax, uiFlags);

	// Stop here if failed
	if(lRet == MRET_FAILED)
		return FALSE;

	// Return target metrics if requested
	if(pliTarget)
	{
		*pliTarget = *this;
	}

	if (pddTarget)
	{
		// First computation was with the target device so we need to recompute
		// with the rendering device. Here we set the device to measure with
		// back to the render device.
		// ... first releases the current measuring dc
		if (_hdcMeasure)
			_pdd->ReleaseMeasureDC(_hdcMeasure);
		_pdd = _pdp;
		_hdcMeasure = _pdp->GetMeasureDC(&_yMeasurePerInch);

		if (_pccs != NULL)
		{
			_pccs->Release();
			_pccs = NULL;
		}

		// We just use this flag as an easy way to get the recomputation to occur.
		lRet = MRET_NOWIDTH;
	}

	// Recompute metrics on rendering device
	if(lRet == MRET_NOWIDTH)
	{
		LONG cch = _cch;
		SHORT cchWhite = _cchWhite;

		// Save the flags for this line because at least the EOP flag gets 
		// screwed up in the recalc and none of the flags will change based
		// on the second recalc of the line.  Ditto for numbering variables
		BYTE bFlags  = _bFlags;
		BYTE bNumber = _bNumber;
		BYTE cchEOP  = _cchEOP;
		WORD wNumber = _wNumber;

#ifdef PWD_JUPITER
        // GuyBark Jupiter 31112: Store the current line height here.
        int yHeightOld = _yHeight;
#endif // PWD_JUPITER

		Advance(-cch);				// move back to BOL

		NewLine(uiFlags & MEASURE_FIRSTINPARA);

#ifdef PWD_JUPITER
        // GuyBark Jupiter 31112: Say the line consists only of an EOP mark.
        // This means Measure() will end up giving the line a default height.
        // This is incorrect as the line should have the height of the EOP.
        // So give the line the it's previous value here as a starting point.
        // Measure() can set it to something else later if it wants to.
        if(cch == cchWhite)
        {
            _yHeight = yHeightOld;
        }
#endif // PWD_JUPITER
        
		// (AndreiB) EOP flag would not get reset below because we excluded it 
		// from the second measure ( - cchWhite) By restoring it right here
		// we ensure we know whether the line is at the end of para or not
		// right from the beginning. This may seem somewhat hacky but it works.
		_cchEOP = cchEOP;

#ifdef PWD_JUPITER
        // GuyBark Jupiter 34903: 
        // I don't really know how this can happen, but the paragraph (_pPF)
        // can be numbered here, but the measured details don't realize it.
        // As a failsafe, make sure the measured details reflect the true
        // paragraph attributes.

        if(!_bNumber &&             // The measure details think this isn't numbered.
            _pPF->wNumbering != 0)  // But the paragraph details says it is numbered!
        {
            // Make all the measure numbering details current.
            _bNumber = _pPF->wNumbering;
            _wNumber = _pPF->wNumbering;
        }
#endif // PWD_JUPITER

   		lRet = Measure(0x7fffffff, cch - cchWhite, uiFlags & MEASURE_FIRSTINPARA);

		if(lRet != 0)
		{
			Assert(lRet != MRET_NOWIDTH);
			return FALSE;
		}

		// Restore the flags and numbering variables
		_bFlags  = bFlags;
		_bNumber = bNumber;
		_cchEOP  = cchEOP;
		_wNumber = wNumber;

		Assert((LONG)_cch == cch - cchWhite);
		_cchWhite = cchWhite;
		_cch = cch;				// account for the white stuff at EOL
		Advance(cchWhite);		// skip white stuff that we did not remeasure
	}
	
	// Now that we know the line width, compute line shift due
	// to alignment, and add it to the left position 
	_xLeft += MeasureLineShift();

	return TRUE;
}

/*
 *	CMeasurer::RecalcLineHeight ()
 *
 *	@mfunc
 *	  Reset the height of the the line we are measuring if the new run of 
 *	  text is taller than the current maximum in the line.
 */
void CMeasurer::RecalcLineHeight()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::RecalcLineHeight");

	// Compute line height
	LONG	yOffset = _pccs->_yOffset;
	SHORT	yHeight = _pccs->_yHeight;
	SHORT 	yDescent = _pccs->_yDescent;
	SHORT	yAscent = yHeight - yDescent;
	SHORT	yAboveBase;
	SHORT	yBelowBase;

	yAboveBase = max(yAscent, yAscent + yOffset);
	yBelowBase = max(yDescent, yDescent - yOffset);
	_yHeight = max(yAboveBase, _yHeight - _yDescent) +
		       max(yBelowBase, _yDescent);
	_yDescent = max(yBelowBase, _yDescent);
}

/*
 *	CMeasurer::Measure (xWidthMax, cchMax, uiFlags)
 *
 *	@mfunc
 *		Measure given amount of text, start at current running position
 *		and storing # chars measured in _cch. 
 *		Can optionally determine line break based on a xWidthMax and 
 *		break out at that point.
 *
 *	@rdesc
 *		0 success
 *		MRET_FAILED	 if failed 
 *		MRET_NOWIDTH if second pass is needed to compute correct width
 *
 *	@devnote
 *		The uiFlags parameter has the following meanings:
 *			MEASURE_FIRSTINPARA		this is first line of paragraph
 *			MEASURE_BREAKATWORD		break out on a word break
 *			MEASURE_BREAKATWIDTH	break closest possible to xWidthMax
 */
LONG CMeasurer::Measure(
	LONG xWidthMax,			//@parm Max width of line (-1 uses CDisplay width)
	LONG cchMax,			//@parm Max chars to process (-1 if no limit)
	UINT uiFlags)			//@parm Flags controlling the process (see above)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::Measure");

	LONG		cch;				// cchChunk count down
	LONG		cchChunk;			// cch of cst-format contiguous run
	LONG		cchNonWhite;		// cch of last nonwhite char in line
	LONG		cchText = GetTextLength();
	unsigned	ch;					// Temporary char
	BOOL		fFirstInPara = uiFlags & MEASURE_FIRSTINPARA;
	BOOL        fLastChObj = FALSE;
	LONG		lRet = 0;
	const TCHAR*pch;
	CTxtEdit *	ped = _pdp->GetED();
	COleObject *pobj;
	LONG		objheight;
	LONG		yHeightBullet = 0;
	LONG		xCaret = dxCaret;
	LONG		xAdd;				// Character width
#ifdef SOFTHYPHEN
	LONG		xSoftHyphen = 0;	// Most recent soft hyphen width
#endif
	LONG		xWidthNonWhite;		// xWidth for last nonwhite char in line
	LONG		xWidthMaxOverhang;	// The max with the current run's overhang
									//  taken into consideration.
	// These two variables are used to keep track of whether there is a height change
	// so that we know whether we need to recalc the line in certain line break cases.
	BOOL		fHeightChange = FALSE;
	LONG		yHeightOld = 0;

	const INT	MAX_SAVED_WIDTHS = 31;	// power of 2 - 1
	INT			i, index, iSavedWidths = 0;
	struct {
		LONG	width;
		LONG	xLineOverhang;
		LONG	yHeight;
		LONG	yDescent;
	} savedWidths[MAX_SAVED_WIDTHS+1];

	_pPF = GetPF();							// Be sure current CParaFormat
											//  ptr is up to date
	BOOL fInTable = _pPF->InTable();
	WORD wNumbering		 = _pPF->wNumbering;
	WORD wNumberingStyle = _pPF->wNumberingStyle;

	if(IsInOutlineView())
	{
		if(IsHeadingStyle(_pPF->sStyle))	// Store heading number if relevant
			_nHeading = -_pPF->sStyle - 1;

		if(_pPF->wEffects & PFE_COLLAPSED)	// Cache collapsed bit
			_fCollapsed = TRUE;
	}

	if(!_hdcMeasure)
	{
		_hdcMeasure = _pdd->GetMeasureDC(&_yMeasurePerInch);
		if(!_hdcMeasure)
		{
			AssertSz(FALSE, "CMeasurer::Measure could not get DC");
			return MRET_FAILED;
		}
	}

	// Init fliFirstInPara flag for new line
	if(fFirstInPara)
	{
		_bFlags |= fliFirstInPara;
		if(fInTable)
			_bFlags |= fliUseOffScreenDC;

		// Because measure bullet depends on the cp we need
		// to measure it before we do the reset of our measuring
		if(wNumbering)	
#ifdef PWD_JUPITER // GuyBark Jupiter 34728: Pay attention to the returned bullet height!
			yHeightBullet = MeasureBulletHeight();
#else
			MeasureBulletHeight();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -