├── .gitignore
├── tests
├── tests.html
├── qunit
│ └── qunit-1.20.0.css
└── tests.js
├── bower.json
├── package.json
├── LICENSE
├── README.md
└── pathseg.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 |
4 |
--------------------------------------------------------------------------------
/tests/tests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PathSeg Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pathseg",
3 | "version": "1.2.1",
4 | "description": "A polyfill for SVG's SVGPathSeg and SVGPathSegList",
5 | "main": "pathseg.js",
6 | "authors": [
7 | "Philip Rogers"
8 | ],
9 | "license": "Chromium's License",
10 | "keywords": [
11 | "SVG",
12 | "polyfill",
13 | "pathseg",
14 | "SVGPathSeg",
15 | "SVGPathSegList"
16 | ],
17 | "homepage": "https://github.com/progers/pathseg",
18 | "moduleType": "globals",
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/progers/pathseg.git"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pathseg",
3 | "version": "1.2.1",
4 | "description": "A polyfill for SVG's SVGPathSeg and SVGPathSegList",
5 | "main": "pathseg.js",
6 | "directories": {
7 | "test": "tests"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/progers/pathseg.git"
12 | },
13 | "author": "Philip Rogers",
14 | "license": "Chromium's License",
15 | "bugs": {
16 | "url": "https://github.com/progers/pathseg/issues"
17 | },
18 | "homepage": "https://github.com/progers/pathseg",
19 | "keywords": [
20 | "SVG",
21 | "polyfill",
22 | "pathseg",
23 | "SVGPathSeg",
24 | "SVGPathSegList"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 The Chromium Authors. All rights reserved.
2 |
3 | The Chromium Authors can be found at
4 | http://src.chromium.org/svn/trunk/src/AUTHORS
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are
8 | met:
9 |
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above
13 | copyright notice, this list of conditions and the following disclaimer
14 | in the documentation and/or other materials provided with the
15 | distribution.
16 | * Neither the name of Google Inc. nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SVGPathSeg polyfill
2 |
3 | This is a drop-in replacement for the SVGPathSeg, SVGPathSegList, and getPathSegAtLength APIs that were removed from SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html). Existing code that uses the SVGPathSeg or SVGPathSegList APIs can use this polyfill to keep working. This polyfill is based on the exact code and tests that were removed from Chromium 47.
4 |
5 | The SVGPathSeg API was difficult to use and has been removed from the SVG spec in favor of a new, awesomer API in the Paths module (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html). All new development should use the SVG Path Data API. There's a polyfill ([path-data-polyfill.js](https://github.com/jarek-foksa/path-data-polyfill.js)) for browsers that do not yet support the new API.
6 |
7 | ## Implementation status
8 |
9 | Now passing all SVGPathSeg tests from the Chromium repository.
10 |
11 | Now used by [svg-edit](https://github.com/SVG-Edit/svgedit) and passes all svg-edit path tests.
12 |
13 | Blink will likely remove SVGPathElement.getPathSegAtLength (see: [Intent to deprecate and remove SVGPathElement.getPathSegAtLength](https://groups.google.com/a/chromium.org/d/msg/blink-dev/Gc1Aw282beo/NsfsKf8LBgAJ)). A getPathSegAtLength polyfill has been added to this library.
14 |
15 | Firefox 59 will likely remove portions of the SVGPathSeg and SVGPathSegList APIs (see: [Remove the WebIDL methods for creating and mutating SVG path data](https://bugzilla.mozilla.org/show_bug.cgi?id=1436438)). This library has support for polyfilling this partial implementation.
16 |
17 | ## Using pathseg.js
18 | Just add pathseg.js to your server and drop this in your html or svg files:
19 | ```
20 |
21 | ```
22 |
23 | ## Example API usage
24 | ```
25 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
26 | var moveToSeg = path.createSVGPathSegMovetoRel(10, 10);
27 | var lineToSeg = path.createSVGPathSegLinetoRel(100, 100);
28 | path.pathSegList.appendItem(moveToSeg);
29 | path.pathSegList.appendItem(lineToSeg);
30 | console.log(path.getAttribute('d')); // m 10 10 l 100 100
31 | moveToSeg.x += 200;
32 | moveToSeg.y += 200;
33 | console.log(path.getAttribute('d')); // m 210 210 l 100 100
34 | ```
35 |
36 | These APIs have been removed from SVG 2 but their original definitions can be found at:
37 |
38 | http://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSeg
39 |
40 | http://www.w3.org/TR/SVG/single-page.html#paths-InterfaceSVGPathSegList
41 |
42 | https://www.w3.org/TR/SVG/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
43 |
--------------------------------------------------------------------------------
/tests/qunit/qunit-1.20.0.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * QUnit 1.20.0
3 | * http://qunitjs.com/
4 | *
5 | * Copyright jQuery Foundation and other contributors
6 | * Released under the MIT license
7 | * http://jquery.org/license
8 | *
9 | * Date: 2015-10-27T17:53Z
10 | */
11 |
12 | /** Font Family and Sizes */
13 |
14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
16 | }
17 |
18 | #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
19 | #qunit-tests { font-size: smaller; }
20 |
21 |
22 | /** Resets */
23 |
24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
25 | margin: 0;
26 | padding: 0;
27 | }
28 |
29 |
30 | /** Header */
31 |
32 | #qunit-header {
33 | padding: 0.5em 0 0.5em 1em;
34 |
35 | color: #8699A4;
36 | background-color: #0D3349;
37 |
38 | font-size: 1.5em;
39 | line-height: 1em;
40 | font-weight: 400;
41 |
42 | border-radius: 5px 5px 0 0;
43 | }
44 |
45 | #qunit-header a {
46 | text-decoration: none;
47 | color: #C2CCD1;
48 | }
49 |
50 | #qunit-header a:hover,
51 | #qunit-header a:focus {
52 | color: #FFF;
53 | }
54 |
55 | #qunit-testrunner-toolbar label {
56 | display: inline-block;
57 | padding: 0 0.5em 0 0.1em;
58 | }
59 |
60 | #qunit-banner {
61 | height: 5px;
62 | }
63 |
64 | #qunit-testrunner-toolbar {
65 | padding: 0.5em 1em 0.5em 1em;
66 | color: #5E740B;
67 | background-color: #EEE;
68 | overflow: hidden;
69 | }
70 |
71 | #qunit-filteredTest {
72 | padding: 0.5em 1em 0.5em 1em;
73 | background-color: #F4FF77;
74 | color: #366097;
75 | }
76 |
77 | #qunit-userAgent {
78 | padding: 0.5em 1em 0.5em 1em;
79 | background-color: #2B81AF;
80 | color: #FFF;
81 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
82 | }
83 |
84 | #qunit-modulefilter-container {
85 | float: right;
86 | padding: 0.2em;
87 | }
88 |
89 | .qunit-url-config {
90 | display: inline-block;
91 | padding: 0.1em;
92 | }
93 |
94 | .qunit-filter {
95 | display: block;
96 | float: right;
97 | margin-left: 1em;
98 | }
99 |
100 | /** Tests: Pass/Fail */
101 |
102 | #qunit-tests {
103 | list-style-position: inside;
104 | }
105 |
106 | #qunit-tests li {
107 | padding: 0.4em 1em 0.4em 1em;
108 | border-bottom: 1px solid #FFF;
109 | list-style-position: inside;
110 | }
111 |
112 | #qunit-tests > li {
113 | display: none;
114 | }
115 |
116 | #qunit-tests li.running,
117 | #qunit-tests li.pass,
118 | #qunit-tests li.fail,
119 | #qunit-tests li.skipped {
120 | display: list-item;
121 | }
122 |
123 | #qunit-tests.hidepass li.running,
124 | #qunit-tests.hidepass li.pass {
125 | visibility: hidden;
126 | position: absolute;
127 | width: 0;
128 | height: 0;
129 | padding: 0;
130 | border: 0;
131 | margin: 0;
132 | }
133 |
134 | #qunit-tests li strong {
135 | cursor: pointer;
136 | }
137 |
138 | #qunit-tests li.skipped strong {
139 | cursor: default;
140 | }
141 |
142 | #qunit-tests li a {
143 | padding: 0.5em;
144 | color: #C2CCD1;
145 | text-decoration: none;
146 | }
147 |
148 | #qunit-tests li p a {
149 | padding: 0.25em;
150 | color: #6B6464;
151 | }
152 | #qunit-tests li a:hover,
153 | #qunit-tests li a:focus {
154 | color: #000;
155 | }
156 |
157 | #qunit-tests li .runtime {
158 | float: right;
159 | font-size: smaller;
160 | }
161 |
162 | .qunit-assert-list {
163 | margin-top: 0.5em;
164 | padding: 0.5em;
165 |
166 | background-color: #FFF;
167 |
168 | border-radius: 5px;
169 | }
170 |
171 | .qunit-source {
172 | margin: 0.6em 0 0.3em;
173 | }
174 |
175 | .qunit-collapsed {
176 | display: none;
177 | }
178 |
179 | #qunit-tests table {
180 | border-collapse: collapse;
181 | margin-top: 0.2em;
182 | }
183 |
184 | #qunit-tests th {
185 | text-align: right;
186 | vertical-align: top;
187 | padding: 0 0.5em 0 0;
188 | }
189 |
190 | #qunit-tests td {
191 | vertical-align: top;
192 | }
193 |
194 | #qunit-tests pre {
195 | margin: 0;
196 | white-space: pre-wrap;
197 | word-wrap: break-word;
198 | }
199 |
200 | #qunit-tests del {
201 | background-color: #E0F2BE;
202 | color: #374E0C;
203 | text-decoration: none;
204 | }
205 |
206 | #qunit-tests ins {
207 | background-color: #FFCACA;
208 | color: #500;
209 | text-decoration: none;
210 | }
211 |
212 | /*** Test Counts */
213 |
214 | #qunit-tests b.counts { color: #000; }
215 | #qunit-tests b.passed { color: #5E740B; }
216 | #qunit-tests b.failed { color: #710909; }
217 |
218 | #qunit-tests li li {
219 | padding: 5px;
220 | background-color: #FFF;
221 | border-bottom: none;
222 | list-style-position: inside;
223 | }
224 |
225 | /*** Passing Styles */
226 |
227 | #qunit-tests li li.pass {
228 | color: #3C510C;
229 | background-color: #FFF;
230 | border-left: 10px solid #C6E746;
231 | }
232 |
233 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
234 | #qunit-tests .pass .test-name { color: #366097; }
235 |
236 | #qunit-tests .pass .test-actual,
237 | #qunit-tests .pass .test-expected { color: #999; }
238 |
239 | #qunit-banner.qunit-pass { background-color: #C6E746; }
240 |
241 | /*** Failing Styles */
242 |
243 | #qunit-tests li li.fail {
244 | color: #710909;
245 | background-color: #FFF;
246 | border-left: 10px solid #EE5757;
247 | white-space: pre;
248 | }
249 |
250 | #qunit-tests > li:last-child {
251 | border-radius: 0 0 5px 5px;
252 | }
253 |
254 | #qunit-tests .fail { color: #000; background-color: #EE5757; }
255 | #qunit-tests .fail .test-name,
256 | #qunit-tests .fail .module-name { color: #000; }
257 |
258 | #qunit-tests .fail .test-actual { color: #EE5757; }
259 | #qunit-tests .fail .test-expected { color: #008000; }
260 |
261 | #qunit-banner.qunit-fail { background-color: #EE5757; }
262 |
263 | /*** Skipped tests */
264 |
265 | #qunit-tests .skipped {
266 | background-color: #EBECE9;
267 | }
268 |
269 | #qunit-tests .qunit-skipped-label {
270 | background-color: #F4FF77;
271 | display: inline-block;
272 | font-style: normal;
273 | color: #366097;
274 | line-height: 1.8em;
275 | padding: 0 0.5em;
276 | margin: -0.4em 0.4em -0.4em 0;
277 | }
278 |
279 | /** Result */
280 |
281 | #qunit-testresult {
282 | padding: 0.5em 1em 0.5em 1em;
283 |
284 | color: #2B81AF;
285 | background-color: #D2E0E6;
286 |
287 | border-bottom: 1px solid #FFF;
288 | }
289 | #qunit-testresult .module-name {
290 | font-weight: 700;
291 | }
292 |
293 | /** Fixture */
294 |
295 | #qunit-fixture {
296 | position: absolute;
297 | top: -10000px;
298 | left: -10000px;
299 | width: 1000px;
300 | height: 1000px;
301 | }
302 |
--------------------------------------------------------------------------------
/tests/tests.js:
--------------------------------------------------------------------------------
1 | // LayoutTests/svg/dom/script-tests/path-segments.js
2 | QUnit.test("Path segment types", function(assert) {
3 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
4 |
5 | assert.equal(SVGPathSeg.PATHSEG_UNKNOWN, "0");
6 | assert.equal(SVGPathSeg.PATHSEG_CLOSEPATH, "1");
7 | assert.equal(SVGPathSeg.PATHSEG_MOVETO_ABS, "2");
8 | assert.equal(SVGPathSeg.PATHSEG_MOVETO_REL, "3");
9 | assert.equal(SVGPathSeg.PATHSEG_LINETO_ABS, "4");
10 | assert.equal(SVGPathSeg.PATHSEG_LINETO_REL, "5");
11 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "6");
12 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "7");
13 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "8");
14 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "9");
15 | assert.equal(SVGPathSeg.PATHSEG_ARC_ABS, "10");
16 | assert.equal(SVGPathSeg.PATHSEG_ARC_REL, "11");
17 | assert.equal(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "12");
18 | assert.equal(SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "13");
19 | assert.equal(SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "14");
20 | assert.equal(SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "15");
21 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "16");
22 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "17");
23 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "18");
24 | assert.equal(SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "19");
25 |
26 | assert.equal(path.createSVGPathSegClosePath().pathSegType, SVGPathSeg.PATHSEG_CLOSEPATH);
27 | assert.equal(path.createSVGPathSegClosePath().pathSegTypeAsLetter, "z");
28 | assert.equal(path.createSVGPathSegMovetoAbs(1, 2).pathSegType, SVGPathSeg.PATHSEG_MOVETO_ABS);
29 | assert.equal(path.createSVGPathSegMovetoAbs(1, 2).pathSegTypeAsLetter, "M");
30 | assert.equal(path.createSVGPathSegMovetoAbs(1, 2).x, "1");
31 | assert.equal(path.createSVGPathSegMovetoAbs(1, 2).y, "2");
32 | assert.equal(path.createSVGPathSegMovetoRel(1, 2).pathSegType, SVGPathSeg.PATHSEG_MOVETO_REL);
33 | assert.equal(path.createSVGPathSegMovetoRel(1, 2).pathSegTypeAsLetter, "m");
34 | assert.equal(path.createSVGPathSegMovetoRel(1, 2).x, "1");
35 | assert.equal(path.createSVGPathSegMovetoRel(1, 2).y, "2");
36 | assert.equal(path.createSVGPathSegLinetoAbs(1, 2).pathSegType, SVGPathSeg.PATHSEG_LINETO_ABS);
37 | assert.equal(path.createSVGPathSegLinetoAbs(1, 2).pathSegTypeAsLetter, "L");
38 | assert.equal(path.createSVGPathSegLinetoAbs(1, 2).x, "1");
39 | assert.equal(path.createSVGPathSegLinetoAbs(1, 2).y, "2");
40 | assert.equal(path.createSVGPathSegLinetoRel(1, 2).pathSegType, SVGPathSeg.PATHSEG_LINETO_REL);
41 | assert.equal(path.createSVGPathSegLinetoRel(1, 2).pathSegTypeAsLetter, "l");
42 | assert.equal(path.createSVGPathSegLinetoRel(1, 2).x, "1");
43 | assert.equal(path.createSVGPathSegLinetoRel(1, 2).y, "2");
44 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).pathSegType, SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS);
45 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).pathSegTypeAsLetter, "C");
46 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).x, "1");
47 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).y, "2");
48 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).x1, "3");
49 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).y1, "4");
50 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).x2, "5");
51 | assert.equal(path.createSVGPathSegCurvetoCubicAbs(1, 2, 3, 4, 5, 6).y2, "6");
52 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).pathSegType, SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL);
53 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).pathSegTypeAsLetter, "c");
54 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).x, "1");
55 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).y, "2");
56 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).x1, "3");
57 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).y1, "4");
58 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).x2, "5");
59 | assert.equal(path.createSVGPathSegCurvetoCubicRel(1, 2, 3, 4, 5, 6).y2, "6");
60 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).pathSegType, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS);
61 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).pathSegTypeAsLetter, "Q");
62 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).x, "1");
63 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).y, "2");
64 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).x1, "3");
65 | assert.equal(path.createSVGPathSegCurvetoQuadraticAbs(1, 2, 3, 4).y1, "4");
66 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).pathSegType, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL);
67 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).pathSegTypeAsLetter, "q");
68 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).x, "1");
69 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).y, "2");
70 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).x1, "3");
71 | assert.equal(path.createSVGPathSegCurvetoQuadraticRel(1, 2, 3, 4).y1, "4");
72 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).pathSegType, SVGPathSeg.PATHSEG_ARC_ABS);
73 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).pathSegTypeAsLetter, "A");
74 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).x, "1");
75 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).y, "2");
76 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).r1, "3");
77 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).r2, "4");
78 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).angle, "5");
79 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).largeArcFlag, false);
80 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, true, false).largeArcFlag, true);
81 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, false).sweepFlag, false);
82 | assert.equal(path.createSVGPathSegArcAbs(1, 2, 3, 4, 5, false, true).sweepFlag, true);
83 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).pathSegType, SVGPathSeg.PATHSEG_ARC_REL);
84 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).pathSegTypeAsLetter, "a");
85 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).x, "1");
86 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).y, "2");
87 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).r1, "3");
88 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).r2, "4");
89 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).angle, "5");
90 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).largeArcFlag, false);
91 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, true, false).largeArcFlag, true);
92 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, false).sweepFlag, false);
93 | assert.equal(path.createSVGPathSegArcRel(1, 2, 3, 4, 5, false, true).sweepFlag, true);
94 | assert.equal(path.createSVGPathSegLinetoHorizontalAbs(1).pathSegType, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS);
95 | assert.equal(path.createSVGPathSegLinetoHorizontalAbs(1).pathSegTypeAsLetter, "H");
96 | assert.equal(path.createSVGPathSegLinetoHorizontalAbs(1).x, "1");
97 | assert.equal(path.createSVGPathSegLinetoHorizontalRel(1).pathSegType, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL);
98 | assert.equal(path.createSVGPathSegLinetoHorizontalRel(1).pathSegTypeAsLetter, "h");
99 | assert.equal(path.createSVGPathSegLinetoHorizontalRel(1).x, "1");
100 | assert.equal(path.createSVGPathSegLinetoVerticalAbs(1).pathSegType, SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS);
101 | assert.equal(path.createSVGPathSegLinetoVerticalAbs(1).pathSegTypeAsLetter, "V");
102 | assert.equal(path.createSVGPathSegLinetoVerticalAbs(1).y, "1");
103 | assert.equal(path.createSVGPathSegLinetoVerticalRel(1).pathSegType, SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL);
104 | assert.equal(path.createSVGPathSegLinetoVerticalRel(1).pathSegTypeAsLetter, "v");
105 | assert.equal(path.createSVGPathSegLinetoVerticalRel(1).y, "1");
106 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).pathSegType, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS);
107 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).pathSegTypeAsLetter, "S");
108 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).x, "1");
109 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).y, "2");
110 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).x2, "3");
111 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothAbs(1, 2, 3, 4).y2, "4");
112 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).pathSegType, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL);
113 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).pathSegTypeAsLetter, "s");
114 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).x, "1");
115 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).y, "2");
116 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).x2, "3");
117 | assert.equal(path.createSVGPathSegCurvetoCubicSmoothRel(1, 2, 3, 4).y2, "4");
118 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothAbs(1, 2).pathSegType, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS);
119 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothAbs(1, 2).pathSegTypeAsLetter, "T");
120 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothAbs(1, 2).x, "1");
121 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothAbs(1, 2).y, "2");
122 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothRel(1, 2).pathSegType, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
123 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothRel(1, 2).pathSegTypeAsLetter, "t");
124 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothRel(1, 2).x, "1");
125 | assert.equal(path.createSVGPathSegCurvetoQuadraticSmoothRel(1, 2).y, "2");
126 | });
127 |
128 | // LayoutTests/svg/dom/svg2-inheritance.html
129 | QUnit.test("Validate the SVGPathSeg inheritance model", function(assert) {
130 | function checkParent(type, expectedParent) {
131 | assert.ok(window[type]);
132 | var parentPrototype = window[type].prototype.__proto__;
133 | var expectedPrototype = window[expectedParent] ? window[expectedParent].prototype : null;
134 |
135 | assert.equal(parentPrototype, expectedPrototype);
136 | }
137 |
138 | checkParent("SVGPathSeg", "Object");
139 | checkParent("SVGPathSegArcAbs", "SVGPathSeg");
140 | checkParent("SVGPathSegArcRel", "SVGPathSeg");
141 | checkParent("SVGPathSegClosePath", "SVGPathSeg");
142 | checkParent("SVGPathSegCurvetoCubicAbs", "SVGPathSeg");
143 | checkParent("SVGPathSegCurvetoCubicRel", "SVGPathSeg");
144 | checkParent("SVGPathSegCurvetoCubicSmoothAbs", "SVGPathSeg");
145 | checkParent("SVGPathSegCurvetoCubicSmoothRel", "SVGPathSeg");
146 | checkParent("SVGPathSegCurvetoQuadraticAbs", "SVGPathSeg");
147 | checkParent("SVGPathSegCurvetoQuadraticRel", "SVGPathSeg");
148 | checkParent("SVGPathSegCurvetoQuadraticSmoothAbs", "SVGPathSeg");
149 | checkParent("SVGPathSegCurvetoQuadraticSmoothRel", "SVGPathSeg");
150 | checkParent("SVGPathSegLinetoAbs", "SVGPathSeg");
151 | checkParent("SVGPathSegLinetoHorizontalAbs", "SVGPathSeg");
152 | checkParent("SVGPathSegLinetoHorizontalRel", "SVGPathSeg");
153 | checkParent("SVGPathSegLinetoRel", "SVGPathSeg");
154 | checkParent("SVGPathSegLinetoVerticalAbs", "SVGPathSeg");
155 | checkParent("SVGPathSegLinetoVerticalRel", "SVGPathSeg");
156 | checkParent("SVGPathSegList", "Object");
157 | checkParent("SVGPathSegMovetoAbs", "SVGPathSeg");
158 | checkParent("SVGPathSegMovetoRel", "SVGPathSeg");
159 | });
160 |
161 | QUnit.test("Validate the SVGPathSegList inheritance model", function(assert) {
162 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
163 | assert.ok(path.pathSegList instanceof SVGPathSegList);
164 | });
165 |
166 | // Source/core/svg/SVGPathParserTest.cpp
167 | QUnit.test("Path parsing", function(assert) {
168 | // This test is only for the polyfill.
169 | if (!SVGPathSegList._pathSegArrayAsString) {
170 | expect(0);
171 | return;
172 | }
173 |
174 | function checkParsing(string, expected) {
175 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
176 | path.setAttribute("d", string);
177 | var pathSegArray = path.pathSegList._parsePath(string);
178 | var actual = SVGPathSegList._pathSegArrayAsString(pathSegArray);
179 | assert.equal(actual, expected);
180 | }
181 |
182 | checkParsing("M1,2", "M 1 2");
183 | checkParsing("m1,2", "m 1 2");
184 | checkParsing("M100,200 m3,4", "M 100 200 m 3 4");
185 | checkParsing("M100,200 L3,4", "M 100 200 L 3 4");
186 | checkParsing("M100,200 l3,4", "M 100 200 l 3 4");
187 | checkParsing("M100,200 H3", "M 100 200 H 3");
188 | checkParsing("M100,200 h3", "M 100 200 h 3");
189 | checkParsing("M100,200 V3", "M 100 200 V 3");
190 | checkParsing("M100,200 v3", "M 100 200 v 3");
191 | checkParsing("M100,200 Z", "M 100 200 z");
192 | checkParsing("M100,200 z", "M 100 200 z");
193 | checkParsing("M100,200 C3,4,5,6,7,8", "M 100 200 C 3 4 5 6 7 8");
194 | checkParsing("M100,200 c3,4,5,6,7,8", "M 100 200 c 3 4 5 6 7 8");
195 | checkParsing("M100,200 S3,4,5,6", "M 100 200 S 3 4 5 6");
196 | checkParsing("M100,200 s3,4,5,6", "M 100 200 s 3 4 5 6");
197 | checkParsing("M100,200 Q3,4,5,6", "M 100 200 Q 3 4 5 6");
198 | checkParsing("M100,200 q3,4,5,6", "M 100 200 q 3 4 5 6");
199 | checkParsing("M100,200 T3,4", "M 100 200 T 3 4");
200 | checkParsing("M100,200 t3,4", "M 100 200 t 3 4");
201 | checkParsing("M100,200 A3,4,5,0,0,6,7", "M 100 200 A 3 4 5 0 0 6 7");
202 | checkParsing("M100,200 A3,4,5,1,0,6,7", "M 100 200 A 3 4 5 1 0 6 7");
203 | checkParsing("M100,200 A3,4,5,0,1,6,7", "M 100 200 A 3 4 5 0 1 6 7");
204 | checkParsing("M100,200 A3,4,5,1,1,6,7", "M 100 200 A 3 4 5 1 1 6 7");
205 | checkParsing("M100,200 a3,4,5,0,0,6,7", "M 100 200 a 3 4 5 0 0 6 7");
206 | checkParsing("M100,200 a3,4,5,0,1,6,7", "M 100 200 a 3 4 5 0 1 6 7");
207 | checkParsing("M100,200 a3,4,5,1,0,6,7", "M 100 200 a 3 4 5 1 0 6 7");
208 | checkParsing("M100,200 a3,4,5,1,1,6,7", "M 100 200 a 3 4 5 1 1 6 7");
209 | checkParsing("M100,200 a3,4,5,006,7", "M 100 200 a 3 4 5 0 0 6 7");
210 | checkParsing("M100,200 a3,4,5,016,7", "M 100 200 a 3 4 5 0 1 6 7");
211 | checkParsing("M100,200 a3,4,5,106,7", "M 100 200 a 3 4 5 1 0 6 7");
212 | checkParsing("M100,200 a3,4,5,116,7", "M 100 200 a 3 4 5 1 1 6 7");
213 |
214 | checkParsing("M100,200 a0,4,5,0,0,10,0 a4,0,5,0,0,0,10 a0,0,5,0,0,-10,0 z", "M 100 200 a 0 4 5 0 0 10 0 a 4 0 5 0 0 0 10 a 0 0 5 0 0 -10 0 z");
215 |
216 | checkParsing("M1,2,3,4", "M 1 2 L 3 4");
217 | checkParsing("m100,200,3,4", "m 100 200 l 3 4");
218 |
219 | checkParsing("M 100-200", "M 100 -200");
220 | checkParsing("M 0.6.5", "M 0.6 0.5");
221 |
222 | checkParsing(" M1,2", "M 1 2");
223 | checkParsing(" M1,2", "M 1 2");
224 | checkParsing("\tM1,2", "M 1 2");
225 | checkParsing("\nM1,2", "M 1 2");
226 | checkParsing("\rM1,2", "M 1 2");
227 | checkParsing("M1,2 ", "M 1 2");
228 | checkParsing("M1,2\t", "M 1 2");
229 | checkParsing("M1,2\n", "M 1 2");
230 | checkParsing("M1,2\r", "M 1 2");
231 |
232 | checkParsing("", "");
233 | checkParsing(" ", "");
234 | checkParsing("M.1 .2 L.3 .4 .5 .6", "M 0.1 0.2 L 0.3 0.4 L 0.5 0.6");
235 |
236 | checkParsing("M1,1h2,3", "M 1 1 h 2 h 3");
237 | checkParsing("M1,1H2,3", "M 1 1 H 2 H 3");
238 | checkParsing("M1,1v2,3", "M 1 1 v 2 v 3");
239 | checkParsing("M1,1V2,3", "M 1 1 V 2 V 3");
240 |
241 | checkParsing("M1,1c2,3 4,5 6,7 8,9 10,11 12,13", "M 1 1 c 2 3 4 5 6 7 c 8 9 10 11 12 13");
242 | checkParsing("M1,1C2,3 4,5 6,7 8,9 10,11 12,13", "M 1 1 C 2 3 4 5 6 7 C 8 9 10 11 12 13");
243 | checkParsing("M1,1s2,3 4,5 6,7 8,9", "M 1 1 s 2 3 4 5 s 6 7 8 9");
244 | checkParsing("M1,1S2,3 4,5 6,7 8,9", "M 1 1 S 2 3 4 5 S 6 7 8 9");
245 | checkParsing("M1,1q2,3 4,5 6,7 8,9", "M 1 1 q 2 3 4 5 q 6 7 8 9");
246 | checkParsing("M1,1Q2,3 4,5 6,7 8,9", "M 1 1 Q 2 3 4 5 Q 6 7 8 9");
247 | checkParsing("M1,1t2,3 4,5", "M 1 1 t 2 3 t 4 5");
248 | checkParsing("M1,1T2,3 4,5", "M 1 1 T 2 3 T 4 5");
249 | checkParsing("M1,1a2,3,4,0,0,5,6 7,8,9,0,0,10,11", "M 1 1 a 2 3 4 0 0 5 6 a 7 8 9 0 0 10 11");
250 | checkParsing("M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11", "M 1 1 A 2 3 4 0 0 5 6 A 7 8 9 0 0 10 11");
251 | });
252 |
253 | // LayoutTests/svg/dom/SVGPathSegList-appendItem.xhtml
254 | QUnit.test("Test of SVGPathSegList.appendItem", function(assert) {
255 | var path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
256 | path1.setAttribute("d", "M 0 0 L 100 0 L 100 100");
257 | var path2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
258 | path2.setAttribute("d", "M 0 0 L 50 100 h 100 h 100 v 100");
259 |
260 | // Check initial 'pathSegList' value of path1
261 | assert.equal(path1.pathSegList.numberOfItems, "3");
262 |
263 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
264 | assert.equal(path1.pathSegList.getItem(0).x, "0");
265 | assert.equal(path1.pathSegList.getItem(0).y, "0");
266 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
267 | assert.equal(path1.pathSegList.getItem(1).x, "100");
268 | assert.equal(path1.pathSegList.getItem(1).y, "0");
269 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
270 | assert.equal(path1.pathSegList.getItem(2).x, "100");
271 | assert.equal(path1.pathSegList.getItem(2).y, "100");
272 |
273 | // Check initial 'pathSegList' value of path2
274 | assert.equal(path2.pathSegList.numberOfItems, "5");
275 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
276 | assert.equal(path2.pathSegList.getItem(0).x, "0");
277 | assert.equal(path2.pathSegList.getItem(0).y, "0");
278 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
279 | assert.equal(path2.pathSegList.getItem(1).x, "50");
280 | assert.equal(path2.pathSegList.getItem(1).y, "100");
281 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoHorizontalRel]");
282 | assert.equal(path2.pathSegList.getItem(2).x, "100");
283 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
284 | assert.equal(path2.pathSegList.getItem(3).x, "100");
285 | assert.equal(path2.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoVerticalRel]");
286 | assert.equal(path2.pathSegList.getItem(4).y, "100");
287 |
288 | // Negate x value of fourth segment in path2
289 | assert.equal(path2.pathSegList.getItem(3).x = -path2.pathSegList.getItem(3).x, "-100");
290 |
291 | // Append second item from path1 to path2 list
292 | assert.equal(path2.pathSegList.appendItem(path2.pathSegList.getItem(3)).toString(), "[object SVGPathSegLinetoHorizontalRel]");
293 | assert.equal(path2.pathSegList.numberOfItems, "6");
294 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
295 | assert.equal(path2.pathSegList.getItem(0).x, "0");
296 | assert.equal(path2.pathSegList.getItem(0).y, "0");
297 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
298 | assert.equal(path2.pathSegList.getItem(1).x, "50");
299 | assert.equal(path2.pathSegList.getItem(1).y, "100");
300 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoHorizontalRel]");
301 | assert.equal(path2.pathSegList.getItem(2).x, "100");
302 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
303 | assert.equal(path2.pathSegList.getItem(3).x, "-100");
304 | assert.equal(path2.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoVerticalRel]");
305 | assert.equal(path2.pathSegList.getItem(4).y, "100");
306 | assert.equal(path2.pathSegList.getItem(5).toString(), "[object SVGPathSegLinetoHorizontalRel]");
307 | assert.equal(path2.pathSegList.getItem(5).x, "-100");
308 |
309 | // Append second item from path2 to path1 list
310 | assert.equal(path1.pathSegList.appendItem(path2.pathSegList.getItem(1)).toString(), "[object SVGPathSegLinetoAbs]");
311 |
312 | // Change last item of path1 list, that came from path2 list, assure it's updating path1
313 | assert.equal(path1.pathSegList.getItem(3).x -= 50, "0");
314 |
315 | // Reset points attribute to M 0 0 L 100 0 v 100"
316 | path2.setAttribute("d", "M 0 0 L 100 0 v 100");
317 |
318 | // Append fourth item from path1 to path2 list - now should look like a rectangle
319 | assert.equal(path2.pathSegList.appendItem(path1.pathSegList.getItem(3)).toString(), "[object SVGPathSegLinetoAbs]");
320 |
321 | // Check final 'pathSegList' value of path1
322 | assert.equal(path1.pathSegList.numberOfItems, "4");
323 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
324 | assert.equal(path1.pathSegList.getItem(0).x, "0");
325 | assert.equal(path1.pathSegList.getItem(0).y, "0");
326 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
327 | assert.equal(path1.pathSegList.getItem(1).x, "100");
328 | assert.equal(path1.pathSegList.getItem(1).y, "0");
329 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
330 | assert.equal(path1.pathSegList.getItem(2).x, "100");
331 | assert.equal(path1.pathSegList.getItem(2).y, "100");
332 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
333 | assert.equal(path1.pathSegList.getItem(3).x, "0");
334 | assert.equal(path1.pathSegList.getItem(3).y, "100");
335 |
336 | // Check final 'pathSegList' value of path2
337 | assert.equal(path2.pathSegList.numberOfItems, "4");
338 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
339 | assert.equal(path2.pathSegList.getItem(0).x, "0");
340 | assert.equal(path2.pathSegList.getItem(0).y, "0");
341 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
342 | assert.equal(path2.pathSegList.getItem(1).x, "100");
343 | assert.equal(path1.pathSegList.getItem(1).y, "0");
344 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoVerticalRel]");
345 | assert.equal(path2.pathSegList.getItem(2).y, "100");
346 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
347 | assert.equal(path2.pathSegList.getItem(3).x, "0");
348 | assert.equal(path1.pathSegList.getItem(3).y, "100");
349 | });
350 |
351 | // LayoutTests/svg/dom/SVGPathSegList-clear-and-initialize.xhtml
352 | QUnit.test("Test of SVGPathSegList.clear and SVGPathSegList.initialize", function(assert) {
353 | var path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
354 | path1.setAttribute("d", "M 100 100 L 100 0 L 100 100");
355 | var path2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
356 | path2.setAttribute("d", "M 50 50 L 0 100 M 0 0");
357 |
358 | // Check initial 'pathSegList' value of path1
359 | assert.equal(path1.pathSegList.numberOfItems, "3");
360 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
361 | assert.equal(path1.pathSegList.getItem(0).x, "100");
362 | assert.equal(path1.pathSegList.getItem(0).y, "100");
363 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
364 | assert.equal(path1.pathSegList.getItem(1).x, "100");
365 | assert.equal(path1.pathSegList.getItem(1).y, "0");
366 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
367 | assert.equal(path1.pathSegList.getItem(2).x, "100");
368 | assert.equal(path1.pathSegList.getItem(2).y, "100");
369 |
370 | // Check initial 'pathSegList' value of path2
371 | assert.equal(path2.pathSegList.numberOfItems, "3");
372 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
373 | assert.equal(path2.pathSegList.getItem(0).x, "50");
374 | assert.equal(path2.pathSegList.getItem(0).y, "50");
375 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
376 | assert.equal(path2.pathSegList.getItem(1).x, "0");
377 | assert.equal(path2.pathSegList.getItem(1).y, "100");
378 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegMovetoAbs]");
379 | assert.equal(path2.pathSegList.getItem(2).x, "0");
380 | assert.equal(path2.pathSegList.getItem(2).y, "0");
381 |
382 | // Cache first item of path1 in local variable 'item0'
383 | var item0 = path1.pathSegList.getItem(0);
384 | assert.equal(item0.x, "100");
385 | assert.equal(item0.y, "100");
386 |
387 | // Clear path1 segment list
388 | path1.pathSegList.clear()
389 |
390 | // Verify that item0 is still alive, and can be modified
391 | assert.equal(item0.x, "100");
392 | assert.equal(item0.y, "100");
393 | assert.equal(item0.x += 50, "150");
394 | assert.equal(item0.y += 50, "150");
395 |
396 | // Check intermediate list state of path1
397 | assert.equal(path1.pathSegList.numberOfItems, "0");
398 | assert.throws(function() {
399 | path1.pathSegList.getItem(0);
400 | });
401 |
402 | // Check intermediate list state of path2
403 | assert.equal(path2.pathSegList.numberOfItems, "3");
404 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
405 | assert.equal(path2.pathSegList.getItem(0).x, "50");
406 | assert.equal(path2.pathSegList.getItem(0).y, "50");
407 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
408 | assert.equal(path2.pathSegList.getItem(1).x, "0");
409 | assert.equal(path2.pathSegList.getItem(1).y, "100");
410 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegMovetoAbs]");
411 | assert.equal(path2.pathSegList.getItem(2).x, "0");
412 | assert.equal(path2.pathSegList.getItem(2).y, "0");
413 |
414 | // Initialize path1 list with first item of path2
415 | assert.equal(path1.pathSegList.initialize(path2.pathSegList.getItem(0)).toString(), "[object SVGPathSegMovetoAbs]");
416 |
417 | // Check intermediate list state of path1
418 | assert.equal(path1.pathSegList.numberOfItems, "1");
419 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
420 | assert.equal(path1.pathSegList.getItem(0).x, "50");
421 | assert.equal(path1.pathSegList.getItem(0).y, "50");
422 |
423 | // Check intermediate list state of path2
424 | assert.equal(path2.pathSegList.numberOfItems, "3");
425 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
426 | assert.equal(path2.pathSegList.getItem(0).x, "50");
427 | assert.equal(path2.pathSegList.getItem(0).y, "50");
428 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
429 | assert.equal(path2.pathSegList.getItem(1).x, "0");
430 | assert.equal(path2.pathSegList.getItem(1).y, "100");
431 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegMovetoAbs]");
432 | assert.equal(path2.pathSegList.getItem(2).x, "0");
433 | assert.equal(path2.pathSegList.getItem(2).y, "0");
434 |
435 | // Initialize path2 list with item0
436 | assert.equal(path2.pathSegList.initialize(item0).toString(), "[object SVGPathSegMovetoAbs]");
437 |
438 | // Check final list state of path1
439 | assert.equal(path1.pathSegList.numberOfItems, "1");
440 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
441 | assert.equal(path1.pathSegList.getItem(0).x, "50");
442 | assert.equal(path1.pathSegList.getItem(0).y, "50");
443 |
444 | // Check final list state of path2
445 | assert.equal(path2.pathSegList.numberOfItems, "1");
446 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
447 | assert.equal(path2.pathSegList.getItem(0).x, "150");
448 | assert.equal(path2.pathSegList.getItem(0).y, "150");
449 | });
450 |
451 | // LayoutTests/svg/dom/SVGPathSegList-removeItem.xhtml
452 | QUnit.test("Test of SVGPathSegList::removeItem", function(assert) {
453 | var path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
454 | path1.setAttribute("d", "M 0 0 L 100 0 L 0 100 L 100 100");
455 |
456 | // Check initial 'pathSegList' value of path1.
457 | assert.equal(path1.pathSegList.numberOfItems, "4");
458 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
459 | assert.equal(path1.pathSegList.getItem(0).x, "0");
460 | assert.equal(path1.pathSegList.getItem(0).y, "0");
461 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
462 | assert.equal(path1.pathSegList.getItem(1).x, "100");
463 | assert.equal(path1.pathSegList.getItem(1).y, "0");
464 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
465 | assert.equal(path1.pathSegList.getItem(2).x, "0");
466 | assert.equal(path1.pathSegList.getItem(2).y, "100");
467 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
468 | assert.equal(path1.pathSegList.getItem(3).x, "100");
469 | assert.equal(path1.pathSegList.getItem(3).y, "100");
470 |
471 | // Insert fourth item at position three using insertItemBefore().
472 | assert.equal(path1.pathSegList.insertItemBefore(path1.pathSegList.getItem(3), 2).toString(), "[object SVGPathSegLinetoAbs]");
473 | assert.equal(path1.pathSegList.numberOfItems, "5");
474 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
475 | assert.equal(path1.pathSegList.getItem(0).x, "0");
476 | assert.equal(path1.pathSegList.getItem(0).y, "0");
477 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
478 | assert.equal(path1.pathSegList.getItem(1).x, "100");
479 | assert.equal(path1.pathSegList.getItem(1).y, "0");
480 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
481 | assert.equal(path1.pathSegList.getItem(2).x, "100");
482 | assert.equal(path1.pathSegList.getItem(2).y, "100");
483 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
484 | assert.equal(path1.pathSegList.getItem(3).x, "0");
485 | assert.equal(path1.pathSegList.getItem(3).y, "100");
486 | assert.equal(path1.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoAbs]");
487 | assert.equal(path1.pathSegList.getItem(4).x, "100");
488 | assert.equal(path1.pathSegList.getItem(4).y, "100");
489 |
490 | // Change last item of path1 list.
491 | assert.equal(path1.pathSegList.getItem(4).x = 0, "0");
492 |
493 | // Check final 'pathSegList' value of path1.
494 | assert.equal(path1.pathSegList.numberOfItems, "5");
495 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
496 | assert.equal(path1.pathSegList.getItem(0).x, "0");
497 | assert.equal(path1.pathSegList.getItem(0).y, "0");
498 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
499 | assert.equal(path1.pathSegList.getItem(1).x, "100");
500 | assert.equal(path1.pathSegList.getItem(1).y, "0");
501 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
502 | assert.equal(path1.pathSegList.getItem(2).x, "100");
503 | assert.equal(path1.pathSegList.getItem(2).y, "100");
504 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
505 | assert.equal(path1.pathSegList.getItem(3).x, "0");
506 | assert.equal(path1.pathSegList.getItem(3).y, "100");
507 | assert.equal(path1.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoAbs]");
508 | assert.equal(path1.pathSegList.getItem(4).x, "0");
509 | assert.equal(path1.pathSegList.getItem(4).y, "100");
510 | });
511 |
512 | // LayoutTests/svg/dom/SVGPathSegList-insertItemBefore.xhtml
513 | QUnit.test("Test of SVGPathSegList.insertItemBefore", function(assert) {
514 | var path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
515 | path1.setAttribute("d", "M 0 0 L 100 0 L 100 100 z L 0 100");
516 | var path2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
517 | path2.setAttribute("d", "M 0 0 h 100 z v 100 h -100");
518 |
519 | // Check initial 'pathSegList' value of path1.
520 | assert.equal(path1.pathSegList.numberOfItems, "5");
521 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
522 | assert.equal(path1.pathSegList.getItem(0).x, "0");
523 | assert.equal(path1.pathSegList.getItem(0).y, "0");
524 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
525 | assert.equal(path1.pathSegList.getItem(1).x, "100");
526 | assert.equal(path1.pathSegList.getItem(1).y, "0");
527 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
528 | assert.equal(path1.pathSegList.getItem(2).x, "100");
529 | assert.equal(path1.pathSegList.getItem(2).y, "100");
530 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegClosePath]");
531 | assert.equal(path1.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoAbs]");
532 | assert.equal(path1.pathSegList.getItem(4).x, "0");
533 | assert.equal(path1.pathSegList.getItem(4).y, "100");
534 |
535 | // Check initial 'pathSegList' value of path2.
536 | assert.equal(path2.pathSegList.numberOfItems, "5");
537 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
538 | assert.equal(path2.pathSegList.getItem(0).x, "0");
539 | assert.equal(path2.pathSegList.getItem(0).y, "0");
540 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoHorizontalRel]");
541 | assert.equal(path2.pathSegList.getItem(1).x, "100");
542 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegClosePath]");
543 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoVerticalRel]");
544 | assert.equal(path2.pathSegList.getItem(3).y, "100");
545 | assert.equal(path2.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoHorizontalRel]");
546 | assert.equal(path2.pathSegList.getItem(4).x, "-100");
547 |
548 | // Remove fourth item of path1.
549 | assert.equal(path1.pathSegList.removeItem(3).toString(), "[object SVGPathSegClosePath]");
550 |
551 | // Remove third item of path2.
552 | assert.equal(path2.pathSegList.removeItem(2).toString(), "[object SVGPathSegClosePath]");
553 | });
554 |
555 | // LayoutTests/svg/dom/SVGPathSegList-replaceItem.xhtml
556 | QUnit.test("Test of SVGPathSegList.replaceItem", function(assert) {
557 | var path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
558 | path1.setAttribute("d", "M 0 0 L 100 100 L 100 0 L 100 100 v 100 L 0 100");
559 | var path2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
560 | path2.setAttribute("d", "M 0 0 h 100 L 200 100 h -100");
561 |
562 | // Check initial 'pathSegList' value of path1.
563 | assert.equal(path1.pathSegList.numberOfItems, "6");
564 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
565 | assert.equal(path1.pathSegList.getItem(0).x, "0");
566 | assert.equal(path1.pathSegList.getItem(0).y, "0");
567 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
568 | assert.equal(path1.pathSegList.getItem(1).x, "100");
569 | assert.equal(path1.pathSegList.getItem(1).y, "100");
570 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
571 | assert.equal(path1.pathSegList.getItem(2).x, "100");
572 | assert.equal(path1.pathSegList.getItem(2).y, "0");
573 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoAbs]");
574 | assert.equal(path1.pathSegList.getItem(3).x, "100");
575 | assert.equal(path1.pathSegList.getItem(3).y, "100");
576 | assert.equal(path1.pathSegList.getItem(4).toString(), "[object SVGPathSegLinetoVerticalRel]");
577 | assert.equal(path1.pathSegList.getItem(4).y, "100");
578 | assert.equal(path1.pathSegList.getItem(5).toString(), "[object SVGPathSegLinetoAbs]");
579 | assert.equal(path1.pathSegList.getItem(5).x, "0");
580 | assert.equal(path1.pathSegList.getItem(5).y, "100");
581 |
582 | // Check initial 'pathSegList' value of path2.
583 | assert.equal(path2.pathSegList.numberOfItems, "4");
584 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
585 | assert.equal(path2.pathSegList.getItem(0).x, "0");
586 | assert.equal(path2.pathSegList.getItem(0).y, "0");
587 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoHorizontalRel]");
588 | assert.equal(path2.pathSegList.getItem(1).x, "100");
589 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
590 | assert.equal(path2.pathSegList.getItem(2).x, "200");
591 | assert.equal(path2.pathSegList.getItem(2).y, "100");
592 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
593 | assert.equal(path2.pathSegList.getItem(3).x, "-100");
594 |
595 | // Replace second item with third item of path1.
596 | assert.equal(path1.pathSegList.replaceItem(path1.pathSegList.getItem(2), 1).toString(), "[object SVGPathSegLinetoAbs]");
597 |
598 | // Replace third item of path2 with fourth item of path1.
599 | assert.equal(path2.pathSegList.replaceItem(path1.pathSegList.getItem(4), 2).toString(), "[object SVGPathSegLinetoVerticalRel]");
600 |
601 | // Reset points attribute to M 0 0 L 100 0 v 100.
602 | path1.setAttribute("d", "M 0 0 L 100 0 v 100 h 100");
603 |
604 | // Replace fourth item of path1 with third item of path2.
605 | assert.equal(path1.pathSegList.replaceItem(path2.pathSegList.getItem(3), 3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
606 |
607 | // Check final 'pathSegList' value of path1.
608 | assert.equal(path1.pathSegList.numberOfItems, "4");
609 | assert.equal(path1.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
610 | assert.equal(path1.pathSegList.getItem(0).x, "0");
611 | assert.equal(path1.pathSegList.getItem(0).y, "0");
612 | assert.equal(path1.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
613 | assert.equal(path1.pathSegList.getItem(1).x, "100");
614 | assert.equal(path1.pathSegList.getItem(1).y, "0");
615 | assert.equal(path1.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoVerticalRel]");
616 | assert.equal(path1.pathSegList.getItem(2).y, "100");
617 | assert.equal(path1.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
618 | assert.equal(path1.pathSegList.getItem(3).x, "-100");
619 |
620 | // Check final 'pathSegList' value of path2.
621 | assert.equal(path2.pathSegList.numberOfItems, "4");
622 | assert.equal(path2.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
623 | assert.equal(path2.pathSegList.getItem(0).x, "0");
624 | assert.equal(path2.pathSegList.getItem(0).y, "0");
625 | assert.equal(path2.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoHorizontalRel]");
626 | assert.equal(path2.pathSegList.getItem(1).x, "100");
627 | assert.equal(path2.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoVerticalRel]");
628 | assert.equal(path2.pathSegList.getItem(2).y, "100");
629 | assert.equal(path2.pathSegList.getItem(3).toString(), "[object SVGPathSegLinetoHorizontalRel]");
630 | assert.equal(path2.pathSegList.getItem(3).x, "-100");
631 | });
632 |
633 | // LayoutTests/svg/dom/SVGPathSegList-xml-dom-synchronization.xhtml
634 | QUnit.test("Test how SVGLengthList reacts to XML DOM modifications", function(assert) {
635 | // Cross-browser formatting of the d string, needed so both gecko and blink can use the same test.
636 | function formatDAttribute(string) {
637 | return string.replace(/,/g, " ") // Remove Firefox commas
638 | .replace(/([A-Z])/g, " $1 ") // "M 100 0L 50 0" -> " M 100 0 L 50 0"
639 | .replace(/^\s/, "") // " M 100 0" -> "M 100 0"
640 | .replace(/\s\s/g, " "); // If there was already whitespace between coordinates & commands, fix it up again.
641 | }
642 |
643 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
644 | path.setAttribute("d", "M 200 0 L 100 0 L 100 100");
645 |
646 | assert.equal(path.pathSegList.numberOfItems, "3");
647 |
648 | // Check initial 'd' attribute value.
649 | assert.equal(formatDAttribute(path.getAttribute("d")), "M 200 0 L 100 0 L 100 100");
650 |
651 | // Append one item, check 'd' attribute changed.
652 | path.pathSegList.appendItem(path.createSVGPathSegLinetoAbs(0, 100));
653 | assert.equal(formatDAttribute(path.getAttribute("d")), "M 200 0 L 100 0 L 100 100 L 0 100");
654 |
655 | // Modify first item, check 'd' attribute changed.
656 | path.pathSegList.getItem(0).x -= 100;
657 | assert.equal(formatDAttribute(path.getAttribute("d")), "M 100 0 L 100 0 L 100 100 L 0 100");
658 |
659 | // Modify first item, check 'd' attribute changed, now a green rectangle should be visible.
660 | path.pathSegList.getItem(0).x -= 100;
661 | assert.equal(formatDAttribute(path.getAttribute("d")), "M 0 0 L 100 0 L 100 100 L 0 100");
662 | });
663 |
664 | // LayoutTests/svg/dom/svglist-exception-on-out-bounds-error.html
665 | QUnit.test("Tests that out of bounds accesses of SVGPathSegList correctly throw exceptions", function(assert) {
666 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
667 | var svgList = path.pathSegList;
668 | var indicesToTest = [-Infinity, NaN, -1, 0, 1, Infinity];
669 | for (var i = 0; i < indicesToTest.length; i++) {
670 | var index = indicesToTest[i];
671 | assert.throws(function() {
672 | svgList.getItem(index);
673 | });
674 | assert.throws(function() {
675 | svgList.insertItemBefore(null, index);
676 | });
677 | var seg = path.createSVGPathSegClosePath();
678 | assert.equal(svgList.insertItemBefore(seg, index), seg);
679 | svgList.removeItem(0);
680 | assert.throws(function() {
681 | svgList.replaceItem(seg, index);
682 | });
683 | assert.throws(function() {
684 | svgList.replaceItem(null, index);
685 | });
686 | assert.throws(function() {
687 | svgList.removeItem(index);
688 | });
689 | }
690 | });
691 |
692 | // LayoutTests/svg/dom/svglist-insertItemBefore-appends.html
693 | QUnit.test("Tests that insertItemBefore correctly appends if its index is out of bounds", function(assert) {
694 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
695 | var seg00 = path.createSVGPathSegMovetoAbs(0,0);
696 | var seg01 = path.createSVGPathSegMovetoAbs(0,1);
697 | var seg11 = path.createSVGPathSegMovetoAbs(1,1);
698 | var seg10 = path.createSVGPathSegMovetoAbs(1,0);
699 | var svgList = path.pathSegList;
700 | assert.equal(svgList.numberOfItems, "0");
701 | svgList.appendItem(seg01);
702 | assert.equal(svgList.numberOfItems, "1");
703 | assert.equal(svgList.getItem(0), seg01);
704 | svgList.appendItem(seg11);
705 | assert.equal(svgList.numberOfItems, "2");
706 | assert.equal(svgList.getItem(0), seg01);
707 | assert.equal(svgList.getItem(1), seg11);
708 | svgList.insertItemBefore(seg00, 0);
709 | assert.equal(svgList.numberOfItems, "3");
710 | assert.equal(svgList.getItem(0), seg00);
711 | assert.equal(svgList.getItem(1), seg01);
712 | assert.equal(svgList.getItem(2), seg11);
713 | svgList.insertItemBefore(seg10, 42);
714 | assert.equal(svgList.numberOfItems, "4");
715 | assert.equal(svgList.getItem(0), seg00);
716 | assert.equal(svgList.getItem(1), seg01);
717 | assert.equal(svgList.getItem(2), seg11);
718 | assert.equal(svgList.getItem(3), seg10);
719 | });
720 |
721 | QUnit.test("SVGEdit replaceItem browser sniffing support", function(assert) {
722 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
723 | path.setAttribute("d", "M0,0 10,10");
724 | var seglist = path.pathSegList;
725 | var seg = path.createSVGPathSegLinetoAbs(5,5);
726 | var replaced = seglist.replaceItem(seg, 0);
727 | assert.equal(replaced, seg);
728 | });
729 |
730 | QUnit.test("SVGEdit insertItemBefore browser sniffing support", function(assert) {
731 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
732 | path.setAttribute("d", "M0,0 10,10");
733 | var seglist = path.pathSegList;
734 | var seg = path.createSVGPathSegLinetoAbs(5,5);
735 | var inserted = seglist.insertItemBefore(seg, 0);
736 | assert.equal(inserted, seg);
737 | });
738 |
739 | QUnit.test("Asynchronous mutation observer", function(assert) {
740 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
741 | path.setAttribute("d", "M 1 2 M 3 4 Z");
742 | var segList = path.pathSegList;
743 | var moveToSeg = segList.getItem(1);
744 | assert.equal(moveToSeg.toString(), "[object SVGPathSegMovetoAbs]");
745 | assert.equal(moveToSeg.x, "3");
746 | assert.equal(moveToSeg.y, "4");
747 | assert.equal(segList.numberOfItems, 3);
748 | path.setAttribute("d", "M50,51 L52,53 L54,55Z");
749 |
750 | var done = assert.async();
751 | setTimeout(function() {
752 | // This check is only for the polyfill and should pass whether the polyfill is used or not.
753 | if (SVGPathSegList._pathSegArrayAsString) {
754 | // Ensure the path seg list was updated asynchronously by checking the interal _list
755 | // member which will not synchronize the list automatically.
756 | assert.equal(segList._list.length, "4");
757 | }
758 |
759 | assert.equal(path.pathSegList.numberOfItems, "4");
760 | assert.equal(path.pathSegList.getItem(0).toString(), "[object SVGPathSegMovetoAbs]");
761 | assert.equal(path.pathSegList.getItem(0).x, "50");
762 | assert.equal(path.pathSegList.getItem(0).y, "51");
763 | assert.equal(path.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
764 | assert.equal(path.pathSegList.getItem(1).x, "52");
765 | assert.equal(path.pathSegList.getItem(1).y, "53");
766 | assert.equal(path.pathSegList.getItem(2).toString(), "[object SVGPathSegLinetoAbs]");
767 | assert.equal(path.pathSegList.getItem(2).x, "54");
768 | assert.equal(path.pathSegList.getItem(2).y, "55");
769 | assert.equal(path.pathSegList.getItem(3).toString(), "[object SVGPathSegClosePath]");
770 |
771 | // Path segs tearoffs should still be usable even if they are detached.
772 | assert.equal(moveToSeg.toString(), "[object SVGPathSegMovetoAbs]");
773 | assert.equal(moveToSeg.x, "3");
774 | assert.equal(moveToSeg.y, "4");
775 | moveToSeg.x += 5;
776 | moveToSeg.y += 10;
777 | assert.equal(moveToSeg.x, "8");
778 | assert.equal(moveToSeg.y, "14");
779 |
780 | // Detached path segs should not modify the old list.
781 | assert.equal(path.pathSegList.numberOfItems, "4");
782 | assert.equal(path.pathSegList.getItem(1).toString(), "[object SVGPathSegLinetoAbs]");
783 | assert.equal(path.pathSegList.getItem(1).x, "52");
784 | assert.equal(path.pathSegList.getItem(1).y, "53");
785 | done();
786 | });
787 | });
788 |
789 | QUnit.test("Test getPathSegAtLength length boundary conditions", function(assert) {
790 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
791 |
792 | // Empty path.
793 | path.setAttribute("d", "");
794 | assert.equal(path.getPathSegAtLength(-10), "0");
795 | assert.equal(path.getPathSegAtLength(0), "0");
796 | assert.equal(path.getPathSegAtLength(1), "0");
797 | assert.equal(path.getPathSegAtLength(10), "0");
798 |
799 | // Path with one segment.
800 | path.setAttribute("d", "M1 1");
801 | assert.equal(path.getPathSegAtLength(-10), "0");
802 | assert.equal(path.getPathSegAtLength(0), "0");
803 | assert.equal(path.getPathSegAtLength(1), "0");
804 | assert.equal(path.getPathSegAtLength(10), "0");
805 |
806 | // Path with one close segment.
807 | path.setAttribute("d", "z");
808 | assert.equal(path.getPathSegAtLength(-10), "0");
809 | assert.equal(path.getPathSegAtLength(0), "0");
810 | assert.equal(path.getPathSegAtLength(1), "0");
811 | assert.equal(path.getPathSegAtLength(10), "0");
812 | });
813 |
814 | // LayoutTests/svg/dom/script-tests/svgpath-getPathSegAtLength.js
815 | QUnit.test("Test the getPathSegAtLength API", function(assert) {
816 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
817 | path.setAttribute("d", "M0 0 L0 5 L5 5 L 5 0");
818 |
819 | assert.equal(path.getPathSegAtLength(0), "0");
820 | assert.equal(path.getPathSegAtLength(1), "1");
821 | assert.equal(path.getPathSegAtLength(5), "1");
822 | assert.equal(path.getPathSegAtLength(6), "2");
823 | assert.equal(path.getPathSegAtLength(10), "2");
824 | assert.equal(path.getPathSegAtLength(11), "3");
825 | // WebKit/Opera/FF all return the last path segment if the distance exceeds the actual path length:
826 | assert.equal(path.getPathSegAtLength(16), "3");
827 | assert.equal(path.getPathSegAtLength(20), "3");
828 | assert.equal(path.getPathSegAtLength(24), "3");
829 | assert.equal(path.getPathSegAtLength(25), "3");
830 | assert.equal(path.getPathSegAtLength(100), "3");
831 | });
832 |
833 | // LayoutTests/svg/dom/SVGGeometryElement-valid-arguments.html
834 | QUnit.test("Test invalid arguments when calling getPathSegAtLength", function(assert) {
835 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
836 | assert.throws(function() {
837 | path.getPathSegAtLength();
838 | });
839 | assert.throws(function() {
840 | path.getPathSegAtLength(NaN);
841 | });
842 | assert.throws(function() {
843 | path.getPathSegAtLength(Infinity);
844 | });
845 | });
846 |
847 | QUnit.test("Test getPathSegAtLength with non-trivial paths", function(assert) {
848 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
849 |
850 | // Absolute line-to.
851 | path.setAttribute("d", "M0 0 L0 5 L5 5 L5 0");
852 | assert.equal(path.getPathSegAtLength(0), "0");
853 | assert.equal(path.getPathSegAtLength(1), "1");
854 | assert.equal(path.getPathSegAtLength(5), "1");
855 | assert.equal(path.getPathSegAtLength(6), "2");
856 |
857 | // Relative line-to.
858 | path.setAttribute("d", "M0 0 l0 5 l5 0 l0 -5");
859 | assert.equal(path.getPathSegAtLength(0), "0");
860 | assert.equal(path.getPathSegAtLength(1), "1");
861 | assert.equal(path.getPathSegAtLength(5), "1");
862 | assert.equal(path.getPathSegAtLength(6), "2");
863 |
864 | // Cubic curve.
865 | path.setAttribute("d", "M100,250 C 100,50 400,50 400,250Z");
866 | assert.equal(path.getPathSegAtLength(0), "0");
867 | assert.equal(path.getPathSegAtLength(1), "1");
868 | assert.equal(path.getPathSegAtLength(100), "1");
869 | assert.equal(path.getPathSegAtLength(200), "1");
870 | assert.equal(path.getPathSegAtLength(300), "1");
871 | assert.equal(path.getPathSegAtLength(400), "1");
872 | assert.equal(path.getPathSegAtLength(500), "2");
873 |
874 | // Multiple quadratic curves.
875 | path.setAttribute("d", "M0,0 Q0,0 100,50 T100,100 T300, 300Z");
876 | assert.equal(path.getPathSegAtLength(0), "0");
877 | assert.equal(path.getPathSegAtLength(1), "1");
878 | assert.equal(path.getPathSegAtLength(100), "1");
879 | assert.equal(path.getPathSegAtLength(200), "2");
880 | assert.equal(path.getPathSegAtLength(400), "3");
881 | assert.equal(path.getPathSegAtLength(600), "4");
882 |
883 | // Discontinuous paths.
884 | // This didn't get spec'd (see: https://github.com/w3c/svgwg/issues/282) but had consistent behavior in Edge, Blink, WebKit, and Gecko.
885 | path.setAttribute("d", "M0,0 h100 M100,100 v0 M0,100 h0");
886 | assert.equal(path.getPathSegAtLength(99), "1");
887 | assert.equal(path.getPathSegAtLength(100), "1");
888 | assert.equal(path.getPathSegAtLength(101), "5");
889 | path.setAttribute("d", "M50,50 L150,50 M50,100 L150,100");
890 | assert.equal(path.getPathSegAtLength(99), "1");
891 | assert.equal(path.getPathSegAtLength(100), "1");
892 | assert.equal(path.getPathSegAtLength(101), "3");
893 | });
894 |
895 | QUnit.test("Test PathSegList.length", function(assert) {
896 | var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
897 |
898 | // Empty path.
899 | path.setAttribute("d", "");
900 | assert.equal(path.pathSegList.length, path.pathSegList.numberOfItems);
901 | assert.equal(path.pathSegList.length, 0);
902 |
903 | // Path with one segment.
904 | path.setAttribute("d", "M1 1");
905 | assert.equal(path.pathSegList.length, path.pathSegList.numberOfItems);
906 | assert.equal(path.pathSegList.length, 1);
907 |
908 | // Path with one close segment.
909 | path.setAttribute("d", "z");
910 | assert.equal(path.pathSegList.length, path.pathSegList.numberOfItems);
911 | assert.equal(path.pathSegList.length, 0);
912 |
913 | // Path with two segments and a close.
914 | path.setAttribute("d", "M1 1 L2 2Z");
915 | assert.equal(path.pathSegList.length, path.pathSegList.numberOfItems);
916 | assert.equal(path.pathSegList.length, 3);
917 | });
--------------------------------------------------------------------------------
/pathseg.js:
--------------------------------------------------------------------------------
1 | // SVGPathSeg API polyfill
2 | // https://github.com/progers/pathseg
3 | //
4 | // This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
5 | // SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
6 | // changes which were implemented in Firefox 43 and Chrome 46.
7 |
8 | (function() { "use strict";
9 | // The polyfill only applies to browser environments with a `window` object
10 | // (i.e. not node.js, workers, etc.). If included in one of these
11 | // environments (such as when using 'react-dom/server'), simply return out
12 | if (typeof window === 'undefined')
13 | return;
14 |
15 | if (!("SVGPathSeg" in window)) {
16 | // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
17 | window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
18 | this.pathSegType = type;
19 | this.pathSegTypeAsLetter = typeAsLetter;
20 | this._owningPathSegList = owningPathSegList;
21 | }
22 |
23 | window.SVGPathSeg.prototype.classname = "SVGPathSeg";
24 |
25 | window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
26 | window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
27 | window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
28 | window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
29 | window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
30 | window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
31 | window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
32 | window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
33 | window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
34 | window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
35 | window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
36 | window.SVGPathSeg.PATHSEG_ARC_REL = 11;
37 | window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
38 | window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
39 | window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
40 | window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
41 | window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
42 | window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
43 | window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
44 | window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
45 |
46 | // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
47 | window.SVGPathSeg.prototype._segmentChanged = function() {
48 | if (this._owningPathSegList)
49 | this._owningPathSegList.segmentChanged(this);
50 | }
51 |
52 | window.SVGPathSegClosePath = function(owningPathSegList) {
53 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
54 | }
55 | window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
56 | window.SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; }
57 | window.SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
58 | window.SVGPathSegClosePath.prototype.clone = function() { return new window.SVGPathSegClosePath(undefined); }
59 |
60 | window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
61 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
62 | this._x = x;
63 | this._y = y;
64 | }
65 | window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
66 | window.SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; }
67 | window.SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
68 | window.SVGPathSegMovetoAbs.prototype.clone = function() { return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y); }
69 | Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
70 | Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
71 |
72 | window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
73 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
74 | this._x = x;
75 | this._y = y;
76 | }
77 | window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
78 | window.SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; }
79 | window.SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
80 | window.SVGPathSegMovetoRel.prototype.clone = function() { return new window.SVGPathSegMovetoRel(undefined, this._x, this._y); }
81 | Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
82 | Object.defineProperty(window.SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
83 |
84 | window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
85 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
86 | this._x = x;
87 | this._y = y;
88 | }
89 | window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
90 | window.SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; }
91 | window.SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
92 | window.SVGPathSegLinetoAbs.prototype.clone = function() { return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y); }
93 | Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
94 | Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
95 |
96 | window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
97 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
98 | this._x = x;
99 | this._y = y;
100 | }
101 | window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
102 | window.SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; }
103 | window.SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
104 | window.SVGPathSegLinetoRel.prototype.clone = function() { return new window.SVGPathSegLinetoRel(undefined, this._x, this._y); }
105 | Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
106 | Object.defineProperty(window.SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
107 |
108 | window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
109 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
110 | this._x = x;
111 | this._y = y;
112 | this._x1 = x1;
113 | this._y1 = y1;
114 | this._x2 = x2;
115 | this._y2 = y2;
116 | }
117 | window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
118 | window.SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; }
119 | window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
120 | window.SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
121 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
122 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
123 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
124 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
125 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
126 | Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
127 |
128 | window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
129 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
130 | this._x = x;
131 | this._y = y;
132 | this._x1 = x1;
133 | this._y1 = y1;
134 | this._x2 = x2;
135 | this._y2 = y2;
136 | }
137 | window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
138 | window.SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; }
139 | window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
140 | window.SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
141 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
142 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
143 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
144 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
145 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
146 | Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
147 |
148 | window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
149 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
150 | this._x = x;
151 | this._y = y;
152 | this._x1 = x1;
153 | this._y1 = y1;
154 | }
155 | window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
156 | window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; }
157 | window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
158 | window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
159 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
160 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
161 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
162 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
163 |
164 | window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
165 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
166 | this._x = x;
167 | this._y = y;
168 | this._x1 = x1;
169 | this._y1 = y1;
170 | }
171 | window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
172 | window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; }
173 | window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
174 | window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
175 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
176 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
177 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
178 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
179 |
180 | window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
181 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
182 | this._x = x;
183 | this._y = y;
184 | this._r1 = r1;
185 | this._r2 = r2;
186 | this._angle = angle;
187 | this._largeArcFlag = largeArcFlag;
188 | this._sweepFlag = sweepFlag;
189 | }
190 | window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
191 | window.SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; }
192 | window.SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
193 | window.SVGPathSegArcAbs.prototype.clone = function() { return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
194 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
195 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
196 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
197 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
198 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
199 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
200 | Object.defineProperty(window.SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
201 |
202 | window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
203 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
204 | this._x = x;
205 | this._y = y;
206 | this._r1 = r1;
207 | this._r2 = r2;
208 | this._angle = angle;
209 | this._largeArcFlag = largeArcFlag;
210 | this._sweepFlag = sweepFlag;
211 | }
212 | window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
213 | window.SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; }
214 | window.SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
215 | window.SVGPathSegArcRel.prototype.clone = function() { return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
216 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
217 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
218 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
219 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
220 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
221 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
222 | Object.defineProperty(window.SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
223 |
224 | window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
225 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
226 | this._x = x;
227 | }
228 | window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
229 | window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; }
230 | window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
231 | window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
232 | Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
233 |
234 | window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
235 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
236 | this._x = x;
237 | }
238 | window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
239 | window.SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; }
240 | window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
241 | window.SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x); }
242 | Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
243 |
244 | window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
245 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
246 | this._y = y;
247 | }
248 | window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
249 | window.SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; }
250 | window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
251 | window.SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y); }
252 | Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
253 |
254 | window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
255 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
256 | this._y = y;
257 | }
258 | window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
259 | window.SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; }
260 | window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
261 | window.SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalRel(undefined, this._y); }
262 | Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
263 |
264 | window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
265 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
266 | this._x = x;
267 | this._y = y;
268 | this._x2 = x2;
269 | this._y2 = y2;
270 | }
271 | window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
272 | window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; }
273 | window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
274 | window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
275 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
276 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
277 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
278 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
279 |
280 | window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
281 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
282 | this._x = x;
283 | this._y = y;
284 | this._x2 = x2;
285 | this._y2 = y2;
286 | }
287 | window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
288 | window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; }
289 | window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
290 | window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
291 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
292 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
293 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
294 | Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
295 |
296 | window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
297 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
298 | this._x = x;
299 | this._y = y;
300 | }
301 | window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
302 | window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; }
303 | window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
304 | window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
305 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
306 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
307 |
308 | window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
309 | window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
310 | this._x = x;
311 | this._y = y;
312 | }
313 | window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
314 | window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; }
315 | window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
316 | window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
317 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
318 | Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
319 |
320 | // Add createSVGPathSeg* functions to window.SVGPathElement.
321 | // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
322 | window.SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new window.SVGPathSegClosePath(undefined); }
323 | window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new window.SVGPathSegMovetoAbs(undefined, x, y); }
324 | window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new window.SVGPathSegMovetoRel(undefined, x, y); }
325 | window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new window.SVGPathSegLinetoAbs(undefined, x, y); }
326 | window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new window.SVGPathSegLinetoRel(undefined, x, y); }
327 | window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
328 | window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
329 | window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
330 | window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
331 | window.SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
332 | window.SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
333 | window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new window.SVGPathSegLinetoHorizontalAbs(undefined, x); }
334 | window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new window.SVGPathSegLinetoHorizontalRel(undefined, x); }
335 | window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new window.SVGPathSegLinetoVerticalAbs(undefined, y); }
336 | window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new window.SVGPathSegLinetoVerticalRel(undefined, y); }
337 | window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
338 | window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
339 | window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
340 | window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
341 |
342 | if (!("getPathSegAtLength" in window.SVGPathElement.prototype)) {
343 | // Add getPathSegAtLength to SVGPathElement.
344 | // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
345 | // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
346 | window.SVGPathElement.prototype.getPathSegAtLength = function(distance) {
347 | if (distance === undefined || !isFinite(distance))
348 | throw "Invalid arguments.";
349 |
350 | var measurementElement = document.createElementNS("http://www.w3.org/2000/svg", "path");
351 | measurementElement.setAttribute("d", this.getAttribute("d"));
352 | var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
353 |
354 | // If the path is empty, return 0.
355 | if (lastPathSegment <= 0)
356 | return 0;
357 |
358 | do {
359 | measurementElement.pathSegList.removeItem(lastPathSegment);
360 | if (distance > measurementElement.getTotalLength())
361 | break;
362 | lastPathSegment--;
363 | } while (lastPathSegment > 0);
364 | return lastPathSegment;
365 | }
366 | }
367 | }
368 |
369 | // Checking for SVGPathSegList in window checks for the case of an implementation without the
370 | // SVGPathSegList API.
371 | // The second check for appendItem is specific to Firefox 59+ which removed only parts of the
372 | // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API
373 | // so the polyfill data (i.e., _list) is used throughout.
374 | if (!("SVGPathSegList" in window) || !("appendItem" in window.SVGPathSegList.prototype)) {
375 | // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
376 | window.SVGPathSegList = function(pathElement) {
377 | this._pathElement = pathElement;
378 | this._list = this._parsePath(this._pathElement.getAttribute("d"));
379 |
380 | // Use a MutationObserver to catch changes to the path's "d" attribute.
381 | this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] };
382 | this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
383 | this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
384 | }
385 |
386 | window.SVGPathSegList.prototype.classname = "SVGPathSegList";
387 |
388 | Object.defineProperty(window.SVGPathSegList.prototype, "numberOfItems", {
389 | get: function() {
390 | this._checkPathSynchronizedToList();
391 | return this._list.length;
392 | },
393 | enumerable: true
394 | });
395 |
396 | // The length property was not specified but was in Firefox 58.
397 | Object.defineProperty(window.SVGPathSegList.prototype, "length", {
398 | get: function() {
399 | this._checkPathSynchronizedToList();
400 | return this._list.length;
401 | },
402 | enumerable: true
403 | });
404 |
405 | // Add the pathSegList accessors to window.SVGPathElement.
406 | // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
407 | Object.defineProperty(window.SVGPathElement.prototype, "pathSegList", {
408 | get: function() {
409 | if (!this._pathSegList)
410 | this._pathSegList = new window.SVGPathSegList(this);
411 | return this._pathSegList;
412 | },
413 | enumerable: true
414 | });
415 | // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
416 | Object.defineProperty(window.SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
417 | Object.defineProperty(window.SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
418 | Object.defineProperty(window.SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
419 |
420 | // Process any pending mutations to the path element and update the list as needed.
421 | // This should be the first call of all public functions and is needed because
422 | // MutationObservers are not synchronous so we can have pending asynchronous mutations.
423 | window.SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
424 | this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
425 | }
426 |
427 | window.SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
428 | if (!this._pathElement)
429 | return;
430 | var hasPathMutations = false;
431 | mutationRecords.forEach(function(record) {
432 | if (record.attributeName == "d")
433 | hasPathMutations = true;
434 | });
435 | if (hasPathMutations)
436 | this._list = this._parsePath(this._pathElement.getAttribute("d"));
437 | }
438 |
439 | // Serialize the list and update the path's 'd' attribute.
440 | window.SVGPathSegList.prototype._writeListToPath = function() {
441 | this._pathElementMutationObserver.disconnect();
442 | this._pathElement.setAttribute("d", window.SVGPathSegList._pathSegArrayAsString(this._list));
443 | this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
444 | }
445 |
446 | // When a path segment changes the list needs to be synchronized back to the path element.
447 | window.SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
448 | this._writeListToPath();
449 | }
450 |
451 | window.SVGPathSegList.prototype.clear = function() {
452 | this._checkPathSynchronizedToList();
453 |
454 | this._list.forEach(function(pathSeg) {
455 | pathSeg._owningPathSegList = null;
456 | });
457 | this._list = [];
458 | this._writeListToPath();
459 | }
460 |
461 | window.SVGPathSegList.prototype.initialize = function(newItem) {
462 | this._checkPathSynchronizedToList();
463 |
464 | this._list = [newItem];
465 | newItem._owningPathSegList = this;
466 | this._writeListToPath();
467 | return newItem;
468 | }
469 |
470 | window.SVGPathSegList.prototype._checkValidIndex = function(index) {
471 | if (isNaN(index) || index < 0 || index >= this.numberOfItems)
472 | throw "INDEX_SIZE_ERR";
473 | }
474 |
475 | window.SVGPathSegList.prototype.getItem = function(index) {
476 | this._checkPathSynchronizedToList();
477 |
478 | this._checkValidIndex(index);
479 | return this._list[index];
480 | }
481 |
482 | window.SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
483 | this._checkPathSynchronizedToList();
484 |
485 | // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
486 | if (index > this.numberOfItems)
487 | index = this.numberOfItems;
488 | if (newItem._owningPathSegList) {
489 | // SVG2 spec says to make a copy.
490 | newItem = newItem.clone();
491 | }
492 | this._list.splice(index, 0, newItem);
493 | newItem._owningPathSegList = this;
494 | this._writeListToPath();
495 | return newItem;
496 | }
497 |
498 | window.SVGPathSegList.prototype.replaceItem = function(newItem, index) {
499 | this._checkPathSynchronizedToList();
500 |
501 | if (newItem._owningPathSegList) {
502 | // SVG2 spec says to make a copy.
503 | newItem = newItem.clone();
504 | }
505 | this._checkValidIndex(index);
506 | this._list[index] = newItem;
507 | newItem._owningPathSegList = this;
508 | this._writeListToPath();
509 | return newItem;
510 | }
511 |
512 | window.SVGPathSegList.prototype.removeItem = function(index) {
513 | this._checkPathSynchronizedToList();
514 |
515 | this._checkValidIndex(index);
516 | var item = this._list[index];
517 | this._list.splice(index, 1);
518 | this._writeListToPath();
519 | return item;
520 | }
521 |
522 | window.SVGPathSegList.prototype.appendItem = function(newItem) {
523 | this._checkPathSynchronizedToList();
524 |
525 | if (newItem._owningPathSegList) {
526 | // SVG2 spec says to make a copy.
527 | newItem = newItem.clone();
528 | }
529 | this._list.push(newItem);
530 | newItem._owningPathSegList = this;
531 | // TODO: Optimize this to just append to the existing attribute.
532 | this._writeListToPath();
533 | return newItem;
534 | }
535 |
536 | window.SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
537 | var string = "";
538 | var first = true;
539 | pathSegArray.forEach(function(pathSeg) {
540 | if (first) {
541 | first = false;
542 | string += pathSeg._asPathString();
543 | } else {
544 | string += " " + pathSeg._asPathString();
545 | }
546 | });
547 | return string;
548 | }
549 |
550 | // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
551 | window.SVGPathSegList.prototype._parsePath = function(string) {
552 | if (!string || string.length == 0)
553 | return [];
554 |
555 | var owningPathSegList = this;
556 |
557 | var Builder = function() {
558 | this.pathSegList = [];
559 | }
560 |
561 | Builder.prototype.appendSegment = function(pathSeg) {
562 | this.pathSegList.push(pathSeg);
563 | }
564 |
565 | var Source = function(string) {
566 | this._string = string;
567 | this._currentIndex = 0;
568 | this._endIndex = this._string.length;
569 | this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
570 |
571 | this._skipOptionalSpaces();
572 | }
573 |
574 | Source.prototype._isCurrentSpace = function() {
575 | var character = this._string[this._currentIndex];
576 | return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
577 | }
578 |
579 | Source.prototype._skipOptionalSpaces = function() {
580 | while (this._currentIndex < this._endIndex && this._isCurrentSpace())
581 | this._currentIndex++;
582 | return this._currentIndex < this._endIndex;
583 | }
584 |
585 | Source.prototype._skipOptionalSpacesOrDelimiter = function() {
586 | if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",")
587 | return false;
588 | if (this._skipOptionalSpaces()) {
589 | if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
590 | this._currentIndex++;
591 | this._skipOptionalSpaces();
592 | }
593 | }
594 | return this._currentIndex < this._endIndex;
595 | }
596 |
597 | Source.prototype.hasMoreData = function() {
598 | return this._currentIndex < this._endIndex;
599 | }
600 |
601 | Source.prototype.peekSegmentType = function() {
602 | var lookahead = this._string[this._currentIndex];
603 | return this._pathSegTypeFromChar(lookahead);
604 | }
605 |
606 | Source.prototype._pathSegTypeFromChar = function(lookahead) {
607 | switch (lookahead) {
608 | case "Z":
609 | case "z":
610 | return window.SVGPathSeg.PATHSEG_CLOSEPATH;
611 | case "M":
612 | return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
613 | case "m":
614 | return window.SVGPathSeg.PATHSEG_MOVETO_REL;
615 | case "L":
616 | return window.SVGPathSeg.PATHSEG_LINETO_ABS;
617 | case "l":
618 | return window.SVGPathSeg.PATHSEG_LINETO_REL;
619 | case "C":
620 | return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
621 | case "c":
622 | return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
623 | case "Q":
624 | return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
625 | case "q":
626 | return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
627 | case "A":
628 | return window.SVGPathSeg.PATHSEG_ARC_ABS;
629 | case "a":
630 | return window.SVGPathSeg.PATHSEG_ARC_REL;
631 | case "H":
632 | return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
633 | case "h":
634 | return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
635 | case "V":
636 | return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
637 | case "v":
638 | return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
639 | case "S":
640 | return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
641 | case "s":
642 | return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
643 | case "T":
644 | return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
645 | case "t":
646 | return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
647 | default:
648 | return window.SVGPathSeg.PATHSEG_UNKNOWN;
649 | }
650 | }
651 |
652 | Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
653 | // Check for remaining coordinates in the current command.
654 | if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
655 | if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
656 | return window.SVGPathSeg.PATHSEG_LINETO_ABS;
657 | if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
658 | return window.SVGPathSeg.PATHSEG_LINETO_REL;
659 | return previousCommand;
660 | }
661 | return window.SVGPathSeg.PATHSEG_UNKNOWN;
662 | }
663 |
664 | Source.prototype.initialCommandIsMoveTo = function() {
665 | // If the path is empty it is still valid, so return true.
666 | if (!this.hasMoreData())
667 | return true;
668 | var command = this.peekSegmentType();
669 | // Path must start with moveTo.
670 | return command == window.SVGPathSeg.PATHSEG_MOVETO_ABS || command == window.SVGPathSeg.PATHSEG_MOVETO_REL;
671 | }
672 |
673 | // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
674 | // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
675 | Source.prototype._parseNumber = function() {
676 | var exponent = 0;
677 | var integer = 0;
678 | var frac = 1;
679 | var decimal = 0;
680 | var sign = 1;
681 | var expsign = 1;
682 |
683 | var startIndex = this._currentIndex;
684 |
685 | this._skipOptionalSpaces();
686 |
687 | // Read the sign.
688 | if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
689 | this._currentIndex++;
690 | else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
691 | this._currentIndex++;
692 | sign = -1;
693 | }
694 |
695 | if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != "."))
696 | // The first character of a number must be one of [0-9+-.].
697 | return undefined;
698 |
699 | // Read the integer part, build right-to-left.
700 | var startIntPartIndex = this._currentIndex;
701 | while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
702 | this._currentIndex++; // Advance to first non-digit.
703 |
704 | if (this._currentIndex != startIntPartIndex) {
705 | var scanIntPartIndex = this._currentIndex - 1;
706 | var multiplier = 1;
707 | while (scanIntPartIndex >= startIntPartIndex) {
708 | integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
709 | multiplier *= 10;
710 | }
711 | }
712 |
713 | // Read the decimals.
714 | if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
715 | this._currentIndex++;
716 |
717 | // There must be a least one digit following the .
718 | if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
719 | return undefined;
720 | while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
721 | frac *= 10;
722 | decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
723 | this._currentIndex += 1;
724 | }
725 | }
726 |
727 | // Read the exponent part.
728 | if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) {
729 | this._currentIndex++;
730 |
731 | // Read the sign of the exponent.
732 | if (this._string.charAt(this._currentIndex) == "+") {
733 | this._currentIndex++;
734 | } else if (this._string.charAt(this._currentIndex) == "-") {
735 | this._currentIndex++;
736 | expsign = -1;
737 | }
738 |
739 | // There must be an exponent.
740 | if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
741 | return undefined;
742 |
743 | while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
744 | exponent *= 10;
745 | exponent += (this._string.charAt(this._currentIndex) - "0");
746 | this._currentIndex++;
747 | }
748 | }
749 |
750 | var number = integer + decimal;
751 | number *= sign;
752 |
753 | if (exponent)
754 | number *= Math.pow(10, expsign * exponent);
755 |
756 | if (startIndex == this._currentIndex)
757 | return undefined;
758 |
759 | this._skipOptionalSpacesOrDelimiter();
760 |
761 | return number;
762 | }
763 |
764 | Source.prototype._parseArcFlag = function() {
765 | if (this._currentIndex >= this._endIndex)
766 | return undefined;
767 | var flag = false;
768 | var flagChar = this._string.charAt(this._currentIndex++);
769 | if (flagChar == "0")
770 | flag = false;
771 | else if (flagChar == "1")
772 | flag = true;
773 | else
774 | return undefined;
775 |
776 | this._skipOptionalSpacesOrDelimiter();
777 | return flag;
778 | }
779 |
780 | Source.prototype.parseSegment = function() {
781 | var lookahead = this._string[this._currentIndex];
782 | var command = this._pathSegTypeFromChar(lookahead);
783 | if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
784 | // Possibly an implicit command. Not allowed if this is the first command.
785 | if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
786 | return null;
787 | command = this._nextCommandHelper(lookahead, this._previousCommand);
788 | if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
789 | return null;
790 | } else {
791 | this._currentIndex++;
792 | }
793 |
794 | this._previousCommand = command;
795 |
796 | switch (command) {
797 | case window.SVGPathSeg.PATHSEG_MOVETO_REL:
798 | return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
799 | case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
800 | return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
801 | case window.SVGPathSeg.PATHSEG_LINETO_REL:
802 | return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
803 | case window.SVGPathSeg.PATHSEG_LINETO_ABS:
804 | return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
805 | case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
806 | return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
807 | case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
808 | return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
809 | case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
810 | return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
811 | case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
812 | return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
813 | case window.SVGPathSeg.PATHSEG_CLOSEPATH:
814 | this._skipOptionalSpaces();
815 | return new window.SVGPathSegClosePath(owningPathSegList);
816 | case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
817 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
818 | return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
819 | case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
820 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
821 | return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
822 | case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
823 | var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
824 | return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
825 | case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
826 | var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
827 | return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
828 | case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
829 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
830 | return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
831 | case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
832 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
833 | return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
834 | case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
835 | return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
836 | case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
837 | return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
838 | case window.SVGPathSeg.PATHSEG_ARC_REL:
839 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
840 | return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
841 | case window.SVGPathSeg.PATHSEG_ARC_ABS:
842 | var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
843 | return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
844 | default:
845 | throw "Unknown path seg type."
846 | }
847 | }
848 |
849 | var builder = new Builder();
850 | var source = new Source(string);
851 |
852 | if (!source.initialCommandIsMoveTo())
853 | return [];
854 | while (source.hasMoreData()) {
855 | var pathSeg = source.parseSegment();
856 | if (!pathSeg)
857 | return [];
858 | builder.appendSegment(pathSeg);
859 | }
860 |
861 | return builder.pathSegList;
862 | }
863 | }
864 | }());
865 |
--------------------------------------------------------------------------------