|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
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 |
|
9 |
|
10 #include "SkDisplayable.h" |
|
11 #include "SkDisplayApply.h" |
|
12 #include "SkParse.h" |
|
13 #ifdef SK_DEBUG |
|
14 #include "SkDisplayList.h" |
|
15 #endif |
|
16 #include "SkDisplayTypes.h" |
|
17 |
|
18 #ifdef SK_FIND_LEAKS |
|
19 // int SkDisplayable::fAllocationCount; |
|
20 SkTDDisplayableArray SkDisplayable::fAllocations; |
|
21 #endif |
|
22 |
|
23 #ifdef SK_DEBUG |
|
24 SkDisplayable::SkDisplayable() { |
|
25 id = _id.c_str(); |
|
26 #ifdef SK_FIND_LEAKS |
|
27 // fAllocationCount++; |
|
28 *fAllocations.append() = this; |
|
29 #endif |
|
30 } |
|
31 #endif |
|
32 |
|
33 SkDisplayable::~SkDisplayable() { |
|
34 #ifdef SK_FIND_LEAKS |
|
35 // fAllocationCount--; |
|
36 int index = fAllocations.find(this); |
|
37 SkASSERT(index >= 0); |
|
38 fAllocations.remove(index); |
|
39 #endif |
|
40 } |
|
41 |
|
42 bool SkDisplayable::addChild(SkAnimateMaker& , SkDisplayable* child) { |
|
43 return false; |
|
44 } |
|
45 |
|
46 //void SkDisplayable::apply(SkAnimateMaker& , const SkMemberInfo* , |
|
47 // SkDisplayable* , SkScalar [], int count) { |
|
48 // SkASSERT(0); |
|
49 //} |
|
50 |
|
51 bool SkDisplayable::canContainDependents() const { |
|
52 return false; |
|
53 } |
|
54 |
|
55 bool SkDisplayable::childrenNeedDisposing() const { |
|
56 return false; |
|
57 } |
|
58 |
|
59 void SkDisplayable::clearBounder() { |
|
60 } |
|
61 |
|
62 bool SkDisplayable::contains(SkDisplayable* ) { |
|
63 return false; |
|
64 } |
|
65 |
|
66 SkDisplayable* SkDisplayable::contains(const SkString& ) { |
|
67 return NULL; |
|
68 } |
|
69 |
|
70 SkDisplayable* SkDisplayable::deepCopy(SkAnimateMaker* maker) { |
|
71 SkDisplayTypes type = getType(); |
|
72 if (type == SkType_Unknown) { |
|
73 SkASSERT(0); |
|
74 return NULL; |
|
75 } |
|
76 SkDisplayable* copy = SkDisplayType::CreateInstance(maker, type); |
|
77 int index = -1; |
|
78 int propIndex = 0; |
|
79 const SkMemberInfo* info; |
|
80 do { |
|
81 info = copy->getMember(++index); |
|
82 if (info == NULL) |
|
83 break; |
|
84 if (info->fType == SkType_MemberProperty) { |
|
85 SkScriptValue value; |
|
86 if (getProperty(propIndex, &value)) |
|
87 copy->setProperty(propIndex, value); |
|
88 propIndex++; |
|
89 continue; |
|
90 } |
|
91 if (info->fType == SkType_MemberFunction) |
|
92 continue; |
|
93 if (info->fType == SkType_Array) { |
|
94 SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); |
|
95 int arrayCount; |
|
96 if (array == NULL || (arrayCount = array->count()) == 0) |
|
97 continue; |
|
98 SkTDOperandArray* copyArray = (SkTDOperandArray*) info->memberData(copy); |
|
99 copyArray->setCount(arrayCount); |
|
100 SkDisplayTypes elementType; |
|
101 if (type == SkType_Array) { |
|
102 SkDisplayArray* dispArray = (SkDisplayArray*) this; |
|
103 elementType = dispArray->values.getType(); |
|
104 } else |
|
105 elementType = info->arrayType(); |
|
106 size_t elementSize = SkMemberInfo::GetSize(elementType); |
|
107 size_t byteSize = elementSize * arrayCount; |
|
108 memcpy(copyArray->begin(), array->begin(), byteSize); |
|
109 continue; |
|
110 } |
|
111 if (SkDisplayType::IsDisplayable(maker, info->fType)) { |
|
112 SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); |
|
113 if (*displayable == NULL || *displayable == (SkDisplayable*) -1) |
|
114 continue; |
|
115 SkDisplayable* deeper = (*displayable)->deepCopy(maker); |
|
116 info->setMemberData(copy, deeper, sizeof(deeper)); |
|
117 continue; |
|
118 } |
|
119 if (info->fType == SkType_String || info->fType == SkType_DynamicString) { |
|
120 SkString* string; |
|
121 info->getString(this, &string); |
|
122 info->setString(copy, string); |
|
123 continue; |
|
124 } |
|
125 void* data = info->memberData(this); |
|
126 size_t size = SkMemberInfo::GetSize(info->fType); |
|
127 info->setMemberData(copy, data, size); |
|
128 } while (true); |
|
129 copy->dirty(); |
|
130 return copy; |
|
131 } |
|
132 |
|
133 void SkDisplayable::dirty() { |
|
134 } |
|
135 |
|
136 #ifdef SK_DUMP_ENABLED |
|
137 void SkDisplayable::dump(SkAnimateMaker* maker) { |
|
138 dumpBase(maker); |
|
139 #if SK_USE_CONDENSED_INFO == 0 |
|
140 this->dumpAttrs(maker); |
|
141 this->dumpChildren(maker); |
|
142 #endif |
|
143 } |
|
144 |
|
145 void SkDisplayable::dumpAttrs(SkAnimateMaker* maker) { |
|
146 SkDisplayTypes type = getType(); |
|
147 if (type == SkType_Unknown) { |
|
148 //SkDebugf("/>\n"); |
|
149 return; |
|
150 } |
|
151 SkDisplayable* blankCopy = SkDisplayType::CreateInstance(maker, type); |
|
152 |
|
153 int index = -1; |
|
154 int propIndex = 0; |
|
155 const SkMemberInfo* info; |
|
156 const SkMemberInfo* blankInfo; |
|
157 SkScriptValue value; |
|
158 SkScriptValue blankValue; |
|
159 SkOperand values[2]; |
|
160 SkOperand blankValues[2]; |
|
161 do { |
|
162 info = this->getMember(++index); |
|
163 if (NULL == info) { |
|
164 //SkDebugf("\n"); |
|
165 break; |
|
166 } |
|
167 if (SkType_MemberProperty == info->fType) { |
|
168 if (getProperty(propIndex, &value)) { |
|
169 blankCopy->getProperty(propIndex, &blankValue); |
|
170 //last two are dummies |
|
171 dumpValues(info, value.fType, value.fOperand, blankValue.fOperand, value.fOperand, blankValue.fOperand); |
|
172 } |
|
173 |
|
174 propIndex++; |
|
175 continue; |
|
176 } |
|
177 if (SkDisplayType::IsDisplayable(maker, info->fType)) { |
|
178 continue; |
|
179 } |
|
180 |
|
181 if (info->fType == SkType_MemberFunction) |
|
182 continue; |
|
183 |
|
184 |
|
185 if (info->fType == SkType_Array) { |
|
186 SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); |
|
187 int arrayCount; |
|
188 if (array == NULL || (arrayCount = array->count()) == 0) |
|
189 continue; |
|
190 SkDisplayTypes elementType; |
|
191 if (type == SkType_Array) { |
|
192 SkDisplayArray* dispArray = (SkDisplayArray*) this; |
|
193 elementType = dispArray->values.getType(); |
|
194 } else |
|
195 elementType = info->arrayType(); |
|
196 bool firstElem = true; |
|
197 SkDebugf("%s=\"[", info->fName); |
|
198 for (SkOperand* op = array->begin(); op < array->end(); op++) { |
|
199 if (!firstElem) SkDebugf(","); |
|
200 switch (elementType) { |
|
201 case SkType_Displayable: |
|
202 SkDebugf("%s", op->fDisplayable->id); |
|
203 break; |
|
204 case SkType_Int: |
|
205 SkDebugf("%d", op->fS32); |
|
206 break; |
|
207 case SkType_Float: |
|
208 SkDebugf("%g", SkScalarToFloat(op->fScalar)); |
|
209 break; |
|
210 case SkType_String: |
|
211 case SkType_DynamicString: |
|
212 SkDebugf("%s", op->fString->c_str()); |
|
213 break; |
|
214 default: |
|
215 break; |
|
216 } |
|
217 firstElem = false; |
|
218 } |
|
219 SkDebugf("]\" "); |
|
220 continue; |
|
221 } |
|
222 |
|
223 if (info->fType == SkType_String || info->fType == SkType_DynamicString) { |
|
224 SkString* string; |
|
225 info->getString(this, &string); |
|
226 if (string->isEmpty() == false) |
|
227 SkDebugf("%s=\"%s\"\t", info->fName, string->c_str()); |
|
228 continue; |
|
229 } |
|
230 |
|
231 |
|
232 blankInfo = blankCopy->getMember(index); |
|
233 int i = info->fCount; |
|
234 info->getValue(this, values, i); |
|
235 blankInfo->getValue(blankCopy, blankValues, i); |
|
236 dumpValues(info, info->fType, values[0], blankValues[0], values[1], blankValues[1]); |
|
237 } while (true); |
|
238 delete blankCopy; |
|
239 } |
|
240 |
|
241 void SkDisplayable::dumpBase(SkAnimateMaker* maker) { |
|
242 SkDisplayTypes type = getType(); |
|
243 const char* elementName = "(unknown)"; |
|
244 if (type != SkType_Unknown && type != SkType_Screenplay) |
|
245 elementName = SkDisplayType::GetName(maker, type); |
|
246 SkDebugf("%*s", SkDisplayList::fIndent, ""); |
|
247 if (SkDisplayList::fDumpIndex != 0 && SkDisplayList::fIndent == 0) |
|
248 SkDebugf("%d: ", SkDisplayList::fDumpIndex); |
|
249 SkDebugf("<%s ", elementName); |
|
250 if (strcmp(id,"") != 0) |
|
251 SkDebugf("id=\"%s\" ", id); |
|
252 } |
|
253 |
|
254 void SkDisplayable::dumpChildren(SkAnimateMaker* maker, bool closedAngle) { |
|
255 |
|
256 int index = -1; |
|
257 const SkMemberInfo* info; |
|
258 index = -1; |
|
259 SkDisplayList::fIndent += 4; |
|
260 do { |
|
261 info = this->getMember(++index); |
|
262 if (NULL == info) { |
|
263 break; |
|
264 } |
|
265 if (SkDisplayType::IsDisplayable(maker, info->fType)) { |
|
266 SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); |
|
267 if (*displayable == NULL || *displayable == (SkDisplayable*) -1) |
|
268 continue; |
|
269 if (closedAngle == false) { |
|
270 SkDebugf(">\n"); |
|
271 closedAngle = true; |
|
272 } |
|
273 (*displayable)->dump(maker); |
|
274 } |
|
275 } while (true); |
|
276 SkDisplayList::fIndent -= 4; |
|
277 if (closedAngle) |
|
278 dumpEnd(maker); |
|
279 else |
|
280 SkDebugf("/>\n"); |
|
281 } |
|
282 |
|
283 void SkDisplayable::dumpEnd(SkAnimateMaker* maker) { |
|
284 SkDisplayTypes type = getType(); |
|
285 const char* elementName = "(unknown)"; |
|
286 if (type != SkType_Unknown && type != SkType_Screenplay) |
|
287 elementName = SkDisplayType::GetName(maker, type); |
|
288 SkDebugf("%*s", SkDisplayList::fIndent, ""); |
|
289 SkDebugf("</%s>\n", elementName); |
|
290 } |
|
291 |
|
292 void SkDisplayable::dumpEvents() { |
|
293 } |
|
294 |
|
295 void SkDisplayable::dumpValues(const SkMemberInfo* info, SkDisplayTypes type, SkOperand op, SkOperand blankOp, |
|
296 SkOperand op2, SkOperand blankOp2) { |
|
297 switch (type) { |
|
298 case SkType_BitmapEncoding: |
|
299 switch (op.fS32) { |
|
300 case 0 : SkDebugf("type=\"jpeg\" "); |
|
301 break; |
|
302 case 1 : SkDebugf("type=\"png\" "); |
|
303 break; |
|
304 default: SkDebugf("type=\"UNDEFINED\" "); |
|
305 } |
|
306 break; |
|
307 //should make this a separate case in dump attrs, rather than make dump values have a larger signature |
|
308 case SkType_Point: |
|
309 if (op.fScalar != blankOp.fScalar || op2.fScalar != blankOp.fScalar) { |
|
310 SkDebugf("%s=\"[%g,%g]\" ", info->fName, SkScalarToFloat(op.fScalar), SkScalarToFloat(op2.fScalar)); |
|
311 } |
|
312 break; |
|
313 case SkType_FromPathMode: |
|
314 switch (op.fS32) { |
|
315 case 0: |
|
316 //don't want to print anything for 0, just adding it to remove it from default: |
|
317 break; |
|
318 case 1: |
|
319 SkDebugf("%s=\"%s\" ", info->fName, "angle"); |
|
320 break; |
|
321 case 2: |
|
322 SkDebugf("%s=\"%s\" ", info->fName, "position"); |
|
323 break; |
|
324 default: |
|
325 SkDebugf("%s=\"INVALID\" ", info->fName); |
|
326 } |
|
327 break; |
|
328 case SkType_MaskFilterBlurStyle: |
|
329 switch (op.fS32) { |
|
330 case 0: |
|
331 break; |
|
332 case 1: |
|
333 SkDebugf("%s=\"%s\" ", info->fName, "solid"); |
|
334 break; |
|
335 case 2: |
|
336 SkDebugf("%s=\"%s\" ", info->fName, "outer"); |
|
337 break; |
|
338 case 3: |
|
339 SkDebugf("%s=\"%s\" ", info->fName, "inner"); |
|
340 break; |
|
341 default: |
|
342 SkDebugf("%s=\"INVALID\" ", info->fName); |
|
343 } |
|
344 break; |
|
345 case SkType_FilterType: |
|
346 if (op.fS32 == 1) |
|
347 SkDebugf("%s=\"%s\" ", info->fName, "bilinear"); |
|
348 break; |
|
349 case SkType_PathDirection: |
|
350 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "cw" : "ccw"); |
|
351 break; |
|
352 case SkType_FillType: |
|
353 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "winding" : "evenOdd"); |
|
354 break; |
|
355 case SkType_TileMode: |
|
356 //correct to look at the S32? |
|
357 if (op.fS32 != blankOp.fS32) |
|
358 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "clamp" : op.fS32 == 1 ? "repeat" : "mirror"); |
|
359 break; |
|
360 case SkType_Boolean: |
|
361 if (op.fS32 != blankOp.fS32) |
|
362 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "false" : "true"); |
|
363 break; |
|
364 case SkType_Int: |
|
365 if (op.fS32 != blankOp.fS32) |
|
366 SkDebugf(" %s=\"%d\" ", info->fName, op.fS32); |
|
367 break; |
|
368 case SkType_Float: |
|
369 if (op.fScalar != blankOp.fScalar) { //or /65536? |
|
370 SkDebugf("%s=\"%g\" ", info->fName, SkScalarToFloat(op.fScalar)); |
|
371 } |
|
372 break; |
|
373 case SkType_String: |
|
374 case SkType_DynamicString: |
|
375 if (op.fString->size() > 0) |
|
376 SkDebugf("%s=\"%s\" ", info->fName, op.fString->c_str()); |
|
377 break; |
|
378 case SkType_MSec: |
|
379 if (op.fS32 != blankOp.fS32) { |
|
380 SkDebugf(" %s=\"%g\" ", info->fName, SkScalarToFloat(SkScalarDiv(op.fS32, 1000))); |
|
381 } |
|
382 default: |
|
383 SkDebugf(""); |
|
384 } |
|
385 } |
|
386 |
|
387 #endif |
|
388 |
|
389 bool SkDisplayable::enable( SkAnimateMaker& ) { |
|
390 return false; |
|
391 } |
|
392 |
|
393 void SkDisplayable::enableBounder() { |
|
394 } |
|
395 |
|
396 void SkDisplayable::executeFunction(SkDisplayable* , int index, |
|
397 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) { |
|
398 SkASSERT(0); |
|
399 } |
|
400 |
|
401 void SkDisplayable::executeFunction(SkDisplayable* target, |
|
402 const SkMemberInfo* info, SkTypedArray* values, SkScriptValue* value) { |
|
403 SkTDArray<SkScriptValue> typedValues; |
|
404 for (SkOperand* op = values->begin(); op < values->end(); op++) { |
|
405 SkScriptValue temp; |
|
406 temp.fType = values->getType(); |
|
407 temp.fOperand = *op; |
|
408 *typedValues.append() = temp; |
|
409 } |
|
410 executeFunction(target, info->functionIndex(), typedValues, info->getType(), value); |
|
411 } |
|
412 |
|
413 void SkDisplayable::executeFunction2(SkDisplayable* , int index, |
|
414 SkOpArray* params, SkDisplayTypes, SkOperand2* ) { |
|
415 SkASSERT(0); |
|
416 } |
|
417 |
|
418 void SkDisplayable::getBounds(SkRect* rect) { |
|
419 SkASSERT(rect); |
|
420 rect->fLeft = rect->fTop = SK_ScalarMax; |
|
421 rect->fRight= rect->fBottom = -SK_ScalarMax; |
|
422 } |
|
423 |
|
424 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() { |
|
425 return NULL; |
|
426 } |
|
427 |
|
428 const SkMemberInfo* SkDisplayable::getMember(int index) { |
|
429 return NULL; |
|
430 } |
|
431 |
|
432 const SkMemberInfo* SkDisplayable::getMember(const char name[]) { |
|
433 return NULL; |
|
434 } |
|
435 |
|
436 const SkFunctionParamType* SkDisplayable::getParameters(const SkMemberInfo* info, |
|
437 int* paramCount) { |
|
438 const SkFunctionParamType* params = getFunctionsParameters(); |
|
439 SkASSERT(params != NULL); |
|
440 int funcIndex = info->functionIndex(); |
|
441 // !!! eventually break traversing params into an external function (maybe this whole function) |
|
442 int index = funcIndex; |
|
443 int offset = 0; |
|
444 while (--index >= 0) { |
|
445 while (params[offset] != 0) |
|
446 offset++; |
|
447 offset++; |
|
448 } |
|
449 int count = 0; |
|
450 while (params[offset] != 0) { |
|
451 count++; |
|
452 offset++; |
|
453 } |
|
454 *paramCount = count; |
|
455 return ¶ms[offset - count]; |
|
456 } |
|
457 |
|
458 SkDisplayable* SkDisplayable::getParent() const { |
|
459 return NULL; |
|
460 } |
|
461 |
|
462 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const { |
|
463 // SkASSERT(0); |
|
464 return false; |
|
465 } |
|
466 |
|
467 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const { |
|
468 SkASSERT(0); |
|
469 return false; |
|
470 } |
|
471 |
|
472 SkDisplayTypes SkDisplayable::getType() const { |
|
473 return SkType_Unknown; |
|
474 } |
|
475 |
|
476 bool SkDisplayable::hasEnable() const { |
|
477 return false; |
|
478 } |
|
479 |
|
480 bool SkDisplayable::isDrawable() const { |
|
481 return false; |
|
482 } |
|
483 |
|
484 void SkDisplayable::onEndElement(SkAnimateMaker& ) {} |
|
485 |
|
486 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) { |
|
487 return NULL; |
|
488 } |
|
489 |
|
490 bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { |
|
491 return false; |
|
492 } |
|
493 |
|
494 //SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) { |
|
495 // return this; |
|
496 //} |
|
497 |
|
498 void SkDisplayable::setChildHasID() { |
|
499 } |
|
500 |
|
501 bool SkDisplayable::setParent(SkDisplayable* ) { |
|
502 return false; |
|
503 } |
|
504 |
|
505 bool SkDisplayable::setProperty(int index, SkScriptValue& ) { |
|
506 //SkASSERT(0); |
|
507 return false; |
|
508 } |
|
509 |
|
510 void SkDisplayable::setReference(const SkMemberInfo* info, SkDisplayable* displayable) { |
|
511 if (info->fType == SkType_MemberProperty) { |
|
512 SkScriptValue scriptValue; |
|
513 scriptValue.fOperand.fDisplayable = displayable; |
|
514 scriptValue.fType = displayable->getType(); |
|
515 setProperty(info->propertyIndex(), scriptValue); |
|
516 } else if (info->fType == SkType_Array) { |
|
517 SkASSERT(displayable->getType() == SkType_Array); |
|
518 SkDisplayArray* dispArray = (SkDisplayArray*) displayable; |
|
519 SkTDScalarArray* array = (SkTDScalarArray* ) info->memberData(this); |
|
520 array->setCount(dispArray->values.count()); |
|
521 memcpy(array->begin(), dispArray->values.begin(), dispArray->values.count() * sizeof(int)); |
|
522 // |
|
523 |
|
524 // !!! need a way for interpreter engine to own array |
|
525 // !!! probably need to replace all scriptable arrays with single bigger array |
|
526 // that has operand and type on every element -- or |
|
527 // when array is dirtied, need to get parent to reparse to local array |
|
528 } else { |
|
529 void* storage = info->memberData(this); |
|
530 memcpy(storage, &displayable, sizeof(SkDisplayable*)); |
|
531 } |
|
532 // !!! unclear why displayable is dirtied here |
|
533 // if this is called, this breaks fromPath.xml |
|
534 // displayable->dirty(); |
|
535 } |
|
536 |
|
537 #ifdef SK_DEBUG |
|
538 void SkDisplayable::validate() { |
|
539 } |
|
540 #endif |