summaryrefslogtreecommitdiffstats
path: root/skia/animator/SkMemberInfo.cpp
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:09:42 +0000
commitae2c20f398933a9e86c387dcc465ec0f71065ffc (patch)
treede668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/animator/SkMemberInfo.cpp
parent09911bf300f1a419907a9412154760efd0b7abc3 (diff)
downloadchromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz
chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/animator/SkMemberInfo.cpp')
-rw-r--r--skia/animator/SkMemberInfo.cpp568
1 files changed, 568 insertions, 0 deletions
diff --git a/skia/animator/SkMemberInfo.cpp b/skia/animator/SkMemberInfo.cpp
new file mode 100644
index 0000000..d4f4e51
--- /dev/null
+++ b/skia/animator/SkMemberInfo.cpp
@@ -0,0 +1,568 @@
+/* libs/graphics/animator/SkMemberInfo.cpp
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "SkMemberInfo.h"
+#include "SkAnimateMaker.h"
+#include "SkAnimatorScript.h"
+#include "SkBase64.h"
+#include "SkCamera.h"
+#include "SkDisplayable.h"
+#include "SkDisplayTypes.h"
+#include "SkDraw3D.h"
+#include "SkDrawColor.h"
+#include "SkParse.h"
+#include "SkScript.h"
+#include "SkTSearch.h"
+#include "SkTypedArray.h"
+
+size_t SkMemberInfo::GetSize(SkDisplayTypes type) { // size of simple types only
+ size_t byteSize;
+ switch (type) {
+ case SkType_ARGB:
+ byteSize = sizeof(SkColor);
+ break;
+ case SkType_AddMode:
+ case SkType_Align:
+ case SkType_ApplyMode:
+ case SkType_ApplyTransition:
+ case SkType_BitmapEncoding:
+ case SkType_Boolean:
+ case SkType_Cap:
+ case SkType_EventCode:
+ case SkType_EventKind:
+ case SkType_EventMode:
+ case SkType_FilterType:
+ case SkType_FontStyle:
+ case SkType_FromPathMode:
+ case SkType_Join:
+ case SkType_MaskFilterBlurStyle:
+ case SkType_PathDirection:
+ case SkType_Style:
+ case SkType_TileMode:
+ case SkType_Xfermode:
+ byteSize = sizeof(int);
+ break;
+ case SkType_Base64: // assume base64 data is always const, copied by ref
+ case SkType_Displayable:
+ case SkType_Drawable:
+ case SkType_Matrix:
+ byteSize = sizeof(void*);
+ break;
+ case SkType_MSec:
+ byteSize = sizeof(SkMSec);
+ break;
+ case SkType_Point:
+ byteSize = sizeof(SkPoint);
+ break;
+ case SkType_3D_Point:
+ byteSize = sizeof(Sk3D_Point);
+ break;
+ case SkType_Int:
+ byteSize = sizeof(int32_t);
+ break;
+ case SkType_Float:
+ byteSize = sizeof(SkScalar);
+ break;
+ case SkType_DynamicString:
+ case SkType_String:
+ byteSize = sizeof(SkString); // assume we'll copy by reference, not value
+ break;
+ default:
+// SkASSERT(0);
+ byteSize = 0;
+ }
+ return byteSize;
+}
+
+bool SkMemberInfo::getArrayValue(const SkDisplayable* displayable, int index, SkOperand* value) const {
+ SkASSERT(fType != SkType_String && fType != SkType_MemberProperty);
+ char* valuePtr = (char*) *(SkOperand**) memberData(displayable);
+ SkDisplayTypes type = (SkDisplayTypes) 0;
+ if (displayable->getType() == SkType_Array) {
+ SkDisplayArray* dispArray = (SkDisplayArray*) displayable;
+ if (dispArray->values.count() <= index)
+ return false;
+ type = dispArray->values.getType();
+ } else
+ SkASSERT(0); // incomplete
+ size_t byteSize = GetSize(type);
+ memcpy(value, valuePtr + index * byteSize, byteSize);
+ return true;
+}
+
+size_t SkMemberInfo::getSize(const SkDisplayable* displayable) const {
+ size_t byteSize;
+ switch (fType) {
+ case SkType_MemberProperty:
+ byteSize = GetSize(propertyType());
+ break;
+ case SkType_Array: {
+ SkDisplayTypes type;
+ if (displayable == NULL)
+ return sizeof(int);
+ if (displayable->getType() == SkType_Array) {
+ SkDisplayArray* dispArray = (SkDisplayArray*) displayable;
+ type = dispArray->values.getType();
+ } else
+ type = propertyType();
+ SkTDOperandArray* array = (SkTDOperandArray*) memberData(displayable);
+ byteSize = GetSize(type) * array->count();
+ } break;
+ default:
+ byteSize = GetSize((SkDisplayTypes) fType);
+ }
+ return byteSize;
+}
+
+void SkMemberInfo::getString(const SkDisplayable* displayable, SkString** string) const {
+ if (fType == SkType_MemberProperty) {
+ SkScriptValue value;
+ displayable->getProperty(propertyIndex(), &value);
+ SkASSERT(value.fType == SkType_String);
+ *string = value.fOperand.fString;
+ return;
+ }
+ SkASSERT(fCount == sizeof(SkString) / sizeof(SkScalar));
+ SkASSERT(fType == SkType_String || fType == SkType_DynamicString);
+ void* valuePtr = memberData(displayable);
+ *string = (SkString*) valuePtr;
+}
+
+void SkMemberInfo::getValue(const SkDisplayable* displayable, SkOperand value[], int count) const {
+ SkASSERT(fType != SkType_String && fType != SkType_MemberProperty);
+ SkASSERT(count == fCount);
+ void* valuePtr = memberData(displayable);
+ size_t byteSize = getSize(displayable);
+ SkASSERT(sizeof(value[0].fScalar) == sizeof(value[0])); // no support for 64 bit pointers, yet
+ memcpy(value, valuePtr, byteSize);
+}
+
+void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
+ SkString* string = (SkString*) memberData(displayable);
+ string->set(*value);
+ displayable->dirty();
+}
+
+void SkMemberInfo::setValue(SkDisplayable* displayable, const SkOperand values[],
+ int count) const {
+ SkASSERT(sizeof(values[0].fScalar) == sizeof(values[0])); // no support for 64 bit pointers, yet
+ char* dst = (char*) memberData(displayable);
+ if (fType == SkType_Array) {
+ SkTDScalarArray* array = (SkTDScalarArray* ) dst;
+ array->setCount(count);
+ dst = (char*) array->begin();
+ }
+ memcpy(dst, values, count * sizeof(SkOperand));
+ displayable->dirty();
+}
+
+
+static inline bool is_between(int c, int min, int max)
+{
+ return (unsigned)(c - min) <= (unsigned)(max - min);
+}
+
+static inline bool is_hex(int c)
+{
+ if (is_between(c, '0', '9'))
+ return true;
+ c |= 0x20; // make us lower-case
+ if (is_between(c, 'a', 'f'))
+ return true;
+ return false;
+}
+
+
+bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage,
+ int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType,
+ const char rawValue[], size_t rawValueLen) const
+{
+ SkString valueStr(rawValue, rawValueLen);
+ SkScriptValue scriptValue;
+ scriptValue.fType = SkType_Unknown;
+ scriptValue.fOperand.fS32 = 0;
+ SkDisplayTypes type = getType();
+ SkAnimatorScript engine(maker, displayable, type);
+ if (arrayStorage)
+ displayable = NULL;
+ bool success = true;
+ void* untypedStorage = NULL;
+ if (displayable && fType != SkType_MemberProperty && fType != SkType_MemberFunction)
+ untypedStorage = (SkTDOperandArray*) memberData(displayable);
+
+ if (type == SkType_ARGB) {
+ // for both SpiderMonkey and SkiaScript, substitute any #xyz or #xxyyzz first
+ // it's enough to expand the colors into 0xFFxxyyzz
+ const char* poundPos;
+ while ((poundPos = strchr(valueStr.c_str(), '#')) != NULL) {
+ size_t offset = poundPos - valueStr.c_str();
+ if (valueStr.size() - offset < 4)
+ break;
+ char r = poundPos[1];
+ char g = poundPos[2];
+ char b = poundPos[3];
+ if (is_hex(r) == false || is_hex(g) == false || is_hex(b) == false)
+ break;
+ char hex = poundPos[4];
+ if (is_hex(hex) == false) {
+ valueStr.insertUnichar(offset + 1, r);
+ valueStr.insertUnichar(offset + 3, g);
+ valueStr.insertUnichar(offset + 5, b);
+ }
+ *(char*) poundPos = '0'; // overwrite '#'
+ valueStr.insert(offset + 1, "xFF");
+ }
+ }
+ if (SkDisplayType::IsDisplayable(&maker, type) || SkDisplayType::IsEnum(&maker, type) || type == SkType_ARGB)
+ goto scriptCommon;
+ switch (type) {
+ case SkType_String:
+#if 0
+ if (displayable && displayable->isAnimate()) {
+
+ goto noScriptString;
+ }
+ if (strncmp(rawValue, "#string:", sizeof("#string:") - 1) == 0) {
+ SkASSERT(sizeof("string") == sizeof("script"));
+ char* stringHeader = valueStr.writable_str();
+ memcpy(&stringHeader[1], "script", sizeof("script") - 1);
+ rawValue = valueStr.c_str();
+ goto noScriptString;
+ } else
+#endif
+ if (strncmp(rawValue, "#script:", sizeof("#script:") - 1) != 0)
+ goto noScriptString;
+ valueStr.remove(0, 8);
+ case SkType_Unknown:
+ case SkType_Int:
+ case SkType_MSec: // for the purposes of script, MSec is treated as a Scalar
+ case SkType_Point:
+ case SkType_3D_Point:
+ case SkType_Float:
+ case SkType_Array:
+scriptCommon: {
+ const char* script = valueStr.c_str();
+ success = engine.evaluateScript(&script, &scriptValue);
+ if (success == false) {
+ maker.setScriptError(engine);
+ return false;
+ }
+ }
+ SkASSERT(success);
+ if (scriptValue.fType == SkType_Displayable) {
+ if (type == SkType_String) {
+ const char* charPtr;
+ maker.findKey(scriptValue.fOperand.fDisplayable, &charPtr);
+ scriptValue.fOperand.fString = new SkString(charPtr);
+ scriptValue.fType = SkType_String;
+ engine.SkScriptEngine::track(scriptValue.fOperand.fString);
+ break;
+ }
+ SkASSERT(SkDisplayType::IsDisplayable(&maker, type));
+ if (displayable)
+ displayable->setReference(this, scriptValue.fOperand.fDisplayable);
+ else
+ arrayStorage->begin()[0].fDisplayable = scriptValue.fOperand.fDisplayable;
+ return true;
+ }
+ if (type != scriptValue.fType) {
+ if (scriptValue.fType == SkType_Array) {
+ engine.forget(scriptValue.getArray());
+ goto writeStruct; // real structs have already been written by script
+ }
+ switch (type) {
+ case SkType_String:
+ success = engine.convertTo(SkType_String, &scriptValue);
+ break;
+ case SkType_MSec:
+ case SkType_Float:
+ success = engine.convertTo(SkType_Float, &scriptValue);
+ break;
+ case SkType_Int:
+ success = engine.convertTo(SkType_Int, &scriptValue);
+ break;
+ case SkType_Array:
+ success = engine.convertTo(arrayType(), &scriptValue);
+ // !!! incomplete; create array of appropriate type and add scriptValue to it
+ SkASSERT(0);
+ break;
+ case SkType_Displayable:
+ case SkType_Drawable:
+ return false; // no way to convert other types to this
+ default: // to avoid warnings
+ break;
+ }
+ if (success == false)
+ return false;
+ }
+ if (type == SkType_MSec)
+ scriptValue.fOperand.fMSec = SkScalarMulRound(scriptValue.fOperand.fScalar, 1000);
+ scriptValue.fType = type;
+ break;
+ noScriptString:
+ case SkType_DynamicString:
+ if (fType == SkType_MemberProperty && displayable) {
+ SkString string(rawValue, rawValueLen);
+ SkScriptValue scriptValue;
+ scriptValue.fOperand.fString = &string;
+ scriptValue.fType = SkType_String;
+ displayable->setProperty(propertyIndex(), scriptValue);
+ } else if (displayable) {
+ SkString* string = (SkString*) memberData(displayable);
+ string->set(rawValue, rawValueLen);
+ } else {
+ SkASSERT(arrayStorage->count() == 1);
+ arrayStorage->begin()->fString->set(rawValue, rawValueLen);
+ }
+ goto dirty;
+ case SkType_Base64: {
+ SkBase64 base64;
+ base64.decode(rawValue, rawValueLen);
+ *(SkBase64* ) untypedStorage = base64;
+ } goto dirty;
+ default:
+ SkASSERT(0);
+ break;
+ }
+// if (SkDisplayType::IsStruct(type) == false)
+ {
+writeStruct:
+ if (writeValue(displayable, arrayStorage, storageOffset, maxStorage,
+ untypedStorage, outType, scriptValue)) {
+ maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType);
+ return false;
+ }
+ }
+dirty:
+ if (displayable)
+ displayable->dirty();
+ return true;
+}
+
+bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage,
+ int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType,
+ SkString& raw) const {
+ return setValue(maker, arrayStorage, storageOffset, maxStorage, displayable, outType, raw.c_str(),
+ raw.size());
+}
+
+bool SkMemberInfo::writeValue(SkDisplayable* displayable, SkTDOperandArray* arrayStorage,
+ int storageOffset, int maxStorage, void* untypedStorage, SkDisplayTypes outType,
+ SkScriptValue& scriptValue) const
+{
+ SkOperand* storage = untypedStorage ? (SkOperand*) untypedStorage : arrayStorage ?
+ arrayStorage->begin() : NULL;
+ if (storage)
+ storage += storageOffset;
+ SkDisplayTypes type = getType();
+ if (fType == SkType_MemberProperty) {
+ if(displayable)
+ displayable->setProperty(propertyIndex(), scriptValue);
+ else {
+ SkASSERT(storageOffset < arrayStorage->count());
+ switch (scriptValue.fType) {
+ case SkType_Boolean:
+ case SkType_Float:
+ case SkType_Int:
+ memcpy(&storage->fScalar, &scriptValue.fOperand.fScalar, sizeof(SkScalar));
+ break;
+ case SkType_Array:
+ memcpy(&storage->fScalar, scriptValue.fOperand.fArray->begin(), scriptValue.fOperand.fArray->count() * sizeof(SkScalar));
+ break;
+ case SkType_String:
+ storage->fString->set(*scriptValue.fOperand.fString);
+ break;
+ default:
+ SkASSERT(0); // type isn't handled yet
+ }
+ }
+ } else if (fType == SkType_MemberFunction) {
+ SkASSERT(scriptValue.fType == SkType_Array);
+ if (displayable)
+ displayable->executeFunction(displayable, this, scriptValue.fOperand.fArray, NULL);
+ else {
+ int count = scriptValue.fOperand.fArray->count();
+ // SkASSERT(maxStorage == 0 || count == maxStorage);
+ if (arrayStorage->count() == 2)
+ arrayStorage->setCount(2 * count);
+ else {
+ storageOffset *= count;
+ SkASSERT(count + storageOffset <= arrayStorage->count());
+ }
+ memcpy(&(*arrayStorage)[storageOffset], scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand));
+ }
+
+ } else if (fType == SkType_Array) {
+ SkTypedArray* destArray = (SkTypedArray*) (untypedStorage ? untypedStorage : arrayStorage);
+ SkASSERT(destArray);
+ // destArray->setCount(0);
+ if (scriptValue.fType != SkType_Array) {
+ SkASSERT(type == scriptValue.fType);
+ // SkASSERT(storageOffset + 1 <= maxStorage);
+ destArray->setCount(storageOffset + 1);
+ (*destArray)[storageOffset] = scriptValue.fOperand;
+ } else {
+ if (type == SkType_Unknown) {
+ type = scriptValue.fOperand.fArray->getType();
+ destArray->setType(type);
+ }
+ SkASSERT(type == scriptValue.fOperand.fArray->getType());
+ int count = scriptValue.fOperand.fArray->count();
+ // SkASSERT(storageOffset + count <= maxStorage);
+ destArray->setCount(storageOffset + count);
+ memcpy(destArray->begin() + storageOffset, scriptValue.fOperand.fArray->begin(), sizeof(SkOperand) * count);
+ }
+ } else if (type == SkType_String) {
+ SkString* string = untypedStorage ? (SkString*) untypedStorage : (*arrayStorage)[storageOffset].fString;
+ string->set(*scriptValue.fOperand.fString);
+ } else if (type == SkType_ARGB && outType == SkType_Float) {
+ SkTypedArray* array = scriptValue.fOperand.fArray;
+ SkASSERT(scriptValue.fType == SkType_Int || scriptValue.fType == SkType_ARGB ||
+ scriptValue.fType == SkType_Array);
+ SkASSERT(scriptValue.fType != SkType_Array || (array != NULL &&
+ array->getType() == SkType_Int));
+ int numberOfColors = scriptValue.fType == SkType_Array ? array->count() : 1;
+ int numberOfComponents = numberOfColors * 4;
+ // SkASSERT(maxStorage == 0 || maxStorage == numberOfComponents);
+ if (maxStorage == 0)
+ arrayStorage->setCount(numberOfComponents);
+ for (int index = 0; index < numberOfColors; index++) {
+ SkColor color = scriptValue.fType == SkType_Array ?
+ (SkColor) array->begin()[index].fS32 : (SkColor) scriptValue.fOperand.fS32;
+ storage[0].fScalar = SkIntToScalar(SkColorGetA(color));
+ storage[1].fScalar = SkIntToScalar(SkColorGetR(color));
+ storage[2].fScalar = SkIntToScalar(SkColorGetG(color));
+ storage[3].fScalar = SkIntToScalar(SkColorGetB(color));
+ storage += 4;
+ }
+ } else if (SkDisplayType::IsStruct(NULL /* !!! maker*/, type)) {
+ if (scriptValue.fType != SkType_Array)
+ return true; // error
+ SkASSERT(sizeof(SkScalar) == sizeof(SkOperand)); // !!! no 64 bit pointer support yet
+ int count = scriptValue.fOperand.fArray->count();
+ if (count > 0) {
+ SkASSERT(fCount == count);
+ memcpy(storage, scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand));
+ }
+ } else if (scriptValue.fType == SkType_Array) {
+ SkASSERT(scriptValue.fOperand.fArray->getType() == type);
+ SkASSERT(scriptValue.fOperand.fArray->count() == getCount());
+ memcpy(storage, scriptValue.fOperand.fArray->begin(), getCount() * sizeof(SkOperand));
+ } else {
+ memcpy(storage, &scriptValue.fOperand, sizeof(SkOperand));
+ }
+ return false;
+}
+
+
+//void SkMemberInfo::setValue(SkDisplayable* displayable, const char value[], const char name[]) const {
+// void* valuePtr = (void*) ((char*) displayable + fOffset);
+// switch (fType) {
+// case SkType_Point3D: {
+// static const char xyz[] = "x|y|z";
+// int index = find_one(xyz, name);
+// SkASSERT(index >= 0);
+// valuePtr = (void*) ((char*) valuePtr + index * sizeof(SkScalar));
+// } break;
+// default:
+// SkASSERT(0);
+// }
+// SkParse::FindScalar(value, (SkScalar*) valuePtr);
+// displayable->dirty();
+//}
+
+#if SK_USE_CONDENSED_INFO == 0
+
+// Find Nth memberInfo
+const SkMemberInfo* SkMemberInfo::Find(const SkMemberInfo info[], int count, int* index) {
+ SkASSERT(*index >= 0);
+ if (info->fType == SkType_BaseClassInfo) {
+ const SkMemberInfo* inherited = (SkMemberInfo*) info->fName;
+ const SkMemberInfo* result = SkMemberInfo::Find(inherited, info->fCount, index);
+ if (result != NULL)
+ return result;
+ if (--count == 0)
+ return NULL;
+ info++;
+ }
+ SkASSERT(info->fName);
+ SkASSERT(info->fType != SkType_BaseClassInfo);
+ if (*index >= count) {
+ *index -= count;
+ return NULL;
+ }
+ return &info[*index];
+}
+
+// Find named memberinfo
+const SkMemberInfo* SkMemberInfo::Find(const SkMemberInfo info[], int count, const char** matchPtr) {
+ const char* match = *matchPtr;
+ if (info->fType == SkType_BaseClassInfo) {
+ const SkMemberInfo* inherited = (SkMemberInfo*) info->fName;
+ const SkMemberInfo* result = SkMemberInfo::Find(inherited, info->fCount, matchPtr);
+ if (result != NULL)
+ return result;
+ if (--count == 0)
+ return NULL;
+ info++;
+ }
+ SkASSERT(info->fName);
+ SkASSERT(info->fType != SkType_BaseClassInfo);
+ int index = SkStrSearch(&info->fName, count, match, sizeof(*info));
+ if (index < 0 || index >= count)
+ return NULL;
+ return &info[index];
+}
+
+const SkMemberInfo* SkMemberInfo::getInherited() const {
+ return (SkMemberInfo*) fName;
+}
+
+#endif // SK_USE_CONDENSED_INFO == 0
+
+#if 0
+bool SkMemberInfo::SetValue(void* valuePtr, const char value[], SkDisplayTypes type,
+ int count) {
+ switch (type) {
+ case SkType_Animate:
+ case SkType_BaseBitmap:
+ case SkType_Bitmap:
+ case SkType_Dash:
+ case SkType_Displayable:
+ case SkType_Drawable:
+ case SkType_Matrix:
+ case SkType_Path:
+ case SkType_Text:
+ case SkType_3D_Patch:
+ return false; // ref to object; caller must resolve
+ case SkType_MSec: {
+ SkParse::FindMSec(value, (SkMSec*) valuePtr);
+ } break;
+ case SkType_3D_Point:
+ case SkType_Point:
+ // case SkType_PointArray:
+ case SkType_ScalarArray:
+ SkParse::FindScalars(value, (SkScalar*) valuePtr, count);
+ break;
+ default:
+ SkASSERT(0);
+ }
+ return true;
+}
+#endif
+
+