• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGlyphRun_DEFINED
9 #define SkGlyphRun_DEFINED
10 
11 #include <functional>
12 #include <optional>
13 #include <vector>
14 
15 #include "include/core/SkFont.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPoint.h"
18 #include "include/core/SkRSXform.h"
19 #include "include/core/SkSpan.h"
20 #include "include/core/SkTypes.h"
21 #include "include/private/base/SkTemplates.h"
22 #include "src/base/SkZip.h"
23 #include "src/core/SkGlyphBuffer.h"
24 
25 class SkBaseDevice;
26 class SkCanvas;
27 class SkGlyph;
28 class SkTextBlob;
29 class SkTextBlobRunIterator;
30 
31 namespace sktext {
32 class GlyphRunBuilder;
33 class GlyphRunList;
34 
35 class SkSubRunBuffers {
36 public:
37     class ScopedBuffers {
38     public:
39         ScopedBuffers(SkSubRunBuffers* painter, size_t size);
40         ~ScopedBuffers();
buffers()41         std::tuple<SkDrawableGlyphBuffer*, SkSourceGlyphBuffer*> buffers() {
42             return {&fBuffers->fAccepted, &fBuffers->fRejected};
43         }
44 
45     private:
46         SkSubRunBuffers* const fBuffers;
47     };
48     static ScopedBuffers SK_WARN_UNUSED_RESULT EnsureBuffers(const GlyphRunList& glyphRunList);
49 
50 private:
51     SkDrawableGlyphBuffer fAccepted;
52     SkSourceGlyphBuffer fRejected;
53 };
54 
55 class GlyphRun {
56 public:
57     GlyphRun(const SkFont& font,
58              SkSpan<const SkPoint> positions,
59              SkSpan<const SkGlyphID> glyphIDs,
60              SkSpan<const char> text,
61              SkSpan<const uint32_t> clusters,
62              SkSpan<const SkVector> scaledRotations);
63 
64     GlyphRun(const GlyphRun& glyphRun, const SkFont& font);
65 
runSize()66     size_t runSize() const { return fSource.size(); }
positions()67     SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
glyphsIDs()68     SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
source()69     SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
font()70     const SkFont& font() const { return fFont; }
clusters()71     SkSpan<const uint32_t> clusters() const { return fClusters; }
text()72     SkSpan<const char> text() const { return fText; }
scaledRotations()73     SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }
74 
75 private:
76     // GlyphIDs and positions.
77     const SkZip<const SkGlyphID, const SkPoint> fSource;
78     // Original text from SkTextBlob if present. Will be empty of not present.
79     const SkSpan<const char> fText;
80     // Original clusters from SkTextBlob if present. Will be empty if not present.
81     const SkSpan<const uint32_t>   fClusters;
82     // Possible RSXForm information
83     const SkSpan<const SkVector> fScaledRotations;
84     // Font for this run modified to have glyph encoding and left alignment.
85     SkFont fFont;
86 };
87 
88 class GlyphRunList {
89     SkSpan<const GlyphRun> fGlyphRuns;
90 
91 public:
92     // Blob maybe null.
93     GlyphRunList(const SkTextBlob* blob,
94                  SkRect bounds,
95                  SkPoint origin,
96                  SkSpan<const GlyphRun> glyphRunList,
97                  GlyphRunBuilder* builder);
98 
99     GlyphRunList(const GlyphRun& glyphRun,
100                  const SkRect& bounds,
101                  SkPoint origin,
102                  GlyphRunBuilder* builder);
103     uint64_t uniqueID() const;
104     bool anyRunsLCD() const;
105     void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
106 
canCache()107     bool canCache() const { return fOriginalTextBlob != nullptr; }
runCount()108     size_t runCount() const { return fGlyphRuns.size(); }
totalGlyphCount()109     size_t totalGlyphCount() const {
110         size_t glyphCount = 0;
111         for (const GlyphRun& run : *this) {
112             glyphCount += run.runSize();
113         }
114         return glyphCount;
115     }
maxGlyphRunSize()116     size_t maxGlyphRunSize() const {
117         size_t size = 0;
118         for (const GlyphRun& run : *this) {
119             size = std::max(run.runSize(), size);
120         }
121         return size;
122     }
123 
hasRSXForm()124     bool hasRSXForm() const {
125         for (const GlyphRun& run : *this) {
126             if (!run.scaledRotations().empty()) { return true; }
127         }
128         return false;
129     }
130 
131     sk_sp<SkTextBlob> makeBlob() const;
132 
origin()133     SkPoint origin() const { return fOrigin; }
sourceBounds()134     SkRect sourceBounds() const { return fSourceBounds; }
sourceBoundsWithOrigin()135     SkRect sourceBoundsWithOrigin() const { return fSourceBounds.makeOffset(fOrigin); }
blob()136     const SkTextBlob* blob() const { return fOriginalTextBlob; }
builder()137     GlyphRunBuilder* builder() const { return fBuilder; }
138     SkSubRunBuffers* buffers() const;
139 
140     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();      }
141     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();        }
142     auto begin() const -> decltype(std::cbegin(fGlyphRuns))    { return std::cbegin(fGlyphRuns); }
143     auto end()   const -> decltype(std::cend(fGlyphRuns))      { return std::cend(fGlyphRuns);   }
144     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();       }
145     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();      }
146     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];         }
147 
148 private:
149     // The text blob is needed to hook up the call back that the SkTextBlob destructor calls. It
150     // should be used for nothing else.
151     const SkTextBlob* fOriginalTextBlob{nullptr};
152     const SkRect fSourceBounds{SkRect::MakeEmpty()};
153     const SkPoint fOrigin = {0, 0};
154     GlyphRunBuilder* const fBuilder;
155 };
156 
157 class GlyphRunBuilder {
158 public:
159     GlyphRunList makeGlyphRunList(const GlyphRun& run, const SkPaint& paint, SkPoint origin);
160     const GlyphRunList& textToGlyphRunList(const SkFont& font,
161                                            const SkPaint& paint,
162                                            const void* bytes,
163                                            size_t byteLength,
164                                            SkPoint origin,
165                                            SkTextEncoding encoding = SkTextEncoding::kUTF8);
166     const GlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin);
167     std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
168             convertRSXForm(SkSpan<const SkRSXform> xforms);
169 
empty()170     bool empty() const { return fGlyphRunListStorage.empty(); }
buffers()171     SkSubRunBuffers* buffers() { return &fSubRunBuffers; }
172 
173 private:
174     void initialize(const SkTextBlob& blob);
175     void prepareBuffers(int positionCount, int RSXFormCount);
176 
177     SkSpan<const SkGlyphID> textToGlyphIDs(
178             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
179 
180     void makeGlyphRun(
181             const SkFont& font,
182             SkSpan<const SkGlyphID> glyphIDs,
183             SkSpan<const SkPoint> positions,
184             SkSpan<const char> text,
185             SkSpan<const uint32_t> clusters,
186             SkSpan<const SkVector> scaledRotations);
187 
188     const GlyphRunList& setGlyphRunList(
189             const SkTextBlob* blob, const SkRect& bounds, SkPoint origin);
190 
191     int fMaxTotalRunSize{0};
192     skia_private::AutoTMalloc<SkPoint> fPositions;
193     int fMaxScaledRotations{0};
194     skia_private::AutoTMalloc<SkVector> fScaledRotations;
195 
196     std::vector<GlyphRun> fGlyphRunListStorage;
197     std::optional<GlyphRunList> fGlyphRunList;  // Defaults to no value;
198 
199     // Used as a temporary for preparing using utfN text. This implies that only one run of
200     // glyph ids will ever be needed because blobs are already glyph based.
201     std::vector<SkGlyphID> fScratchGlyphIDs;
202 
203     SkSubRunBuffers fSubRunBuffers;
204 };
buffers()205 inline SkSubRunBuffers* GlyphRunList::buffers() const { return fBuilder->buffers(); }
206 }  // namespace sktext
207 
208 #endif  // SkGlyphRun_DEFINED
209