Blame SOURCES/0001-fdo-70968-Incorrect-rendering-of-Devanagari-short-i-.patch

2135ec
From 71077148d442b3bbfeefd9a572942946c6a95823 Mon Sep 17 00:00:00 2001
2135ec
From: Khaled Hosny <khaledhosny@eglug.org>
2135ec
Date: Wed, 30 Oct 2013 09:34:38 +0200
2135ec
Subject: [PATCH] fdo#70968: Incorrect rendering of Devanagari short 'i' vowel
2135ec
2135ec
It seems that some Indic fonts assign 'mark' glyph class to combining
2135ec
spacing marks (spacing not non spacing) so my reliance on the glyph
2135ec
class to set the IS_DIACRITIC flags broke those fonts. This is a bandaid
2135ec
to get around the issue, plus some long rant! (at this rate, I'll be
2135ec
writing "The VCL haters handbook" pretty soon).
2135ec
2135ec
Change-Id: I3ff892acf746d50182573f94e7e8c3c6f9464ae0
2135ec
---
2135ec
 vcl/generic/glyphs/gcach_layout.cxx | 26 +++++++++++++++++++++-----
2135ec
 vcl/source/gdi/sallayout.cxx        | 21 +++++++++++++++++++++
2135ec
 2 files changed, 42 insertions(+), 5 deletions(-)
2135ec
2135ec
diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx
2135ec
index 4673931..7a8bfc9 100644
2135ec
--- a/vcl/generic/glyphs/gcach_layout.cxx
2135ec
+++ b/vcl/generic/glyphs/gcach_layout.cxx
2135ec
@@ -456,20 +456,36 @@ bool HbLayoutEngine::layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs)
2135ec
             if (bInCluster)
2135ec
                 nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
2135ec
 
2135ec
+            // The whole IS_DIACRITIC concept is a stupid hack that was
2135ec
+            // introduced ages ago to work around the utter brokenness of the
2135ec
+            // way justification adjustments are applied (the DXArray fiasco).
2135ec
+            // Since it is such a stupid hack, there is no sane way to directly
2135ec
+            // map to concepts of the "outside" world, so we do some rather
2135ec
+            // ugly hacks:
2135ec
+            // * If the font has a GDEF table, we check for glyphs with mark
2135ec
+            //   glyph class which is sensible, except that some fonts
2135ec
+            //   (fdo#70968) assign mark class to spacing marks (which is wrong
2135ec
+            //   but usually harmless), so we try to sniff what HarfBuzz thinks
2135ec
+            //   about this glyph by checking if it gives it a zero advance
2135ec
+            //   width.
2135ec
+            // * If the font has no GDEF table, we just check if the glyph has
2135ec
+            //   zero advance width, but this is stupid and can be wrong. A
2135ec
+            //   better way would to check the character's Unicode combining
2135ec
+            //   class, but unfortunately glyph gives combining marks the
2135ec
+            //   cluster value of its base character, so nCharPos will be
2135ec
+            //   pointing to the wrong character (but HarfBuzz might change
2135ec
+            //   this in the future).
2135ec
             bool bDiacritic = false;
2135ec
             if (hb_ot_layout_has_glyph_classes(mpHbFace))
2135ec
             {
2135ec
                 // the font has GDEF table
2135ec
-                if (hb_ot_layout_get_glyph_class(mpHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK)
2135ec
+                bool bMark = hb_ot_layout_get_glyph_class(mpHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK;
2135ec
+                if (bMark && pHbPositions[i].x_advance == 0)
2135ec
                     bDiacritic = true;
2135ec
             }
2135ec
             else
2135ec
             {
2135ec
                 // the font lacks GDEF table
2135ec
-                // HACK: if the resolved glyph advance is zero assume it is a
2135ec
-                // combining mark.  The whole IS_DIACRITIC concept is a hack to
2135ec
-                // fix the other hacks we use to second-guess glyph advances in
2135ec
-                // ApplyDXArray and the likes and it needs to die
2135ec
                 if (pHbPositions[i].x_advance == 0)
2135ec
                     bDiacritic = true;
2135ec
             }
2135ec
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
2135ec
index f395936..450ec232 100644
2135ec
--- a/vcl/source/gdi/sallayout.cxx
2135ec
+++ b/vcl/source/gdi/sallayout.cxx
2135ec
@@ -1018,6 +1018,27 @@ void GenericSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
2135ec
 
2135ec
 // -----------------------------------------------------------------------
2135ec
 
2135ec
+// This DXArray thing is one of the stupidest ideas I have ever seen (I've been
2135ec
+// told that it probably a one-to-one mapping of some Windows 3.1 API, which is
2135ec
+// telling). To justify a text string, Writer calls OutputDevice::GetTextArray()
2135ec
+// to get an array that maps input characters (not glyphs) to their absolute
2135ec
+// position, GetTextArray() in turn calls SalLayout::FillDXArray() to get an
2135ec
+// array of character widths that it converts to absolute positions.
2135ec
+//
2135ec
+// Writer would then apply justification adjustments to that array of absolute
2135ec
+// character positions and return to OutputDevice, which eventually calls
2135ec
+// ApplyDXArray(), which needs to extract the individual adjustments for each
2135ec
+// character to apply it to corresponding glyphs, and since that information is
2135ec
+// already lost it tries to do some heuristics to guess it again. Those
2135ec
+// heuristics often fail, and have always been a source of all sorts of weird
2135ec
+// text layout bugs, and instead of fixing the broken design a hack after hack
2135ec
+// have been applied on top of it, making it a complete mess that nobody
2135ec
+// understands.
2135ec
+//
2135ec
+// As you can see by now, this is utterly stupid, why Writer does not just send
2135ec
+// us directly the advance width transformations it wants to apply to each
2135ec
+// character instead of this whole mess?
2135ec
+
2135ec
 void GenericSalLayout::ApplyDXArray( ImplLayoutArgs& rArgs )
2135ec
 {
2135ec
     if( m_GlyphItems.empty())
2135ec
-- 
2135ec
1.8.3.1
2135ec