OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTextBlob.h" | 8 #include "SkTextBlob.h" |
9 | 9 |
10 #include "SkReadBuffer.h" | |
11 #include "SkWriteBuffer.h" | |
12 | |
10 SkTextBlob::SkTextBlob(uint16_t *glyphs, SkScalar *pos, const SkTArray<Run> *run s, | 13 SkTextBlob::SkTextBlob(uint16_t *glyphs, SkScalar *pos, const SkTArray<Run> *run s, |
11 const SkRect& bounds) | 14 const SkRect& bounds) |
12 : fGlyphBuffer(glyphs) | 15 : fGlyphBuffer(glyphs) |
13 , fPosBuffer(pos) | 16 , fPosBuffer(pos) |
14 , fRuns(runs) | 17 , fRuns(runs) |
15 , fBounds(bounds) { | 18 , fBounds(bounds) { |
16 } | 19 } |
17 | 20 |
18 uint32_t SkTextBlob::uniqueID() const { | 21 uint32_t SkTextBlob::uniqueID() const { |
19 static int32_t gTextBlobGenerationID; // = 0; | 22 static int32_t gTextBlobGenerationID; // = 0; |
20 | 23 |
21 // loop in case our global wraps around, as we never want to return SK_Inval idGenID | 24 // loop in case our global wraps around, as we never want to return SK_Inval idGenID |
22 while (SK_InvalidGenID == fUniqueID) { | 25 while (SK_InvalidGenID == fUniqueID) { |
23 fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1; | 26 fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1; |
24 } | 27 } |
25 | 28 |
26 return fUniqueID; | 29 return fUniqueID; |
27 } | 30 } |
28 | 31 |
32 unsigned SkTextBlob::ScalarsPerGlyph(GlyphPositioning pos) { | |
33 // GlyphPositioning values are directly mapped to scalars-per-glyph. | |
34 SkASSERT(pos <= 2); | |
35 return pos; | |
36 } | |
37 | |
38 void SkTextBlob::flatten(SkWriteBuffer& buffer) const { | |
39 int runCount = (NULL == fRuns.get()) ? 0 : fRuns->count(); | |
40 | |
41 buffer.write32(runCount); | |
robertphillips
2014/08/25 21:32:05
Shouldn't we bail here if runCount == 0 ?
f(malita)
2014/08/25 23:56:02
We could (and it would save us writing the bounds
| |
42 buffer.writeRect(fBounds); | |
43 | |
44 SkPaint runPaint; | |
45 RunIterator it(this); | |
46 while (!it.done()) { | |
47 SkASSERT(it.glyphCount() > 0); | |
48 | |
49 buffer.write32(it.glyphCount()); | |
robertphillips
2014/08/25 21:32:05
Don't we bail here if glyphCount == 0 ?
f(malita)
2014/08/25 23:56:03
We shouldn't have any zero-length runs (asserting
| |
50 buffer.write32(it.positioning()); | |
51 buffer.writePoint(it.offset()); | |
52 // This should go away when switching to SkFont | |
53 it.applyFontToPaint(&runPaint); | |
54 buffer.writePaint(runPaint); | |
55 | |
56 buffer.writeByteArray(it.glyphs(), it.glyphCount() * sizeof(uint16_t)); | |
57 buffer.writeByteArray(it.pos(), | |
58 it.glyphCount() * sizeof(SkScalar) * ScalarsPerGlyph(it.positioning( ))); | |
59 | |
60 it.next(); | |
61 SkDEBUGCODE(runCount--); | |
62 } | |
63 SkASSERT(0 == runCount); | |
64 } | |
65 | |
66 const SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& reader) { | |
67 int runCount = reader.read32(); | |
68 if (runCount <= 0) { | |
f(malita)
2014/08/25 23:56:02
The earlier comment did point out this one though:
| |
69 return NULL; | |
70 } | |
71 | |
72 SkRect bounds; | |
73 reader.readRect(&bounds); | |
74 | |
75 SkTextBlobBuilder blobBuilder; | |
76 for (int i = 0; i < runCount; ++i) { | |
77 int glyphCount = reader.read32(); | |
78 GlyphPositioning pos = static_cast<GlyphPositioning>(reader.read32()); | |
79 if (glyphCount <= 0 || pos > kFull_Positioning) { | |
80 return NULL; | |
81 } | |
82 | |
83 SkPoint offset; | |
84 reader.readPoint(&offset); | |
85 SkPaint font; | |
86 reader.readPaint(&font); | |
87 | |
88 const SkTextBlobBuilder::RunBuffer* buf = NULL; | |
89 switch (pos) { | |
90 case kDefault_Positioning: | |
91 buf = &blobBuilder.allocRun(font, glyphCount, offset.x(), offset.y() , &bounds); | |
92 break; | |
93 case kHorizontal_Positioning: | |
94 buf = &blobBuilder.allocRunPosH(font, glyphCount, offset.y(), &bound s); | |
95 break; | |
96 case kFull_Positioning: | |
97 buf = &blobBuilder.allocRunPos(font, glyphCount, &bounds); | |
98 break; | |
99 default: | |
100 return NULL; | |
101 } | |
102 | |
103 if (!reader.readByteArray(buf->glyphs, glyphCount * sizeof(uint16_t)) || | |
104 !reader.readByteArray(buf->pos, glyphCount * sizeof(SkScalar) * Scal arsPerGlyph(pos))) { | |
105 return NULL; | |
106 } | |
107 } | |
108 | |
109 return blobBuilder.build(); | |
110 } | |
111 | |
29 SkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) | 112 SkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) |
30 : fBlob(blob) | 113 : fBlob(blob) |
31 , fIndex(0) { | 114 , fIndex(0) { |
32 SkASSERT(NULL != blob); | 115 SkASSERT(NULL != blob); |
33 } | 116 } |
34 | 117 |
35 bool SkTextBlob::RunIterator::done() const { | 118 bool SkTextBlob::RunIterator::done() const { |
36 return NULL == fBlob->fRuns.get() || fIndex >= fBlob->fRuns->count(); | 119 return NULL == fBlob->fRuns.get() || fIndex >= fBlob->fRuns->count(); |
37 } | 120 } |
38 | 121 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 newRun.positioning = pos; | 237 newRun.positioning = pos; |
155 } | 238 } |
156 | 239 |
157 void SkTextBlobBuilder::allocInternal(const SkPaint &font, | 240 void SkTextBlobBuilder::allocInternal(const SkPaint &font, |
158 SkTextBlob::GlyphPositioning positioning, | 241 SkTextBlob::GlyphPositioning positioning, |
159 int count, SkPoint offset, const SkRect* b ounds) { | 242 int count, SkPoint offset, const SkRect* b ounds) { |
160 SkASSERT(count > 0); | 243 SkASSERT(count > 0); |
161 | 244 |
162 this->ensureRun(font, positioning, offset); | 245 this->ensureRun(font, positioning, offset); |
163 | 246 |
164 // SkTextBlob::GlyphPositioning values are directly mapped to scalars-per-gl yph. | 247 unsigned posScalarsPerGlyph = SkTextBlob::ScalarsPerGlyph(positioning); |
165 unsigned posScalarsPerGlyph = positioning; | |
166 SkASSERT(posScalarsPerGlyph <= 2); | |
167 | 248 |
168 fGlyphBuffer.append(count); | 249 fGlyphBuffer.append(count); |
169 fPosBuffer.append(count * posScalarsPerGlyph); | 250 fPosBuffer.append(count * posScalarsPerGlyph); |
170 | 251 |
171 SkASSERT(NULL != fRuns && !fRuns->empty()); | 252 SkASSERT(NULL != fRuns && !fRuns->empty()); |
172 SkTextBlob::Run& run = fRuns->back(); | 253 SkTextBlob::Run& run = fRuns->back(); |
173 | 254 |
174 run.count += count; | 255 run.count += count; |
175 | 256 |
176 // The current run might have been merged, so the start offset may point to prev run data. | 257 // The current run might have been merged, so the start offset may point to prev run data. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 // empty blob | 316 // empty blob |
236 SkASSERT(NULL == fRuns || fRuns->empty()); | 317 SkASSERT(NULL == fRuns || fRuns->empty()); |
237 SkASSERT(fBounds.isEmpty()); | 318 SkASSERT(fBounds.isEmpty()); |
238 | 319 |
239 blob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())); | 320 blob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())); |
240 } | 321 } |
241 | 322 |
242 return blob; | 323 return blob; |
243 } | 324 } |
244 | 325 |
OLD | NEW |