| Index: gm/textblob.cpp
|
| diff --git a/gm/textblob.cpp b/gm/textblob.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e7a0a1d2efedf357e85566811d1864932c6142ac
|
| --- /dev/null
|
| +++ b/gm/textblob.cpp
|
| @@ -0,0 +1,172 @@
|
| +/*
|
| + * 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 "gm.h"
|
| +
|
| +#include "SkCanvas.h"
|
| +#include "SkPoint.h"
|
| +#include "SkTextBlob.h"
|
| +#include "SkTDArray.h"
|
| +
|
| +namespace {
|
| +
|
| +enum Pos {
|
| + kDefault_Pos = 0,
|
| + kScalar_Pos = 1,
|
| + kPoint_Pos = 2,
|
| +};
|
| +
|
| +const struct BlobCfg {
|
| + unsigned count;
|
| + Pos pos;
|
| + SkScalar scale;
|
| +} blobConfigs[][3][3] = {
|
| + {
|
| + { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
|
| + { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
|
| + { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
|
| + },
|
| + {
|
| + { { 4, kDefault_Pos, 1}, { 4, kDefault_Pos, 1}, { 4, kDefault_Pos, 1} },
|
| + { { 4, kScalar_Pos, 1}, { 4, kScalar_Pos, 1}, { 4, kScalar_Pos, 1} },
|
| + { { 4, kPoint_Pos, 1}, { 4, kPoint_Pos, 1}, { 4, kPoint_Pos, 1} },
|
| + },
|
| +
|
| + {
|
| + { { 4, kDefault_Pos, 1}, { 4, kDefault_Pos, 1}, { 4, kScalar_Pos, 1} },
|
| + { { 4, kScalar_Pos, 1}, { 4, kScalar_Pos, 1}, { 4, kPoint_Pos, 1} },
|
| + { { 4, kPoint_Pos, 1}, { 4, kPoint_Pos, 1}, { 4, kDefault_Pos, 1} },
|
| + },
|
| +
|
| + {
|
| + { { 4, kDefault_Pos, 1}, { 4, kScalar_Pos, 1}, { 4, kPoint_Pos, 1} },
|
| + { { 4, kScalar_Pos, 1}, { 4, kPoint_Pos, 1}, { 4, kDefault_Pos, 1} },
|
| + { { 4, kPoint_Pos, 1}, { 4, kDefault_Pos, 1}, { 4, kScalar_Pos, 1} },
|
| + },
|
| +};
|
| +
|
| +const SkScalar kFontSize = 16;
|
| +}
|
| +
|
| +class TextBlobGM : public skiagm::GM {
|
| +public:
|
| + TextBlobGM(const char* txt) {
|
| + SkPaint p;
|
| + size_t txtLen = strlen(txt);
|
| + int glyphCount = p.textToGlyphs(txt, txtLen, NULL);
|
| +
|
| + fGlyphs.append(glyphCount);
|
| + p.textToGlyphs(txt, txtLen, fGlyphs.begin());
|
| + }
|
| +
|
| +protected:
|
| + virtual SkString onShortName() SK_OVERRIDE {
|
| + return SkString("textblob");
|
| + }
|
| +
|
| + virtual SkISize onISize() SK_OVERRIDE {
|
| + return SkISize::Make(640, 480);
|
| + }
|
| +
|
| + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
| + for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
|
| + SkAutoTUnref<const SkTextBlob> blob(makeBlob(b));
|
| +
|
| + SkPaint p;
|
| + p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
| + p.setTextSize(kFontSize);
|
| + p.setAntiAlias(true);
|
| + p.setSubpixelText(true);
|
| +
|
| + SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
|
| + SkIntToScalar(20 + 150 * (b / 2)));
|
| +
|
| + canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
|
| +
|
| + p.setColor(SK_ColorBLUE);
|
| + p.setStyle(SkPaint::kStroke_Style);
|
| + SkRect box = blob->bounds();
|
| + box.offset(offset);
|
| + canvas->drawRect(box, p);
|
| +
|
| + }
|
| + }
|
| +
|
| +private:
|
| + const SkTextBlob* makeBlob(unsigned blobIndex) {
|
| + SkTextBlobBuilder builder;
|
| +
|
| + SkPaint font;
|
| + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
| +
|
| + for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
|
| + unsigned currentGlyph = 0;
|
| +
|
| + for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
|
| + const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
|
| + unsigned count = cfg->count;
|
| +
|
| + if (count > fGlyphs.count() - currentGlyph) {
|
| + count = fGlyphs.count() - currentGlyph;
|
| + }
|
| + if (0 == count) {
|
| + break;
|
| + }
|
| +
|
| + font.setTextSize(kFontSize * cfg->scale);
|
| + const SkScalar advanceX = font.getTextSize() * 0.85f;
|
| + const SkScalar advanceY = font.getTextSize() * 1.5f;
|
| +
|
| + SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
|
| + advanceY * l);
|
| + switch (cfg->pos) {
|
| + case kDefault_Pos: {
|
| + const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
|
| + offset.x(),
|
| + offset.y());
|
| + memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
|
| + } break;
|
| + case kScalar_Pos: {
|
| + const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
|
| + offset.y());
|
| + SkTDArray<SkScalar> pos;
|
| + for (unsigned i = 0; i < count; ++i) {
|
| + *pos.append() = offset.x() + i * advanceX;
|
| + }
|
| +
|
| + memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
|
| + memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
|
| + } break;
|
| + case kPoint_Pos: {
|
| + const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
|
| +
|
| + SkTDArray<SkScalar> pos;
|
| + for (unsigned i = 0; i < count; ++i) {
|
| + *pos.append() = offset.x() + i * advanceX;
|
| + *pos.append() = offset.y() + i * (advanceY / count);
|
| + }
|
| +
|
| + memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
|
| + memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
|
| + } break;
|
| + default:
|
| + SkFAIL("unhandled pos value");
|
| + }
|
| +
|
| + currentGlyph += count;
|
| + }
|
| + }
|
| +
|
| + return builder.build();
|
| + }
|
| +
|
| + SkTDArray<uint16_t> fGlyphs;
|
| +
|
| + typedef skiagm::GM INHERITED;
|
| +};
|
| +
|
| +DEF_GM( return SkNEW_ARGS(TextBlobGM, ("hamburgefons")); )
|
|
|