Commit 3bb121da authored by fs's avatar fs Committed by Commit bot

SVGPath object "mutability" cleanup

Move addToSVGPathByteStream to SVGPath.cpp (the only place using it),
rename it to addPathByteStreams. Move the "regular" blending out into a
helper(blendPathByteStreams), and eliminate the redundant copy. Make the
functions more "functional" (return the result.)

Add a (private) setter for byte-stream data and use that to ensure
invalidation of the cached path. Also add an SVGPath::create(...)
accepting a SVGPathByteStream and use that in PathSVGInterpolation.

Inline mutableByteStream into the remaining user.

Review URL: https://codereview.chromium.org/1460253002

Cr-Commit-Position: refs/heads/master@{#361128}
parent 72ee18e7
......@@ -433,12 +433,12 @@ PassRefPtr<PathSVGInterpolation> PathSVGInterpolation::maybeCreate(SVGPropertyBa
PassRefPtrWillBeRawPtr<SVGPropertyBase> PathSVGInterpolation::fromInterpolableValue(const InterpolableValue& value, const Vector<SVGPathSegType>& pathSegTypes)
{
RefPtrWillBeRawPtr<SVGPath> result = SVGPath::create();
OwnPtr<SVGPathByteStream> pathByteStream = SVGPathByteStream::create();
InterpolatedPathSource source(toInterpolableList(value), pathSegTypes);
SVGPathByteStreamBuilder builder(result->mutableByteStream());
SVGPathByteStreamBuilder builder(*pathByteStream);
SVGPathParser parser(&source, &builder);
parser.parsePathDataFromSource(UnalteredParsing, false);
return result.release();
return SVGPath::create(pathByteStream.release());
}
PassRefPtrWillBeRawPtr<SVGPropertyBase> PathSVGInterpolation::interpolatedValue(SVGElement&) const
......
......@@ -36,6 +36,35 @@
namespace blink {
namespace {
PassOwnPtr<SVGPathByteStream> blendPathByteStreams(const SVGPathByteStream& fromStream, const SVGPathByteStream& toStream, float progress)
{
OwnPtr<SVGPathByteStream> resultStream = SVGPathByteStream::create();
SVGPathByteStreamBuilder builder(*resultStream);
SVGPathByteStreamSource fromSource(fromStream);
SVGPathByteStreamSource toSource(toStream);
SVGPathBlender blender(&fromSource, &toSource, &builder);
blender.blendAnimatedPath(progress);
return resultStream.release();
}
PassOwnPtr<SVGPathByteStream> addPathByteStreams(PassOwnPtr<SVGPathByteStream> fromStream, const SVGPathByteStream& byStream, unsigned repeatCount = 1)
{
if (fromStream->isEmpty() || byStream.isEmpty())
return fromStream;
OwnPtr<SVGPathByteStream> tempFromStream = fromStream;
OwnPtr<SVGPathByteStream> resultStream = SVGPathByteStream::create();
SVGPathByteStreamBuilder builder(*resultStream);
SVGPathByteStreamSource fromSource(*tempFromStream);
SVGPathByteStreamSource bySource(byStream);
SVGPathBlender blender(&fromSource, &bySource, &builder);
blender.addAnimatedPath(repeatCount);
return resultStream.release();
}
}
SVGPath::SVGPath()
: SVGPropertyBase(classType())
{
......@@ -63,7 +92,7 @@ const Path& SVGPath::path() const
PassRefPtrWillBeRawPtr<SVGPath> SVGPath::clone() const
{
return adoptRefWillBeNoop(new SVGPath(byteStream().copy()));
return SVGPath::create(byteStream().copy());
}
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGPath::cloneForAnimation(const String& value) const
......@@ -81,7 +110,7 @@ SVGPathByteStream& SVGPath::ensureByteStream()
return *m_byteStream.get();
}
void SVGPath::byteStreamWillChange()
void SVGPath::byteStreamChanged()
{
m_cachedPath.clear();
}
......@@ -91,12 +120,6 @@ const SVGPathByteStream& SVGPath::byteStream() const
return const_cast<SVGPath*>(this)->ensureByteStream();
}
SVGPathByteStream& SVGPath::mutableByteStream()
{
byteStreamWillChange();
return ensureByteStream();
}
String SVGPath::valueAsString() const
{
String string;
......@@ -106,17 +129,24 @@ String SVGPath::valueAsString() const
void SVGPath::setValueAsString(const String& string, ExceptionState& exceptionState)
{
if (!buildSVGPathByteStreamFromString(string, mutableByteStream(), UnalteredParsing))
if (!buildSVGPathByteStreamFromString(string, ensureByteStream(), UnalteredParsing))
exceptionState.throwDOMException(SyntaxError, "Problem parsing path \"" + string + "\"");
byteStreamChanged();
}
void SVGPath::setValueAsByteStream(PassOwnPtr<SVGPathByteStream> byteStream)
{
m_byteStream = byteStream;
byteStreamChanged();
}
void SVGPath::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement*)
{
RefPtrWillBeRawPtr<SVGPath> otherList = toSVGPath(other);
if (byteStream().size() != otherList->byteStream().size())
const SVGPathByteStream& otherPathByteStream = toSVGPath(other)->byteStream();
if (byteStream().size() != otherPathByteStream.size())
return;
addToSVGPathByteStream(mutableByteStream(), otherList->byteStream());
setValueAsByteStream(addPathByteStreams(m_byteStream.release(), otherPathByteStream));
}
void SVGPath::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtrWillBeRawPtr<SVGPropertyBase> fromValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*)
......@@ -124,56 +154,47 @@ void SVGPath::calculateAnimatedValue(SVGAnimationElement* animationElement, floa
ASSERT(animationElement);
bool isToAnimation = animationElement->animationMode() == ToAnimation;
const RefPtrWillBeRawPtr<SVGPath> from = toSVGPath(fromValue);
const RefPtrWillBeRawPtr<SVGPath> to = toSVGPath(toValue);
const RefPtrWillBeRawPtr<SVGPath> toAtEndOfDuration = toSVGPath(toAtEndOfDurationValue);
const SVGPathByteStream& toStream = to->byteStream();
const SVGPathByteStream* fromStream = &from->byteStream();
OwnPtr<SVGPathByteStream> copy;
// If no 'to' value is given, nothing to animate.
if (!toStream.size())
return;
const RefPtrWillBeRawPtr<SVGPath> from = toSVGPath(fromValue);
const SVGPathByteStream* fromStream = &from->byteStream();
OwnPtr<SVGPathByteStream> copy;
if (isToAnimation) {
copy = byteStream().copy();
fromStream = copy.get();
}
byteStreamWillChange();
// If the 'from' value is given and it's length doesn't match the 'to' value list length, fallback to a discrete animation.
if (fromStream->size() != toStream.size() && fromStream->size()) {
if (percentage < 0.5) {
if (!isToAnimation) {
m_byteStream = fromStream->copy();
setValueAsByteStream(fromStream->copy());
return;
}
} else {
m_byteStream = toStream.copy();
setValueAsByteStream(toStream.copy());
return;
}
}
OwnPtr<SVGPathByteStream> lastAnimatedStream = m_byteStream.release();
m_byteStream = SVGPathByteStream::create();
SVGPathByteStreamBuilder builder(*m_byteStream);
SVGPathByteStreamSource fromSource(*fromStream);
SVGPathByteStreamSource toSource(toStream);
SVGPathBlender blender(&fromSource, &toSource, &builder);
blender.blendAnimatedPath(percentage);
OwnPtr<SVGPathByteStream> newStream = blendPathByteStreams(*fromStream, toStream, percentage);
// Handle additive='sum'.
if (!fromStream->size() || (animationElement->isAdditive() && !isToAnimation))
addToSVGPathByteStream(*m_byteStream, *lastAnimatedStream);
newStream = addPathByteStreams(newStream.release(), *lastAnimatedStream);
// Handle accumulate='sum'.
if (animationElement->isAccumulated() && repeatCount)
addToSVGPathByteStream(*m_byteStream, toAtEndOfDuration->byteStream(), repeatCount);
newStream = addPathByteStreams(newStream.release(), toSVGPath(toAtEndOfDurationValue)->byteStream(), repeatCount);
setValueAsByteStream(newStream.release());
}
float SVGPath::calculateDistance(PassRefPtrWillBeRawPtr<SVGPropertyBase> to, SVGElement*)
......
......@@ -47,13 +47,16 @@ public:
{
return adoptRefWillBeNoop(new SVGPath());
}
static PassRefPtrWillBeRawPtr<SVGPath> create(PassOwnPtr<SVGPathByteStream> pathByteStream)
{
return adoptRefWillBeNoop(new SVGPath(pathByteStream));
}
~SVGPath() override;
const Path& path() const;
const SVGPathByteStream& byteStream() const;
SVGPathByteStream& mutableByteStream();
// SVGPropertyBase:
PassRefPtrWillBeRawPtr<SVGPath> clone() const;
......@@ -72,7 +75,8 @@ private:
explicit SVGPath(PassOwnPtr<SVGPathByteStream>);
SVGPathByteStream& ensureByteStream();
void byteStreamWillChange();
void byteStreamChanged();
void setValueAsByteStream(PassOwnPtr<SVGPathByteStream>);
OwnPtr<SVGPathByteStream> m_byteStream;
mutable OwnPtr<Path> m_cachedPath;
......
......@@ -20,11 +20,9 @@
#include "config.h"
#include "core/svg/SVGPathUtilities.h"
#include "core/svg/SVGPathBlender.h"
#include "core/svg/SVGPathBuilder.h"
#include "core/svg/SVGPathByteStreamBuilder.h"
#include "core/svg/SVGPathByteStreamSource.h"
#include "core/svg/SVGPathElement.h"
#include "core/svg/SVGPathParser.h"
#include "core/svg/SVGPathStringBuilder.h"
#include "core/svg/SVGPathStringSource.h"
......@@ -85,21 +83,6 @@ bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream& result
return ok;
}
bool addToSVGPathByteStream(SVGPathByteStream& fromStream, const SVGPathByteStream& byStream, unsigned repeatCount)
{
if (fromStream.isEmpty() || byStream.isEmpty())
return true;
OwnPtr<SVGPathByteStream> fromStreamCopy = fromStream.copy();
fromStream.clear();
SVGPathByteStreamBuilder builder(fromStream);
SVGPathByteStreamSource fromSource(*fromStreamCopy);
SVGPathByteStreamSource bySource(byStream);
SVGPathBlender blender(&fromSource, &bySource, &builder);
return blender.addAnimatedPath(repeatCount);
}
unsigned getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream& stream, float length)
{
if (stream.isEmpty())
......
......@@ -40,8 +40,6 @@ bool buildSVGPathByteStreamFromString(const String&, SVGPathByteStream&, PathPar
// SVGPathByteStream -> String
bool buildStringFromByteStream(const SVGPathByteStream&, String&, PathParsingMode);
bool addToSVGPathByteStream(SVGPathByteStream&, const SVGPathByteStream&, unsigned repeatCount = 1);
unsigned getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream&, float length);
float getTotalLengthOfSVGPathByteStream(const SVGPathByteStream&);
FloatPoint getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream&, float length);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment