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 <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl 2023-05-05 15:34:38 +09:00 committed by Tomaž Vajngerl
parent 6868a857fc
commit 6c042848b6
7 changed files with 272 additions and 3 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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:

View file

@ -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

View file

@ -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: */

Binary file not shown.

View file

@ -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;