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