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