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         SkString name("textblobmixedsizes");
     89         if (fUseDFT) {
     90             name.appendf("_df");
     91         }
     92         return name;
     93     }
     94 
     95     SkISize onISize() override {
     96         return SkISize::Make(kWidth, kHeight);
     97     }
     98 
     99     void onDraw(SkCanvas* inputCanvas) override {
    100         SkCanvas* canvas = inputCanvas;
    101         sk_sp<SkSurface> surface;
    102         if (fUseDFT) {
    103 #if SK_SUPPORT_GPU
    104             // Create a new Canvas to enable DFT
    105             GrContext* ctx = inputCanvas->getGrContext();
    106             SkISize size = onISize();
    107             sk_sp<SkColorSpace> colorSpace = inputCanvas->imageInfo().refColorSpace();
    108             SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(),
    109                                                     kPremul_SkAlphaType, colorSpace);
    110             SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag,
    111                                  SkSurfaceProps::kLegacyFontHost_InitType);
    112             surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props);
    113             canvas = surface.get() ? surface->getCanvas() : inputCanvas;
    114             // init our new canvas with the old canvas's matrix
    115             canvas->setMatrix(inputCanvas->getTotalMatrix());
    116 #endif
    117         }
    118         canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
    119 
    120         SkRect bounds = fBlob->bounds();
    121 
    122         const int kPadX = SkScalarFloorToInt(bounds.width() / 3);
    123         const int kPadY = SkScalarFloorToInt(bounds.height() / 3);
    124 
    125         int rowCount = 0;
    126         canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY));
    127         canvas->save();
    128         SkRandom random;
    129 
    130         SkPaint paint;
    131         if (!fUseDFT) {
    132             paint.setColor(sk_tool_utils::color_to_565(SK_ColorWHITE));
    133         }
    134         paint.setAntiAlias(false);
    135 
    136         const SkScalar kSigma = SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(8));
    137 
    138         // setup blur paint
    139         SkPaint blurPaint(paint);
    140         blurPaint.setColor(sk_tool_utils::color_to_565(SK_ColorBLACK));
    141         blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kSigma));
    142 
    143         for (int i = 0; i < 4; i++) {
    144             canvas->save();
    145             switch (i % 2) {
    146                 case 0:
    147                     canvas->rotate(random.nextF() * 45.f);
    148                     break;
    149                 case 1:
    150                     canvas->rotate(-random.nextF() * 45.f);
    151                     break;
    152             }
    153             if (!fUseDFT) {
    154                 canvas->drawTextBlob(fBlob, 0, 0, blurPaint);
    155             }
    156             canvas->drawTextBlob(fBlob, 0, 0, paint);
    157             canvas->restore();
    158             canvas->translate(bounds.width() + SK_Scalar1 * kPadX, 0);
    159             ++rowCount;
    160             if ((bounds.width() + 2 * kPadX) * rowCount > kWidth) {
    161                 canvas->restore();
    162                 canvas->translate(0, bounds.height() + SK_Scalar1 * kPadY);
    163                 canvas->save();
    164                 rowCount = 0;
    165             }
    166         }
    167         canvas->restore();
    168 
    169 #if SK_SUPPORT_GPU
    170         // render offscreen buffer
    171         if (surface) {
    172             SkAutoCanvasRestore acr(inputCanvas, true);
    173             // since we prepended this matrix already, we blit using identity
    174             inputCanvas->resetMatrix();
    175             inputCanvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, nullptr);
    176         }
    177 #endif
    178     }
    179 
    180 private:
    181     sk_sp<SkTextBlob> fBlob;
    182 
    183     static constexpr int kWidth = 2100;
    184     static constexpr int kHeight = 1900;
    185 
    186     bool fUseDFT;
    187 
    188     typedef GM INHERITED;
    189 };
    190 
    191 //////////////////////////////////////////////////////////////////////////////
    192 
    193 DEF_GM( return new TextBlobMixedSizes(false); )
    194 #if SK_SUPPORT_GPU
    195 DEF_GM( return new TextBlobMixedSizes(true); )
    196 #endif
    197 }
    198