• 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 <vector>
13 
14 #include "include/core/SkFont.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPoint.h"
17 #include "include/core/SkTypes.h"
18 #include "include/private/SkTemplates.h"
19 #include "src/core/SkSpan.h"
20 
21 class SkBaseDevice;
22 class SkGlyph;
23 class SkTextBlob;
24 class SkTextBlobRunIterator;
25 
26 class SkGlyphRun {
27 public:
28     SkGlyphRun() = default;
29     SkGlyphRun(const SkFont& font,
30                SkSpan<const SkPoint> positions,
31                SkSpan<const SkGlyphID> glyphIDs,
32                SkSpan<const char> text,
33                SkSpan<const uint32_t> clusters);
34     SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
35 
36     void filloutGlyphsAndPositions(SkGlyphID* glyphIDs, SkPoint* positions);
37 
runSize()38     size_t runSize() const { return fGlyphIDs.size(); }
positions()39     SkSpan<const SkPoint> positions() const { return fPositions; }
glyphsIDs()40     SkSpan<const SkGlyphID> glyphsIDs() const { return fGlyphIDs; }
font()41     const SkFont& font() const { return fFont; }
clusters()42     SkSpan<const uint32_t> clusters() const { return fClusters; }
text()43     SkSpan<const char> text() const { return fText; }
44 
45 private:
46     // Positions of each glyph.
47     const SkSpan<const SkPoint> fPositions;
48     // This is temporary while converting from the old per glyph code to the bulk code.
49     const SkSpan<const SkGlyphID> fGlyphIDs;
50     // Original text from SkTextBlob if present. Will be empty of not present.
51     const SkSpan<const char> fText;
52     // Original clusters from SkTextBlob if present. Will be empty if not present.
53     const SkSpan<const uint32_t>   fClusters;
54     // Paint for this run modified to have glyph encoding and left alignment.
55     SkFont fFont;
56 };
57 
58 class SkGlyphRunList {
59     const SkPaint* fOriginalPaint{nullptr};  // This should be deleted soon.
60     // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
61     // should be used for nothing else
62     const SkTextBlob*  fOriginalTextBlob{nullptr};
63     SkPoint fOrigin = {0, 0};
64     SkSpan<const SkGlyphRun> fGlyphRuns;
65 
66 public:
67     SkGlyphRunList();
68     // Blob maybe null.
69     SkGlyphRunList(
70             const SkPaint& paint,
71             const SkTextBlob* blob,
72             SkPoint origin,
73             SkSpan<const SkGlyphRun> glyphRunList);
74 
75     SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint);
76 
77     uint64_t uniqueID() const;
78     bool anyRunsLCD() const;
79     bool anyRunsSubpixelPositioned() const;
80     void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
81 
canCache()82     bool canCache() const { return fOriginalTextBlob != nullptr; }
runCount()83     size_t runCount() const { return fGlyphRuns.size(); }
totalGlyphCount()84     size_t totalGlyphCount() const {
85         size_t glyphCount = 0;
86         for(const auto& run : fGlyphRuns) {
87             glyphCount += run.runSize();
88         }
89         return glyphCount;
90     }
91     bool allFontsFinite() const;
92 
origin()93     SkPoint origin() const { return fOrigin; }
paint()94     const SkPaint& paint() const { return *fOriginalPaint; }
blob()95     const SkTextBlob* blob() const { return fOriginalTextBlob; }
96 
97     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();  }
98     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();    }
99     auto begin() const -> decltype(fGlyphRuns.cbegin())        { return fGlyphRuns.cbegin(); }
100     auto end()   const -> decltype(fGlyphRuns.cend())          { return fGlyphRuns.cend();   }
101     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();   }
102     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();  }
103     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];     }
104 };
105 
106 class SkGlyphIDSet {
107 public:
108     SkSpan<const SkGlyphID> uniquifyGlyphIDs(
109             uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs,
110             SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices);
111 private:
112     size_t fUniverseToUniqueSize{0};
113     SkAutoTMalloc<uint16_t> fUniverseToUnique;
114 };
115 
116 class SkGlyphRunBuilder {
117 public:
118     void drawTextUTF8(
119         const SkPaint& paint, const SkFont&, const void* bytes, size_t byteLength, SkPoint origin);
120     void drawGlyphsWithPositions(
121             const SkPaint&, const SkFont&, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos);
122     void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkBaseDevice*);
123 
124     void textBlobToGlyphRunListIgnoringRSXForm(
125             const SkPaint& paint, const SkTextBlob& blob, SkPoint origin);
126 
127     const SkGlyphRunList& useGlyphRunList();
128 
empty()129     bool empty() const { return fGlyphRunListStorage.size() == 0; }
130 
131 private:
132     void initialize(size_t totalRunSize);
133     SkSpan<const SkGlyphID> textToGlyphIDs(
134             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
135 
136     void makeGlyphRun(
137             const SkFont& font,
138             SkSpan<const SkGlyphID> glyphIDs,
139             SkSpan<const SkPoint> positions,
140             SkSpan<const char> text,
141             SkSpan<const uint32_t> clusters);
142 
143     void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin);
144 
145     void simplifyDrawText(
146             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
147             SkPoint origin, SkPoint* positions,
148             SkSpan<const char> text = SkSpan<const char>{},
149             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
150     void simplifyDrawPosTextH(
151             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
152             const SkScalar* xpos, SkScalar constY, SkPoint* positions,
153             SkSpan<const char> text = SkSpan<const char>{},
154             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
155     void simplifyDrawPosText(
156             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
157             const SkPoint* pos,
158             SkSpan<const char> text = SkSpan<const char>{},
159             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
160     void simplifyTextBlobIgnoringRSXForm(
161             const SkTextBlobRunIterator& it,
162             SkPoint* positions);
163 
164     size_t fMaxTotalRunSize{0};
165     SkAutoTMalloc<SkPoint> fPositions;
166 
167     std::vector<SkGlyphRun> fGlyphRunListStorage;
168     SkGlyphRunList fGlyphRunList;
169 
170     // Used as a temporary for preparing using utfN text. This implies that only one run of
171     // glyph ids will ever be needed because blobs are already glyph based.
172     std::vector<SkGlyphID> fScratchGlyphIDs;
173 
174     // Used for collecting the set of unique glyphs.
175     SkGlyphIDSet fGlyphIDSet;
176     SkAutoTMalloc<SkGlyphID> fUniqueGlyphIDs;
177     SkAutoTMalloc<uint16_t> fUniqueGlyphIDIndices;
178 };
179 
180 #endif  // SkGlyphRun_DEFINED
181