diff options
author | 2014-08-21 08:53:26 -0700 | |
---|---|---|
committer | 2014-08-21 08:53:26 -0700 | |
commit | 00d5c2c6523321d25b32905ff4822f083a4173ee (patch) | |
tree | 7810daf8bac8a4105080a6c42889b47005a4709a /gm | |
parent | 9fa60daad4d5f54c0dbe3dbcc7608a8f6d721187 (diff) |
SkTextBlob
Initial implementation.
R=bungeman@google.com, jbroman@chromium.org, mtklein@google.com, reed@google.com, robertphillips@google.com
Author: fmalita@chromium.org
Review URL: https://codereview.chromium.org/473633002
Diffstat (limited to 'gm')
-rw-r--r-- | gm/textblob.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/gm/textblob.cpp b/gm/textblob.cpp new file mode 100644 index 0000000000..e7a0a1d2ef --- /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")); ) |