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

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

Issue 473633002: SkTextBlob (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Build warnings fix. 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
« no previous file with comments | « 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 SkPoint& SkTextBlob::RunIterator::offset() const {
60 SkASSERT(!this->done());
61 return (*fBlob->fRuns)[fIndex].offset;
62 }
63
64 const SkPaint& SkTextBlob::RunIterator::font() const {
65 SkASSERT(!this->done());
66 return (*fBlob->fRuns)[fIndex].font;
67 }
68
69 SkTextBlob::GlyphPositioning SkTextBlob::RunIterator::positioning() const {
70 SkASSERT(!this->done());
71 return (*fBlob->fRuns)[fIndex].positioning;
72 }
73
74 SkTextBlobBuilder::SkTextBlobBuilder(unsigned runs)
75 : fRuns(NULL)
76 , fDeferredBounds(false) {
77
78 if (runs > 0) {
79 // if the number of runs is known, size our run storage accordingly.
80 fRuns = SkNEW(SkTArray<SkTextBlob::Run>(runs));
81 }
82 fBounds.setEmpty();
83 }
84
85 SkTextBlobBuilder::~SkTextBlobBuilder() {
86 // unused runs
87 SkDELETE(fRuns);
88 }
89
90 void SkTextBlobBuilder::updateDeferredBounds() {
91 SkASSERT(!fDeferredBounds || (NULL != fRuns && !fRuns->empty()));
92
93 if (!fDeferredBounds) {
94 return;
95 }
96
97 // FIXME: measure the current run & union bounds
98 fDeferredBounds = false;
99 }
100
101 void SkTextBlobBuilder::ensureRun(const SkPaint& font, SkTextBlob::GlyphPosition ing pos,
102 const SkPoint& offset) {
103 SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
104
105 if (NULL == fRuns) {
106 fRuns = SkNEW(SkTArray<SkTextBlob::Run>());
107 }
108
109 // we can merge same-font/same-positioning runs in the following cases:
110 // * fully positioned run following another fully positioned run
111 // * horizontally postioned run following another horizontally positioned run with the same
112 // y-offset
113 if (!fRuns->empty()
114 && fRuns->back().positioning == pos
115 && fRuns->back().font == font
116 && (SkTextBlob::kFull_Positioning == fRuns->back().positioning
117 || (SkTextBlob::kHorizontal_Positioning == fRuns->back().positioning
118 && fRuns->back().offset.y() == offset.y()))){
119 return;
120 }
121
122 this->updateDeferredBounds();
123
124 // start a new run
125 SkTextBlob::Run& newRun = fRuns->push_back();
126 newRun.count = 0;
127 newRun.glyphStart = fGlyphBuffer.count();
128 newRun.posStart = fPosBuffer.count();
129 newRun.offset = offset;
130 newRun.font = font;
131 newRun.positioning = pos;
132 }
133
134 void SkTextBlobBuilder::allocInternal(const SkPaint &font,
135 SkTextBlob::GlyphPositioning positioning,
136 int count, SkPoint offset, const SkRect* b ounds) {
137 SkASSERT(count > 0);
138
139 this->ensureRun(font, positioning, offset);
140
141 // SkTextBlob::GlyphPositioning values are directly mapped to scalars-per-gl yph.
142 unsigned posScalarsPerGlyph = positioning;
143 SkASSERT(posScalarsPerGlyph <= 2);
144
145 fGlyphBuffer.append(count);
146 fPosBuffer.append(count * posScalarsPerGlyph);
147
148 SkASSERT(NULL != fRuns && !fRuns->empty());
149 SkTextBlob::Run& run = fRuns->back();
150
151 run.count += count;
152
153 // The current run might have been merged, so the start offset may point to prev run data.
154 // Start from the back (which always points to the end of the current run bu ffers) instead.
155 fCurrentRunBuffer.glyphs = fGlyphBuffer.isEmpty()
156 ? NULL : fGlyphBuffer.end() - count;
157 SkASSERT(NULL == fCurrentRunBuffer.glyphs || fCurrentRunBuffer.glyphs >= fGl yphBuffer.begin());
158 fCurrentRunBuffer.pos = fPosBuffer.isEmpty()
159 ? NULL : fPosBuffer.end() - count * posScalarsPerGlyph;
160 SkASSERT(NULL == fCurrentRunBuffer.pos || fCurrentRunBuffer.pos >= fPosBuffe r.begin());
161
162 if (!fDeferredBounds) {
163 if (NULL != bounds) {
164 fBounds.join(*bounds);
165 } else {
166 fDeferredBounds = true;
167 }
168 }
169 }
170
171 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRun(const SkPaint& f ont, int count,
172 SkScalar x, SkSc alar y,
173 const SkRect* bo unds) {
174 this->allocInternal(font, SkTextBlob::kDefault_Positioning, count, SkPoint:: Make(x, y), bounds);
175
176 return fCurrentRunBuffer;
177 }
178
179 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPosH(const SkPain t& font, int count,
180 SkScalar y,
181 const SkRect * bounds) {
182 this->allocInternal(font, SkTextBlob::kHorizontal_Positioning, count, SkPoin t::Make(0, y),
183 bounds);
184
185 return fCurrentRunBuffer;
186 }
187
188 const SkTextBlobBuilder::RunBuffer& SkTextBlobBuilder::allocRunPos(const SkPaint & font, int count,
189 const SkRect *bounds) {
190 this->allocInternal(font, SkTextBlob::kFull_Positioning, count, SkPoint::Mak e(0, 0), bounds);
191
192 return fCurrentRunBuffer;
193 }
194
195 const SkTextBlob* SkTextBlobBuilder::build() {
196 const SkTextBlob* blob;
197
198 if (fGlyphBuffer.count() > 0) {
199 // we have some glyphs, construct a real blob
200 SkASSERT(NULL != fRuns && !fRuns->empty());
201
202 this->updateDeferredBounds();
203
204 // ownership of all buffers is transferred to the blob
205 blob = SkNEW_ARGS(SkTextBlob, (fGlyphBuffer.detach(),
206 fPosBuffer.detach(),
207 fRuns,
208 fBounds));
209 fRuns = NULL;
210 fBounds.setEmpty();
211 } else {
212 // empty blob
213 SkASSERT(NULL == fRuns || fRuns->empty());
214 SkASSERT(fBounds.isEmpty());
215
216 blob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty()));
217 }
218
219 return blob;
220 }
221
OLDNEW
« no previous file with comments | « src/core/SkRecords.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698