editeng/source/editeng/editeng.cxx | 16 +++ include/editeng/editeng.hxx | 5 - sd/CppunitTest_sd_textfitting_tests.mk | 79 ++++++++++++++++ sd/Module_sd.mk | 1 sd/qa/unit/TextFittingTest.cxx | 154 +++++++++++++++++++++++++++++++++ sd/qa/unit/data/TextFitting.odp |binary svx/source/svdraw/svdotext.cxx | 20 +++- 7 files changed, 272 insertions(+), 3 deletions(-)
New commits: commit 6c042848b688f64b3c56d65dd9dc5fe85412660a Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri May 5 15:34:38 2023 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sat May 6 14:38:32 2023 +0200 Change text auto-fit alg. to also increase the scaling When in edit mode, the text can be deleted, so the text box size can become smaller, but the auto-fit algorithm didn't take into account. In this case we already have the font and spacing scaling already set to a specific value and we need to find a scaling value where the margin is the smallest. This change also adds a test for the issue. Change-Id: I6c52f06dfbf5a1e582f7b31aceabf4736498ee90 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151412 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index 5b70a2c2288b..d263363253e1 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -2275,11 +2275,27 @@ void EditEngine::getGlobalSpacingScale(double& rX, double& rY) const pImpEditEngine->getSpacingScale(rX, rY); } +basegfx::B2DTuple EditEngine::getGlobalSpacingScale() const +{ + double x = 0.0; + double y = 0.0; + pImpEditEngine->getSpacingScale(x, y); + return {x, y}; +} + void EditEngine::getGlobalFontScale(double& rX, double& rY) const { pImpEditEngine->getFontScale(rX, rY); } +basegfx::B2DTuple EditEngine::getGlobalFontScale() const +{ + double x = 0.0; + double y = 0.0; + pImpEditEngine->getFontScale(x, y); + return {x, y}; +} + void EditEngine::setRoundFontSizeToPt(bool bRound) const { pImpEditEngine->setRoundToNearestPt(bRound); diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx index b3d67c1c472e..b31b77160ad5 100644 --- a/include/editeng/editeng.hxx +++ b/include/editeng/editeng.hxx @@ -16,7 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -// MyEDITENG, due to exported EditEng + #ifndef INCLUDED_EDITENG_EDITENG_HXX #define INCLUDED_EDITENG_EDITENG_HXX @@ -41,6 +41,7 @@ #include <tools/degree.hxx> #include <tools/long.hxx> #include <tools/fontenum.hxx> +#include <basegfx/tuple/b2dtuple.hxx> #include <editeng/eedata.hxx> #include <o3tl/typed_flags_set.hxx> @@ -418,7 +419,9 @@ public: void setGlobalScale(double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); void getGlobalSpacingScale(double& rX, double& rY) const; + basegfx::B2DTuple getGlobalSpacingScale() const; void getGlobalFontScale(double& rX, double& rY) const; + basegfx::B2DTuple getGlobalFontScale() const; void setRoundFontSizeToPt(bool bRound) const; diff --git a/sd/CppunitTest_sd_textfitting_tests.mk b/sd/CppunitTest_sd_textfitting_tests.mk new file mode 100644 index 000000000000..20e302d86793 --- /dev/null +++ b/sd/CppunitTest_sd_textfitting_tests.mk @@ -0,0 +1,79 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,sd_textfitting_tests)) + +$(eval $(call gb_CppunitTest_use_externals,sd_textfitting_tests,\ + boost_headers \ + libxml2 \ +)) + +$(eval $(call gb_CppunitTest_use_common_precompiled_header,sd_textfitting_tests)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sd_textfitting_tests, \ + sd/qa/unit/TextFittingTest \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sd_textfitting_tests, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + for \ + forui \ + i18nlangtag \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sd \ + sfx \ + sot \ + subsequenttest \ + svl \ + svt \ + svx \ + svxcore \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_set_include,sd_textfitting_tests,\ + -I$(SRCDIR)/sd/source/ui/inc \ + -I$(SRCDIR)/sd/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,sd_textfitting_tests)) +$(eval $(call gb_CppunitTest_use_ure,sd_textfitting_tests)) +$(eval $(call gb_CppunitTest_use_vcl,sd_textfitting_tests)) +$(eval $(call gb_CppunitTest_use_rdb,sd_textfitting_tests,services)) + +$(eval $(call gb_CppunitTest_use_custom_headers,sd_textfitting_tests,\ + officecfg/registry \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,sd_textfitting_tests)) + +$(eval $(call gb_CppunitTest_add_arguments,sd_textfitting_tests, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/sd/Module_sd.mk b/sd/Module_sd.mk index 93cf5e0dc6e8..9b7736a41a5f 100644 --- a/sd/Module_sd.mk +++ b/sd/Module_sd.mk @@ -49,6 +49,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sd,\ CppunitTest_sd_filter_eppt \ CppunitTest_sd_shape_import_export_tests \ CppunitTest_sd_a11y \ + CppunitTest_sd_textfitting_tests \ )) endif diff --git a/sd/qa/unit/TextFittingTest.cxx b/sd/qa/unit/TextFittingTest.cxx new file mode 100644 index 000000000000..5cbe8a6b9c69 --- /dev/null +++ b/sd/qa/unit/TextFittingTest.cxx @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <officecfg/Office/Common.hxx> + +#include "sdmodeltestbase.hxx" + +#include <com/sun/star/uno/Reference.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> + +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include <DrawDocShell.hxx> +#include <editeng/editeng.hxx> +#include <drawdoc.hxx> +#include <vcl/scheduler.hxx> +#include <svx/sdr/table/tablecontroller.hxx> +#include <sfx2/request.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svxids.hrc> +#include <editeng/eeitem.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <undo/undomanager.hxx> +#include <GraphicViewShell.hxx> +#include <sdpage.hxx> +#include <comphelper/base64.hxx> +#include <LayerTabBar.hxx> +#include <vcl/event.hxx> +#include <vcl/keycodes.hxx> +#include <svx/svdoashp.hxx> +#include <tools/gen.hxx> +#include <svx/view3d.hxx> +#include <svx/scene3d.hxx> +#include <svx/sdmetitm.hxx> +#include <unomodel.hxx> + +using namespace css; + +class TextFittingTest : public SdModelTestBase +{ +public: + TextFittingTest() + : SdModelTestBase("/sd/qa/unit/data/") + { + } +}; + +CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest) +{ + createSdImpressDoc("TextFitting.odp"); + + SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pXImpressDocument); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdPage* pPage = pViewShell->GetActualPage(); + auto pTextObject = DynCastSdrTextObj(pPage->GetObj(0)); + CPPUNIT_ASSERT(pTextObject); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetFontScale(), 1E-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetSpacingScale(), 1E-2); + + { + OutlinerParaObject* pOutlinerParagraphObject = pTextObject->GetOutlinerParaObject(); + const EditTextObject& aEdit = pOutlinerParagraphObject->GetTextObject(); + CPPUNIT_ASSERT_EQUAL(OUString(u"D1"), aEdit.GetText(0)); + CPPUNIT_ASSERT_EQUAL(OUString(u"D2"), aEdit.GetText(1)); + CPPUNIT_ASSERT_EQUAL(OUString(u"D3"), aEdit.GetText(2)); + } + + sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView1 = pViewShell1->GetView(); + Scheduler::ProcessEventsToIdle(); + pView1->SdrBeginTextEdit(pTextObject); + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + + auto* pOLV = pView1->GetTextEditOutlinerView(); + CPPUNIT_ASSERT(pOLV); + auto& rEditView = pOLV->GetEditView(); + auto* pEditEngine = rEditView.GetEditEngine(); + CPPUNIT_ASSERT(pEditEngine); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pEditEngine->GetParagraphCount()); + + // Add paragraph 4 + rEditView.SetSelection(ESelection(3, 0, 3, 0)); + rEditView.InsertText(u"\nD4"); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pEditEngine->GetParagraphCount()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(87.49, pEditEngine->getGlobalFontScale().getY(), 1E-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(90.0, pEditEngine->getGlobalSpacingScale().getY(), 1E-2); + + // Add paragraph 5 + rEditView.SetSelection(ESelection(4, 0, 4, 0)); + rEditView.InsertText(u"\nD5"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pEditEngine->GetParagraphCount()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(54.68, pEditEngine->getGlobalFontScale().getY(), 1E-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pEditEngine->getGlobalSpacingScale().getY(), 1E-2); + + // Add paragraph 6 + rEditView.SetSelection(ESelection(5, 0, 5, 0)); + rEditView.InsertText(u"\nD6"); + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pEditEngine->GetParagraphCount()); + + // Delete paragraph 6 + rEditView.SetSelection(ESelection(4, EE_TEXTPOS_MAX_COUNT, 5, EE_TEXTPOS_MAX_COUNT)); + rEditView.DeleteSelected(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pEditEngine->GetParagraphCount()); + + // Delete paragraph 5 + rEditView.SetSelection(ESelection(3, EE_TEXTPOS_MAX_COUNT, 4, EE_TEXTPOS_MAX_COUNT)); + rEditView.DeleteSelected(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pEditEngine->GetParagraphCount()); + + // Delete paragraph 4 + rEditView.SetSelection(ESelection(2, EE_TEXTPOS_MAX_COUNT, 3, EE_TEXTPOS_MAX_COUNT)); + rEditView.DeleteSelected(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pEditEngine->GetParagraphCount()); + + // not ideal - scaling should be 100%, but close enough + CPPUNIT_ASSERT_DOUBLES_EQUAL(99.05, pEditEngine->getGlobalFontScale().getY(), 1E-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pEditEngine->getGlobalSpacingScale().getY(), 1E-2); + + // are we still in text edit mode? + CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit()); + pView1->SdrEndTextEdit(); + CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetFontScale(), 1E-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetSpacingScale(), 1E-2); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/qa/unit/data/TextFitting.odp b/sd/qa/unit/data/TextFitting.odp new file mode 100644 index 000000000000..1d4d4fd7ef65 Binary files /dev/null and b/sd/qa/unit/data/TextFitting.odp differ diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index f2951787b551..a27e112d85cb 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -1303,7 +1303,11 @@ void SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size& else fCurrentFitFactor = double(rTextBoxSize.Height()) / aCurrentTextBoxSize.Height(); - if (fCurrentFitFactor >= 1.0) + double fInitialFontScaleY = 0.0; + double fInitialSpacing = 0.0; + rOutliner.getGlobalScale(o3tl::temporary(double()), fInitialFontScaleY, o3tl::temporary(double()), fInitialSpacing); + + if (fCurrentFitFactor >= 1.0 && fInitialFontScaleY >= 100.0 && fInitialSpacing >= 100.0) return; sal_Int32 nFontHeight = GetObjectItemSet().Get(EE_CHAR_FONTHEIGHT).GetHeight(); @@ -1313,9 +1317,21 @@ void SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size& double fMaxY = fMaxScale; double fBestFontScale = 0.0; - double fBestSpacing = fMaxScale; + double fBestSpacing = 100.0; double fBestFitFactor = fCurrentFitFactor; + if (fCurrentFitFactor >= 1.0) + { + fMinY = fInitialFontScaleY; + fBestFontScale = fInitialFontScaleY; + fBestSpacing = fInitialSpacing; + fBestFitFactor = fCurrentFitFactor; + } + else + { + fMaxY = std::min(fInitialFontScaleY, fMaxScale); + } + double fInTheMidle = 0.5; int iteration = 0;