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")); ) |