sw/qa/extras/layout/data/tdf126154.fodt | 8 sw/qa/extras/layout/data/tdf126154_minimum_shrinking.fodt | 245 ++++++++++++++ sw/qa/extras/layout/layout3.cxx | 91 +++++ sw/source/core/text/guess.cxx | 1 sw/source/core/text/portxt.cxx | 26 + 5 files changed, 364 insertions(+), 7 deletions(-)
New commits: commit 3dd2d7f449f13bec0f0a5c6e0c33a143409c3723 Author: László Németh <nem...@numbertext.org> AuthorDate: Thu May 8 17:37:42 2025 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Thu May 8 18:59:28 2025 +0200 tdf#126154 sw word spacing: fix greedy space shrinking If there are multiple possible break points allowed by minimum word spacing to avoid of hyphenation, choose the nearest to the desired word spacing, not the opposite. Note: fix also potential unit testing problems by using metric-equivalent Liberation Sans in the old test document tdf126154.fodt instead of Arial. Follow-up to commit 5a48070f5904c51dc9e7bbad4213d802fd4bc89b "tdf#126154 sw offapi xmloff cui: add min/max word spacing" and commit 7d6696757dcdfa3cee481ac7795a91b2b47da363 "tdf#159923 sw cui offapi xmloff: add custom word spacing". Change-Id: Ib08e1910997d6e0526edcdb9c8fef10d5c8614d4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185058 Tested-by: Jenkins Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/sw/qa/extras/layout/data/tdf126154.fodt b/sw/qa/extras/layout/data/tdf126154.fodt index ad4d775baa72..b8748d1f973d 100644 --- a/sw/qa/extras/layout/data/tdf126154.fodt +++ b/sw/qa/extras/layout/data/tdf126154.fodt @@ -152,8 +152,8 @@ </config:config-item-set> </office:settings> <office:font-face-decls> - <style:font-face style:name="Arial" svg:font-family="Arial"/> - <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Bold" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Liberation Sans" svg:font-family="Liberation Sans"/> + <style:font-face style:name="Liberation Sans1" svg:font-family="Liberation Sans" style:font-adornments="Bold" style:font-family-generic="swiss" style:font-pitch="variable"/> </office:font-face-decls> <office:styles> <style:default-style style:family="graphic"> @@ -175,7 +175,7 @@ </style:default-style> <style:style style:name="Standard" style:family="paragraph" style:class="text"> <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="0pt" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false" fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> - <style:text-properties style:font-name="Arial" fo:font-family="Arial" fo:font-size="10pt" fo:language="en" fo:country="GB"/> + <style:text-properties style:font-name="Liberation Sans" fo:font-family="Liberation Sans" fo:font-size="10pt" fo:language="en" fo:country="GB"/> </style:style> <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="7pt" style:contextual-spacing="false" fo:line-height="115%"/> @@ -183,7 +183,7 @@ </office:styles> <office:automatic-styles> <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Heading_20_5"> - <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Bold" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="12pt" fo:font-weight="bold" /> + <style:text-properties style:font-name="Liberation Sans1" fo:font-family="Liberation Sans" style:font-style-name="Bold" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="12pt" fo:font-weight="bold" /> </style:style> <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard"> <style:paragraph-properties fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="true"/> diff --git a/sw/qa/extras/layout/data/tdf126154_minimum_shrinking.fodt b/sw/qa/extras/layout/data/tdf126154_minimum_shrinking.fodt new file mode 100644 index 000000000000..38a62c9d5032 --- /dev/null +++ b/sw/qa/extras/layout/data/tdf126154_minimum_shrinking.fodt @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:c alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns: meta:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">9246</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">22368</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">12661</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">8156</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">7959</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">9246</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">22366</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">21906</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">172</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">true</config:config-item> + <config:config-item config:name="LegacySingleLineFontwork" config:type="boolean">true</config:config-item> + <config:config-item config:name="ConnectorUseSnapRect" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreBreakAfterMultilineField" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="BalanceSpacesAndIdeographicSpaces" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompGridMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="PaintHellOverHeaderFooter" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="NoNumberingShowFollowBy" config:type="boolean">false</config:config-item> + <config:config-item config:name="MinRowHeightInclBorder" config:type="boolean">false</config:config-item> + <config:config-item config:name="HyphenateURLs" config:type="boolean">true</config:config-item> + <config:config-item config:name="ImagePreferredDPI" config:type="int">0</config:config-item> + <config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item> + <config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item> + <config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordUlTrailSpace" config:type="boolean">false</config:config-item> + <config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">true</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="AutoFirstLineIndentDisregardLineSpace" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyTextAttrToEmptyLineAtEndOfParagraph" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="NoClippingWithWrapPolygon" config:type="boolean">false</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">true</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="JustifyLinesWithShrinking" config:type="boolean">false</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">585804</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="UseVariableWidthNBSP" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="NoGapAfterNoteNumber" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">true</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="IgnoreHiddenCharsForLineCalculation" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="DropCapPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">1072074</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:font-face-decls> + <style:font-face style:name="Liberation Sans" svg:font-family="Liberation Sans"/> + <style:font-face style:name="Liberation Serif" svg:font-family="Liberation Serif" style:font-adornments="Bold" style:font-family-generic="swiss" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="8.5pt" draw:shadow-offset-y="8.5pt" draw:start-line-spacing-horizontal="8.02pt" draw:start-line-spacing-vertical="8.02pt" draw:end-line-spacing-horizontal="8.02pt" draw:end-line-spacing-vertical="8.02pt" style:writing-mode="lr-tb" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0pt" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="10pt" fo:language="en" fo:country="US" style:letter-kerning="false" /> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="false" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="36pt" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="10pt" fo:language="en" fo:country="US" style:letter-kerning="false" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="no-limit" loext:hyphenation-zone="no-limit"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="0pt" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false" fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:font-name="Liberation Sans" fo:font-family="Liberation Sans" fo:font-size="10pt" fo:language="en" fo:country="GB"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="7pt" style:contextual-spacing="false" fo:line-height="115%"/> + </style:style> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Heading_20_5"> + <style:text-properties style:font-name="Liberation Serif" fo:font-family="Liberation Serif" style:font-style-name="Bold" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="12pt" fo:font-weight="bold" /> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard"> + <style:paragraph-properties fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="true"/> + <style:text-properties officeooo:rsid="000f3b24" officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" loext:hyphenation-compound-remain-char-count="2"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard"> + <style:paragraph-properties fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="true" loext:word-spacing-minimum="80%"/> + <style:text-properties officeooo:rsid="000f3b24" officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" loext:hyphenation-compound-remain-char-count="2"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Standard"> + <style:paragraph-properties fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" loext:hyphenation-keep-type="column" loext:hyphenation-keep-line="true" loext:word-spacing-minimum="80%" loext:word-spacing-maximum="133%"/> + <style:text-properties officeooo:rsid="000f3b24" officeooo:paragraph-rsid="00105bca" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="4" loext:hyphenation-zone="no-limit" loext:hyphenation-compound-remain-char-count="2"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00105bca"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="419.56pt" fo:page-height="595.3pt" style:num-format="1" style:print-orientation="portrait" fo:margin-top="21.6pt" fo:margin-bottom="14.4pt" fo:margin-left="36pt" fo:margin-right="36pt" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="31" style:layout-grid-base-height="18pt" style:layout-grid-ruby-height="0pt" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0pt" loext:margin-gutter="0pt"> + <style:footnote-sep style:width="0.51pt" style:distance-before-sep="2.86pt" style:distance-after-sep="2.86pt" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"> + <style:drawing-page-properties draw:background-size="full"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text> + <text:p text:style-name="P1">Only desired word spacing (100%, 100%, 100%)</text:p> + <text:p text:style-name="P2">,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P2">,,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P1">Minimum word spacing (80%, 100%, 100%)</text:p> + <text:p text:style-name="P3">,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P3">,,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P1">Minimum and maximum word spacing (80%, 100%, 133%)</text:p> + <text:p text:style-name="P4">,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + <text:p text:style-name="P4">,,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum c on sequat mi quis pretium semper.</text:p> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx index 1920c4a78360..8bfba150d5e5 100644 --- a/sw/qa/extras/layout/layout3.cxx +++ b/sw/qa/extras/layout/layout3.cxx @@ -1056,6 +1056,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf126154) assertXPath( pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]", "portion", u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + // This was "... bulum c" (more shrinking, than needed to remove hyphenation) assertXPath( pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[1]", "portion", u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); @@ -1081,6 +1082,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf126154) assertXPath( pXmlDoc, "/root/page[1]/body/txt[18]/SwParaPortion/SwLineLayout[1]", "portion", u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + // This was "... bulum c" (more shrinking, than needed to remove hyphenation) assertXPath( pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[1]", "portion", u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); @@ -1123,6 +1125,95 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf106234) "width", u"7882"); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf126154_minimum_shrinking) +{ + // minimum, desired and maximum word spacing + uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator(); + if (!xHyphenator->hasLocale(lang::Locale(u"en"_ustr, u"US"_ustr, OUString()))) + return; + + createSwDoc("tdf126154_minimum_shrinking.fodt"); + // Ensure that all text portions are calculated before testing. + SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell(); + CPPUNIT_ASSERT(pViewShell); + pViewShell->Reformat(); + + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + // only desired word space: 100%, 100%, 100% + // 5 lines are hyphenated + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout[1]", "portion", + u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout[1]", "portion", + u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti "); + + // also minimum word space: 80%, 100%, 100% + // only a single line is hyphenated from the previous ones + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout[1]", "portion", + u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout[1]", "portion", + u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[14]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[15]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bu"); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[16]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti "); + + // minimum, desired and maximum word spacing: 80%, 100%, 133% + // no hyphenation in the same text: hyphenation of all the short words are limited + // by the minimum and maximum word spacing settings + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[18]/SwParaPortion/SwLineLayout[1]", "portion", + u",, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[19]/SwParaPortion/SwLineLayout[1]", "portion", + u",,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[20]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[21]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath(pXmlDoc, "/root/page[1]/body/txt[22]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + u"Vesti bulum "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[23]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti "); + assertXPath( + pXmlDoc, "/root/page[1]/body/txt[24]/SwParaPortion/SwLineLayout[1]", "portion", + u",,,,,,,, , , , , , , , Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vesti "); +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf155324) { createSwDoc("tox-update-wrong-pages.odt"); diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx index 4740244139b7..6b833ed395ec 100644 --- a/sw/source/core/text/guess.cxx +++ b/sw/source/core/text/guess.cxx @@ -298,6 +298,7 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf, bool bHyph = rInf.IsHyphenate() && !rInf.IsHyphForbud() && // disable hyphenation at minimum word spacing + // (and at weighted word spacing between minimum and desired word spacing) !( nPropWordSpacing < aAdjustItem.GetPropWordSpacing() ); // disable hyphenation according to hyphenation-keep and hyphenation-keep-type, diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx index 661e0ae883b4..e824d0c102da 100644 --- a/sw/source/core/text/portxt.cxx +++ b/sw/source/core/text/portxt.cxx @@ -421,17 +421,37 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) pGuess.emplace(); bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine, aAdjustItem.GetPropWordSpacing() ); } - if ( bWordSpacingMinimum ) + if ( bWordSpacingMinimum && pGuess->HyphWord().is() && pGuess->BreakPos() > rInf.GetLineStart() ) { std::optional<SwTextGuess> pGuess2(std::in_place); SwTwips nOldExtraSpace = rInf.GetExtraSpace(); // break the line after the hyphenated word, if it's possible // (hyphenation is disabled in Guess(), when called with GetPropWordSpacingMinimum()) - // FIXME: if there are multiple possible break points allowed by minimum - // word spacing, choose the nearest to the desired word spacing, not the opposite bool bFull2 = !pGuess2->Guess( *this, rInf, Height(), nSpacesInLine, aAdjustItem.GetPropWordSpacingMinimum() ); if ( pGuess2->BreakWidth() > nOldWidth ) { + // instead of the maximum shrinking, break after the word which was hyphenated before + for (sal_Int32 i = sal_Int32(pGuess->BreakPos()); i < sal_Int32(pGuess2->BreakPos()); ++i) + { + sal_Unicode cChar = rInf.GetText()[i]; + // first space after the hyphenated word, and it's not the chosen one + if ( cChar == CH_BLANK ) + { + // using a weighted word spacing, try to break the line after the hyphenated word + sal_Int32 nOldBreak = sal_Int32(pGuess2->BreakPos()) - sal_Int32(pGuess->BreakPos()); + sal_Int32 nNewBreak = i - sal_Int32(pGuess->BreakPos()); + SwTwips nWeightedSpacing = aAdjustItem.GetPropWordSpacingMinimum() * (1.0 * nNewBreak/nOldBreak) + + aAdjustItem.GetPropWordSpacing() * (1.0 * (nOldBreak - nNewBreak)/nOldBreak); + std::optional<SwTextGuess> pGuess3(std::in_place); + pGuess3->Guess( *this, rInf, Height(), nSpacesInLine, nWeightedSpacing ); + if ( pGuess3->BreakWidth() > nOldWidth ) + { + pGuess2.emplace(); + pGuess2 = std::move(pGuess3); + } + break; + } + } pGuess = std::move(pGuess2); bFull = bFull2; }