1e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt/* 2e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * Copyright 2015 Google Inc. 3e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * 4e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * Use of this source code is governed by a BSD-style license that can be 5e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt * found in the LICENSE file. 6e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt */ 7e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 8e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "gm.h" 933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h" 10e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 11e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "Resources.h" 12e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkBlurMask.h" 13e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkBlurMaskFilter.h" 14e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkCanvas.h" 15e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkGradientShader.h" 16e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkImage.h" 17e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkRandom.h" 18e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkStream.h" 19e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkSurface.h" 20e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkTextBlob.h" 21e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#include "SkTypeface.h" 22e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 23e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittnamespace skiagm { 24e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittclass TextBlobMixedSizes : public GM { 25e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittpublic: 26e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // This gm tests that textblobs of mixed sizes with a large glyph will render properly 27e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt TextBlobMixedSizes(bool useDFT) : fUseDFT(useDFT) {} 28e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 29e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittprotected: 30e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt void onOnceBeforeDraw() override { 31e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkTextBlobBuilder builder; 32e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 33e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // make textblob. To stress distance fields, we choose sizes appropriately 34e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkPaint paint; 35e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setAntiAlias(true); 36e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setSubpixelText(true); 37e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setLCDRenderText(true); 3813b9c95295f4c5732e34574789e721a6bc08f7b4bungeman paint.setTypeface(MakeResourceAsTypeface("/fonts/HangingS.ttf")); 39e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 4033e91f1673123d3f19b372ec0660edd611f706a0joshualitt const char* text = "Skia"; 41e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 42e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // extra large 43e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setTextSize(262); 44e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 45e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, 0); 46e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 47e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // large 48e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkRect bounds; 49e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.measureText(text, strlen(text), &bounds); 50e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkScalar yOffset = bounds.height(); 51e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setTextSize(162); 52e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 53e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); 54e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 55e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // Medium 56e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.measureText(text, strlen(text), &bounds); 57e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt yOffset += bounds.height(); 58e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setTextSize(72); 59e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 60e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); 61e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 62e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // Small 63e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.measureText(text, strlen(text), &bounds); 64e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt yOffset += bounds.height(); 65e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setTextSize(32); 66e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 67e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); 68e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 69e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // micro (will fall out of distance field text even if distance field text is enabled) 70e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.measureText(text, strlen(text), &bounds); 71e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt yOffset += bounds.height(); 72e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setTextSize(14); 73e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 74e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); 75e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 7668c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen // Zero size. 7768c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen paint.measureText(text, strlen(text), &bounds); 7868c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen yOffset += bounds.height(); 7968c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen paint.setTextSize(0); 8068c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen 8168c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen sk_tool_utils::add_to_text_blob(&builder, text, paint, 0, yOffset); 8268c63b3727f05638a95fcf5f65c5476a2fcb34d0kkinnunen 83e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // build 8437283c28aa5bea2204c18956e74f83b238d7a891fmalita fBlob = builder.make(); 85e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 86e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 87e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkString onShortName() override { 88e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkString name("textblobmixedsizes"); 89e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if (fUseDFT) { 90e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt name.appendf("_df"); 91e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 92e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt return name; 93e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 94e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 95e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkISize onISize() override { 96e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt return SkISize::Make(kWidth, kHeight); 97e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 98e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 99e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt void onDraw(SkCanvas* inputCanvas) override { 100e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkCanvas* canvas = inputCanvas; 101e8f3062a36d3682f4019309a32b5b84dc9eddf8creed sk_sp<SkSurface> surface; 102e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if (fUseDFT) { 103e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU 104e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // Create a new Canvas to enable DFT 105e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt GrContext* ctx = inputCanvas->getGrContext(); 10652ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman SkISize size = onISize(); 107693fdbd6b81a860657612e7604430dd55d6e721bMike Reed sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace(); 10852ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), 10952ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman kPremul_SkAlphaType, colorSpace); 1103a0dbde1cfa84b08c7dd5b597142e9f6179f2d07brianosman SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, 111e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkSurfaceProps::kLegacyFontHost_InitType); 112e8f3062a36d3682f4019309a32b5b84dc9eddf8creed surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); 113e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas = surface.get() ? surface->getCanvas() : inputCanvas; 114e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // init our new canvas with the old canvas's matrix 115e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->setMatrix(inputCanvas->getTotalMatrix()); 116e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif 117e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 118e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE)); 119e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 120e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkRect bounds = fBlob->bounds(); 121e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 122dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein const int kPadX = SkScalarFloorToInt(bounds.width() / 3); 123dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein const int kPadY = SkScalarFloorToInt(bounds.height() / 3); 124e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 125e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt int rowCount = 0; 126e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY)); 127e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->save(); 128e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkRandom random; 129e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 130e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkPaint paint; 131e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if (!fUseDFT) { 132e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setColor(sk_tool_utils::color_to_565(SK_ColorWHITE)); 133e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 134e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt paint.setAntiAlias(false); 135e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 136dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8)); 137e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 138e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // setup blur paint 139e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkPaint blurPaint(paint); 140e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt blurPaint.setColor(sk_tool_utils::color_to_565(SK_ColorBLACK)); 141efdfd51b68a300d5c6e28743fe0344ca05d1cec9reed blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kSigma)); 142dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein 143e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt for (int i = 0; i < 4; i++) { 144e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->save(); 145e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt switch (i % 2) { 146e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt case 0: 147e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->rotate(random.nextF() * 45.f); 148e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt break; 149e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt case 1: 150e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->rotate(-random.nextF() * 45.f); 151e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt break; 152e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 153e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if (!fUseDFT) { 154e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->drawTextBlob(fBlob, 0, 0, blurPaint); 155e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 156e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->drawTextBlob(fBlob, 0, 0, paint); 157e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->restore(); 158e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0); 159e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt ++rowCount; 160e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) { 161e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->restore(); 162e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY); 163e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->save(); 164e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt rowCount = 0; 165e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 166e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 167e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt canvas->restore(); 168e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 169e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU 170e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // render offscreen buffer 171e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt if (surface) { 172e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt SkAutoCanvasRestore acr(inputCanvas, true); 173e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt // since we prepended this matrix already, we blit using identity 174e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt inputCanvas->resetMatrix(); 1759ce9d6772df650ceb0511f275e1a83dffa78ff72reed inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr); 176e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 177e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif 178e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt } 179e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 180e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualittprivate: 18137283c28aa5bea2204c18956e74f83b238d7a891fmalita sk_sp<SkTextBlob> fBlob; 182e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 183dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein static constexpr int kWidth = 2100; 184dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein static constexpr int kHeight = 1900; 185e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 186e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt bool fUseDFT; 187e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 188e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt typedef GM INHERITED; 189e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt}; 190e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 191e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt////////////////////////////////////////////////////////////////////////////// 192e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt 193385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(false); ) 194e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#if SK_SUPPORT_GPU 195385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanaryDEF_GM( return new TextBlobMixedSizes(true); ) 196e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt#endif 197e46cf96ef5781ac40852bbf4f489bc47e2a2485ejoshualitt} 198