void SVGComponentTransferFunctionElement::parseMappedAttribute(Attribute* attr) { const String& value = attr->value(); if (attr->name() == SVGNames::typeAttr) { if (value == "identity") setTypeBaseValue(FECOMPONENTTRANSFER_TYPE_IDENTITY); else if (value == "table") setTypeBaseValue(FECOMPONENTTRANSFER_TYPE_TABLE); else if (value == "discrete") setTypeBaseValue(FECOMPONENTTRANSFER_TYPE_DISCRETE); else if (value == "linear") setTypeBaseValue(FECOMPONENTTRANSFER_TYPE_LINEAR); else if (value == "gamma") setTypeBaseValue(FECOMPONENTTRANSFER_TYPE_GAMMA); } else if (attr->name() == SVGNames::tableValuesAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedTableValuesListWrappers(newList.size()); setTableValuesBaseValue(newList); } else if (attr->name() == SVGNames::slopeAttr) setSlopeBaseValue(value.toFloat()); else if (attr->name() == SVGNames::interceptAttr) setInterceptBaseValue(value.toFloat()); else if (attr->name() == SVGNames::amplitudeAttr) setAmplitudeBaseValue(value.toFloat()); else if (attr->name() == SVGNames::exponentAttr) setExponentBaseValue(value.toFloat()); else if (attr->name() == SVGNames::offsetAttr) setOffsetBaseValue(value.toFloat()); else SVGElement::parseMappedAttribute(attr); }
void SVGFEColorMatrixElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (!isSupportedAttribute(name)) { SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); return; } if (name == SVGNames::typeAttr) { ColorMatrixType propertyValue = SVGPropertyTraits<ColorMatrixType>::fromString(value); if (propertyValue > 0) setTypeBaseValue(propertyValue); return; } if (name == SVGNames::inAttr) { setIn1BaseValue(value); return; } if (name == SVGNames::valuesAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedValuesListWrappers(newList.size()); setValuesBaseValue(newList); return; } ASSERT_NOT_REACHED(); }
void DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo(const SVGNumberList& 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)!! RefPtr<DOMSVGAnimatedNumberList> kungFuDeathGrip; if (mBaseVal) { if (aNewValue.Length() < mBaseVal->LengthNoFlush()) { // 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 SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue) { SVGNumberList newBaseValue; nsresult rv = newBaseValue.SetValueFromString(aValue); if (NS_FAILED(rv)) { return rv; } DOMSVGAnimatedNumberList *domWrapper = DOMSVGAnimatedNumberList::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 Element::SetAttr, // which takes care of notifying. mIsBaseSet = true; 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; }
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); }
nsresult SVGNumberList::SetValueFromString(const nsAString& aValue) { SVGNumberList temp; nsCharSeparatedTokenizerTemplate<IsSVGWhitespace> tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); nsAutoCString str; // outside loop to minimize memory churn while (tokenizer.hasMoreTokens()) { CopyUTF16toUTF8(tokenizer.nextToken(), str); // NS_ConvertUTF16toUTF8 const char *token = str.get(); if (*token == '\0') { return NS_ERROR_DOM_SYNTAX_ERR; // nothing between commas } char *end; float num = float(PR_strtod(token, &end)); if (*end != '\0' || !NS_finite(num)) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(num)) { return NS_ERROR_OUT_OF_MEMORY; } } if (tokenizer.lastTokenEndedWithSeparator()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } return CopyFrom(temp); }
SVGPropertyBase* SVGNumberListInterpolationType::appliedSVGValue( const InterpolableValue& interpolableValue, const NonInterpolableValue*) const { SVGNumberList* result = SVGNumberList::create(); const InterpolableList& list = toInterpolableList(interpolableValue); for (size_t i = 0; i < list.length(); i++) result->append( SVGNumber::create(toInterpolableNumber(list.get(i))->value())); return result; }
static inline void extractFloatValuesFromSVGNumberList(const SVGNumberList& list, Vector<float>& floatValues, unsigned textContentLength) { unsigned length = list.size(); if (length > textContentLength) length = textContentLength; floatValues.reserveCapacity(length); for (unsigned i = 0; i < length; ++i) floatValues.append(list.at(i)); }
void SVGNumberList::add(SVGPropertyBase* other, SVGElement* contextElement) { SVGNumberList* otherList = toSVGNumberList(other); if (length() != otherList->length()) return; for (size_t i = 0; i < length(); ++i) at(i)->setValue(at(i)->value() + otherList->at(i)->value()); }
PassRefPtr<FilterEffect> SVGFEConvolveMatrixElement::build(SVGFilterBuilder* filterBuilder) { FilterEffect* input1 = filterBuilder->getEffectById(in1()); if (!input1) return 0; Vector<float> kernelMatrixValues; SVGNumberList* numbers = kernelMatrix(); ExceptionCode ec = 0; int numberOfItems = numbers->numberOfItems(); for (int i = 0; i < numberOfItems; ++i) kernelMatrixValues.append(numbers->getItem(i, ec)); int orderXValue = orderX(); int orderYValue = orderY(); if (!hasAttribute(SVGNames::orderAttr)) { orderXValue = 3; orderYValue = 3; } // The spec says this is a requirement, and should bail out if fails if (orderXValue * orderYValue != numberOfItems) return 0; int targetXValue = targetX(); int targetYValue = targetY(); if (hasAttribute(SVGNames::targetXAttr) && (targetXValue < 0 || targetXValue >= orderXValue)) return 0; // The spec says the default value is: targetX = floor ( orderX / 2 )) if (!hasAttribute(SVGNames::targetXAttr)) targetXValue = static_cast<int>(floorf(orderXValue / 2)); if (hasAttribute(SVGNames::targetYAttr) && (targetYValue < 0 || targetYValue >= orderYValue)) return 0; // The spec says the default value is: targetY = floor ( orderY / 2 )) if (!hasAttribute(SVGNames::targetYAttr)) targetYValue = static_cast<int>(floorf(orderYValue / 2)); float divisorValue = divisor(); if (hasAttribute(SVGNames::divisorAttr) && !divisorValue) return 0; if (!hasAttribute(SVGNames::divisorAttr)) { for (int i = 0; i < numberOfItems; ++i) divisorValue += kernelMatrixValues[i]; if (!divisorValue) divisorValue = 1; } RefPtr<FilterEffect> effect = FEConvolveMatrix::create( IntSize(orderXValue, orderYValue), divisorValue, bias(), IntPoint(targetXValue, targetYValue), static_cast<EdgeModeType>(edgeMode()), FloatPoint(kernelUnitLengthX(), kernelUnitLengthX()), preserveAlpha(), kernelMatrixValues); effect->inputEffects().append(input1); return effect.release(); }
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(); }
void DOMSVGAnimatedNumberList::InternalAnimValListWillChangeTo(const SVGNumberList& aNewValue) { if (mAnimVal) { mAnimVal->InternalListLengthWillChange(aNewValue.Length()); } }
bool SVGFEColorMatrixElement::build(SVGResourceFilter* filterResource) { FilterEffect* input1 = filterResource->builder()->getEffectById(in1()); if (!input1) return false; Vector<float> filterValues; SVGNumberList* numbers = values(); const ColorMatrixType filterType(static_cast<const ColorMatrixType>(type())); // Use defaults if values is empty (SVG 1.1 15.10). if (!hasAttribute(SVGNames::valuesAttr)) { switch (filterType) { case FECOLORMATRIX_TYPE_MATRIX: for (size_t i = 0; i < 20; i++) filterValues.append((i % 6) ? 0.0f : 1.0f); break; case FECOLORMATRIX_TYPE_HUEROTATE: filterValues.append(0.0f); break; case FECOLORMATRIX_TYPE_SATURATE: filterValues.append(1.0f); break; default: break; } } else { size_t size = numbers->numberOfItems(); for (size_t i = 0; i < size; i++) { ExceptionCode ec = 0; filterValues.append(numbers->getItem(i, ec)); } size = filterValues.size(); if ((filterType == FECOLORMATRIX_TYPE_MATRIX && size != 20) || (filterType == FECOLORMATRIX_TYPE_HUEROTATE && size != 1) || (filterType == FECOLORMATRIX_TYPE_SATURATE && (size != 1 || filterValues[0] < 0.0f || filterValues[0] > 1.0f))) return false; } RefPtr<FilterEffect> effect = FEColorMatrix::create(input1, filterType, filterValues); filterResource->addFilterEffect(this, effect.release()); return true; }
ComponentTransferFunction SVGComponentTransferFunctionElement::transferFunction() const { ComponentTransferFunction func; func.type = (ComponentTransferType) type(); func.slope = slope(); func.intercept = intercept(); func.amplitude = amplitude(); func.exponent = exponent(); func.offset = offset(); SVGNumberList* numbers = tableValues(); ExceptionCode ec = 0; unsigned int nr = numbers->numberOfItems(); for (unsigned int i = 0; i < nr; i++) func.tableValues.append(numbers->getItem(i, ec)); return func; }
void SVGFEConvolveMatrixElement::parseMappedAttribute(Attribute* attr) { const String& value = attr->value(); if (attr->name() == SVGNames::inAttr) setIn1BaseValue(value); else if (attr->name() == SVGNames::orderAttr) { float x, y; if (parseNumberOptionalNumber(value, x, y)) { setOrderXBaseValue(x); setOrderYBaseValue(y); } } else if (attr->name() == SVGNames::edgeModeAttr) { if (value == "duplicate") setEdgeModeBaseValue(EDGEMODE_DUPLICATE); else if (value == "wrap") setEdgeModeBaseValue(EDGEMODE_WRAP); else if (value == "none") setEdgeModeBaseValue(EDGEMODE_NONE); } else if (attr->name() == SVGNames::kernelMatrixAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedKernelMatrixListWrappers(newList.size()); kernelMatrixBaseValue() = newList; } else if (attr->name() == SVGNames::divisorAttr) setDivisorBaseValue(value.toFloat()); else if (attr->name() == SVGNames::biasAttr) setBiasBaseValue(value.toFloat()); else if (attr->name() == SVGNames::targetXAttr) setTargetXBaseValue(value.toUIntStrict()); else if (attr->name() == SVGNames::targetYAttr) setTargetYBaseValue(value.toUIntStrict()); else if (attr->name() == SVGNames::kernelUnitLengthAttr) { float x, y; if (parseNumberOptionalNumber(value, x, y)) { setKernelUnitLengthXBaseValue(x); setKernelUnitLengthYBaseValue(y); } } else if (attr->name() == SVGNames::preserveAlphaAttr) { if (value == "true") setPreserveAlphaBaseValue(true); else if (value == "false") setPreserveAlphaBaseValue(false); } else SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr); }
nsresult SVGNumberList::CopyFrom(const SVGNumberList& rhs) { if (!mNumbers.SetCapacity(rhs.Length())) { // Yes, we do want fallible alloc here return NS_ERROR_OUT_OF_MEMORY; } mNumbers = rhs.mNumbers; return NS_OK; }
bool SVGFEColorMatrixElement::build(FilterBuilder* builder) { FilterEffect* input1 = builder->getEffectById(in1()); if(!input1) return false; Vector<float> _values; SVGNumberList* numbers = values(); ExceptionCode ec = 0; unsigned int nr = numbers->numberOfItems(); for (unsigned int i = 0;i < nr;i++) _values.append(numbers->getItem(i, ec)); builder->add(result(), FEColorMatrix::create(input1, static_cast<ColorMatrixType> (type()), _values)); return true; }
void SVGFEColorMatrixElement::parseMappedAttribute(Attribute* attr) { const String& value = attr->value(); if (attr->name() == SVGNames::typeAttr) { if (value == "matrix") setTypeBaseValue(FECOLORMATRIX_TYPE_MATRIX); else if (value == "saturate") setTypeBaseValue(FECOLORMATRIX_TYPE_SATURATE); else if (value == "hueRotate") setTypeBaseValue(FECOLORMATRIX_TYPE_HUEROTATE); else if (value == "luminanceToAlpha") setTypeBaseValue(FECOLORMATRIX_TYPE_LUMINANCETOALPHA); } else if (attr->name() == SVGNames::inAttr) setIn1BaseValue(value); else if (attr->name() == SVGNames::valuesAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedValuesListWrappers(newList.size()); setValuesBaseValue(newList); } else SVGFilterPrimitiveStandardAttributes::parseMappedAttribute(attr); }
nsresult SVGNumberList::SetValueFromString(const nsAString& aValue) { SVGNumberList temp; nsCharSeparatedTokenizerTemplate<IsSVGWhitespace> tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); while (tokenizer.hasMoreTokens()) { float num; if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), num)) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(num)) { return NS_ERROR_OUT_OF_MEMORY; } } if (tokenizer.separatorAfterCurrentToken()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } return CopyFrom(temp); }
void SVGNumberList::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, SVGPropertyBase* fromValue, SVGPropertyBase* toValue, SVGPropertyBase* toAtEndOfDurationValue, SVGElement* contextElement) { SVGNumberList* fromList = toSVGNumberList(fromValue); SVGNumberList* toList = toSVGNumberList(toValue); SVGNumberList* toAtEndOfDurationList = toSVGNumberList(toAtEndOfDurationValue); size_t fromListSize = fromList->length(); size_t toListSize = toList->length(); size_t toAtEndOfDurationListSize = toAtEndOfDurationList->length(); if (!adjustFromToListValues(fromList, toList, percentage, animationElement->getAnimationMode())) return; for (size_t i = 0; i < toListSize; ++i) { float effectiveFrom = fromListSize ? fromList->at(i)->value() : 0; float effectiveTo = toListSize ? toList->at(i)->value() : 0; float effectiveToAtEnd = i < toAtEndOfDurationListSize ? toAtEndOfDurationList->at(i)->value() : 0; float animated = at(i)->value(); animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom, effectiveTo, effectiveToAtEnd, animated); at(i)->setValue(animated); } }
void SVGFEConvolveMatrixElement::parseAttribute(const QualifiedName& name, const AtomicString& value) { if (!isSupportedAttribute(name)) { SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value); return; } if (name == SVGNames::inAttr) { setIn1BaseValue(value); return; } if (name == SVGNames::orderAttr) { float x, y; if (parseNumberOptionalNumber(value, x, y) && x >= 1 && y >= 1) { setOrderXBaseValue(x); setOrderYBaseValue(y); } else document().accessSVGExtensions()->reportWarning( "feConvolveMatrix: problem parsing order=\"" + value + "\". Filtered element will not be displayed."); return; } if (name == SVGNames::edgeModeAttr) { EdgeModeType propertyValue = SVGPropertyTraits<EdgeModeType>::fromString(value); if (propertyValue > 0) setEdgeModeBaseValue(propertyValue); else document().accessSVGExtensions()->reportWarning( "feConvolveMatrix: problem parsing edgeMode=\"" + value + "\". Filtered element will not be displayed."); return; } if (name == SVGNames::kernelMatrixAttr) { SVGNumberList newList; newList.parse(value); detachAnimatedKernelMatrixListWrappers(newList.size()); setKernelMatrixBaseValue(newList); return; } if (name == SVGNames::divisorAttr) { float divisor = value.toFloat(); if (divisor) setDivisorBaseValue(divisor); else document().accessSVGExtensions()->reportWarning( "feConvolveMatrix: problem parsing divisor=\"" + value + "\". Filtered element will not be displayed."); return; } if (name == SVGNames::biasAttr) { setBiasBaseValue(value.toFloat()); return; } if (name == SVGNames::targetXAttr) { setTargetXBaseValue(value.string().toUIntStrict()); return; } if (name == SVGNames::targetYAttr) { setTargetYBaseValue(value.string().toUIntStrict()); return; } if (name == SVGNames::kernelUnitLengthAttr) { float x, y; if (parseNumberOptionalNumber(value, x, y) && x > 0 && y > 0) { setKernelUnitLengthXBaseValue(x); setKernelUnitLengthYBaseValue(y); } else document().accessSVGExtensions()->reportWarning( "feConvolveMatrix: problem parsing kernelUnitLength=\"" + value + "\". Filtered element will not be displayed."); return; } if (name == SVGNames::preserveAlphaAttr) { if (value == "true") setPreserveAlphaBaseValue(true); else if (value == "false") setPreserveAlphaBaseValue(false); else document().accessSVGExtensions()->reportWarning( "feConvolveMatrix: problem parsing preserveAlphaAttr=\"" + value + "\". Filtered element will not be displayed."); return; } ASSERT_NOT_REACHED(); }