Disable letterspacing for connected scripts

The appearance of letterspacing with scripts with cursive connections
is poor, so we simply disable letterspacing for those scripts. There
may be some cases where some form of letterspacing is desirable, but
this gives the highest likelihood that the final result will be good
without requiring additional work from clients.

Bug: 21935803
Change-Id: Ie25266249ac3a2605aa89ef5132e8edbe3a06d35
diff --git a/libs/minikin/Layout.cpp b/libs/minikin/Layout.cpp
index 17ce596..0c8c4ca 100644
--- a/libs/minikin/Layout.cpp
+++ b/libs/minikin/Layout.cpp
@@ -514,6 +514,29 @@
     return len;
 }
 
+/**
+ * Disable certain scripts (mostly those with cursive connection) from having letterspacing
+ * applied. See https://github.com/behdad/harfbuzz/issues/64 for more details.
+ */
+static bool isScriptOkForLetterspacing(hb_script_t script) {
+    return !(
+            script == HB_SCRIPT_ARABIC ||
+            script == HB_SCRIPT_NKO ||
+            script == HB_SCRIPT_PSALTER_PAHLAVI ||
+            script == HB_SCRIPT_MANDAIC ||
+            script == HB_SCRIPT_MONGOLIAN ||
+            script == HB_SCRIPT_PHAGS_PA ||
+            script == HB_SCRIPT_DEVANAGARI ||
+            script == HB_SCRIPT_BENGALI ||
+            script == HB_SCRIPT_GURMUKHI ||
+            script == HB_SCRIPT_MODI ||
+            script == HB_SCRIPT_SHARADA ||
+            script == HB_SCRIPT_SYLOTI_NAGRI ||
+            script == HB_SCRIPT_TIRHUTA ||
+            script == HB_SCRIPT_OGHAM
+            );
+}
+
 void Layout::doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
         int bidiFlags, const FontStyle &style, const MinikinPaint &paint) {
     AutoMutex _l(gMinikinLock);
@@ -678,15 +701,6 @@
 
     double size = ctx->paint.size;
     double scaleX = ctx->paint.scaleX;
-    double letterSpace = ctx->paint.letterSpacing * size * scaleX;
-    double letterSpaceHalfLeft;
-    if ((ctx->paint.paintFlags & LinearTextFlag) == 0) {
-        letterSpace = round(letterSpace);
-        letterSpaceHalfLeft = floor(letterSpace * 0.5);
-    } else {
-        letterSpaceHalfLeft = letterSpace * 0.5;
-    }
-    double letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
 
     float x = mAdvance;
     float y = 0;
@@ -716,6 +730,21 @@
             srunend = srunstart;
             hb_script_t script = getScriptRun(buf + start, run.end, &srunend);
 
+            double letterSpace = 0.0;
+            double letterSpaceHalfLeft = 0.0;
+            double letterSpaceHalfRight = 0.0;
+
+            if (ctx->paint.letterSpacing != 0.0 && isScriptOkForLetterspacing(script)) {
+                letterSpace = ctx->paint.letterSpacing * size * scaleX;
+                if ((ctx->paint.paintFlags & LinearTextFlag) == 0) {
+                    letterSpace = round(letterSpace);
+                    letterSpaceHalfLeft = floor(letterSpace * 0.5);
+                } else {
+                    letterSpaceHalfLeft = letterSpace * 0.5;
+                }
+                letterSpaceHalfRight = letterSpace - letterSpaceHalfLeft;
+            }
+
             hb_buffer_clear_contents(buffer);
             hb_buffer_set_script(buffer, script);
             hb_buffer_set_direction(buffer, isRtl? HB_DIRECTION_RTL : HB_DIRECTION_LTR);