15c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon/* 25c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * Copyright 2017 Google Inc. 35c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * 45c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * Use of this source code is governed by a BSD-style license that can be 55c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * found in the LICENSE file. 65c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon */ 75c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 85c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "gm.h" 95c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "Resources.h" 105c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "SkCanvas.h" 115c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "SkSurface.h" 125c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "SkTextBlob.h" 135c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "SkTypeface.h" 145c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#include "sk_tool_utils.h" 155c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 165c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon/** 175c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * This GM tests reusing the same text blobs with distance fields rendering using various 185c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * combinations of perspective and non-perspetive matrices, scissor clips, and different x,y params 195c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon * passed to the draw. 205c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon */ 215c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomonclass DFTextBlobPerspGM : public skiagm::GM { 225c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomonpublic: 235c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); } 245c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 255c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomonprotected: 265c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkString onShortName() override { 275c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkString name("dftext_blob_persp"); 285c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon name.append(sk_tool_utils::platform_font_manager()); 295c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon return name; 305c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 315c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 325c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkISize onISize() override { return SkISize::Make(900, 350); } 335c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 345c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon void onOnceBeforeDraw() override { 355c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon for (int i = 0; i < 3; ++i) { 365c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkPaint paint; 375c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.setTextSize(32); 385c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.setAntiAlias(i > 0); 395c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.setLCDRenderText(i > 1); 405c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.setSubpixelText(true); 415c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkTextBlobBuilder builder; 425c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon sk_tool_utils::add_to_text_blob(&builder, "SkiaText", paint, 0, 0); 435c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon fBlobs.emplace_back(builder.make()); 445c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 455c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 465c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 475c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon virtual void onDraw(SkCanvas* inputCanvas) override { 485c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon // set up offscreen rendering with distance field text 495c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#if SK_SUPPORT_GPU 505c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon GrContext* ctx = inputCanvas->getGrContext(); 515c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkISize size = this->onISize(); 525c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon if (!inputCanvas->getBaseLayerSize().isEmpty()) { 535c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon size = inputCanvas->getBaseLayerSize(); 545c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 555c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType, 565c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon inputCanvas->imageInfo().refColorSpace()); 575c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, 585c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkSurfaceProps::kLegacyFontHost_InitType); 595c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); 605c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas; 615c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon // init our new canvas with the old canvas's matrix 625c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->setMatrix(inputCanvas->getTotalMatrix()); 635c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#else 645c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkCanvas* canvas = inputCanvas; 655c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#endif 665c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkScalar x = 0, y = 0; 675c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkScalar maxH = 0; 685c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) { 695c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) { 705c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon for (auto& blob : fBlobs) { 715c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon for (bool clip : {false, true}) { 725c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->save(); 735c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkScalar w = blob->bounds().width(); 745c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkScalar h = blob->bounds().height(); 755c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon if (clip) { 765c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon auto rect = 775c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f); 785c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->clipRect(rect, false); 795c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 805c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm); 815c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon x += w + 20.f; 825c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon maxH = SkTMax(h, maxH); 835c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->restore(); 845c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 855c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 865c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon x = 0; 875c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon y += maxH + 20.f; 885c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon maxH = 0; 895c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 905c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 915c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#if SK_SUPPORT_GPU 925c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon // render offscreen buffer 935c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon if (surface) { 945c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkAutoCanvasRestore acr(inputCanvas, true); 955c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon // since we prepended this matrix already, we blit using identity 965c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon inputCanvas->resetMatrix(); 975c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); 985c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 995c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon#endif 1005c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 1015c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 1025c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomonprivate: 1035c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon enum class PerspMode { kNone, kX, kY, kXY }; 1045c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 1055c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon enum class TranslateWithMatrix : bool { kNo, kYes }; 1065c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 1075c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y, 1085c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon PerspMode perspMode, TranslateWithMatrix translateWithMatrix) { 1095c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->save(); 1105c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkMatrix persp = SkMatrix::I(); 1115c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon switch (perspMode) { 1125c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon case PerspMode::kNone: 1135c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon break; 1145c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon case PerspMode::kX: 1155c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp.setPerspX(0.005f); 1165c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon break; 1175c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon case PerspMode::kY: 1185c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp.setPerspY(00.005f); 1195c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon break; 1205c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon case PerspMode::kXY: 1215c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp.setPerspX(-0.001f); 1225c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp.setPerspY(-0.0015f); 1235c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon break; 1245c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 1255c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp = SkMatrix::Concat(persp, SkMatrix::MakeTrans(-x, -y)); 1265c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon persp = SkMatrix::Concat(SkMatrix::MakeTrans(x, y), persp); 1275c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->concat(persp); 1285c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon if (TranslateWithMatrix::kYes == translateWithMatrix) { 1295c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->translate(x, y); 1305c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon x = 0; 1315c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon y = 0; 1325c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 1335c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkPaint paint; 1345c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon paint.setColor(color); 1355c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->drawTextBlob(blob, x, y, paint); 1365c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon canvas->restore(); 1375c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon } 1385c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 1395c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon SkTArray<sk_sp<SkTextBlob>, true> fBlobs; 1405c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon typedef skiagm::GM INHERITED; 1415c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon}; 1425c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian Salomon 1435c6ac64516bb56bbdb5d7aedee1a348acc16e29bBrian SalomonDEF_GM(return new DFTextBlobPerspGM;) 144