• 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/SkRSXform.h"
18 #include "include/core/SkSpan.h"
19 #include "include/core/SkTypes.h"
20 #include "include/private/SkTemplates.h"
21 #include "src/core/SkZip.h"
22 
23 class SkBaseDevice;
24 class SkCanvas;
25 class SkGlyph;
26 class SkTextBlob;
27 class SkTextBlobRunIterator;
28 
29 class SkGlyphRun {
30 public:
31     SkGlyphRun() = default;
32     SkGlyphRun(const SkFont& font,
33                SkSpan<const SkPoint> positions,
34                SkSpan<const SkGlyphID> glyphIDs,
35                SkSpan<const char> text,
36                SkSpan<const uint32_t> clusters,
37                SkSpan<const SkVector> scaledRotations);
38 
39     SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
40 
runSize()41     size_t runSize() const { return fSource.size(); }
positions()42     SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
glyphsIDs()43     SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
source()44     SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
font()45     const SkFont& font() const { return fFont; }
clusters()46     SkSpan<const uint32_t> clusters() const { return fClusters; }
text()47     SkSpan<const char> text() const { return fText; }
scaledRotations()48     SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }
49     SkRect sourceBounds(const SkPaint& paint) const;
50 
51 private:
52     // GlyphIDs and positions.
53     const SkZip<const SkGlyphID, const SkPoint> fSource;
54     // Original text from SkTextBlob if present. Will be empty of not present.
55     const SkSpan<const char> fText;
56     // Original clusters from SkTextBlob if present. Will be empty if not present.
57     const SkSpan<const uint32_t>   fClusters;
58     // Possible RSXForm information
59     const SkSpan<const SkVector> fScaledRotations;
60     // Font for this run modified to have glyph encoding and left alignment.
61     SkFont fFont;
62 };
63 
64 class SkGlyphRunList {
65     SkSpan<const SkGlyphRun> fGlyphRuns;
66 
67 public:
68     SkGlyphRunList();
69     // Blob maybe null.
70     SkGlyphRunList(
71             const SkTextBlob* blob,
72             SkRect bounds,
73             SkPoint origin,
74             SkSpan<const SkGlyphRun> glyphRunList);
75 
76     SkGlyphRunList(const SkGlyphRun& glyphRun, const SkRect& bounds, SkPoint origin);
77 
78     uint64_t uniqueID() const;
79     bool anyRunsLCD() 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 SkGlyphRun& run : *this) {
87             glyphCount += run.runSize();
88         }
89         return glyphCount;
90     }
91 
hasRSXForm()92     bool hasRSXForm() const {
93         for (const SkGlyphRun& run : *this) {
94             if (!run.scaledRotations().empty()) { return true; }
95         }
96         return false;
97     }
98 
99     sk_sp<SkTextBlob> makeBlob() const;
100 
origin()101     SkPoint origin() const { return fOrigin; }
sourceBounds()102     SkRect sourceBounds() const { return fSourceBounds; }
blob()103     const SkTextBlob* blob() const { return fOriginalTextBlob; }
104 
105     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();      }
106     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();        }
107     auto begin() const -> decltype(std::cbegin(fGlyphRuns))    { return std::cbegin(fGlyphRuns); }
108     auto end()   const -> decltype(std::cend(fGlyphRuns))      { return std::cend(fGlyphRuns);   }
109     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();       }
110     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();      }
111     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];         }
112 
113 private:
114     // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
115     // should be used for nothing else
116     const SkTextBlob* fOriginalTextBlob{nullptr};
117     const SkRect fSourceBounds{SkRect::MakeEmpty()};
118     const SkPoint fOrigin = {0, 0};
119 };
120 
121 class SkGlyphRunBuilder {
122 public:
123     const SkGlyphRunList& textToGlyphRunList(const SkFont& font,
124                                              const SkPaint& paint,
125                                              const void* bytes,
126                                              size_t byteLength,
127                                              SkPoint origin,
128                                              SkTextEncoding encoding = SkTextEncoding::kUTF8);
129     const SkGlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin);
130     std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
131             convertRSXForm(SkSpan<const SkRSXform> xforms);
132 
empty()133     bool empty() const { return fGlyphRunListStorage.empty(); }
134 
135 private:
136     void initialize(const SkTextBlob& blob);
137     void prepareBuffers(int positionCount, int RSXFormCount);
138 
139     SkSpan<const SkGlyphID> textToGlyphIDs(
140             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
141 
142     void makeGlyphRun(
143             const SkFont& font,
144             SkSpan<const SkGlyphID> glyphIDs,
145             SkSpan<const SkPoint> positions,
146             SkSpan<const char> text,
147             SkSpan<const uint32_t> clusters,
148             SkSpan<const SkVector> scaledRotations);
149 
150     const SkGlyphRunList& makeGlyphRunList(
151             const SkTextBlob* blob, const SkRect& bounds, SkPoint origin);
152 
153     int fMaxTotalRunSize{0};
154     SkAutoTMalloc<SkPoint> fPositions;
155     int fMaxScaledRotations{0};
156     SkAutoTMalloc<SkVector> fScaledRotations;
157 
158     std::vector<SkGlyphRun> fGlyphRunListStorage;
159     SkGlyphRunList fGlyphRunList;
160 
161     // Used as a temporary for preparing using utfN text. This implies that only one run of
162     // glyph ids will ever be needed because blobs are already glyph based.
163     std::vector<SkGlyphID> fScratchGlyphIDs;
164 };
165 
166 #endif  // SkGlyphRun_DEFINED
167