1/*
2 * Copyright 2018 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#include "samplecode/Sample.h"
8#include "tools/ToolUtils.h"
9
10#include "include/core/SkCanvas.h"
11#include "include/core/SkPath.h"
12#include "include/core/SkRRect.h"
13#include "include/core/SkTypeface.h"
14#include "include/utils/SkRandom.h"
15#include "tools/timer/TimeUtils.h"
16
17#include <cmath>
18
19// Implementation in C++ of Animated Emoji
20// See https://t.d3fc.io/status/705212795936247808
21// See https://crbug.com/848616
22
23class GlyphTransformView : public Sample {
24public:
25    GlyphTransformView() {}
26
27protected:
28    void onOnceBeforeDraw() override {
29        fEmojiFont.fTypeface = ToolUtils::emoji_typeface();
30        fEmojiFont.fText     = ToolUtils::emoji_sample_text();
31    }
32
33    SkString name() override { return SkString("Glyph Transform"); }
34
35    void onDrawContent(SkCanvas* canvas) override {
36        SkPaint paint;
37
38        SkFont font(fEmojiFont.fTypeface);
39        const char* text = fEmojiFont.fText;
40
41        double baseline = this->height() / 2;
42        canvas->drawLine(0, baseline, this->width(), baseline, paint);
43
44        SkMatrix ctm;
45        ctm.setRotate(fRotate); // d3 rotate takes degrees
46        ctm.postScale(fScale * 4, fScale * 4);
47        ctm.postTranslate(fTranslate.fX  + this->width() * 0.8, fTranslate.fY + baseline);
48        canvas->concat(ctm);
49
50        // d3 by default anchors text around the middle
51        SkRect bounds;
52        font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
53        canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, -bounds.centerX(), -bounds.centerY(),
54                               font, paint);
55    }
56
57    bool onAnimate(double nanos) override {
58        constexpr SkScalar maxt = 100000;
59        double t = TimeUtils::PingPong(1e-9 * nanos, 20, 0, 0, maxt); // d3 t is in milliseconds
60
61        fTranslate.set(sin(t / 3000) - t * this->width() * 0.7 / maxt, sin(t / 999) / t);
62        fScale = 4.5 - std::sqrt(t) / 99;
63        fRotate = sin(t / 734);
64
65        return true;
66    }
67
68private:
69    struct EmojiFont {
70        sk_sp<SkTypeface> fTypeface;
71        const char* fText;
72    } fEmojiFont;
73
74    SkVector fTranslate;
75    SkScalar fScale;
76    SkScalar fRotate;
77
78    using INHERITED = Sample;
79};
80
81//////////////////////////////////////////////////////////////////////////////
82
83DEF_SAMPLE( return new GlyphTransformView(); )
84