diff --git a/cui/source/inc/paragrph.hxx b/cui/source/inc/paragrph.hxx index 51d49765ff15..4218f3091e3b 100644 --- a/cui/source/inc/paragrph.hxx +++ b/cui/source/inc/paragrph.hxx @@ -161,7 +161,6 @@ class SvxParaAlignTabPage : public SfxTabPage /// letter spacing std::unique_ptr m_xLabelLetterSpacing; - std::unique_ptr m_xLetterSpacing; std::unique_ptr m_xLetterSpacingMinimum; std::unique_ptr m_xLetterSpacingMaximum; @@ -171,9 +170,6 @@ class SvxParaAlignTabPage : public SfxTabPage DECL_LINK(WordSpacingHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(WordSpacingMinimumHdl_Impl, weld::MetricSpinButton&, void); DECL_LINK(WordSpacingMaximumHdl_Impl, weld::MetricSpinButton&, void); - DECL_LINK(LetterSpacingHdl_Impl, weld::MetricSpinButton&, void); - DECL_LINK(LetterSpacingMinimumHdl_Impl, weld::MetricSpinButton&, void); - DECL_LINK(LetterSpacingMaximumHdl_Impl, weld::MetricSpinButton&, void); void UpdateExample_Impl(); diff --git a/cui/source/tabpages/paragrph.cxx b/cui/source/tabpages/paragrph.cxx index b55863973c2a..5feaf5420286 100644 --- a/cui/source/tabpages/paragrph.cxx +++ b/cui/source/tabpages/paragrph.cxx @@ -1288,7 +1288,6 @@ SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon , m_xWordSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_WORD_SPACING_MIN"_ustr, FieldUnit::PERCENT)) , m_xWordSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_WORD_SPACING_MAX"_ustr, FieldUnit::PERCENT)) , m_xLabelLetterSpacing(m_xBuilder->weld_label(u"labelLetterSpacing"_ustr)) - , m_xLetterSpacing(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING"_ustr, FieldUnit::PERCENT)) , m_xLetterSpacingMinimum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MIN"_ustr, FieldUnit::PERCENT)) , m_xLetterSpacingMaximum(m_xBuilder->weld_metric_spin_button(u"spin_LETTER_SPACING_MAX"_ustr, FieldUnit::PERCENT)) { @@ -1334,12 +1333,6 @@ SvxParaAlignTabPage::SvxParaAlignTabPage(weld::Container* pPage, weld::DialogCon m_xWordSpacing->connect_value_changed(LINK(this, SvxParaAlignTabPage, WordSpacingHdl_Impl)); m_xWordSpacingMinimum->connect_value_changed(LINK(this, SvxParaAlignTabPage, WordSpacingMinimumHdl_Impl)); m_xWordSpacingMaximum->connect_value_changed(LINK(this, SvxParaAlignTabPage, WordSpacingMaximumHdl_Impl)); - - // Minimum <= Desired <= Maximum letter spacing - // apply these modifying the other values, if needed - m_xLetterSpacing->connect_value_changed(LINK(this, SvxParaAlignTabPage, LetterSpacingHdl_Impl)); - m_xLetterSpacingMinimum->connect_value_changed(LINK(this, SvxParaAlignTabPage, LetterSpacingMinimumHdl_Impl)); - m_xLetterSpacingMaximum->connect_value_changed(LINK(this, SvxParaAlignTabPage, LetterSpacingMaximumHdl_Impl)); } SvxParaAlignTabPage::~SvxParaAlignTabPage() @@ -1389,7 +1382,6 @@ bool SvxParaAlignTabPage::FillItemSet( SfxItemSet* rOutSet ) m_xWordSpacing->get_value_changed_from_saved() || m_xWordSpacingMinimum->get_value_changed_from_saved() || m_xWordSpacingMaximum->get_value_changed_from_saved() || - m_xLetterSpacing->get_value_changed_from_saved() || m_xLetterSpacingMinimum->get_value_changed_from_saved() || m_xLetterSpacingMaximum->get_value_changed_from_saved(); } @@ -1505,6 +1497,7 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) m_xLabelLetterSpacing->set_sensitive(true); // TODO add LetterSpacing (CharKern) and LetterSpacingMinimum m_xLetterSpacingMaximum->set_sensitive(true); + m_xLetterSpacingMinimum->set_sensitive(true); m_xLetterSpacingMinimum->set_value(rAdj.GetPropLetterSpacingMinimum(), FieldUnit::PERCENT); m_xLetterSpacingMaximum->set_value(rAdj.GetPropLetterSpacingMaximum(), FieldUnit::PERCENT); } @@ -1518,7 +1511,6 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) m_xWordSpacingMinimum->set_sensitive(false); m_xWordSpacingMaximum->set_sensitive(false); m_xLabelLetterSpacing->set_sensitive(false); - m_xLetterSpacing->set_sensitive(false); m_xLetterSpacingMinimum->set_sensitive(false); m_xLetterSpacingMaximum->set_sensitive(false); } @@ -1537,7 +1529,6 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) m_xWordSpacingMinimum->set_sensitive(false); m_xWordSpacingMaximum->set_sensitive(false); m_xLabelLetterSpacing->set_sensitive(false); - m_xLetterSpacing->set_sensitive(false); m_xLetterSpacingMinimum->set_sensitive(false); m_xLetterSpacingMaximum->set_sensitive(false); } @@ -1600,7 +1591,6 @@ void SvxParaAlignTabPage::Reset( const SfxItemSet* rSet ) m_xWordSpacing->save_value(); m_xWordSpacingMinimum->save_value(); m_xWordSpacingMaximum->save_value(); - m_xLetterSpacing->save_value(); m_xLetterSpacingMinimum->save_value(); m_xLetterSpacingMaximum->save_value(); @@ -1621,7 +1611,6 @@ void SvxParaAlignTabPage::ChangesApplied() m_xWordSpacing->save_value(); m_xWordSpacingMinimum->save_value(); m_xWordSpacingMaximum->save_value(); - m_xLetterSpacing->save_value(); m_xLetterSpacingMinimum->save_value(); m_xLetterSpacingMaximum->save_value(); } @@ -1639,9 +1628,8 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, AlignHdl_Impl, weld::Toggleable&, void) m_xWordSpacingMinimum->set_sensitive(bJustify); m_xWordSpacingMaximum->set_sensitive(bJustify); m_xLabelLetterSpacing->set_sensitive(bJustify); - // TODO implement LetterSpacing and LetterSpaceMinimum - m_xLetterSpacing->set_sensitive(false); - m_xLetterSpacingMinimum->set_sensitive(false); + // TODO visualize CharKerning with percentage + m_xLetterSpacingMinimum->set_sensitive(bJustify); m_xLetterSpacingMaximum->set_sensitive(bJustify); bool bLastLineIsBlock = m_xLastLineLB->get_active() == 2; @@ -1698,33 +1686,6 @@ IMPL_LINK_NOARG(SvxParaAlignTabPage, WordSpacingMaximumHdl_Impl, weld::MetricSpi m_xWordSpacing->set_value(nMaximum, FieldUnit::PERCENT); } -IMPL_LINK_NOARG(SvxParaAlignTabPage, LetterSpacingHdl_Impl, weld::MetricSpinButton&, void) -{ - sal_Int16 nDesired = m_xLetterSpacing->get_value(FieldUnit::PERCENT); - if (nDesired < m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT)) - m_xLetterSpacingMinimum->set_value(nDesired, FieldUnit::PERCENT); - if (nDesired > m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT)) - m_xLetterSpacingMaximum->set_value(nDesired, FieldUnit::PERCENT); -} - -IMPL_LINK_NOARG(SvxParaAlignTabPage, LetterSpacingMinimumHdl_Impl, weld::MetricSpinButton&, void) -{ - sal_Int16 nMinimum = m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT); - if (nMinimum > m_xLetterSpacing->get_value(FieldUnit::PERCENT)) - m_xLetterSpacing->set_value(nMinimum, FieldUnit::PERCENT); - if (nMinimum > m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT)) - m_xLetterSpacingMaximum->set_value(nMinimum, FieldUnit::PERCENT); -} - -IMPL_LINK_NOARG(SvxParaAlignTabPage, LetterSpacingMaximumHdl_Impl, weld::MetricSpinButton&, void) -{ - sal_Int16 nMaximum = m_xLetterSpacingMaximum->get_value(FieldUnit::PERCENT); - if (nMaximum < m_xLetterSpacingMinimum->get_value(FieldUnit::PERCENT)) - m_xLetterSpacingMinimum->set_value(nMaximum, FieldUnit::PERCENT); - if (nMaximum < m_xLetterSpacing->get_value(FieldUnit::PERCENT)) - m_xLetterSpacing->set_value(nMaximum, FieldUnit::PERCENT); -} - void SvxParaAlignTabPage::UpdateExample_Impl() { if (m_xLeft->get_active()) diff --git a/cui/uiconfig/ui/paragalignpage.ui b/cui/uiconfig/ui/paragalignpage.ui index 36bf63e7c379..451f6b6765cc 100644 --- a/cui/uiconfig/ui/paragalignpage.ui +++ b/cui/uiconfig/ui/paragalignpage.ui @@ -21,7 +21,7 @@ 10 - 500 + 0 -100 0 1 @@ -29,14 +29,7 @@ 500 - -100 - 0 - 1 - 10 - - - 500 - -100 + 0 0 1 10 @@ -556,7 +549,7 @@ True False - _Letter spacing: + _Letter spacing: True 0 @@ -574,7 +567,7 @@ adjustmentPercent4 - Adjusts the minimum letter spacing. Enter a number between -100% (no letter spacing) and 250% (two and a half times the width of the normal letter spacing). + Adjusts the minimum letter spacing. Enter a number between -100% and 0% (original letter spacing). @@ -584,33 +577,15 @@ - + True True True True adjustmentPercent5 - - - Adjusts the desired letter spacing. Enter a number between -100% (no letter spacing) and 250% (two and a half times the width of the normal letter spacing). - - - - - 2 - 2 - - - - - True - True - True - True - adjustmentPercent6 - Adjusts the maximum letter spacing. Enter a number between -100% (no letter spacing) and 250% (two and a half times the width of the normal letter spacing). + Adjusts the maximum letter spacing. Enter a number between 0% (original letter spacing) and 500% (letter spacing is five times the width of the space character). diff --git a/offapi/com/sun/star/style/ParagraphProperties.idl b/offapi/com/sun/star/style/ParagraphProperties.idl index 387aa569ae89..45bc14c6508e 100644 --- a/offapi/com/sun/star/style/ParagraphProperties.idl +++ b/offapi/com/sun/star/style/ParagraphProperties.idl @@ -514,6 +514,9 @@ published service ParagraphProperties /** specifies the desired word spacing as percentage value relative to the width of the space character. +

It takes a percent value between [0, 1000], where the original + word spacing is denoted by 100.

+ @see ParaWordSpacingMininum @see ParaWordSpacingMaximum @@ -525,6 +528,9 @@ published service ParagraphProperties /** specifies the minimum word spacing as percentage value relative to the width of the space character. +

It takes a percent value between [0, 1000], where the original + word spacing is denoted by 100.

+ @see ParaWordSpacing @see ParaWordSpacingMaximum @@ -536,6 +542,9 @@ published service ParagraphProperties /** specifies the maximum word spacing as percentage value relative to the width of the space character. +

It takes a percent value between [0, 1000], where the original + word spacing is denoted by 100.

+ @see ParaWordSpacing @see ParaWordSpacingMininum @@ -547,6 +556,9 @@ published service ParagraphProperties /** specifies the minimum letter spacing as percentage value relative to the width of the space character. +

It takes a percent value between [-100, 0], where the original + letter spacing is denoted by 0, and negative values mean its shrinking.

+ @see CharKerning @see ParaLetterSpacingMaximum @@ -558,6 +570,9 @@ published service ParagraphProperties /** specifies the maximum letter spacing as percentage value relative to the width of the space character. +

It takes a percent value between [0, 500], where the original + letter spacing is denoted by 0, and negative values mean its shrinking.

+ @see CharKerning @see ParaLetterSpacingMininum diff --git a/sw/qa/extras/layout/data/tdf167648_minimum.fodt b/sw/qa/extras/layout/data/tdf167648_minimum.fodt new file mode 100644 index 000000000000..7e81d76bd543 --- /dev/null +++ b/sw/qa/extras/layout/data/tdf167648_minimum.fodt @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur aliquam hendrerit. + + + diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx index cfc53c6eca62..6b259aa69bc4 100644 --- a/sw/qa/extras/layout/layout3.cxx +++ b/sw/qa/extras/layout/layout3.cxx @@ -545,7 +545,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf163149) // Assert we are using the expected position for the last char // This was 4673, now 4163, according to the fixed space shrinking - CPPUNIT_ASSERT_LESS(sal_Int32(4200), sal_Int32(pDXArray[45])); + CPPUNIT_ASSERT_LESS(sal_Int32(4250), sal_Int32(pDXArray[45])); break; } } @@ -573,8 +573,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf167648) auto pTextArrayAction = static_cast(pAction); auto pDXArray = pTextArrayAction->GetDXArray(); - // There should be 27 chars on the first line - // (tdf#164499 no space shrinking in lines with tabulation) + // There should be 27 characters on the first line CPPUNIT_ASSERT_EQUAL(size_t(27), pDXArray.size()); // Assert we are using the expected position for the @@ -593,6 +592,43 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf167648) } } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf167648_minimum) +{ + createSwDoc("tdf167648_minimum.fodt"); + // Ensure that all text portions are calculated before testing. + SwDocShell* pShell = getSwDocShell(); + + // Dump the rendering of the first page as an XML file. + std::shared_ptr xMetaFile = pShell->GetPreviewMetaFile(); + MetafileXmlDump dumper; + + xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile); + CPPUNIT_ASSERT(pXmlDoc); + + // Find the first text array action + for (size_t nAction = 0; nAction < xMetaFile->GetActionSize(); nAction++) + { + auto pAction = xMetaFile->GetAction(nAction); + if (pAction->GetType() == MetaActionType::TEXTARRAY) + { + auto pTextArrayAction = static_cast(pAction); + auto pDXArray = pTextArrayAction->GetDXArray(); + + // There should be 39 characters on the first line + // This was 27 characters, but setting minimum letter spacing + // to -25% allows more words in the line + CPPUNIT_ASSERT_EQUAL(size_t(39), pDXArray.size()); + + // Assert we are using the expected position for the + // second character of the first word with enlarged letter-spacing + // This was 286, now 266, according to the -25% minimum letter spacing + CPPUNIT_ASSERT_LESS(sal_Int32(270), sal_Int32(pDXArray[1])); + + break; + } + } +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf164499) { createSwDoc("tdf164499.docx"); diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx index 694a74361553..384c98baba8d 100644 --- a/sw/source/core/text/guess.cxx +++ b/sw/source/core/text/guess.cxx @@ -499,6 +499,18 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, SwTextFormatInfo &rInf, { m_nCutPos = rInf.GetTextBreak( nLineWidth, nMaxLen, nMaxComp, rInf.GetCachedVclData().get() ); + // tdf#167648 minimum letter spacing allows more text in the line + // TODO don't be greedy, allow only an extra word or word part + if ( const sal_Int16 nLetterSpacingMinimum = aAdjustItem.GetPropLetterSpacingMinimum() ) + { + SwTwips nExtraSpace = sal_Int32(m_nCutPos - rInf.GetIdx()) * + nSpaceWidth / 10.0 * nLetterSpacingMinimum / 100.0; + nLineWidth -= nExtraSpace; + // sum minimum word spacing and letter spacing + rInf.SetExtraSpace( rInf.GetExtraSpace() + nExtraSpace ); + m_nCutPos = rInf.GetTextBreak( nLineWidth, nMaxLen, nMaxComp, rInf.GetCachedVclData().get() ); + } + #if OSL_DEBUG_LEVEL > 1 if ( TextFrameIndex(COMPLETE_STRING) != m_nCutPos ) { diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx index 9c0f15d62451..8c297d4e300d 100644 --- a/sw/source/core/text/inftxt.cxx +++ b/sw/source/core/text/inftxt.cxx @@ -780,7 +780,7 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo aDrawInf.SetSmartTags( bTmpSmart ? m_pSmartTags : nullptr ); // set custom letter spacing (hyphenation hasn't been supported yet) - if ( rPor.GetLetterSpacing() > 0 ) + if ( rPor.GetLetterSpacing() != 0 ) aDrawInf.SetLetterSpacing( rPor.GetLetterSpacing() / sal_Int32(nLength) ); m_pFnt->DrawText_( aDrawInf ); diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx index 3a1a956f4059..c6230b18f5db 100644 --- a/sw/source/core/text/itradj.cxx +++ b/sw/source/core/text/itradj.cxx @@ -370,11 +370,11 @@ void SwTextAdjuster::CalcNewBlock( SwLineLayout *pCurrent, : 0; SwLinePortion *pPortion = pCurrent->GetFirstPortion(); - tools::Long nSpaceKern = pPortion->GetLetterSpacing() > 0 && pPortion->GetSpaceCount() + tools::Long nSpaceKern = pPortion->GetSpaceCount() ? tools::Long(pPortion->GetLetterSpacing()) / sal_Int32(pPortion->GetSpaceCount()) * 100 : 0; // set expansion in 1/100 twips/space - pCurrent->SetLLSpaceAdd( nSpaceSub ? nSpaceSub : (nSpaceAdd > nSpaceKern ? nSpaceAdd - nSpaceKern : 0), nSpaceIdx ); + pCurrent->SetLLSpaceAdd( nSpaceSub ? nSpaceSub + nSpaceKern : (nSpaceAdd > nSpaceKern ? nSpaceAdd - nSpaceKern : 0), nSpaceIdx ); pPos->Width( static_cast(pPos)->GetFixWidth() ); } else if (IsOneBlock() && nCharCnt > TextFrameIndex(1)) diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx index a95ec986ef7b..a8c4fac62a03 100644 --- a/sw/source/core/text/portxt.cxx +++ b/sw/source/core/text/portxt.cxx @@ -337,6 +337,33 @@ sal_uInt16 SwTextPortion::GetMaxComp(const SwTextFormatInfo& rInf) const : 0; } +void SwTextPortion::SetSpacing( SwTextFormatInfo &rInf, const TextFrameIndex nBreakPos, + const sal_Int32 nSpaces, const sal_Int16 nWidthOf10Spaces ) +{ + SvxAdjustItem aAdjustItem = + rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust(); + // width of a single expanded space without letter spacing and glyph scaling + float fSpaceNormal = + (rInf.GetLineWidth() - (rInf.GetBreakWidth() - nSpaces * nWidthOf10Spaces/10.0)) / nSpaces; + // the part to be removed: the previous width minus the maximum allowed space width + float fExpansionOverMax = + fSpaceNormal - nWidthOf10Spaces / 10.0 * aAdjustItem.GetPropWordSpacingMaximum() / 100.0; + ExtraSpaceSize( fExpansionOverMax > 0 ? fExpansionOverMax : 0 ); + int nLetterCount = sal_Int32(nBreakPos) - sal_Int32(rInf.GetIdx()); + // letter spacing/character to be added or substracted to get the desired word spacing + float fLetterSpacingForDesiredWordSpacing = + nLetterCount > 0 ? (((fSpaceNormal - nWidthOf10Spaces/10.0) * nSpaces) / nLetterCount) : 0; + // letter spacing/character allowed by maximum letter spacing + float fMaximumLetterSpacing = + nWidthOf10Spaces / 10.0 * aAdjustItem.GetPropLetterSpacingMaximum() / 100.0; + // final letter spacing/character based on the desired word spacing and maximum letter spacing + // TODO fix resolution applying 1/100 twips instead of 1 twip + SwTwips nLetterSpacing = std::min( fLetterSpacingForDesiredWordSpacing, fMaximumLetterSpacing ); + // full width of the extra (rounded) letter spacing within the line + SetLetterSpacing( SwTwips(nLetterSpacing * nLetterCount) ); + SetSpaceCount( TextFrameIndex(nSpaces) ); +} + bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) { // 5744: If only the hyphen does not fit anymore, we still need to wrap @@ -379,6 +406,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) bool bNoWordSpacing = aAdjustItem.GetPropWordSpacing() == 100 && aAdjustItem.GetPropWordSpacingMinimum() == 100 && aAdjustItem.GetPropWordSpacingMaximum() == 100 && + aAdjustItem.GetPropLetterSpacingMinimum() == 0 && aAdjustItem.GetPropLetterSpacingMaximum() == 0; // support old ODT documents, where only JustifyLinesWithShrinking was set bool bOldInterop = bInteropSmartJustify && bNoWordSpacing; @@ -430,20 +458,9 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) // calculate available word spacing for letter spacing, and for the word spacing indicator // for non-hyphenated single portion lines - // TODO: enable letter spacing for multiportion lines + // TODO: enable letter spacing for multiportion, also for hyphenated lines if ( !bOrigHyphenated && rInf.GetLineStart() == rInf.GetIdx() ) - { - // TODO calculate correct value for letter spacing of hyphenated lines - float fExpansionOverMax = fSpaceNormal - nSpaceWidth/10.0 * aAdjustItem.GetPropWordSpacingMaximum()/100.0; - ExtraSpaceSize( rInf.GetBreakWidth() > rInf.GetLineWidth()/2 && fExpansionOverMax > 0 ? fExpansionOverMax : 0); - int nLetterCount = sal_Int32(pGuess->BreakPos()) - sal_Int32(rInf.GetIdx()); - float fAvailableLetterSpacing = ((fSpaceNormal - nSpaceWidth/10.0) * nRealSpaces) / nLetterCount; - float fCustomLetterSpacing = nSpaceWidth/10.0 * aAdjustItem.GetPropLetterSpacingMaximum() / 100.0; - // TODO fix resolution applying 1/100 twips instead of 1 twip - SwTwips nLetterSpacing = std::min(fAvailableLetterSpacing, fCustomLetterSpacing); - SetLetterSpacing(SwTwips(nLetterSpacing * nLetterCount)); - SetSpaceCount(TextFrameIndex(nRealSpaces)); - } + SetSpacing(rInf, pGuess->BreakPos(), nRealSpaces, nSpaceWidth); // calculate line breaking with desired word spacing, also // if the desired word spacing is 100%, but there is a greater @@ -454,23 +471,12 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) pGuess.emplace(); bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine, aAdjustItem.GetPropWordSpacing(), nSpaceWidth ); sal_Int32 nSpacesInLine2 = rInf.GetLineSpaceCount( pGuess->BreakPos() ); - - if ( rInf.GetBreakWidth() <= rInf.GetLineWidth() ) + if ( aAdjustItem.GetPropLetterSpacingMinimum() < 0 || rInf.GetBreakWidth() <= rInf.GetLineWidth() ) { fSpaceNormal = (rInf.GetLineWidth() - (rInf.GetBreakWidth() - nSpacesInLine2 * nSpaceWidth/10.0))/nSpacesInLine2; - // TODO: enable letter spacing for multiportion lines + // TODO: enable letter spacing for multiportion, also for hyphenated lines if ( !bOrigHyphenated && rInf.GetLineStart() == rInf.GetIdx() ) - { - float fExpansionOverMax = fSpaceNormal - nSpaceWidth/10.0 * aAdjustItem.GetPropWordSpacingMaximum()/100.0; - ExtraSpaceSize( rInf.GetBreakWidth() > rInf.GetLineWidth()/2 && fExpansionOverMax > 0 ? fExpansionOverMax : 0); - int nLetterCount = sal_Int32(pGuess->BreakPos()) - sal_Int32(rInf.GetIdx()); - float fAvailableLetterSpacing = ((fSpaceNormal - nSpaceWidth/10.0) * nRealSpaces) / nLetterCount; - float fCustomLetterSpacing = nSpaceWidth/10.0 * aAdjustItem.GetPropLetterSpacingMaximum() / 100.0; - // TODO fix resolution applying 1/100 twips instead of 1 twip - SwTwips nLetterSpacing = std::min(fAvailableLetterSpacing, fCustomLetterSpacing); - SetLetterSpacing(SwTwips(nLetterSpacing * nLetterCount)); - SetSpaceCount(TextFrameIndex(nRealSpaces)); - } + SetSpacing(rInf, pGuess->BreakPos(), nSpacesInLine2, nSpaceWidth); } } @@ -539,16 +545,15 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) if ( z1 >= z0 || bIsPortion ) { pGuess = std::move(pGuess2); - ExtraSpaceSize(0); - SetLetterSpacing(0); + SetSpacing(rInf, pGuess->BreakPos(), nSpacesInLineShrink, nSpaceWidth); bFull = bFull2; } } else if ( bOldInterop ) { pGuess = std::move(pGuess2); + SetSpaceCount( TextFrameIndex(nSpacesInLineShrink)); ExtraSpaceSize(0); - SetLetterSpacing(0); bFull = bFull2; } } @@ -561,7 +566,6 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) { ExtraShrunkWidth( pGuess->BreakWidth() ); ExtraSpaceSize( 0 ); - SetLetterSpacing(0); } } } diff --git a/sw/source/core/text/portxt.hxx b/sw/source/core/text/portxt.hxx index 132efe86dd20..aff2680731f4 100644 --- a/sw/source/core/text/portxt.hxx +++ b/sw/source/core/text/portxt.hxx @@ -27,6 +27,8 @@ class SwTextPortion : public SwLinePortion { void BreakCut( SwTextFormatInfo &rInf, const SwTextGuess &rGuess ); void BreakUnderflow( SwTextFormatInfo &rInf ); + void SetSpacing( SwTextFormatInfo &rInf, const TextFrameIndex nBreakPos, + const sal_Int32 nSpaces, const sal_Int16 nWidthOf10Spaces ); bool Format_( SwTextFormatInfo &rInf ); public: