nsresult SVGLengthList::SetValueFromString(const nsAString& aValue) { SVGLengthList temp; NS_ConvertUTF16toUTF8 value(aValue); char* start = SkipWhitespace(value.BeginWriting()); // We can't use strtok with SVG_COMMA_WSP_DELIM because to correctly handle // invalid input in the form of two commas without a value between them, we // would need to know if strtok overwrote a comma or not. while (*start != '\0') { int end = strcspn(start, SVG_COMMA_WSP_DELIM); if (end == 0) { // found comma in an invalid location return NS_ERROR_DOM_SYNTAX_ERR; } SVGLength length; if (!length.SetValueFromString(NS_ConvertUTF8toUTF16(start, PRUint32(end)))) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(length)) { return NS_ERROR_OUT_OF_MEMORY; } start = SkipWhitespace(start + end); if (*start == ',') { start = SkipWhitespace(start + 1); } } return CopyFrom(temp); }
void DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& aNewValue) { // When the number of items in our internal counterpart's baseVal changes, // we MUST keep our baseVal in sync. If we don't, script will either see a // list that is too short and be unable to access indexes that should be // valid, or else, MUCH WORSE, script will see a list that is too long and be // able to access "items" at indexes that are out of bounds (read/write to // bad memory)!! nsRefPtr<DOMSVGAnimatedLengthList> kungFuDeathGrip; if (mBaseVal) { if (aNewValue.Length() < mBaseVal->Length()) { // InternalListLengthWillChange might clear last reference to |this|. // Retain a temporary reference to keep from dying before returning. kungFuDeathGrip = this; } mBaseVal->InternalListLengthWillChange(aNewValue.Length()); } // If our attribute is not animating, then our animVal mirrors our baseVal // and we must sync its length too. (If our attribute is animating, then the // SMIL engine takes care of calling InternalAnimValListWillChangeTo() if // necessary.) if (!IsAnimating()) { InternalAnimValListWillChangeTo(aNewValue); } }
nsresult SVGAnimatedLengthList::SetBaseValueString(const nsAString& aValue) { SVGLengthList newBaseValue; nsresult rv = newBaseValue.SetValueFromString(aValue); if (NS_FAILED(rv)) { return rv; } DOMSVGAnimatedLengthList *domWrapper = DOMSVGAnimatedLengthList::GetDOMWrapperIfExists(this); if (domWrapper) { // We must send this notification *before* changing mBaseVal! If the length // of our baseVal is being reduced, our baseVal's DOM wrapper list may have // to remove DOM items from itself, and any removed DOM items need to copy // their internal counterpart values *before* we change them. // domWrapper->InternalBaseValListWillChangeTo(newBaseValue); } // We don't need to call DidChange* here - we're only called by // nsSVGElement::ParseAttribute under nsGenericElement::SetAttr, // which takes care of notifying. rv = mBaseVal.CopyFrom(newBaseValue); if (NS_FAILED(rv) && domWrapper) { // Attempting to increase mBaseVal's length failed - reduce domWrapper // back to the same length: domWrapper->InternalBaseValListWillChangeTo(mBaseVal); } return rv; }
JSValue* JSSVGLengthList::getValueProperty(ExecState* exec, int token) const { switch (token) { case NumberOfItemsAttrNum: { SVGLengthList* imp = static_cast<SVGLengthList*>(impl()); return jsNumber(imp->numberOfItems()); } } return 0; }
void SVGLengthList::add(SVGPropertyBase* other, SVGElement* contextElement) { SVGLengthList* otherList = toSVGLengthList(other); if (length() != otherList->length()) return; SVGLengthContext lengthContext(contextElement); for (size_t i = 0; i < length(); ++i) at(i)->setValue( at(i)->value(lengthContext) + otherList->at(i)->value(lengthContext), lengthContext); }
static inline void extractFloatValuesFromSVGLengthList(SVGElement* lengthContext, const SVGLengthList& list, Vector<float>& floatValues, unsigned textContentLength) { ASSERT(lengthContext); unsigned length = list.size(); if (length > textContentLength) length = textContentLength; floatValues.reserveCapacity(length); for (unsigned i = 0; i < length; ++i) { const SVGLength& length = list.at(i); floatValues.append(length.value(lengthContext)); } }
void DOMSVGAnimatedLengthList::InternalAnimValListWillChangeTo(const SVGLengthList& aNewValue) { if (mAnimVal) { mAnimVal->InternalListLengthWillChange(aNewValue.Length()); } }
nsresult SVGLengthList::CopyFrom(const SVGLengthList& rhs) { if (!mLengths.SetCapacity(rhs.Length())) { // Yes, we do want fallible alloc here return NS_ERROR_OUT_OF_MEMORY; } mLengths = rhs.mLengths; return NS_OK; }
bool SVGLengthList::operator==(const SVGLengthList& rhs) const { if (Length() != rhs.Length()) { return false; } for (uint32_t i = 0; i < Length(); ++i) { if (!(mLengths[i] == rhs.mLengths[i])) { return false; } } return true; }
nsresult SVGLengthList::SetValueFromString(const nsAString& aValue) { SVGLengthList temp; nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tokenizer( aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); while (tokenizer.hasMoreTokens()) { SVGLength length; if (!length.SetValueFromString(tokenizer.nextToken())) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(length)) { return NS_ERROR_OUT_OF_MEMORY; } } if (tokenizer.separatorAfterCurrentToken()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } return CopyFrom(temp); }
PRBool SVGLengthList::operator==(const SVGLengthList& rhs) const { if (Length() != rhs.Length()) { return PR_FALSE; } for (PRUint32 i = 0; i < Length(); ++i) { if (!(mLengths[i] == rhs.mLengths[i])) { return PR_FALSE; } } return PR_TRUE; }
void SVGAnimatedLengthListAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated) { ASSERT(m_animationElement); ASSERT(m_contextElement); SVGLengthList fromLengthList = m_animationElement->animationMode() == ToAnimation ? animated->lengthList() : from->lengthList(); SVGLengthList toLengthList = to->lengthList(); const SVGLengthList& toAtEndOfDurationLengthList = toAtEndOfDuration->lengthList(); SVGLengthList& animatedLengthList = animated->lengthList(); // Apply CSS inheritance rules. m_animationElement->adjustForInheritance<SVGLengthList>(parseLengthListFromString, m_animationElement->fromPropertyValueType(), fromLengthList, m_contextElement); m_animationElement->adjustForInheritance<SVGLengthList>(parseLengthListFromString, m_animationElement->toPropertyValueType(), toLengthList, m_contextElement); if (!m_animationElement->adjustFromToListValues<SVGLengthList>(fromLengthList, toLengthList, animatedLengthList, percentage)) return; unsigned fromLengthListSize = fromLengthList.size(); unsigned toLengthListSize = toLengthList.size(); unsigned toAtEndOfDurationListSize = toAtEndOfDurationLengthList.size(); SVGLengthContext lengthContext(m_contextElement); for (unsigned i = 0; i < toLengthListSize; ++i) { float animatedNumber = animatedLengthList[i].value(lengthContext); SVGLengthType unitType = toLengthList[i].unitType(); float effectiveFrom = 0; if (fromLengthListSize) { if (percentage < 0.5) unitType = fromLengthList[i].unitType(); effectiveFrom = fromLengthList[i].value(lengthContext); } float effectiveToAtEnd = i < toAtEndOfDurationListSize ? toAtEndOfDurationLengthList[i].value(lengthContext) : 0; m_animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom, toLengthList[i].value(lengthContext), effectiveToAtEnd, animatedNumber); animatedLengthList[i].setValue(lengthContext, animatedNumber, m_lengthMode, unitType, ASSERT_NO_EXCEPTION); } }
JSValue JSC_HOST_CALL jsSVGLengthListPrototypeFunctionAppendItem(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UNUSED_PARAM(args); if (!thisValue.inherits(&JSSVGLengthList::s_info)) return throwError(exec, TypeError); JSSVGLengthList* castedThisObj = static_cast<JSSVGLengthList*>(asObject(thisValue)); SVGLengthList* imp = static_cast<SVGLengthList*>(castedThisObj->impl()); ExceptionCode ec = 0; SVGLength item = toSVGLength(args.at(0)); JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<SVGLength>::create(imp->appendItem(item, ec)).get(), castedThisObj->context()); setDOMException(exec, ec); return result; }
nsresult SVGLengthList::SetValueFromString(const nsAString& aValue) { SVGLengthList temp; nsCharSeparatedTokenizerTemplate<IsSVGWhitespace> tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); nsCAutoString str; // outside loop to minimize memory churn while (tokenizer.hasMoreTokens()) { SVGLength length; if (!length.SetValueFromString(tokenizer.nextToken())) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(length)) { return NS_ERROR_OUT_OF_MEMORY; } } if (tokenizer.lastTokenEndedWithSeparator()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } return CopyFrom(temp); }
void DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& aNewValue) { // When the number of items in our internal counterpart's baseVal changes, // we MUST keep our baseVal in sync. If we don't, script will either see a // list that is too short and be unable to access indexes that should be // valid, or else, MUCH WORSE, script will see a list that is too long and be // able to access "items" at indexes that are out of bounds (read/write to // bad memory)!! if (mBaseVal) { mBaseVal->InternalListLengthWillChange(aNewValue.Length()); } // If our attribute is not animating, then our animVal mirrors our baseVal // and we must sync its length too. (If our attribute is animating, then the // SMIL engine takes care of calling InternalAnimValListWillChangeTo() if // necessary.) if (!IsAnimating()) { InternalAnimValListWillChangeTo(aNewValue); } }
SVGLengthList* SVGLengthList::clone() { SVGLengthList* ret = SVGLengthList::create(m_mode); ret->deepCopy(this); return ret; }
static SVGLengthList parseLengthListFromString(SVGAnimationElement* animationElement, const String& string) { SVGLengthList lengthList; lengthList.parse(string, SVGLength::lengthModeForAnimatedLengthAttribute(animationElement->attributeName())); return lengthList; }
SVGPropertyBase* SVGLengthList::cloneForAnimation(const String& value) const { SVGLengthList* ret = SVGLengthList::create(m_mode); ret->setValueAsString(value); return ret; }
void SVGLengthList::calculateAnimatedValue( SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, SVGPropertyBase* fromValue, SVGPropertyBase* toValue, SVGPropertyBase* toAtEndOfDurationValue, SVGElement* contextElement) { SVGLengthList* fromList = toSVGLengthList(fromValue); SVGLengthList* toList = toSVGLengthList(toValue); SVGLengthList* toAtEndOfDurationList = toSVGLengthList(toAtEndOfDurationValue); SVGLengthContext lengthContext(contextElement); ASSERT(m_mode == SVGLength::lengthModeForAnimatedLengthAttribute( animationElement->attributeName())); size_t fromLengthListSize = fromList->length(); size_t toLengthListSize = toList->length(); size_t toAtEndOfDurationListSize = toAtEndOfDurationList->length(); if (!adjustFromToListValues(fromList, toList, percentage, animationElement->getAnimationMode())) return; for (size_t i = 0; i < toLengthListSize; ++i) { // TODO(shanmuga.m): Support calc for SVGLengthList animation float animatedNumber = at(i)->value(lengthContext); CSSPrimitiveValue::UnitType unitType = toList->at(i)->typeWithCalcResolved(); float effectiveFrom = 0; if (fromLengthListSize) { if (percentage < 0.5) unitType = fromList->at(i)->typeWithCalcResolved(); effectiveFrom = fromList->at(i)->value(lengthContext); } float effectiveTo = toList->at(i)->value(lengthContext); float effectiveToAtEnd = i < toAtEndOfDurationListSize ? toAtEndOfDurationList->at(i)->value(lengthContext) : 0; animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom, effectiveTo, effectiveToAtEnd, animatedNumber); at(i)->setUnitType(unitType); at(i)->setValue(animatedNumber, lengthContext); } }
void SVGTextPositioningElement::parseMappedAttribute(Attribute* attr) { if (attr->name() == SVGNames::xAttr) { SVGLengthList newList; newList.parse(attr->value(), LengthModeWidth); detachAnimatedXListWrappers(newList.size()); setXBaseValue(newList); } else if (attr->name() == SVGNames::yAttr) { SVGLengthList newList; newList.parse(attr->value(), LengthModeHeight); detachAnimatedYListWrappers(newList.size()); setYBaseValue(newList); } else if (attr->name() == SVGNames::dxAttr) { SVGLengthList newList; newList.parse(attr->value(), LengthModeWidth); detachAnimatedDxListWrappers(newList.size()); setDxBaseValue(newList); } else if (attr->name() == SVGNames::dyAttr) { SVGLengthList newList; newList.parse(attr->value(), LengthModeHeight); detachAnimatedDyListWrappers(newList.size()); setDyBaseValue(newList); } else if (attr->name() == SVGNames::rotateAttr) { SVGNumberList newList; newList.parse(attr->value()); detachAnimatedRotateListWrappers(newList.size()); setRotateBaseValue(newList); } else SVGTextContentElement::parseMappedAttribute(attr); }
void SVGTextPositioningElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (!isSupportedAttribute(name)) { SVGTextContentElement::parseAttribute(name, value); return; } if (name == SVGNames::xAttr) { SVGLengthList newList; newList.parse(value, LengthModeWidth); detachAnimatedXListWrappers(newList.size()); setXBaseValue(newList); return; } if (name == SVGNames::yAttr) { SVGLengthList newList; newList.parse(value, LengthModeHeight); detachAnimatedYListWrappers(newList.size()); setYBaseValue(newList); return; } if (name == SVGNames::dxAttr) { SVGLengthList newList; newList.parse(value, LengthModeWidth); detachAnimatedDxListWrappers(newList.size()); setDxBaseValue(newList); return; } if (name == SVGNames::dyAttr) { SVGLengthList newList; newList.parse(value, LengthModeHeight); detachAnimatedDyListWrappers(newList.size()); setDyBaseValue(newList); return; } if (name == SVGNames::rotateAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedRotateListWrappers(newList.size()); setRotateBaseValue(newList); return; } ASSERT_NOT_REACHED(); }
JSValue* JSSVGLengthListPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) { if (!thisObj->inherits(&JSSVGLengthList::info)) return throwError(exec, TypeError); JSSVGLengthList* castedThisObj = static_cast<JSSVGLengthList*>(thisObj); SVGLengthList* imp = static_cast<SVGLengthList*>(castedThisObj->impl()); switch (id) { case JSSVGLengthList::ClearFuncNum: { ExceptionCode ec = 0; imp->clear(ec); setDOMException(exec, ec); return jsUndefined(); } case JSSVGLengthList::InitializeFuncNum: { ExceptionCode ec = 0; SVGLength item = toSVGLength(args[0]); KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->initialize(item, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } case JSSVGLengthList::GetItemFuncNum: { ExceptionCode ec = 0; bool indexOk; unsigned index = args[0]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->getItem(index, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } case JSSVGLengthList::InsertItemBeforeFuncNum: { ExceptionCode ec = 0; SVGLength item = toSVGLength(args[0]); bool indexOk; unsigned index = args[1]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->insertItemBefore(item, index, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } case JSSVGLengthList::ReplaceItemFuncNum: { ExceptionCode ec = 0; SVGLength item = toSVGLength(args[0]); bool indexOk; unsigned index = args[1]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->replaceItem(item, index, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } case JSSVGLengthList::RemoveItemFuncNum: { ExceptionCode ec = 0; bool indexOk; unsigned index = args[0]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, TYPE_MISMATCH_ERR); return jsUndefined(); } KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->removeItem(index, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } case JSSVGLengthList::AppendItemFuncNum: { ExceptionCode ec = 0; SVGLength item = toSVGLength(args[0]); KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapperCreatorReadOnly<SVGLength>(imp->appendItem(item, ec)), castedThisObj->context()); setDOMException(exec, ec); return result; } } return 0; }