📄 measure.cpp
字号:
case tomLineSpaceAtLeast:
if(_yHeight >= yHeight)
break;
// Fall thru to space exactly
case tomLineSpaceExactly:
_yHeight = (SHORT)yHeight;
break;
case tomLineSpaceMultiple: // Multiple-line space after
dyAfter = (_yHeight*dySpacing)/20 // (20 units per line)
- _yHeight;
}
}
if(_cchEOP)
dyAfter += LYtoDY(pPF->dySpaceAfter); // Space after paragraph end
_yHeight += (SHORT)(dyBefore + dyAfter); // Add in any space before
_yDescent += (SHORT)dyAfter; // and after
if(_pPF->InTable())
{
_yHeight++;
if(!_fNextInTable)
{
_yHeight++;
_yDescent++;
}
}
}
/*
* CMeasurer::MeasureLeftIndent()
*
* @mfunc
* Compute and return left indent of line in device units
*
* @rdesc
* Left indent of line in device units
*
* @comm
* Plain text is sensitive to StartIndent and RightIndent settings,
* but usually these are zero for plain text.
*/
LONG CMeasurer::MeasureLeftIndent()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureLeftIndent");
AssertSz(_pPF != NULL, "CMeasurer::MeasureLeftIndent _pPF not set!");
LONG xLeft = _pPF->dxStartIndent; // Use logical units
// up to return
if(IsRich())
{
LONG dxOffset = _pPF->dxOffset;
BOOL fFirstInPara = _bFlags & fliFirstInPara;
if(IsInOutlineView())
{
xLeft = lDefaultTab/2 * (_pPF->bOutlineLevel + 1);
if(!fFirstInPara)
dxOffset = 0;
}
if(fFirstInPara)
{
if(_pPF->wNumbering) // Add offset to text
{ // on first line
LONG dx = DXtoLX(MeasureBulletWidth()); // Use max of bullet
dx = max(dx, _pPF->wNumberingTab); // width, numbering tab,
dxOffset = max(dxOffset, dx); // and para offset
}
else if(_pPF->InTable()) // For tables, need to
xLeft += dxOffset; // add in trgaph twice
// since dxStartIndent
else // subtracts one
dxOffset = 0;
}
xLeft += dxOffset;
}
return LXtoDX(max(xLeft, 0));
}
/*
* CMeasurer::HitTest(x)
*
* @mfunc
* Return HITTEST for displacement x in this line. Can't be specific
* about text area (_xLeft to _xLeft + _xWidth), since need to measure
* to get appropriate cp (done elsewhere)
*
* @rdesc
* HITTEST for a displacement x in this line
*/
HITTEST CMeasurer::HitTest(
LONG x) //@parm Displacement to test hit
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::HitTest");
if(x < 0)
return HT_SelectionBar;
if(x > _xLeft + _xWidth)
return HT_RightOfText;
if(x > _xLeft) // Caller can refine this
return HT_Text; // with CLine::CchFromXpos()
if(IsRich() && (_bFlags & fliFirstInPara))
{
_pPF = GetPF();
LONG dx;
if(_pPF->wNumbering)
{
// Doesn't handle case where Bullet is wider than following dx
dx = LXtoDX(max(_pPF->dxOffset, _pPF->wNumberingTab));
if(x >= _xLeft - dx)
return HT_BulletArea;
}
if(IsInOutlineView())
{
dx = LXtoDX(lDefaultTab/2 * _pPF->bOutlineLevel);
if(x >= dx && x < dx + (_pPF->bOutlineLevel & 1
? LXtoDX(lDefaultTab/2) : _pdp->Zoom(BITMAP_WIDTH_HEADING)))
{
return HT_OutlineSymbol;
}
}
}
return HT_LeftOfText;
}
/*
* CMeasurer::MeasureRightIndent()
*
* @mfunc
* Compute and return right indent of line in device units
*
* @rdesc
* right indent of line in device units
*
* @comm
* Plain text is sensitive to StartIndent and RightIndent settings,
* but usually these are zero for plain text.
*/
LONG CMeasurer::MeasureRightIndent()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureRightIndent");
return LXtoDX(max(_pPF->dxRightIndent, 0));
}
/*
* CMeasurer::MeasureTab()
*
* @mfunc
* Computes and returns the width from the current position to the
* next tab stop (in device units).
*/
LONG CMeasurer::MeasureTab(unsigned ch)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureTab");
LONG xCur = _xWidth + MeasureLeftIndent();
const CParaFormat * pPF = _pPF;
LONG cTab = pPF->cTabCount;
LONG dxDefaultTab = lDefaultTab;
LONG dxIndent = LXtoDX(pPF->dxStartIndent + pPF->dxOffset);
LONG dxOffset = pPF->dxOffset;
LONG dxOutline = 0;
BOOL fInTable = pPF->InTable();
LONG h = 0;
LONG const * pl = pPF->rgxTabs;
LONG xT;
LONG xTab;
AssertSz(cTab >= 0 || cTab <= MAX_TAB_STOPS,
"CMeasurer::MeasureTab: illegal tab count");
if(fInTable)
{
h = LXtoDX(dxOffset);
dxOffset = 0;
}
if(IsInOutlineView())
dxOutline = lDefaultTab/2 * (pPF->bOutlineLevel + 1);
if(cTab && (!fInTable || ch == CELL)) // Use default TAB for TAB in
{ // table
for(xTab = 0; cTab--; pl++) // Try explicit tab stops 1st
{
xT = GetTabPos(*pl) + dxOutline; // (2 most significant nibbles
xT = LXtoDX(xT); // are for type/style)
if(xT > _pdp->GetMaxPixelWidth()) // Ignore tabs wider than
break; // display
if(xT + h > xCur) // Allow text in table cell to
{ // move into cell gap (h > 0)
if(dxOffset > 0 && xT < dxIndent)// Explicit tab in a hanging
return xT - xCur; // indent takes precedence
xTab = xT;
break;
}
}
if(dxOffset > 0 && xCur < dxIndent) // If no tab before hanging
return dxIndent - xCur; // indent, tab to indent
if(xTab) // Else use tab position
{
if(fInTable)
{
xTab += h;
if(cTab) // Don't include the cell gap
xTab += h; // in the last cell
if(IsInOutlineView() && cTab < pPF->cTabCount)
xTab += h;
}
return xTab - xCur;
}
if(pPF->cTabCount)
dxDefaultTab = pPF->rgxTabs[0];
dxDefaultTab = GetPed()->GetDefaultTab();
if(!dxDefaultTab)
dxDefaultTab = lDefaultTab;
dxDefaultTab = GetTabPos(dxDefaultTab);
}
AssertSz(dxDefaultTab > 0, "Default tab is bad");
dxDefaultTab = LXtoDX(dxDefaultTab);
return dxDefaultTab - xCur%dxDefaultTab; // Round up to nearest
}
/*
* CMeasurer::MeasureLineShift ()
*
* @mfunc
* Computes and returns the line x shift due to alignment
*
* @comm
* Plain text is sensitive to StartIndent and RightIndent settings,
* but usually these are zero for plain text.
*/
LONG CMeasurer::MeasureLineShift()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureLineShift");
WORD wAlignment = _pPF->wAlignment;
LONG xShift;
if (IsInOutlineView() ||
(wAlignment != PFA_RIGHT && wAlignment != PFA_CENTER))
{
return 0;
}
// Normal view with center or flush-right para. Move right accordingly
xShift = _pPF->InTable()
? -LXtoDX(GetTabPos(_pPF->rgxTabs[_pPF->cTabCount - 1]) - _pPF->dxStartIndent)
: -_xLineOverhang - _xWidth;
xShift += _pdp->GetMaxPixelWidth() - _xLeft - MeasureRightIndent()
- GetCaretDelta();
xShift = max(xShift, 0); // Don't allow alignment to go < 0
// Can happen with a target device
if(wAlignment == PFA_CENTER)
xShift /= 2;
return xShift;
}
/*
* CMeasurer::MeasureBulletHeight()
*
* @mfunc
* Computes bullet/numbering height
*
* @rdesc
* return bullet/numbering string height
*/
LONG CMeasurer::MeasureBulletHeight()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureBulletHeight");
CCcs *pccs = GetCcsBullet(NULL);
LONG yHeight = 0;
if(pccs && pccs != (CCcs *)(-1)) // NB: pccs = -1 if bullet
{ // display is suppressed
yHeight = pccs->_yHeight;
pccs->Release();
}
return yHeight;
}
/*
* CMeasurer::MeasureBulletWidth()
*
* @mfunc
* Computes bullet/numbering width
*
* @rdesc
* return bullet/numbering string width
*/
LONG CMeasurer::MeasureBulletWidth()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::MeasureBulletWidth");
CCcs *pccs = GetCcsBullet(NULL);
LONG xWidth = 0;
if(pccs && pccs != (CCcs *)(-1)) // NB: pccs = -1 if bullet
{ // display is suppressed
WCHAR szBullet[CCHMAXNUMTOSTR];
GetBullet(szBullet, pccs, &xWidth);
pccs->Release();
}
return xWidth;
}
/*
* CMeasurer::GetBullet(pch, pccs, pxWidth)
*
* @mfunc
* Computes bullet/numbering string, string length, and width
*
* @rdesc
* return bullet/numbering string length
*/
LONG CMeasurer::GetBullet(
WCHAR *pch, //@parm Bullet string to receive bullet text
CCcs *pccs, //@parm CCcs to use
LONG *pxWidth) //@parm Out parm for bullet width
{
Assert(pccs && pch);
LONG cch = _pPF->NumToStr(pch, _bNumber);
LONG dx;
LONG i;
LONG xWidth = 0;
pch[cch++] = ' '; // Ensure a little extra space
for(i = cch; i--; xWidth += dx)
{
if(!pccs->Include(*pch++, dx))
{
TRACEERRSZSC("CMeasurer::MeasureBulletWidth(): Error filling CCcs", E_FAIL);
}
}
xWidth += pccs->_xUnderhang + pccs->_xOverhang;
if(pxWidth)
*pxWidth = xWidth;
return cch;
}
/*
* CMeasurer::GetCcsBullet(pCFRet)
*
* @mfunc
* Get CCcs for numbering/bullet font. If bullet is suppressed because
* preceding EOP is a VT (Shift-Enter), then returns -1. If GetCcs()
* fails, it returns NULL.
*
* @rdesc
* ptr to bullet CCcs, or NULL (GetCcs() failed), or -1 (bullet suppressed)
*
* @comm
* This approach is crazy: the bullet charformat is constructed every
* time a bullet paragraph gets measured or rendered. Would be better
* if bullet is stored in line and can have a special CHARFORMAT run if
* the user applies one
*/
CCcs * CMeasurer::GetCcsBullet(
CCharFormat *pCFRet) //@parm option character format to return
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CMeasurer::GetCcsBullet");
// Make sure the static bullet charformat still makes sense
AssertSz(sizeof(CHARFORMAT) == cfBullet.cbSize,
"CMeasurer::GetCcsBullet Bullet charformat size corrupt");
AssertSz(CFE_AUTOCOLOR + CFE_AUTOBACKCOLOR == cfBullet.dwEffects,
"CMeasurer::GetCcsBullet Bullet dwEffects size corrupt");
AssertSz(SYMBOL_CHARSET == cfBullet.bCharSet,
"CMeasurer::GetCcsBullet Bullet bCharSet size corrupt");
if((_pPF->wNumberingStyle & 0xF00) == PFNS_NONUMBER)
return (CCcs *)(-1); // Number/bullet suppressed
CCharFormat CF;
CCcs * pccs;
const CCharFormat * pCF;
CCharFormat * pCFUsed = (pCFRet) ? pCFRet : &CF;
CTxtPtr rpTX(_rpTX);
// Bullet CF is given by that for EOP in bullet's paragraph.
if(GetCp()) // Not at beginning of story
{ // If preceding EOP is a VT
if(rpTX.PrevChar() == VT) // (Shift-Enter), suppress
return (CCcs *)(-1); // display of bullet
rpTX.AdvanceCp(1); // Restore rpTX to _rpTX
}
CFormatRunPtr rpCF(_rpCF);
rpCF.AdvanceCp(rpTX.FindEOP(tomForward));
rpCF.AdjustBackward();
pCF = GetPed()->GetCharFormat(rpCF.GetFormat());
if (NULL == pCF)
{
Assert(pCF);
return NULL;
}
// Construct bullet (or numbering) CCharFormat for the bullet
if(_pPF->wNumbering > PFN_BULLET) // All numbering and Unicode
*pCFUsed = *pCF; // bullets use CF at EOP
else // Traditional bullet uses
{ // Symbol font bullet, but
pCFUsed->Set(&cfBullet); // some attributes of CF at
pCFUsed->yHeight = pCF->yHeight; // EOP
pCFUsed->dwEffects = pCF->dwEffects;
pCFUsed->crTextColor = pCF->crTextColor;
// GUYBARK: Can have highlighted background now.
pCFUsed->crBackColor = pCF->crBackColor;
}
// Since we always cook up the bullet character format, we don't need
// to cache it.
pccs = fc().GetCcs(_hdcMeasure, pCFUsed, _pdp->GetZoomNumerator(),
_pdp->GetZoomDenominator(), _yMeasurePerInch);
#if DEBUG
if(!pccs)
{
TRACEERRSZSC("CMeasurer::GetCcsBullet(): no CCcs", E_FAIL);
}
#endif // DEBUG
return pccs;
}
/*
* CMeasurer::SetNumber(wNumber)
*
* @mfunc
* Store number if numbered paragraph
*/
void CMeasurer::SetNumber(WORD wNumber)
{
if(!GetPF()->IsListNumbered())
wNumber = 0;
else if (!wNumber)
wNumber = 1;
_wNumber = wNumber;
}
/*
* CMeasurer::DXtoLX(x), LXtoDX(x), LYtoDY(y)
*
* @mfunc
* Functions that return dezoomed and zoomed scaled coordinates
*
* @rdesc
* Scaled coordinate
*/
LONG CMeasurer::DXtoLX(LONG x)
{
return _pdp->UnZoom(_pdd->DXtoLX(x));
}
LONG CMeasurer::LXtoDX(LONG x)
{
return _pdd->LXtoDX(_pdp->Zoom(x));
}
LONG CMeasurer::LYtoDY(LONG y)
{
return _pdd->LYtoDY(_pdp->Zoom(y));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -