bool SVGTransformable::parseTransformAttribute(SVGTransformList& list, const UChar*& currTransform, const UChar* end, TransformParsingMode mode) { if (mode == ClearList) list.clear(); bool delimParsed = false; while (currTransform < end) { delimParsed = false; SVGTransform::SVGTransformType type = SVGTransform::SVG_TRANSFORM_UNKNOWN; skipOptionalSVGSpaces(currTransform, end); if (!parseAndSkipType(currTransform, end, type)) return false; SVGTransform transform; if (!parseTransformValue(type, currTransform, end, transform)) return false; list.append(transform); skipOptionalSVGSpaces(currTransform, end); if (currTransform < end && *currTransform == ',') { delimParsed = true; ++currTransform; } skipOptionalSVGSpaces(currTransform, end); } return !delimParsed; }
nsresult SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) { SVGTransformList newBaseValue; nsresult rv = newBaseValue.SetValueFromString(aValue); if (NS_FAILED(rv)) { return rv; } DOMSVGAnimatedTransformList *domWrapper = DOMSVGAnimatedTransformList::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->InternalBaseValListWillChangeLengthTo(newBaseValue.Length()); } // We don't need to call DidChange* here - we're only called by // nsSVGElement::ParseAttribute under Element::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->InternalBaseValListWillChangeLengthTo(mBaseVal.Length()); } else { mIsAttrSet = true; } return rv; }
JSValue* JSSVGTransformList::insertItemBefore(ExecState* exec, const List& args) { ExceptionCode ec = 0; SVGTransform newItem = toSVGTransform(args[0]); bool indexOk; unsigned index = args[1]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, DOMException::TYPE_MISMATCH_ERR); return jsUndefined(); } SVGTransformList* imp = static_cast<SVGTransformList*>(impl()); SVGList<RefPtr<SVGPODListItem<SVGTransform> > >* listImp = imp; SVGPODListItem<SVGTransform>* listItem = listImp->insertItemBefore(SVGPODListItem<SVGTransform>::copy(newItem), index, ec).get(); JSSVGPODTypeWrapperCreatorForList<SVGTransform>* obj = new JSSVGPODTypeWrapperCreatorForList<SVGTransform>(listItem, imp->associatedAttributeName()); KJS::JSValue* result = toJS(exec, obj, m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); return result; }
void SVGGradientElement::parseMappedAttribute(Attribute* attr) { if (attr->name() == SVGNames::gradientUnitsAttr) { if (attr->value() == "userSpaceOnUse") setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE); else if (attr->value() == "objectBoundingBox") setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); } else if (attr->name() == SVGNames::gradientTransformAttr) { SVGTransformList newList; if (!SVGTransformable::parseTransformAttribute(newList, attr->value())) newList.clear(); detachAnimatedGradientTransformListWrappers(newList.size()); setGradientTransformBaseValue(newList); } else if (attr->name() == SVGNames::spreadMethodAttr) { if (attr->value() == "reflect") setSpreadMethodBaseValue(SpreadMethodReflect); else if (attr->value() == "repeat") setSpreadMethodBaseValue(SpreadMethodRepeat); else if (attr->value() == "pad") setSpreadMethodBaseValue(SpreadMethodPad); } else { if (SVGURIReference::parseMappedAttribute(attr)) return; if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; SVGStyledElement::parseMappedAttribute(attr); } }
void SVGGradientElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == SVGNames::gradientUnitsAttr) { if (attr->value() == "userSpaceOnUse") setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE); else if (attr->value() == "objectBoundingBox") setGradientUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); } else if (attr->name() == SVGNames::gradientTransformAttr) { SVGTransformList* gradientTransforms = gradientTransformBaseValue(); if (!SVGTransformable::parseTransformAttribute(gradientTransforms, attr->value())) { ExceptionCode ec = 0; gradientTransforms->clear(ec); } } else if (attr->name() == SVGNames::spreadMethodAttr) { if (attr->value() == "reflect") setSpreadMethodBaseValue(SpreadMethodReflect); else if (attr->value() == "repeat") setSpreadMethodBaseValue(SpreadMethodRepeat); else if (attr->value() == "pad") setSpreadMethodBaseValue(SpreadMethodPad); } else { if (SVGURIReference::parseMappedAttribute(attr)) return; if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; SVGStyledElement::parseMappedAttribute(attr); } }
void SVGGradientElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (name == SVGNames::gradientUnitsAttr) { auto propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); if (propertyValue > 0) setGradientUnitsBaseValue(propertyValue); return; } if (name == SVGNames::gradientTransformAttr) { SVGTransformList newList; newList.parse(value); detachAnimatedGradientTransformListWrappers(newList.size()); setGradientTransformBaseValue(newList); return; } if (name == SVGNames::spreadMethodAttr) { auto propertyValue = SVGPropertyTraits<SVGSpreadMethodType>::fromString(value); if (propertyValue > 0) setSpreadMethodBaseValue(propertyValue); return; } SVGElement::parseAttribute(name, value); SVGURIReference::parseAttribute(name, value); SVGExternalResourcesRequired::parseAttribute(name, value); }
void SVGTextElement::parseMappedAttribute(MappedAttribute *attr) { if (attr->name() == SVGNames::transformAttr) { SVGTransformList *localTransforms = transform()->baseVal(); localTransforms->clear(); SVGTransformable::parseTransformAttribute(localTransforms, attr->value()); updateLocalTransform(localTransforms); } else SVGTextPositioningElement::parseMappedAttribute(attr); }
JSValue* JSSVGTransformList::getValueProperty(ExecState* exec, int token) const { switch (token) { case NumberOfItemsAttrNum: { SVGTransformList* imp = static_cast<SVGTransformList*>(impl()); return jsNumber(imp->numberOfItems()); } } return 0; }
nsresult nsSVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) { SVGTransformList newBaseValue; nsresult rv = newBaseValue.SetValueFromString(aValue); if (NS_FAILED(rv)) { return rv; } return SetBaseValue(newBaseValue); }
void SVGStyledTransformableElement::parseMappedAttribute(MappedAttribute* attr) { if (SVGTransformable::isKnownAttribute(attr->name())) { SVGTransformList* localTransforms = transformBaseValue(); if (!SVGTransformable::parseTransformAttribute(localTransforms, attr->value())) { ExceptionCode ec = 0; localTransforms->clear(ec); } } else SVGStyledLocatableElement::parseMappedAttribute(attr); }
void SVGStyledTransformableElement::parseMappedAttribute(Attribute* attr) { if (SVGTransformable::isKnownAttribute(attr->name())) { SVGTransformList newList; if (!SVGTransformable::parseTransformAttribute(newList, attr->value())) newList.clear(); detachAnimatedTransformListWrappers(newList.size()); setTransformBaseValue(newList); } else SVGStyledLocatableElement::parseMappedAttribute(attr); }
SVGPropertyBase* SVGTransformListInterpolationType::appliedSVGValue( const InterpolableValue& interpolableValue, const NonInterpolableValue* nonInterpolableValue) const { SVGTransformList* result = SVGTransformList::create(); const InterpolableList& list = toInterpolableList(interpolableValue); const Vector<SVGTransformType>& transformTypes = toSVGTransformNonInterpolableValue(nonInterpolableValue) ->transformTypes(); for (size_t i = 0; i < list.length(); ++i) result->append(fromInterpolableValue(*list.get(i), transformTypes.at(i))); return result; }
JSValue JSC_HOST_CALL jsSVGTransformListPrototypeFunctionConsolidate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UNUSED_PARAM(args); if (!thisValue.isObject(&JSSVGTransformList::s_info)) return throwError(exec, TypeError); JSSVGTransformList* castedThisObj = static_cast<JSSVGTransformList*>(asObject(thisValue)); SVGTransformList* imp = static_cast<SVGTransformList*>(castedThisObj->impl()); JSC::JSValue result = toJS(exec, JSSVGStaticPODTypeWrapper<SVGTransform>::create(imp->consolidate()).get(), castedThisObj->context()); return result; }
JSValue* JSSVGTransformList::clear(ExecState* exec, const List&) { ExceptionCode ec = 0; SVGTransformList* imp = static_cast<SVGTransformList*>(impl()); imp->clear(ec); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); return jsUndefined(); }
void SVGViewSpec::setTransformString(const String& transform) { if (!m_contextElement) return; SVGTransformList newList; newList.parse(transform); if (SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGElement, SVGAnimatedTransformList>(m_contextElement, transformPropertyInfo())) static_cast<SVGAnimatedTransformList*>(wrapper)->detachListWrappers(newList.size()); m_transform = newList; }
void SVGStyledTransformableElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == SVGNames::transformAttr) { SVGTransformList* localTransforms = transformBaseValue(); ExceptionCode ec = 0; localTransforms->clear(ec); if (!SVGTransformable::parseTransformAttribute(localTransforms, attr->value())) localTransforms->clear(ec); else setTransformBaseValue(localTransforms); } else SVGStyledLocatableElement::parseMappedAttribute(attr); }
void SVGPatternElement::parseMappedAttribute(Attribute* attr) { if (attr->name() == SVGNames::patternUnitsAttr) { if (attr->value() == "userSpaceOnUse") setPatternUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE); else if (attr->value() == "objectBoundingBox") setPatternUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); } else if (attr->name() == SVGNames::patternContentUnitsAttr) { if (attr->value() == "userSpaceOnUse") setPatternContentUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE); else if (attr->value() == "objectBoundingBox") setPatternContentUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX); } else if (attr->name() == SVGNames::patternTransformAttr) { SVGTransformList newList; if (!SVGTransformable::parseTransformAttribute(newList, attr->value())) newList.clear(); detachAnimatedPatternTransformListWrappers(newList.size()); setPatternTransformBaseValue(newList); } else if (attr->name() == SVGNames::xAttr) setXBaseValue(SVGLength(LengthModeWidth, attr->value())); else if (attr->name() == SVGNames::yAttr) setYBaseValue(SVGLength(LengthModeHeight, attr->value())); else if (attr->name() == SVGNames::widthAttr) { setWidthBaseValue(SVGLength(LengthModeWidth, attr->value())); if (widthBaseValue().value(this) < 0.0) document()->accessSVGExtensions()->reportError("A negative value for pattern attribute <width> is not allowed"); } else if (attr->name() == SVGNames::heightAttr) { setHeightBaseValue(SVGLength(LengthModeHeight, attr->value())); if (heightBaseValue().value(this) < 0.0) document()->accessSVGExtensions()->reportError("A negative value for pattern attribute <height> is not allowed"); } else { if (SVGURIReference::parseMappedAttribute(attr)) return; if (SVGTests::parseMappedAttribute(attr)) return; if (SVGLangSpace::parseMappedAttribute(attr)) return; if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; if (SVGFitToViewBox::parseMappedAttribute(document(), attr)) return; SVGStyledElement::parseMappedAttribute(attr); } }
AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const { AffineTransform ctm = SVGFitToViewBox::viewBoxToViewTransform( currentViewBoxRect(), currentPreserveAspectRatio(), viewWidth, viewHeight); if (!m_viewSpec) return ctm; SVGTransformList* transformList = m_viewSpec->transform(); if (transformList->isEmpty()) return ctm; AffineTransform transform; if (transformList->concatenate(transform)) ctm *= transform; return ctm; }
JSValue* JSSVGTransformList::initialize(ExecState* exec, const List& args) { ExceptionCode ec = 0; SVGTransform newItem = toSVGTransform(args[0]); SVGTransformList* imp = static_cast<SVGTransformList*>(impl()); SVGList<RefPtr<SVGPODListItem<SVGTransform> > >* listImp = imp; SVGPODListItem<SVGTransform>* listItem = listImp->initialize(SVGPODListItem<SVGTransform>::copy(newItem), ec).get(); JSSVGPODTypeWrapperCreatorForList<SVGTransform>* obj = new JSSVGPODTypeWrapperCreatorForList<SVGTransform>(listItem, imp->associatedAttributeName()); KJS::JSValue* result = toJS(exec, obj, m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); return result; }
void SVGTextElement::parseMappedAttribute(MappedAttribute* attr) { if (attr->name() == SVGNames::transformAttr) { SVGTransformList* localTransforms = transformBaseValue(); ExceptionCode ec = 0; localTransforms->clear(ec); if (!SVGTransformable::parseTransformAttribute(localTransforms, attr->value())) localTransforms->clear(ec); else { setTransformBaseValue(localTransforms); if (renderer()) renderer()->setNeedsLayout(true); // should be in setTransformBaseValue } } else SVGTextPositioningElement::parseMappedAttribute(attr); }
// static bool SVGTransformListSMILType::AppendTransforms(const SVGTransformList& aList, nsSMILValue& aValue) { NS_PRECONDITION(aValue.mType == &sSingleton, "Unexpected SMIL value type"); TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr); if (!transforms.SetCapacity(transforms.Length() + aList.Length())) return PR_FALSE; for (PRUint32 i = 0; i < aList.Length(); ++i) { // No need to check the return value below since we have already allocated // the necessary space transforms.AppendElement(SVGTransformSMILData(aList[i])); } return PR_TRUE; }
// static bool SVGTransformListSMILType::AppendTransforms(const SVGTransformList& aList, nsSMILValue& aValue) { NS_PRECONDITION(aValue.mType == Singleton(), "Unexpected SMIL value type"); TransformArray& transforms = *static_cast<TransformArray*>(aValue.mU.mPtr); if (!transforms.SetCapacity(transforms.Length() + aList.Length(), fallible)) return false; for (uint32_t i = 0; i < aList.Length(); ++i) { // No need to check the return value below since we have already allocated // the necessary space MOZ_ALWAYS_TRUE(transforms.AppendElement(SVGTransformSMILData(aList[i]), fallible)); } return true; }
void SVGGraphicsElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (!isSupportedAttribute(name)) { SVGElement::parseAttribute(name, value); return; } if (name == SVGNames::transformAttr) { SVGTransformList newList; newList.parse(value); detachAnimatedTransformListWrappers(newList.size()); setTransformBaseValue(newList); return; } if (SVGTests::parseAttribute(name, value)) return; ASSERT_NOT_REACHED(); }
void SVGPatternElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (name == SVGNames::patternUnitsAttr) { auto propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); if (propertyValue > 0) setPatternUnitsBaseValue(propertyValue); return; } if (name == SVGNames::patternContentUnitsAttr) { auto propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value); if (propertyValue > 0) setPatternContentUnitsBaseValue(propertyValue); return; } if (name == SVGNames::patternTransformAttr) { SVGTransformList newList; newList.parse(value); detachAnimatedPatternTransformListWrappers(newList.size()); setPatternTransformBaseValue(newList); return; } SVGParsingError parseError = NoError; if (name == SVGNames::xAttr) setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError)); else if (name == SVGNames::yAttr) setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError)); else if (name == SVGNames::widthAttr) setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths)); else if (name == SVGNames::heightAttr) setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths)); reportAttributeParsingError(parseError, name, value); SVGElement::parseAttribute(name, value); SVGURIReference::parseAttribute(name, value); SVGTests::parseAttribute(name, value); SVGExternalResourcesRequired::parseAttribute(name, value); SVGFitToViewBox::parseAttribute(this, name, value); }
JSValue* JSSVGTransformList::removeItem(ExecState* exec, const List& args) { ExceptionCode ec = 0; bool indexOk; unsigned index = args[0]->toInt32(exec, indexOk); if (!indexOk) { setDOMException(exec, DOMException::TYPE_MISMATCH_ERR); return jsUndefined(); } SVGTransformList* imp = static_cast<SVGTransformList*>(impl()); SVGList<RefPtr<SVGPODListItem<SVGTransform> > >* listImp = imp; RefPtr<SVGPODListItem<SVGTransform> > listItem(listImp->removeItem(index, ec)); JSSVGPODTypeWrapper<SVGTransform>* obj = new JSSVGPODTypeWrapperCreatorReadOnly<SVGTransform>(*listItem.get()); KJS::JSValue* result = toJS(exec, obj, m_context.get()); setDOMException(exec, ec); m_context->svgAttributeChanged(imp->associatedAttributeName()); return result; }
nsresult nsSVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue, nsSVGElement *aElement) { bool prevSet = HasTransform() || aElement->GetAnimateMotionTransform(); SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // A new animation may totally change the number of items in the animVal // list, replacing what was essentially a mirror of the baseVal list, or // else replacing and overriding an existing animation. When this happens // we must try and keep our animVal's DOM wrapper in sync (see the comment // in SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo). // // It's not possible for us to reliably distinguish between calls to this // method that are setting a new sample for an existing animation, and // calls that are setting the first sample of an animation that will // override an existing animation. Happily it's cheap to just blindly // notify our animVal's DOM wrapper of its internal counterpart's new value // each time this method is called, so that's what we do. // // Note that we must send this notification *before* setting or changing // mAnimVal! (See the comment in SetBaseValueString above.) // domWrapper->InternalAnimValListWillChangeLengthTo(aValue.Length()); } if (!mAnimVal) { mAnimVal = new SVGTransformList(); } nsresult rv = mAnimVal->CopyFrom(aValue); if (NS_FAILED(rv)) { // OOM. We clear the animation, and, importantly, ClearAnimValue() ensures // that mAnimVal and its DOM wrapper (if any) will have the same length! ClearAnimValue(aElement); return rv; } int32_t modType; if(prevSet) { modType = nsIDOMMutationEvent::MODIFICATION; } else { modType = nsIDOMMutationEvent::ADDITION; } aElement->DidAnimateTransformList(modType); return NS_OK; }
JSValue* JSSVGTransformListPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) { if (!thisObj->inherits(&JSSVGTransformList::info)) return throwError(exec, TypeError); SVGTransformList* imp = static_cast<SVGTransformList*>(static_cast<JSSVGTransformList*>(thisObj)->impl()); switch (id) { case JSSVGTransformList::ClearFuncNum: { ExceptionCode ec = 0; imp->clear(ec); setDOMException(exec, ec); return jsUndefined(); } case JSSVGTransformList::InitializeFuncNum: { ExceptionCode ec = 0; SVGTransform item = toSVGTransform(args[0]); KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapper<SVGTransform>(imp->initialize(item, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::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 JSSVGPODTypeWrapper<SVGTransform>(imp->getItem(index, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::InsertItemBeforeFuncNum: { ExceptionCode ec = 0; SVGTransform item = toSVGTransform(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 JSSVGPODTypeWrapper<SVGTransform>(imp->insertItemBefore(item, index, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::ReplaceItemFuncNum: { ExceptionCode ec = 0; SVGTransform item = toSVGTransform(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 JSSVGPODTypeWrapper<SVGTransform>(imp->replaceItem(item, index, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::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 JSSVGPODTypeWrapper<SVGTransform>(imp->removeItem(index, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::AppendItemFuncNum: { ExceptionCode ec = 0; SVGTransform item = toSVGTransform(args[0]); KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapper<SVGTransform>(imp->appendItem(item, ec))); setDOMException(exec, ec); return result; } case JSSVGTransformList::CreateSVGTransformFromMatrixFuncNum: { AffineTransform matrix = toSVGMatrix(args[0]); KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapper<SVGTransform>(imp->createSVGTransformFromMatrix(matrix))); return result; } case JSSVGTransformList::ConsolidateFuncNum: { KJS::JSValue* result = toJS(exec, new JSSVGPODTypeWrapper<SVGTransform>(imp->consolidate())); return result; } } return 0; }