1 /* 2 * Copyright 2017 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 8 #include "gm.h" 9 #include "Resources.h" 10 #include "SkCanvas.h" 11 #include "SkSurface.h" 12 #include "SkTextBlob.h" 13 #include "SkTypeface.h" 14 #include "sk_tool_utils.h" 15 16 /** 17 * This GM tests reusing the same text blobs with distance fields rendering using various 18 * combinations of perspective and non-perspetive matrices, scissor clips, and different x,y params 19 * passed to the draw. 20 */ 21 class DFTextBlobPerspGM : public skiagm::GM { 22 public: DFTextBlobPerspGM()23 DFTextBlobPerspGM() { this->setBGColor(0xFFFFFFFF); } 24 25 protected: onShortName()26 SkString onShortName() override { 27 SkString name("dftext_blob_persp"); 28 name.append(sk_tool_utils::platform_font_manager()); 29 return name; 30 } 31 onISize()32 SkISize onISize() override { return SkISize::Make(900, 350); } 33 onOnceBeforeDraw()34 void onOnceBeforeDraw() override { 35 for (int i = 0; i < 3; ++i) { 36 SkFont font; 37 font.setSize(32); 38 font.setEdging(i == 0 ? SkFont::Edging::kAlias : 39 (i == 1 ? SkFont::Edging::kAntiAlias : 40 SkFont::Edging::kSubpixelAntiAlias)); 41 font.setSubpixel(true); 42 SkTextBlobBuilder builder; 43 sk_tool_utils::add_to_text_blob(&builder, "SkiaText", font, 0, 0); 44 fBlobs.emplace_back(builder.make()); 45 } 46 } 47 onDraw(SkCanvas * inputCanvas)48 void onDraw(SkCanvas* inputCanvas) override { 49 // set up offscreen rendering with distance field text 50 GrContext* ctx = inputCanvas->getGrContext(); 51 SkISize size = this->onISize(); 52 if (!inputCanvas->getBaseLayerSize().isEmpty()) { 53 size = inputCanvas->getBaseLayerSize(); 54 } 55 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType, 56 inputCanvas->imageInfo().refColorSpace()); 57 SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, 58 SkSurfaceProps::kLegacyFontHost_InitType); 59 auto surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); 60 SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas; 61 // init our new canvas with the old canvas's matrix 62 canvas->setMatrix(inputCanvas->getTotalMatrix()); 63 SkScalar x = 0, y = 0; 64 SkScalar maxH = 0; 65 for (auto twm : {TranslateWithMatrix::kNo, TranslateWithMatrix::kYes}) { 66 for (auto pm : {PerspMode::kNone, PerspMode::kX, PerspMode::kY, PerspMode::kXY}) { 67 for (auto& blob : fBlobs) { 68 for (bool clip : {false, true}) { 69 canvas->save(); 70 SkScalar w = blob->bounds().width(); 71 SkScalar h = blob->bounds().height(); 72 if (clip) { 73 auto rect = 74 SkRect::MakeXYWH(x + 5, y + 5, w * 3.f / 4.f, h * 3.f / 4.f); 75 canvas->clipRect(rect, false); 76 } 77 this->drawBlob(canvas, blob.get(), SK_ColorBLACK, x, y + h, pm, twm); 78 x += w + 20.f; 79 maxH = SkTMax(h, maxH); 80 canvas->restore(); 81 } 82 } 83 x = 0; 84 y += maxH + 20.f; 85 maxH = 0; 86 } 87 } 88 // render offscreen buffer 89 if (surface) { 90 SkAutoCanvasRestore acr(inputCanvas, true); 91 // since we prepended this matrix already, we blit using identity 92 inputCanvas->resetMatrix(); 93 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); 94 } 95 } 96 97 private: 98 enum class PerspMode { kNone, kX, kY, kXY }; 99 100 enum class TranslateWithMatrix : bool { kNo, kYes }; 101 drawBlob(SkCanvas * canvas,SkTextBlob * blob,SkColor color,SkScalar x,SkScalar y,PerspMode perspMode,TranslateWithMatrix translateWithMatrix)102 void drawBlob(SkCanvas* canvas, SkTextBlob* blob, SkColor color, SkScalar x, SkScalar y, 103 PerspMode perspMode, TranslateWithMatrix translateWithMatrix) { 104 canvas->save(); 105 SkMatrix persp = SkMatrix::I(); 106 switch (perspMode) { 107 case PerspMode::kNone: 108 break; 109 case PerspMode::kX: 110 persp.setPerspX(0.005f); 111 break; 112 case PerspMode::kY: 113 persp.setPerspY(00.005f); 114 break; 115 case PerspMode::kXY: 116 persp.setPerspX(-0.001f); 117 persp.setPerspY(-0.0015f); 118 break; 119 } 120 persp = SkMatrix::Concat(persp, SkMatrix::MakeTrans(-x, -y)); 121 persp = SkMatrix::Concat(SkMatrix::MakeTrans(x, y), persp); 122 canvas->concat(persp); 123 if (TranslateWithMatrix::kYes == translateWithMatrix) { 124 canvas->translate(x, y); 125 x = 0; 126 y = 0; 127 } 128 SkPaint paint; 129 paint.setColor(color); 130 canvas->drawTextBlob(blob, x, y, paint); 131 canvas->restore(); 132 } 133 134 SkTArray<sk_sp<SkTextBlob>> fBlobs; 135 typedef skiagm::GM INHERITED; 136 }; 137 138 DEF_GM(return new DFTextBlobPerspGM;) 139