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