2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
12 #include "SkTextBlob.h"
13 #include "SkTDArray.h"
23 const struct BlobCfg {
27 } blobConfigs[][3][3] = {
29 { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
30 { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
31 { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
34 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } },
35 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } },
36 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } },
40 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
41 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
42 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
46 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
47 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
48 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
52 { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } },
53 { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } },
54 { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } },
58 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } },
59 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } },
60 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } },
64 const SkScalar kFontSize = 16;
67 class TextBlobGM : public skiagm::GM {
69 TextBlobGM(const char* txt)
70 : fTypeface(sk_tool_utils::create_portable_typeface("Times", SkTypeface::kNormal)) {
72 p.setTypeface(fTypeface);
73 size_t txtLen = strlen(txt);
74 int glyphCount = p.textToGlyphs(txt, txtLen, NULL);
76 fGlyphs.append(glyphCount);
77 p.textToGlyphs(txt, txtLen, fGlyphs.begin());
81 SkString onShortName() SK_OVERRIDE {
82 return SkString("textblob");
85 SkISize onISize() SK_OVERRIDE {
86 return SkISize::Make(640, 480);
89 void onDraw(SkCanvas* canvas) SK_OVERRIDE {
90 for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
91 SkAutoTUnref<const SkTextBlob> blob(this->makeBlob(b));
94 SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
95 SkIntToScalar(20 + 150 * (b / 2)));
97 canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
99 p.setColor(SK_ColorBLUE);
100 p.setStyle(SkPaint::kStroke_Style);
101 SkRect box = blob->bounds();
103 canvas->drawRect(box, p);
109 const SkTextBlob* makeBlob(unsigned blobIndex) {
110 SkTextBlobBuilder builder;
113 font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
114 font.setAntiAlias(true);
115 font.setSubpixelText(true);
116 font.setTypeface(fTypeface);
118 for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
119 unsigned currentGlyph = 0;
121 for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
122 const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
123 unsigned count = cfg->count;
125 if (count > fGlyphs.count() - currentGlyph) {
126 count = fGlyphs.count() - currentGlyph;
132 font.setTextSize(kFontSize * cfg->scale);
133 const SkScalar advanceX = font.getTextSize() * 0.85f;
134 const SkScalar advanceY = font.getTextSize() * 1.5f;
136 SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
140 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
143 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
146 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
148 SkTDArray<SkScalar> pos;
149 for (unsigned i = 0; i < count; ++i) {
150 *pos.append() = offset.x() + i * advanceX;
153 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
154 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
157 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
159 SkTDArray<SkScalar> pos;
160 for (unsigned i = 0; i < count; ++i) {
161 *pos.append() = offset.x() + i * advanceX;
162 *pos.append() = offset.y() + i * (advanceY / count);
165 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
166 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
169 SkFAIL("unhandled pos value");
172 currentGlyph += count;
176 return builder.build();
179 SkTDArray<uint16_t> fGlyphs;
180 SkAutoTUnref<SkTypeface> fTypeface;
182 typedef skiagm::GM INHERITED;
185 DEF_GM( return SkNEW_ARGS(TextBlobGM, ("hamburgefons")); )