michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkAnimator_DEFINED michael@0: #define SkAnimator_DEFINED michael@0: michael@0: #include "SkScalar.h" michael@0: #include "SkKey.h" michael@0: #include "SkEventSink.h" michael@0: michael@0: class SkAnimateMaker; michael@0: class SkCanvas; michael@0: class SkDisplayable; michael@0: class SkEvent; michael@0: class SkExtras; michael@0: struct SkMemberInfo; michael@0: class SkPaint; michael@0: struct SkRect; michael@0: class SkStream; michael@0: class SkTypedArray; michael@0: class SkXMLParserError; michael@0: class SkDOM; michael@0: struct SkDOMNode; michael@0: michael@0: /** SkElementType is the type of element: a rectangle, a color, an animator, and so on. michael@0: This enum is incomplete and will be fleshed out in a future release */ michael@0: enum SkElementType { michael@0: kElementDummyType michael@0: }; michael@0: /** SkFieldType is the type of field: a scalar, a string, an integer, a boolean, and so on. michael@0: This enum is incomplete and will be fleshed out in a future release */ michael@0: enum SkFieldType { michael@0: kFieldDummyType michael@0: }; michael@0: michael@0: /** \class SkAnimator michael@0: michael@0: The SkAnimator class decodes an XML stream into a display list. The michael@0: display list can be drawn statically as a picture, or can drawn michael@0: different elements at different times to form a moving animation. michael@0: michael@0: SkAnimator does not read the system time on its own; it relies on the michael@0: caller to pass the current time. The caller can pause, speed up, or michael@0: reverse the animation by varying the time passed in. michael@0: michael@0: The XML describing the display list must conform to the schema michael@0: described by SkAnimateSchema.xsd. michael@0: michael@0: The XML must contain an element to draw. Usually, it contains michael@0: an block to add some drawing elements to the michael@0: display list when the document is first decoded. michael@0: michael@0: Here's an "Hello World" XML sample: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: michael@0: To read and draw this sample: michael@0: michael@0: // choose one of these two michael@0: SkAnimator animator; // declare an animator instance on the stack michael@0: // SkAnimator* animator = new SkAnimator() // or one could instantiate the class michael@0: michael@0: // choose one of these three michael@0: animator.decodeMemory(buffer, size); // to read from RAM michael@0: animator.decodeStream(stream); // to read from a user-defined stream (e.g., a zip file) michael@0: animator.decodeURI(filename); // to read from a web location, or from a local text file michael@0: michael@0: // to draw to the current window: michael@0: SkCanvas canvas(getBitmap()); // create a canvas michael@0: animator.draw(canvas, &paint, 0); // draw the scene michael@0: */ michael@0: class SkAnimator : public SkEventSink { michael@0: public: michael@0: SkAnimator(); michael@0: virtual ~SkAnimator(); michael@0: michael@0: /** Add a drawable extension to the graphics engine. Experimental. michael@0: @param extras A derived class that implements methods that identify and instantiate the class michael@0: */ michael@0: void addExtras(SkExtras* extras); michael@0: michael@0: /** Read in XML from a stream, and append it to the current michael@0: animator. Returns false if an error was encountered. michael@0: Error diagnostics are stored in fErrorCode and fLineNumber. michael@0: @param stream The stream to append. michael@0: @return true if the XML was parsed successfully. michael@0: */ michael@0: bool appendStream(SkStream* stream); michael@0: michael@0: /** Read in XML from memory. Returns true if the file can be michael@0: read without error. Returns false if an error was encountered. michael@0: Error diagnostics are stored in fErrorCode and fLineNumber. michael@0: @param buffer The XML text as UTF-8 characters. michael@0: @param size The XML text length in bytes. michael@0: @return true if the XML was parsed successfully. michael@0: */ michael@0: bool decodeMemory(const void* buffer, size_t size); michael@0: michael@0: /** Read in XML from a stream. Returns true if the file can be michael@0: read without error. Returns false if an error was encountered. michael@0: Error diagnostics are stored in fErrorCode and fLineNumber. michael@0: @param stream The stream containg the XML text as UTF-8 characters. michael@0: @return true if the XML was parsed successfully. michael@0: */ michael@0: virtual bool decodeStream(SkStream* stream); michael@0: michael@0: /** Parse the DOM tree starting at the specified node. Returns true if it can be michael@0: parsed without error. Returns false if an error was encountered. michael@0: Error diagnostics are stored in fErrorCode and fLineNumber. michael@0: @return true if the DOM was parsed successfully. michael@0: */ michael@0: virtual bool decodeDOM(const SkDOM&, const SkDOMNode*); michael@0: michael@0: /** Read in XML from a URI. Returns true if the file can be michael@0: read without error. Returns false if an error was encountered. michael@0: Error diagnostics are stored in fErrorCode and fLineNumber. michael@0: @param uri The complete url path to be read (either ftp, http or https). michael@0: @return true if the XML was parsed successfully. michael@0: */ michael@0: bool decodeURI(const char uri[]); michael@0: michael@0: /** Pass a char event, usually a keyboard symbol, to the animator. michael@0: This triggers events of the form michael@0: and other mouse events. michael@0: @param state The mouse state, described by SkView::Click::State : values are michael@0: down == 0, moved == 1, up == 2 michael@0: @param x The x-position of the mouse michael@0: @param y The y-position of the mouse michael@0: @return true if the event was dispatched successfully. michael@0: */ michael@0: bool doClickEvent(int state, SkScalar x, SkScalar y); michael@0: michael@0: /** Pass a meta-key event, such as an arrow , to the animator. michael@0: This triggers events of the form element that specifies a minimal michael@0: redraw area. michael@0: */ michael@0: DifferenceType draw(SkCanvas* canvas, SkPaint* paint, SkMSec time); michael@0: michael@0: /** Draws one frame of the animation, using a new Paint each time. michael@0: The first call to draw always michael@0: draws the initial frame of the animation. Subsequent calls draw michael@0: the offset into the animation by michael@0: subtracting the initial time from the current time. michael@0: @param canvas The canvas to draw into. michael@0: @param time The offset into the current animation. michael@0: @return kNotDifferent if there are no active animations; kDifferent if there are active animations; and michael@0: kPartiallyDifferent if the document contains an active element that specifies a minimal michael@0: redraw area. michael@0: */ michael@0: DifferenceType draw(SkCanvas* canvas, SkMSec time); michael@0: michael@0: /** Experimental: michael@0: Helper to choose whether to return a SkView::Click handler. michael@0: @param x ignored michael@0: @param y ignored michael@0: @return true if a mouseDown event handler is enabled. michael@0: */ michael@0: bool findClickEvent(SkScalar x, SkScalar y); michael@0: michael@0: michael@0: /** Get the nested animator associated with this element, if any. michael@0: Use this to access a movie's event sink, to send events to movies. michael@0: @param element the value returned by getElement michael@0: @return the internal animator. michael@0: */ michael@0: const SkAnimator* getAnimator(const SkDisplayable* element) const; michael@0: michael@0: /** Returns the scalar value of the specified element's attribute[index] michael@0: @param element the value returned by getElement michael@0: @param field the value returned by getField michael@0: @param index the array entry michael@0: @return the integer value to retrieve, or SK_NaN32 if unsuccessful michael@0: */ michael@0: int32_t getArrayInt(const SkDisplayable* element, const SkMemberInfo* field, int index); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute[index] michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param index the array entry michael@0: @return the integer value to retrieve, or SK_NaN32 if unsuccessful michael@0: */ michael@0: int32_t getArrayInt(const char* elementID, const char* fieldName, int index); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute[index] michael@0: @param element the value returned by getElement michael@0: @param field the value returned by getField michael@0: @param index the array entry michael@0: @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful michael@0: */ michael@0: SkScalar getArrayScalar(const SkDisplayable* element, const SkMemberInfo* field, int index); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute[index] michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param index the array entry michael@0: @return the scalar value to retrieve, or SK_ScalarNaN if unsuccessful michael@0: */ michael@0: SkScalar getArrayScalar(const char* elementID, const char* fieldName, int index); michael@0: michael@0: /** Returns the string value of the specified element's attribute[index] michael@0: @param element is a value returned by getElement michael@0: @param field is a value returned by getField michael@0: @param index the array entry michael@0: @return the string value to retrieve, or null if unsuccessful michael@0: */ michael@0: const char* getArrayString(const SkDisplayable* element, const SkMemberInfo* field, int index); michael@0: michael@0: /** Returns the string value of the specified element's attribute[index] michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param index the array entry michael@0: @return the string value to retrieve, or null if unsuccessful michael@0: */ michael@0: const char* getArrayString(const char* elementID, const char* fieldName, int index); michael@0: michael@0: /** Returns the XML element corresponding to the given ID. michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @return the element matching the ID, or null if the element can't be found michael@0: */ michael@0: const SkDisplayable* getElement(const char* elementID); michael@0: michael@0: /** Returns the element type corresponding to the XML element. michael@0: The element type matches the element name; for instance, returns kElement_LineType michael@0: @param element is a value returned by getElement michael@0: @return element type, or 0 if the element can't be found michael@0: */ michael@0: SkElementType getElementType(const SkDisplayable* element); michael@0: michael@0: /** Returns the element type corresponding to the given ID. michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @return element type, or 0 if the element can't be found michael@0: */ michael@0: SkElementType getElementType(const char* elementID); michael@0: michael@0: /** Returns the XML field of the named attribute in the XML element. michael@0: @param element is a value returned by getElement michael@0: @param fieldName is the attribute to return michael@0: @return the attribute matching the fieldName, or null if the element can't be found michael@0: */ michael@0: const SkMemberInfo* getField(const SkDisplayable* element, const char* fieldName); michael@0: michael@0: /** Returns the XML field of the named attribute in the XML element matching the elementID. michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName is the attribute to return michael@0: @return the attribute matching the fieldName, or null if the element can't be found michael@0: */ michael@0: const SkMemberInfo* getField(const char* elementID, const char* fieldName); michael@0: michael@0: /** Returns the value type coresponding to the element's attribute. michael@0: The value type matches the XML schema: and may be kField_BooleanType, kField_ScalarType, etc. michael@0: @param field is a value returned by getField michael@0: @return the attribute type, or 0 if the element can't be found michael@0: */ michael@0: SkFieldType getFieldType(const SkMemberInfo* field); michael@0: michael@0: /** Returns the value type coresponding to the element's attribute. michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @return the attribute type, or 0 if the element can't be found michael@0: */ michael@0: SkFieldType getFieldType(const char* elementID, const char* fieldName); michael@0: michael@0: /** Returns the recommended animation interval. Returns zero if no michael@0: interval is specified. michael@0: */ michael@0: SkMSec getInterval(); michael@0: michael@0: /** Returns the partial rectangle to invalidate after drawing. Call after draw() returns michael@0: kIsPartiallyDifferent to do a mimimal inval(). */ michael@0: void getInvalBounds(SkRect* inval); michael@0: michael@0: /** Returns the details of any error encountered while parsing the XML. michael@0: */ michael@0: const SkXMLParserError* getParserError(); michael@0: michael@0: /** Returns the details of any error encountered while parsing the XML as string. michael@0: */ michael@0: const char* getParserErrorString(); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute michael@0: @param element is a value returned by getElement michael@0: @param field is a value returned by getField michael@0: @return the integer value to retrieve, or SK_NaN32 if not found michael@0: */ michael@0: int32_t getInt(const SkDisplayable* element, const SkMemberInfo* field); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @return the integer value to retrieve, or SK_NaN32 if not found michael@0: */ michael@0: int32_t getInt(const char* elementID, const char* fieldName); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute michael@0: @param element is a value returned by getElement michael@0: @param field is a value returned by getField michael@0: @return the scalar value to retrieve, or SK_ScalarNaN if not found michael@0: */ michael@0: SkScalar getScalar(const SkDisplayable* element, const SkMemberInfo* field); michael@0: michael@0: /** Returns the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @return the scalar value to retrieve, or SK_ScalarNaN if not found michael@0: */ michael@0: SkScalar getScalar(const char* elementID, const char* fieldName); michael@0: michael@0: /** Returns the string value of the specified element's attribute michael@0: @param element is a value returned by getElement michael@0: @param field is a value returned by getField michael@0: @return the string value to retrieve, or null if not found michael@0: */ michael@0: const char* getString(const SkDisplayable* element, const SkMemberInfo* field); michael@0: michael@0: /** Returns the string value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @return the string value to retrieve, or null if not found michael@0: */ michael@0: const char* getString(const char* elementID, const char* fieldName); michael@0: michael@0: /** Gets the file default directory of the URL base path set explicitly or by reading the last URL. */ michael@0: const char* getURIBase(); michael@0: michael@0: /** Resets the animator to a newly created state with no animation data. */ michael@0: void initialize(); michael@0: michael@0: /** Experimental. Resets any active animations so that the next time passed is treated as michael@0: time zero. */ michael@0: void reset(); michael@0: michael@0: /** Sets the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param array is the c-style array of integers michael@0: @param count is the length of the array michael@0: @return true if the value was set successfully michael@0: */ michael@0: bool setArrayInt(const char* elementID, const char* fieldName, const int* array, int count); michael@0: michael@0: /** Sets the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param array is the c-style array of strings michael@0: @param count is the length of the array michael@0: @return true if the value was set successfully michael@0: */ michael@0: bool setArrayString(const char* elementID, const char* fieldName, const char** array, int count); michael@0: michael@0: /** Sets the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param data the integer value to set michael@0: @return true if the value was set successfully michael@0: */ michael@0: bool setInt(const char* elementID, const char* fieldName, int32_t data); michael@0: michael@0: /** Sets the scalar value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param data the scalar value to set michael@0: @return true if the value was set successfully michael@0: */ michael@0: bool setScalar(const char* elementID, const char* fieldName, SkScalar data); michael@0: michael@0: /** Sets the string value of the specified element's attribute michael@0: @param elementID is the value of the id attribute in the XML of this element michael@0: @param fieldName specifies the name of the attribute michael@0: @param data the string value to set michael@0: @return true if the value was set successfully michael@0: */ michael@0: bool setString(const char* elementID, const char* fieldName, const char* data); michael@0: michael@0: /** Sets the file default directory of the URL base path michael@0: @param path the directory path michael@0: */ michael@0: void setURIBase(const char* path); michael@0: michael@0: typedef void* Handler; michael@0: // This guy needs to be exported to java, so don't make it virtual michael@0: void setHostHandler(Handler handler) { michael@0: this->onSetHostHandler(handler); michael@0: } michael@0: michael@0: /** \class Timeline michael@0: Returns current time to animator. To return a custom timeline, create a child michael@0: class and override the getMSecs method. michael@0: */ michael@0: class Timeline { michael@0: public: michael@0: virtual ~Timeline() {} michael@0: michael@0: /** Returns the current time in milliseconds */ michael@0: virtual SkMSec getMSecs() const = 0; michael@0: }; michael@0: michael@0: /** Sets a user class to return the current time to the animator. michael@0: Optional; if not called, the system clock will be used by calling SkTime::GetMSecs instead. michael@0: @param callBack the time function michael@0: */ michael@0: void setTimeline(const Timeline& ); michael@0: michael@0: static void Init(bool runUnitTests); michael@0: static void Term(); michael@0: michael@0: /** The event sink events generated by the animation are posted to. michael@0: Screenplay also posts an inval event to this event sink after processing an michael@0: event to force a redraw. michael@0: @param target the event sink id michael@0: */ michael@0: void setHostEventSinkID(SkEventSinkID hostID); michael@0: SkEventSinkID getHostEventSinkID() const; michael@0: michael@0: // helper michael@0: void setHostEventSink(SkEventSink* sink) { michael@0: this->setHostEventSinkID(sink ? sink->getSinkID() : 0); michael@0: } michael@0: michael@0: virtual void setJavaOwner(Handler owner); michael@0: michael@0: #ifdef SK_DEBUG michael@0: virtual void eventDone(const SkEvent& evt); michael@0: virtual bool isTrackingEvents(); michael@0: static bool NoLeaks(); michael@0: #endif michael@0: michael@0: protected: michael@0: virtual void onSetHostHandler(Handler handler); michael@0: virtual void onEventPost(SkEvent*, SkEventSinkID); michael@0: virtual void onEventPostTime(SkEvent*, SkEventSinkID, SkMSec time); michael@0: michael@0: private: michael@0: // helper functions for setters michael@0: bool setArray(SkDisplayable* element, const SkMemberInfo* field, SkTypedArray array); michael@0: bool setArray(const char* elementID, const char* fieldName, SkTypedArray array); michael@0: bool setInt(SkDisplayable* element, const SkMemberInfo* field, int32_t data); michael@0: bool setScalar(SkDisplayable* element, const SkMemberInfo* field, SkScalar data); michael@0: bool setString(SkDisplayable* element, const SkMemberInfo* field, const char* data); michael@0: michael@0: virtual bool onEvent(const SkEvent&); michael@0: SkAnimateMaker* fMaker; michael@0: friend class SkAnimateMaker; michael@0: friend class SkAnimatorScript; michael@0: friend class SkAnimatorScript2; michael@0: friend class SkApply; michael@0: friend class SkDisplayMovie; michael@0: friend class SkDisplayType; michael@0: friend class SkPost; michael@0: friend class SkXMLAnimatorWriter; michael@0: }; michael@0: michael@0: #endif