@@ -18,6 +18,10 @@ const CLIP_PATH_TAG_NAME: &str = "clipPath";
18
18
const PATH_TAG_NAME : & str = "path" ;
19
19
const POLYLINE_TAG_NAME : & str = "polyline" ;
20
20
const POLYGON_TAG_NAME : & str = "polygon" ;
21
+ const RECT_TAG_NAME : & str = "rect" ;
22
+ const CIRCLE_TAG_NAME : & str = "circle" ;
23
+ const ELLIPSE_TAG_NAME : & str = "ellipse" ;
24
+ const LINE_TAG_NAME : & str = "line" ;
21
25
const GROUP_TAG_NAME : & str = "g" ;
22
26
23
27
pub trait XmlVisitor {
@@ -57,8 +61,8 @@ impl<'a, T: Turtle> XmlVisitor for ConversionVisitor<'a, T> {
57
61
}
58
62
59
63
// TODO: https://www.w3.org/TR/css-transforms-1/#transform-origin-property
60
- if let Some ( origin) = node. attribute ( "transform-origin" ) . map ( PointsParser :: from) {
61
- let _origin = PointsParser :: from ( origin) . next ( ) ;
64
+ if let Some ( mut origin) = node. attribute ( "transform-origin" ) . map ( PointsParser :: from) {
65
+ let _origin = origin. next ( ) ;
62
66
warn ! ( "transform-origin not supported yet" ) ;
63
67
}
64
68
@@ -197,6 +201,157 @@ impl<'a, T: Turtle> XmlVisitor for ConversionVisitor<'a, T> {
197
201
warn ! ( "There is a {name} node containing no actual path: {node:?}" ) ;
198
202
}
199
203
}
204
+ RECT_TAG_NAME => {
205
+ let x = self . length_attr_to_user_units ( & node, "x" ) . unwrap_or ( 0. ) ;
206
+ let y = self . length_attr_to_user_units ( & node, "y" ) . unwrap_or ( 0. ) ;
207
+ let width = self . length_attr_to_user_units ( & node, "width" ) ;
208
+ let height = self . length_attr_to_user_units ( & node, "height" ) ;
209
+ let rx = self . length_attr_to_user_units ( & node, "rx" ) . unwrap_or ( 0. ) ;
210
+ let ry = self . length_attr_to_user_units ( & node, "ry" ) . unwrap_or ( 0. ) ;
211
+ let has_radius = rx > 0. && ry > 0. ;
212
+
213
+ match ( width, height) {
214
+ ( Some ( width) , Some ( height) ) => {
215
+ self . comment ( & node) ;
216
+ apply_path (
217
+ & mut self . terrarium ,
218
+ [
219
+ MoveTo {
220
+ abs : true ,
221
+ x : x + rx,
222
+ y,
223
+ } ,
224
+ HorizontalLineTo {
225
+ abs : true ,
226
+ x : x + width - rx,
227
+ } ,
228
+ EllipticalArc {
229
+ abs : true ,
230
+ rx,
231
+ ry,
232
+ x_axis_rotation : 0. ,
233
+ large_arc : false ,
234
+ sweep : true ,
235
+ x : x + width,
236
+ y : y + ry,
237
+ } ,
238
+ VerticalLineTo {
239
+ abs : true ,
240
+ y : y + height - ry,
241
+ } ,
242
+ EllipticalArc {
243
+ abs : true ,
244
+ rx,
245
+ ry,
246
+ x_axis_rotation : 0. ,
247
+ large_arc : false ,
248
+ sweep : true ,
249
+ x : x + width - rx,
250
+ y : y + height,
251
+ } ,
252
+ HorizontalLineTo {
253
+ abs : true ,
254
+ x : x + rx,
255
+ } ,
256
+ EllipticalArc {
257
+ abs : true ,
258
+ rx,
259
+ ry,
260
+ x_axis_rotation : 0. ,
261
+ large_arc : false ,
262
+ sweep : true ,
263
+ x,
264
+ y : y + height - ry,
265
+ } ,
266
+ VerticalLineTo {
267
+ abs : true ,
268
+ y : y + ry,
269
+ } ,
270
+ EllipticalArc {
271
+ abs : true ,
272
+ rx,
273
+ ry,
274
+ x_axis_rotation : 0. ,
275
+ large_arc : false ,
276
+ sweep : true ,
277
+ x : x + rx,
278
+ y,
279
+ } ,
280
+ ClosePath { abs : true } ,
281
+ ]
282
+ . into_iter ( )
283
+ . filter ( |p| has_radius || !matches ! ( p, EllipticalArc { .. } ) ) ,
284
+ )
285
+ }
286
+ _other => {
287
+ warn ! ( "Invalid rectangle node: {node:?}" ) ;
288
+ }
289
+ }
290
+ }
291
+ CIRCLE_TAG_NAME | ELLIPSE_TAG_NAME => {
292
+ let cx = self . length_attr_to_user_units ( & node, "cx" ) . unwrap_or ( 0. ) ;
293
+ let cy = self . length_attr_to_user_units ( & node, "cy" ) . unwrap_or ( 0. ) ;
294
+ let r = self . length_attr_to_user_units ( & node, "r" ) . unwrap_or ( 0. ) ;
295
+ let rx = self . length_attr_to_user_units ( & node, "rx" ) . unwrap_or ( r) ;
296
+ let ry = self . length_attr_to_user_units ( & node, "ry" ) . unwrap_or ( r) ;
297
+ if rx > 0. && ry > 0. {
298
+ self . comment ( & node) ;
299
+ apply_path (
300
+ & mut self . terrarium ,
301
+ std:: iter:: once ( MoveTo {
302
+ abs : true ,
303
+ x : cx + rx,
304
+ y : cy,
305
+ } )
306
+ . chain (
307
+ [ ( cx, cy + ry) , ( cx - rx, cy) , ( cx, cy - ry) , ( cx + rx, cy) ] . map (
308
+ |( x, y) | EllipticalArc {
309
+ abs : true ,
310
+ rx,
311
+ ry,
312
+ x_axis_rotation : 0. ,
313
+ large_arc : false ,
314
+ sweep : true ,
315
+ x,
316
+ y,
317
+ } ,
318
+ ) ,
319
+ )
320
+ . chain ( std:: iter:: once ( ClosePath { abs : true } ) ) ,
321
+ ) ;
322
+ } else {
323
+ warn ! ( "Invalid {} node: {node:?}" , node. tag_name( ) . name( ) ) ;
324
+ }
325
+ }
326
+ LINE_TAG_NAME => {
327
+ let x1 = self . length_attr_to_user_units ( & node, "x1" ) ;
328
+ let y1 = self . length_attr_to_user_units ( & node, "y1" ) ;
329
+ let x2 = self . length_attr_to_user_units ( & node, "x2" ) ;
330
+ let y2 = self . length_attr_to_user_units ( & node, "y2" ) ;
331
+ match ( x1, y1, x2, y2) {
332
+ ( Some ( x1) , Some ( y1) , Some ( x2) , Some ( y2) ) => {
333
+ self . comment ( & node) ;
334
+ apply_path (
335
+ & mut self . terrarium ,
336
+ [
337
+ MoveTo {
338
+ abs : true ,
339
+ x : x1,
340
+ y : y1,
341
+ } ,
342
+ LineTo {
343
+ abs : true ,
344
+ x : x2,
345
+ y : y2,
346
+ } ,
347
+ ] ,
348
+ ) ;
349
+ }
350
+ _other => {
351
+ warn ! ( "Invalid line node: {node:?}" ) ;
352
+ }
353
+ }
354
+ }
200
355
// No-op tags
201
356
SVG_TAG_NAME | GROUP_TAG_NAME => { }
202
357
_ => {
0 commit comments