| Index: src/core/SkTextBlob.cpp
|
| diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c5d627cb6cf43d0099e8a839d2ae07dd5fea6d96
|
| --- /dev/null
|
| +++ b/src/core/SkTextBlob.cpp
|
| @@ -0,0 +1,153 @@
|
| +/*
|
| + * Copyright 2014 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "SkTextBlob.h"
|
| +
|
| +#include "SkDevice.h"
|
| +
|
| +const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, const SkPaint& paint,
|
| + const SkRect* bounds) {
|
| + if (NULL == glyphs || 0 == count) {
|
| + return NULL;
|
| + }
|
| +
|
| + return SkNEW_ARGS(SkTextChunk, (glyphs, count, NULL, 0, paint, bounds));
|
| +}
|
| +
|
| +const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, const SkScalar* pos,
|
| + const SkPaint& paint, const SkRect* bounds) {
|
| + if (NULL == glyphs || NULL == pos || 0 == count) {
|
| + return NULL;
|
| + }
|
| +
|
| + return SkNEW_ARGS(SkTextChunk, (glyphs, count, pos, 1, paint, bounds));
|
| +}
|
| +
|
| +const SkTextChunk* SkTextChunk::Create(const uint16_t* glyphs, size_t count, const SkPoint* pos,
|
| + const SkPaint& paint, const SkRect* bounds) {
|
| + if (NULL == glyphs || NULL == pos || 0 == count) {
|
| + return NULL;
|
| + }
|
| +
|
| + SK_COMPILE_ASSERT(sizeof(SkScalar) * 2 == sizeof(SkPoint), point_is_two_scalars);
|
| + return SkNEW_ARGS(SkTextChunk,
|
| + (glyphs, count, reinterpret_cast<const SkScalar*>(pos), 2, paint, bounds));
|
| +}
|
| +
|
| +SkTextChunk::SkTextChunk(const uint16_t* glyphs, size_t count, const SkScalar* pos,
|
| + unsigned scalarsPerPos, const SkPaint& paint, const SkRect* bounds)
|
| + : fGlyphCount(count)
|
| + , fPos(NULL)
|
| + , fFont(paint)
|
| + , fScalarsPerPos(scalarsPerPos) {
|
| +
|
| + SkASSERT(glyphs);
|
| + SkASSERT(count > 0);
|
| + size_t glyphStorageSize = sizeof(uint16_t) * count;
|
| + fGlyphs = reinterpret_cast<uint16_t*>(sk_malloc_throw(glyphStorageSize));
|
| + memcpy(fGlyphs, glyphs, glyphStorageSize);
|
| +
|
| + SkASSERT(scalarsPerPos <= 2);
|
| + SkASSERT((NULL != pos) == (scalarsPerPos > 0));
|
| + if (NULL != pos) {
|
| + size_t posStorageSize = sizeof(SkScalar) * fScalarsPerPos * count;
|
| + fPos = reinterpret_cast<SkScalar*>(sk_malloc_throw(posStorageSize));
|
| + memcpy(fPos, pos, posStorageSize);
|
| + }
|
| +
|
| + fBoundsDirty = (NULL == bounds);
|
| + if (!fBoundsDirty) {
|
| + fBounds = *bounds;
|
| + }
|
| +
|
| + SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
|
| +}
|
| +
|
| +SkTextChunk::~SkTextChunk() {
|
| + sk_free(fGlyphs);
|
| + sk_free(fPos);
|
| +}
|
| +
|
| +const SkRect& SkTextChunk::bounds() const {
|
| + if (fBoundsDirty) {
|
| + fFont.measureText(fGlyphs, fGlyphCount, &fBounds);
|
| + fBoundsDirty = false;
|
| + }
|
| +
|
| + return fBounds;
|
| +}
|
| +
|
| +void SkTextChunk::draw(SkBaseDevice* device, const SkDraw& draw, const SkPaint& paint) const {
|
| + SkASSERT(NULL != device);
|
| + SkASSERT(SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding());
|
| +
|
| + size_t length = sizeof(uint16_t) * fGlyphCount;
|
| + if (NULL != fPos) {
|
| + SkASSERT(1 == fScalarsPerPos || 2 == fScalarsPerPos);
|
| + device->drawPosText(draw, fGlyphs, length, fPos, 0, fScalarsPerPos, paint);
|
| + } else {
|
| + SkASSERT(0 == fScalarsPerPos);
|
| + device->drawText(draw, fGlyphs, length, 0, 0, paint);
|
| + }
|
| +}
|
| +
|
| +const SkTextBlob* SkTextBlob::Create(const SkTextChunk *chunk) {
|
| + SkTDArray<const SkTextChunk*> chunks;
|
| + chunks.setReserve(1);
|
| + *chunks.append() = chunk;
|
| + return SkNEW_ARGS(SkTextBlob, (chunks));
|
| +}
|
| +
|
| +const SkTextBlob* SkTextBlob::Create(const SkTDArray<const SkTextChunk*>& chunks) {
|
| + return SkNEW_ARGS(SkTextBlob, (chunks));
|
| +}
|
| +
|
| +SkTextBlob::SkTextBlob(const SkTDArray<const SkTextChunk*>& chunks)
|
| + : fChunks(chunks)
|
| + , fUniqueID(SK_InvalidGenID) {
|
| +}
|
| +
|
| +SkTextBlob::~SkTextBlob() {
|
| + Iter it(this);
|
| + while (const SkTextChunk* chunk = it.next()) {
|
| + SkDELETE(chunk);
|
| + }
|
| +}
|
| +
|
| +uint32_t SkTextBlob::uniqueID() const {
|
| + static int32_t gTextBlobGenerationID; // = 0;
|
| +
|
| + // do a loop in case our global wraps around, as we never want to
|
| + // return SK_InvalidGenID
|
| + while (SK_InvalidGenID == fUniqueID) {
|
| + fUniqueID = sk_atomic_inc(&gTextBlobGenerationID) + 1;
|
| + }
|
| +
|
| + return fUniqueID;
|
| +}
|
| +
|
| +SkTextBlobBuilder::SkTextBlobBuilder() {
|
| +}
|
| +
|
| +SkTextBlobBuilder::~SkTextBlobBuilder() {
|
| + // unused chunks.
|
| + for (int i = 0; i < fChunks.count(); ++i) {
|
| + SkDELETE(fChunks[i]);
|
| + }
|
| +}
|
| +
|
| +const SkTextBlob* SkTextBlobBuilder::build() {
|
| + const SkTextBlob* blob = SkTextBlob::Create(fChunks);
|
| + fChunks.rewind();
|
| + return blob;
|
| +}
|
| +
|
| +void SkTextBlobBuilder::addChunk(const SkTextChunk* chunk) {
|
| + *fChunks.append() = chunk;
|
| +}
|
| +
|
| +
|
|
|