1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*
3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2006 The Android Open Source Project
4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *
5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file.
7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkDisplayTypes.h"
11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkAnimateBase.h"
12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkDisplayDepend::canContainDependents() const {
14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDisplayDepend::dirty() {
18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDisplayable** last = fDependents.end();
19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (SkDisplayable** depPtr = fDependents.begin(); depPtr < last; depPtr++) {
20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkAnimateBase* animate = (SkAnimateBase* ) *depPtr;
21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        animate->setChanged(true);
22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// Boolean
26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if SK_USE_CONDENSED_INFO == 0
27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMemberInfo SkDisplayBoolean::fInfo[] = {
29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER(value, Boolean)
30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
34f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerDEFINE_GET_MEMBER(SkDisplayBoolean);
35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
36f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayBoolean::SkDisplayBoolean() : value(false) {
37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DUMP_ENABLED
40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDisplayBoolean::dump(SkAnimateMaker* maker){
41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dumpBase(maker);
42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDebugf("value=\"%s\" />\n", value ? "true" : "false");
43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// int32_t
47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if SK_USE_CONDENSED_INFO == 0
48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMemberInfo SkDisplayInt::fInfo[] = {
50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER(value, Int)
51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
55f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerDEFINE_GET_MEMBER(SkDisplayInt);
56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
57f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayInt::SkDisplayInt() : value(0) {
58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DUMP_ENABLED
61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDisplayInt::dump(SkAnimateMaker* maker){
62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dumpBase(maker);
63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDebugf("value=\"%d\" />\n", value);
64f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// SkScalar
68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if SK_USE_CONDENSED_INFO == 0
69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMemberInfo SkDisplayFloat::fInfo[] = {
71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER(value, Float)
72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
76f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerDEFINE_GET_MEMBER(SkDisplayFloat);
77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
78f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayFloat::SkDisplayFloat() : value(0) {
79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DUMP_ENABLED
82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDisplayFloat::dump(SkAnimateMaker* maker) {
83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dumpBase(maker);
84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_CAN_USE_FLOAT
85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDebugf("value=\"%g\" />\n", SkScalarToFloat(value));
86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else
87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDebugf("value=\"%x\" />\n", value);
88f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// SkString
93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerenum SkDisplayString_Functions {
94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_FUNCTION(slice)
95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerenum SkDisplayString_Properties {
98f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_PROPERTY(length)
99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkFunctionParamType SkDisplayString::fFunctionParameters[] = {
102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    (SkFunctionParamType) SkType_Int,   // slice
103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    (SkFunctionParamType) SkType_Int,
104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    (SkFunctionParamType) 0
105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if SK_USE_CONDENSED_INFO == 0
108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMemberInfo SkDisplayString::fInfo[] = {
110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER_PROPERTY(length, Int),
111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER_FUNCTION(slice, String),
112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER(value, String)
113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
117f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerDEFINE_GET_MEMBER(SkDisplayString);
118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
119f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayString::SkDisplayString() {
120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
122f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayString::SkDisplayString(SkString& copyFrom) : value(copyFrom) {
123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDisplayString::executeFunction(SkDisplayable* target, int index,
126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkTDArray<SkScriptValue>& parameters, SkDisplayTypes type,
127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkScriptValue* scriptValue) {
128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (scriptValue == NULL)
129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return;
130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(target == this);
131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    switch (index) {
132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case SK_FUNCTION(slice):
133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            scriptValue->fType = SkType_String;
134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkASSERT(parameters[0].fType == SkType_Int);
135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            int start =  parameters[0].fOperand.fS32;
136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (start < 0)
137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                start = (int) (value.size() - start);
138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            int end = (int) value.size();
139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (parameters.count() > 1) {
140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkASSERT(parameters[1].fType == SkType_Int);
141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                end = parameters[1].fOperand.fS32;
142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            //if (end >= 0 && end < (int) value.size())
144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (end >= 0 && end <= (int) value.size())
145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                scriptValue->fOperand.fString = new SkString(&value.c_str()[start], end - start);
146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            else
147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                scriptValue->fOperand.fString = new SkString(value);
148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        break;
149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkFunctionParamType* SkDisplayString::getFunctionsParameters() {
153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return fFunctionParameters;
154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkDisplayString::getProperty(int index, SkScriptValue* scriptValue) const {
157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    switch (index) {
158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case SK_PROPERTY(length):
159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            scriptValue->fType = SkType_Int;
160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            scriptValue->fOperand.fS32 = (int32_t) value.size();
161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            break;
162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        default:
163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkASSERT(0);
164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return false;
165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// SkArray
171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if 0   // !!! reason enough to qualify enum with class name or move typedArray into its own file
172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerenum SkDisplayArray_Properties {
173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_PROPERTY(length)
174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if SK_USE_CONDENSED_INFO == 0
178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMemberInfo SkDisplayArray::fInfo[] = {
180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER_PROPERTY(length, Int),
181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_MEMBER_ARRAY(values, Unknown)
182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
186f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerDEFINE_GET_MEMBER(SkDisplayArray);
187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
188f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayArray::SkDisplayArray() {
189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
191f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayArray::SkDisplayArray(SkTypedArray& copyFrom) : values(copyFrom) {
192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
195f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkDisplayArray::~SkDisplayArray() {
196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (values.getType() == SkType_String) {
197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int index = 0; index < values.count(); index++)
198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            delete values[index].fString;
199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return;
200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (values.getType() == SkType_Array) {
202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int index = 0; index < values.count(); index++)
203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            delete values[index].fArray;
204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkDisplayArray::getProperty(int index, SkScriptValue* value) const {
208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    switch (index) {
209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case SK_PROPERTY(length):
210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            value->fType = SkType_Int;
211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            value->fOperand.fS32 = values.count();
212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            break;
213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        default:
214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkASSERT(0);
215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return false;
216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
222