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>
diff --git a/modules/skparagraph/src/ParagraphImpl.cpp b/modules/skparagraph/src/ParagraphImpl.cpp
index b0c0470..7849f9a 100644
--- a/modules/skparagraph/src/ParagraphImpl.cpp
+++ b/modules/skparagraph/src/ParagraphImpl.cpp
@@ -83,7 +83,7 @@
, fOldWidth(0)
, fOldHeight(0)
, fOrigin(SkRect::MakeEmpty()) {
- fICU = ::SkUnicode::Make();
+ fICU = ::skia::SkUnicode::Make();
}
ParagraphImpl::ParagraphImpl(const std::u16string& utf16text,
diff --git a/modules/skshaper/include/SkShaper.h b/modules/skshaper/include/SkShaper.h
index a8f724f..c0864af 100644
--- a/modules/skshaper/include/SkShaper.h
+++ b/modules/skshaper/include/SkShaper.h
@@ -39,7 +39,6 @@
class SkFont;
class SkFontMgr;
-class SkUnicode;
/**
Shapes text using HarfBuzz and places the shaped text into a
@@ -134,9 +133,9 @@
static std::unique_ptr<BiDiRunIterator>
MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
- #ifdef SK_UNICODE_AVAILABLE
+ #ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
static std::unique_ptr<BiDiRunIterator>
- MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
+ MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel);
#endif
class TrivialBiDiRunIterator : public TrivialRunIterator<BiDiRunIterator> {
public:
diff --git a/modules/skshaper/src/SkShaper.cpp b/modules/skshaper/src/SkShaper.cpp
index 185d349..bd2df51 100644
--- a/modules/skshaper/src/SkShaper.cpp
+++ b/modules/skshaper/src/SkShaper.cpp
@@ -38,13 +38,9 @@
std::unique_ptr<SkShaper::BiDiRunIterator>
SkShaper::MakeBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
-#ifdef SK_UNICODE_AVAILABLE
- auto unicode = SkUnicode::Make();
+#ifdef SK_SHAPER_HARFBUZZ_AVAILABLE
std::unique_ptr<SkShaper::BiDiRunIterator> bidi =
- SkShaper::MakeSkUnicodeBidiRunIterator(unicode.get(),
- utf8,
- utf8Bytes,
- bidiLevel);
+ SkShaper::MakeIcuBiDiRunIterator(utf8, utf8Bytes, bidiLevel);
if (bidi) {
return bidi;
}
diff --git a/modules/skshaper/src/SkShaper_harfbuzz.cpp b/modules/skshaper/src/SkShaper_harfbuzz.cpp
index fd36b9c..905747f 100644
--- a/modules/skshaper/src/SkShaper_harfbuzz.cpp
+++ b/modules/skshaper/src/SkShaper_harfbuzz.cpp
@@ -26,7 +26,6 @@
#include "include/private/SkTemplates.h"
#include "include/private/SkTo.h"
#include "modules/skshaper/include/SkShaper.h"
-#include "modules/skshaper/src/SkUnicode.h"
#include "src/core/SkLRUCache.h"
#include "src/core/SkSpan.h"
#include "src/core/SkTDPQueue.h"
@@ -35,6 +34,7 @@
#include <hb.h>
#include <hb-icu.h>
#include <hb-ot.h>
+#include <unicode/ubidi.h>
#include <unicode/ubrk.h>
#include <unicode/umachine.h>
#include <unicode/urename.h>
@@ -71,11 +71,10 @@
using HBFace = resource<hb_face_t , decltype(hb_face_destroy) , hb_face_destroy >;
using HBFont = resource<hb_font_t , decltype(hb_font_destroy) , hb_font_destroy >;
using HBBuffer = resource<hb_buffer_t , decltype(hb_buffer_destroy), hb_buffer_destroy>;
+using ICUBiDi = resource<UBiDi , decltype(ubidi_close) , ubidi_close >;
using ICUBrk = resource<UBreakIterator, decltype(ubrk_close) , ubrk_close >;
using ICUUText = resource<UText , decltype(utext_close) , utext_close >;
-using SkUnicodeBidi = std::unique_ptr<SkBidiIterator>;
-
hb_position_t skhb_position(SkScalar value) {
// Treat HarfBuzz hb_position_t as 16.16 fixed-point.
constexpr int kHbPosition1 = 1 << 16;
@@ -344,26 +343,25 @@
return val < 0 ? 0xFFFD : val;
}
-class SkUnicodeBidiRunIterator final : public SkShaper::BiDiRunIterator {
+class IcuBiDiRunIterator final : public SkShaper::BiDiRunIterator {
public:
- SkUnicodeBidiRunIterator(const char* utf8, const char* end, SkUnicodeBidi bidi)
+ IcuBiDiRunIterator(const char* utf8, const char* end, ICUBiDi bidi)
: fBidi(std::move(bidi))
, fEndOfCurrentRun(utf8)
, fBegin(utf8)
, fEnd(end)
, fUTF16LogicalPosition(0)
- , fLevel(SkBidiIterator::kLTR)
+ , fLevel(UBIDI_DEFAULT_LTR)
{}
-
void consume() override {
- SkASSERT(fUTF16LogicalPosition < fBidi->getLength());
- int32_t endPosition = fBidi->getLength();
- fLevel = fBidi->getLevelAt(fUTF16LogicalPosition);
+ SkASSERT(fUTF16LogicalPosition < ubidi_getLength(fBidi.get()));
+ int32_t endPosition = ubidi_getLength(fBidi.get());
+ fLevel = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
SkUnichar u = utf8_next(&fEndOfCurrentRun, fEnd);
fUTF16LogicalPosition += SkUTF::ToUTF16(u);
- SkBidiIterator::Level level;
+ UBiDiLevel level;
while (fUTF16LogicalPosition < endPosition) {
- level = fBidi->getLevelAt(fUTF16LogicalPosition);
+ level = ubidi_getLevelAt(fBidi.get(), fUTF16LogicalPosition);
if (level != fLevel) {
break;
}
@@ -376,18 +374,19 @@
return fEndOfCurrentRun - fBegin;
}
bool atEnd() const override {
- return fUTF16LogicalPosition == fBidi->getLength();
+ return fUTF16LogicalPosition == ubidi_getLength(fBidi.get());
}
- SkBidiIterator::Level currentLevel() const override {
+
+ UBiDiLevel currentLevel() const override {
return fLevel;
}
private:
- SkUnicodeBidi fBidi;
+ ICUBiDi fBidi;
char const * fEndOfCurrentRun;
char const * const fBegin;
char const * const fEnd;
int32_t fUTF16LogicalPosition;
- SkBidiIterator::Level fLevel;
+ UBiDiLevel fLevel;
};
class HbIcuScriptRunIterator final : public SkShaper::ScriptRunIterator {
@@ -510,7 +509,7 @@
bool fUnsafeToBreak;
};
struct ShapedRun {
- ShapedRun(SkShaper::RunHandler::Range utf8Range, const SkFont& font, SkBidiIterator::Level level,
+ ShapedRun(SkShaper::RunHandler::Range utf8Range, const SkFont& font, UBiDiLevel level,
std::unique_ptr<ShapedGlyph[]> glyphs, size_t numGlyphs, SkVector advance = {0, 0})
: fUtf8Range(utf8Range), fFont(font), fLevel(level)
, fGlyphs(std::move(glyphs)), fNumGlyphs(numGlyphs), fAdvance(advance)
@@ -518,7 +517,7 @@
SkShaper::RunHandler::Range fUtf8Range;
SkFont fFont;
- SkBidiIterator::Level fLevel;
+ UBiDiLevel fLevel;
std::unique_ptr<ShapedGlyph[]> fGlyphs;
size_t fNumGlyphs;
SkVector fAdvance;
@@ -528,7 +527,7 @@
SkVector fAdvance = { 0, 0 };
};
-constexpr bool is_LTR(SkBidiIterator::Level level) {
+constexpr bool is_LTR(UBiDiLevel level) {
return (level & 1) == 0;
}
@@ -566,12 +565,12 @@
handler->beginLine();
int numRuns = line.runs.size();
- SkAutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
+ SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
for (int i = 0; i < numRuns; ++i) {
runLevels[i] = line.runs[i].fLevel;
}
SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
- SkBidiIterator::ReorderVisual(runLevels, numRuns, logicalFromVisual);
+ ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
for (int i = 0; i < numRuns; ++i) {
int logicalIndex = logicalFromVisual[i];
@@ -668,7 +667,6 @@
const FontRunIterator&,
const Feature*, size_t featuresSize) const;
private:
- std::unique_ptr<SkUnicode> fUnicode = SkUnicode::Make();
const sk_sp<SkFontMgr> fFontMgr;
HBBuffer fBuffer;
hb_language_t fUndefinedLanguage;
@@ -806,12 +804,9 @@
SkScalar width,
RunHandler* handler) const
{
- SkBidiIterator::Level defaultLevel = leftToRight ? SkBidiIterator::kLTR : SkBidiIterator::kRTL;
- std::unique_ptr<BiDiRunIterator> bidi(MakeSkUnicodeBidiRunIterator(fUnicode.get(),
- utf8,
- utf8Bytes,
- defaultLevel));
+ UBiDiLevel defaultLevel = leftToRight ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL;
+ std::unique_ptr<BiDiRunIterator> bidi(MakeIcuBiDiRunIterator(utf8, utf8Bytes, defaultLevel));
if (!bidi) {
return;
}
@@ -1187,12 +1182,12 @@
}
int numRuns = current.fRunIndex - previousBreak.fRunIndex + 1;
- SkAutoSTMalloc<4, SkBidiIterator::Level> runLevels(numRuns);
+ SkAutoSTMalloc<4, UBiDiLevel> runLevels(numRuns);
for (int i = 0; i < numRuns; ++i) {
runLevels[i] = runs[previousBreak.fRunIndex + i].fLevel;
}
SkAutoSTMalloc<4, int32_t> logicalFromVisual(numRuns);
- SkBidiIterator::ReorderVisual(runLevels, numRuns, logicalFromVisual);
+ ubidi_reorderVisual(runLevels, numRuns, logicalFromVisual);
// step through the runs in reverse visual order and the glyphs in reverse logical order
// until a visible glyph is found and force them to the end of the visual line.
@@ -1442,7 +1437,7 @@
} // namespace
std::unique_ptr<SkShaper::BiDiRunIterator>
-SkShaper::MakeSkUnicodeBidiRunIterator(SkUnicode* unicode, const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
+SkShaper::MakeIcuBiDiRunIterator(const char* utf8, size_t utf8Bytes, uint8_t bidiLevel) {
// ubidi only accepts utf16 (though internally it basically works on utf32 chars).
// We want an ubidi_setPara(UBiDi*, UText*, UBiDiLevel, UBiDiLevel*, UErrorCode*);
if (!SkTFitsIn<int32_t>(utf8Bytes)) {
@@ -1450,23 +1445,35 @@
return nullptr;
}
- int32_t utf16Units = SkUTF::UTF8ToUTF16(nullptr, 0, utf8, utf8Bytes);
- if (utf16Units < 0) {
- SkDEBUGF("Invalid utf8 input\n");
+ UErrorCode status = U_ZERO_ERROR;
+
+ // Getting the length like this seems to always set U_BUFFER_OVERFLOW_ERROR
+ int32_t utf16Units;
+ u_strFromUTF8(nullptr, 0, &utf16Units, utf8, utf8Bytes, &status);
+ status = U_ZERO_ERROR;
+ std::unique_ptr<UChar[]> utf16(new UChar[utf16Units]);
+ u_strFromUTF8(utf16.get(), utf16Units, nullptr, utf8, utf8Bytes, &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Invalid utf8 input: %s", u_errorName(status));
return nullptr;
}
- std::unique_ptr<uint16_t[]> utf16(new uint16_t[utf16Units]);
- (void)SkUTF::UTF8ToUTF16(utf16.get(), utf16Units, utf8, utf8Bytes);
+ ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
+ return nullptr;
+ }
+ SkASSERT(bidi);
- auto bidiDir = (bidiLevel % 2 == 0) ? SkBidiIterator::kLTR : SkBidiIterator::kRTL;
- SkUnicodeBidi bidi = unicode->makeBidiIterator(utf16.get(), utf16Units, bidiDir);
- if (!bidi) {
- SkDEBUGF("Bidi error\n");
+ // 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(), utf16.get(), utf16Units, bidiLevel, nullptr, &status);
+ if (U_FAILURE(status)) {
+ SkDEBUGF("Bidi error: %s", u_errorName(status));
return nullptr;
}
- return std::make_unique<SkUnicodeBidiRunIterator>(utf8, utf8 + utf8Bytes, std::move(bidi));
+ return std::make_unique<IcuBiDiRunIterator>(utf8, utf8 + utf8Bytes, std::move(bidi));
}
std::unique_ptr<SkShaper::ScriptRunIterator>
diff --git a/modules/skshaper/src/SkUnicode.h b/modules/skshaper/src/SkUnicode.h
index 0b5b363..2219ce3 100644
--- a/modules/skshaper/src/SkUnicode.h
+++ b/modules/skshaper/src/SkUnicode.h
@@ -31,6 +31,8 @@
#endif
#endif
+namespace skia {
+
enum class UtfFormat {
kUTF8,
kUTF16
@@ -71,40 +73,12 @@
Position end;
};
-class SKUNICODE_API SkBidiIterator {
-public:
- typedef int32_t Position;
- typedef uint8_t Level;
- struct Region {
- Region(Position start, Position end, Level level)
- : start(start), end(end), level(level) { }
- Position start;
- Position end;
- Level level;
- };
- enum Direction {
- kLTR,
- kRTL,
- };
- virtual ~SkBidiIterator() {}
- virtual Position getLength() = 0;
- virtual Level getLevelAt(Position) = 0;
- static void ReorderVisual(const Level runLevels[], int levelsCount, int32_t logicalFromVisual[]);
-};
-
class SKUNICODE_API SkUnicode {
public:
typedef uint32_t ScriptID;
typedef uint32_t CombiningClass;
typedef uint32_t GeneralCategory;
virtual ~SkUnicode() = default;
-
- // Iterators (used in SkShaper)
- virtual std::unique_ptr<SkBidiIterator> makeBidiIterator
- (const uint16_t text[], int count, SkBidiIterator::Direction) = 0;
- virtual std::unique_ptr<SkBidiIterator> makeBidiIterator
- (const char text[], int count, SkBidiIterator::Direction) = 0;
-
// High level methods (that we actually use somewhere=SkParagraph)
virtual bool getBidiRegions
(const char utf8[], int utf8Units, Direction dir, std::vector<BidiRegion>* results) = 0;
@@ -122,4 +96,6 @@
static std::unique_ptr<SkUnicode> Make();
};
+} // namespace skia
+
#endif // SkUnicode_DEFINED
diff --git a/modules/skshaper/src/SkUnicode_icu.cpp b/modules/skshaper/src/SkUnicode_icu.cpp
index 7f218b9..4e426c2 100644
--- a/modules/skshaper/src/SkUnicode_icu.cpp
+++ b/modules/skshaper/src/SkUnicode_icu.cpp
@@ -15,7 +15,7 @@
#include <vector>
#include <functional>
-using SkUnicodeBidi = std::unique_ptr<UBiDi, SkFunctionWrapper<decltype(ubidi_close), ubidi_close>>;
+using ICUBiDi = 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,92 +25,7 @@
return val < 0 ? 0xFFFD : val;
}
-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);
-}
+namespace skia {
class SkUnicode_icu : public SkUnicode {
@@ -148,7 +63,7 @@
// Create bidi iterator
UErrorCode status = U_ZERO_ERROR;
- SkUnicodeBidi bidi(ubidi_openSized(utf16Units, 0, &status));
+ ICUBiDi bidi(ubidi_openSized(utf16Units, 0, &status));
if (U_FAILURE(status)) {
SkDEBUGF("Bidi error: %s", u_errorName(status));
return false;
@@ -278,14 +193,6 @@
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 {
return extractBidi(utf8, utf8Units, dir, results);
@@ -331,3 +238,6 @@
};
std::unique_ptr<SkUnicode> SkUnicode::Make() { return std::make_unique<SkUnicode_icu>(); }
+
+} // namespace skia
+