@@ -18,6 +18,10 @@ const CLIP_PATH_TAG_NAME: &str = "clipPath";
1818const PATH_TAG_NAME : & str = "path" ;
1919const POLYLINE_TAG_NAME : & str = "polyline" ;
2020const 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" ;
2125const GROUP_TAG_NAME : & str = "g" ;
2226
2327pub trait XmlVisitor {
@@ -57,8 +61,8 @@ impl<'a, T: Turtle> XmlVisitor for ConversionVisitor<'a, T> {
5761 }
5862
5963 // 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 ( ) ;
6266 warn ! ( "transform-origin not supported yet" ) ;
6367 }
6468
@@ -197,6 +201,157 @@ impl<'a, T: Turtle> XmlVisitor for ConversionVisitor<'a, T> {
197201 warn ! ( "There is a {name} node containing no actual path: {node:?}" ) ;
198202 }
199203 }
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+ }
200355 // No-op tags
201356 SVG_TAG_NAME | GROUP_TAG_NAME => { }
202357 _ => {
0 commit comments