include/vcl/outdev.hxx | 2 include/vcl/vcllayout.hxx | 6 +- vcl/inc/ImplLayoutArgs.hxx | 4 - vcl/inc/font/FontMetricData.hxx | 6 +- vcl/inc/font/LogicalFontInstance.hxx | 2 vcl/inc/impglyphitem.hxx | 33 ++++++++------- vcl/inc/quartz/salgdi.h | 4 - vcl/inc/sallayout.hxx | 16 +++---- vcl/inc/skia/osx/gdiimpl.hxx | 3 - vcl/qa/cppunit/complextext.cxx | 2 vcl/quartz/salgdi.cxx | 6 +- vcl/skia/osx/gdiimpl.cxx | 4 - vcl/source/font/LogicalFontInstance.cxx | 2 vcl/source/gdi/CommonSalLayout.cxx | 16 +++---- vcl/source/gdi/pdfwriter_impl.cxx | 2 vcl/source/gdi/sallayout.cxx | 70 +++++++++++++++----------------- vcl/source/outdev/text.cxx | 64 +++++++++-------------------- vcl/source/text/ImplLayoutArgs.cxx | 2 18 files changed, 109 insertions(+), 135 deletions(-)
New commits: commit c46f8c356d812230c3a43cd08fb79674be88d9a8 Author: Khaled Hosny <kha...@libreoffice.org> AuthorDate: Mon Jul 17 12:16:58 2023 +0300 Commit: خالد حسني <kha...@libreoffice.org> CommitDate: Sun Jul 23 06:01:31 2023 +0200 vcl: Simplify AquaGraphics*::drawTextLayout() calling Take TextRenderModeForResolutionIndependentLayout() from the SalLayout argument instead of passing it separately. Change-Id: I155ea645e401618ad884fdc36c4c1aeab69980ee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154516 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@libreoffice.org> diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index 01826c5c93e0..026f5e066382 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -292,7 +292,7 @@ public: const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue) = 0; - virtual void drawTextLayout(const GenericSalLayout& layout, bool bTextRenderModeForResolutionIndependentLayout) = 0; + virtual void drawTextLayout(const GenericSalLayout& layout) = 0; virtual void Flush() {} virtual void Flush( const tools::Rectangle& ) {} virtual void WindowBackingPropertiesChanged() {}; @@ -445,7 +445,7 @@ public: ControlState nState, const ImplControlValue &aValue) override; - virtual void drawTextLayout(const GenericSalLayout& layout, bool bTextRenderModeForResolutionIndependentLayout) override; + virtual void drawTextLayout(const GenericSalLayout& layout) override; bool supportsOperation(OutDevSupportType eType) const override; }; diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx index b90b576a873f..b97245e86e11 100644 --- a/vcl/inc/skia/osx/gdiimpl.hxx +++ b/vcl/inc/skia/osx/gdiimpl.hxx @@ -38,8 +38,7 @@ public: const tools::Rectangle& rControlRegion, ControlState nState, const ImplControlValue& aValue) override; - virtual void drawTextLayout(const GenericSalLayout& layout, - bool bTextRenderModeForResolutionIndependentLayout) override; + virtual void drawTextLayout(const GenericSalLayout& layout) override; virtual void Flush() override; virtual void Flush(const tools::Rectangle&) override; diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx index 4af4b28ffa2c..b06e0d41bdbd 100644 --- a/vcl/quartz/salgdi.cxx +++ b/vcl/quartz/salgdi.cxx @@ -306,10 +306,10 @@ bool AquaSalGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection*, void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) { - mpBackend->drawTextLayout(rLayout, rLayout.GetTextRenderModeForResolutionIndependentLayout()); + mpBackend->drawTextLayout(rLayout); } -void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout, bool bTextRenderModeForResolutionIndependentLayout) +void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout) { #ifdef IOS if (!mrShared.checkContext()) @@ -397,7 +397,7 @@ void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout, bool b CGContextSetTextDrawingMode(mrShared.maContextHolder.get(), kCGTextFillStroke); } - if (bTextRenderModeForResolutionIndependentLayout) + if (rLayout.GetTextRenderModeForResolutionIndependentLayout()) { CGContextSetAllowsFontSubpixelQuantization(mrShared.maContextHolder.get(), false); CGContextSetShouldSubpixelQuantizeFonts(mrShared.maContextHolder.get(), false); diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx index fd0bdca04333..e392587c8836 100644 --- a/vcl/skia/osx/gdiimpl.cxx +++ b/vcl/skia/osx/gdiimpl.cxx @@ -294,9 +294,9 @@ bool AquaSkiaSalGraphicsImpl::drawNativeControl(ControlType nType, ControlPart n return bOK; } -void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout, - bool bSubpixelPositioning) +void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout) { + const bool bSubpixelPositioning = rLayout.GetTextRenderModeForResolutionIndependentLayout(); const CoreTextFont& rFont = *static_cast<const CoreTextFont*>(&rLayout.GetFont()); const vcl::font::FontSelectPattern& rFontSelect = rFont.GetFontSelectPattern(); int nHeight = rFontSelect.mnHeight; commit 172b500ccbc8dac0496cc2936a9bcca793c0b594 Author: Khaled Hosny <kha...@libreoffice.org> AuthorDate: Sun Jul 16 21:11:40 2023 +0300 Commit: خالد حسني <kha...@libreoffice.org> CommitDate: Sun Jul 23 06:01:23 2023 +0200 vcl: Use more doubles for text measurements Change-Id: I5695d9ab51eb09929b4c290ceaf7ae2be46f5989 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154504 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@libreoffice.org> diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index cfa423759202..f898f4f13902 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1232,7 +1232,7 @@ public: const SalLayoutGlyphs* pGlyphs = nullptr) const; SAL_DLLPRIVATE vcl::text::ImplLayoutArgs ImplPrepareLayoutArgs( OUString&, const sal_Int32 nIndex, const sal_Int32 nLen, - DeviceCoordinate nPixelWidth, + double nPixelWidth, SalLayoutFlags flags = SalLayoutFlags::NONE, vcl::text::TextLayoutCache const* = nullptr) const; SAL_DLLPRIVATE std::unique_ptr<SalLayout> diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx index d7100d71fd8b..1802ce19decd 100644 --- a/vcl/inc/ImplLayoutArgs.hxx +++ b/vcl/inc/ImplLayoutArgs.hxx @@ -37,7 +37,7 @@ public: // positioning related inputs const double* mpDXArray; // in floating point pixel units const sal_Bool* mpKashidaArray; - DeviceCoordinate mnLayoutWidth; // in pixel units + double mnLayoutWidth; // in pixel units Degree10 mnOrientation; // in 0-3600 system // data for bidi and glyph+script fallback @@ -47,7 +47,7 @@ public: ImplLayoutArgs(OUString const& rStr, int nMinCharPos, int nEndCharPos, SalLayoutFlags nFlags, LanguageTag aLanguageTag, vcl::text::TextLayoutCache const* pLayoutCache); - void SetLayoutWidth(DeviceCoordinate nWidth); + void SetLayoutWidth(double nWidth); void SetDXArray(const double* pDXArray); void SetKashidaArray(const sal_Bool* pKashidaArray); void SetOrientation(Degree10 nOrientation); diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index 51f62d9b0057..274de68a0400 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -141,7 +141,7 @@ private: GenericSalLayout& operator=( const GenericSalLayout& ) = delete; void ApplyDXArray(const double*, const sal_Bool*); - void Justify(DeviceCoordinate nNewWidth); + void Justify(double nNewWidth); void ApplyAsianKerning(std::u16string_view rStr); void GetCharWidths(std::vector<double>& rCharWidths, diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index da70859f4c53..ba2f1e050dca 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -276,9 +276,9 @@ double GenericSalLayout::GetTextWidth() const return nWidth; } -void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) +void GenericSalLayout::Justify(double nNewWidth) { - DeviceCoordinate nOldWidth = GetTextWidth(); + double nOldWidth = GetTextWidth(); if( !nOldWidth || nNewWidth==nOldWidth ) return; @@ -292,7 +292,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) std::vector<GlyphItem>::iterator pGlyphIter; // count stretchable glyphs int nStretchable = 0; - int nMaxGlyphWidth = 0; + double nMaxGlyphWidth = 0; for(pGlyphIter = m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter) { if( !pGlyphIter->IsInCluster() ) @@ -311,7 +311,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) pGlyphIterRight->setLinearPosX( nNewWidth ); // justify glyph widths and positions - int nDiffWidth = nNewWidth - nOldWidth; + double nDiffWidth = nNewWidth - nOldWidth; if( nDiffWidth >= 0) // expanded case { // expand width by distributing space between glyphs evenly @@ -326,7 +326,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) continue; // distribute extra space equally to stretchable glyphs - int nDeltaWidth = nDiffWidth / nStretchable--; + double nDeltaWidth = nDiffWidth / nStretchable--; nDiffWidth -= nDeltaWidth; pGlyphIter->addNewWidth(nDeltaWidth); nDeltaSum += nDeltaWidth; @@ -335,13 +335,13 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) else // condensed case { // squeeze width by moving glyphs proportionally - double fSqueeze = static_cast<double>(nNewWidth) / nOldWidth; + double fSqueeze = nNewWidth / nOldWidth; if(m_GlyphItems.size() > 1) { for( pGlyphIter = m_GlyphItems.begin(); ++pGlyphIter != pGlyphIterRight;) { - int nX = pGlyphIter->linearPos().getX(); - nX = static_cast<int>(nX * fSqueeze); + double nX = pGlyphIter->linearPos().getX(); + nX = nX * fSqueeze; pGlyphIter->setLinearPosX( nX ); } } @@ -423,7 +423,7 @@ void GenericSalLayout::ApplyAsianKerning(std::u16string_view rStr) continue; // apply punctuation compression to logical glyph widths - DeviceCoordinate nDelta = (nKernCurrent < nKernNext) ? nKernCurrent : nKernNext; + double nDelta = (nKernCurrent < nKernNext) ? nKernCurrent : nKernNext; if (nDelta < 0) { nDelta = (nDelta * pGlyphIter->origWidth() + 2) / 4; @@ -640,7 +640,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) { // for stretched text in a MultiSalLayout the target width needs to be // distributed by individually adjusting its virtual character widths - DeviceCoordinate nTargetWidth = aMultiArgs.mnLayoutWidth; + double nTargetWidth = aMultiArgs.mnLayoutWidth; aMultiArgs.mnLayoutWidth = 0; // we need to get the original unmodified layouts ready @@ -652,7 +652,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) // #i17359# multilayout is not simplified yet, so calculating the // unjustified width needs handholding; also count the number of // stretchable virtual char widths - DeviceCoordinate nOrigWidth = 0; + double nOrigWidth = 0; int nStretchable = 0; for( int i = 0; i < nCharCount; ++i ) { @@ -665,14 +665,14 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) // now we are able to distribute the extra width over the virtual char widths if( nOrigWidth && (nTargetWidth != nOrigWidth) ) { - DeviceCoordinate nDiffWidth = nTargetWidth - nOrigWidth; - DeviceCoordinate nWidthSum = 0; + double nDiffWidth = nTargetWidth - nOrigWidth; + double nWidthSum = 0; for( int i = 0; i < nCharCount; ++i ) { - DeviceCoordinate nJustWidth = aJustificationArray[i]; + double nJustWidth = aJustificationArray[i]; if( (nJustWidth > 0) && (nStretchable > 0) ) { - DeviceCoordinate nDeltaWidth = nDiffWidth / nStretchable; + double nDeltaWidth = nDiffWidth / nStretchable; nJustWidth += nDeltaWidth; nDiffWidth -= nDeltaWidth; --nStretchable; diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 81f4aa095840..6e35beccfec0 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -1115,7 +1115,7 @@ void OutputDevice::DrawStretchText( const Point& rStartPt, sal_Int32 nWidth, vcl::text::ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, const sal_Int32 nMinIndex, const sal_Int32 nLen, - DeviceCoordinate nPixelWidth, + double nPixelWidth, SalLayoutFlags nLayoutFlags, vcl::text::TextLayoutCache const*const pLayoutCache) const { @@ -1328,17 +1328,17 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, pGlyphs = nullptr; } - DeviceCoordinate nPixelWidth = static_cast<DeviceCoordinate>(nLogicalWidth); + double nPixelWidth = nLogicalWidth; if( nLogicalWidth && mbMap ) { // convert from logical units to physical units - nPixelWidth = LogicWidthToDeviceCoordinate( nLogicalWidth ); + nPixelWidth = ImplLogicWidthToDeviceSubPixel(nLogicalWidth); } vcl::text::ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, nPixelWidth, flags, pLayoutCache); - DeviceCoordinate nEndGlyphCoord(0); + double nEndGlyphCoord(0); std::unique_ptr<double[]> xDXPixelArray; if( !pDXArray.empty() ) { @@ -1405,7 +1405,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, // adjust to right alignment if necessary if( aLayoutArgs.mnFlags & SalLayoutFlags::RightAlign ) { - DeviceCoordinate nRTLOffset; + double nRTLOffset; if (!pDXArray.empty()) nRTLOffset = nEndGlyphCoord; else if( nPixelWidth ) diff --git a/vcl/source/text/ImplLayoutArgs.cxx b/vcl/source/text/ImplLayoutArgs.cxx index 80aec6b5f42c..826d288bba6f 100644 --- a/vcl/source/text/ImplLayoutArgs.cxx +++ b/vcl/source/text/ImplLayoutArgs.cxx @@ -88,7 +88,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int nMinCharPos, int nEndCh maRuns.ResetPos(); } -void ImplLayoutArgs::SetLayoutWidth(DeviceCoordinate nWidth) { mnLayoutWidth = nWidth; } +void ImplLayoutArgs::SetLayoutWidth(double nWidth) { mnLayoutWidth = nWidth; } void ImplLayoutArgs::SetDXArray(double const* pDXArray) { mpDXArray = pDXArray; } commit 507a8745870e9a755be3a72f59c6e9a9d811fdcf Author: Khaled Hosny <kha...@libreoffice.org> AuthorDate: Sun Jul 16 16:06:59 2023 +0300 Commit: خالد حسني <kha...@libreoffice.org> CommitDate: Sun Jul 23 06:01:17 2023 +0200 vcl: Use doubles for glyph item coordinates Change how glyph coordinates are represented inside VCL to use floating point instead of integers. Should make no functional difference because we are still rounding them. Change-Id: I5480ee3dec3afab50194954095fd6829ebaa4a22 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154499 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@libreoffice.org> diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx index 4705a44d9b92..4acfb9b4ab04 100644 --- a/include/vcl/vcllayout.hxx +++ b/include/vcl/vcllayout.hxx @@ -93,9 +93,9 @@ public: } // methods using string indexing - virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const = 0; - virtual DeviceCoordinate FillDXArray( std::vector<DeviceCoordinate>* pDXArray, const OUString& rStr ) const = 0; - virtual DeviceCoordinate GetTextWidth() const { return FillDXArray( nullptr, {} ); } + virtual sal_Int32 GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const = 0; + virtual double FillDXArray( std::vector<double>* pDXArray, const OUString& rStr ) const = 0; + virtual double GetTextWidth() const { return FillDXArray( nullptr, {} ); } virtual void GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const = 0; virtual bool IsKashidaPosValid ( int /*nCharPos*/, int /*nNextCharPos*/ ) const = 0; // i60594 diff --git a/vcl/inc/font/FontMetricData.hxx b/vcl/inc/font/FontMetricData.hxx index 000a5a250bbd..bd552562ff9a 100644 --- a/vcl/inc/font/FontMetricData.hxx +++ b/vcl/inc/font/FontMetricData.hxx @@ -56,11 +56,11 @@ public: tools::Long GetInternalLeading() const { return mnIntLeading; } tools::Long GetExternalLeading() const { return mnExtLeading; } int GetSlant() const { return mnSlant; } - tools::Long GetMinKashida() const { return mnMinKashida; } + double GetMinKashida() const { return mnMinKashida; } tools::Long GetHangingBaseline() const { return mnHangingBaseline; } void SetSlant(int nSlant) { mnSlant=nSlant; } - void SetMinKashida( tools::Long nMinKashida ) { mnMinKashida=nMinKashida; } + void SetMinKashida(double nMinKashida ) { mnMinKashida=nMinKashida; } // font attributes queried from the font instance bool IsFullstopCentered() const { return mbFullstopCentered; } @@ -117,7 +117,7 @@ private: tools::Long mnIntLeading; // Internal Leading tools::Long mnExtLeading; // External Leading int mnSlant; // Slant (Italic/Oblique) - tools::Long mnMinKashida; // Minimal width of kashida (Arabic) + double mnMinKashida; // Minimal width of kashida (Arabic) tools::Long mnHangingBaseline; // Offset of hanging baseline to Romn baseline // font attributes queried from the font instance diff --git a/vcl/inc/font/LogicalFontInstance.hxx b/vcl/inc/font/LogicalFontInstance.hxx index e85d25b41f10..43b23d9cd0e9 100644 --- a/vcl/inc/font/LogicalFontInstance.hxx +++ b/vcl/inc/font/LogicalFontInstance.hxx @@ -109,7 +109,7 @@ public: // TODO: make data members private double GetGlyphWidth(sal_GlyphId, bool = false, bool = true) const; - int GetKashidaWidth() const; + double GetKashidaWidth() const; void GetScale(double* nXScale, double* nYScale) const; diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx index 87f966bd1676..c729d0cc9b7e 100644 --- a/vcl/inc/impglyphitem.hxx +++ b/vcl/inc/impglyphitem.hxx @@ -24,6 +24,7 @@ #include <tools/gen.hxx> #include <vcl/dllapi.h> #include <vcl/outdev.hxx> +#include <rtl/math.hxx> #include <vector> #include "font/LogicalFontInstance.hxx" @@ -51,18 +52,18 @@ template <> struct typed_flags<GlyphItemFlags> : is_typed_flags<GlyphItemFlags, class VCL_DLLPUBLIC GlyphItem { DevicePoint m_aLinearPos; // absolute position of non rotated string - DeviceCoordinate m_nOrigWidth; // original glyph width + double m_nOrigWidth; // original glyph width sal_Int32 m_nCharPos; // index in string - sal_Int32 m_nXOffset; - sal_Int32 m_nYOffset; - DeviceCoordinate m_nNewWidth; // width after adjustments + double m_nXOffset; + double m_nYOffset; + double m_nNewWidth; // width after adjustments sal_GlyphId m_aGlyphId; GlyphItemFlags m_nFlags; sal_Int8 m_nCharCount; // number of characters making up this glyph public: GlyphItem(int nCharPos, int nCharCount, sal_GlyphId aGlyphId, const DevicePoint& rLinearPos, - GlyphItemFlags nFlags, DeviceCoordinate nOrigWidth, int nXOffset, int nYOffset) + GlyphItemFlags nFlags, double nOrigWidth, double nXOffset, double nYOffset) : m_aLinearPos(rLinearPos) , m_nOrigWidth(nOrigWidth) , m_nCharPos(nCharPos) @@ -93,24 +94,26 @@ public: sal_GlyphId glyphId() const { return m_aGlyphId; } int charCount() const { return m_nCharCount; } - DeviceCoordinate origWidth() const { return m_nOrigWidth; } + double origWidth() const { return m_nOrigWidth; } int charPos() const { return m_nCharPos; } - int xOffset() const { return m_nXOffset; } - int yOffset() const { return m_nYOffset; } - DeviceCoordinate newWidth() const { return m_nNewWidth; } + double xOffset() const { return m_nXOffset; } + double yOffset() const { return m_nYOffset; } + double newWidth() const { return m_nNewWidth; } const DevicePoint& linearPos() const { return m_aLinearPos; } - void setNewWidth(DeviceCoordinate width) { m_nNewWidth = width; } - void addNewWidth(DeviceCoordinate width) { m_nNewWidth += width; } + void setNewWidth(double width) { m_nNewWidth = width; } + void addNewWidth(double width) { m_nNewWidth += width; } void setLinearPos(const DevicePoint& point) { m_aLinearPos = point; } void setLinearPosX(double x) { m_aLinearPos.setX(x); } void adjustLinearPosX(double diff) { m_aLinearPos.adjustX(diff); } bool isLayoutEquivalent(const GlyphItem& other) const { - return m_aLinearPos == other.m_aLinearPos && m_nOrigWidth == other.m_nOrigWidth - && m_nCharPos == other.m_nCharPos && m_nXOffset == other.m_nXOffset - && m_nYOffset == other.m_nYOffset && m_nNewWidth == other.m_nNewWidth - && m_aGlyphId == other.m_aGlyphId && m_nCharCount == other.m_nCharCount + return rtl::math::approxEqual(m_aLinearPos.getX(), other.m_aLinearPos.getX(), 8) + && rtl::math::approxEqual(m_aLinearPos.getY(), other.m_aLinearPos.getY(), 8) + && m_nOrigWidth == other.m_nOrigWidth && m_nCharPos == other.m_nCharPos + && m_nXOffset == other.m_nXOffset && m_nYOffset == other.m_nYOffset + && m_nNewWidth == other.m_nNewWidth && m_aGlyphId == other.m_aGlyphId + && m_nCharCount == other.m_nCharCount && (m_nFlags & ~GlyphItemFlags::IS_UNSAFE_TO_BREAK) == (other.m_nFlags & ~GlyphItemFlags::IS_UNSAFE_TO_BREAK); } diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index d48edaaf67f2..51f62d9b0057 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -61,9 +61,9 @@ class MultiSalLayout final : public SalLayout { public: void DrawText(SalGraphics&) const override; - sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override; - DeviceCoordinate GetTextWidth() const final override; - DeviceCoordinate FillDXArray(std::vector<DeviceCoordinate>* pDXArray, const OUString& rStr) const override; + sal_Int32 GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const override; + double GetTextWidth() const final override; + double FillDXArray(std::vector<double>* pDXArray, const OUString& rStr) const override; void GetCaretPositions(int nArraySize, sal_Int32* pCaretXArray) const override; bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, const LogicalFontInstance** ppGlyphFont = nullptr) const override; @@ -117,9 +117,9 @@ public: bool IsKashidaPosValid(int nCharPos, int nNextCharPos) const final override; // used by upper layers - DeviceCoordinate GetTextWidth() const final override; - DeviceCoordinate FillDXArray(std::vector<DeviceCoordinate>* pDXArray, const OUString& rStr) const final override; - sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const final override; + double GetTextWidth() const final override; + double FillDXArray(std::vector<double>* pDXArray, const OUString& rStr) const final override; + sal_Int32 GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const final override; void GetCaretPositions(int nArraySize, sal_Int32* pCaretXArray) const final override; // used by display layers @@ -144,7 +144,7 @@ private: void Justify(DeviceCoordinate nNewWidth); void ApplyAsianKerning(std::u16string_view rStr); - void GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths, + void GetCharWidths(std::vector<double>& rCharWidths, const OUString& rStr) const; void SetNeedFallback(vcl::text::ImplLayoutArgs&, sal_Int32, bool); diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index db8593e48fbb..6c2491a27010 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -424,7 +424,7 @@ CPPUNIT_TEST_FIXTURE(VclComplexTextTest, testTdf152048) // Without the fix this fails with: // - Expected: 393 // - Actual : 511 - CPPUNIT_ASSERT_EQUAL(DeviceCoordinate(nRefTextWidth + nKashida), pLayout->GetTextWidth()); + CPPUNIT_ASSERT_EQUAL(double(nRefTextWidth + nKashida), pLayout->GetTextWidth()); #endif } diff --git a/vcl/source/font/LogicalFontInstance.cxx b/vcl/source/font/LogicalFontInstance.cxx index 766dd2514120..965fc91591c1 100644 --- a/vcl/source/font/LogicalFontInstance.cxx +++ b/vcl/source/font/LogicalFontInstance.cxx @@ -102,7 +102,7 @@ hb_font_t* LogicalFontInstance::GetHbFontUntransformed() const return pHbFont; } -int LogicalFontInstance::GetKashidaWidth() const +double LogicalFontInstance::GetKashidaWidth() const { sal_GlyphId nGlyph = GetGlyphIndex(0x0640); if (nGlyph) diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index f46f4d875210..ca34b098c8cb 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -239,12 +239,12 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay // horizontal text. That is the offset from original baseline to // the center of EM box. Maybe we can use OpenType base table to improve this // in the future. - DeviceCoordinate nBaseOffset = 0; + double nBaseOffset = 0; if (rArgs.mnFlags & SalLayoutFlags::Vertical) { hb_font_extents_t extents; if (hb_font_get_h_extents(pHbFont, &extents)) - nBaseOffset = ( extents.ascender + extents.descender ) / 2; + nBaseOffset = ( extents.ascender + extents.descender ) / 2.0; } hb_buffer_t* pHbBuffer = hb_buffer_create(); @@ -505,7 +505,7 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay if (hb_glyph_info_get_glyph_flags(&pHbGlyphInfos[i]) & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) nGlyphFlags |= GlyphItemFlags::IS_SAFE_TO_INSERT_KASHIDA; - DeviceCoordinate nAdvance, nXOffset, nYOffset; + double nAdvance, nXOffset, nYOffset; if (aSubRun.maDirection == HB_DIRECTION_TTB) { nGlyphFlags |= GlyphItemFlags::IS_VERTICAL; @@ -523,7 +523,7 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay GetFont().GetGlyphBoundRect(nGlyphIndex, aRect, true); nXOffset = -(aRect.Top() / nXScale + ( pHbPositions[i].y_advance - + ( aRect.GetHeight() / nXScale ) ) / 2 ); + + ( aRect.GetHeight() / nXScale ) ) / 2.0 ); } } @@ -557,7 +557,7 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay return true; } -void GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths, const OUString& rStr) const +void GenericSalLayout::GetCharWidths(std::vector<double>& rCharWidths, const OUString& rStr) const { const int nCharCount = mnEndCharPos - mnMinCharPos; @@ -595,7 +595,7 @@ void GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths, { // More than one grapheme cluster, we want to distribute the glyph // width over them. - std::vector<DeviceCoordinate> aWidths(nGraphemeCount); + std::vector<double> aWidths(nGraphemeCount); // Check if the glyph has ligature caret positions. unsigned int nCarets = nGraphemeCount; @@ -662,7 +662,7 @@ void GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths, void GenericSalLayout::ApplyDXArray(const double* pDXArray, const sal_Bool* pKashidaArray) { int nCharCount = mnEndCharPos - mnMinCharPos; - std::vector<DeviceCoordinate> aOldCharWidths; + std::vector<double> aOldCharWidths; std::unique_ptr<double[]> const pNewCharWidths(new double[nCharCount]); // Get the natural character widths (i.e. before applying DX adjustments). @@ -679,7 +679,7 @@ void GenericSalLayout::ApplyDXArray(const double* pDXArray, const sal_Bool* pKas // Map of Kashida insertion points (in the glyph items vector) and the // requested width. - std::map<size_t, std::pair<DeviceCoordinate, DeviceCoordinate>> pKashidas; + std::map<size_t, std::pair<double, double>> pKashidas; // The accumulated difference in X position. double nDelta = 0; diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 42f85d42bb76..533fd62f2ae6 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -6983,7 +6983,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool if( m_aCurrentPDFState.m_aFont.IsWordLineMode() ) { DevicePoint aStartPt; - DeviceCoordinate nWidth = 0; + double nWidth = 0; nIndex = 0; while (rLayout.GetNextGlyph(&pGlyph, aPos, nIndex)) { diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index be3506bf4e3c..da70859f4c53 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -255,7 +255,7 @@ SalLayoutGlyphs SalLayout::GetGlyphs() const return SalLayoutGlyphs(); // invalid } -DeviceCoordinate GenericSalLayout::FillDXArray( std::vector<DeviceCoordinate>* pCharWidths, const OUString& rStr ) const +double GenericSalLayout::FillDXArray( std::vector<double>* pCharWidths, const OUString& rStr ) const { if (pCharWidths) GetCharWidths(*pCharWidths, rStr); @@ -264,12 +264,12 @@ DeviceCoordinate GenericSalLayout::FillDXArray( std::vector<DeviceCoordinate>* p } // the text width is the maximum logical extent of all glyphs -DeviceCoordinate GenericSalLayout::GetTextWidth() const +double GenericSalLayout::GetTextWidth() const { if (!m_GlyphItems.IsValid()) return 0; - DeviceCoordinate nWidth = 0; + double nWidth = 0; for (auto const& aGlyphItem : m_GlyphItems) nWidth += aGlyphItem.newWidth(); @@ -470,15 +470,15 @@ void GenericSalLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray } } -sal_Int32 GenericSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor ) const +sal_Int32 GenericSalLayout::GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const { - std::vector<DeviceCoordinate> aCharWidths; + std::vector<double> aCharWidths; GetCharWidths(aCharWidths, {}); - DeviceCoordinate nWidth = 0; + double nWidth = 0; for( int i = mnMinCharPos; i < mnEndCharPos; ++i ) { - DeviceCoordinate nDelta = aCharWidths[ i - mnMinCharPos ] * nFactor; + double nDelta = aCharWidths[ i - mnMinCharPos ] * nFactor; if (nDelta != 0) { @@ -634,8 +634,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) { SalLayout::AdjustLayout( rArgs ); vcl::text::ImplLayoutArgs aMultiArgs = rArgs; - std::vector<DeviceCoordinate> aJustificationArray; - std::vector<double> aNaturalJustificationArray; + std::vector<double> aJustificationArray; if( !rArgs.HasDXArray() && rArgs.mnLayoutWidth ) { @@ -684,11 +683,8 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) if( nWidthSum != nTargetWidth ) aJustificationArray[ nCharCount-1 ] = nTargetWidth; - aNaturalJustificationArray.reserve(aJustificationArray.size()); - for (DeviceCoordinate a : aJustificationArray) - aNaturalJustificationArray.push_back(a); // change the DXArray temporarily (just for the justification) - aMultiArgs.mpDXArray = aNaturalJustificationArray.data(); + aMultiArgs.mpDXArray = aJustificationArray.data(); } } @@ -976,7 +972,7 @@ void MultiSalLayout::DrawText( SalGraphics& rGraphics ) const // NOTE: now the baselevel font is active again } -sal_Int32 MultiSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor ) const +sal_Int32 MultiSalLayout::GetTextBreak(double nMaxWidth, double nCharExtra, int nFactor) const { if( mnLevel <= 0 ) return -1; @@ -984,8 +980,8 @@ sal_Int32 MultiSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordi return mpLayouts[0]->GetTextBreak( nMaxWidth, nCharExtra, nFactor ); int nCharCount = mnEndCharPos - mnMinCharPos; - std::vector<DeviceCoordinate> aCharWidths; - std::vector<DeviceCoordinate> aFallbackCharWidths; + std::vector<double> aCharWidths; + std::vector<double> aFallbackCharWidths; mpLayouts[0]->FillDXArray( &aCharWidths, {} ); for( int n = 1; n < mnLevel; ++n ) @@ -997,7 +993,7 @@ sal_Int32 MultiSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordi aCharWidths[i] = aFallbackCharWidths[i]; } - DeviceCoordinate nWidth = 0; + double nWidth = 0; for( int i = 0; i < nCharCount; ++i ) { nWidth += aCharWidths[ i ] * nFactor; @@ -1009,7 +1005,7 @@ sal_Int32 MultiSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordi return -1; } -DeviceCoordinate MultiSalLayout::GetTextWidth() const +double MultiSalLayout::GetTextWidth() const { // Measure text width. There might be holes in each SalLayout due to // missing chars, so we use GetNextGlyph() to get the glyphs across all @@ -1018,19 +1014,19 @@ DeviceCoordinate MultiSalLayout::GetTextWidth() const DevicePoint aPos; const GlyphItem* pGlyphItem; - DeviceCoordinate nWidth = 0; + double nWidth = 0; while (GetNextGlyph(&pGlyphItem, aPos, nStart)) nWidth += pGlyphItem->newWidth(); return nWidth; } -DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* pCharWidths, const OUString& rStr ) const +double MultiSalLayout::FillDXArray( std::vector<double>* pCharWidths, const OUString& rStr ) const { if (pCharWidths) { // prepare merging of fallback levels - std::vector<DeviceCoordinate> aTempWidths; + std::vector<double> aTempWidths; const int nCharCount = mnEndCharPos - mnMinCharPos; pCharWidths->clear(); pCharWidths->resize(nCharCount, 0); @@ -1047,7 +1043,7 @@ DeviceCoordinate MultiSalLayout::FillDXArray( std::vector<DeviceCoordinate>* pCh // one char cannot be resolved from different fallbacks if ((*pCharWidths)[i] != 0) continue; - DeviceCoordinate nCharWidth = aTempWidths[i]; + double nCharWidth = aTempWidths[i]; if (!nCharWidth) continue; (*pCharWidths)[i] = nCharWidth; diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 61d965a28b68..81f4aa095840 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -989,14 +989,13 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernAr return 0; } -#if VCL_FLOAT_DEVICE_PIXEL - std::unique_ptr<std::vector<DeviceCoordinate>> xDXPixelArray; + std::unique_ptr<std::vector<double>> xDXPixelArray; if(pDXAry) { - xDXPixelArray.reset(new std::vector<DeviceCoordinate>(nLen)); + xDXPixelArray.reset(new std::vector<double>(nLen)); } - std::vector<DeviceCoordinate>* pDXPixelArray = xDXPixelArray.get(); - DeviceCoordinate nWidth = pSalLayout->FillDXArray(pDXPixelArray, bCaret ? rStr : OUString()); + std::vector<double>* pDXPixelArray = xDXPixelArray.get(); + double nWidth = pSalLayout->FillDXArray(pDXPixelArray, bCaret ? rStr : OUString()); // convert virtual char widths to virtual absolute positions if( pDXPixelArray ) @@ -1006,57 +1005,34 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernAr (*pDXPixelArray)[i] += (*pDXPixelArray)[i - 1]; } } - if( mbMap ) - { - if( pDXPixelArray ) - { - for( int i = 0; i < nLen; ++i ) - { - (*pDXPixelArray)[i] = ImplDevicePixelToLogicWidth((*pDXPixelArray)[i]); - } - } - nWidth = ImplDevicePixelToLogicWidth( nWidth ); - } - if(pDXAry) - { - pDXAry->resize(nLen); - for( int i = 0; i < nLen; ++i ) - { - (*pDXAry)[i] = basegfx::fround((*pDXPixelArray)[i]); - } - } - return basegfx::fround(nWidth); - -#else /* ! VCL_FLOAT_DEVICE_PIXEL */ - - tools::Long nWidth = pSalLayout->FillDXArray( pDXAry, bCaret ? rStr : OUString() ); - - // convert virtual char widths to virtual absolute positions - if( pDXAry ) - for( int i = 1; i < nLen; ++i ) - (*pDXAry)[ i ] += (*pDXAry)[ i-1 ]; // convert from font units to logical units - if (pDXAry) + if (pDXPixelArray) { int nSubPixelFactor = pKernArray->get_factor(); if (mbMap) { for (int i = 0; i < nLen; ++i) - (*pDXAry)[i] = ImplDevicePixelToLogicWidth( (*pDXAry)[i] * nSubPixelFactor ); + (*pDXPixelArray)[i] = ImplDevicePixelToLogicWidth((*pDXPixelArray)[i] * nSubPixelFactor); } else if (nSubPixelFactor) { for (int i = 0; i < nLen; ++i) - (*pDXAry)[i] *= nSubPixelFactor; + (*pDXPixelArray)[i] *= nSubPixelFactor; } } + if (pDXAry) + { + pDXAry->resize(nLen); + for (int i = 0; i < nLen; ++i) + (*pDXAry)[i] = basegfx::fround((*pDXPixelArray)[i]); + } + if (mbMap) nWidth = ImplDevicePixelToLogicWidth( nWidth ); - return nWidth; -#endif /* VCL_FLOAT_DEVICE_PIXEL */ + return basegfx::fround(nWidth); } void OutputDevice::GetCaretPositions( const OUString& rStr, sal_Int32* pCaretXArray,