Home | History | Annotate | Download | only in samplecode
      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 "Sample.h"
      9 #include "SkCanvas.h"
     10 #include "SkUTF.h"
     11 #include "SkColorPriv.h"
     12 #include "SkColorFilter.h"
     13 #include "SkImage.h"
     14 #include "SkRandom.h"
     15 #include "SkTime.h"
     16 #include "SkTypeface.h"
     17 #include "Timer.h"
     18 
     19 #if SK_SUPPORT_GPU
     20 #include "GrContext.h"
     21 #include "GrContextPriv.h"
     22 #endif
     23 
     24 SkRandom gRand;
     25 
     26 static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, SkScalar x, SkScalar y,
     27                         const SkFont& font, const SkPaint& paint) {
     28     SkFont f(font);
     29     f.setSubpixel(true);
     30     canvas->drawSimpleText(text, length, kUTF8_SkTextEncoding, x, y, f, paint);
     31 }
     32 
     33 // This sample demonstrates the cache behavior of bitmap vs. distance field text
     34 // It renders variously sized text with an animated scale and rotation.
     35 // Specifically one should:
     36 //   use 'D' to toggle between bitmap and distance field fonts
     37 //   use '2' to toggle between scaling the image by 2x
     38 //            -- this feature boosts the rendering out of the small point-size
     39 //               SDF-text special case (which falls back to bitmap fonts for small points)
     40 
     41 class AnimatedTextView : public Sample {
     42 public:
     43     AnimatedTextView() : fScale(1.0f), fScaleInc(0.1f), fRotation(0.0f), fSizeScale(1) {
     44         fCurrentTime = 0;
     45         fTimer.start();
     46         memset(fTimes, 0, sizeof(fTimes));
     47     }
     48 
     49 protected:
     50     bool onQuery(Sample::Event* evt) override {
     51         if (Sample::TitleQ(*evt)) {
     52             Sample::TitleR(evt, "AnimatedText");
     53             return true;
     54         }
     55 
     56         SkUnichar uni;
     57         if (Sample::CharQ(*evt, &uni)) {
     58             if ('2' == uni) {
     59                 if (fSizeScale == 2) {
     60                     fSizeScale = 1;
     61                 } else {
     62                     fSizeScale = 2;
     63                 }
     64                 return true;
     65             }
     66         }
     67         return this->INHERITED::onQuery(evt);
     68     }
     69 
     70     void onDrawContent(SkCanvas* canvas) override {
     71         SkFont font(SkTypeface::MakeFromFile("/skimages/samplefont.ttf"));
     72 
     73         SkPaint paint;
     74         paint.setAntiAlias(true);
     75         paint.setFilterQuality(kMedium_SkFilterQuality);
     76 
     77         SkString outString("fps: ");
     78         fTimer.end();
     79 
     80         // TODO: generalize this timing code in utils
     81         fTimes[fCurrentTime] = (float)(fTimer.fWall);
     82         fCurrentTime = (fCurrentTime + 1) & 0x1f;
     83 
     84         float meanTime = 0.0f;
     85         for (int i = 0; i < 32; ++i) {
     86             meanTime += fTimes[i];
     87         }
     88         meanTime /= 32.f;
     89         SkScalar fps = 1000.f / meanTime;
     90         outString.appendScalar(fps);
     91         outString.append(" ms: ");
     92         outString.appendScalar(meanTime);
     93 
     94         SkString modeString("Text scale: ");
     95         modeString.appendU32(fSizeScale);
     96         modeString.append("x");
     97 
     98         fTimer.start();
     99 
    100         canvas->save();
    101 
    102 #if SK_SUPPORT_GPU
    103         GrContext* grContext = canvas->getGrContext();
    104         if (grContext) {
    105             sk_sp<SkImage> image = grContext->contextPriv().getFontAtlasImage_ForTesting(
    106                                                                 GrMaskFormat::kA8_GrMaskFormat);
    107             canvas->drawImageRect(image,
    108                                   SkRect::MakeXYWH(512.0f, 10.0f, 512.0f, 512.0f), &paint);
    109         }
    110 #endif
    111         canvas->translate(180, 180);
    112         canvas->rotate(fRotation);
    113         canvas->scale(fScale, fScale);
    114         canvas->translate(-180, -180);
    115 
    116         const char* text = "Hamburgefons";
    117         size_t length = strlen(text);
    118 
    119         SkScalar y = SkIntToScalar(0);
    120         for (int i = 12; i <= 26; i++) {
    121             font.setSize(SkIntToScalar(i*fSizeScale));
    122             y += font.getSpacing();
    123             DrawTheText(canvas, text, length, SkIntToScalar(110), y, font, paint);
    124         }
    125         canvas->restore();
    126 
    127         font.setSize(16);
    128 //        canvas->drawString(outString, 512.f, 540.f, paint);
    129         canvas->drawString(modeString, 768.f, 540.f, font, paint);
    130     }
    131 
    132     bool onAnimate(const SkAnimTimer& timer) override {
    133         // We add noise to the scale and rotation animations to
    134         // keep the font atlas from falling into a steady state
    135         fRotation += (1.0f + gRand.nextRangeF(-0.1f, 0.1f));
    136         fScale += (fScaleInc + gRand.nextRangeF(-0.025f, 0.025f));
    137         if (fScale >= 2.0f) {
    138             fScaleInc = -0.1f;
    139         } else if (fScale <= 1.0f) {
    140             fScaleInc = 0.1f;
    141         }
    142         return true;
    143     }
    144 
    145 private:
    146     float fScale;
    147     float fScaleInc;
    148     float fRotation;
    149     int   fSizeScale;
    150 
    151     WallTimer   fTimer;
    152     float       fTimes[32];
    153     int         fCurrentTime;
    154 
    155 
    156     typedef Sample INHERITED;
    157 };
    158 
    159 //////////////////////////////////////////////////////////////////////////////
    160 
    161 DEF_SAMPLE( return new AnimatedTextView(); )
    162