1 // Copyright 2021 Google LLC.
2 
3 #include "experimental/sktext/include/Processor.h"
4 #include "experimental/sktext/src/Shaper.h"
5 
6 namespace skia {
7 namespace text {
8 
9 // TODO: calculate intrinsic sizes
10 // Shape the text in one line
process()11 bool Shaper::process() {
12 
13     auto text(fProcessor->fText);
14     for (auto& block : fProcessor->fFontBlocks) {
15 
16         SkFont font(this->createFont(block));
17 
18         SkShaper::TrivialFontRunIterator fontIter(font, text.size());
19         SkShaper::TrivialLanguageRunIterator langIter(text.c_str(), text.size());
20         std::unique_ptr<SkShaper::BiDiRunIterator> bidiIter(
21             SkShaper::MakeSkUnicodeBidiRunIterator(
22                 fProcessor->fUnicode.get(), text.c_str(), text.size(), fDefaultTextDirection == TextDirection::kLtr ? 0 : 1));
23         std::unique_ptr<SkShaper::ScriptRunIterator> scriptIter(
24             SkShaper::MakeSkUnicodeHbScriptRunIterator(fProcessor->fUnicode.get(), text.c_str(), text.size()));
25         auto shaper = SkShaper::MakeShapeDontWrapOrReorder();
26         if (shaper == nullptr) {
27             // For instance, loadICU does not work. We have to stop the process
28             return false;
29         }
30 
31         shaper->shape(text.c_str(), text.size(),
32                 fontIter, *bidiIter, *scriptIter, langIter,
33                 std::numeric_limits<SkScalar>::max(), this);
34     }
35 
36     return true;
37 }
38 
commitRunBuffer(const RunInfo &)39 void Shaper::commitRunBuffer(const RunInfo&) {
40     fCurrentRun->commit();
41     fProcessor->fRuns.emplace_back(std::move(*fCurrentRun));
42 }
43 
createFont(const FontBlock & block)44 SkFont Shaper::createFont(const FontBlock& block) {
45 
46     sk_sp<SkTypeface> typeface = matchTypeface(block.fFontFamily, block.fFontStyle);
47 
48     SkFont font(std::move(typeface), block.fFontSize);
49     font.setEdging(SkFont::Edging::kAntiAlias);
50     font.setHinting(SkFontHinting::kSlight);
51     font.setSubpixel(true);
52 
53     return font;
54 }
55 
matchTypeface(const SkString & fontFamily,SkFontStyle fontStyle)56 sk_sp<SkTypeface> Shaper::matchTypeface(const SkString& fontFamily, SkFontStyle fontStyle) {
57     sk_sp<SkFontStyleSet> set(fFontManager->matchFamily(fontFamily.c_str()));
58     if (!set || set->count() == 0) {
59         return nullptr;
60     }
61 
62     sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
63     if (match) {
64         return match;
65     }
66 
67     return nullptr;
68 }
69 
70 } // namespace text
71 } // namespace skia
72