| 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 |