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

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

Issue 473633002: SkTextBlob (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: SkRecord plumbing + partial blob bounds logic 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(const uint16_t *glyphs, const SkScalar *pos, const SkTArr ay<Run> *runs,
11 const SkRect& bounds)
12 : fGlyphBuffer(glyphs)
13 , fPosBuffer(pos)
14 , fRuns(runs)
15 , fBounds(bounds) {
16 }
17
18 SkTextBlob::~SkTextBlob() {
19 sk_free(const_cast<uint16_t*>(fGlyphBuffer));
20 sk_free(const_cast<SkScalar*>(fPosBuffer));
21 SkDELETE(fRuns);
22 }
23
24 uint32_t SkTextBlob::uniqueID() const {
25 static int32_t gTextBlobGenerationID; // = 0;
26
27 // loop in case our global wraps around, as we never want to return SK_Inval idGenID
28 while (SK_InvalidGenID == fUniqueID) {
29 fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1;
30 }
31
32 return fUniqueID;
33 }
34
35 const SkTextBlob::RunInfo SkTextBlob::runInfo(unsigned runIndex) const {
36 SkASSERT(NULL != fRuns && runIndex < (unsigned)fRuns->count());
37
38 const Run& run = (*fRuns)[runIndex];
39 return RunInfo(run.count, run.positioning, fGlyphBuffer + run.glyphStart,
40 fPosBuffer + run.posStart, &run.font);
41 }
42
43 SkTextBlobBuilder::SkTextBlobBuilder(unsigned runs)
44 : fRuns(NULL)
45 , fDeferredRunBounds(false) {
46
47 if (runs > 0) {
48 // if the number of runs is known, size our run storage accordingly.
49 fRuns = SkNEW(SkTArray<SkTextBlob::Run>(runs));
50 }
51 fBounds.setEmpty();
52 }
53
54 SkTextBlobBuilder::~SkTextBlobBuilder() {
55 // unused runs
56 SkDELETE(fRuns);
57 }
58
59 void SkTextBlobBuilder::updateRunBounds() {
60 if (!fDeferredRunBounds) {
61 // Run bounds are up to date.
62 return;
63 }
64
65 SkASSERT(NULL != fRuns && !fRuns->empty());
66
67 // FIXME: compute run bounds.
68 SkRect runBounds = SkRect::MakeEmpty();
69
70 fBounds.join(runBounds);
71 fDeferredRunBounds = false;
72 }
73
74 void SkTextBlobBuilder::ensureRun(const SkPaint& font, SkTextBlob::Positioning p os,
75 unsigned count, const SkRect* runBounds) {
76 SkASSERT(SkPaint::kGlyphID_TextEncoding == font.getTextEncoding());
77
78 if (NULL == fRuns) {
79 fRuns = SkNEW(SkTArray<SkTextBlob::Run>());
80 }
81
82 // same-font/same-positioning runs are merged
83 if (fRuns->empty() || fRuns->back().positioning != pos || fRuns->back().font != font) {
84 // former run bounds may need updating
85 updateRunBounds();
86
87 // start a new run
88 SkTextBlob::Run& newRun = fRuns->push_back();
89 newRun.count = 0;
90 newRun.glyphStart = fGlyphBuffer.count();
91 newRun.posStart = fPosBuffer.count();
92 newRun.font = font;
93 newRun.positioning = pos;
94 }
95
96 // reserve buffer storage upfront if the glyph count is known
97 if (count > 0) {
98 fGlyphBuffer.setReserve(fGlyphBuffer.count() + count);
99 SkASSERT(pos <= 2);
100 fPosBuffer.setReserve(fPosBuffer.count() + count * pos);
101 }
102
103 fDeferredRunBounds |= (NULL == runBounds);
104 // when in deferred bounds mode, we'll compute the bounds at a later time.
105 if (!fDeferredRunBounds) {
106 fBounds.join(*runBounds);
107 }
108 }
109
110 const SkTextBlob* SkTextBlobBuilder::build() {
111 const SkTextBlob* leBlob;
112
113 if (fGlyphBuffer.count() > 0) {
114 // we have some glyphs, construct a real blob
115 SkASSERT(NULL != fRuns && !fRuns->empty());
116
117 // last run may require deferred bounds computation
118 updateRunBounds();
119
120 // ownership of all buffers is transferred to the blob
121 leBlob = SkNEW_ARGS(SkTextBlob, (fGlyphBuffer.detach(),
122 fPosBuffer.detach(),
123 fRuns,
124 fBounds));
125 fRuns = NULL;
126 fBounds.setEmpty();
127 } else {
128 // empty blob
129 SkASSERT(NULL == fRuns || fRuns->empty());
130 SkASSERT(fBounds.isEmpty());
131
132 leBlob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())) ;
133 }
134
135 return leBlob;
136 }
137
138 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kDefault_Positioning>::addGlyph(u int16_t glyph) {
139 SkASSERT(NULL != fBlobBuilder->fRuns);
140 SkASSERT(fBlobBuilder->fRuns->count() > 0);
141 SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kDefault_Pos itioning);
142
143 *fBlobBuilder->fGlyphBuffer.append() = glyph;
144
145 fBlobBuilder->fRuns->back().count += 1;
146 }
147
148 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kDefault_Positioning>::addGlyphs(
149 const uint16_t glyphs[], size_t count) {
150
151 for (size_t i = 0; i < count; ++i) {
152 this->addGlyph(glyphs[i]);
153 }
154 }
155
156 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kHorizontal_Positioning>::addGlyp h(uint16_t glyph,
157 Sk Scalar x) {
158 SkASSERT(NULL != fBlobBuilder->fRuns);
159 SkASSERT(fBlobBuilder->fRuns->count() > 0);
160 SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kHorizontal_ Positioning);
161
162 *fBlobBuilder->fGlyphBuffer.append() = glyph;
163 *fBlobBuilder->fPosBuffer.append() = x;
164
165 fBlobBuilder->fRuns->back().count += 1;
166 }
167
168 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kHorizontal_Positioning>::addGlyp hs(
169 const uint16_t glyphs[], const SkScalar xPos[], size_t count) {
170
171 for (size_t i = 0; i < count; ++i) {
172 this->addGlyph(glyphs[i], xPos[i]);
173 }
174 }
175
176 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyph(uint 16_t glyph,
177 SkS calar x,
178 SkS calar y) {
179 SkASSERT(NULL != fBlobBuilder->fRuns);
180 SkASSERT(fBlobBuilder->fRuns->count() > 0);
181 SkASSERT(fBlobBuilder->fRuns->back().positioning == SkTextBlob::kFull_Positi oning);
182
183 *fBlobBuilder->fGlyphBuffer.append() = glyph;
184 *fBlobBuilder->fPosBuffer.append() = x;
185 *fBlobBuilder->fPosBuffer.append() = y;
186
187 fBlobBuilder->fRuns->back().count += 1;
188 }
189
190 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyph(uint 16_t glyph,
191 SkPo int pos) {
192 this->addGlyph(glyph, pos.x(), pos.y());
193 }
194
195 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyphs(
196 const uint16_t glyphs[], const SkScalar xPos[], const SkScalar yPos[], s ize_t count) {
197
198 for (size_t i = 0; i < count; ++i) {
199 this->addGlyph(glyphs[i], xPos[i], yPos[i]);
200 }
201 }
202
203 void SkTextBlobBuilder::RunBuilder<SkTextBlob::kFull_Positioning>::addGlyphs(
204 const uint16_t glyphs[], const SkPoint pos[], size_t count) {
205
206 for (size_t i = 0; i < count; ++i) {
207 this->addGlyph(glyphs[i], pos[i].x(), pos[i].y());
208 }
209 }
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