void SVGMotionSMILAnimationFunction::RebuildPathAndVerticesFromPathAttr() { const nsAString& pathSpec = GetAttr(nsGkAtoms::path)->GetStringValue(); mPathSourceType = ePathSourceType_PathAttr; // Generate Path from |path| attr SVGPathData path; nsSVGPathDataParser pathParser(pathSpec, &path); // We ignore any failure returned from Parse() since the SVG spec says to // accept all segments up to the first invalid token. Instead we must // explicitly check that the parse produces at least one path segment (if // the path data doesn't begin with a valid "M", then it's invalid). pathParser.Parse(); if (!path.Length()) { return; } mPath = path.ToPathForLengthOrPositionMeasuring(); bool ok = path.GetDistancesFromOriginToEndsOfVisibleSegments(&mPathVertices); if (!ok || !mPathVertices.Length()) { mPath = nullptr; } }
RefPtr<gfx::Path> SVGContentUtils::GetPath(const nsAString& aPathString) { SVGPathData pathData; nsSVGPathDataParser parser(aPathString, &pathData); if (!parser.Parse()) { return NULL; } return pathData.BuildPath(mozilla::gfx::FillRule::FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 1); }
nsresult SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue) { SVGPathData newBaseValue; // The spec says that the path data is parsed and accepted up to the first // error encountered, so we don't return early if an error occurs. However, // we do want to throw any error code from setAttribute if there's a problem. nsresult rv = newBaseValue.SetValueFromString(aValue); // We must send these notifications *before* changing mBaseVal! 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's values *before* we // change them. See the comments in // DOMSVGPathSegList::InternalListWillChangeTo(). DOMSVGPathSegList *baseValWrapper = DOMSVGPathSegList::GetDOMWrapperIfExists(GetBaseValKey()); if (baseValWrapper) { baseValWrapper->InternalListWillChangeTo(newBaseValue); } DOMSVGPathSegList* animValWrapper = nullptr; if (!IsAnimating()) { // DOM anim val wraps our base val too! animValWrapper = DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey()); if (animValWrapper) { animValWrapper->InternalListWillChangeTo(newBaseValue); } } // Only now may we modify mBaseVal! // We don't need to call DidChange* here - we're only called by // nsSVGElement::ParseAttribute under Element::SetAttr, // which takes care of notifying. nsresult rv2 = mBaseVal.CopyFrom(newBaseValue); if (NS_FAILED(rv2)) { // Attempting to increase mBaseVal's length failed (mBaseVal is left // unmodified). We MUST keep any DOM wrappers in sync: if (baseValWrapper) { baseValWrapper->InternalListWillChangeTo(mBaseVal); } if (animValWrapper) { animValWrapper->InternalListWillChangeTo(mBaseVal); } return rv2; } return rv; }
TemporaryRef<gfx::Path> SVGContentUtils::GetPath(const nsAString& aPathString) { SVGPathData pathData; nsSVGPathDataParser parser(aPathString, &pathData); if (!parser.Parse()) { return NULL; } RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(); RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder(FillRule::FILL_WINDING); return pathData.BuildPath(builder, NS_STYLE_STROKE_LINECAP_BUTT, 1); }