• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/animator/SkDisplayXMLParser.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkDisplayXMLParser.h"
19 #include "SkAnimateMaker.h"
20 #include "SkDisplayApply.h"
21 #include "SkUtils.h"
22 #ifdef SK_DEBUG
23 #include "SkTime.h"
24 #endif
25 
26 static char const* const gErrorStrings[] = {
27     "unknown error ",
28     "apply scopes itself",
29     "display tree too deep (circular reference?) ",
30     "element missing parent ",
31     "element type not allowed in parent ",
32     "error adding <data> to <post> ",
33     "error adding to <matrix> ",
34     "error adding to <paint> ",
35     "error adding to <path> ",
36     "error in attribute value ",
37     "error in script ",
38     "expected movie in sink attribute ",
39     "field not in target ",
40     "number of offsets in gradient must match number of colors",
41     "no offset in gradient may be greater than one",
42     "last offset in gradient must be one",
43     "offsets in gradient must be increasing",
44     "first offset in gradient must be zero",
45     "gradient attribute \"points\" must have length of four",
46     "in include ",
47     "in movie ",
48     "include name unknown or missing ",
49     "index out of range ",
50     "movie name unknown or missing ",
51     "no parent available to resolve sink attribute ",
52     "parent element can't contain ",
53     "saveLayer must specify a bounds",
54     "target id not found ",
55     "unexpected type "
56 };
57 
~SkDisplayXMLParserError()58 SkDisplayXMLParserError::~SkDisplayXMLParserError() {
59 }
60 
getErrorString(SkString * str) const61 void SkDisplayXMLParserError::getErrorString(SkString* str) const {
62     if (fCode > kUnknownError)
63         str->set(gErrorStrings[fCode - kUnknownError]);
64     else
65         str->reset();
66     INHERITED::getErrorString(str);
67 }
68 
setInnerError(SkAnimateMaker * parent,const SkString & src)69 void SkDisplayXMLParserError::setInnerError(SkAnimateMaker* parent, const SkString& src) {
70     SkString inner;
71     getErrorString(&inner);
72     inner.prepend(": ");
73     inner.prependS32(getLineNumber());
74     inner.prepend(", line ");
75     inner.prepend(src);
76     parent->setErrorNoun(inner);
77 }
78 
79 
SkDisplayXMLParser(SkAnimateMaker & maker)80 SkDisplayXMLParser::SkDisplayXMLParser(SkAnimateMaker& maker)
81     : INHERITED(&maker.fError), fMaker(maker), fInInclude(maker.fInInclude),
82         fInSkia(maker.fInInclude), fCurrDisplayable(NULL)
83 {
84 }
85 
~SkDisplayXMLParser()86 SkDisplayXMLParser::~SkDisplayXMLParser() {
87     if (fCurrDisplayable && fMaker.fChildren.find(fCurrDisplayable) < 0)
88         delete fCurrDisplayable;
89     for (Parent* parPtr = fParents.begin() + 1; parPtr < fParents.end(); parPtr++) {
90         SkDisplayable* displayable = parPtr->fDisplayable;
91         if (displayable == fCurrDisplayable)
92             continue;
93         SkASSERT(fMaker.fChildren.find(displayable) < 0);
94         if (fMaker.fHelpers.find(displayable) < 0)
95             delete displayable;
96     }
97 }
98 
99 
100 
onAddAttribute(const char name[],const char value[])101 bool SkDisplayXMLParser::onAddAttribute(const char name[], const char value[]) {
102     return onAddAttributeLen(name, value, strlen(value));
103 }
104 
onAddAttributeLen(const char attrName[],const char attrValue[],size_t attrValueLen)105 bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char attrValue[],
106                                         size_t attrValueLen)
107 {
108     if (fCurrDisplayable == NULL)    // this signals we should ignore attributes for this element
109         return strncmp(attrName, "xmlns", sizeof("xmlns") - 1) != 0;
110     SkDisplayable*  displayable = fCurrDisplayable;
111     SkDisplayTypes  type = fCurrType;
112 
113     if (strcmp(attrName, "id") == 0) {
114         if (fMaker.find(attrValue, attrValueLen, NULL)) {
115             fError->setNoun(attrValue, attrValueLen);
116             fError->setCode(SkXMLParserError::kDuplicateIDs);
117             return true;
118         }
119 #ifdef SK_DEBUG
120         displayable->_id.set(attrValue, attrValueLen);
121         displayable->id = displayable->_id.c_str();
122 #endif
123         fMaker.idsSet(attrValue, attrValueLen, displayable);
124         int parentIndex = fParents.count() - 1;
125         if (parentIndex > 0) {
126             SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable;
127             parent->setChildHasID();
128         }
129         return false;
130     }
131     const char* name = attrName;
132     const SkMemberInfo* info = SkDisplayType::GetMember(&fMaker, type, &name);
133     if (info == NULL) {
134         fError->setNoun(name);
135         fError->setCode(SkXMLParserError::kUnknownAttributeName);
136         return true;
137     }
138     if (info->setValue(fMaker, NULL, 0, info->getCount(), displayable, info->getType(), attrValue,
139             attrValueLen))
140         return false;
141     if (fMaker.fError.hasError()) {
142         fError->setNoun(attrValue, attrValueLen);
143         return true;
144     }
145     SkDisplayable* ref = NULL;
146     if (fMaker.find(attrValue, attrValueLen, &ref) == false) {
147         ref = fMaker.createInstance(attrValue, attrValueLen);
148         if (ref == NULL) {
149             fError->setNoun(attrValue, attrValueLen);
150             fError->setCode(SkXMLParserError::kErrorInAttributeValue);
151             return true;
152         } else
153             fMaker.helperAdd(ref);
154     }
155     if (info->fType != SkType_MemberProperty) {
156         fError->setNoun(name);
157         fError->setCode(SkXMLParserError::kUnknownAttributeName);
158         return true;
159     }
160     SkScriptValue scriptValue;
161     scriptValue.fOperand.fDisplayable = ref;
162     scriptValue.fType = ref->getType();
163     displayable->setProperty(info->propertyIndex(), scriptValue);
164     return false;
165 }
166 
167 #if defined(SK_BUILD_FOR_WIN32)
168     #define SK_strcasecmp   stricmp
169     #define SK_strncasecmp  strnicmp
170 #else
171     #define SK_strcasecmp   strcasecmp
172     #define SK_strncasecmp  strncasecmp
173 #endif
174 
onEndElement(const char elem[])175 bool SkDisplayXMLParser::onEndElement(const char elem[])
176 {
177     int parentIndex = fParents.count() - 1;
178     if (parentIndex >= 0) {
179         Parent& container = fParents[parentIndex];
180         SkDisplayable* displayable = container.fDisplayable;
181         fMaker.fEndDepth = parentIndex;
182         displayable->onEndElement(fMaker);
183         if (fMaker.fError.hasError())
184             return true;
185         if (parentIndex > 0) {
186             SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable;
187             bool result = parent->add(fMaker, displayable);
188             if (fMaker.hasError())
189                 return true;
190             if (result == false) {
191                 int infoCount;
192                 const SkMemberInfo* info =
193                     SkDisplayType::GetMembers(&fMaker, fParents[parentIndex - 1].fType, &infoCount);
194                 const SkMemberInfo* foundInfo;
195                 if ((foundInfo = searchContainer(info, infoCount)) != NULL) {
196                     parent->setReference(foundInfo, displayable);
197         //          if (displayable->isHelper() == false)
198                         fMaker.helperAdd(displayable);
199                 } else {
200                     fMaker.setErrorCode(SkDisplayXMLParserError::kElementTypeNotAllowedInParent);
201                     return true;
202                 }
203             }
204             if (parent->childrenNeedDisposing())
205                 delete displayable;
206         }
207         fParents.remove(parentIndex);
208     }
209     fCurrDisplayable = NULL;
210     if (fInInclude == false && SK_strcasecmp(elem, "screenplay") == 0) {
211         if (fMaker.fInMovie == false) {
212             fMaker.fEnableTime = fMaker.getAppTime();
213 #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
214             if (fMaker.fDebugTimeBase == (SkMSec) -1)
215                 fMaker.fDebugTimeBase = fMaker.fEnableTime;
216             SkString debugOut;
217             SkMSec time = fMaker.getAppTime();
218             debugOut.appendS32(time - fMaker.fDebugTimeBase);
219             debugOut.append(" onLoad enable=");
220             debugOut.appendS32(fMaker.fEnableTime - fMaker.fDebugTimeBase);
221             SkDebugf("%s\n", debugOut.c_str());
222 #endif
223             fMaker.fEvents.doEvent(fMaker, SkDisplayEvent::kOnload, NULL);
224             if (fMaker.fError.hasError())
225                 return true;
226             fMaker.fEvents.removeEvent(SkDisplayEvent::kOnload, NULL);
227 
228         }
229         fInSkia = false;
230     }
231     return false;
232 }
233 
onStartElement(const char name[])234 bool SkDisplayXMLParser::onStartElement(const char name[])
235 {
236     return onStartElementLen(name, strlen(name));
237 }
238 
onStartElementLen(const char name[],size_t len)239 bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) {
240     fCurrDisplayable = NULL; // init so we'll ignore attributes if we exit early
241 
242     if (SK_strncasecmp(name, "screenplay", len) == 0) {
243         fInSkia = true;
244         if (fInInclude == false)
245             fMaker.idsSet(name, len, &fMaker.fScreenplay);
246         return false;
247     }
248     if (fInSkia == false)
249         return false;
250 
251     SkDisplayable* displayable = fMaker.createInstance(name, len);
252     if (displayable == NULL) {
253         fError->setNoun(name, len);
254         fError->setCode(SkXMLParserError::kUnknownElement);
255         return true;
256     }
257     SkDisplayTypes type = displayable->getType();
258     Parent record = { displayable, type };
259     *fParents.append() = record;
260     if (fParents.count() == 1)
261         fMaker.childrenAdd(displayable);
262     else {
263         Parent* parent = fParents.end() - 2;
264         if (displayable->setParent(parent->fDisplayable)) {
265             fError->setNoun(name, len);
266             getError()->setCode(SkDisplayXMLParserError::kParentElementCantContain);
267             return true;
268         }
269     }
270 
271     // set these for subsequent calls to addAttribute()
272     fCurrDisplayable = displayable;
273     fCurrType = type;
274     return false;
275 }
276 
searchContainer(const SkMemberInfo * infoBase,int infoCount)277 const SkMemberInfo* SkDisplayXMLParser::searchContainer(const SkMemberInfo* infoBase,
278                                                          int infoCount) {
279     const SkMemberInfo* bestDisplayable = NULL;
280     const SkMemberInfo* lastResort = NULL;
281     for (int index = 0; index < infoCount; index++) {
282         const SkMemberInfo* info = &infoBase[index];
283         if (info->fType == SkType_BaseClassInfo) {
284             const SkMemberInfo* inherited = info->getInherited();
285             const SkMemberInfo* result = searchContainer(inherited, info->fCount);
286             if (result != NULL)
287                 return result;
288             continue;
289         }
290         Parent* container = fParents.end() - 1;
291         SkDisplayTypes type = (SkDisplayTypes) info->fType;
292         if (type == SkType_MemberProperty)
293             type = info->propertyType();
294         SkDisplayTypes containerType = container->fType;
295         if (type == containerType && (type == SkType_Rect || type == SkType_Polygon ||
296             type == SkType_Array || type == SkType_Int || type == SkType_Bitmap))
297             goto rectNext;
298         while (type != containerType) {
299             if (containerType == SkType_Displayable)
300                 goto next;
301             containerType = SkDisplayType::GetParent(&fMaker, containerType);
302             if (containerType == SkType_Unknown)
303                 goto next;
304         }
305         return info;
306 next:
307         if (type == SkType_Drawable || (type == SkType_Displayable &&
308             container->fDisplayable->isDrawable())) {
309 rectNext:
310             if (fParents.count() > 1) {
311                 Parent* parent = fParents.end() - 2;
312                 if (info == parent->fDisplayable->preferredChild(type))
313                     bestDisplayable = info;
314                 else
315                     lastResort = info;
316             }
317         }
318     }
319     if (bestDisplayable)
320         return bestDisplayable;
321     if (lastResort)
322         return lastResort;
323     return NULL;
324 }
325 
326 
327