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 SkPaint runPaint; |
| 45 RunIterator it(this); |
| 46 while (!it.done()) { |
| 47 SkASSERT(it.glyphCount() > 0); |
| 48 |
| 49 buffer.write32(it.glyphCount()); |
| 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) { |
| 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 |