Reland "Reland "ICU: SkShaper (bidi iterator only)""
This reverts commit 03cde5f9997d47458c022c29e72b90d5933100f2.
Reason for revert: Fixing the build
Original change's description:
> Revert "Reland "ICU: SkShaper (bidi iterator only)""
>
> This reverts commit 7bc5542a9e752d87a7d65fbcb8e787798869789c.
>
> Reason for revert: breaking Android roll
>
> Original change's description:
> > Reland "ICU: SkShaper (bidi iterator only)"
> >
> > This reverts commit 73f003acfdc68bd7cc1aa1384442bd31d7da43fd.
> >
> > Reason for revert: Fixed the build
> >
> > Original change's description:
> > > Revert "ICU: SkShaper (bidi iterator only)"
> > >
> > > This reverts commit 64e3d040e911687a9e65514696c421a50953a6fe.
> > >
> > > Reason for revert: Breaking google3
> > >
> > > Original change's description:
> > > > ICU: SkShaper (bidi iterator only)
> > > >
> > > > Change-Id: I845cc0a962790ce37600f943473f21f619ee029b
> > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/308508
> > > > Reviewed-by: Ben Wagner <bungeman@google.com>
> > > > Commit-Queue: Julia Lavrova <jlavrova@google.com>
> > >
> > > TBR=djsollen@google.com,bungeman@google.com,reed@google.com,jlavrova@google.com
> > >
> > > Change-Id: Ib081d97f61e57f74bb9414b3973cca640f3b3929
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/309442
> > > Reviewed-by: Julia Lavrova <jlavrova@google.com>
> > > Commit-Queue: Julia Lavrova <jlavrova@google.com>
> >
> > TBR=djsollen@google.com,bungeman@google.com,reed@google.com,jlavrova@google.com
> >
> > Change-Id: I2d9c79deaaac97d3e0eb9b39ec9d53815fdb1f59
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/310757
> > Reviewed-by: Ben Wagner <bungeman@google.com>
> > Commit-Queue: Julia Lavrova <jlavrova@google.com>
>
> TBR=bungeman@google.com,jlavrova@google.com
>
> Change-Id: I89e80462edf8e014d7ea273885feeca17748a63a
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313378
> Reviewed-by: Derek Sollenberger <djsollen@google.com>
> Commit-Queue: Derek Sollenberger <djsollen@google.com>
TBR=djsollen@google.com,bungeman@google.com,jlavrova@google.com
Change-Id: Idce514c64309e7463fa23425d10f1b13dd9c8d18
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313407
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
diff --git a/modules/skshaper/src/SkUnicode_icu.cpp b/modules/skshaper/src/SkUnicode_icu.cpp
index 4e426c2..1a859fe 100644
--- a/modules/skshaper/src/SkUnicode_icu.cpp
+++ b/modules/skshaper/src/SkUnicode_icu.cpp
@@ -15,7 +15,7 @@
#include <vector>
#include <functional>
-using ICUBiDi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>;
+using SkUnicodeBidi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>;
using ICUUText = std::unique_ptr<UText, SkFunctionWrapper<decltype(utext_close), utext_close>>;
using ICUBreakIterator = std::unique_ptr<UBreakIterator, SkFunctionWrapper<decltype(ubrk_close), ubrk_close>>;
@@ -25,7 +25,92 @@
return val < 0 ? 0xFFFD : val;
}
-namespace skia {
+class SkBidiIterator_icu : public SkBidiIterator {
+ SkUnicodeBidi fBidi;
+public:
+ explicit SkBidiIterator_icu(SkUnicodeBidi bidi) : fBidi(std::move(bidi)) {}
+ Position getLength() override { return ubidi_getLength(fBidi.get()); }
+ Level getLevelAt(Position pos) override { return ubidi_getLevelAt(fBidi.get(), pos); }
+
+ static std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t utf16[], int utf16Units, Direction dir) {
+ UErrorCode status = U_ZERO_ERROR;
+ SkUnicodeBidi bidi(ubidi_openSized(utf16Units, 0, &status));
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
+ return nullptr;
+ }
+ SkASSERT(bidi);
+ uint8_t bidiLevel = (dir == SkBidiIterator::kLTR) ? UBIDI_LTR : UBIDI_RTL;
+ // The required lifetime of utf16 isn't well documented.
+ // It appears it isn't used after ubidi_setPara except through ubidi_getText.
+ ubidi_setPara(bidi.get(), (const UChar*)utf16, utf16Units, bidiLevel, nullptr, &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
+ return nullptr;
+ }
+ return std::unique_ptr<SkBidiIterator>(new SkBidiIterator_icu(std::move(bidi)));
+ }
+
+ // ICU bidi iterator works with utf16 but clients (Flutter for instance) may work with utf8
+ // This method allows the clients not to think about all these details
+ static std::unique_ptr<SkBidiIterator> makeBidiIterator(const char utf8[], int utf8Units, Direction dir) {
+ // Convert utf8 into utf16 since ubidi only accepts utf16
+ if (!SkTFitsIn<int32_t>(utf8Units)) {
+ SkDEBUGF("Bidi error: text too long");
+ return nullptr;
+ }
+
+ // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
+ int utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Units);
+ if (utf16Units < 0) {
+ SkDEBUGF("Bidi error: Invalid utf8 input");
+ return nullptr;
+ }
+ std::unique_ptr<uint16_t[]> utf16(new uint16_t[utf16Units]);
+ SkDEBUGCODE(int dstLen =) SkUTF::UTF8ToUTF16(utf16.get(), utf16Units, utf8, utf8Units);
+ SkASSERT(dstLen == utf16Units);
+
+ return makeBidiIterator(utf16.get(), utf16Units, dir);
+ }
+
+ // This method returns the final results only: a list of bidi regions
+ // (this is all SkParagraph really needs; SkShaper however uses the iterator itself)
+ static std::vector<Region> getBidiRegions(const char utf8[], int utf8Units, Direction dir) {
+
+ auto bidiIterator = makeBidiIterator(utf8, utf8Units, dir);
+ std::vector<Region> bidiRegions;
+ const char* start8 = utf8;
+ const char* end8 = utf8 + utf8Units;
+ SkBidiIterator::Level currentLevel = 0;
+
+ Position pos8 = 0;
+ Position pos16 = 0;
+ Position end16 = bidiIterator->getLength();
+ while (pos16 < end16) {
+ auto level = bidiIterator->getLevelAt(pos16);
+ if (pos16 == 0) {
+ currentLevel = level;
+ } else if (level != currentLevel) {
+ auto end = start8 - utf8;
+ bidiRegions.emplace_back(pos8, end, currentLevel);
+ currentLevel = level;
+ pos8 = end;
+ }
+ SkUnichar u = utf8_next(&start8, end8);
+ pos16 += SkUTF::ToUTF16(u);
+ }
+ auto end = start8 - utf8;
+ if (end != pos8) {
+ bidiRegions.emplace_back(pos8, end, currentLevel);
+ }
+ return bidiRegions;
+ }
+};
+
+void SkBidiIterator::ReorderVisual(const Level runLevels[], int levelsCount,
+ int32_t logicalFromVisual[]) {
+ ubidi_reorderVisual(runLevels, levelsCount, logicalFromVisual);
+}
class SkUnicode_icu : public SkUnicode {
@@ -52,7 +137,7 @@
return utf16Units;
}
- static bool extractBidi(const char utf8[], int utf8Units, Direction dir, std::vector<BidiRegion>* bidiRegions) {
+ static bool extractBidi(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* bidiRegions) {
// Convert to UTF16 since for now bidi iterator only operates on utf16
std::unique_ptr<uint16_t[]> utf16;
@@ -63,13 +148,13 @@
// Create bidi iterator
UErrorCode status = U_ZERO_ERROR;
- ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
+ SkUnicodeBidi bidi(ubidi_openSized(utf16Units, 0, &status));
if (U_FAILURE(status)) {
SkDEBUGF("Bidi error: %s", u_errorName(status));
return false;
}
SkASSERT(bidi);
- uint8_t bidiLevel = (dir == Direction::kLTR) ? UBIDI_LTR : UBIDI_RTL;
+ uint8_t bidiLevel = (dir == TextDirection::kLTR) ? UBIDI_LTR : UBIDI_RTL;
// The required lifetime of utf16 isn't well documented.
// It appears it isn't used after ubidi_setPara except through ubidi_getText.
ubidi_setPara(bidi.get(), (const UChar*)utf16.get(), utf16Units, bidiLevel, nullptr, &status);
@@ -193,8 +278,16 @@
public:
~SkUnicode_icu() override { }
+ std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count,
+ SkBidiIterator::Direction dir) override {
+ return SkBidiIterator_icu::makeBidiIterator(text, count, dir);
+ }
+ std::unique_ptr<SkBidiIterator> makeBidiIterator(const char text[], int count,
+ SkBidiIterator::Direction dir) override {
+ return SkBidiIterator_icu::makeBidiIterator(text, count, dir);
+ }
- bool getBidiRegions(const char utf8[], int utf8Units, Direction dir, std::vector<BidiRegion>* results) override {
+ bool getBidiRegions(const char utf8[], int utf8Units, TextDirection dir, std::vector<BidiRegion>* results) override {
return extractBidi(utf8, utf8Units, dir, results);
}
@@ -238,6 +331,3 @@
};
std::unique_ptr<SkUnicode> SkUnicode::Make() { return std::make_unique<SkUnicode_icu>(); }
-
-} // namespace skia
-