blob: ec8ef46d5b9115c453bad948116a1d26f8dbf775 [file] [log] [blame]
Julia Lavrovaa3552c52019-05-30 16:12:56 -04001// Copyright 2019 Google LLC.
Julia Lavrovaa3552c52019-05-30 16:12:56 -04002#include "include/core/SkPaint.h"
3#include "modules/skparagraph/include/ParagraphStyle.h"
Greg Danielf91aeb22019-06-18 09:58:02 -04004#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
Julia Lavrovaa3552c52019-05-30 16:12:56 -04005#include "modules/skparagraph/src/ParagraphImpl.h"
6#include "src/core/SkMakeUnique.h"
7#include "src/core/SkSpan.h"
8#include "unicode/unistr.h"
9
10namespace skia {
11namespace textlayout {
12
Julia Lavrova6e6333f2019-06-17 10:34:10 -040013std::unique_ptr<ParagraphBuilder> ParagraphBuilder::make(
Julia Lavrovaa3552c52019-05-30 16:12:56 -040014 ParagraphStyle style, sk_sp<FontCollection> fontCollection) {
Julia Lavrova6e6333f2019-06-17 10:34:10 -040015 return skstd::make_unique<ParagraphBuilderImpl>(style, fontCollection);
Julia Lavrovaa3552c52019-05-30 16:12:56 -040016}
17
18ParagraphBuilderImpl::ParagraphBuilderImpl(
19 ParagraphStyle style, sk_sp<FontCollection> fontCollection)
20 : ParagraphBuilder(style, fontCollection), fFontCollection(std::move(fontCollection)) {
21 this->setParagraphStyle(style);
22}
23
24ParagraphBuilderImpl::~ParagraphBuilderImpl() = default;
25
26void ParagraphBuilderImpl::setParagraphStyle(const ParagraphStyle& style) {
27 fParagraphStyle = style;
28 fTextStyles.push(fParagraphStyle.getTextStyle());
29 fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), fParagraphStyle.getTextStyle());
30}
31
32void ParagraphBuilderImpl::pushStyle(const TextStyle& style) {
33 this->endRunIfNeeded();
34
35 fTextStyles.push(style);
36 if (!fStyledBlocks.empty() && fStyledBlocks.back().fEnd == fUtf8.size() &&
37 fStyledBlocks.back().fStyle == style) {
38 // Just continue with the same style
39 } else {
40 // Go with the new style
41 fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), fTextStyles.top());
42 }
43}
44
45void ParagraphBuilderImpl::pop() {
46 this->endRunIfNeeded();
47
48 if (fTextStyles.size() > 1) {
49 fTextStyles.pop();
50 } else {
51 // In this case we use paragraph style and skip Pop operation
52 SkDebugf("SkParagraphBuilder.Pop() called too many times.\n");
53 }
54
55 auto top = fTextStyles.top();
56 fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), top);
57}
58
59TextStyle ParagraphBuilderImpl::peekStyle() {
60 this->endRunIfNeeded();
61
62 if (!fTextStyles.empty()) {
63 return fTextStyles.top();
64 } else {
65 SkDebugf("SkParagraphBuilder._styles is empty.\n");
66 return fParagraphStyle.getTextStyle();
67 }
68}
69
70void ParagraphBuilderImpl::addText(const std::u16string& text) {
71 icu::UnicodeString unicode;
72 unicode.setTo((UChar*)text.data());
73 std::string str;
74 unicode.toUTF8String(str);
75 // SkDebugf("Layout text16: '%s'\n", str.c_str());
76 fUtf8.insert(fUtf8.size(), str.c_str());
77}
78
79void ParagraphBuilderImpl::addText(const char* text) {
80 // SkDebugf("Layout text8: '%s'\n", text);
81 fUtf8.insert(fUtf8.size(), text);
82}
83
84void ParagraphBuilderImpl::endRunIfNeeded() {
85 if (fStyledBlocks.empty()) {
86 return;
87 }
88
89 auto& last = fStyledBlocks.back();
90 if (last.fStart == fUtf8.size()) {
91 fStyledBlocks.pop_back();
92 } else {
93 last.fEnd = fUtf8.size();
94 }
95}
96
97std::unique_ptr<Paragraph> ParagraphBuilderImpl::Build() {
98 if (!fUtf8.isEmpty()) {
99 this->endRunIfNeeded();
100 }
101 return skstd::make_unique<ParagraphImpl>(
102 fUtf8, fParagraphStyle, fStyledBlocks, fFontCollection);
103}
104
105} // namespace textlayout
106} // namespace skia