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 "SkCanvas.h"
     13 #include "SkGradientShader.h"
     14 #include "SkRandomScalerContext.h"
     15 #include "SkStream.h"
     16 #include "SkSurface.h"
     17 #include "SkTextBlob.h"
     18 #include "SkTypeface.h"
     19 
     20 #include "GrContext.h"
     21 
     22 namespace skiagm {
     23 class TextBlobRandomFont : public GpuGM {
     24 public:
     25     // This gm tests that textblobs can be translated and scaled with a font that returns random
     26     // but deterministic masks
     27     TextBlobRandomFont() { }
     28 
     29 protected:
     30     void onOnceBeforeDraw() override {
     31         SkTextBlobBuilder builder;
     32 
     33         const char* text = "The quick brown fox jumps over the lazy dog.";
     34 
     35         SkPaint paint;
     36         paint.setAntiAlias(true);
     37         paint.setColor(SK_ColorMAGENTA);
     38 
     39         // make textbloben
     40         SkFont font;
     41         font.setSize(32);
     42         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
     43 
     44         // Setup our random scaler context
     45         auto typeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
     46         if (!typeface) {
     47             typeface = SkTypeface::MakeDefault();
     48         }
     49         font.setTypeface(sk_make_sp<SkRandomTypeface>(std::move(typeface), paint, false));
     50 
     51         SkScalar y = 0;
     52         SkRect bounds;
     53         font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &bounds);
     54         y -= bounds.fTop;
     55         sk_tool_utils::add_to_text_blob(&builder, text, font, 0, y);
     56         y += bounds.fBottom;
     57 
     58         // A8
     59         const char* bigtext1 = "The quick brown fox";
     60         const char* bigtext2 = "jumps over the lazy dog.";
     61         font.setSize(160);
     62         font.setSubpixel(false);
     63         font.setEdging(SkFont::Edging::kAntiAlias);
     64         font.measureText(bigtext1, strlen(bigtext1), kUTF8_SkTextEncoding, &bounds);
     65         y -= bounds.fTop;
     66         sk_tool_utils::add_to_text_blob(&builder, bigtext1, font, 0, y);
     67         y += bounds.fBottom;
     68 
     69         font.measureText(bigtext2, strlen(bigtext2), kUTF8_SkTextEncoding, &bounds);
     70         y -= bounds.fTop;
     71         sk_tool_utils::add_to_text_blob(&builder, bigtext2, font, 0, y);
     72         y += bounds.fBottom;
     73 
     74         // color emoji
     75         if (sk_sp<SkTypeface> origEmoji = sk_tool_utils::emoji_typeface()) {
     76             font.setTypeface(sk_make_sp<SkRandomTypeface>(origEmoji, paint, false));
     77             const char* emojiText = sk_tool_utils::emoji_sample_text();
     78             font.measureText(emojiText, strlen(emojiText), kUTF8_SkTextEncoding, &bounds);
     79             y -= bounds.fTop;
     80             sk_tool_utils::add_to_text_blob(&builder, emojiText, font, 0, y);
     81             y += bounds.fBottom;
     82         }
     83 
     84         // build
     85         fBlob = builder.make();
     86     }
     87 
     88     SkString onShortName() override {
     89         return SkString("textblobrandomfont");
     90     }
     91 
     92     SkISize onISize() override {
     93         return SkISize::Make(kWidth, kHeight);
     94     }
     95 
     96     DrawResult onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas,
     97                       SkString* errorMsg) override {
     98         // This GM exists to test a specific feature of the GPU backend.
     99         // This GM uses sk_tool_utils::makeSurface which doesn't work well with vias.
    100         // This GM uses SkRandomTypeface which doesn't work well with serialization.
    101         canvas->drawColor(SK_ColorWHITE);
    102 
    103         SkImageInfo info = SkImageInfo::Make(kWidth, kHeight, canvas->imageInfo().colorType(),
    104                                              kPremul_SkAlphaType,
    105                                              canvas->imageInfo().refColorSpace());
    106         SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
    107         auto surface(sk_tool_utils::makeSurface(canvas, info, &props));
    108         if (!surface) {
    109             *errorMsg = "This test requires a surface";
    110             return DrawResult::kFail;
    111         }
    112 
    113         SkPaint paint;
    114         paint.setAntiAlias(true);
    115 
    116         SkCanvas* surfaceCanvas = surface->getCanvas();
    117 
    118         SkScalar stride = SkScalarCeilToScalar(fBlob->bounds().height());
    119         SkScalar yOffset = 5;
    120 
    121         canvas->save();
    122         // Originally we would alternate between rotating and not to force blob regeneration,
    123         // but that code seems to have rotted. Keeping the rotate to match the old GM as
    124         // much as possible, and it seems like a reasonable stress test for transformed
    125         // color emoji.
    126         canvas->rotate(-0.05f);
    127         canvas->drawTextBlob(fBlob, 10, yOffset, paint);
    128         yOffset += stride;
    129         canvas->restore();
    130 
    131         // Rotate in the surface canvas, not the final canvas, to avoid aliasing
    132         surfaceCanvas->rotate(-0.05f);
    133         surfaceCanvas->drawTextBlob(fBlob, 10, yOffset, paint);
    134         surface->draw(canvas, 0, 0, nullptr);
    135         yOffset += stride;
    136 
    137         // free gpu resources and verify
    138         context->freeGpuResources();
    139 
    140         canvas->rotate(-0.05f);
    141         canvas->drawTextBlob(fBlob, 10, yOffset, paint);
    142         yOffset += stride;
    143         return DrawResult::kOk;
    144     }
    145 
    146 private:
    147     sk_sp<SkTextBlob> fBlob;
    148 
    149     static constexpr int kWidth = 2000;
    150     static constexpr int kHeight = 1600;
    151 
    152     typedef GM INHERITED;
    153 };
    154 
    155 //////////////////////////////////////////////////////////////////////////////
    156 
    157 DEF_GM(return new TextBlobRandomFont;)
    158 }
    159