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); |
| 42 buffer.writeRect(fBounds); |
| 43 |
| 44 size_t glyphBufferCount = 0; |
| 45 size_t posBufferCount = 0; |
| 46 |
| 47 for (int i = 0; i < runCount; ++i) { |
| 48 const Run& run = (*fRuns)[i]; |
| 49 SkASSERT(run.count > 0); |
| 50 |
| 51 buffer.write32(run.count); |
| 52 buffer.write32(run.glyphStart); |
| 53 buffer.write32(run.posStart); |
| 54 buffer.writePoint(run.offset); |
| 55 buffer.writePaint(run.font); |
| 56 buffer.write32(run.positioning); |
| 57 |
| 58 glyphBufferCount += run.count; |
| 59 posBufferCount += run.count * ScalarsPerGlyph(run.positioning); |
| 60 } |
| 61 |
| 62 buffer.writeByteArray(fGlyphBuffer, glyphBufferCount * sizeof(uint16_t)); |
| 63 buffer.writeByteArray(fPosBuffer, posBufferCount * sizeof(SkScalar)); |
| 64 } |
| 65 |
| 66 const SkTextBlob* SkTextBlob::CreateFromBuffer(SkReadBuffer& buffer) { |
| 67 int runCount = buffer.read32(); |
| 68 if (runCount <= 0) { |
| 69 return NULL; |
| 70 } |
| 71 |
| 72 SkRect bounds; |
| 73 buffer.readRect(&bounds); |
| 74 |
| 75 size_t glyphBufferCount = 0; |
| 76 size_t posBufferCount = 0; |
| 77 SkAutoTDelete<SkTArray<Run> > runs(SkNEW_ARGS(SkTArray<Run>, (runCount))); |
| 78 for (int i = 0; i < runCount; ++i) { |
| 79 Run& run = runs->push_back(); |
| 80 |
| 81 run.count = buffer.read32(); |
| 82 if (0 == run.count) { |
| 83 return NULL; |
| 84 } |
| 85 |
| 86 run.glyphStart = buffer.read32(); |
| 87 run.posStart = buffer.read32(); |
| 88 if (run.glyphStart != glyphBufferCount || run.posStart != posBufferCount
) { |
| 89 return NULL; |
| 90 } |
| 91 |
| 92 buffer.readPoint(&run.offset); |
| 93 buffer.readPaint(&run.font); |
| 94 |
| 95 run.positioning = static_cast<GlyphPositioning>(buffer.read32()); |
| 96 if (run.positioning > 2) { |
| 97 return NULL; |
| 98 } |
| 99 |
| 100 glyphBufferCount += run.count; |
| 101 posBufferCount += run.count * ScalarsPerGlyph(run.positioning); |
| 102 } |
| 103 |
| 104 SkTDArray<uint16_t> glyphBuffer; |
| 105 SkTDArray<SkScalar> posBuffer; |
| 106 |
| 107 buffer.readByteArray(glyphBuffer.append(glyphBufferCount), |
| 108 glyphBufferCount * sizeof(uint16_t)); |
| 109 buffer.readByteArray(posBuffer.append(posBufferCount), |
| 110 posBufferCount * sizeof(SkScalar)); |
| 111 |
| 112 return SkNEW_ARGS(SkTextBlob, (glyphBuffer.detach(), |
| 113 posBuffer.detach(), |
| 114 runs.detach(), |
| 115 bounds)); |
| 116 } |
| 117 |
29 SkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) | 118 SkTextBlob::RunIterator::RunIterator(const SkTextBlob* blob) |
30 : fBlob(blob) | 119 : fBlob(blob) |
31 , fIndex(0) { | 120 , fIndex(0) { |
32 SkASSERT(NULL != blob); | 121 SkASSERT(NULL != blob); |
33 } | 122 } |
34 | 123 |
35 bool SkTextBlob::RunIterator::done() const { | 124 bool SkTextBlob::RunIterator::done() const { |
36 return NULL == fBlob->fRuns.get() || fIndex >= fBlob->fRuns->count(); | 125 return NULL == fBlob->fRuns.get() || fIndex >= fBlob->fRuns->count(); |
37 } | 126 } |
38 | 127 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 newRun.positioning = pos; | 243 newRun.positioning = pos; |
155 } | 244 } |
156 | 245 |
157 void SkTextBlobBuilder::allocInternal(const SkPaint &font, | 246 void SkTextBlobBuilder::allocInternal(const SkPaint &font, |
158 SkTextBlob::GlyphPositioning positioning, | 247 SkTextBlob::GlyphPositioning positioning, |
159 int count, SkPoint offset, const SkRect* b
ounds) { | 248 int count, SkPoint offset, const SkRect* b
ounds) { |
160 SkASSERT(count > 0); | 249 SkASSERT(count > 0); |
161 | 250 |
162 this->ensureRun(font, positioning, offset); | 251 this->ensureRun(font, positioning, offset); |
163 | 252 |
164 // SkTextBlob::GlyphPositioning values are directly mapped to scalars-per-gl
yph. | 253 unsigned posScalarsPerGlyph = SkTextBlob::ScalarsPerGlyph(positioning); |
165 unsigned posScalarsPerGlyph = positioning; | |
166 SkASSERT(posScalarsPerGlyph <= 2); | |
167 | 254 |
168 fGlyphBuffer.append(count); | 255 fGlyphBuffer.append(count); |
169 fPosBuffer.append(count * posScalarsPerGlyph); | 256 fPosBuffer.append(count * posScalarsPerGlyph); |
170 | 257 |
171 SkASSERT(NULL != fRuns && !fRuns->empty()); | 258 SkASSERT(NULL != fRuns && !fRuns->empty()); |
172 SkTextBlob::Run& run = fRuns->back(); | 259 SkTextBlob::Run& run = fRuns->back(); |
173 | 260 |
174 run.count += count; | 261 run.count += count; |
175 | 262 |
176 // The current run might have been merged, so the start offset may point to
prev run data. | 263 // 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 | 322 // empty blob |
236 SkASSERT(NULL == fRuns || fRuns->empty()); | 323 SkASSERT(NULL == fRuns || fRuns->empty()); |
237 SkASSERT(fBounds.isEmpty()); | 324 SkASSERT(fBounds.isEmpty()); |
238 | 325 |
239 blob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())); | 326 blob = SkNEW_ARGS(SkTextBlob, (NULL, NULL, NULL, SkRect::MakeEmpty())); |
240 } | 327 } |
241 | 328 |
242 return blob; | 329 return blob; |
243 } | 330 } |
244 | 331 |
OLD | NEW |