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