Skip to content

Instantly share code, notes, and snippets.

@kangabru
Created October 4, 2020 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kangabru/20bf4c0fb4265a3b6a5ec6e752e37067 to your computer and use it in GitHub Desktop.
Save kangabru/20bf4c0fb4265a3b6a5ec6e752e37067 to your computer and use it in GitHub Desktop.
// Copyright (c) 2018 Dan Field
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// Modified from flutter_svg: ^0.17.3+1
// package:flutter_svg/src/svg/parser_state.dart
import 'dart:ui';
import 'package:path_drawing/path_drawing.dart';
import 'package:xml/xml.dart';
Path xmlToPath(XmlElement elem) {
var tag = elem.name.toString();
return _svgPathFuncs[tag](elem);
}
typedef _PathFunc = Path Function(XmlElement elem);
const Map<String, _PathFunc> _svgPathFuncs = <String, _PathFunc>{
'circle': _Paths.circle,
'path': _Paths.path,
'rect': _Paths.rect,
'polygon': _Paths.polygon,
'polyline': _Paths.polyline,
'ellipse': _Paths.ellipse,
'line': _Paths.line,
};
get validTags => _svgPathFuncs.keys.toList();
class _Paths {
static Path circle(XmlElement elem) {
final double cx = parseDouble(getAttribute(elem, 'cx', def: '0'));
final double cy = parseDouble(getAttribute(elem, 'cy', def: '0'));
final double r = parseDouble(getAttribute(elem, 'r', def: '0'));
final Rect oval = Rect.fromCircle(center: Offset(cx, cy), radius: r);
return Path()..addOval(oval);
}
static Path path(XmlElement elem) {
final String d = getAttribute(elem, 'd');
return parseSvgPathData(d);
}
static Path rect(XmlElement elem) {
final double x = parseDouble(getAttribute(elem, 'x', def: '0'));
final double y = parseDouble(getAttribute(elem, 'y', def: '0'));
final double w = parseDouble(getAttribute(elem, 'width', def: '0'));
final double h = parseDouble(getAttribute(elem, 'height', def: '0'));
final Rect rect = Rect.fromLTWH(x, y, w, h);
String rxRaw = getAttribute(elem, 'rx', def: null);
String ryRaw = getAttribute(elem, 'ry', def: null);
rxRaw ??= ryRaw;
ryRaw ??= rxRaw;
if (rxRaw != null && rxRaw != '') {
final double rx = parseDouble(rxRaw);
final double ry = parseDouble(ryRaw);
return Path()..addRRect(RRect.fromRectXY(rect, rx, ry));
}
return Path()..addRect(rect);
}
static Path polygon(XmlElement elem) {
return parsePathFromPoints(elem, true);
}
static Path polyline(XmlElement elem) {
return parsePathFromPoints(elem, false);
}
static Path parsePathFromPoints(XmlElement elem, bool close) {
final String points = getAttribute(elem, 'points');
if (points == '') {
return null;
}
final String path = 'M$points${close ? 'z' : ''}';
return parseSvgPathData(path);
}
static Path ellipse(XmlElement elem) {
final double cx = parseDouble(getAttribute(elem, 'cx', def: '0'));
final double cy = parseDouble(getAttribute(elem, 'cy', def: '0'));
final double rx = parseDouble(getAttribute(elem, 'rx', def: '0'));
final double ry = parseDouble(getAttribute(elem, 'ry', def: '0'));
final Rect r = Rect.fromLTWH(cx - rx, cy - ry, rx * 2, ry * 2);
return Path()..addOval(r);
}
static Path line(XmlElement elem) {
final double x1 = parseDouble(getAttribute(elem, 'x1', def: '0'));
final double x2 = parseDouble(getAttribute(elem, 'x2', def: '0'));
final double y1 = parseDouble(getAttribute(elem, 'y1', def: '0'));
final double y2 = parseDouble(getAttribute(elem, 'y2', def: '0'));
return Path()
..moveTo(x1, y1)
..lineTo(x2, y2);
}
}
String getAttribute(XmlElement elem, String attr, {String def}) =>
elem.getAttribute(attr) ?? def;
/// Parses a `String` to a `double`.
/// Passing `null` will return `null`.
/// Will strip off a `px` prefix.
double parseDouble(String maybeDouble, {bool tryParse = false}) {
assert(tryParse != null);
if (maybeDouble == null) {
return null;
}
maybeDouble = maybeDouble.trim().replaceFirst('px', '').trim();
if (tryParse) {
return double.tryParse(maybeDouble);
}
return double.parse(maybeDouble);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment