• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 Google LLC.
2 #include "experimental/sktext/editor/Texts.h"
3 
4 using namespace skia::text;
5 
6 namespace skia {
7 namespace editor {
8 
paint(SkCanvas * canvas)9 void DynamicText::paint(SkCanvas* canvas) {
10     if (!fDrawableText) {
11         auto chunks = this->getDecorationChunks(fDecorations);
12         fDrawableText = fWrappedText->prepareToDraw<DrawableText>(fUnicodeText.get(),
13                                                                   PositionType::kGraphemeCluster,
14                                                                   SkSpan<TextIndex>(chunks.data(), chunks.size()));
15     }
16 
17     auto foregroundPaint = fDecorations[0].foregroundPaint;
18     auto textBlobs = fDrawableText->getTextBlobs();
19     for (auto& textBLob : textBlobs) {
20         canvas->drawTextBlob(textBLob, 0, 0, foregroundPaint);
21     }
22 }
23 
getDecorationChunks(SkSpan<DecoratedBlock> decorations) const24 std::vector<TextIndex> DynamicText::getDecorationChunks(SkSpan<DecoratedBlock> decorations) const {
25     std::vector<TextIndex> result;
26     TextIndex textIndex = 0;
27     for (auto& decoration : decorations) {
28         textIndex += decoration.charCount;
29         result.emplace_back(textIndex);
30     }
31     return result;
32 }
33 
paint(SkCanvas * canvas)34 void EditableText::paint(SkCanvas* canvas) {
35 
36     if (fSelection->isEmpty()) {
37         DynamicText::paint(canvas);
38     } else {
39         auto decorations = mergeSelectionIntoDecorations();
40         auto chunks = this->getDecorationChunks(SkSpan<DecoratedBlock>(decorations.data(), decorations.size()));
41         fDrawableText = fWrappedText->prepareToDraw<DrawableText>(fUnicodeText.get(),
42                                                                   PositionType::kGraphemeCluster,
43                                                                   SkSpan<TextIndex>(chunks.data(), chunks.size()));
44     }
45     auto foregroundPaint = fDecorations[0].foregroundPaint;
46     auto textBlobs = fDrawableText->getTextBlobs();
47     for (auto& textBLob : textBlobs) {
48         canvas->drawTextBlob(textBLob, 0, 0, foregroundPaint);
49     }
50 }
51 
mergeSelectionIntoDecorations()52 SkTArray<DecoratedBlock> EditableText::mergeSelectionIntoDecorations() {
53     SkTArray<DecoratedBlock> merged;
54     merged.reserve_back(fDecorations.size() + fSelection->count());
55 
56     size_t indexDecor = 0ul;                        // index in fDecorations
57     size_t decorPos = 0ul;
58     for (auto& selected : fSelection->fTextRanges) {
59         // Add all the decoration blocks that are placed before the selected block
60         DecoratedBlock& decor = fDecorations[indexDecor];
61         while (indexDecor < fDecorations.size()) {
62             decor = fDecorations[indexDecor++];
63             if (decorPos + decor.charCount >= selected.fStart) {
64                 break;
65             }
66             // The entire decoration block is before
67             merged.emplace_back(decor);
68             decorPos += decor.charCount;
69         }
70 
71         auto lastDecorPos = decorPos;
72         if (selected.fStart > decorPos) {
73             // The decoration block is has a part that is before the selection so we add it
74             merged.emplace_back(selected.fStart - decorPos, decor.foregroundPaint, decor.backgroundPaint);
75             decorPos = selected.fStart;
76         }
77         SkASSERT(decorPos == selected.fStart);
78 
79         // So the next decoration intersects the selection (and the selection wins)
80         merged.emplace_back(selected.width(), fSelection->fForeground, fSelection->fBackground);
81         decorPos += selected.width();
82         SkASSERT(decorPos == selected.fEnd);
83 
84         if (lastDecorPos + decor.charCount > selected.fEnd) {
85             // We still need to add the rest of the decoration block
86             merged.emplace_back(lastDecorPos + decor.charCount - selected.fEnd, decor.foregroundPaint, decor.backgroundPaint);
87             decorPos += lastDecorPos + decor.charCount - selected.fEnd;
88         }
89     }
90     return merged;
91 }
92 
93 } // namespace editor
94 } // namespace skia
95