1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11
12#include "SkAnimator.h"
13#include "SkStream.h"
14#include "SkDOM.h"
15
16///////////////////////////////////////////////////////////////////////////////
17
18class SkAnimatorView : public SkView {
19public:
20    SkAnimatorView();
21    virtual ~SkAnimatorView();
22
23    void setURIBase(const char dir[]);
24
25    SkAnimator* getAnimator() const { return fAnimator; }
26
27    bool    decodeFile(const char path[]);
28    bool    decodeMemory(const void* buffer, size_t size);
29    bool    decodeStream(SkStream* stream);
30
31protected:
32    // overrides
33    virtual void onDraw(SkCanvas*);
34    virtual bool onQuery(SkEvent* evt);
35
36private:
37    SkString fBaseURI;
38    SkAnimator* fAnimator;
39
40    typedef SkView INHERITED;
41};
42
43SkAnimatorView::SkAnimatorView() : fAnimator(nullptr) {}
44
45SkAnimatorView::~SkAnimatorView() {
46    delete fAnimator;
47}
48
49void SkAnimatorView::setURIBase(const char dir[]) {
50    fBaseURI.set(dir);
51}
52
53bool SkAnimatorView::decodeFile(const char path[]) {
54    SkAutoTDelete<SkStream> is(SkStream::NewFromFile(path));
55    return is.get() != nullptr && this->decodeStream(is);
56}
57
58bool SkAnimatorView::decodeMemory(const void* buffer, size_t size) {
59    SkMemoryStream is(buffer, size);
60    return this->decodeStream(&is);
61}
62
63static const SkDOMNode* find_nodeID(const SkDOM& dom,
64                        const SkDOMNode* node, const char name[]) {
65    if (nullptr == node) {
66        node = dom.getRootNode();
67    }
68    do {
69        const char* idval = dom.findAttr(node, "id");
70        if (idval && !strcmp(idval, name)) {
71            return node;
72        }
73        const SkDOMNode* child = dom.getFirstChild(node);
74        if (child) {
75            const SkDOMNode* found = find_nodeID(dom, child, name);
76            if (found) {
77                return found;
78            }
79        }
80    } while ((node = dom.getNextSibling(node)) != nullptr);
81    return nullptr;
82}
83
84bool SkAnimatorView::decodeStream(SkStream* stream) {
85    delete fAnimator;
86    fAnimator = new SkAnimator;
87    fAnimator->setURIBase(fBaseURI.c_str());
88#if 0
89    if (!fAnimator->decodeStream(stream)) {
90        delete fAnimator;
91        fAnimator = nullptr;
92        return false;
93    }
94#else
95    size_t len = stream->getLength();
96    char* text = (char*)sk_malloc_throw(len);
97    stream->read(text, len);
98    SkDOM dom;
99    const SkDOM::Node* root = dom.build(text, len);
100    if (nullptr == root) {
101        return false;
102    }
103    if (!fAnimator->decodeDOM(dom, root)) {
104        delete fAnimator;
105        fAnimator = nullptr;
106        return false;
107    }
108    for (int i = 0; i <= 10; i++) {
109        SkString name("glyph");
110        name.appendS32(i);
111        const SkDOM::Node* node = find_nodeID(dom, nullptr, name.c_str());
112        SkASSERT(node);
113        SkRect r;
114        dom.findScalar(node, "left", &r.fLeft);
115        dom.findScalar(node, "top", &r.fTop);
116        dom.findScalar(node, "width", &r.fRight); r.fRight += r.fLeft;
117        dom.findScalar(node, "height", &r.fBottom); r.fBottom += r.fTop;
118        SkDebugf("--- %s [%g %g %g %g]\n", name.c_str(),
119                 r.fLeft, r.fTop, r.fRight, r.fBottom);
120    }
121#endif
122    return true;
123}
124
125#include "SkTime.h"
126
127void SkAnimatorView::onDraw(SkCanvas* canvas) {
128    canvas->drawColor(SK_ColorWHITE);
129    if (fAnimator) {
130        fAnimator->draw(canvas, 0);
131#if 0
132        canvas->save();
133        canvas->translate(120, 30);
134        canvas->scale(0.5, 0.5);
135        fAnimator->draw(canvas, 0);
136        canvas->restore();
137
138        canvas->save();
139        canvas->translate(190, 40);
140        canvas->scale(0.25, 0.25);
141        fAnimator->draw(canvas, 0);
142        canvas->restore();
143
144        this->inval(nullptr);
145#endif
146    }
147}
148
149bool SkAnimatorView::onQuery(SkEvent* evt) {
150    if (SampleCode::TitleQ(*evt)) {
151        SampleCode::TitleR(evt, "Animator");
152        return true;
153    }
154    return this->INHERITED::onQuery(evt);
155}
156
157//////////////////////////////////////////////////////////////////////////////
158
159static SkView* MyFactory() {
160    SkAnimatorView* av = new SkAnimatorView;
161//    av->decodeFile("/skimages/test.xml");
162#if 0
163    av->setURIBase("/skia/trunk/animations/");
164    av->decodeFile("/skia/trunk/animations/checkbox.xml");
165#else
166    av->setURIBase("/");
167    av->decodeFile("/testanim.txt");
168#endif
169    return av;
170}
171
172static SkViewRegister reg(MyFactory);
173