1 /* 2 * Copyright 2025 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #include "modules/skunicode/include/SkUnicode_bidi.h" 8 9 #include "include/core/SkSpan.h" 10 #include "include/core/SkString.h" 11 #include "include/core/SkTypes.h" 12 #include "include/private/base/SkTArray.h" 13 #include "include/private/base/SkTo.h" 14 #include "modules/skunicode/include/SkUnicode.h" 15 #include "modules/skunicode/src/SkBidiFactory_icu_subset.h" 16 #include "modules/skunicode/src/SkUnicode_hardcoded.h" 17 #include "modules/skunicode/src/SkUnicode_icu_bidi.h" 18 #include "src/base/SkBitmaskEnum.h" 19 #include "src/base/SkUTF.h" 20 21 #include <algorithm> 22 #include <cstdint> 23 #include <memory> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 #include <array> 28 #include <unicode/ubidi.h> 29 #include <unicode/ubrk.h> 30 #include <unicode/uchar.h> 31 #include <unicode/uloc.h> 32 #include <unicode/uscript.h> 33 #include <unicode/ustring.h> 34 #include <unicode/utext.h> 35 #include <unicode/utypes.h> 36 37 using namespace skia_private; 38 39 class SkUnicode_bidi : public SkUnicodeHardCodedCharProperties { 40 public: SkUnicode_bidi()41 SkUnicode_bidi() {} 42 ~SkUnicode_bidi() override = default; 43 makeBidiIterator(const uint16_t text[],int count,SkBidiIterator::Direction dir)44 std::unique_ptr<SkBidiIterator> makeBidiIterator(const uint16_t text[], int count, 45 SkBidiIterator::Direction dir) override { 46 return fBidiFact->MakeIterator(text, count, dir); 47 } makeBidiIterator(const char text[],int count,SkBidiIterator::Direction dir)48 std::unique_ptr<SkBidiIterator> makeBidiIterator(const char text[], 49 int count, 50 SkBidiIterator::Direction dir) override { 51 SkDEBUGF("Method 'makeBidiIterator' is not implemented\n"); 52 return nullptr; 53 } makeBreakIterator(const char locale[],BreakType breakType)54 std::unique_ptr<SkBreakIterator> makeBreakIterator(const char locale[], 55 BreakType breakType) override { 56 SkDEBUGF("Method 'makeBreakIterator' is not implemented\n"); 57 return nullptr; 58 } makeBreakIterator(BreakType breakType)59 std::unique_ptr<SkBreakIterator> makeBreakIterator(BreakType breakType) override { 60 SkDEBUGF("Method 'makeBreakIterator' is not implemented\n"); 61 return nullptr; 62 } 63 getBidiRegions(const char utf8[],int utf8Units,TextDirection dir,std::vector<BidiRegion> * results)64 bool getBidiRegions(const char utf8[], 65 int utf8Units, 66 TextDirection dir, 67 std::vector<BidiRegion>* results) override { 68 return fBidiFact->ExtractBidi(utf8, utf8Units, dir, results); 69 } 70 getUtf8Words(const char utf8[],int utf8Units,const char * locale,std::vector<Position> * results)71 bool getUtf8Words(const char utf8[], 72 int utf8Units, 73 const char* locale, 74 std::vector<Position>* results) override { 75 SkDEBUGF("Method 'getUtf8Words' is not implemented\n"); 76 return false; 77 } 78 getSentences(const char utf8[],int utf8Units,const char * locale,std::vector<SkUnicode::Position> * results)79 bool getSentences(const char utf8[], 80 int utf8Units, 81 const char* locale, 82 std::vector<SkUnicode::Position>* results) override { 83 SkDEBUGF("Method 'getSentences' is not implemented\n"); 84 return false; 85 } 86 computeCodeUnitFlags(char utf8[],int utf8Units,bool replaceTabs,TArray<SkUnicode::CodeUnitFlags,true> * results)87 bool computeCodeUnitFlags(char utf8[], 88 int utf8Units, 89 bool replaceTabs, 90 TArray<SkUnicode::CodeUnitFlags, true>* results) override { 91 SkDEBUGF("Method 'computeCodeUnitFlags' is not implemented\n"); 92 return false; 93 } 94 computeCodeUnitFlags(char16_t utf16[],int utf16Units,bool replaceTabs,TArray<SkUnicode::CodeUnitFlags,true> * results)95 bool computeCodeUnitFlags(char16_t utf16[], int utf16Units, bool replaceTabs, 96 TArray<SkUnicode::CodeUnitFlags, true>* results) override { 97 results->clear(); 98 results->push_back_n(utf16Units + 1, CodeUnitFlags::kNoCodeUnitFlag); 99 for (auto i = 0; i < utf16Units; ++i) { 100 auto unichar = utf16[i]; 101 if (this->isSpace(unichar)) { 102 results->at(i) |= SkUnicode::kPartOfIntraWordBreak; 103 } 104 if (this->isWhitespace(unichar)) { 105 results->at(i) |= SkUnicode::kPartOfWhiteSpaceBreak; 106 } 107 if (this->isControl(unichar)) { 108 results->at(i) |= SkUnicode::kControl; 109 } 110 if (this->isIdeographic(unichar)) { 111 results->at(i) |= SkUnicode::kIdeographic; 112 } 113 } 114 return true; 115 } 116 getWords(const char utf8[],int utf8Units,const char * locale,std::vector<Position> * results)117 bool getWords(const char utf8[], int utf8Units, const char* locale, std::vector<Position>* results) override { 118 SkDEBUGF("Method 'getWords' is not implemented\n"); 119 return false; 120 } 121 toUpper(const SkString & str)122 SkString toUpper(const SkString& str) override { 123 SkDEBUGF("Method 'toUpper' is not implemented\n"); 124 return SkString(); 125 } 126 toUpper(const SkString & str,const char * locale)127 SkString toUpper(const SkString& str, const char* locale) override { 128 SkDEBUGF("Method 'toUpper' is not implemented\n"); 129 return SkString(); 130 } 131 reorderVisual(const BidiLevel runLevels[],int levelsCount,int32_t logicalFromVisual[])132 void reorderVisual(const BidiLevel runLevels[], 133 int levelsCount, 134 int32_t logicalFromVisual[]) override { 135 fBidiFact->bidi_reorderVisual(runLevels, levelsCount, logicalFromVisual); 136 } 137 138 private: 139 sk_sp<SkBidiFactory> fBidiFact = sk_make_sp<SkBidiSubsetFactory>(); 140 }; 141 142 namespace SkUnicodes::Bidi { Make()143 sk_sp<SkUnicode> Make() { 144 return sk_make_sp<SkUnicode_bidi>(); 145 } 146 } 147