vcl/inc/ImplLayoutArgs.hxx | 8 ++---- vcl/inc/sallayout.hxx | 10 +++----- vcl/source/gdi/CommonSalLayout.cxx | 15 ++++-------- vcl/source/gdi/sallayout.cxx | 20 ++++++++-------- vcl/source/outdev/text.cxx | 46 ++++++++++--------------------------- vcl/source/text/ImplLayoutArgs.cxx | 22 ++++------------- 6 files changed, 41 insertions(+), 80 deletions(-)
New commits: commit 9cabb7ca71dfc426b9925300c4214f05399bfd12 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Aug 19 20:54:14 2022 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Sat Aug 20 13:06:09 2022 +0200 always transport the text dxarray as doubles when rendering continue to do rounding to integer, just transported as double, unless the opt-in TextRenderModeForResolutionIndependentLayout is set, so this is not intended to create visible changes though nRunAdvance = static_cast<tools::Long>(nRunAdvance*fUnitMul + 0.5); becomes nRunAdvance = nRunAdvance * fUnitMul; in MultiSalLayout::ImplAdjustMultiLayout which might create a difference, but it is in the glyph fallback case where things are a last ditch effort already Change-Id: Iebd4ff9a602d0fa29a5253d73e6372d274d0c8c9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138565 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx index 105a4e2d8961..381d09185563 100644 --- a/vcl/inc/ImplLayoutArgs.hxx +++ b/vcl/inc/ImplLayoutArgs.hxx @@ -35,8 +35,7 @@ public: vcl::text::TextLayoutCache const* m_pTextLayoutCache; // positioning related inputs - const DeviceCoordinate* mpDXArray; // in integer pixel units - const double* mpAltNaturalDXArray; // in floating point pixel units + const double* mpNaturalDXArray; // in floating point pixel units const sal_Bool* mpKashidaArray; DeviceCoordinate mnLayoutWidth; // in pixel units Degree10 mnOrientation; // in 0-3600 system @@ -49,8 +48,7 @@ public: LanguageTag aLanguageTag, vcl::text::TextLayoutCache const* pLayoutCache); void SetLayoutWidth(DeviceCoordinate nWidth); - void SetDXArray(const DeviceCoordinate* pDXArray); - void SetAltNaturalDXArray(const double* pDXArray); + void SetNaturalDXArray(const double* pDXArray); void SetKashidaArray(const sal_Bool* pKashidaArray); void SetOrientation(Degree10 nOrientation); @@ -58,7 +56,7 @@ public: bool GetNextPos(int* nCharPos, bool* bRTL); bool GetNextRun(int* nMinRunPos, int* nEndRunPos, bool* bRTL); void AddFallbackRun(int nMinRunPos, int nEndRunPos, bool bRTL); - bool HasDXArray() const { return mpDXArray || mpAltNaturalDXArray; } + bool HasDXArray() const { return mpNaturalDXArray; } // methods used by BiDi and glyph fallback bool HasFallbackRun() const; diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index b49c1c663ee4..165a6170bbc2 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -82,10 +82,9 @@ public: void SetIncomplete(bool bIncomplete); - template<typename DC> void ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, vcl::text::ImplLayoutArgs& rMultiArgs, - const DC* pMultiDXArray); + const double* pMultiDXArray); virtual ~MultiSalLayout() override; @@ -101,10 +100,10 @@ private: class VCL_DLLPUBLIC GenericSalLayout : public SalLayout { - template<typename DC> friend void MultiSalLayout::ImplAdjustMultiLayout( + friend void MultiSalLayout::ImplAdjustMultiLayout( vcl::text::ImplLayoutArgs& rArgs, vcl::text::ImplLayoutArgs& rMultiArgs, - const DC* pMultiDXArray); + const double* pMultiDXArray); public: GenericSalLayout(LogicalFontInstance&); @@ -142,8 +141,7 @@ private: GenericSalLayout( const GenericSalLayout& ) = delete; GenericSalLayout& operator=( const GenericSalLayout& ) = delete; - template<typename DC> - void ApplyDXArray(const DC*, const sal_Bool*); + void ApplyDXArray(const double*, const sal_Bool*); void Justify(DeviceCoordinate nNewWidth); void ApplyAsianKerning(const OUString& rStr); diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index eff9dab9acbb..4072a47d7109 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -196,10 +196,8 @@ void GenericSalLayout::AdjustLayout(vcl::text::ImplLayoutArgs& rArgs) { SalLayout::AdjustLayout(rArgs); - if (rArgs.mpAltNaturalDXArray) // Used when "TextRenderModeForResolutionIndependentLayout" is set - ApplyDXArray(rArgs.mpAltNaturalDXArray, rArgs.mpKashidaArray); - else if (rArgs.mpDXArray) // Normal case - ApplyDXArray(rArgs.mpDXArray, rArgs.mpKashidaArray); + if (rArgs.mpNaturalDXArray) + ApplyDXArray(rArgs.mpNaturalDXArray, rArgs.mpKashidaArray); else if (rArgs.mnLayoutWidth) Justify(rArgs.mnLayoutWidth); // apply asian kerning if the glyphs are not already formatted @@ -653,12 +651,11 @@ void GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths) // justification). // - pKashidaArray: is the places where kashidas are inserted (for Arabic // justification). The number of kashidas is calculated from the pDXArray. -template<typename DC> -void GenericSalLayout::ApplyDXArray(const DC* pDXArray, const sal_Bool* pKashidaArray) +void GenericSalLayout::ApplyDXArray(const double* pDXArray, const sal_Bool* pKashidaArray) { int nCharCount = mnEndCharPos - mnMinCharPos; std::vector<DeviceCoordinate> aOldCharWidths; - std::unique_ptr<DC[]> const pNewCharWidths(new DC[nCharCount]); + std::unique_ptr<double[]> const pNewCharWidths(new double[nCharCount]); // Get the natural character widths (i.e. before applying DX adjustments). GetCharWidths(aOldCharWidths); @@ -677,7 +674,7 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, const sal_Bool* pKashida std::map<size_t, DeviceCoordinate> pKashidas; // The accumulated difference in X position. - DC nDelta = 0; + double nDelta = 0; // Apply the DX adjustments to glyph positions and widths. size_t i = 0; @@ -686,7 +683,7 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, const sal_Bool* pKashida // Accumulate the width difference for all characters corresponding to // this glyph. int nCharPos = m_GlyphItems[i].charPos() - mnMinCharPos; - DC nDiff = 0; + double nDiff = 0; for (int j = 0; j < m_GlyphItems[i].charCount(); j++) nDiff += pNewCharWidths[nCharPos + j] - aOldCharWidths[nCharPos + j]; diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index cf74b3efdb8f..eca07148ed53 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -660,6 +660,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) SalLayout::AdjustLayout( rArgs ); vcl::text::ImplLayoutArgs aMultiArgs = rArgs; std::vector<DeviceCoordinate> aJustificationArray; + std::vector<double> aNaturalJustificationArray; if( !rArgs.HasDXArray() && rArgs.mnLayoutWidth ) { @@ -721,21 +722,20 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) } } - // change the mpDXArray temporarily (just for the justification) - aMultiArgs.mpDXArray = aJustificationArray.data(); + aNaturalJustificationArray.reserve(aJustificationArray.size()); + for (DeviceCoordinate a : aJustificationArray) + aNaturalJustificationArray.push_back(a); + // change the DXArray temporarily (just for the justification) + aMultiArgs.mpNaturalDXArray = aNaturalJustificationArray.data(); } } - if (aMultiArgs.mpAltNaturalDXArray) - ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpAltNaturalDXArray); - else - ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpDXArray); + ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpNaturalDXArray); } -template<typename DC> void MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, vcl::text::ImplLayoutArgs& rMultiArgs, - const DC* pMultiDXArray) + const double* pMultiDXArray) { // Compute rtl flags, since in some scripts glyphs/char order can be // reversed for a few character sequences e.g. Myanmar @@ -865,7 +865,7 @@ void MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, } // skip to end of layout run and calculate its advance width - DC nRunAdvance = 0; + double nRunAdvance = 0; bool bKeepNotDef = (nFBLevel >= nLevel); for(;;) { @@ -976,7 +976,7 @@ void MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, // the measured width is still in fallback font units // => convert it to base level font units if( n > 0 ) // optimization: because (fUnitMul==1.0) for (n==0) - nRunAdvance = static_cast<tools::Long>(nRunAdvance*fUnitMul + 0.5); + nRunAdvance = nRunAdvance * fUnitMul; } // calculate new x position (in base level units) diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 06f43fa2d3ea..d2c8855a2543 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -1356,7 +1356,6 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, OUString aStr = rOrigStr; - // convert from logical units to physical units // recode string if needed if( mpFontInstance->mpConversion ) { mpFontInstance->mpConversion->RecodeString( aStr, 0, aStr.getLength() ); @@ -1367,6 +1366,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, DeviceCoordinate nPixelWidth = static_cast<DeviceCoordinate>(nLogicalWidth); if( nLogicalWidth && mbMap ) { + // convert from logical units to physical units nPixelWidth = LogicWidthToDeviceCoordinate( nLogicalWidth ); } @@ -1375,59 +1375,39 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, bool bTextRenderModeForResolutionIndependentLayout(false); DeviceCoordinate nEndGlyphCoord(0); - std::unique_ptr<DeviceCoordinate[]> xDXPixelArray; std::unique_ptr<double[]> xNaturalDXPixelArray; if( !pDXArray.empty() ) { - DeviceCoordinate* pDXPixelArray(nullptr); + xNaturalDXPixelArray.reset(new double[nLen]); + if (mbMap) { + // convert from logical units to font units if (GetTextRenderModeForResolutionIndependentLayout()) { + // without rounding, keeping accuracy for lower levels bTextRenderModeForResolutionIndependentLayout = true; - - // convert from logical units to font units using a temporary array - xNaturalDXPixelArray.reset(new double[nLen]); - for (int i = 0; i < nLen; ++i) xNaturalDXPixelArray[i] = ImplLogicWidthToDeviceFontWidth(pDXArray[i]); - aLayoutArgs.SetAltNaturalDXArray(xNaturalDXPixelArray.get()); - nEndGlyphCoord = std::lround(xNaturalDXPixelArray[nLen - 1]); } else { - // convert from logical units to font units using a temporary array - xDXPixelArray.reset(new DeviceCoordinate[nLen]); - pDXPixelArray = xDXPixelArray.get(); + // with rounding // using base position for better rounding a.k.a. "dancing characters" DeviceCoordinate nPixelXOfs2 = LogicWidthToDeviceCoordinate(rLogicalPos.X() * 2); - for( int i = 0; i < nLen; ++i ) - { - pDXPixelArray[i] = (LogicWidthToDeviceCoordinate((rLogicalPos.X() + pDXArray[i]) * 2) - nPixelXOfs2) / 2; - } - - aLayoutArgs.SetDXArray(pDXPixelArray); - nEndGlyphCoord = pDXPixelArray[nLen - 1]; + for (int i = 0; i < nLen; ++i) + xNaturalDXPixelArray[i] = (LogicWidthToDeviceCoordinate((rLogicalPos.X() + pDXArray[i]) * 2) - nPixelXOfs2) / 2; } - } else { -#if VCL_FLOAT_DEVICE_PIXEL - xDXPixelArray.reset(new DeviceCoordinate[nLen]); - pDXPixelArray = xDXPixelArray.get(); - for( int i = 0; i < nLen; ++i ) - { - pDXPixelArray[i] = pDXArray[i]; - } -#else /* !VCL_FLOAT_DEVICE_PIXEL */ - pDXPixelArray = const_cast<DeviceCoordinate*>(pDXArray.data()); -#endif /* !VCL_FLOAT_DEVICE_PIXEL */ - - aLayoutArgs.SetDXArray(pDXPixelArray); - nEndGlyphCoord = pDXPixelArray[nLen - 1]; + for(int i = 0; i < nLen; ++i) + xNaturalDXPixelArray[i] = pDXArray[i]; } + + aLayoutArgs.SetNaturalDXArray(xNaturalDXPixelArray.get()); + nEndGlyphCoord = std::lround(xNaturalDXPixelArray[nLen - 1]); } if (!pKashidaArray.empty()) diff --git a/vcl/source/text/ImplLayoutArgs.cxx b/vcl/source/text/ImplLayoutArgs.cxx index 45b951a9845d..943de7d2eb75 100644 --- a/vcl/source/text/ImplLayoutArgs.cxx +++ b/vcl/source/text/ImplLayoutArgs.cxx @@ -37,8 +37,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int nMinCharPos, int nEndCh , mnMinCharPos(nMinCharPos) , mnEndCharPos(nEndCharPos) , m_pTextLayoutCache(pLayoutCache) - , mpDXArray(nullptr) - , mpAltNaturalDXArray(nullptr) + , mpNaturalDXArray(nullptr) , mpKashidaArray(nullptr) , mnLayoutWidth(0) , mnOrientation(0) @@ -91,12 +90,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int nMinCharPos, int nEndCh void ImplLayoutArgs::SetLayoutWidth(DeviceCoordinate nWidth) { mnLayoutWidth = nWidth; } -void ImplLayoutArgs::SetDXArray(DeviceCoordinate const* pDXArray) { mpDXArray = pDXArray; } - -void ImplLayoutArgs::SetAltNaturalDXArray(double const* pDXArray) -{ - mpAltNaturalDXArray = pDXArray; -} +void ImplLayoutArgs::SetNaturalDXArray(double const* pDXArray) { mpNaturalDXArray = pDXArray; } void ImplLayoutArgs::SetKashidaArray(sal_Bool const* pKashidaArray) { @@ -308,7 +302,7 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs s << "\""; s << ",DXArray="; - if (rArgs.mpDXArray || rArgs.mpAltNaturalDXArray) + if (rArgs.mpNaturalDXArray) { s << "["; int count = rArgs.mnEndCharPos - rArgs.mnMinCharPos; @@ -317,10 +311,7 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs lim = 7; for (int i = 0; i < lim; i++) { - if (rArgs.mpDXArray) - s << rArgs.mpDXArray[i]; - else - s << rArgs.mpAltNaturalDXArray[i]; + s << rArgs.mpNaturalDXArray[i]; if (i < lim - 1) s << ","; } @@ -328,10 +319,7 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs { if (count > lim + 1) s << "..."; - if (rArgs.mpDXArray) - s << rArgs.mpDXArray[count - 1]; - else - s << rArgs.mpAltNaturalDXArray[count - 1]; + s << rArgs.mpNaturalDXArray[count - 1]; } s << "]"; }