summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2016-09-11 10:25:46 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2016-10-18 20:41:31 +0200
commit15f6a97d9f23124c19471b9d8dd38f14f53829b3 (patch)
treecbcb1cdf11821749d465b726ce2d4957a06fca05 /vcl
parent66104ff9856ff1c81ec8c776a0467796f85efc01 (diff)
Fix applying DX adjustments in CommonSalLayout
By overriding GetCharWidths() and ApplyDXArray() with a simpler and saner implementation. This fixes rendering of Awami Nastaliq, as well as subtending marks in Amiri and potentially other bugs. Breaks Kashida justification, will need to rewrite that one as well. Change-Id: I843679e937f2881e77df61f5cbd9516b6df1b3b6
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/CommonSalLayout.hxx3
-rw-r--r--vcl/inc/sallayout.hxx4
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx63
3 files changed, 68 insertions, 2 deletions
diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index dbd7bc1a1e0a..dfd58fed0d50 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -68,6 +68,9 @@ public:
bool LayoutText(ImplLayoutArgs&) override;
void DrawText(SalGraphics&) const override;
std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&) const override;
+
+ virtual bool GetCharWidths(DeviceCoordinate* pCharWidths) const override;
+ virtual void ApplyDXArray(ImplLayoutArgs&) override;
};
#endif
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index cfb29306cdb9..1050943c2e77 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -326,7 +326,7 @@ public:
void AppendGlyph( const GlyphItem& );
void Reserve(int size) { m_GlyphItems.reserve(size + 1); }
virtual void AdjustLayout( ImplLayoutArgs& ) override;
- void ApplyDXArray( ImplLayoutArgs& );
+ virtual void ApplyDXArray( ImplLayoutArgs& );
void Justify( DeviceCoordinate nNewWidth );
void KashidaJustify( long nIndex, int nWidth );
void ApplyAsianKerning(const OUString& rStr);
@@ -352,7 +352,7 @@ protected:
virtual void DropGlyph( int nStart ) override;
virtual void Simplify( bool bIsBase ) override;
- bool GetCharWidths( DeviceCoordinate* pCharWidths ) const;
+ virtual bool GetCharWidths( DeviceCoordinate* pCharWidths ) const;
std::vector<GlyphItem> m_GlyphItems;
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index a303f707e7dd..2be6dd8a0afa 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -489,3 +489,66 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
return true;
}
+
+bool CommonSalLayout::GetCharWidths(DeviceCoordinate* pCharWidths) const
+{
+ int nCharCount = mnEndCharPos - mnMinCharPos;
+
+ for (int i = 0; i < nCharCount; ++i)
+ pCharWidths[i] = 0;
+
+ for (auto const& aGlyphItem : m_GlyphItems)
+ pCharWidths[aGlyphItem.mnCharPos - mnMinCharPos] += aGlyphItem.mnNewWidth;
+
+ return true;
+}
+
+void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
+{
+ if (rArgs.mpDXArray == nullptr)
+ return;
+
+ int nCharCount = mnEndCharPos - mnMinCharPos;
+ std::unique_ptr<DeviceCoordinate[]> const pOldCharWidths(new DeviceCoordinate[nCharCount]);
+ std::unique_ptr<DeviceCoordinate[]> const pNewCharWidths(new DeviceCoordinate[nCharCount]);
+
+ // Get the natural character widths (i.e. before applying DX adjustments).
+ GetCharWidths(pOldCharWidths.get());
+
+ // Calculate the character widths after DX adjustments.
+ for (int i = 0; i < nCharCount; ++i)
+ {
+ if (i == 0)
+ pNewCharWidths[i] = rArgs.mpDXArray[i];
+ else
+ pNewCharWidths[i] = rArgs.mpDXArray[i] - rArgs.mpDXArray[i - 1];
+ }
+
+ // The accumulated difference in X position.
+ DeviceCoordinate nDelta = 0;
+
+ // Apply the DX adjustments to glyph positions and widths.
+ size_t i = 0;
+ while (i < m_GlyphItems.size())
+ {
+ int nCharPos = m_GlyphItems[i].mnCharPos - mnMinCharPos;
+ DeviceCoordinate nDiff = pNewCharWidths[nCharPos] - pOldCharWidths[nCharPos];
+
+ m_GlyphItems[i].maLinearPos.X() += nDelta;
+ size_t j = i;
+ // Apply the delta to other glyphs belonging to the same character.
+ while (++j < m_GlyphItems.size())
+ {
+ if (m_GlyphItems[j].mnCharPos != m_GlyphItems[i].mnCharPos)
+ break;
+ m_GlyphItems[j].maLinearPos.X() += nDelta;
+ }
+
+ // Increment the delta, the loop above makes sure we do so only once
+ // for every character not for every glyph (otherwise we would apply it
+ // multiple times for each glyphs belonging to the same character which
+ // is wrong since DX adjustments are character based).
+ nDelta += nDiff;
+ i = j;
+ }
+}