blob: 48af8013936d95d74123ef1f1018989ffae27afc [file] [log] [blame]
/*
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann
* <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
* Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/svg/svg_path_query.h"
#include "third_party/blink/renderer/core/svg/svg_path_byte_stream_source.h"
#include "third_party/blink/renderer/core/svg/svg_path_consumer.h"
#include "third_party/blink/renderer/core/svg/svg_path_data.h"
#include "third_party/blink/renderer/core/svg/svg_path_parser.h"
#include "third_party/blink/renderer/platform/graphics/path_traversal_state.h"
namespace blink {
namespace {
class SVGPathTraversalState final : public SVGPathConsumer {
public:
SVGPathTraversalState(
PathTraversalState::PathTraversalAction traversal_action,
float desired_length = 0)
: traversal_state_(traversal_action) {
traversal_state_.desired_length_ = desired_length;
}
float TotalLength() const { return traversal_state_.total_length_; }
FloatPoint ComputedPoint() const { return traversal_state_.current_; }
bool ProcessSegment() {
traversal_state_.ProcessSegment();
if (traversal_state_.success_)
return true;
return false;
}
private:
void EmitSegment(const PathSegmentData&) override;
PathTraversalState traversal_state_;
};
void SVGPathTraversalState::EmitSegment(const PathSegmentData& segment) {
switch (segment.command) {
case kPathSegMoveToAbs:
traversal_state_.total_length_ +=
traversal_state_.MoveTo(segment.target_point);
break;
case kPathSegLineToAbs:
traversal_state_.total_length_ +=
traversal_state_.LineTo(segment.target_point);
break;
case kPathSegClosePath:
traversal_state_.total_length_ += traversal_state_.CloseSubpath();
break;
case kPathSegCurveToCubicAbs:
traversal_state_.total_length_ += traversal_state_.CubicBezierTo(
segment.point1, segment.point2, segment.target_point);
break;
default:
NOTREACHED();
}
}
void ExecuteQuery(const SVGPathByteStream& path_byte_stream,
SVGPathTraversalState& traversal_state) {
SVGPathByteStreamSource source(path_byte_stream);
SVGPathNormalizer normalizer(&traversal_state);
bool has_more_data = source.HasMoreData();
while (has_more_data) {
PathSegmentData segment = source.ParseSegment();
DCHECK_NE(segment.command, kPathSegUnknown);
normalizer.EmitSegment(segment);
has_more_data = source.HasMoreData();
if (traversal_state.ProcessSegment())
break;
}
}
} // namespace
SVGPathQuery::SVGPathQuery(const SVGPathByteStream& path_byte_stream)
: path_byte_stream_(path_byte_stream) {}
float SVGPathQuery::GetTotalLength() const {
SVGPathTraversalState traversal_state(
PathTraversalState::kTraversalTotalLength);
ExecuteQuery(path_byte_stream_, traversal_state);
return traversal_state.TotalLength();
}
FloatPoint SVGPathQuery::GetPointAtLength(float length) const {
SVGPathTraversalState traversal_state(
PathTraversalState::kTraversalPointAtLength, length);
ExecuteQuery(path_byte_stream_, traversal_state);
return traversal_state.ComputedPoint();
}
} // namespace blink