aboutsummaryrefslogtreecommitdiffhomepage
path: root/gm
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2014-08-21 08:53:26 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-21 08:53:26 -0700
commit00d5c2c6523321d25b32905ff4822f083a4173ee (patch)
tree7810daf8bac8a4105080a6c42889b47005a4709a /gm
parent9fa60daad4d5f54c0dbe3dbcc7608a8f6d721187 (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.cpp172
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")); )