14ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com/*
24ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com * Copyright 2013 Google Inc.
34ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com *
44ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com * Use of this source code is governed by a BSD-style license that can be
54ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com * found in the LICENSE file.
64ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com */
74ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
84ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com#include "gm.h"
933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h"
10651bb5fafe1edd723425dffd478dfa67b113da73robertphillips#include "SkAnimTimer.h"
114ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com#include "SkCanvas.h"
124ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com#include "SkPath.h"
134ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
144ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com// Reproduces https://code.google.com/p/chromium/issues/detail?id=279014
154ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
16dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int kWidth = 440;
17dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int kHeight = 440;
18dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr SkScalar kAngle = 0.305f;
19dbfd7ab10883f173f5c1b653a233e18dc6142002mtkleinconstexpr int kMaxNumSteps = 140;
204ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
214ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com// Renders a string art shape.
224ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com// The particular shape rendered can be controlled by adjusting kAngle, from 0 to 1
234ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
244ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.comclass StringArtGM : public skiagm::GM {
254ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.compublic:
26651bb5fafe1edd723425dffd478dfa67b113da73robertphillips    StringArtGM() : fNumSteps(kMaxNumSteps) {}
274ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
284ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.comprotected:
29a90c6803865766d28e92091f56f718f5e41fe80fcommit-bot@chromium.org
3036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkString onShortName() override {
314ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        return SkString("stringart");
324ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com    }
334ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
3436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkISize onISize() override {
354ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        return SkISize::Make(kWidth, kHeight);
364ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com    }
374ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
3836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onDraw(SkCanvas* canvas) override {
394ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkScalar angle = kAngle*SK_ScalarPI + SkScalarHalf(SK_ScalarPI);
40eb95d6a59176e350777a991d4fa9073f6c774b40jvanverth@google.com        SkScalar size = SkIntToScalar(SkMin32(kWidth, kHeight));
414ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkPoint center = SkPoint::Make(SkScalarHalf(kWidth), SkScalarHalf(kHeight));
424ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkScalar length = 5;
434ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkScalar step = angle;
444ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
454ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkPath path;
464ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        path.moveTo(center);
474ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
48651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        for (int i = 0; i < fNumSteps && length < (SkScalarHalf(size) - 10.f); ++i) {
494ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com            SkPoint rp = SkPoint::Make(length*SkScalarCos(step) + center.fX,
504ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com                                       length*SkScalarSin(step) + center.fY);
514ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com            path.lineTo(rp);
5280ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed            length += angle / SkScalarHalf(SK_ScalarPI);
534ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com            step += angle;
544ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        }
554ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
564ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        SkPaint paint;
574ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        paint.setAntiAlias(true);
584ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        paint.setStyle(SkPaint::kStroke_Style);
59125960152dfd7f2aba4c2239131bdf75d9ac2705caryclark        paint.setColor(sk_tool_utils::color_to_565(0xFF007700));
604ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
614ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com        canvas->drawPath(path, paint);
624ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com    }
634ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
64651bb5fafe1edd723425dffd478dfa67b113da73robertphillips    bool onAnimate(const SkAnimTimer& timer) override {
65dbfd7ab10883f173f5c1b653a233e18dc6142002mtklein        constexpr SkScalar kDesiredDurationSecs = 3.0f;
66651bb5fafe1edd723425dffd478dfa67b113da73robertphillips
67651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        // Make the animation ping-pong back and forth but start in the fully drawn state
68651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        SkScalar fraction = 1.0f - timer.scaled(2.0f/kDesiredDurationSecs, 2.0f);
69651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        if (fraction <= 0.0f) {
70651bb5fafe1edd723425dffd478dfa67b113da73robertphillips            fraction = -fraction;
71651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        }
72651bb5fafe1edd723425dffd478dfa67b113da73robertphillips
73651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        SkASSERT(fraction >= 0.0f && fraction <= 1.0f);
74651bb5fafe1edd723425dffd478dfa67b113da73robertphillips
75651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        fNumSteps = (int) (fraction * kMaxNumSteps);
76651bb5fafe1edd723425dffd478dfa67b113da73robertphillips        return true;
77651bb5fafe1edd723425dffd478dfa67b113da73robertphillips    }
78651bb5fafe1edd723425dffd478dfa67b113da73robertphillips
794ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.comprivate:
80651bb5fafe1edd723425dffd478dfa67b113da73robertphillips    int fNumSteps;
81651bb5fafe1edd723425dffd478dfa67b113da73robertphillips
824ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com    typedef GM INHERITED;
834ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com};
844ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.com
854ea2878f076cd41da803e6fcdcfb884b18a5b00cjvanverth@google.comDEF_GM( return new StringArtGM; )
86