diff options
Diffstat (limited to 'editeng/source/editeng/impedit3.cxx')
-rw-r--r-- | editeng/source/editeng/impedit3.cxx | 223 |
1 files changed, 155 insertions, 68 deletions
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 6a14cda16f92..c33db07b2a6b 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -70,6 +70,7 @@ #include <osl/diagnose.h> #include <comphelper/string.hxx> #include <memory> +#include <set> #include <vcl/outdev/ScopedStates.hxx> @@ -375,8 +376,8 @@ void ImpEditEngine::FormatDoc() // Here already, so that not always in CreateLines... bool bMapChanged = ImpCheckRefMapMode(); + std::set<sal_Int32> aRepaintParas; - aInvalidRect = tools::Rectangle(); // make empty for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { ParaPortion& rParaPortion = GetParaPortions()[nPara]; @@ -410,46 +411,21 @@ void ImpEditEngine::FormatDoc() rParaPortion.SetMustRepaint( false ); } - // InvalidRect set only once... - if ( aInvalidRect.IsEmpty() ) - { - // For Paperwidth 0 (AutoPageSize) it would otherwise be Empty()... - tools::Long nWidth = std::max(tools::Long(1), getWidthDirectionAware(aPaperSize)); - Range aInvRange( GetInvalidYOffsets( &rParaPortion ) ); - aInvalidRect = tools::Rectangle( Point( 0, nY+aInvRange.Min() ), - Size( nWidth, aInvRange.Len() ) ); - } - else - { - aInvalidRect.SetBottom( nY + rParaPortion.GetHeight() ); - } - } - else if ( bGrow ) - { - aInvalidRect.SetBottom( nY + rParaPortion.GetHeight() ); + aRepaintParas.insert(nPara); } nY += rParaPortion.GetHeight(); } + aInvalidRect = tools::Rectangle(); // make empty + // One can also get into the formatting through UpdateMode ON=>OFF=>ON... // enable optimization first after Vobis delivery... { - sal_uInt32 nNewHeightNTP; - sal_uInt32 nNewHeight = CalcTextHeight( &nNewHeightNTP ); + tools::Long nNewHeightNTP; + tools::Long nNewHeight = CalcTextHeight(&nNewHeightNTP); tools::Long nDiff = nNewHeight - nCurTextHeight; if ( nDiff ) aStatus.GetStatusWord() |= !IsVertical() ? EditStatusFlags::TextHeightChanged : EditStatusFlags::TEXTWIDTHCHANGED; - if ( nNewHeight < nCurTextHeight ) - { - aInvalidRect.SetBottom( static_cast<tools::Long>(std::max( nNewHeight, nCurTextHeight )) ); - if ( aInvalidRect.IsEmpty() ) - { - aInvalidRect.SetTop( 0 ); - // Left and Right are not evaluated, are however set due to IsEmpty. - aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight(getWidthDirectionAware(aPaperSize)); - } - } nCurTextHeight = nNewHeight; nCurTextHeightNTP = nNewHeightNTP; @@ -473,6 +449,20 @@ void ImpEditEngine::FormatDoc() } } } + + if (nDiff) + aInvalidRect.Union(tools::Rectangle::Justify( + { 0, nNewHeight }, { getWidthDirectionAware(aPaperSize), nCurTextHeight })); + + if (!aRepaintParas.empty()) + { + auto CombineRepaintParasAreas = [&](const LineAreaInfo& rInfo) { + if (aRepaintParas.count(rInfo.nPortion)) + aInvalidRect.Union(rInfo.aArea); + return CallbackResult::Continue; + }; + IterateLineAreas(CombineRepaintParasAreas, IterFlag::inclILS); + } } bIsFormatting = false; @@ -566,10 +556,10 @@ void ImpEditEngine::CheckPageOverflow() { SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( aStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); - sal_uInt32 nBoxHeight = GetMaxAutoPaperSize().Height(); + tools::Long nBoxHeight = GetMaxAutoPaperSize().Height(); SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current MaxAutoPaperHeight is " << nBoxHeight); - sal_uInt32 nTxtHeight = CalcTextHeight(nullptr); + tools::Long nTxtHeight = CalcTextHeight(nullptr); SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current Text Height is " << nTxtHeight); sal_uInt32 nParaCount = GetParaPortions().Count(); @@ -598,6 +588,13 @@ static sal_Int32 ImplCalculateFontIndependentLineSpacing( const sal_Int32 nFontH return ( nFontHeight * 12 ) / 10; // + 20% } +tools::Long ImpEditEngine::GetColumnWidth(const Size& rPaperSize) const +{ + assert(mnColumns >= 1); + tools::Long nWidth = IsVertical() ? rPaperSize.Height() : rPaperSize.Width(); + return (nWidth - mnColumnSpacing * (mnColumns - 1)) / mnColumns; +} + bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { ParaPortion& rParaPortion = GetParaPortions()[nPara]; @@ -785,11 +782,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } } - tools::Long nMaxLineWidth; - if ( !IsVertical() ) - nMaxLineWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : aPaperSize.Width(); - else - nMaxLineWidth = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : aPaperSize.Height(); + const bool bAutoSize = IsVertical() ? aStatus.AutoPageHeight() : aStatus.AutoPageWidth(); + tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? aMaxAutoPaperSize : aPaperSize); nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); nMaxLineWidth -= nStartX; @@ -797,7 +791,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // If PaperSize == long_max, one cannot take away any negative // first line indent. (Overflow) if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) ) - nMaxLineWidth = getWidthDirectionAware(aPaperSize) - GetXValue(rLRItem.GetRight()); + nMaxLineWidth = GetColumnWidth(aPaperSize) - GetXValue(rLRItem.GetRight()); // If still less than 0, it may be just the right edge. if ( nMaxLineWidth <= 0 ) @@ -824,7 +818,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { GetTextRanger()->SetVertical( IsVertical() ); - tools::Long nTextY = nStartPosY + GetEditCursor( &rParaPortion, pLine->GetStart() ).Top(); + tools::Long nTextY = nStartPosY + GetEditCursor( &rParaPortion, pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top(); if ( !bSameLineAgain ) { SeekCursor( pNode, nTmpPos+1, aTmpFont ); @@ -1468,7 +1462,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // has to be used for the Alignment. If it does not fit or if it // will change the paper width, it will be formatted again for // Justification! = LEFT anyway. - tools::Long nMaxLineWidthFix = getWidthDirectionAware(aPaperSize) + tools::Long nMaxLineWidthFix = GetColumnWidth(aPaperSize) - GetXValue( rLRItem.GetRight() ) - nStartX; if ( aTextSize.Width() < nMaxLineWidthFix ) nMaxLineWidth = nMaxLineWidthFix; @@ -1725,7 +1719,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) { sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); SvxAdjust eJustification = GetJustification( nPara ); - tools::Long nMaxLineWidth = getWidthDirectionAware(aPaperSize); + tools::Long nMaxLineWidth = GetColumnWidth(aPaperSize); nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); if ( nMaxLineWidth < 0 ) nMaxLineWidth = 1; @@ -3020,15 +3014,17 @@ void ImpEditEngine::setYDirectionAware(Point& pt, tools::Long y) const pt.setX(y); } -bool ImpEditEngine::isYOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const +tools::Long ImpEditEngine::getYOverflowDirectionAware(const Point& pt, + const tools::Rectangle& rectMax) const { + tools::Long nRes; if (!IsVertical()) - return pt.Y() >= rectMax.Bottom(); - - if (IsTopToBottom()) - return pt.X() <= rectMax.Left(); + nRes = pt.Y() - rectMax.Bottom(); + else if (IsTopToBottom()) + nRes = rectMax.Left() - pt.X(); else - return pt.X() >= rectMax.Right(); + nRes = pt.X() - rectMax.Right(); + return std::max(nRes, tools::Long(0)); } bool ImpEditEngine::isXOverflowDirectionAware(const Point& pt, const tools::Rectangle& rectMax) const @@ -3042,6 +3038,95 @@ bool ImpEditEngine::isXOverflowDirectionAware(const Point& pt, const tools::Rect return pt.Y() < rectMax.Top(); } +tools::Long ImpEditEngine::getLeftDirectionAware(const tools::Rectangle& rect) const +{ + if (!IsVertical()) + return rect.Left(); + + if (IsTopToBottom()) + return rect.Top(); + else + return rect.Bottom(); +} + +tools::Long ImpEditEngine::getRightDirectionAware(const tools::Rectangle& rect) const +{ + if (!IsVertical()) + return rect.Right(); + + if (IsTopToBottom()) + return rect.Bottom(); + else + return rect.Top(); +} + +tools::Long ImpEditEngine::getTopDirectionAware(const tools::Rectangle& rect) const +{ + if (!IsVertical()) + return rect.Top(); + + if (IsTopToBottom()) + return rect.Right(); + else + return rect.Left(); +} + +tools::Long ImpEditEngine::getBottomDirectionAware(const tools::Rectangle& rect) const +{ + if (!IsVertical()) + return rect.Bottom(); + + if (IsTopToBottom()) + return rect.Left(); + else + return rect.Right(); +} + +// Returns the resulting shift for the point; allows to apply the same shift to other points +Point ImpEditEngine::MoveToNextLine( + Point& rMovePos, // [in, out] Point that will move to the next line + tools::Long nLineHeight, // [in] Y-direction move distance (direction-aware) + sal_Int32& rColumn, // [in, out] current column number + Point aOrigin, // [in] Origin point to calculate limits and initial Y position in a new column + tools::Long* pnHeightNeededToNotWrap // On column wrap, returns how much more height is needed +) const +{ + const Point aOld = rMovePos; + + // Move the point by the requested distance in Y direction + adjustYDirectionAware(rMovePos, nLineHeight); + // Check if the resulting position has moved beyond the limits, and more columns left. + // The limits are defined by a rectangle starting from aOrigin with width of aPaperSize + // and height of nCurTextHeight + Size aActPaperSize(aPaperSize); + if (IsVertical()) + aActPaperSize.setWidth(nCurTextHeight); + else + aActPaperSize.setHeight(nCurTextHeight); + tools::Long nNeeded = getYOverflowDirectionAware(rMovePos, { aOrigin, aActPaperSize }); + if (pnHeightNeededToNotWrap) + *pnHeightNeededToNotWrap = nNeeded; + if (nNeeded && rColumn < mnColumns) + { + ++rColumn; + // If we didn't fit into the last column, indicate that only by setting the column number + // to the total number of columns; do not adjust + if (rColumn < mnColumns) + { + // Set Y position of the point to that of aOrigin + setYDirectionAware(rMovePos, getYDirectionAware(aOrigin)); + // Move the point by the requested distance in Y direction + adjustYDirectionAware(rMovePos, nLineHeight); + // Move the point by the column+spacing distance in X direction + adjustXDirectionAware(rMovePos, GetColumnWidth(aPaperSize) + mnColumnSpacing); + } + } + + return rMovePos - aOld; +} + +// TODO: use IterateLineAreas in ImpEditEngine::Paint, to avoid algorithm duplication + void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly, Degree10 nOrientation ) { if ( !GetUpdateMode() && !bStripOnly ) @@ -3077,6 +3162,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const tools::Long nVertLineSpacing = CalcVertLineSpacing(aStartPos); + sal_Int32 nColumn = 0; // Over all the paragraphs... @@ -3109,8 +3195,6 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po adjustYDirectionAware(aStartPos, rPortion.GetFirstLineOffset()); - const Point aParaStart( aStartPos ); - const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; @@ -3121,12 +3205,13 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const EditLine* const pLine = &rPortion.GetLines()[nLine]; assert( pLine && "NULL-Pointer in the line iterator in UpdateViews" ); sal_Int32 nIndex = pLine->GetStart(); + tools::Long nLineHeight = pLine->GetHeight(); + if (nLine != nLastLine) + nLineHeight += nVertLineSpacing; + MoveToNextLine(aStartPos, nLineHeight, nColumn, aOrigin); aTmpPos = aStartPos; adjustXDirectionAware(aTmpPos, pLine->GetStartPosX()); - adjustYDirectionAware(aTmpPos, pLine->GetMaxAscent()); - adjustYDirectionAware(aStartPos, pLine->GetHeight()); - if (nLine != nLastLine) - adjustYDirectionAware(aStartPos, nVertLineSpacing); + adjustYDirectionAware(aTmpPos, pLine->GetMaxAscent() - nLineHeight); if ( ( !IsVertical() && ( aStartPos.Y() > aClipRect.Top() ) ) || ( IsVertical() && IsTopToBottom() && aStartPos.X() < aClipRect.Right() ) @@ -3140,7 +3225,9 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // does, too. No change for not-layouting (painting). if(0 == nLine) // && !bStripOnly) { - GetEditEnginePtr()->PaintingFirstLine(n, aParaStart, aOrigin, nOrientation, rOutDev); + Point aLineStart(aStartPos); + adjustYDirectionAware(aLineStart, -nLineHeight); + GetEditEnginePtr()->PaintingFirstLine(n, aLineStart, aOrigin, nOrientation, rOutDev); // Remember whether a bullet was painted. const SfxBoolItem& rBulletState = pEditEngine->GetParaAttrib(n, EE_PARA_BULLETSTATE); @@ -3159,7 +3246,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const TextPortion& rTextPortion = rPortion.GetTextPortions()[nPortion]; const tools::Long nPortionXOffset = GetPortionXOffset( &rPortion, pLine, nPortion ); - setXDirectionAware(aTmpPos, getXDirectionAware(aParaStart)); + setXDirectionAware(aTmpPos, getXDirectionAware(aStartPos)); adjustXDirectionAware(aTmpPos, nPortionXOffset); if (isXOverflowDirectionAware(aTmpPos, aClipRect)) break; // No further output in line necessary @@ -3326,8 +3413,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // what will lead to a compressed look with multiple lines const sal_uInt16 nMaxAscent(pLine->GetMaxAscent()); - adjustYDirectionAware(aStartPos, nMaxAscent); - adjustYDirectionAware(aTmpPos, nMaxAscent); + aTmpPos += MoveToNextLine(aStartPos, nMaxAscent, + nColumn, aOrigin); } std::vector< sal_Int32 >::iterator curIt = itSubLines; ++itSubLines; @@ -3739,7 +3826,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } // no more visible actions? - if (isYOverflowDirectionAware(aStartPos, aClipRect)) + if (getYOverflowDirectionAware(aStartPos, aClipRect)) break; } @@ -3780,7 +3867,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po pPDFExtOutDevData->EndStructureElement(); // no more visible actions? - if (isYOverflowDirectionAware(aStartPos, aClipRect)) + if (getYOverflowDirectionAware(aStartPos, aClipRect)) break; } } @@ -3958,7 +4045,7 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew { aInvalidRect = tools::Rectangle(); // make empty aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight( aPaperSize.Width() ); + aInvalidRect.SetRight(GetColumnWidth(aPaperSize)); aInvalidRect.SetTop( GetParaPortions().GetYOffset( pUpperPortion ) ); aInvalidRect.SetBottom( GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight() ); @@ -4551,10 +4638,10 @@ void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* } } -void ImpEditEngine::ImplUpdateOverflowingParaNum(sal_uInt32 nPaperHeight) +void ImpEditEngine::ImplUpdateOverflowingParaNum(tools::Long nPaperHeight) { - sal_uInt32 nY = 0; - sal_uInt32 nPH; + tools::Long nY = 0; + tools::Long nPH; for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { ParaPortion& rPara = GetParaPortions()[nPara]; @@ -4570,12 +4657,12 @@ void ImpEditEngine::ImplUpdateOverflowingParaNum(sal_uInt32 nPaperHeight) } } -void ImpEditEngine::ImplUpdateOverflowingLineNum(sal_uInt32 nPaperHeight, +void ImpEditEngine::ImplUpdateOverflowingLineNum(tools::Long nPaperHeight, sal_uInt32 nOverflowingPara, - sal_uInt32 nHeightBeforeOverflowingPara) + tools::Long nHeightBeforeOverflowingPara) { - sal_uInt32 nY = nHeightBeforeOverflowingPara; - sal_uInt32 nLH; + tools::Long nY = nHeightBeforeOverflowingPara; + tools::Long nLH; ParaPortion& rPara = GetParaPortions()[nOverflowingPara]; |