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

📄 measure.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#endif // PWD_JUPITER

		else if(IsInOutlineView() && IsHeadingStyle(_pPF->sStyle))
			yHeightBullet = BITMAP_HEIGHT_HEADING + 1;
	}

	// If line spacing or space before/after, measure from beginning of line
	if(_cch && (_pPF->bLineSpacingRule || _pPF->dySpaceBefore
		|| _pPF->dySpaceAfter || fInTable))					
	{										
		 Advance(-(LONG)_cch);
		 NewLine(fFirstInPara);
	}

	_bNumber = _wNumber < 256 ? _wNumber : 255;	// Store current para # offset
	_xLeft = MeasureLeftIndent();				// Set left indent

	// Compute width to break out at
	if(xWidthMax < 0)
	{					
		xWidthMax = MaxWidth();

		// MaxWidth includes the caret size.
		xCaret = 0;
	}
	else
	{							  
		// (AndreiB) xWidthMax that's coming down to us is always calculated
		// with respect to the screen DC. The only scenario it comes into play
		// however is in TxGetNaturalSize, which may output a slightly
		// different result because of that.
		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
			xWidthMax = _pdd->ConvertXToDev(xWidthMax, _pdp);
		}
	}

	// For overhang support, we test against this adjusted widthMax.
	xWidthMaxOverhang = xWidthMax;

	// Are we ignoring the offset of the characters for the measure?
	if ((uiFlags & MEASURE_IGNOREOFFSET) == 0)
	{
		// No - then take it from the max
		xWidthMaxOverhang -= (_xLineOverhang + xCaret);
	}

	// Compute max number of characters to process
	cch = cchText - GetCp();
	if(cchMax < 0 || cchMax > cch)
		cchMax = cch;

	cchNonWhite		= _cch;							// Default nonwhite parms
	xWidthNonWhite	= _xWidth;
	for( ; cchMax > 0;								// Measure up to cchMax
		cchMax -= cchChunk, Advance(cchChunk))		//  chars
	{												
		pch = GetPch(cch);
		cch = min(cch, cchMax);						// Compute constant-format
		cchChunk = GetCchLeftRunCF();
		cch = min(cch, cchChunk);					// Counter for next while
		cchChunk = cch;								// Save chunk size

		if(GetCF()->dwEffects & CFE_HIDDEN)			// Ignore hidden text
		{
			_cch += cchChunk;
			continue;
		}

		if (_chPassword != 0)
		{
			// WARNING: pch cannot be incremented after this point.
			// Be sure that any new code does not modify pch after
			// it is set here when we deal with passwords.
			pch = &_chPassword;
		}

		// Check if new character format run or whether we don't yet have
		// a font.
		if ( !_pccs || FormatIsChanged() )
		{
			// New CF run or format for this line not yet initialized
			ResetCachediFormat();

			// If the format has changed,we release our old Format cache
			if( _pccs != NULL )
			{
				// Release previous char cache if this is a new CF run
				_pccs->Release();
			}
				
			_pccs = fc().GetCcs(_hdcMeasure, GetCF(), 
								_pdp->GetZoomNumerator(),
								_pdp->GetZoomDenominator(), 
								_yMeasurePerInch);

			// If we couldn't get one, we are dead.
			if(!_pccs)
			{
				// When zooming, we may fail in low mem situations in which case
				// the text won't display. If there was a zoom factor try
				// getting the character metrics without the zoom factor.
				if (_pdp->GetZoomNumerator() != _pdp->GetZoomDenominator()) {
					_pccs = fc().GetCcs(_hdcMeasure, GetCF(), 
										1, 1, _yMeasurePerInch);
				}
				if (!_pccs) {
					AssertSz(FALSE, "CMeasurer::Measure could not get _pccs");
					return MRET_FAILED;
				}
			}

			if (_cch && (0 == GetIchRunCF()))
			{
				// This is not the first character in the line,
				// therefore there are multiple character formats
				// on the line so we want to remember to render
				// this off screen.
				_bFlags |= fliUseOffScreenDC;
			}
		}

		// NOTE: Drawing with a dotted pen on the screen and in a
		// compatible bit map does not seem to match on some hardware.
		// If at some future point we do a better job of drawing the
		// dotted underline, this statement block can be removed.
		if (CFU_UNDERLINEDOTTED == _pccs->_bUnderlineType)
		{
			// We draw all dotted underline lines off screen to get
			// a consistent display of the dotted line.
			_bFlags |= fliUseOffScreenDC;
		}

		_xLineOverhang = _pccs->_xOverhang;

		xWidthMaxOverhang = xWidthMax;			// Overhang reduces max.

		// Are we ignoring the offset of the characters for the measure?
		if ((uiFlags & MEASURE_IGNOREOFFSET) == 0)
		{
			// No - then take it from the max
			xWidthMaxOverhang -= (_pccs->_xOverhang + xCaret);
		}

		// Adjust line height for new format run
		if(cch > 0 && *pch)
		{
			// Note: the EOP only contributes to the height calculation for the
			// line if there are no non-white space characters on the line or 
			// the paragraph is a bullet paragraph. The bullet paragraph 
			// contribution to the line height is done in AdjustLineHeight.
			if ((0 == cchNonWhite) || (*pch != CR && *pch != LF))
			{
				// Determine if the current run is the tallest text on this
				// line and if so, increase the height of the line.
				yHeightOld = _yHeight;
				RecalcLineHeight();

				// Test for a change in line height. This only happens when
				// this is not the first character in the line and (surprise)
				// the height changes.
				if (yHeightOld && yHeightOld != _yHeight)
					fHeightChange = TRUE;
			}
		}

		while(cch > 0)
		{											// Process next char
			xAdd = 0;								// Default zero width
			AssertSz(_chPassword == 0 || pch == &_chPassword,
				"CMeasurer::Measure pch set to invalid data");
			ch = *pch;	  

#ifdef PWD_JUPITER
			// GuyBark Jupiter: If this is the special character for preserving
			// CRLF in table cells, measure it as if it were a space.
			if(ch == 0xFFFA)
			{
			    ch = ' ';
			}
#endif // PWD_JUPITER

			if(ch == WCH_EMBEDDING)
			{
				_bFlags |= fliHasOle;
				pobj = ped->GetObjectMgr()->GetObjectFromCp
								(GetCp() + cchChunk - cch);
				if( pobj )
				{
					pobj->MeasureObj(_pdp, xAdd, objheight, _yDescent);

					// Only update height for line if the object is going
					// to be on this line.
					if((!_cch || _xWidth + xAdd <= xWidthMaxOverhang) 
						&& objheight > _yHeight)
					{
						_yHeight = (short)objheight;
					}
				}
				if(_xWidth + xAdd > xWidthMaxOverhang)
					fLastChObj = TRUE;
			}
			// The following if succeeds if ch isn't a CELL, BS, TAB, LF,
			// VT, FF, or CR
			else if(!IN_RANGE(CELL, ch, CR))		// Not TAB or EOP
			{										
				if(!_pccs->Include(ch, xAdd))		// Get char width	
				{
					AssertSz(FALSE, "CMeasurer::Measure char not in font");
					return MRET_FAILED;
				}
#ifdef SOFTHYPHEN
				if(ch == SOFTHYPHEN)
				{
					_bFlags |= fliHasTabs;			// Setup RenderChunk()
					if(_xWidth + xAdd < xWidthMaxOverhang || !_cch)
					{
						xSoftHyphen = xAdd;			// Save soft hyphen width
						xAdd = 0;					// Use 0 unless at EOL
					}
				}
#endif
			}
			else if(ch == TAB || ch == CELL)		
			{
				_bFlags |= fliHasTabs;
				xAdd = MeasureTab(ch);
			}
			else									// Done with line
				goto eop;							// Go process EOP chars

			index = iSavedWidths++ & MAX_SAVED_WIDTHS;
			savedWidths[ index ].width = xAdd;
			savedWidths[ index ].xLineOverhang = _xLineOverhang;
			savedWidths[ index ].yHeight = _yHeight;
			savedWidths[ index ].yDescent = _yDescent;
			_xWidth += xAdd;

			if(_xWidth > xWidthMaxOverhang && _cch > 0)
				goto overflow;

			_cch++;
			if (_chPassword == 0)
			{
				pch++;
			}
			cch--;
			if((ped->IsIMEComposition() && 0 == cch) || ch != TEXT(' ') /*&& ch != TAB*/)	// If not whitespace char,
			{
				cchNonWhite		= _cch;				//  update nonwhitespace
				xWidthNonWhite	= _xWidth;			//  count and width
			}
		}											// while(cch > 0)
	}												// for(;cchMax > 0;...)
	goto eol;										// All text exhausted 


// End Of Paragraph	char encountered (CR, LF, VT, or FF, but mostly CR)
eop:
	Advance(cchChunk - cch);				// Position tp at EOP
	cch = AdvanceCRLF();					// Bypass possibly multibyte EOP
	_cchEOP = cch;							// Store EOP cch
	_cch   += cch;							// Increment line count
											
	if(ch == CR)							// Get new para number
	{
		const CParaFormat *pPF = GetPF();
		_wNumber = pPF->UpdateNumber(_wNumber, _pPF);
		_fNextInTable = pPF->InTable() && GetCp() < cchText;
	}

	AssertSz(ped->Get10Mode() || cch == 1,
		"CMeasurer::Measure: EOP isn't a single char");
	AssertSz(ped->TxGetMultiLine() || GetCp() == cchText,
		"CMeasurer::Measure: EOP in single-line control");

eol:										// End of current line
	if(uiFlags & MEASURE_BREAKATWORD)		// Compute count of whitespace
	{										//  chars at EOL
		_cchWhite = (SHORT)(_cch - cchNonWhite);
		_xWidth = xWidthNonWhite;
	}
	goto done;


overflow:									// Went past max width for line
	_xWidth -= xAdd;
	--iSavedWidths;
	_xLineOverhang = savedWidths[iSavedWidths & MAX_SAVED_WIDTHS].xLineOverhang;
	Advance(cchChunk - cch);				// Position *this at overflow
											//  position
	if(uiFlags & MEASURE_BREAKATWORD)		// If required, adjust break on
	{										//  word boundary
		// We should not have the EOP flag set here.  The case to watch out
		// for is when we reuse a line that used to have an EOP.  It is the
		// responsibility of the measurer to clear this flag as appropriate.
	
		Assert(_cchEOP == 0);

		_cchEOP = 0;							// Just in case

		if (ch == TAB || ch == CELL)
		{
			// If the last character measured is a tab,	leave it on the
			// next line to allow tabbing off the end of line as in Word
			goto done;
		}

		LONG cpStop = GetCp();					// Remember current cp

		cch = -FindWordBreak(WB_LEFTBREAK, _cch+1);

		if (cch == 0 && fLastChObj)				// If preceding char is an
		{										//  object,	put current char
			goto done;							//  on next line
		}

		Assert(cch >= 0);
		if(cch + 1 < (LONG)_cch)				// Break char not at BOL
		{
			ch = _rpTX.GetPrevChar();
			if (ch == TAB || ch == CELL)		// If break char is a TAB,
			{									//  put it on the next line
				cch++;							//  as in Word
				Advance(-1);					
			}
#ifdef SOFTHYPHEN
			else if(ch == SOFTHYPHEN)
				_xWidth += xSoftHyphen;
#endif
			_cch -= cch;
		}
		else if(cch == (LONG)_cch && cch > 1 &&
			_rpTX.GetChar() == ' ')				// Blanks all the way back to
		{										//  BOL. Bypass first blank
			Advance(1);
			cch--;
			_cch = 1;
		}
		else									// Advance forward to end of
			SetCp(cpStop);						//  measurement

		Assert(_cch > 0);

		// Now search at start of word to figure how many white chars at EOL
		if(GetCp() < cchText)
		{
			pch = GetPch(cch);
			cch = 0;
			if(ped->_pfnWB((TCHAR *)pch, 0, sizeof(TCHAR), WB_ISDELIMITER))
			{
				cch = FindWordBreak(WB_RIGHT);
				Assert(cch >= 0);
			}

			_cchWhite = (SHORT)cch;
			_cch += cch;

			if(_rpTX.IsAtEOP())					// skip *only* 1 EOP -jOn
			{
				_cchEOP = AdvanceCRLF();
				_cch += _cchEOP;
				goto done;
			}
		}

		i = cpStop - GetCp();
		if( i )
		{
			if ( i > 0 )
				i += _cchWhite;
			if (i > 0 && i < iSavedWidths && i < MAX_SAVED_WIDTHS)
			{
				while (i-- > 0)
				{
					iSavedWidths = (iSavedWidths - 1) & MAX_SAVED_WIDTHS;
					_xWidth -= savedWidths[iSavedWidths].width;
				}
				_xLineOverhang = savedWidths[iSavedWidths].xLineOverhang;
				_yHeight	   = savedWidths[iSavedWidths].yHeight;
				_yDescent	   = savedWidths[iSavedWidths].yDescent;
			}
			else
			{
				// Need to recompute width from scratch.
				_xWidth = -1;
				lRet = MRET_NOWIDTH;
			}
		}
		else
		{
			// i == 0 means that we are breaking on the first letter in a word.
			// Therefore, we want to set the width to the total non-white space
			// calculated so far because that does not include the size of the
			// character that caused the break nor any of the white space 
			// preceeding the character that caused the break.
			if (!fHeightChange)
			{
				_xWidth = xWidthNonWhite;
			}
			else
			{
				// Need to recompute from scratch so that we can get the 
				// correct height for the control
				_xWidth = -1;
				lRet = MRET_NOWIDTH;
			}
		}
	}
	else if(uiFlags & MEASURE_BREAKATWIDTH)
	{
		// Breaks at character closest to target width
		if((_cch == 1) && (xWidthMax < _xWidth / 2))
		{
			_cch = 0;
			_xWidth = 0;
			Advance(-1);
		}
		if(xAdd && xWidthMax - _xWidth >= xAdd / 2)
		{
			_cch++;
			_xWidth += xAdd;
			Advance(1);
		}
	}

done:
	// If no height yet, use default height
	if(_yHeight == 0)
	{
		const CCharFormat *pcf = ped->GetCharFormat(-1);
		CCcs * const pccs = fc().GetCcs(_hdcMeasure, pcf, _pdp->GetZoomNumerator(),
			_pdp->GetZoomDenominator(), _yMeasurePerInch);
		_yHeight = pccs->_yHeight;
		_yDescent = pccs->_yDescent;
		pccs->Release();
	}

	// Allow last minute adjustment to line height
	if (yHeightBullet > _yHeight)
	{
		_yHeight = yHeightBullet;
	}

	_fStartsList = (_bNumber == 1 && fFirstInPara);
	AdjustLineHeight();
	return lRet;
}

/*
 *	CMeasurer::AdjustLineHeight()
 *
 *	@mfunc
 *		Adjust for space before/after and line spacing rules.
 *		No effect for plain text.
 *
 *	@future
 *		Base multiple line height calculations on largest font height rather
 *		than on line height (_yHeight), since the latter may be unduly large
 *		due to embedded objects.  Word does this correctly.
 */
void CMeasurer::AdjustLineHeight()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::AdjustLineHeight");

	if(!IsRich() || IsInOutlineView())			// Plain text and outline mode
		return;									//  don't use special line
												//  spacings
	const CParaFormat * pPF = _pPF;
	DWORD	dwRule	  = pPF->bLineSpacingRule;
	LONG	dyAfter	  = 0;						// Default no space after
	LONG	dyBefore  = 0;						// Default no space before
	LONG	dySpacing = pPF->dyLineSpacing;
	LONG	yHeight	  = LYtoDY(dySpacing);

	if(_bFlags & fliFirstInPara)
		dyBefore = LYtoDY(pPF->dySpaceBefore);	// Space before paragraph

	if(yHeight < 0)								// Negative heights mean use
		_yHeight = -(SHORT)yHeight;				//  the magnitude exactly

	else if(dwRule)								// Line spacing rule is active
	{
		switch (dwRule)
		{
		case tomLineSpace1pt5:
			dyAfter = _yHeight >> 1;			// Half-line space after
			break;								//  (per line)
	
		case tomLineSpaceDouble:
			dyAfter = _yHeight;					// Full-line space after
			break;								//  (per line)
	

⌨️ 快捷键说明

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