summaryrefslogtreecommitdiff
path: root/editeng
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2024-03-28 12:30:34 +0900
committerMiklos Vajna <vmiklos@collabora.com>2024-04-15 14:56:31 +0200
commit774c1ddfecc6389234f8d0e68d6e17c1fe218cb1 (patch)
treee3761a8d1d48b330a9202c0494e1ed1188d707d9 /editeng
parent134bbf9ad54ad351b859e31bd4f7aecae17e595c (diff)
editeng: use text scaling that better mimics MSO text scaling
Implement text scaling algorithm that is similar to MSO text scaling for text boxes for the compatibility purpuse, so that the Impress slides better match how the PP slides are layed out. This also moves the implementation into EditEng, where it is possible to better control how searching for the best scaling factor is performed without doing additional irrelevant work or trigger invalidations that should not be triggered. An additional change is that the paragraph with no content at the end are ignored, and are not taken into account when determining the height of the content. This is done for compatibility reasons. Fix horizontal spacing of tabs - the spacing shouldn't be scaled and the tab shouldn't include the space at the beginning of the line. Change-Id: Ie37fa67f1cf300e915a4ebaef2a7f968bf6c5744 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165441 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> (cherry picked from commit f61ea135430d7b4a1fac7de1e57a1314fbb1b49e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166087 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'editeng')
-rw-r--r--editeng/inc/editdoc.hxx14
-rw-r--r--editeng/source/editeng/impedit.hxx9
-rw-r--r--editeng/source/editeng/impedit2.cxx22
-rw-r--r--editeng/source/editeng/impedit3.cxx139
4 files changed, 141 insertions, 43 deletions
diff --git a/editeng/inc/editdoc.hxx b/editeng/inc/editdoc.hxx
index 80e3cc34243c..8e17c6c38fa6 100644
--- a/editeng/inc/editdoc.hxx
+++ b/editeng/inc/editdoc.hxx
@@ -662,7 +662,9 @@ public:
class ParaPortionList
{
mutable sal_Int32 nLastCache;
- std::vector<std::unique_ptr<ParaPortion>> maPortions;
+ typedef std::vector<std::unique_ptr<ParaPortion>> ParaPortionContainerType;
+ ParaPortionContainerType maPortions;
+
public:
ParaPortionList();
~ParaPortionList();
@@ -684,6 +686,16 @@ public:
void Append(std::unique_ptr<ParaPortion> p);
sal_Int32 Count() const;
+ ParaPortion& getRef(sal_Int32 nPosition) { return *maPortions[nPosition]; }
+ ParaPortion const& getRef(sal_Int32 nPosition) const { return *maPortions[nPosition]; }
+
+ sal_Int32 lastIndex() const { return Count() - 1; }
+
+ ParaPortionContainerType::iterator begin() { return maPortions.begin(); }
+ ParaPortionContainerType::iterator end() { return maPortions.end(); }
+ ParaPortionContainerType::const_iterator cbegin() const { return maPortions.cbegin(); }
+ ParaPortionContainerType::const_iterator cend() const { return maPortions.cend(); }
+
#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
// temporary:
static void DbgCheck(ParaPortionList const&, EditDoc const& rDoc);
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
index 34d57e8e9747..988c446aca57 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -530,6 +530,7 @@ private:
Color maBackgroundColor;
+ ScalingParameters maCustomScalingParameters;
ScalingParameters maScalingParameters;
bool mbRoundToNearestPt;
@@ -617,6 +618,7 @@ private:
void ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreUndoCheck = false );
void TextModified();
void CalcHeight( ParaPortion* pPortion );
+ bool isInEmptyClusterAtTheEnd(ParaPortion& rParaPortion);
void InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge = false );
void ResetUndoManager();
@@ -880,8 +882,11 @@ public:
void SetMinColumnWrapHeight(tools::Long nVal) { mnMinColumnWrapHeight = nVal; }
- void FormatDoc();
- void FormatFullDoc();
+ tools::Long FormatParagraphs(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs);
+ void ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs);
+ void FormatDoc();
+ void FormatFullDoc();
+
void UpdateViews( EditView* pCurView = nullptr );
void Paint( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice );
void Paint(OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly = false, Degree10 nOrientation = 0_deg10);
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index 8c5265e1304e..048226658d4e 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -4376,12 +4376,31 @@ tools::Long ImpEditEngine::GetXPos(
return nX;
}
+/** Is true if paragraph is in the empty cluster of paragraphs at the end */
+bool ImpEditEngine::isInEmptyClusterAtTheEnd(ParaPortion& rPortion)
+{
+ sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion);
+
+ auto& rParagraphs = GetParaPortions();
+ if (rParagraphs.Count() <= 0)
+ return false;
+
+ sal_Int32 nCurrent = rParagraphs.lastIndex();
+ while (nCurrent > 0 && rParagraphs.getRef(nCurrent).IsEmpty())
+ {
+ if (nCurrent == nPortion)
+ return true;
+ nCurrent--;
+ }
+ return false;
+}
+
void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
{
pPortion->nHeight = 0;
pPortion->nFirstLineOffset = 0;
- if ( !pPortion->IsVisible() )
+ if (!pPortion->IsVisible() || isInEmptyClusterAtTheEnd(*pPortion))
return;
OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight" );
@@ -4416,7 +4435,6 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
pPortion->nHeight += scaleYSpacingValue(rULItem.GetLower()); // not in the last
}
-
if ( !nPortion || maStatus.ULSpaceSummation() )
return;
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index 79c943516bc7..464e9ed07550 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -392,53 +392,39 @@ bool ImpEditEngine::IsPageOverflow( ) const
void ImpEditEngine::FormatFullDoc()
{
- for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
- GetParaPortions()[nPortion]->MarkSelectionInvalid( 0 );
+ for ( sal_Int32 nPortion = 0; nPortion < maParaPortionList.Count(); nPortion++ )
+ maParaPortionList[nPortion]->MarkSelectionInvalid( 0 );
FormatDoc();
}
-void ImpEditEngine::FormatDoc()
+tools::Long ImpEditEngine::FormatParagraphs(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList)
{
- if (!IsUpdateLayout() || IsFormatting())
- return;
-
- mbIsFormatting = true;
-
- // Then I can also start the spell-timer...
- if ( GetStatus().DoOnlineSpelling() )
- StartOnlineSpellTimer();
-
+ sal_Int32 nParaCount = maParaPortionList.Count();
tools::Long nY = 0;
bool bGrow = false;
- // Here already, so that not always in CreateLines...
- bool bMapChanged = ImpCheckRefMapMode();
- sal_Int32 nParaCount = GetParaPortions().Count();
- o3tl::sorted_vector<sal_Int32> aRepaintParas;
- aRepaintParas.reserve(nParaCount);
-
- for ( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
+ for (sal_Int32 nParagraph = 0; nParagraph < nParaCount; nParagraph++)
{
- ParaPortion* pParaPortion = GetParaPortions()[nPara];
- if ( pParaPortion->MustRepaint() || ( pParaPortion->IsInvalid() && pParaPortion->IsVisible() ) )
+ ParaPortion& rParaPortion = maParaPortionList.getRef(nParagraph);
+ if (rParaPortion.MustRepaint() || (rParaPortion.IsInvalid() && rParaPortion.IsVisible()))
{
// No formatting should be necessary for MustRepaint()!
- if ( !pParaPortion->IsInvalid() || CreateLines( nPara, nY ) )
+ if (CreateLines(nParagraph, nY))
{
- if ( !bGrow && GetTextRanger() )
+ if (!bGrow && GetTextRanger())
{
// For a change in height all below must be reformatted...
- for ( sal_Int32 n = nPara+1; n < GetParaPortions().Count(); n++ )
+ for (sal_Int32 n = nParagraph + 1; n < nParaCount; n++)
{
- ParaPortion* pPP = GetParaPortions()[n];
- pPP->MarkSelectionInvalid( 0 );
- pPP->GetLines().Reset();
+ ParaPortion& rParaPortionToInvalidate = maParaPortionList.getRef(n);
+ rParaPortionToInvalidate.MarkSelectionInvalid(0);
+ rParaPortionToInvalidate.GetLines().Reset();
}
}
bGrow = true;
- if ( IsCallParaInsertedOrDeleted() )
+ if (IsCallParaInsertedOrDeleted())
{
- GetEditEnginePtr()->ParagraphHeightChanged( nPara );
+ GetEditEnginePtr()->ParagraphHeightChanged(nParagraph);
for (EditView* pView : aEditViews)
{
@@ -447,13 +433,90 @@ void ImpEditEngine::FormatDoc()
}
}
- pParaPortion->SetMustRepaint( false );
+ rParaPortion.SetMustRepaint(false);
}
- aRepaintParas.insert(nPara);
+ aRepaintParagraphList.insert(nParagraph);
}
- nY += pParaPortion->GetHeight();
+ nY += rParaPortion.GetHeight();
}
+ return nY;
+}
+
+namespace
+{
+constexpr std::array<ScalingParameters, 13> constScaleLevels =
+{
+ ScalingParameters{100.0, 100.0, 100.0, 90.0 },
+ ScalingParameters{ 92.5, 92.5, 100.0, 90.0 },
+ ScalingParameters{ 92.5, 92.5, 100.0, 80.0 },
+ ScalingParameters{ 85.0, 85.0, 100.0, 90.0 },
+ ScalingParameters{ 85.0, 85.0, 100.0, 80.0 },
+ ScalingParameters{ 77.5, 77.5, 100.0, 80.0 },
+ ScalingParameters{ 70.0, 70.0, 100.0, 80.0 },
+ ScalingParameters{ 62.5, 62.5, 100.0, 80.0 },
+ ScalingParameters{ 55.0, 55.0, 100.0, 80.0 },
+ ScalingParameters{ 47.5, 47.5, 100.0, 80.0 },
+ ScalingParameters{ 40.0, 40.0, 100.0, 80.0 },
+ ScalingParameters{ 32.5, 32.5, 100.0, 80.0 },
+ ScalingParameters{ 25.0, 25.0, 100.0, 80.0 },
+};
+
+} // end anonymous ns
+
+void ImpEditEngine::ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList)
+{
+ if (!maCustomScalingParameters.areValuesDefault())
+ maScalingParameters = maCustomScalingParameters;
+
+ tools::Long nHeight = FormatParagraphs(aRepaintParagraphList);
+ bool bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns);
+
+ size_t nCurrentScaleLevel = 0;
+ while (bOverflow && nCurrentScaleLevel < constScaleLevels.size())
+ {
+ // Clean-up and reset paragraphs
+ aRepaintParagraphList.clear();
+ for (auto& pParaPortionToInvalidate : maParaPortionList)
+ {
+ pParaPortionToInvalidate->GetLines().Reset();
+ pParaPortionToInvalidate->MarkSelectionInvalid(0);
+ pParaPortionToInvalidate->SetMustRepaint(true);
+ }
+
+ // Get new scaling parameters
+ maScalingParameters = constScaleLevels[nCurrentScaleLevel];
+
+ // Try again with different scaling factor
+ nHeight = FormatParagraphs(aRepaintParagraphList);
+ bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns);
+
+ // Increase scale level
+ nCurrentScaleLevel++;
+ }
+}
+
+void ImpEditEngine::FormatDoc()
+{
+ if (!IsUpdateLayout() || IsFormatting())
+ return;
+
+ mbIsFormatting = true;
+
+ // Then I can also start the spell-timer...
+ if (GetStatus().DoOnlineSpelling())
+ StartOnlineSpellTimer();
+
+ // Reserve, as it should match the current number of paragraphs
+ bool bMapChanged = ImpCheckRefMapMode();
+
+ o3tl::sorted_vector<sal_Int32> aRepaintParagraphList;
+ aRepaintParagraphList.reserve(maParaPortionList.Count());
+
+ if (maStatus.DoStretch())
+ ScaleContentToFitWindow(aRepaintParagraphList);
+ else
+ FormatParagraphs(aRepaintParagraphList);
aInvalidRect = tools::Rectangle(); // make empty
@@ -493,10 +556,10 @@ void ImpEditEngine::FormatDoc()
}
}
- if (!aRepaintParas.empty())
+ if (!aRepaintParagraphList.empty())
{
auto CombineRepaintParasAreas = [&](const LineAreaInfo& rInfo) {
- if (aRepaintParas.count(rInfo.nPortion))
+ if (aRepaintParagraphList.count(rInfo.nPortion))
aInvalidRect.Union(rInfo.aArea);
return CallbackResult::Continue;
};
@@ -1015,9 +1078,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY )
if (maStatus.DoStretch() && (fFontScalingX != 100.0))
nCurPos = basegfx::fround(double(nCurPos) * 100.0 / std::max(fFontScalingX, 1.0));
- short nAllSpaceBeforeText = static_cast< short >(rLRItem.GetTextLeft()/* + rLRItem.GetTextLeft()*/ + nSpaceBeforeAndMinLabelWidth);
- aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/, maEditDoc.GetDefTab() );
- aCurrentTab.nTabPos = scaleXFontValue(tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText/*rLRItem.GetTextLeft()*/));
+ short nAllSpaceBeforeText = short(rLRItem.GetTextLeft());
+ aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText , maEditDoc.GetDefTab() );
+ aCurrentTab.nTabPos = tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText);
aCurrentTab.bValid = false;
// Switch direction in R2L para...
@@ -4470,7 +4533,7 @@ void ImpEditEngine::setScalingParameters(ScalingParameters const& rScalingParame
}
bool bScalingChanged = maScalingParameters != aNewScalingParameters;
- maScalingParameters = aNewScalingParameters;
+ maCustomScalingParameters = maScalingParameters = aNewScalingParameters;
if (bScalingChanged && maStatus.DoStretch())
{