1 /* 2 * Copyright 2015 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/gm.h" 9 #include "include/core/SkBlurTypes.h" 10 #include "include/core/SkCanvas.h" 11 #include "include/core/SkColor.h" 12 #include "include/core/SkColorSpace.h" 13 #include "include/core/SkFont.h" 14 #include "include/core/SkFontTypes.h" 15 #include "include/core/SkImageInfo.h" 16 #include "include/core/SkMaskFilter.h" 17 #include "include/core/SkPaint.h" 18 #include "include/core/SkRect.h" 19 #include "include/core/SkRefCnt.h" 20 #include "include/core/SkScalar.h" 21 #include "include/core/SkSize.h" 22 #include "include/core/SkString.h" 23 #include "include/core/SkSurface.h" 24 #include "include/core/SkSurfaceProps.h" 25 #include "include/core/SkTextBlob.h" 26 #include "include/core/SkTypeface.h" 27 #include "include/core/SkTypes.h" 28 #include "include/utils/SkRandom.h" 29 #include "src/core/SkBlurMask.h" 30 #include "tools/Resources.h" 31 #include "tools/ToolUtils.h" 32 33 #include <string.h> 34 35 class GrContext; 36 37 namespace skiagm { 38 class TextBlobMixedSizes : public GM { 39 public: 40 // This gm tests that textblobs of mixed sizes with a large glyph will render properly TextBlobMixedSizes(bool useDFT)41 TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {} 42 43 protected: onOnceBeforeDraw()44 void onOnceBeforeDraw() override { 45 SkTextBlobBuilder builder; 46 47 // make textblob. To stress distance fields, we choose sizes appropriately 48 SkFont font(MakeResourceAsTypeface("fonts/HangingS.ttf"), 262); 49 font.setSubpixel(true); 50 font.setEdging(SkFont::Edging::kSubpixelAntiAlias); 51 52 const char* text = "Skia"; 53 54 ToolUtils::add_to_text_blob(&builder, text, font, 0, 0); 55 56 // large 57 SkRect bounds; 58 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 59 SkScalar yOffset = bounds.height(); 60 font.setSize(162); 61 62 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset); 63 64 // Medium 65 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 66 yOffset += bounds.height(); 67 font.setSize(72); 68 69 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset); 70 71 // Small 72 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 73 yOffset += bounds.height(); 74 font.setSize(32); 75 76 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset); 77 78 // micro (will fall out of distance field text even if distance field text is enabled) 79 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 80 yOffset += bounds.height(); 81 font.setSize(14); 82 83 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset); 84 85 // Zero size. 86 font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds); 87 yOffset += bounds.height(); 88 font.setSize(0); 89 90 ToolUtils::add_to_text_blob(&builder, text, font, 0, yOffset); 91 92 // build 93 fBlob = builder.make(); 94 } 95 onShortName()96 SkString onShortName() override { 97 return SkStringPrintf("textblobmixedsizes%s", 98 fUseDFT ? "_df" : ""); 99 } 100 onISize()101 SkISize onISize() override { 102 return SkISize::Make(kWidth, kHeight); 103 } 104 onDraw(SkCanvas * inputCanvas)105 void onDraw(SkCanvas* inputCanvas) override { 106 SkCanvas* canvas = inputCanvas; 107 sk_sp<SkSurface> surface; 108 if (fUseDFT) { 109 // Create a new Canvas to enable DFT 110 GrContext* ctx = inputCanvas->getGrContext(); 111 SkISize size = onISize(); 112 sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace(); 113 SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), 114 kPremul_SkAlphaType, colorSpace); 115 SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, 116 SkSurfaceProps::kLegacyFontHost_InitType); 117 surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); 118 canvas = surface.get() ? surface->getCanvas() : inputCanvas; 119 // init our new canvas with the old canvas's matrix 120 canvas->setMatrix(inputCanvas->getTotalMatrix()); 121 } 122 canvas->drawColor(SK_ColorWHITE); 123 124 SkRect bounds = fBlob->bounds(); 125 126 const int kPadX = SkScalarFloorToInt(bounds.width() / 3); 127 const int kPadY = SkScalarFloorToInt(bounds.height() / 3); 128 129 int rowCount = 0; 130 canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY)); 131 canvas->save(); 132 SkRandom random; 133 134 SkPaint paint; 135 if (!fUseDFT) { 136 paint.setColor(SK_ColorWHITE); 137 } 138 paint.setAntiAlias(false); 139 140 const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8)); 141 142 // setup blur paint 143 SkPaint blurPaint(paint); 144 blurPaint.setColor(SK_ColorBLACK); 145 blurPaint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, kSigma)); 146 147 for (int i = 0; i < 4; i++) { 148 canvas->save(); 149 switch (i % 2) { 150 case 0: 151 canvas->rotate(random.nextF() * 45.f); 152 break; 153 case 1: 154 canvas->rotate(-random.nextF() * 45.f); 155 break; 156 } 157 if (!fUseDFT) { 158 canvas->drawTextBlob(fBlob, 0, 0, blurPaint); 159 } 160 canvas->drawTextBlob(fBlob, 0, 0, paint); 161 canvas->restore(); 162 canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0); 163 ++rowCount; 164 if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) { 165 canvas->restore(); 166 canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY); 167 canvas->save(); 168 rowCount = 0; 169 } 170 } 171 canvas->restore(); 172 173 // render offscreen buffer 174 if (surface) { 175 SkAutoCanvasRestore acr(inputCanvas, true); 176 // since we prepended this matrix already, we blit using identity 177 inputCanvas->resetMatrix(); 178 inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); 179 } 180 } 181 182 private: 183 sk_sp<SkTextBlob> fBlob; 184 185 static constexpr int kWidth = 2100; 186 static constexpr int kHeight = 1900; 187 188 bool fUseDFT; 189 190 typedef GM INHERITED; 191 }; 192 193 ////////////////////////////////////////////////////////////////////////////// 194 195 DEF_GM( return new TextBlobMixedSizes(false); ) 196 DEF_GM( return new TextBlobMixedSizes(true); ) 197 } 198