1 // Copyright 2019 Google LLC. 2 #ifndef FontIterator_DEFINED 3 #define FontIterator_DEFINED 4 5 #include <unicode/brkiter.h> 6 #include <unicode/ubidi.h> 7 #include "include/core/SkBlurTypes.h" 8 #include "include/core/SkCanvas.h" 9 #include "include/core/SkFontMgr.h" 10 #include "include/core/SkPictureRecorder.h" 11 #include "modules/skparagraph/src/FontResolver.h" 12 #include "modules/skparagraph/src/ParagraphImpl.h" 13 #include "src/core/SkSpan.h" 14 #include "src/utils/SkUTF.h" 15 16 namespace skia { 17 namespace textlayout { 18 19 class FontIterator final : public SkShaper::FontRunIterator { 20 public: FontIterator(SkSpan<const char> utf8,FontResolver * fontResolver)21 FontIterator(SkSpan<const char> utf8, FontResolver* fontResolver) 22 : fText(utf8), fCurrentChar(utf8.begin()), fFontResolver(fontResolver) { 23 } 24 consume()25 void consume() override { 26 SkASSERT(fCurrentChar < fText.end()); 27 auto found = fFontResolver->findNext(fCurrentChar, &fFont, &fLineHeight); 28 SkASSERT(found); 29 if (!found) { 30 fCurrentChar = fText.end(); 31 return; 32 } 33 // Move until we find the first character that cannot be resolved with the current font 34 while (++fCurrentChar != fText.end()) { 35 SkFont font; 36 SkScalar height; 37 if (fFontResolver->findNext(fCurrentChar, &font, &height)) { 38 if (fFont == font && fLineHeight == height) { 39 continue; 40 } 41 break; 42 } 43 } 44 } 45 endOfCurrentRun()46 size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); } atEnd()47 bool atEnd() const override { return fCurrentChar == fText.end(); } currentFont()48 const SkFont& currentFont() const override { return fFont; } currentLineHeight()49 SkScalar currentLineHeight() const { return fLineHeight; } 50 51 private: 52 53 SkSpan<const char> fText; 54 const char* fCurrentChar; 55 SkFont fFont; 56 SkScalar fLineHeight; 57 FontResolver* fFontResolver; 58 }; 59 60 class LangIterator final : public SkShaper::LanguageRunIterator { 61 public: LangIterator(SkSpan<const char> utf8,SkSpan<Block> styles,const TextStyle & defaultStyle)62 LangIterator(SkSpan<const char> utf8, SkSpan<Block> styles, const TextStyle& defaultStyle) 63 : fText(utf8) 64 , fTextStyles(styles) 65 , fCurrentChar(utf8.begin()) 66 , fCurrentStyle(fTextStyles.begin()) 67 , fCurrentLocale(defaultStyle.getLocale()) {} 68 consume()69 void consume() override { 70 SkASSERT(fCurrentChar < fText.end()); 71 72 if (fCurrentStyle == fTextStyles.end()) { 73 fCurrentChar = fText.end(); 74 return; 75 } 76 77 fCurrentChar = fText.begin() + fCurrentStyle->fRange.end; 78 fCurrentLocale = fCurrentStyle->fStyle.getLocale(); 79 while (++fCurrentStyle != fTextStyles.end()) { 80 if (fCurrentStyle->fStyle.getLocale() != fCurrentLocale) { 81 break; 82 } 83 fCurrentChar = fText.begin() + fCurrentStyle->fRange.end; 84 } 85 } 86 endOfCurrentRun()87 size_t endOfCurrentRun() const override { return fCurrentChar - fText.begin(); } atEnd()88 bool atEnd() const override { return fCurrentChar == fText.end(); } currentLanguage()89 const char* currentLanguage() const override { return fCurrentLocale.c_str(); } 90 91 private: 92 SkSpan<const char> fText; 93 SkSpan<Block> fTextStyles; 94 const char* fCurrentChar; 95 Block* fCurrentStyle; 96 SkString fCurrentLocale; 97 }; 98 } // namespace textlayout 99 } // namespace skia 100 101 #endif // FontIterator_DEFINED 102