Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: src/core/SkTextBlob.cpp

Issue 473633002: SkTextBlob (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Alloc API + review comments Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« include/core/SkTextBlob.h ('K') | « src/core/SkRecords.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 Google Inc.
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 #include "SkTextBlob.h"
9
10 SkTextBlob::SkTextBlob(uint16_t *glyphs, SkScalar *pos, const SkTArray<Run> *run s,
11 const SkRect& bounds)
12 : fGlyphBuffer(glyphs)
13 , fPosBuffer(pos)
14 , fRuns(runs)
15 , fBounds(bounds) {
16 }
17
18 uint32_t SkTextBlob::uniqueID() const {
19 static int32_t gTextBlobGenerationID; // = 0;
20
21 // loop in case our global wraps around, as we never want to return SK_Inval idGenID
22 while (SK_InvalidGenID == fUniqueID) {
23 fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1;
24 }
25
26 return fUniqueID;
27 }
28
29 SkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob)
30 : fBlob(blob)
31 , fIndex(0) {
32 SkASSERT(NULL != blob);
33 }
34
35 bool SkTextBlob::RunIterator::done() const {
36 return NULL == fBlob->fRuns.get() || fIndex >= fBlob->fRuns->count();
37 }
38
39 void SkTextBlob::RunIterator::next() {
40 SkASSERT(!this->done());
41 fIndex++;
42 }
43
44 uint32_t SkTextBlob::RunIterator::glyphCount() const {
45 SkASSERT(!this->done());
46 return (*fBlob->fRuns)[fIndex].count;
47 }
48
49 const uint16_t* SkTextBlob::RunIterator::glyphs() const {
50 SkASSERT(!this->done());
51 return fBlob->fGlyphBuffer.get() + (*fBlob->fRuns)[fIndex].glyphStart;
52 }
53
54 const SkScalar* SkTextBlob::RunIterator::pos() const {
55 SkASSERT(!this->done());
56 return fBlob->fPosBuffer.get() + (*fBlob->fRuns)[fIndex].posStart;
57 }
58
59 const SkPaint& SkTextBlob::RunIterator::font() const {
60 SkASSERT(!this->done());
61 return (*fBlob->fRuns)[fIndex].font;
62 }
63
64 SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const {
65 SkASSERT(!this->done());
66 return (*fBlob->fRuns)[fIndex].positioning;
67 }
68
69 SkTextBlobBuilder::SkTextBlobBuilder(unsigned runs)
70 : fRuns(NULL)
71 , fDeferredBounds(false) {
72
73 if (runs > 0) {
74 // if the number of runs is known, size our run storage accordingly.
75 fRuns = SkNEW(SkTArray<SkTextBlob::Run>(runs));
76 }
77 fBounds.setEmpty();
78 }
79
80 SkTextBlobBuilder::~SkTextBlobBuilder() {
81 // unused runs
82 SkDELETE(fRuns);
83 }
84
85 void SkTextBlobBuilder::updateDeferredBounds() {
86 SkASSERT(!fDeferredBounds || (NULL != fRuns && !fRuns->empty()));
87
88 if (!fDeferredBounds) {
89 return;
90 }
91
92 // FIXME: measure the current run & union bounds
93 fDeferredBounds = false;
94 }
95
96 void SkTextBlobBuilder::ensureRun(const SkPaint& font, SkTextBlob::GlyphPosition ing pos,
97 const SkPoint& offset) {
98 SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
99
100 if (NULL == fRuns) {
101 fRuns = SkNEW(SkTArray<SkTextBlob::Run>());
102 }
103
104 // we can merge same-font/same-positioning runs in the following cases:
105 // * fully positioned run following another fully positioned run
106 // * horizontally postioned run following another horizontally positioned run with the same
107 // y-offset
108 if (!fRuns->empty()
109 && fRuns->back().positioning == pos
110 && fRuns->back().font == font
111 && (SkTextBlob::kFull_Positioning == fRuns->back().positioning
112 || (SkTextBlob::kHorizontal_Positioning == fRuns->back().positioning
113 && fRuns->back().offset.y() == offset.y()))){
114 return;
115 }
116
117 this->updateDeferredBounds();
118
119 // start a new run
120 SkTextBlob::Run& newRun = fRuns->push_back();
121 newRun.count = 0;
122 newRun.glyphStart = fGlyphBuffer.count();
123 newRun.posStart = fPosBuffer.count();
124 newRun.offset = offset;
125 newRun.font = font;
126 newRun.positioning = pos;
127 }
128
129 void SkTextBlobBuilder::alloc_internal(const SkPaint &font,
130 SkTextBlob::GlyphPositioning positioning,
131 size_t count, SkPoint offset, const SkRec t* bounds) {
132 this->ensureRun(font, positioning, offset);
133
134 fGlyphBuffer.append(count);
135 fPosBuffer.append(count * positioning);
jbroman 2014/08/20 15:10:32 nit: It's not immediately obvious why this works (
f(malita) 2014/08/20 15:47:47 Done.
136
137 SkASSERT(NULL != fRuns && !fRuns->empty());
138 fRuns->back().count += count;
139
140 if (!fDeferredBounds) {
141 if (NULL != bounds) {
142 fBounds.join(*bounds);
143 } else {
144 fDeferredBounds = true;
145 }
146 }
147 }
148
149 SkTextBlobBuilder::RunBuffer SkTextBlobBuilder::currentRunBuffer() {
150 SkASSERT(NULL != fRuns && !fRuns->empty());
151
152 RunBuffer buffer;
153 buffer.glyphs = fGlyphBuffer.isEmpty()
154 ? NULL
155 : fGlyphBuffer.begin() + fRuns->back().glyphStart;
156 buffer.pos = fPosBuffer.isEmpty()
157 ? NULL
158 : fPosBuffer.begin() + fRuns->back().posStart;
159
160 return buffer;
161 }
162
163 uint16_t* SkTextBlobBuilder::allocRun(const SkPaint& font, size_t count, SkPoint offset,
164 const SkRect* bounds) {
165 alloc_internal(font, SkTextBlob::kDefault_Positioning, count, offset, bounds );
166
167 return fGlyphBuffer.begin() + fRuns->back().glyphStart;
168 }
169
170 SkTextBlobBuilder::RunBuffer SkTextBlobBuilder::allocRun(const SkPaint& font, si ze_t count,
171 SkScalar yOffset, const SkRect* bounds) {
robertphillips 2014/08/20 14:52:18 this->allocInternal ?
f(malita) 2014/08/20 15:47:47 Done.
172 alloc_internal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoint::Ma ke(0, yOffset),
173 bounds);
174
robertphillips 2014/08/20 14:52:18 this-> ?
f(malita) 2014/08/20 15:47:47 Done.
175 return currentRunBuffer();
176 }
177
178 SkTextBlobBuilder::RunBuffer SkTextBlobBuilder::allocRun(const SkPaint& font, si ze_t count,
179 const SkRect *bounds) {
180 alloc_internal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Make(0, 0), bounds);
181
robertphillips 2014/08/20 14:52:18 this-> ?
f(malita) 2014/08/20 15:47:47 Done.
182 return currentRunBuffer();
183 }
184
185 const SkTextBlob* SkTextBlobBuilder::build() {
186 const SkTextBlob* leBlob;
jbroman 2014/08/20 15:10:32 nit: what does "le blob" mean? Why not "blob"?
f(malita) 2014/08/20 15:47:47 Done.
187
188 if (fGlyphBuffer.count() > 0) {
189 // we have some glyphs, construct a real blob
190 SkASSERT(NULL != fRuns && !fRuns->empty());
191
192 this->updateDeferredBounds();
193
194 // ownership of all buffers is transferred to the blob
195 leBlob = SkNEW_ARGS(SkTextBlob, (fGlyphBuffer.detach(),
196 fPosBuffer.detach(),
197 fRuns,
198 fBounds));
199 fRuns = NULL;
200 fBounds.setEmpty();
201 } else {
202 // empty blob
203 SkASSERT(NULL == fRuns || fRuns->empty());
204 SkASSERT(fBounds.isEmpty());
205
206 leBlob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())) ;
207 }
208
209 return leBlob;
210 }
211
OLDNEW
« include/core/SkTextBlob.h ('K') | « src/core/SkRecords.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698