blob: aff3aaefc62e2681f7caf544d6ee69a6f1345635 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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;
20SkTDDisplayableArray SkDisplayable::fAllocations;
21#endif
22
23#ifdef SK_DEBUG
rmistry@google.comd6176b02012-08-23 18:14:13 +000024SkDisplayable::SkDisplayable() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000025 id = _id.c_str();
26#ifdef SK_FIND_LEAKS
27 // fAllocationCount++;
28 *fAllocations.append() = this;
29#endif
30}
31#endif
32
33SkDisplayable::~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
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000042bool SkDisplayable::addChild(SkAnimateMaker& , SkDisplayable* child) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000043 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000044}
45
rmistry@google.comd6176b02012-08-23 18:14:13 +000046//void SkDisplayable::apply(SkAnimateMaker& , const SkMemberInfo* ,
47// SkDisplayable* , SkScalar [], int count) {
48// SkASSERT(0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000049//}
50
51bool SkDisplayable::canContainDependents() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +000052 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000053}
rmistry@google.comd6176b02012-08-23 18:14:13 +000054
55bool SkDisplayable::childrenNeedDisposing() const {
56 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000057}
58
59void SkDisplayable::clearBounder() {
60}
61
62bool SkDisplayable::contains(SkDisplayable* ) {
63 return false;
64}
65
66SkDisplayable* SkDisplayable::contains(const SkString& ) {
67 return NULL;
68}
69
70SkDisplayable* 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
133void SkDisplayable::dirty() {
134}
135
136#ifdef SK_DUMP_ENABLED
137void 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
145void 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 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 propIndex++;
175 continue;
176 }
177 if (SkDisplayType::IsDisplayable(maker, info->fType)) {
178 continue;
179 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000180
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 if (info->fType == SkType_MemberFunction)
182 continue;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000183
184
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000204 case SkType_Int:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205 SkDebugf("%d", op->fS32);
206 break;
207 case SkType_Float:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 SkDebugf("%g", SkScalarToFloat(op->fScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209 break;
210 case SkType_String:
rmistry@google.comd6176b02012-08-23 18:14:13 +0000211 case SkType_DynamicString:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 SkDebugf("%s", op->fString->c_str());
213 break;
214 default:
215 break;
216 }
217 firstElem = false;
218 }
219 SkDebugf("]\" ");
220 continue;
221 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000222
reed@android.com8a1c16f2008-12-17 15:59:43 +0000223 if (info->fType == SkType_String || info->fType == SkType_DynamicString) {
224 SkString* string;
225 info->getString(this, &string);
226 if (string->isEmpty() == false)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000227 SkDebugf("%s=\"%s\"\t", info->fName, string->c_str());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228 continue;
229 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000230
231
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232 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
241void 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
254void SkDisplayable::dumpChildren(SkAnimateMaker* maker, bool closedAngle) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000255
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 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
283void 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
292void SkDisplayable::dumpEvents() {
293}
294
295void 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) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 SkDebugf("%s=\"[%g,%g]\" ", info->fName, SkScalarToFloat(op.fScalar), SkScalarToFloat(op2.fScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000311 }
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?
rmistry@google.comd6176b02012-08-23 18:14:13 +0000357 if (op.fS32 != blankOp.fS32)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 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?
reed@android.com8a1c16f2008-12-17 15:59:43 +0000370 SkDebugf("%s=\"%g\" ", info->fName, SkScalarToFloat(op.fScalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371 }
372 break;
373 case SkType_String:
374 case SkType_DynamicString:
rmistry@google.comd6176b02012-08-23 18:14:13 +0000375 if (op.fString->size() > 0)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000376 SkDebugf("%s=\"%s\" ", info->fName, op.fString->c_str());
377 break;
378 case SkType_MSec:
379 if (op.fS32 != blankOp.fS32) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000380 SkDebugf(" %s=\"%g\" ", info->fName, SkScalarToFloat(SkScalarDiv(op.fS32, 1000)));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 }
382 default:
383 SkDebugf("");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000384 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000385}
386
387#endif
388
rmistry@google.comd6176b02012-08-23 18:14:13 +0000389bool SkDisplayable::enable( SkAnimateMaker& ) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000390 return false;
391}
392
393void SkDisplayable::enableBounder() {
394}
395
rmistry@google.comd6176b02012-08-23 18:14:13 +0000396void SkDisplayable::executeFunction(SkDisplayable* , int index,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000398 SkASSERT(0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000399}
400
rmistry@google.comd6176b02012-08-23 18:14:13 +0000401void SkDisplayable::executeFunction(SkDisplayable* target,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000402 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
rmistry@google.comd6176b02012-08-23 18:14:13 +0000413void SkDisplayable::executeFunction2(SkDisplayable* , int index,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414 SkOpArray* params, SkDisplayTypes, SkOperand2* ) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000415 SkASSERT(0);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416}
417
418void SkDisplayable::getBounds(SkRect* rect) {
419 SkASSERT(rect);
420 rect->fLeft = rect->fTop = SK_ScalarMax;
421 rect->fRight= rect->fBottom = -SK_ScalarMax;
422}
423
424const SkFunctionParamType* SkDisplayable::getFunctionsParameters() {
425 return NULL;
426}
427
rmistry@google.comd6176b02012-08-23 18:14:13 +0000428const SkMemberInfo* SkDisplayable::getMember(int index) {
429 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430}
431
rmistry@google.comd6176b02012-08-23 18:14:13 +0000432const SkMemberInfo* SkDisplayable::getMember(const char name[]) {
433 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434}
435
rmistry@google.comd6176b02012-08-23 18:14:13 +0000436const SkFunctionParamType* SkDisplayable::getParameters(const SkMemberInfo* info,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000437 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 &params[offset - count];
456}
457
458SkDisplayable* SkDisplayable::getParent() const {
459 return NULL;
460}
461
462bool SkDisplayable::getProperty(int index, SkScriptValue* ) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000463// SkASSERT(0);
464 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
467bool SkDisplayable::getProperty2(int index, SkOperand2* value) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000468 SkASSERT(0);
469 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000470}
471
rmistry@google.comd6176b02012-08-23 18:14:13 +0000472SkDisplayTypes SkDisplayable::getType() const {
473 return SkType_Unknown;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000474}
475
476bool SkDisplayable::hasEnable() const {
477 return false;
478}
479
480bool SkDisplayable::isDrawable() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000481 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000482}
483
484void SkDisplayable::onEndElement(SkAnimateMaker& ) {}
485
486const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) {
487 return NULL;
488}
489
490bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) {
491 return false;
492}
493
rmistry@google.comd6176b02012-08-23 18:14:13 +0000494//SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) {
495// return this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000496//}
497
498void SkDisplayable::setChildHasID() {
499}
500
501bool SkDisplayable::setParent(SkDisplayable* ) {
502 return false;
503}
504
505bool SkDisplayable::setProperty(int index, SkScriptValue& ) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000506 //SkASSERT(0);
507 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000508}
509
510void 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
538void SkDisplayable::validate() {
539}
540#endif