1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "gm/gm.h" 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 11cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 12cb93a386Sopenharmony_ci#include "include/core/SkFontStyle.h" 13cb93a386Sopenharmony_ci#include "include/core/SkFontTypes.h" 14cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 15cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 16cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 17cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 18cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 19cb93a386Sopenharmony_ci#include "include/core/SkSize.h" 20cb93a386Sopenharmony_ci#include "include/core/SkString.h" 21cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h" 22cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 23cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 24cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h" 25cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci#include <cstring> 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_cinamespace { 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cienum Pos { 32cb93a386Sopenharmony_ci kDefault_Pos = 0, 33cb93a386Sopenharmony_ci kScalar_Pos = 1, 34cb93a386Sopenharmony_ci kPoint_Pos = 2, 35cb93a386Sopenharmony_ci}; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciconst struct BlobCfg { 38cb93a386Sopenharmony_ci unsigned count; 39cb93a386Sopenharmony_ci Pos pos; 40cb93a386Sopenharmony_ci SkScalar scale; 41cb93a386Sopenharmony_ci} blobConfigs[][3][3] = { 42cb93a386Sopenharmony_ci { 43cb93a386Sopenharmony_ci { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } }, 44cb93a386Sopenharmony_ci { { 1024, kScalar_Pos, 1 }, { 0, kScalar_Pos, 0 }, { 0, kScalar_Pos, 0 } }, 45cb93a386Sopenharmony_ci { { 1024, kPoint_Pos, 1 }, { 0, kPoint_Pos, 0 }, { 0, kPoint_Pos, 0 } }, 46cb93a386Sopenharmony_ci }, 47cb93a386Sopenharmony_ci { 48cb93a386Sopenharmony_ci { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 } }, 49cb93a386Sopenharmony_ci { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 } }, 50cb93a386Sopenharmony_ci { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 } }, 51cb93a386Sopenharmony_ci }, 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci { 54cb93a386Sopenharmony_ci { { 4, kDefault_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } }, 55cb93a386Sopenharmony_ci { { 4, kScalar_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } }, 56cb93a386Sopenharmony_ci { { 4, kPoint_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } }, 57cb93a386Sopenharmony_ci }, 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci { 60cb93a386Sopenharmony_ci { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 } }, 61cb93a386Sopenharmony_ci { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 } }, 62cb93a386Sopenharmony_ci { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1 } }, 63cb93a386Sopenharmony_ci }, 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci { 66cb93a386Sopenharmony_ci { { 4, kDefault_Pos, .75f }, { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, 1.25f } }, 67cb93a386Sopenharmony_ci { { 4, kScalar_Pos, .75f }, { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, 1.25f } }, 68cb93a386Sopenharmony_ci { { 4, kPoint_Pos, .75f }, { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, 1.25f } }, 69cb93a386Sopenharmony_ci }, 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci { 72cb93a386Sopenharmony_ci { { 4, kDefault_Pos, 1 }, { 4, kScalar_Pos, .75f }, { 4, kPoint_Pos, 1.25f } }, 73cb93a386Sopenharmony_ci { { 4, kScalar_Pos, 1 }, { 4, kPoint_Pos, .75f }, { 4, kDefault_Pos, 1.25f } }, 74cb93a386Sopenharmony_ci { { 4, kPoint_Pos, 1 }, { 4, kDefault_Pos, .75f }, { 4, kScalar_Pos, 1.25f } }, 75cb93a386Sopenharmony_ci }, 76cb93a386Sopenharmony_ci}; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ciconst SkScalar kFontSize = 16; 79cb93a386Sopenharmony_ci} // namespace 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciclass TextBlobGM : public skiagm::GM { 82cb93a386Sopenharmony_cipublic: 83cb93a386Sopenharmony_ci TextBlobGM(const char* txt) 84cb93a386Sopenharmony_ci : fText(txt) { 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ciprotected: 88cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 89cb93a386Sopenharmony_ci fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle()); 90cb93a386Sopenharmony_ci SkFont font(fTypeface); 91cb93a386Sopenharmony_ci size_t txtLen = strlen(fText); 92cb93a386Sopenharmony_ci int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci fGlyphs.append(glyphCount); 95cb93a386Sopenharmony_ci font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount); 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci SkString onShortName() override { 99cb93a386Sopenharmony_ci return SkString("textblob"); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci SkISize onISize() override { 103cb93a386Sopenharmony_ci return SkISize::Make(640, 480); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci void onDraw(SkCanvas* canvas) override { 107cb93a386Sopenharmony_ci for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) { 108cb93a386Sopenharmony_ci sk_sp<SkTextBlob> blob(this->makeBlob(b)); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci SkPaint p; 111cb93a386Sopenharmony_ci p.setAntiAlias(true); 112cb93a386Sopenharmony_ci SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)), 113cb93a386Sopenharmony_ci SkIntToScalar(20 + 150 * (b / 2))); 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci canvas->drawTextBlob(blob, offset.x(), offset.y(), p); 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci p.setColor(SK_ColorBLUE); 118cb93a386Sopenharmony_ci p.setStyle(SkPaint::kStroke_Style); 119cb93a386Sopenharmony_ci SkRect box = blob->bounds(); 120cb93a386Sopenharmony_ci box.offset(offset); 121cb93a386Sopenharmony_ci p.setAntiAlias(false); 122cb93a386Sopenharmony_ci canvas->drawRect(box, p); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ciprivate: 128cb93a386Sopenharmony_ci sk_sp<SkTextBlob> makeBlob(unsigned blobIndex) { 129cb93a386Sopenharmony_ci SkTextBlobBuilder builder; 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci SkFont font; 132cb93a386Sopenharmony_ci font.setSubpixel(true); 133cb93a386Sopenharmony_ci font.setEdging(SkFont::Edging::kAntiAlias); 134cb93a386Sopenharmony_ci font.setTypeface(fTypeface); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) { 137cb93a386Sopenharmony_ci unsigned currentGlyph = 0; 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) { 140cb93a386Sopenharmony_ci const BlobCfg* cfg = &blobConfigs[blobIndex][l][c]; 141cb93a386Sopenharmony_ci unsigned count = cfg->count; 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci if (count > fGlyphs.count() - currentGlyph) { 144cb93a386Sopenharmony_ci count = fGlyphs.count() - currentGlyph; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci if (0 == count) { 147cb93a386Sopenharmony_ci break; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci font.setSize(kFontSize * cfg->scale); 151cb93a386Sopenharmony_ci const SkScalar advanceX = font.getSize() * 0.85f; 152cb93a386Sopenharmony_ci const SkScalar advanceY = font.getSize() * 1.5f; 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX, 155cb93a386Sopenharmony_ci advanceY * l); 156cb93a386Sopenharmony_ci switch (cfg->pos) { 157cb93a386Sopenharmony_ci case kDefault_Pos: { 158cb93a386Sopenharmony_ci const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count, 159cb93a386Sopenharmony_ci offset.x(), 160cb93a386Sopenharmony_ci offset.y()); 161cb93a386Sopenharmony_ci memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); 162cb93a386Sopenharmony_ci } break; 163cb93a386Sopenharmony_ci case kScalar_Pos: { 164cb93a386Sopenharmony_ci const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count, 165cb93a386Sopenharmony_ci offset.y()); 166cb93a386Sopenharmony_ci SkTDArray<SkScalar> pos; 167cb93a386Sopenharmony_ci for (unsigned i = 0; i < count; ++i) { 168cb93a386Sopenharmony_ci *pos.append() = offset.x() + i * advanceX; 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); 172cb93a386Sopenharmony_ci memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar)); 173cb93a386Sopenharmony_ci } break; 174cb93a386Sopenharmony_ci case kPoint_Pos: { 175cb93a386Sopenharmony_ci const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count); 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci SkTDArray<SkScalar> pos; 178cb93a386Sopenharmony_ci for (unsigned i = 0; i < count; ++i) { 179cb93a386Sopenharmony_ci *pos.append() = offset.x() + i * advanceX; 180cb93a386Sopenharmony_ci *pos.append() = offset.y() + i * (advanceY / count); 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t)); 184cb93a386Sopenharmony_ci memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2); 185cb93a386Sopenharmony_ci } break; 186cb93a386Sopenharmony_ci default: 187cb93a386Sopenharmony_ci SK_ABORT("unhandled pos value"); 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci currentGlyph += count; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci return builder.make(); 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci SkTDArray<uint16_t> fGlyphs; 198cb93a386Sopenharmony_ci sk_sp<SkTypeface> fTypeface; 199cb93a386Sopenharmony_ci const char* fText; 200cb93a386Sopenharmony_ci using INHERITED = skiagm::GM; 201cb93a386Sopenharmony_ci}; 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ciDEF_GM(return new TextBlobGM("hamburgefons");) 204