Related: tdf#163590 apply the autofit scales stored in pptx

A PPTX shape keeps the fit the file was saved with until its text is
edited, and after that it is fitted by our own rules.

The fontScale and lnSpcReduction of a normAutofit never reached the
shape, for three reasons.

Import passed fractions to the TextFitToSizeFontScale and
TextFitToSizeSpacingScale properties, which are percentages.

A missing lnSpcReduction was read as 100000, a full reduction,
instead of 0.

When both properties were set in one setPropertyValues call along
with TextFitToSize, the collected fit item was applied last and
overwrote the scales.

Change-Id: I6b7fcfb6a1822f289f18b8ce77e78526a80f8944
Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/13539
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit c6938c35aa527883e2fd867f36e22c396601d376)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211506
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Caolán McNamara
2026-09-28 14:01:41 +02:00
committed by Xisco Fauli
parent 3c72c42f26
commit 370e262391
6 changed files with 68 additions and 19 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ struct TextBodyProperties
OUString msPrst;
/// Normal autofit: font scale (default: 100%).
sal_Int32 mnFontScale = 100000;
sal_Int32 mnSpacingScale = 100000;
sal_Int32 mnSpacingReduction = 0;
OUString msHorzOverflow;
std::optional< sal_Int32 > moVertOverflow{};
@@ -238,9 +238,10 @@ ContextHandlerRef TextBodyPropertiesContext::onCreateContext( sal_Int32 aElement
mrTextBodyProp.maPropertyMap.setProperty( PROP_TextFitToSize, TextFitToSizeType_AUTOFIT);
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextAutoGrowHeight, false);
mrTextBodyProp.mnFontScale = rAttribs.getInteger(XML_fontScale, 100000);
mrTextBodyProp.mnSpacingScale = rAttribs.getInteger(XML_lnSpcReduction, 100000);
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeFontScale, mrTextBodyProp.mnFontScale / 100000.0);
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeSpacingScale, 1.0 - mrTextBodyProp.mnSpacingScale / 100000.0);
mrTextBodyProp.mnSpacingReduction = rAttribs.getInteger(XML_lnSpcReduction, 0);
// The two properties are percentages.
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeFontScale, mrTextBodyProp.mnFontScale / 1000.0);
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeSpacingScale, 100.0 - mrTextBodyProp.mnSpacingReduction / 1000.0);
break;
}
case A_TOKEN( spAutoFit ):
+33
View File
@@ -13,6 +13,8 @@
#include <svx/svdview.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editobj.hxx>
#include <svx/sdtfsitm.hxx>
#include <svx/svddef.hxx>
#include <Outliner.hxx>
#include <DrawDocShell.hxx>
#include <unomodel.hxx>
@@ -203,6 +205,37 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTestBulletDifferenceViewAndEdit)
CPPUNIT_ASSERT_EQUAL(false, pView->IsTextEdit());
}
CPPUNIT_TEST_FIXTURE(TextFittingTest, testStoredFitKeptUntilEdited)
{
// The first slide stores a fit of 55 percent font with 20 percent less line spacing, though
// its text fits at full size. The stored fit is shown until the text is edited, and then the
// text is fitted afresh.
createSdImpressDoc("pptx/TextFittingStored.pptx");
auto pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
auto pBody = DynCastSdrTextObj(pViewShell->GetActualPage()->GetObj(1));
CPPUNIT_ASSERT(pBody);
const SdrTextFitToSizeTypeItem& rStored = pBody->GetMergedItem(SDRATTR_TEXT_FITTOSIZE);
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.55, rStored.getFontScale(), 1E-4);
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.8, rStored.getSpacingScale(), 1E-4);
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.55, pBody->GetFontScale(), 1E-4);
CPPUNIT_ASSERT_DOUBLES_EQUAL(0.8, pBody->GetSpacingScale(), 1E-4);
SdrView* pView = pViewShell->GetView();
Scheduler::ProcessEventsToIdle();
pView->SdrBeginTextEdit(pBody);
CPPUNIT_ASSERT(pView->IsTextEdit());
EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
rEditView.SetSelection(ESelection(0, 0));
rEditView.InsertText(u"x"_ustr);
pView->SdrEndTextEdit();
CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, pBody->GetFontScale(), 1E-4);
CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, pBody->GetSpacingScale(), 1E-4);
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Binary file not shown.
+14
View File
@@ -28,6 +28,8 @@
#include <svl/itemset.hxx>
#include <editeng/eeitem.hxx>
#include <svx/sdtfchim.hxx>
#include <svx/sdtfsitm.hxx>
#include <svx/svddef.hxx>
#include <textchain.hxx>
#include <svx/annotation/ObjectAnnotationData.hxx>
@@ -287,6 +289,18 @@ void SdrTextObj::EndTextEdit(SdrOutliner& rOutl)
SetOutlinerParaObject(std::move(pNewText));
}
// The fit stored with the shape belongs to the text before the edit, so fit afresh.
if (IsAutoFit())
{
SdrTextFitToSizeTypeItem aItem(GetObjectItem(SDRATTR_TEXT_FITTOSIZE));
if (aItem.getFontScale() != 0.0 || aItem.getSpacingScale() != 0.0)
{
aItem.setFontScale(0.0);
aItem.setSpacingScale(0.0);
SetObjectItem(aItem);
}
}
if (isAnnotationObject())
{
auto xTextAPI(getAnnotationData()->mxAnnotation->getTextApiObject());
+16 -15
View File
@@ -2341,26 +2341,27 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn
}
case OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE:
{
double fScale = 0.0;
if (rValue >>= fScale)
{
SdrTextFitToSizeTypeItem aItem(pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
aItem.setFontScale(fScale / 100.0);
pSdrObject->SetMergedItem(aItem);
return true;
}
break;
}
case OWN_ATTR_TEXTFITTOSIZE_SPACING_SCALE:
{
double fScale = 0.0;
if (rValue >>= fScale)
{
SdrTextFitToSizeTypeItem aItem(pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
aItem.setSpacingScale(fScale / 100.0);
pSdrObject->SetMergedItem(aItem);
// A multi-property call may already hold the fit item to apply at the end.
std::optional<SfxItemSet>& rCollected = mpImpl->moItemSet;
const bool bCollected = mbIsMultiPropertyCall && rCollected
&& rCollected->GetItemState(SDRATTR_TEXT_FITTOSIZE)
== SfxItemState::SET;
SdrTextFitToSizeTypeItem aItem(
bCollected ? rCollected->Get(SDRATTR_TEXT_FITTOSIZE)
: pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
if (pProperty->nWID == OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE)
aItem.setFontScale(fScale / 100.0);
else
aItem.setSpacingScale(fScale / 100.0);
if (bCollected)
rCollected->Put(aItem);
else
pSdrObject->SetMergedItem(aItem);
return true;
}
break;