svg_parsers_test.dart 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import 'dart:ui' show PathFillType;
  2. import 'package:flutter_svg/parser.dart';
  3. import 'package:flutter_svg/src/svg/parsers.dart';
  4. import 'package:flutter_svg/src/vector_drawable.dart';
  5. import 'package:test/test.dart';
  6. import 'package:vector_math/vector_math_64.dart';
  7. void main() {
  8. test('SVG Multiple transform parser tests', () {
  9. Matrix4 expected = Matrix4.identity();
  10. expected.translate(0.338957, 0.010104, 0);
  11. expected.translate(-0.5214, 0.125, 0);
  12. expected.translate(0.987, 0.789, 0);
  13. expect(
  14. parseTransform(
  15. 'translate(0.338957,0.010104), translate(-0.5214,0.125),translate(0.987,0.789)'),
  16. expected);
  17. expected = Matrix4.translationValues(0.338957, 0.010104, 0);
  18. expected.scale(0.869768, 1.000000, 1.0);
  19. expect(
  20. parseTransform('translate(0.338957,0.010104),scale(0.869768,1.000000)'),
  21. expected);
  22. });
  23. test('SVG Transform parser tests', () {
  24. expect(() => parseTransform('invalid'), throwsStateError);
  25. expect(() => parseTransform('transformunsupported(0,0)'), throwsStateError);
  26. expect(parseTransform('skewX(60)'), Matrix4.skewX(60.0));
  27. expect(parseTransform('skewY(60)'), Matrix4.skewY(60.0));
  28. expect(parseTransform('translate(10,0.0)'),
  29. Matrix4.translationValues(10.0, 0.0, 0.0));
  30. expect(parseTransform('skewX(60)'), Matrix4.skewX(60.0));
  31. expect(parseTransform('scale(10)'),
  32. Matrix4.identity()..scale(10.0, 10.0, 1.0));
  33. expect(parseTransform('scale(10, 15)'),
  34. Matrix4.identity()..scale(10.0, 15.0, 1.0));
  35. expect(parseTransform('rotate(20)'), Matrix4.rotationZ(radians(20.0)));
  36. expect(
  37. parseTransform('rotate(20, 30)'),
  38. Matrix4.identity()
  39. ..translate(30.0, 30.0)
  40. ..rotateZ(radians(20.0))
  41. ..translate(-30.0, -30.0));
  42. expect(
  43. parseTransform('rotate(20, 30, 40)'),
  44. Matrix4.identity()
  45. ..translate(30.0, 40.0)
  46. ..rotateZ(radians(20.0))
  47. ..translate(-30.0, -40.0));
  48. expect(
  49. parseTransform('matrix(1.5, 2.0, 3.0, 4.0, 5.0, 6.0)'),
  50. Matrix4.fromList(<double>[
  51. 1.5, 2.0, 0.0, 0.0, //
  52. 3.0, 4.0, 0.0, 0.0,
  53. 0.0, 0.0, 1.0, 0.0,
  54. 5.0, 6.0, 0.0, 1.0
  55. ]));
  56. expect(
  57. parseTransform('matrix(1.5, 2.0, 3.0, 4.0, 5.0, 6.0 )'),
  58. Matrix4.fromList(<double>[
  59. 1.5, 2.0, 0.0, 0.0, //
  60. 3.0, 4.0, 0.0, 0.0,
  61. 0.0, 0.0, 1.0, 0.0,
  62. 5.0, 6.0, 0.0, 1.0
  63. ]));
  64. expect(parseTransform('rotate(20)\n\tscale(10)'),
  65. Matrix4.rotationZ(radians(20.0))..scale(10.0, 10.0, 1.0));
  66. });
  67. test('FillRule tests', () {
  68. expect(parseRawFillRule(''), PathFillType.nonZero);
  69. expect(parseRawFillRule(null), isNull);
  70. expect(parseRawFillRule('inherit'), isNull);
  71. expect(parseRawFillRule('nonzero'), PathFillType.nonZero);
  72. expect(parseRawFillRule('evenodd'), PathFillType.evenOdd);
  73. expect(parseRawFillRule('invalid'), PathFillType.nonZero);
  74. });
  75. test('TextAnchor tests', () {
  76. expect(parseTextAnchor(''), DrawableTextAnchorPosition.start);
  77. expect(parseTextAnchor(null), DrawableTextAnchorPosition.start);
  78. expect(parseTextAnchor('inherit'), isNull);
  79. expect(parseTextAnchor('start'), DrawableTextAnchorPosition.start);
  80. expect(parseTextAnchor('middle'), DrawableTextAnchorPosition.middle);
  81. expect(parseTextAnchor('end'), DrawableTextAnchorPosition.end);
  82. });
  83. T find<T extends Drawable>(Drawable drawable, String id) {
  84. if (drawable?.id == id && drawable is T) {
  85. return drawable;
  86. }
  87. if (drawable is DrawableParent) {
  88. final DrawableParent parent = drawable;
  89. for (Drawable item in parent.children) {
  90. final Drawable found = find<T>(item, id);
  91. if (found != null) {
  92. return found as T;
  93. }
  94. }
  95. }
  96. return null;
  97. }
  98. test('Font size parsing tests', () {
  99. expect(parseFontSize(null), isNull);
  100. expect(parseFontSize(''), isNull);
  101. expect(parseFontSize('1'), 1);
  102. expect(parseFontSize(' 1 '), 1);
  103. expect(parseFontSize('xx-small'), 10);
  104. expect(parseFontSize('x-small'), 12);
  105. expect(parseFontSize('small'), 14);
  106. expect(parseFontSize('medium'), 18);
  107. expect(parseFontSize('large'), 22);
  108. expect(parseFontSize('x-large'), 26);
  109. expect(parseFontSize('xx-large'), 32);
  110. expect(parseFontSize('larger'), parseFontSize('large'));
  111. expect(parseFontSize('larger', parentValue: parseFontSize('large')),
  112. parseFontSize('large') * 1.2);
  113. expect(parseFontSize('smaller'), parseFontSize('small'));
  114. expect(parseFontSize('smaller', parentValue: parseFontSize('large')),
  115. parseFontSize('large') / 1.2);
  116. expect(() => parseFontSize('invalid'),
  117. throwsA(const TypeMatcher<StateError>()));
  118. });
  119. test('Check no child with id for svg', () async {
  120. final SvgParser parser = SvgParser();
  121. final DrawableRoot root = await parser.parse(
  122. '<svg id="test" viewBox="0 0 10 10"><text /></svg>',
  123. );
  124. expect(root.children.isEmpty, true);
  125. expect(root.id == 'test', true);
  126. });
  127. test('Check any ids', () async {
  128. const String svgStr =
  129. '''<svg id="svgRoot" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 166 202">
  130. <defs>
  131. <linearGradient id="triangleGradient">
  132. <stop offset="20%" stop-color="#000000" stop-opacity=".55" />
  133. <stop offset="85%" stop-color="#616161" stop-opacity=".01" />
  134. </linearGradient>
  135. <linearGradient id="rectangleGradient" x1="0%" x2="0%" y1="0%" y2="100%">
  136. <stop offset="20%" stop-color="#000000" stop-opacity=".15" />
  137. <stop offset="85%" stop-color="#616161" stop-opacity=".01" />
  138. </linearGradient>
  139. </defs>
  140. <path id="path1" fill="#42A5F5" fill-opacity=".8" d="M37.7 128.9 9.8 101 100.4 10.4 156.2 10.4"/>
  141. <path id="path2" fill="#42A5F5" fill-opacity=".8" d="M156.2 94 100.4 94 79.5 114.9 107.4 142.8"/>
  142. <path id="path3" fill="#0D47A1" d="M79.5 170.7 100.4 191.6 156.2 191.6 156.2 191.6 107.4 142.8"/>
  143. <g id="group1" transform="matrix(0.7071, -0.7071, 0.7071, 0.7071, -77.667, 98.057)">
  144. <rect width="39.4" height="39.4" x="59.8" y="123.1" fill="#42A5F5" />
  145. <rect width="39.4" height="5.5" x="59.8" y="162.5" fill="url(#rectangleGradient)" />
  146. </g>
  147. <path id="path4" d="M79.5 170.7 120.9 156.4 107.4 142.8" fill="url(#triangleGradient)" />
  148. </svg>''';
  149. final SvgParser parser = SvgParser();
  150. final DrawableRoot root = await parser.parse(svgStr);
  151. expect(root.id == 'svgRoot', true);
  152. expect(find<DrawableGroup>(root, 'group1') != null, true);
  153. expect(find<DrawableShape>(root, 'path1') != null, true);
  154. expect(find<DrawableShape>(root, 'path2') != null, true);
  155. expect(find<DrawableShape>(root, 'path3') != null, true);
  156. expect(find<DrawableShape>(root, 'path4') != null, true);
  157. });
  158. test('Check No Svg id', () async {
  159. const String svgStr = '''<?xml version="1.0" encoding="UTF-8"?>
  160. <svg width="27px" height="90px" viewBox="5 10 18 70" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  161. <!-- Generator: Sketch 53 (72520) - https://sketchapp.com -->
  162. <title>svg/stick_figure</title>
  163. <desc>Created with Sketch.</desc>
  164. <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
  165. <g id="iPhone-8" transform="translate(-53.000000, -359.000000)" stroke="#979797">
  166. <g id="stick_figure" transform="translate(53.000000, 359.000000)">
  167. <ellipse id="Oval" fill="#D8D8D8" cx="13.5" cy="12" rx="12" ry="11.5"></ellipse>
  168. <path d="M13.5,24 L13.5,71.5" id="Line" stroke-linecap="square"></path>
  169. <path d="M13.5,71.5 L1,89.5" id="Line-1" stroke-linecap="square"></path>
  170. <path d="M13.5,37.5 L1,55.5" id="Line-2" stroke-linecap="square"></path>
  171. <path d="M26.5,71.5 L14,89.5" id="Line-3" stroke-linecap="square" transform="translate(20.000000, 80.500000) scale(-1, 1) translate(-20.000000, -80.500000) "></path>
  172. <path d="M26.5,37.5 L14,55.5" id="Line-2-Copy" stroke-linecap="square" transform="translate(20.000000, 46.500000) scale(-1, 1) translate(-20.000000, -46.500000) "></path>
  173. </g>
  174. </g>
  175. </g>
  176. </svg>''';
  177. final SvgParser parser = SvgParser();
  178. final DrawableRoot root = await parser.parse(svgStr);
  179. expect(root.id.isEmpty, true);
  180. expect(find<DrawableGroup>(root, 'Page-1') != null, true);
  181. expect(find<DrawableGroup>(root, 'iPhone-8') != null, true);
  182. expect(find<DrawableGroup>(root, 'stick_figure') != null, true);
  183. expect(find<DrawableShape>(root, 'Oval') != null, true);
  184. });
  185. }