blob: 60cec2acde0768b5bc7f12f625f4d600e365a606 [file] [log] [blame]
fmalita00d5c2c2014-08-21 08:53:26 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040011#include "include/core/SkFont.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkFontStyle.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040013#include "include/core/SkFontTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "include/core/SkPaint.h"
15#include "include/core/SkPoint.h"
16#include "include/core/SkRect.h"
17#include "include/core/SkRefCnt.h"
18#include "include/core/SkScalar.h"
19#include "include/core/SkSize.h"
20#include "include/core/SkString.h"
21#include "include/core/SkTextBlob.h"
22#include "include/core/SkTypeface.h"
23#include "include/core/SkTypes.h"
24#include "include/private/SkTDArray.h"
25#include "tools/ToolUtils.h"
fmalita00d5c2c2014-08-21 08:53:26 -070026
Ben Wagnercb3d49c2018-03-14 15:07:43 -040027#include <cstring>
fmalita00d5c2c2014-08-21 08:53:26 -070028
29namespace {
30
31enum Pos {
32 kDefault_Pos = 0,
33 kScalar_Pos = 1,
34 kPoint_Pos = 2,
35};
36
37const struct BlobCfg {
38 unsigned count;
39 Pos pos;
40 SkScalar scale;
41} blobConfigs[][3][3] = {
42 {
43 { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
44 { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } },
45 { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } },
46 },
47 {
fmalita37ecbaf2014-08-22 09:01:19 -070048 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } },
49 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } },
50 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070051 },
52
53 {
fmalita37ecbaf2014-08-22 09:01:19 -070054 { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
55 { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
56 { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
fmalita00d5c2c2014-08-21 08:53:26 -070057 },
58
59 {
fmalita37ecbaf2014-08-22 09:01:19 -070060 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } },
61 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } },
62 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } },
63 },
64
65 {
66 { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } },
67 { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } },
68 { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } },
69 },
70
71 {
72 { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } },
73 { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } },
74 { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } },
fmalita00d5c2c2014-08-21 08:53:26 -070075 },
76};
77
78const SkScalar kFontSize = 16;
John Stilesa6841be2020-08-06 14:11:56 -040079} // namespace
fmalita00d5c2c2014-08-21 08:53:26 -070080
81class TextBlobGM : public skiagm::GM {
82public:
fmalitaacb882c2014-09-16 17:58:34 -070083 TextBlobGM(const char* txt)
kkinnunenb4a797f2015-05-21 06:15:28 -070084 : fText(txt) {
fmalita00d5c2c2014-08-21 08:53:26 -070085 }
86
87protected:
kkinnunenb4a797f2015-05-21 06:15:28 -070088 void onOnceBeforeDraw() override {
Mike Kleinea3f0142019-03-20 11:12:10 -050089 fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
Mike Reedf78b7ea2018-12-25 22:06:17 -050090 SkFont font(fTypeface);
kkinnunenb4a797f2015-05-21 06:15:28 -070091 size_t txtLen = strlen(fText);
Ben Wagner51e15a62019-05-07 15:38:46 -040092 int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8);
kkinnunenb4a797f2015-05-21 06:15:28 -070093
94 fGlyphs.append(glyphCount);
Ben Wagner51e15a62019-05-07 15:38:46 -040095 font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount);
kkinnunenb4a797f2015-05-21 06:15:28 -070096 }
97
mtklein36352bf2015-03-25 18:17:31 -070098 SkString onShortName() override {
fmalita00d5c2c2014-08-21 08:53:26 -070099 return SkString("textblob");
100 }
101
mtklein36352bf2015-03-25 18:17:31 -0700102 SkISize onISize() override {
fmalita00d5c2c2014-08-21 08:53:26 -0700103 return SkISize::Make(640, 480);
104 }
105
mtklein36352bf2015-03-25 18:17:31 -0700106 void onDraw(SkCanvas* canvas) override {
fmalita00d5c2c2014-08-21 08:53:26 -0700107 for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
fmalita37283c22016-09-13 10:00:23 -0700108 sk_sp<SkTextBlob> blob(this->makeBlob(b));
fmalita00d5c2c2014-08-21 08:53:26 -0700109
110 SkPaint p;
Mike Reed3185f902018-10-26 16:33:00 -0400111 p.setAntiAlias(true);
fmalita00d5c2c2014-08-21 08:53:26 -0700112 SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
113 SkIntToScalar(20 + 150 * (b / 2)));
114
115 canvas->drawTextBlob(blob, offset.x(), offset.y(), p);
116
117 p.setColor(SK_ColorBLUE);
118 p.setStyle(SkPaint::kStroke_Style);
119 SkRect box = blob->bounds();
120 box.offset(offset);
Mike Reed3185f902018-10-26 16:33:00 -0400121 p.setAntiAlias(false);
fmalita00d5c2c2014-08-21 08:53:26 -0700122 canvas->drawRect(box, p);
123
124 }
125 }
126
127private:
fmalita37283c22016-09-13 10:00:23 -0700128 sk_sp<SkTextBlob> makeBlob(unsigned blobIndex) {
fmalita00d5c2c2014-08-21 08:53:26 -0700129 SkTextBlobBuilder builder;
130
Mike Reed3185f902018-10-26 16:33:00 -0400131 SkFont font;
Mike Reed5f50f572018-11-12 13:19:37 -0500132 font.setSubpixel(true);
133 font.setEdging(SkFont::Edging::kAntiAlias);
fmalitaacb882c2014-09-16 17:58:34 -0700134 font.setTypeface(fTypeface);
fmalita00d5c2c2014-08-21 08:53:26 -0700135
136 for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
137 unsigned currentGlyph = 0;
138
139 for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
140 const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
141 unsigned count = cfg->count;
142
143 if (count > fGlyphs.count() - currentGlyph) {
144 count = fGlyphs.count() - currentGlyph;
145 }
146 if (0 == count) {
147 break;
148 }
149
Mike Reed3185f902018-10-26 16:33:00 -0400150 font.setSize(kFontSize * cfg->scale);
151 const SkScalar advanceX = font.getSize() * 0.85f;
152 const SkScalar advanceY = font.getSize() * 1.5f;
fmalita00d5c2c2014-08-21 08:53:26 -0700153
154 SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
155 advanceY * l);
156 switch (cfg->pos) {
157 case kDefault_Pos: {
158 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
159 offset.x(),
160 offset.y());
161 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
162 } break;
163 case kScalar_Pos: {
164 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
165 offset.y());
166 SkTDArray<SkScalar> pos;
167 for (unsigned i = 0; i < count; ++i) {
168 *pos.append() = offset.x() + i * advanceX;
169 }
170
171 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
172 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
173 } break;
174 case kPoint_Pos: {
175 const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);
176
177 SkTDArray<SkScalar> pos;
178 for (unsigned i = 0; i < count; ++i) {
179 *pos.append() = offset.x() + i * advanceX;
180 *pos.append() = offset.y() + i * (advanceY / count);
181 }
182
183 memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
184 memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
185 } break;
186 default:
djsollenf2b340f2016-01-29 08:51:04 -0800187 SK_ABORT("unhandled pos value");
fmalita00d5c2c2014-08-21 08:53:26 -0700188 }
189
190 currentGlyph += count;
191 }
192 }
193
fmalita37283c22016-09-13 10:00:23 -0700194 return builder.make();
fmalita00d5c2c2014-08-21 08:53:26 -0700195 }
196
bungeman13b9c952016-05-12 10:09:30 -0700197 SkTDArray<uint16_t> fGlyphs;
198 sk_sp<SkTypeface> fTypeface;
199 const char* fText;
John Stiles7571f9e2020-09-02 22:42:33 -0400200 using INHERITED = skiagm::GM;
fmalita00d5c2c2014-08-21 08:53:26 -0700201};
202
halcanary385fe4d2015-08-26 13:07:48 -0700203DEF_GM(return new TextBlobGM("hamburgefons");)