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