1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkAnimator_DEFINED
18#define SkAnimator_DEFINED
19
20#include "SkScalar.h"
21#include "SkKey.h"
22#include "SkEventSink.h"
23
24class SkAnimateMaker;
25class SkCanvas;
26class SkDisplayable;
27class SkEvent;
28class SkExtras;
29struct SkMemberInfo;
30class SkPaint;
31struct SkRect;
32class SkStream;
33class SkTypedArray;
34class SkXMLParserError;
35class SkDOM;
36struct SkDOMNode;
37
38/** SkElementType is the type of element: a rectangle, a color, an animator, and so on.
39    This enum is incomplete and will be fleshed out in a future release */
40enum SkElementType {
41    kElementDummyType
42};
43/** SkFieldType is the type of field: a scalar, a string, an integer, a boolean, and so on.
44    This enum is incomplete and will be fleshed out in a future release */
45enum SkFieldType {
46    kFieldDummyType
47};
48
49/** \class SkAnimator
50
51    The SkAnimator class decodes an XML stream into a display list. The
52    display list can be drawn statically as a picture, or can drawn
53    different elements at different times to form a moving animation.
54
55    SkAnimator does not read the system time on its own; it relies on the
56    caller to pass the current time. The caller can pause, speed up, or
57    reverse the animation by varying the time passed in.
58
59    The XML describing the display list must conform to the schema
60    described by SkAnimateSchema.xsd.
61
62    The XML must contain an <event> element to draw. Usually, it contains
63    an <event kind="onload" /> block to add some drawing elements to the
64    display list when the document is first decoded.
65
66    Here's an "Hello World" XML sample:
67
68    <screenplay>
69        <event kind="onload" >
70            <text text="Hello World" y="20" />
71        </event>
72    </screenplay>
73
74    To read and draw this sample:
75
76        // choose one of these two
77        SkAnimator animator; // declare an animator instance on the stack
78    //  SkAnimator* animator = new SkAnimator() // or one could instantiate the class
79
80        // choose one of these three
81        animator.decodeMemory(buffer, size); // to read from RAM
82        animator.decodeStream(stream); // to read from a user-defined stream (e.g., a zip file)
83        animator.decodeURI(filename); // to read from a web location, or from a local text file
84
85        // to draw to the current window:
86        SkCanvas canvas(getBitmap()); // create a canvas
87        animator.draw(canvas, &paint, 0); // draw the scene
88*/
89class SkAnimator : public SkEventSink {
90public:
91    SkAnimator();
92    virtual ~SkAnimator();
93
94    /** Add a drawable extension to the graphics engine. Experimental.
95        @param extras A derived class that implements methods that identify and instantiate the class
96    */
97    void addExtras(SkExtras* extras);
98
99    /** Read in XML from a stream, and append it to the current
100        animator. Returns false if an error was encountered.
101        Error diagnostics are stored in fErrorCode and fLineNumber.
102        @param stream  The stream to append.
103        @return true if the XML was parsed successfully.
104    */
105    bool appendStream(SkStream* stream);
106
107    /** Read in XML from memory. Returns true if the file can be
108        read without error. Returns false if an error was encountered.
109        Error diagnostics are stored in fErrorCode and fLineNumber.
110        @param buffer  The XML text as UTF-8 characters.
111        @param size  The XML text length in bytes.
112        @return true if the XML was parsed successfully.
113    */
114    bool decodeMemory(const void* buffer, size_t size);
115
116    /** Read in XML from a stream. Returns true if the file can be
117        read without error. Returns false if an error was encountered.
118        Error diagnostics are stored in fErrorCode and fLineNumber.
119        @param stream  The stream containg the XML text as UTF-8 characters.
120        @return true if the XML was parsed successfully.
121    */
122    virtual bool decodeStream(SkStream* stream);
123
124    /** Parse the DOM tree starting at the specified node. Returns true if it can be
125        parsed without error. Returns false if an error was encountered.
126        Error diagnostics are stored in fErrorCode and fLineNumber.
127        @return true if the DOM was parsed successfully.
128    */
129    virtual bool decodeDOM(const SkDOM&, const SkDOMNode*);
130
131    /** Read in XML from a URI. Returns true if the file can be
132        read without error. Returns false if an error was encountered.
133        Error diagnostics are stored in fErrorCode and fLineNumber.
134        @param uri The complete url path to be read (either ftp, http or https).
135        @return true if the XML was parsed successfully.
136    */
137    bool decodeURI(const char uri[]);
138
139    /** Pass a char event, usually a keyboard symbol, to the animator.
140        This triggers events of the form <event kind="keyChar" key="... />
141        @param ch  The character to match against <event> element "key"
142            attributes.
143        @return true if the event was dispatched successfully.
144    */
145    bool doCharEvent(SkUnichar ch);
146
147    /** Experimental:
148        Pass a mouse click event along with the mouse coordinates to
149        the animator. This triggers events of the form <event kind="mouseDown" ... />
150        and other mouse events.
151        @param state The mouse state, described by SkView::Click::State : values are
152        down == 0, moved == 1, up == 2
153        @param x    The x-position of the mouse
154        @param y The y-position of the mouse
155        @return true if the event was dispatched successfully.
156    */
157    bool doClickEvent(int state, SkScalar x, SkScalar y);
158
159    /** Pass a meta-key event, such as an arrow , to the animator.
160        This triggers events of the form <event kind="keyPress" code="... />
161        @param code  The key to match against <event> element "code"
162            attributes.
163        @return true if the event was dispatched successfully.
164    */
165    bool doKeyEvent(SkKey code);
166    bool doKeyUpEvent(SkKey code);
167
168    /** Send an event to the animator. The animator's clock is set
169        relative to the current time.
170        @return true if the event was dispatched successfully.
171    */
172    bool doUserEvent(const SkEvent& evt);
173
174    /** The possible results from the draw function.
175    */
176    enum DifferenceType {
177        kNotDifferent,
178        kDifferent,
179        kPartiallyDifferent
180    };
181    /** Draws one frame of the animation. The first call to draw always
182        draws the initial frame of the animation. Subsequent calls draw
183        the offset into the animation by
184        subtracting the initial time from the current time.
185        @param canvas  The canvas to draw into.
186        @param paint     The paint to draw with.
187        @param time  The offset into the current animation.
188        @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
189        kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal
190        redraw area.
191    */
192    DifferenceType draw(SkCanvas* canvas, SkPaint* paint, SkMSec time);
193
194    /** Draws one frame of the animation, using a new Paint each time.
195        The first call to draw always
196        draws the initial frame of the animation. Subsequent calls draw
197        the offset into the animation by
198        subtracting the initial time from the current time.
199        @param canvas  The canvas to draw into.
200        @param time  The offset into the current animation.
201        @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and
202        kPartiallyDifferent if the document contains an active <bounds> element that specifies a minimal
203        redraw area.
204    */
205    DifferenceType draw(SkCanvas* canvas, SkMSec time);
206
207    /** Experimental:
208        Helper to choose whether to return a SkView::Click handler.
209        @param x ignored
210        @param y ignored
211        @return true if a mouseDown event handler is enabled.
212    */
213    bool findClickEvent(SkScalar x, SkScalar y);
214
215
216    /** Get the nested animator associated with this element, if any.
217        Use this to access a movie's event sink, to send events to movies.
218        @param element the value returned by getElement
219        @return the internal animator.
220    */
221    const SkAnimator* getAnimator(const SkDisplayable* element) const;
222
223    /** Returns the scalar value of the specified element's attribute[index]
224        @param element the value returned by getElement
225        @param field the value returned by getField
226        @param index the array entry
227        @return the integer value to retrieve, or SK_NaN32 if unsuccessful
228    */
229    int32_t getArrayInt(const SkDisplayable* element, const SkMemberInfo* field, int index);
230
231    /** Returns the scalar value of the specified element's attribute[index]
232        @param elementID is the value of the id attribute in the XML of this element
233        @param fieldName specifies the name of the attribute
234        @param index the array entry
235        @return the integer value to retrieve, or SK_NaN32 if unsuccessful
236    */
237    int32_t getArrayInt(const char* elementID, const char* fieldName, int index);
238
239    /** Returns the scalar value of the specified element's attribute[index]
240        @param element the value returned by getElement
241        @param field the value returned by getField
242        @param index the array entry
243        @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
244    */
245    SkScalar getArrayScalar(const SkDisplayable* element, const SkMemberInfo* field, int index);
246
247    /** Returns the scalar value of the specified element's attribute[index]
248        @param elementID is the value of the id attribute in the XML of this element
249        @param fieldName specifies the name of the attribute
250        @param index the array entry
251        @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful
252    */
253    SkScalar getArrayScalar(const char* elementID, const char* fieldName, int index);
254
255    /** Returns the string value of the specified element's attribute[index]
256        @param element is a value returned by getElement
257        @param field is a value returned by getField
258        @param index the array entry
259        @return the string value to retrieve, or null if unsuccessful
260    */
261    const char* getArrayString(const SkDisplayable* element, const SkMemberInfo* field, int index);
262
263    /** Returns the string value of the specified element's attribute[index]
264        @param elementID is the value of the id attribute in the XML of this element
265        @param fieldName specifies the name of the attribute
266        @param index the array entry
267        @return the string value to retrieve, or null if unsuccessful
268    */
269    const char* getArrayString(const char* elementID, const char* fieldName, int index);
270
271    /** Returns the XML element corresponding to the given ID.
272        @param elementID is the value of the id attribute in the XML of this element
273        @return the element matching the ID, or null if the element can't be found
274    */
275    const SkDisplayable* getElement(const char* elementID);
276
277    /** Returns the element type corresponding to the XML element.
278        The element type matches the element name; for instance, <line> returns kElement_LineType
279        @param element is a value returned by getElement
280        @return element type, or 0 if the element can't be found
281    */
282    SkElementType getElementType(const SkDisplayable* element);
283
284    /** Returns the element type corresponding to the given ID.
285        @param elementID is the value of the id attribute in the XML of this element
286        @return element type, or 0 if the element can't be found
287    */
288    SkElementType getElementType(const char* elementID);
289
290    /** Returns the XML field of the named attribute in the XML element.
291        @param element is a value returned by getElement
292        @param fieldName is the attribute to return
293        @return the attribute matching the fieldName, or null if the element can't be found
294    */
295    const SkMemberInfo* getField(const SkDisplayable* element, const char* fieldName);
296
297    /** Returns the XML field of the named attribute in the XML element matching the elementID.
298        @param elementID is the value of the id attribute in the XML of this element
299        @param fieldName is the attribute to return
300        @return the attribute matching the fieldName, or null if the element can't be found
301    */
302    const SkMemberInfo* getField(const char* elementID, const char* fieldName);
303
304    /** Returns the value type coresponding to the element's attribute.
305        The value type matches the XML schema: and may be kField_BooleanType, kField_ScalarType, etc.
306        @param field is a value returned by getField
307        @return the attribute type, or 0 if the element can't be found
308    */
309    SkFieldType getFieldType(const SkMemberInfo* field);
310
311    /** Returns the value type coresponding to the element's attribute.
312        @param elementID is the value of the id attribute in the XML of this element
313        @param fieldName specifies the name of the attribute
314        @return the attribute type, or 0 if the element can't be found
315    */
316    SkFieldType getFieldType(const char* elementID, const char* fieldName);
317
318    /** Returns the recommended animation interval. Returns zero if no
319        interval is specified.
320    */
321    SkMSec getInterval();
322
323    /** Returns the partial rectangle to invalidate after drawing. Call after draw() returns
324    kIsPartiallyDifferent to do a mimimal inval(). */
325    void getInvalBounds(SkRect* inval);
326
327    /** Returns the details of any error encountered while parsing the XML.
328    */
329    const SkXMLParserError* getParserError();
330
331    /** Returns the details of any error encountered while parsing the XML as string.
332    */
333    const char* getParserErrorString();
334
335    /** Returns the scalar value of the specified element's attribute
336        @param element is a value returned by getElement
337        @param field is a value returned by getField
338        @return the integer value to retrieve, or SK_NaN32 if not found
339    */
340    int32_t getInt(const SkDisplayable* element, const SkMemberInfo* field);
341
342    /** Returns the scalar value of the specified element's attribute
343        @param elementID is the value of the id attribute in the XML of this element
344        @param fieldName specifies the name of the attribute
345        @return the integer value to retrieve, or SK_NaN32 if not found
346    */
347    int32_t getInt(const char* elementID, const char* fieldName);
348
349    /** Returns the scalar value of the specified element's attribute
350        @param element is a value returned by getElement
351        @param field is a value returned by getField
352        @return the scalar value to retrieve, or SK_ScalarNaN if not found
353    */
354    SkScalar getScalar(const SkDisplayable* element, const SkMemberInfo* field);
355
356    /** Returns the scalar value of the specified element's attribute
357        @param elementID is the value of the id attribute in the XML of this element
358        @param fieldName specifies the name of the attribute
359        @return the scalar value to retrieve, or SK_ScalarNaN if not found
360    */
361    SkScalar getScalar(const char* elementID, const char* fieldName);
362
363    /** Returns the string value of the specified element's attribute
364        @param element is a value returned by getElement
365        @param field is a value returned by getField
366        @return the string value to retrieve, or null if not found
367    */
368    const char* getString(const SkDisplayable* element, const SkMemberInfo* field);
369
370    /** Returns the string value of the specified element's attribute
371        @param elementID is the value of the id attribute in the XML of this element
372        @param fieldName specifies the name of the attribute
373        @return the string value to retrieve, or null if not found
374    */
375    const char* getString(const char* elementID, const char* fieldName);
376
377    /** Gets the file default directory of the URL base path set explicitly or by reading the last URL. */
378    const char* getURIBase();
379
380    /** Resets the animator to a newly created state with no animation data. */
381    void initialize();
382
383    /** Experimental. Resets any active animations so that the next time passed is treated as
384        time zero. */
385    void reset();
386
387    /** Sets the scalar value of the specified element's attribute
388        @param elementID is the value of the id attribute in the XML of this element
389        @param fieldName specifies the name of the attribute
390        @param array is the c-style array of integers
391        @param count is the length of the array
392        @return true if the value was set successfully
393    */
394    bool setArrayInt(const char* elementID, const char* fieldName, const int* array, int count);
395
396    /** Sets the scalar value of the specified element's attribute
397        @param elementID is the value of the id attribute in the XML of this element
398        @param fieldName specifies the name of the attribute
399        @param array is the c-style array of strings
400        @param count is the length of the array
401        @return true if the value was set successfully
402    */
403    bool setArrayString(const char* elementID, const char* fieldName, const char** array, int count);
404
405    /** Sets the scalar value of the specified element's attribute
406        @param elementID is the value of the id attribute in the XML of this element
407        @param fieldName specifies the name of the attribute
408        @param data the integer value to set
409        @return true if the value was set successfully
410    */
411    bool setInt(const char* elementID, const char* fieldName, int32_t data);
412
413    /** Sets the scalar value of the specified element's attribute
414        @param elementID is the value of the id attribute in the XML of this element
415        @param fieldName specifies the name of the attribute
416        @param data the scalar value to set
417        @return true if the value was set successfully
418    */
419    bool setScalar(const char* elementID, const char* fieldName, SkScalar data);
420
421    /** Sets the string value of the specified element's attribute
422        @param elementID is the value of the id attribute in the XML of this element
423        @param fieldName specifies the name of the attribute
424        @param data the string value to set
425        @return true if the value was set successfully
426    */
427    bool setString(const char* elementID, const char* fieldName, const char* data);
428
429    /** Sets the file default directory of the URL base path
430        @param path the directory path
431    */
432    void setURIBase(const char* path);
433
434    typedef void* Handler;
435    // This guy needs to be exported to java, so don't make it virtual
436    void setHostHandler(Handler handler) {
437        this->onSetHostHandler(handler);
438    }
439
440    /** \class Timeline
441    Returns current time to animator. To return a custom timeline, create a child
442    class and override the getMSecs method.
443    */
444    class Timeline {
445    public:
446        virtual ~Timeline() {}
447
448        /** Returns the current time in milliseconds */
449        virtual SkMSec getMSecs() const = 0;
450    };
451
452    /** Sets a user class to return the current time to the animator.
453        Optional; if not called, the system clock will be used by calling SkTime::GetMSecs instead.
454        @param callBack the time function
455    */
456    void setTimeline(const Timeline& );
457
458    static void Init(bool runUnitTests);
459    static void Term();
460
461    /** The event sink events generated by the animation are posted to.
462        Screenplay also posts an inval event to this event sink after processing an
463        event to force a redraw.
464        @param target the event sink id
465    */
466    void setHostEventSinkID(SkEventSinkID hostID);
467    SkEventSinkID getHostEventSinkID() const;
468
469    // helper
470    void setHostEventSink(SkEventSink* sink) {
471        this->setHostEventSinkID(sink ? sink->getSinkID() : 0);
472    }
473
474    virtual void setJavaOwner(Handler owner);
475
476#ifdef SK_DEBUG
477    virtual void eventDone(const SkEvent& evt);
478    virtual bool isTrackingEvents();
479    static bool NoLeaks();
480#endif
481
482protected:
483    virtual void onSetHostHandler(Handler handler);
484    virtual void onEventPost(SkEvent*, SkEventSinkID);
485    virtual void onEventPostTime(SkEvent*, SkEventSinkID, SkMSec time);
486
487private:
488// helper functions for setters
489    bool setArray(SkDisplayable* element, const SkMemberInfo* field, SkTypedArray array);
490    bool setArray(const char* elementID, const char* fieldName, SkTypedArray array);
491    bool setInt(SkDisplayable* element, const SkMemberInfo* field, int32_t data);
492    bool setScalar(SkDisplayable* element, const SkMemberInfo* field, SkScalar data);
493    bool setString(SkDisplayable* element, const SkMemberInfo* field, const char* data);
494
495    virtual bool onEvent(const SkEvent&);
496    SkAnimateMaker* fMaker;
497    friend class SkAnimateMaker;
498    friend class SkAnimatorScript;
499    friend class SkAnimatorScript2;
500    friend class SkApply;
501    friend class SkDisplayMovie;
502    friend class SkDisplayType;
503    friend class SkPost;
504    friend class SkXMLAnimatorWriter;
505};
506
507#endif
508
509