Reland "SkParagraph"
This is a reland of 10ad0b9b01e4b8a4721ae2ec1adee9ca7d0fe534
Original change's description:
> SkParagraph
>
> Change-Id: I0a4be75fd0c18021c201bcc1edfdfad8556edeff
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/192100
> Reviewed-by: Ben Wagner <bungeman@google.com>
> Reviewed-by: Mike Reed <reed@google.com>
> Commit-Queue: Julia Lavrova <jlavrova@google.com>
Change-Id: I46cf43eae693edf68e45345acd0eb39e04e02bfc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/219863
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Julia Lavrova <jlavrova@google.com>
diff --git a/modules/skparagraph/src/ParagraphBuilderImpl.cpp b/modules/skparagraph/src/ParagraphBuilderImpl.cpp
new file mode 100644
index 0000000..0a97527
--- /dev/null
+++ b/modules/skparagraph/src/ParagraphBuilderImpl.cpp
@@ -0,0 +1,106 @@
+// Copyright 2019 Google LLC.
+#include "modules/skparagraph/src/ParagraphBuilderImpl.h"
+#include "include/core/SkPaint.h"
+#include "modules/skparagraph/include/ParagraphStyle.h"
+#include "modules/skparagraph/src/ParagraphImpl.h"
+#include "src/core/SkMakeUnique.h"
+#include "src/core/SkSpan.h"
+#include "unicode/unistr.h"
+
+namespace skia {
+namespace textlayout {
+
+std::shared_ptr<ParagraphBuilder> ParagraphBuilder::make(
+ ParagraphStyle style, sk_sp<FontCollection> fontCollection) {
+ return std::make_shared<ParagraphBuilderImpl>(style, fontCollection);
+}
+
+ParagraphBuilderImpl::ParagraphBuilderImpl(
+ ParagraphStyle style, sk_sp<FontCollection> fontCollection)
+ : ParagraphBuilder(style, fontCollection), fFontCollection(std::move(fontCollection)) {
+ this->setParagraphStyle(style);
+}
+
+ParagraphBuilderImpl::~ParagraphBuilderImpl() = default;
+
+void ParagraphBuilderImpl::setParagraphStyle(const ParagraphStyle& style) {
+ fParagraphStyle = style;
+ fTextStyles.push(fParagraphStyle.getTextStyle());
+ fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), fParagraphStyle.getTextStyle());
+}
+
+void ParagraphBuilderImpl::pushStyle(const TextStyle& style) {
+ this->endRunIfNeeded();
+
+ fTextStyles.push(style);
+ if (!fStyledBlocks.empty() && fStyledBlocks.back().fEnd == fUtf8.size() &&
+ fStyledBlocks.back().fStyle == style) {
+ // Just continue with the same style
+ } else {
+ // Go with the new style
+ fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), fTextStyles.top());
+ }
+}
+
+void ParagraphBuilderImpl::pop() {
+ this->endRunIfNeeded();
+
+ if (fTextStyles.size() > 1) {
+ fTextStyles.pop();
+ } else {
+ // In this case we use paragraph style and skip Pop operation
+ SkDebugf("SkParagraphBuilder.Pop() called too many times.\n");
+ }
+
+ auto top = fTextStyles.top();
+ fStyledBlocks.emplace_back(fUtf8.size(), fUtf8.size(), top);
+}
+
+TextStyle ParagraphBuilderImpl::peekStyle() {
+ this->endRunIfNeeded();
+
+ if (!fTextStyles.empty()) {
+ return fTextStyles.top();
+ } else {
+ SkDebugf("SkParagraphBuilder._styles is empty.\n");
+ return fParagraphStyle.getTextStyle();
+ }
+}
+
+void ParagraphBuilderImpl::addText(const std::u16string& text) {
+ icu::UnicodeString unicode;
+ unicode.setTo((UChar*)text.data());
+ std::string str;
+ unicode.toUTF8String(str);
+ // SkDebugf("Layout text16: '%s'\n", str.c_str());
+ fUtf8.insert(fUtf8.size(), str.c_str());
+}
+
+void ParagraphBuilderImpl::addText(const char* text) {
+ // SkDebugf("Layout text8: '%s'\n", text);
+ fUtf8.insert(fUtf8.size(), text);
+}
+
+void ParagraphBuilderImpl::endRunIfNeeded() {
+ if (fStyledBlocks.empty()) {
+ return;
+ }
+
+ auto& last = fStyledBlocks.back();
+ if (last.fStart == fUtf8.size()) {
+ fStyledBlocks.pop_back();
+ } else {
+ last.fEnd = fUtf8.size();
+ }
+}
+
+std::unique_ptr<Paragraph> ParagraphBuilderImpl::Build() {
+ if (!fUtf8.isEmpty()) {
+ this->endRunIfNeeded();
+ }
+ return skstd::make_unique<ParagraphImpl>(
+ fUtf8, fParagraphStyle, fStyledBlocks, fFontCollection);
+}
+
+} // namespace textlayout
+} // namespace skia