summaryrefslogtreecommitdiff
path: root/vcl/source
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/source
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/source')
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx63
1 files changed, 63 insertions, 0 deletions
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;
+ }
+}