From 686d245a0f231167240e156c010609275e571068 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Mon, 12 May 2014 15:10:30 -0700 Subject: [PATCH] Initial BiDi support This patch contains a very basic implementation of BiDi. It respects the BiDi flags passed in as an explicit parameter (through the "-minikin-bidi" pseudo-CSS property), but doesn't yet do its own BiDi run detection. It also takes some shortcuts (marked as TODO) that are based on reasonable assumptions of the current font stack, but not universally valid. Even with these shortcomings, it seems to display RTL text from TextView correctly. Change-Id: I223433923c4eb06f90c0327e86bfbe0aff71d4f5 --- engine/src/flutter/include/minikin/CssParse.h | 2 ++ engine/src/flutter/libs/minikin/CssParse.cpp | 1 + engine/src/flutter/libs/minikin/Layout.cpp | 13 +++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/include/minikin/CssParse.h b/engine/src/flutter/include/minikin/CssParse.h index f79ba1f61c..2dceb4ac26 100644 --- a/engine/src/flutter/include/minikin/CssParse.h +++ b/engine/src/flutter/include/minikin/CssParse.h @@ -28,6 +28,7 @@ enum CssTag { fontWeight, fontStyle, minikinHinting, + minikinBidi, }; const std::string cssTagNames[] = { @@ -36,6 +37,7 @@ const std::string cssTagNames[] = { "font-weight", "font-style", "-minikin-hinting", + "-minikin-bidi", }; class CssValue { diff --git a/engine/src/flutter/libs/minikin/CssParse.cpp b/engine/src/flutter/libs/minikin/CssParse.cpp index d4de23bee0..5bb6949b9a 100644 --- a/engine/src/flutter/libs/minikin/CssParse.cpp +++ b/engine/src/flutter/libs/minikin/CssParse.cpp @@ -41,6 +41,7 @@ CssTag parseTag(const string str, size_t off, size_t len) { if (strEqC(str, off, len, "font-style")) return fontStyle; } else if (c == '-') { if (strEqC(str, off, len, "-minikin-hinting")) return minikinHinting; + if (strEqC(str, off, len, "-minikin-bidi")) return minikinBidi; } return unknown; } diff --git a/engine/src/flutter/libs/minikin/Layout.cpp b/engine/src/flutter/libs/minikin/Layout.cpp index 08365b354e..3a0be6abef 100644 --- a/engine/src/flutter/libs/minikin/Layout.cpp +++ b/engine/src/flutter/libs/minikin/Layout.cpp @@ -19,10 +19,12 @@ #include #include +#include #include #include // for debugging #include // ditto +#include #include #include "MinikinInternal.h" @@ -91,7 +93,6 @@ void Layout::init() { } void Layout::setFontCollection(const FontCollection *collection) { - ALOGD("setFontCollection(%p)", collection); mCollection = collection; } @@ -290,6 +291,11 @@ void Layout::doLayout(const uint16_t* buf, size_t nchars) { MinikinPaint paint; double size = mProps.value(fontSize).getFloatValue(); paint.size = size; + int bidiFlags = mProps.hasTag(minikinBidi) ? mProps.value(minikinBidi).getIntValue() : 0; + bool isRtl = (bidiFlags & 1) != 0; // TODO: do real bidi algo + if (isRtl) { + std::reverse(items.begin(), items.end()); + } mGlyphs.clear(); mFaces.clear(); @@ -315,6 +321,9 @@ void Layout::doLayout(const uint16_t* buf, size_t nchars) { hb_font_set_ppem(hbFont, size, size); hb_font_set_scale(hbFont, HBFloatToFixed(size), HBFloatToFixed(size)); + // TODO: if there are multiple scripts within a font in an RTL run, + // we need to reorder those runs. This is unlikely with our current + // font stack, but should be done for correctness. ssize_t srunend; for (ssize_t srunstart = run.start; srunstart < run.end; srunstart = srunend) { srunend = srunstart; @@ -322,7 +331,7 @@ void Layout::doLayout(const uint16_t* buf, size_t nchars) { hb_buffer_reset(buffer); hb_buffer_set_script(buffer, script); - hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); + hb_buffer_set_direction(buffer, isRtl? HB_DIRECTION_RTL : HB_DIRECTION_LTR); hb_buffer_add_utf16(buffer, buf, nchars, srunstart, srunend - srunstart); hb_shape(hbFont, buffer, NULL, 0); unsigned int numGlyphs;