Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / svg / SVGMotionSMILPathUtils.cpp
blob99665842d7bf0b65154e4a61405e89ffaf1ba287
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "SVGMotionSMILPathUtils.h"
9 #include "nsCharSeparatedTokenizer.h"
10 #include "nsContentUtils.h" // for NS_ENSURE_FINITE2
11 #include "SVGContentUtils.h"
12 #include "SVGLength.h"
14 using namespace mozilla::gfx;
16 namespace mozilla {
18 //----------------------------------------------------------------------
19 // PathGenerator methods
21 // For the dummy 'from' value used in pure by-animation & to-animation
22 void SVGMotionSMILPathUtils::PathGenerator::MoveToOrigin() {
23 MOZ_ASSERT(!mHaveReceivedCommands,
24 "Not expecting requests for mid-path MoveTo commands");
25 mHaveReceivedCommands = true;
26 mPathBuilder->MoveTo(Point(0, 0));
29 // For 'from' and the first entry in 'values'.
30 bool SVGMotionSMILPathUtils::PathGenerator::MoveToAbsolute(
31 const nsAString& aCoordPairStr) {
32 MOZ_ASSERT(!mHaveReceivedCommands,
33 "Not expecting requests for mid-path MoveTo commands");
34 mHaveReceivedCommands = true;
36 float xVal, yVal;
37 if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
38 return false;
40 mPathBuilder->MoveTo(Point(xVal, yVal));
41 return true;
44 // For 'to' and every entry in 'values' except the first.
45 bool SVGMotionSMILPathUtils::PathGenerator::LineToAbsolute(
46 const nsAString& aCoordPairStr, double& aSegmentDistance) {
47 mHaveReceivedCommands = true;
49 float xVal, yVal;
50 if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
51 return false;
53 Point initialPoint = mPathBuilder->CurrentPoint();
55 mPathBuilder->LineTo(Point(xVal, yVal));
56 aSegmentDistance = NS_hypot(initialPoint.x - xVal, initialPoint.y - yVal);
57 return true;
60 // For 'by'.
61 bool SVGMotionSMILPathUtils::PathGenerator::LineToRelative(
62 const nsAString& aCoordPairStr, double& aSegmentDistance) {
63 mHaveReceivedCommands = true;
65 float xVal, yVal;
66 if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
67 return false;
69 mPathBuilder->LineTo(mPathBuilder->CurrentPoint() + Point(xVal, yVal));
70 aSegmentDistance = NS_hypot(xVal, yVal);
71 return true;
74 already_AddRefed<Path>
75 SVGMotionSMILPathUtils::PathGenerator::GetResultingPath() {
76 return mPathBuilder->Finish();
79 //----------------------------------------------------------------------
80 // Helper / protected methods
82 bool SVGMotionSMILPathUtils::PathGenerator::ParseCoordinatePair(
83 const nsAString& aCoordPairStr, float& aXVal, float& aYVal) {
84 nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace,
85 nsTokenizerFlags::SeparatorOptional>
86 tokenizer(aCoordPairStr, ',');
88 SVGLength x, y;
90 if (!tokenizer.hasMoreTokens() ||
91 !x.SetValueFromString(tokenizer.nextToken())) {
92 return false;
95 if (!tokenizer.hasMoreTokens() ||
96 !y.SetValueFromString(tokenizer.nextToken())) {
97 return false;
100 if (tokenizer.separatorAfterCurrentToken() || // Trailing comma.
101 tokenizer.hasMoreTokens()) { // More text remains
102 return false;
105 float xRes = x.GetValueInPixels(mSVGElement, SVGContentUtils::X);
106 float yRes = y.GetValueInPixels(mSVGElement, SVGContentUtils::Y);
108 NS_ENSURE_FINITE2(xRes, yRes, false);
110 aXVal = xRes;
111 aYVal = yRes;
112 return true;
115 //----------------------------------------------------------------------
116 // MotionValueParser methods
117 bool SVGMotionSMILPathUtils::MotionValueParser::Parse(
118 const nsAString& aValueStr) {
119 bool success;
120 if (!mPathGenerator->HaveReceivedCommands()) {
121 // Interpret first value in "values" attribute as the path's initial MoveTo
122 success = mPathGenerator->MoveToAbsolute(aValueStr);
123 if (success) {
124 success = !!mPointDistances->AppendElement(0.0, fallible);
126 } else {
127 double dist;
128 success = mPathGenerator->LineToAbsolute(aValueStr, dist);
129 if (success) {
130 mDistanceSoFar += dist;
131 success = !!mPointDistances->AppendElement(mDistanceSoFar, fallible);
134 return success;
137 } // namespace mozilla