From 3dca054becae784abfab484c24de6d3dbc2a36f4 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 6 Apr 2021 16:07:14 -0700 Subject: [PATCH 001/142] Fix sizing issues (#529) --- CHANGELOG.md | 5 +++++ lib/svg.dart | 38 +++++++++++++++++++++----------------- pubspec.yaml | 2 +- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9293866..f8e85d09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 0.21.0-nullsafety.1 + +- Fix bug introduced when width and height are both null on the widget. +- Use more efficient method for XML attribute parsing. + ## 0.21.0-nullsafety.0 - Fix sizing when both width and height are null. This is potentially breaking. diff --git a/lib/svg.dart b/lib/svg.dart index 5a1558ea..d151f945 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -766,26 +766,30 @@ class _SvgPictureState extends State { height = width / viewport.width * viewport.height; } - child = FittedBox( - fit: widget.fit, - alignment: widget.alignment, - clipBehavior: widget.clipBehavior, - child: SizedBox.fromSize( - size: viewport.size, - child: RawPicture( - _picture, - matchTextDirection: widget.matchTextDirection, - allowDrawingOutsideViewBox: widget.allowDrawingOutsideViewBox, + if (height == null && width == null) { + height = viewport.height; + width = viewport.width; + } + assert(height != null); + assert(width != null); + + child = SizedBox( + width: width, + height: height, + child: FittedBox( + fit: widget.fit, + alignment: widget.alignment, + clipBehavior: widget.clipBehavior, + child: SizedBox.fromSize( + size: viewport.size, + child: RawPicture( + _picture, + matchTextDirection: widget.matchTextDirection, + allowDrawingOutsideViewBox: widget.allowDrawingOutsideViewBox, + ), ), ), ); - if (width != null && height != null) { - child = SizedBox( - width: width, - height: height, - child: child, - ); - } if (widget.pictureProvider.colorFilter == null && widget.colorFilter != null) { diff --git a/pubspec.yaml b/pubspec.yaml index 821fd031..dd2e1c5d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.21.0-nullsafety.0 +version: 0.21.0-nullsafety.1 dependencies: flutter: From 7c6d9ad4f9d76ad34894f10f1ead9b225dc5d6b9 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 6 Apr 2021 16:15:54 -0700 Subject: [PATCH 002/142] stable nullsafe release --- CHANGELOG.md | 4 ++++ pubspec.yaml | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8e85d09..03276c14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 0.21.0 + +- Stable nullsafe release. + ## 0.21.0-nullsafety.1 - Fix bug introduced when width and height are both null on the widget. diff --git a/pubspec.yaml b/pubspec.yaml index dd2e1c5d..074f1700 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,13 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.21.0-nullsafety.1 +version: 0.21.0 dependencies: flutter: sdk: flutter meta: ^1.3.0 - path_drawing: ^0.5.0-nullsafety.0 + path_drawing: ^0.5.0 vector_math: ^2.1.0 xml: ^5.0.0 @@ -19,7 +19,7 @@ dev_dependencies: test: ^1.16.0 environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' flutter: ">=1.24.0-6.0.pre" ## For developing features that require new functionality in engine: From 1eff8690fc50ad13c16c31f5431fc6a86fb74f13 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 7 Apr 2021 11:48:32 -0700 Subject: [PATCH 003/142] Fix alignment issues again (#530) --- CHANGELOG.md | 4 ++++ lib/svg.dart | 14 +++++--------- pubspec.yaml | 2 +- .../golden_widget/flutter_logo.string.ltr.png | Bin 3396 -> 3404 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3476 -> 3490 bytes 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03276c14..c3181d24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 0.21.0+1 + +- Fix alignment/sizing issues introduced in 0.21.0 + ## 0.21.0 - Stable nullsafe release. diff --git a/lib/svg.dart b/lib/svg.dart index d151f945..7a7faca4 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -760,19 +760,15 @@ class _SvgPictureState extends State { double? width = widget.width; double? height = widget.height; - if (height != null && width == null) { + if (width == null && height == null) { + width = viewport.width; + height = viewport.height; + } else if (height != null) { width = height / viewport.height * viewport.width; - } else if (height == null && width != null) { + } else if (width != null) { height = width / viewport.width * viewport.height; } - if (height == null && width == null) { - height = viewport.height; - width = viewport.width; - } - assert(height != null); - assert(width != null); - child = SizedBox( width: width, height: height, diff --git a/pubspec.yaml b/pubspec.yaml index 074f1700..79193403 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.21.0 +version: 0.21.0+1 dependencies: flutter: diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/test/golden_widget/flutter_logo.string.ltr.png index 354d79701da5b5e48490cdfcf5ab5b0e4c034970..e4402865634cfd5469cab823e5056404bd347fb8 100644 GIT binary patch literal 3404 zcmeH|`&&|X9LK+hY%;A7Ej3qyNa}igGA~(E5#m7wGqu(-)6|-)P`fBzf@zY~25Lz% zua&deEZ1Y!R&!b|S47%W63Q%1%P2214ND``xzB0O{)+ki&q@lq9 z^G$3_5JK~LT+T*>=1>tLY$1LGq%<{aKU^@u#sD_D*tTR4Zj1zM-X7eyu+mVpJw$1M=DOs z_ZnF}I7;<8>8YsN!a0$BR!#SNO_H_y-wBEeG<)pF7r67}!6S+7-F$gTOLvi=t)c&v z%6Me#wa>Lbi+b|}G$>?t%{uUZcfhGO_Tlq8nhh>koHx6iTRYd(@vS3AZgC&`i zDp`PdA( z+54hSDZ;20eRIT7kntM_Uo=pFuox!*2LXJ9gCYP_0BZpl09b#AuyPjw+X0AhPzb;g zfHQzpx-V+VhAj~|fGi`tbR=7a5gH2>#z<&JMF})e^--2|iZN{CQFWuZ83I$F6Lz)l>{0dN4s0dN5DoCRCN zdK420F|r{>t_4O2-3~z$?OAAfAV`lJ5m|GkB&399&s*!T#x)jHv6ozjUz5yzCjU+<{zYOSrA-b}@EnUK@% zD@opARW+lX_oZEPe9g6Gy6^PJ$vEs13OwtqBlDfLS34YdJ}HKK!=^`D=fpTcXu9H# zrNWps2(^znz4Vvs5j6nE!IUzFB{{P#MFM0O5KhuDGw=(8R+_cucF@mOV!G_}I znp4rT0^SjD)&!glOgK*@gArncIn^Da#op6zsrRCgna3oxlclSjbXe$T5RqWWmYwOd z7dog9tjX`R5C%Z1^K|Hg%VpJZ+BTuW>k*q2Slsc zZT>dOlKRNs0L-g@XdxE=1Rh(Cw-c6AvX zgB5S|1NC8e30t9rRfQ4h$xoJoHRTiF(t1Yf4;j>lpjc}6Flwe(b=w$0*OgI*iHk)V z`f)4Qzs9PVJ!@uej%H5jYNirG$ZwE!G)R=ob+D1udwD+bjB4|VRZ5iH!pHtPmGwdX6Vt4K=k>JY_v$GN_jin8Adu87K(vC&TzzPvX)RVP=?4EY4rdXok1uxWI PNw^z4zhKTqc1+ek!J+%< literal 3396 zcmeH|`(KlF8^^!*K$(WJk)nb$9HJ&X4&`J+V2qsrMWhwzqf|5U15KBP!(4CTZmj;%nU>#MfFnnuryZL^tiao zO#A%L9gX*-k0g9D_*l3W68N_#P<``;CcR>?L5g@6wSi_m4e_G~_|n=$3tWD+n|2XG zf(e2hLbNDTJVL?N7!INQN-ua&T~+6mqS5DmT(e9)BxFtp;0lUz0DeYbR5$~u2Vepq3l!ZR0IC6;0Wjt(K=lq# z;~;<{O91`?bn=kOL~v&b0lBaDMw`+Q7H$iQJ)nq(B`b`I^Ey<{!)Z? z!g$+3SYV2$olUnuKW?BQ>wqNWyc}m*p4w`L)MNlG06_qJjlig&16Tq}OvDywg9u^O z?}5MdL_6fR!5dw21!*Nn^Ed+3cR`23LzWN(gIMWl zRJ|4q*^UqMAjK8nmfPAf_kvAUNkq$yslnUhaxN3e5L7BOd5KPDfFny-<9mxGhBz7E z_DW1T0TS$hI7Hbi)2XyQ|5VlJ#x@a_v*M-{vpPmXtmu#%NOJXTH)Qni2o>Xm~o{ zOBHX;^(`g3x$IcVo9XkUxt`sp^0!(DIvilCp7!0HIm=`#u1XK-9u_$|HvYHwdgJlq zW%EBx*BK0Fm`amy8BEeS$8Gd2w)6eZ$73BO@=B6eekn&TW>>xQ^p33l@t}x2fjQ5> z;ENcFV=0N+XHrVBe*dxA)Ud!_VlJ6X&eSEj+mKDmFN21ddqTM1aF23GQ|hB1>?_Td zCwO>k6+MUdR>cJfk*fq@qd7asV}@tRr*88<8+WOh{v`(H3$-!g1#Tc%o z(mnISc$=T2w5xfx!`1DDvV$GnUQ_V8{b7lu?Uiz)YN9Wv;S1`SF3WZ36`an29u`q{ zCxJJ9KX!hgU|%mWmXsqGu@A?!uZoD%UT*0B)%~Rt5f^*{n!9_)gZ||zi<I}EQlBtt~&@Og5Gr*tp$cNh9Q<0(J!W^_h4BH*)+n48QpJL+C1e=Kk@gfflZX e1QrsYmA$d>;7u-nqEWjT)9_~oF>2}IX@3FA@AN4E diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/test/golden_widget/flutter_logo.string.rtl.png index 444bb28fdc8be4162c8069c9f5901feafe33162b..6c8dd292777c2640514e08b937b8d3d764a80b9e 100644 GIT binary patch literal 3490 zcmeHH`CF4$7QP7xX{-$&AR?fUunPi?;#kWPGYPAe41-9l3brT=5*4vw5t6T%N}^&& z#9>XrO3``70+KO?5lCw(%!;JJYAn)z}hiFuVjVYO51eg??1$7ohXy{ zwye2xdWP{OzdSY&mFf|`UHNEq zP+It{{!>1Qi;)e>m~0B-I5QD7K#aJt0N@1R2tWt`Yyesb0Gv>F0pI|DApy{tD1-%o zApmRuij|1uvKAw^9(IDAATg@uePn_wOz9{w04Qw)1(I_4l%Oz}Xakd=fcvv1KrsRe z3n+RB-T+Q|!vM%40D=lmdT9Xs3_zNh9a`$S< zf+9ilodS`5Gk}ODkchfSA(gE$q@ec>EHu8AL~gweI|B|()aVH@4HOf!mjOFQpwa}-jHJ;do{fVxl|Rnr-UxM1me`iG|O?&&xa7|>Gqbg;Fr zZ(<}YM;Sk(i5BU;nH$Ki^4T-gx6P7wvo=5O)DUq21#m;^gDY{55VOrIc`YXmP z*_u|_ye%pA;IUZw(4QAwKk1%2V#6PkgTVRUE$J8*`1D-v|9YmRhs<30Q`QQuN$rAF zpgl)8G#htAG_3x4P_SOR-2%NQu8b|d9xO)Y5-7YSR#TDp=o4fONmGNw*Z;_Vey?NN zcMz3@8d8`$q`49kTl6gvbbT0O_yGq;=KDDI>i|0=VK+WI3XeUrob1c+t9m)ul(~W zaYP6kM|lx4Mr_V({A93LLctwGmMD&;k7*)?Q~x z-!G9lK_BiXnrzC9zW@BvFHBz9_fr_%cWD=rxK_6t>$^J}4^6xqMr6ZLLG;M@XZefz zX-QpEgZ5!wMe~Qg|9m&7LDg#s0}HeH2c8LZ;~HT`lI~J*+UrBE6*7Ns0YkPCZM6k2 z2ft`}+eK?p)oY*r+N6w`=V#DNwSPgCV{w}9Y>OQ*_K z)QY~YarQ$|=io?OrNvY=K`FwCsP|HH-e#6Z$%pQV!qSqXabX$gxF-mW{-d+=?JE%J zHX0d7+-C8WS5453d7*`Y+-MRc?<=n!=wFO+2%Ye$rdl0r#;H_(a|c=$-_;AS3Sfi5*+;^Rmw^2RO`*gzb;1nv}cjs zzkaa!b$;%PMuE{}4aS{cCcV2H)&GI*p5t$^Y5rkQ{pH4V zT@HsEe8@=(V9Rm=X^|834S(d(`xeV=H(U)s2FG6t4)gyo6!jO&WW zXYBa{YiGiQ-bWA7GUvN*4jk+@fakqe{vNmJHS(2K!p+8;}1L#rBU%tb2U>j}+Fx-mWp!?z+yAC`si x;c2P`T6$a&8V$e^LbqUZc`a99xdKpux^YoYx0dT9P&g9x2SuI;}vGlYFwQ9W9`%-@fk`mQK`KIEBiX|VDG;;RmO z;|CWPEki87Z0yzzETNDExiQ6$8*?M0`{fdSf^KHV*9A^5rbnq}HP2%l>}u>fr{@pd z?v4A}g3# z#QLg=^VZjh9o3y)@;zRUydCwnq;29JjoY|MN(tipb)nUyH@`@5<1u0011u03eqHzy$!vWPFRi z6%!qG<)J%Q!B-!Aqd&zHq$MmOI*A3b#VBx{qsK7{IO~9O^j4r)Vibt-6I9Z22b{B@ zlFfMlKqW1AfSLu-HeUn)t7H%^+$tcUxgAUdA;w&}h(xv|aMOq+r19pVec^Zlw~sSsgxCjSzeyiLG?<2 zBt1B;Gv`>ReceZT?EIPSW6uX`p#k)XvI6adKD<=?qsU>+Tbvu{?keTv zu+xWD%Rc_Nx%qr~f!mVleft}sJQmCJ&uE?}!&Z?%qPSHC;|yi1nu#j+oFPZeXQtN= zG~B&i;C8AFKb#H{UEpV*6_B`ixcf$$%d?)RwGL zNZY|SHL^hC(1%_BZX-@n8T~23>}zEOml}ugQfr`om$;2u0Myqs0yo}(g0?>WlD7af z7`P;C0vo(}3$|;&_pq^RaN});RA7ZmJbA`yN2A4FJmgmhlUKj2mWRgvy&`cExgXRv zvG^upV)tH~*Ji6**2ep%dU2ZOzS$YEdg7At5HJiK8{i*%rG0nm{-+a0e8?YPcHKFi+bZ3HO3L;?Iw#WW#Qef_gb&k zY!ZKQNb}2yi+u(bhy|q|jhrcr_-Zt6zfd(j6X083l0+L@ect)&;>zS{#bl8RNxdMH zCxqG^)g2_TIehNzLArm4y)WmGQD@Wg)TZXc3vbh>1$xLI)8)x!u}$?0MU#Y`Wg~K} zV3-SyjTmQNmr4o;A40I;J}O)4^_`9B&)^O4l8jj zDOhs`1meCzc7ys@+xOlj?fvBV|2?$oe5iiu>6kjQftw0K?7Vk?;on@u&KfT_cdV%j zyqpr26Ed^%*$=Gk5welx-lW2GO^Zn(R-1z*?2G9jW!2|KwaHe$kA5E6D(YVftn^~# z_gm=EtL^n8!fYyU9#qfXI;|O&i9GnuKk^`Oa5=gBuDR&C%BQ41{1juQKh+Xm z#A7-ruwTs=H&u=4#>)h}JDS>usc&6@egw|*Ns$tPK$M0iD4+=oU(Mdc1g z5i6D9Y17BzXsNRXvE~^{V~`*Qx|jQYV%pso8YgP#CnmA-rp5m_HXm-^gZ_*8GJ}*| z`K9(NLr&=m#rbHQ&xcUq@Z4pwyKQ6gD!sQ7wh+9|eM;QBovd&1Zb?%BSlilU0I)R< zukqbphpMhPbNaNA)b0;ae+^yu2U%I>9Qzer6ThfBF|=)A3+e&UbVgoT5OAn Date: Wed, 21 Apr 2021 22:58:22 -0700 Subject: [PATCH 004/142] expose cache on PictureProvider so that users can change the limit (#538) --- .cirrus.yml | 16 ++----- CHANGELOG.md | 10 ++++- lib/src/picture_cache.dart | 5 +-- lib/src/picture_provider.dart | 19 +++++---- pubspec.yaml | 2 +- test/picture_cache_test.dart | 80 +++++++++++++++++++++++++++-------- test/widget_svg_test.dart | 24 +++++------ 7 files changed, 102 insertions(+), 54 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 34c0d628..331c96ee 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,6 +1,3 @@ -container: - image: cirrusci/flutter:latest - env: CI_NAME: "CirrusCI" CI_BUILD_NUMBER: $CIRRUS_TASK_ID @@ -10,15 +7,10 @@ env: COVERALLS_REPO_TOKEN: ENCRYPTED[61ba3fee193a9ed6116e0f61bbe26fe8c0452287e5dfd86c728e2f1f24327818d6c74c956d7b9cbf3bd6236489af0fd1] test_task: - matrix: - - name: stable - channel_script: | - flutter channel stable - flutter upgrade - - name: master - channel_script: | - flutter channel master - flutter upgrade + container: + matrix: + - image: cirrusci/flutter:dev + - image: cirrusci/flutter:stable pub_cache: folder: ~/.pub-cache analyze_script: flutter analyze . diff --git a/CHANGELOG.md b/CHANGELOG.md index c3181d24..2e662c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGES +## 0.22.0 + +- Expose `PictureCache` on `PictureProvider`, and deprecate + `PictureProvider.cacheCount` and `PictureProvider.clearCache`. This is + intended to allow users to set a maximum cache size, which was previously + impossible. + ## 0.21.0+1 - Fix alignment/sizing issues introduced in 0.21.0 @@ -24,7 +31,8 @@ ## 0.20.0-nullsafety.4 -- Adds option `warningsAsErrors` that throws errors when detecting unsupported SVG elements. +- Adds option `warningsAsErrors` that throws errors when detecting unsupported + SVG elements. ## 0.20.0-nullsafety.3 diff --git a/lib/src/picture_cache.dart b/lib/src/picture_cache.dart index 158bebdd..a06d7a2c 100644 --- a/lib/src/picture_cache.dart +++ b/lib/src/picture_cache.dart @@ -3,7 +3,8 @@ import 'picture_stream.dart'; const int _kDefaultSize = 1000; /// A cache for [Picture] objects. -// TODO(dnfield): Implement memory based limiting, once `approximateByteCount` is exposed in engine +/// +/// By default, this caches up to 1000 objects. class PictureCache { final Map _cache = {}; @@ -41,8 +42,6 @@ class PictureCache { /// /// This is useful if, for instance, the root asset bundle has been updated /// and therefore new images must be obtained. - // TODO(ianh): Provide a way to target individual images. This is currently non-trivial - // because by the time we get to the imageCache, the keys we're using are opaque. void clear() { _cache.clear(); } diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 194a2984..926e91c9 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -201,9 +201,6 @@ class PictureConfiguration { } } -// TODO(dnfield): allow other people to implement this. -PictureCache _cache = PictureCache(); - /// Identifies a picture without committing to the precise final asset. This /// allows a set of pictures to be identified and for the precise picture to later /// be resolved based on the environment, e.g. the device pixel ratio. @@ -304,11 +301,17 @@ abstract class PictureProvider { /// const constructors so that they can be used in const expressions. const PictureProvider(this.colorFilter); - /// The number of items in the [PictureCache]. - static int get cacheCount => _cache.count; + /// The [PictureCache] for [Picture] objects created by [PictureProvider] + /// implementations. + static final PictureCache cache = PictureCache(); + + /// The number of items in the [cache]. + @Deprecated('Use the `cache` object directly instead.') + static int get cacheCount => cache.count; - /// Clears the [PictureCache]. - static void clearCache() => _cache.clear(); + /// Clears the [cache]. + @Deprecated('Use the `cache` object directly instead.') + static void clearCache() => cache.clear(); /// The color filter to apply to the picture, if any. final ColorFilter? colorFilter; @@ -330,7 +333,7 @@ abstract class PictureProvider { (T key) { obtainedKey = key; stream.setCompleter( - _cache.putIfAbsent( + cache.putIfAbsent( key!, () => load(key, onError: onError), ), diff --git a/pubspec.yaml b/pubspec.yaml index 79193403..4443e426 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.21.0+1 +version: 0.22.0 dependencies: flutter: diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index 3bd917c6..f2f0e328 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -8,19 +8,64 @@ import 'package:xml/xml.dart'; class MockPictureStreamCompleter extends PictureStreamCompleter {} void main() { - late PictureCache cache; - + const String svgString = ''' + + + +'''; + + const String svgString2 = ''' + + + +'''; + + const String svgString3 = ''' + + + +'''; + + late int previousMaximumSize; setUp(() { - cache = PictureCache(); + PictureProvider.cache.clear(); + previousMaximumSize = PictureProvider.cache.maximumSize; + }); + + tearDown(() { + PictureProvider.cache.maximumSize = previousMaximumSize; + }); + + testWidgets('Can set a limit on the PictureCache', + (WidgetTester tester) async { + expect(PictureProvider.cache.count, 0); + + PictureProvider.cache.maximumSize = 2; + expect(PictureProvider.cache.count, 0); + + await tester.pumpWidget(Directionality( + textDirection: TextDirection.ltr, + child: SvgPicture.string(svgString), + )); + expect(PictureProvider.cache.count, 1); + + await tester.pumpWidget(Directionality( + textDirection: TextDirection.ltr, + child: SvgPicture.string(svgString2), + )); + expect(PictureProvider.cache.count, 2); + + await tester.pumpWidget(Directionality( + textDirection: TextDirection.ltr, + child: SvgPicture.string(svgString3), + )); + expect(PictureProvider.cache.count, 2); + + PictureProvider.cache.maximumSize = 1; + expect(PictureProvider.cache.count, 1); }); testWidgets('Precache test', (WidgetTester tester) async { - const String svgString = ''' - -'''; - const String svgString2 = ''' - -'''; await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr, @@ -28,7 +73,7 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await precachePicture( StringPicture( SvgPicture.svgStringDecoder, @@ -36,7 +81,7 @@ void main() { ), tester.element(find.text('test_text')), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); await tester.pumpWidget( Directionality( @@ -44,7 +89,7 @@ void main() { child: SvgPicture.string(svgString), ), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); await tester.pumpWidget( Directionality( @@ -52,10 +97,10 @@ void main() { child: SvgPicture.string(svgString2), ), ); - expect(PictureProvider.cacheCount, 2); + expect(PictureProvider.cache.count, 2); - PictureProvider.clearCache(); - expect(PictureProvider.cacheCount, 0); + PictureProvider.cache.clear(); + expect(PictureProvider.cache.count, 0); }); testWidgets('Precache - null context', (WidgetTester tester) async { @@ -63,7 +108,7 @@ void main() { '''; - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await precachePicture( StringPicture( SvgPicture.svgStringDecoder, @@ -71,7 +116,7 @@ void main() { ), null, ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); }); testWidgets('Precache with error', (WidgetTester tester) async { @@ -104,6 +149,7 @@ void main() { }); test('Cache Tests', () { + final PictureCache cache = PictureCache(); expect(cache.maximumSize, equals(1000)); cache.maximumSize = 1; expect(cache.maximumSize, equals(1)); diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 7a295798..1f3ce21b 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -22,7 +22,7 @@ void main() { late FakeHttpClientRequest fakeRequest; late FakeHttpClient fakeHttpClient; setUp(() { - PictureProvider.clearCache(); + PictureProvider.cache.clear(); svg.cacheColorFilterOverride = null; fakeResponse = FakeHttpClientResponse(); fakeRequest = FakeHttpClientRequest(fakeResponse); @@ -32,7 +32,7 @@ void main() { testWidgets( 'SvgPicture does not use a color filtering widget when no color specified', (WidgetTester tester) async { - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await tester.pumpWidget( SvgPicture.string( svgStr, @@ -41,13 +41,13 @@ void main() { ), ); await tester.pumpAndSettle(); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); expect(find.byType(UnboundedColorFiltered), findsNothing); }); testWidgets('SvgPicture does not invalidate the cache when color changes', (WidgetTester tester) async { - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await tester.pumpWidget( SvgPicture.string( svgStr, @@ -57,7 +57,7 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); await tester.pumpWidget( SvgPicture.string( @@ -68,13 +68,13 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); }); testWidgets( 'SvgPicture does invalidate the cache when color changes and color filter is cached', (WidgetTester tester) async { - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await tester.pumpWidget( SvgPicture.string( svgStr, @@ -85,7 +85,7 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); await tester.pumpWidget( SvgPicture.string( @@ -97,14 +97,14 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 2); + expect(PictureProvider.cache.count, 2); }); testWidgets( 'SvgPicture does invalidate the cache when color changes and color filter is cached (override)', (WidgetTester tester) async { svg.cacheColorFilterOverride = true; - expect(PictureProvider.cacheCount, 0); + expect(PictureProvider.cache.count, 0); await tester.pumpWidget( SvgPicture.string( svgStr, @@ -114,7 +114,7 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 1); + expect(PictureProvider.cache.count, 1); await tester.pumpWidget( SvgPicture.string( @@ -125,7 +125,7 @@ void main() { ), ); - expect(PictureProvider.cacheCount, 2); + expect(PictureProvider.cache.count, 2); }); testWidgets('SvgPicture can work with a FittedBox', From 635c00f18f693da9f8fcb59af905bda9bfd69037 Mon Sep 17 00:00:00 2001 From: jefflim-google <52889965+jefflim-google@users.noreply.github.com> Date: Wed, 5 May 2021 16:15:54 +0800 Subject: [PATCH 005/142] Improve performance of SVG parsing (#546) * Improve performance of SVG parsing The previous code used to iterate through a list of XmlEventAttributes for every call to getAttribute. The newer code constructs a Map, and looks up the attribute name directly. This seems to show a 30% overall reduction to svg parsing costs. * Fix lint issues highlighted by github * Fix typo --- lib/src/svg/parser_state.dart | 37 ++++++++++++------------ lib/src/svg/xml_parsers.dart | 27 +++++++++-------- lib/src/utilities/numbers.dart | 2 +- lib/src/utilities/xml.dart | 32 ++++++++++---------- test/xml_svg_test.dart | 53 +++++++++++++++++----------------- 5 files changed, 77 insertions(+), 74 deletions(-) diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 42cfa96f..d72b61bf 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -18,7 +18,7 @@ final Set _unhandledElements = {'title', 'desc'}; typedef _ParseFunc = Future? Function( SvgParserState parserState, bool warningsAsErrors); -typedef _PathFunc = Path? Function(List? attributes); +typedef _PathFunc = Path? Function(Map attributes); const Map _svgElementParsers = { 'svg': _Elements.svg, @@ -635,7 +635,7 @@ class _Elements { } class _Paths { - static Path circle(List? attributes) { + static Path circle(Map attributes) { final double cx = parseDouble(getAttribute(attributes, 'cx', def: '0'))!; final double cy = parseDouble(getAttribute(attributes, 'cy', def: '0'))!; final double r = parseDouble(getAttribute(attributes, 'r', def: '0'))!; @@ -643,12 +643,12 @@ class _Paths { return Path()..addOval(oval); } - static Path path(List? attributes) { + static Path path(Map attributes) { final String d = getAttribute(attributes, 'd')!; return parseSvgPathData(d); } - static Path rect(List? attributes) { + static Path rect(Map attributes) { final double x = parseDouble(getAttribute(attributes, 'x', def: '0'))!; final double y = parseDouble(getAttribute(attributes, 'y', def: '0'))!; final double w = parseDouble(getAttribute(attributes, 'width', def: '0'))!; @@ -669,16 +669,16 @@ class _Paths { return Path()..addRect(rect); } - static Path? polygon(List? attributes) { + static Path? polygon(Map attributes) { return parsePathFromPoints(attributes, true); } - static Path? polyline(List? attributes) { + static Path? polyline(Map attributes) { return parsePathFromPoints(attributes, false); } static Path? parsePathFromPoints( - List? attributes, bool close) { + Map attributes, bool close) { final String? points = getAttribute(attributes, 'points'); if (points == '') { return null; @@ -688,7 +688,7 @@ class _Paths { return parseSvgPathData(path); } - static Path ellipse(List? attributes) { + static Path ellipse(Map attributes) { final double cx = parseDouble(getAttribute(attributes, 'cx', def: '0'))!; final double cy = parseDouble(getAttribute(attributes, 'cy', def: '0'))!; final double rx = parseDouble(getAttribute(attributes, 'rx', def: '0'))!; @@ -698,7 +698,7 @@ class _Paths { return Path()..addOval(r); } - static Path line(List? attributes) { + static Path line(Map attributes) { final double x1 = parseDouble(getAttribute(attributes, 'x1', def: '0'))!; final double x2 = parseDouble(getAttribute(attributes, 'x2', def: '0'))!; final double y1 = parseDouble(getAttribute(attributes, 'y1', def: '0'))!; @@ -734,7 +734,7 @@ class SvgParserState { final Queue<_SvgGroupTuple> _parentDrawables = ListQueue<_SvgGroupTuple>(10); DrawableRoot? _root; bool _inDefs = false; - List? _currentAttributes; + late Map _currentAttributes; XmlStartElementEvent? _currentStartElement; /// The current depth of the reader in the XML hierarchy. @@ -750,7 +750,7 @@ class SvgParserState { depth -= 1; assert(depth >= 0); } - _currentAttributes = []; + _currentAttributes = {}; _currentStartElement = null; if (depth < subtreeStartDepth) { return; @@ -764,8 +764,9 @@ class SvgParserState { final XmlEvent event = _eventIterator.current; bool isSelfClosing = false; if (event is XmlStartElementEvent) { - if (getAttribute(event.attributes, 'display') == 'none' || - getAttribute(event.attributes, 'visibility') == 'hidden') { + final Map attributeMap = event.attributes.toAttributeMap(); + if (getAttribute(attributeMap, 'display') == 'none' || + getAttribute(attributeMap, 'visibility') == 'hidden') { print('SVG Warning: Discarding:\n\n $event\n\n' 'and any children it has since it is not visible.\n' 'If that element is meant to be visible, the `display` or ' @@ -778,7 +779,7 @@ class SvgParserState { } continue; } - _currentAttributes = event.attributes; + _currentAttributes = attributeMap; _currentStartElement = event; depth += 1; isSelfClosing = event.isSelfClosing; @@ -788,7 +789,7 @@ class SvgParserState { if (isSelfClosing || event is XmlEndElementEvent) { depth -= 1; assert(depth >= 0); - _currentAttributes = []; + _currentAttributes = {}; _currentStartElement = null; } if (depth < subtreeStartDepth) { @@ -826,11 +827,11 @@ class SvgParserState { } /// The XML Attributes of the current node in the tree. - List? get attributes => _currentAttributes; + Map get attributes => _currentAttributes; /// Gets the attribute for the current position of the parser. - String? attribute(String name, {String? def, String? namespace}) => - getAttribute(attributes, name, def: def, namespace: namespace); + String? attribute(String name, {String? def}) => + getAttribute(attributes, name, def: def); /// The current group, if any, in the [Drawable] heirarchy. DrawableParent? get currentGroup { diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index 312181e6..3fdbb145 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -2,7 +2,6 @@ import 'dart:ui'; import 'package:path_drawing/path_drawing.dart'; import 'package:vector_math/vector_math_64.dart'; -import 'package:xml/xml_events.dart'; import '../utilities/errors.dart'; import '../utilities/numbers.dart'; @@ -38,7 +37,7 @@ double _parseRawWidthHeight(String? raw) { /// The [respectWidthHeight] parameter specifies whether `width` and `height` attributes /// on the root SVG element should be treated in accordance with the specification. DrawableViewport? parseViewBox( - List? svg, { + Map svg, { bool nullOk = false, }) { final String? viewBox = getAttribute(svg, 'viewBox'); @@ -86,14 +85,14 @@ DrawableViewport? parseViewBox( } /// Builds an IRI in the form of `'url(#id)'`. -String buildUrlIri(List? attributes) => +String buildUrlIri(Map attributes) => 'url(#${getAttribute(attributes, 'id')})'; /// An empty IRI. const String emptyUrlIri = 'url(#)'; /// Parses a `spreadMethod` attribute into a [TileMode]. -TileMode parseTileMode(List? attributes) { +TileMode parseTileMode(Map attributes) { final String? spreadMethod = getAttribute(attributes, 'spreadMethod', def: 'pad'); switch (spreadMethod) { @@ -112,7 +111,7 @@ TileMode parseTileMode(List? attributes) { /// /// Does not currently support percentages. CircularIntervalList? parseDashArray( - List? attributes, + Map attributes, ) { final String? rawDashArray = getAttribute(attributes, 'stroke-dasharray'); if (rawDashArray == '') { @@ -127,7 +126,7 @@ CircularIntervalList? parseDashArray( } /// Parses a @stroke-dashoffset into a [DashOffset]. -DashOffset? parseDashOffset(List? attributes) { +DashOffset? parseDashOffset(Map attributes) { final String? rawDashOffset = getAttribute(attributes, 'stroke-dashoffset'); if (rawDashOffset == '') { return null; @@ -144,7 +143,7 @@ DashOffset? parseDashOffset(List? attributes) { } /// Parses an @opacity value into a [double], clamped between 0..1. -double? parseOpacity(List? attributes) { +double? parseOpacity(Map attributes) { final String? rawOpacity = getAttribute(attributes, 'opacity', def: null); if (rawOpacity != null) { return parseDouble(rawOpacity)!.clamp(0.0, 1.0).toDouble(); @@ -175,7 +174,7 @@ DrawablePaint _getDefinitionPaint( /// Parses a @stroke attribute into a [Paint]. DrawablePaint? parseStroke( String? key, - List? attributes, + Map attributes, Rect? bounds, DrawableDefinitionServer definitions, DrawablePaint? parentStroke, @@ -244,7 +243,7 @@ DrawablePaint? parseStroke( /// Parses a `fill` attribute. DrawablePaint? parseFill( String? key, - List? el, + Map el, Rect? bounds, DrawableDefinitionServer definitions, DrawablePaint? parentFill, @@ -304,14 +303,14 @@ Color? _determineFillColor( } /// Parses a `fill-rule` attribute into a [PathFillType]. -PathFillType? parseFillRule(List? attributes, +PathFillType? parseFillRule(Map attributes, [String attr = 'fill-rule', String? def = 'nonzero']) { final String? rawFillRule = getAttribute(attributes, attr, def: def); return parseRawFillRule(rawFillRule); } /// Applies a transform to a path if the [attributes] contain a `transform`. -Path? applyTransformIfNeeded(Path? path, List? attributes) { +Path? applyTransformIfNeeded(Path? path, Map attributes) { final Matrix4? transform = parseTransform(getAttribute(attributes, 'transform', def: null)); @@ -324,7 +323,7 @@ Path? applyTransformIfNeeded(Path? path, List? attributes) { /// Parses a `clipPath` element into a list of [Path]s. List? parseClipPath( - List? attributes, + Map attributes, DrawableDefinitionServer definitions, ) { final String? rawClipAttribute = getAttribute(attributes, 'clip-path'); @@ -355,7 +354,7 @@ const Map _blendModes = { /// Lookup the mask if the attribute is present. DrawableStyleable? parseMask( - List? attributes, + Map attributes, DrawableDefinitionServer definitions, ) { final String? rawMaskAttribute = getAttribute(attributes, 'mask'); @@ -402,7 +401,7 @@ FontWeight? parseFontWeight(String? fontWeight) { /// Remember that @style attribute takes precedence. DrawableStyle parseStyle( String? key, - List? attributes, + Map attributes, DrawableDefinitionServer definitions, Rect? bounds, DrawableStyle? parentStyle, { diff --git a/lib/src/utilities/numbers.dart b/lib/src/utilities/numbers.dart index 7e05b47a..fc3e1744 100644 --- a/lib/src/utilities/numbers.dart +++ b/lib/src/utilities/numbers.dart @@ -8,7 +8,7 @@ double? parseDouble(String? maybeDouble, {bool tryParse = false}) { if (maybeDouble == null) { return null; } - maybeDouble = maybeDouble.trim().replaceFirst('px', '').trim(); + maybeDouble = maybeDouble.replaceFirst('px', '').trim(); if (tryParse) { return double.tryParse(maybeDouble); } diff --git a/lib/src/utilities/xml.dart b/lib/src/utilities/xml.dart index 95eaf999..018972b5 100644 --- a/lib/src/utilities/xml.dart +++ b/lib/src/utilities/xml.dart @@ -7,10 +7,9 @@ const String kXlinkNamespace = 'http://www.w3.org/1999/xlink'; /// /// SVG 1.1 specifies that these attributes should be in the xlink namespace. /// SVG 2 deprecates that namespace. -String? getHrefAttribute(List? attributes) => getAttribute( +String? getHrefAttribute(Map attributes) => getAttribute( attributes, 'href', - namespace: kXlinkNamespace, def: getAttribute(attributes, 'href'), ); @@ -19,15 +18,14 @@ String? getHrefAttribute(List? attributes) => getAttribute( /// /// Will look to the style first if it can. String? getAttribute( - List? el, + Map el, String name, { String? def = '', - String? namespace, bool checkStyle = true, }) { String raw = ''; if (checkStyle) { - final String? style = _getAttribute(el!, 'style').trim(); + final String? style = _getAttribute(el, 'style'); if (style != '' && style != null) { // Probably possible to slightly optimize this (e.g. use indexOf instead of split), // but handling potential whitespace will get complicated and this just works. @@ -43,25 +41,29 @@ String? getAttribute( } if (raw == '') { - raw = _getAttribute(el, name, namespace: namespace).trim(); + raw = _getAttribute(el, name); } } else { - raw = _getAttribute(el!, name, namespace: namespace).trim(); + raw = _getAttribute(el, name); } return raw == '' ? def : raw; } String _getAttribute( - List list, + Map attributes, String localName, { String def = '', - String? namespace, }) { - for (XmlEventAttribute attr in list) { - if (attr.localName == localName) { - return attr.value; - } - } - return def; + return attributes[localName] ?? def; +} + +/// Extension on List for easy conversion to an attribute +/// map. +extension AttributeMapXmlEventAttributeExtension on List { + /// Converts the List to an attribute map. + Map toAttributeMap() => { + for (final XmlEventAttribute attribute in this) + attribute.localName: attribute.value.trim(), + }; } diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index f8cccfc9..a2b8cdbf 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -17,8 +17,8 @@ void main() { 'xlink:href="http://localhost" />') .first as XmlStartElementEvent; - expect(getHrefAttribute(el.attributes), 'http://localhost'); - expect(getHrefAttribute(elXlink.attributes), 'http://localhost'); + expect(getHrefAttribute(el.attributes.toAttributeMap()), 'http://localhost'); + expect(getHrefAttribute(elXlink.attributes.toAttributeMap()), 'http://localhost'); }); test('Attribute and style tests', () { @@ -27,15 +27,16 @@ void main() { 'style="stroke-opacity:1;fill-opacity:.23" />') .first as XmlStartElementEvent; - expect(getAttribute(el.attributes, 'stroke'), '#fff'); - expect(getAttribute(el.attributes, 'fill'), '#eee'); - expect(getAttribute(el.attributes, 'stroke-dashpattern'), '1 2'); - expect(getAttribute(el.attributes, 'stroke-opacity'), '1'); - expect(getAttribute(el.attributes, 'stroke-another'), ''); - expect(getAttribute(el.attributes, 'fill-opacity'), '.23'); + final Map attributes = el.attributes.toAttributeMap(); + expect(getAttribute(attributes, 'stroke'), '#fff'); + expect(getAttribute(attributes, 'fill'), '#eee'); + expect(getAttribute(attributes, 'stroke-dashpattern'), '1 2'); + expect(getAttribute(attributes, 'stroke-opacity'), '1'); + expect(getAttribute(attributes, 'stroke-another'), ''); + expect(getAttribute(attributes, 'fill-opacity'), '.23'); - expect(getAttribute(el.attributes, 'fill-opacity', checkStyle: false), ''); - expect(getAttribute(el.attributes, 'fill', checkStyle: false), '#eee'); + expect(getAttribute(attributes, 'fill-opacity', checkStyle: false), ''); + expect(getAttribute(attributes, 'fill', checkStyle: false), '#eee'); }); // if the parsing logic changes, we can simplify some methods. for now assert that whitespace in attributes is preserved @@ -76,17 +77,17 @@ void main() { final XmlStartElementEvent svgWithNoSizeInfo = parseEvents('').first as XmlStartElementEvent; - expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes)!.size, + expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())!.size, const Size(50, 50)); - expect(parseViewBox(svgWithViewBox.attributes)!.viewBoxRect, rect); - expect(parseViewBox(svgWithViewBox.attributes)!.viewBoxOffset, Offset.zero); - expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes)!.viewBoxRect, + expect(parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxRect, rect); + expect(parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxOffset, Offset.zero); + expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())!.viewBoxRect, rect); - expect(parseViewBox(svgWithWidthHeight.attributes)!.viewBoxRect, rect); - expect(parseViewBox(svgWithNoSizeInfo.attributes, nullOk: true), null); - expect(() => parseViewBox(svgWithNoSizeInfo.attributes), throwsStateError); - expect(parseViewBox(svgWithViewBoxMinXMinY.attributes)!.viewBoxRect, rect); - expect(parseViewBox(svgWithViewBoxMinXMinY.attributes)!.viewBoxOffset, + expect(parseViewBox(svgWithWidthHeight.attributes.toAttributeMap())!.viewBoxRect, rect); + expect(parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap(), nullOk: true), null); + expect(() => parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap()), throwsStateError); + expect(parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())!.viewBoxRect, rect); + expect(parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())!.viewBoxOffset, const Offset(-42.0, -56.0)); }); @@ -107,12 +108,12 @@ void main() { final XmlStartElementEvent none = parseEvents('').first as XmlStartElementEvent; - expect(parseTileMode(pad.attributes), TileMode.clamp); - expect(parseTileMode(invalid.attributes), TileMode.clamp); - expect(parseTileMode(none.attributes), TileMode.clamp); + expect(parseTileMode(pad.attributes.toAttributeMap()), TileMode.clamp); + expect(parseTileMode(invalid.attributes.toAttributeMap()), TileMode.clamp); + expect(parseTileMode(none.attributes.toAttributeMap()), TileMode.clamp); - expect(parseTileMode(reflect.attributes), TileMode.mirror); - expect(parseTileMode(repeat.attributes), TileMode.repeated); + expect(parseTileMode(reflect.attributes.toAttributeMap()), TileMode.mirror); + expect(parseTileMode(repeat.attributes.toAttributeMap()), TileMode.repeated); }); test('@stroke-dashoffset tests', () { @@ -124,8 +125,8 @@ void main() { as XmlStartElementEvent; // TODO(dnfield): DashOffset is completely opaque right now, maybe expose the raw value? - expect(parseDashOffset(abs.attributes), isNotNull); - expect(parseDashOffset(pct.attributes), isNotNull); + expect(parseDashOffset(abs.attributes.toAttributeMap()), isNotNull); + expect(parseDashOffset(pct.attributes.toAttributeMap()), isNotNull); }); test('font-weight tests', () { From fbbce53ff85026f10c696872380612bb6eaf3beb Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 5 May 2021 01:51:18 -0700 Subject: [PATCH 006/142] version bumps (#547) * version bumps * fix coverage for non-write users --- .ci/coveralls.sh | 11 +++++++++++ .cirrus.yml | 4 +--- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100755 .ci/coveralls.sh diff --git a/.ci/coveralls.sh b/.ci/coveralls.sh new file mode 100755 index 00000000..cce1c722 --- /dev/null +++ b/.ci/coveralls.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -x + +if [[ $COVERALLS_REPO_TOKEN == ENCRYPTED* ]]; then + echo "Skipping coveralls, user not authorized" + exit 0 +fi + +dart pub global activate coveralls +dart pub global run coveralls coverage/lcov.info diff --git a/.cirrus.yml b/.cirrus.yml index 331c96ee..938eb390 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -15,6 +15,4 @@ test_task: folder: ~/.pub-cache analyze_script: flutter analyze . test_script: flutter test --coverage - coveralls_script: | - dart pub global activate coveralls - dart pub global run coveralls coverage/lcov.info + coveralls_script: ./.ci/coveralls.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e662c8b..f464bfcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 0.22.1 + +- Pick up performance improvements in path_parsing 0.2.1 +- Performance improvements in XML parsing of SVGs. + ## 0.22.0 - Expose `PictureCache` on `PictureProvider`, and deprecate diff --git a/pubspec.yaml b/pubspec.yaml index 4443e426..d49128d8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.22.0 +version: 0.22.1 dependencies: flutter: From 1fc769fc080e7a67e4a63109b93c6da50cfd44aa Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 5 May 2021 01:52:22 -0700 Subject: [PATCH 007/142] missing bump --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index d49128d8..153f7a90 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ dependencies: flutter: sdk: flutter meta: ^1.3.0 - path_drawing: ^0.5.0 + path_drawing: ^0.5.1 vector_math: ^2.1.0 xml: ^5.0.0 From c3fd0efeefa5987b7771579c1d4c27a0724b7d86 Mon Sep 17 00:00:00 2001 From: MrBirb <67576036+MrBirb@users.noreply.github.com> Date: Thu, 6 May 2021 06:39:19 +0300 Subject: [PATCH 008/142] Update README.md (#548) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7976d434..05704721 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ The Dart logo is from SVGs in `/assets/noto-emoji` are from [Google i18n noto-emoji](https://github.com/googlei18n/noto-emoji), licensed under the Apache license. -Please submit SVGs this can't render properly (e.g. that don't render here the +Please submit SVGs that can't render properly (e.g. that don't render here the way they do in chrome), as long as they're not using anything "probably out of scope" (above). From feea7e21f6cbdc3218c592439c4242f35fe8207b Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 May 2021 09:06:01 -0700 Subject: [PATCH 009/142] Update coveralls.sh --- .ci/coveralls.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/coveralls.sh b/.ci/coveralls.sh index cce1c722..9dd7e84f 100755 --- a/.ci/coveralls.sh +++ b/.ci/coveralls.sh @@ -2,7 +2,7 @@ set -x -if [[ $COVERALLS_REPO_TOKEN == ENCRYPTED* ]]; then +if [[ -z $COVERALLS_REPO_TOKEN ]]; then echo "Skipping coveralls, user not authorized" exit 0 fi From de08e17f7ad1f29e6a820fe50353e07b3778fa91 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 May 2021 10:08:45 -0700 Subject: [PATCH 010/142] sort directives --- test/error_test.dart | 4 ++-- test/widget_svg_test.dart | 5 +++-- test/xml_svg_test.dart | 4 ++-- tool/gen_golden.dart | 5 ++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/error_test.dart b/test/error_test.dart index 98dad59e..97e5220c 100644 --- a/test/error_test.dart +++ b/test/error_test.dart @@ -1,8 +1,8 @@ import 'package:flutter/foundation.dart'; -import 'package:flutter_test/flutter_test.dart'; - import 'package:flutter_svg/parser.dart'; +import 'package:flutter_test/flutter_test.dart'; + void main() { testWidgets('Reports tag in out of order defs', (WidgetTester tester) async { final FlutterExceptionHandler oldHandler = FlutterError.onError!; diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 1f3ce21b..ed89f9fe 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -5,11 +5,12 @@ import 'dart:typed_data'; import 'dart:ui' show window; import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/unbounded_color_filtered.dart'; + import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_svg/flutter_svg.dart'; Future _checkWidgetAndGolden(Key key, String filename) async { final Finder widgetFinder = find.byKey(key); diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index a2b8cdbf..6bfeece0 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -1,10 +1,10 @@ import 'dart:ui'; +import 'package:flutter_svg/src/svg/xml_parsers.dart'; +import 'package:flutter_svg/src/utilities/xml.dart'; import 'package:test/test.dart'; import 'package:xml/xml_events.dart'; -import 'package:flutter_svg/src/svg/xml_parsers.dart'; -import 'package:flutter_svg/src/utilities/xml.dart'; void main() { test('Xlink href tests', () { diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index d5731d30..79eb8725 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -9,10 +9,9 @@ import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; -import 'package:path/path.dart' as path; - -import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/src/vector_drawable.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:path/path.dart' as path; Future getSvgPngBytes(String svgData) async { final PictureRecorder rec = PictureRecorder(); From af7963b03679de2fbf2855e76a1802e9ead8afc5 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 May 2021 16:44:48 -0700 Subject: [PATCH 011/142] skip golden test on non-linux --- test/no_width_height_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/no_width_height_test.dart b/test/no_width_height_test.dart index 7532b40c..3efffbbb 100644 --- a/test/no_width_height_test.dart +++ b/test/no_width_height_test.dart @@ -19,7 +19,7 @@ void main() { find.byType(RepaintBoundary), matchesGoldenFile('golden_widget/columns_and_rows.png'), ); - }); + }, skip: !isLinux); } class ColumnsAndRows extends StatelessWidget { From 9e19fd3491591a1130aecab0c471260d77a2f5d1 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 18 May 2021 12:25:29 -0700 Subject: [PATCH 012/142] Update for the latest Dart analyze unnecessary_import check (#555) --- example/lib/main.dart | 3 --- test/picture_cache_test.dart | 1 - 2 files changed, 4 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 09ebdd3d..fc29e617 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,4 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:flutter_svg/avd.dart'; import 'package:flutter_svg/flutter_svg.dart'; diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index f2f0e328..2876fb38 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -1,7 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/picture_cache.dart'; -import 'package:flutter_svg/src/picture_provider.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:xml/xml.dart'; From a7388ebfc7a22a125325a51ec073edcacf4b6641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Sousa?= Date: Sun, 23 May 2021 13:04:17 -0300 Subject: [PATCH 013/142] Implemented text-style parser (#556) * font-style attribute parser --- example/assets/simple/text_4.svg | 22 ++++++++++++++++++++++ golden/simple/text_4.png | Bin 0 -> 1022 bytes lib/src/svg/xml_parsers.dart | 19 +++++++++++++++++++ test/xml_svg_test.dart | 9 +++++++++ 4 files changed, 50 insertions(+) create mode 100644 example/assets/simple/text_4.svg create mode 100644 golden/simple/text_4.png diff --git a/example/assets/simple/text_4.svg b/example/assets/simple/text_4.svg new file mode 100644 index 00000000..4348492e --- /dev/null +++ b/example/assets/simple/text_4.svg @@ -0,0 +1,22 @@ + + + + Example text04 - Font style + + + Normal text + + Italic text + + + Oblique text + + + Italic bold text + diff --git a/golden/simple/text_4.png b/golden/simple/text_4.png new file mode 100644 index 0000000000000000000000000000000000000000..03bf13c643200da41e5c8813f4218db0daa86c31 GIT binary patch literal 1022 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_tI8o-U3d6?5L+-JK;CD8TTb^F~M43jYU7gIRKemUvFoT3ae5fBf9JbK-#> z!W?3c*79WPT#Q#=&<--df_=T~UhkT` zk0ayi%UkMqZmg(1Hs{!#vQ1ZWJhxv7R? znfY(BuD&;McZt~{@bTs4{mJ+D$=2O7eBB~e^!su%yQjHWcG>NA{@C)8E2aMP`SvU4 z=AJb#J2SVkdiVO+mlk$;%lCO#z6yzLj@czr_%`au^Ye%IKR?#{^H|@`$M4^L+o~-a zzHUqK{iS=pZkl|LBY*F$6!pCmBl7o3g;uAX{uZ{Z70AAos=l`|V)whZKqU;X`^#>6 z<||zLwK&oA`PQ7zh1?sj$>*-VrO+?WuRm|G{k!|`v%i0ReKNlLPMv&v``@kMe?uqV z-mcu&rxdrRV@LJ&XEQ%nebst&W@df;-%n5fJ$`-t|MRM>S;cwg`Tu?_c_#d1c{_i5 z`KxEoYLdTydltQU=@YY)ZVwM06iGjuo}CSf8eP@xul_f^y}iAo_<7bm!}W&`cbq-@ zwNNs9+mt)2>>Z8H%?|!)dVJl)jcMK|*H$&#)Z5vVosiYYeseGG$j!}%lYlYlxid6> zLeA%BA=8W&ub*tYeO2~^9tdyx8O80Z{84zklXCBwEbi}*jmiskU!(4?bZ@V;*zb?Y zM~-%X?%7*c`-5LC`s}o6(O+u?W(faxV8@yuai&xzGO`9x%b)c7j9jr?P3Mm5T>+Wk M>FVdQ&MBb@0Pi-<#{d8T literal 0 HcmV?d00001 diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index 3fdbb145..d24681ce 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -396,6 +396,22 @@ FontWeight? parseFontWeight(String? fontWeight) { ' is not supported'); } +/// Parses a `font-style` attribute value into a [FontStyle]. +FontStyle? parseFontStyle(String? fontStyle) { + if (fontStyle == null) { + return null; + } + switch (fontStyle) { + case 'normal': + return FontStyle.normal; + case 'italic': + case 'oblique': + return FontStyle.italic; + } + throw UnsupportedError('Attribute value for font-style="$fontStyle"' + ' is not supported'); +} + /// Parses style attributes or @style attribute. /// /// Remember that @style attribute takes precedence. @@ -443,6 +459,9 @@ DrawableStyle parseStyle( fontWeight: parseFontWeight( getAttribute(attributes, 'font-weight', def: null), ), + fontStyle: parseFontStyle( + getAttribute(attributes, 'font-style', def: null), + ), anchor: parseTextAnchor( getAttribute(attributes, 'text-anchor', def: 'inherit'), ), diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index 6bfeece0..95804b18 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -145,4 +145,13 @@ void main() { expect(() => parseFontWeight('invalid'), throwsUnsupportedError); }); + + test('font-style tests', () { + expect(parseFontStyle('normal'), FontStyle.normal); + expect(parseFontStyle('italic'), FontStyle.italic); + expect(parseFontStyle('oblique'), FontStyle.italic); + + expect(parseFontStyle(null), isNull); + expect(() => parseFontStyle('invalid'), throwsUnsupportedError); + }); } From c1e76895c2f2ce82ac6fac653cfbe7cc939932e0 Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Thu, 27 May 2021 19:58:46 +0200 Subject: [PATCH 014/142] Add text-decoration support (#562) * Add text-decoration support * add golden Co-authored-by: Dan Field --- example/assets/simple/text_5.svg | 21 ++++++++++ example/lib/main.dart | 1 + golden/simple/text_5.png | Bin 0 -> 570 bytes lib/src/svg/xml_parsers.dart | 54 +++++++++++++++++++++++- test/xml_svg_test.dart | 69 +++++++++++++++++++++++++------ 5 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 example/assets/simple/text_5.svg create mode 100644 golden/simple/text_5.png diff --git a/example/assets/simple/text_5.svg b/example/assets/simple/text_5.svg new file mode 100644 index 00000000..63f711fb --- /dev/null +++ b/example/assets/simple/text_5.svg @@ -0,0 +1,21 @@ + + + Example text05 - Text decoration + + + Overline text + + + Strike text + + + Underline text + + diff --git a/example/lib/main.dart b/example/lib/main.dart index fc29e617..6a1cc8c0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -14,6 +14,7 @@ const List _assetNames = [ 'assets/simple/group_opacity.svg', 'assets/simple/text.svg', 'assets/simple/text_2.svg', + 'assets/simple/text_5.svg', 'assets/simple/linear_gradient.svg', 'assets/simple/linear_gradient_2.svg', 'assets/simple/male.svg', diff --git a/golden/simple/text_5.png b/golden/simple/text_5.png new file mode 100644 index 0000000000000000000000000000000000000000..8fee9037fb906df539f45c31fad1e94bc9e09a8a GIT binary patch literal 570 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>pxhHr7srr_IdAV8`b9g6I9xPz$@DCH{B%R7$iz(?Q`RWlKI!*j#fk}YrZMG7 zCCvMDUb8-N@1g69^ZTE#X9XHZ0?2<{vNJ|+cYDLib!GevlQ~(M927WM4lTdS{O9uD zzwbCLHhjFF^w;k0JGn+?Y55Z`w^TFrow4O$X><@Eg^;L!bN-F8>W}-8jtV{TjxxUw z7yJ8X$Hwpf`+DCuyUk5FOl$cV?R)L#^LLyQPp;43y6)cNUD&bHdn6`;Y=tqk;ejGGXwq-RZ_jE~dmkX|B<}AeN(o01MGX z;-C6U*MH`HXOX$_$HC72-Mj`+NNks1Z}W@YuA%v{!Vb@N1pyMm9H_K`|AV+ii0<#@ Svp!~lbb7k_xvX svg, { + Map svg, { bool nullOk = false, }) { final String? viewBox = getAttribute(svg, 'viewBox'); @@ -243,7 +243,7 @@ DrawablePaint? parseStroke( /// Parses a `fill` attribute. DrawablePaint? parseFill( String? key, - Map el, + Map el, Rect? bounds, DrawableDefinitionServer definitions, DrawablePaint? parentFill, @@ -412,6 +412,47 @@ FontStyle? parseFontStyle(String? fontStyle) { ' is not supported'); } +/// Parses a `text-decoration` attribute value into a [TextDecoration]. +TextDecoration? parseTextDecoration(String? textDecoration) { + if (textDecoration == null) { + return null; + } + switch (textDecoration) { + case 'none': + return TextDecoration.none; + case 'underline': + return TextDecoration.underline; + case 'overline': + return TextDecoration.overline; + case 'line-through': + return TextDecoration.lineThrough; + } + throw UnsupportedError('Attribute value for text-decoration="$textDecoration"' + ' is not supported'); +} + +/// Parses a `text-decoration-style` attribute value into a [TextDecorationStyle]. +TextDecorationStyle? parseTextDecorationStyle(String? textDecorationStyle) { + if (textDecorationStyle == null) { + return null; + } + switch (textDecorationStyle) { + case 'solid': + return TextDecorationStyle.solid; + case 'dashed': + return TextDecorationStyle.dashed; + case 'dotted': + return TextDecorationStyle.dotted; + case 'double': + return TextDecorationStyle.double; + case 'wavy': + return TextDecorationStyle.wavy; + } + throw UnsupportedError( + 'Attribute value for text-decoration-style="$textDecorationStyle"' + ' is not supported'); +} + /// Parses style attributes or @style attribute. /// /// Remember that @style attribute takes precedence. @@ -465,6 +506,15 @@ DrawableStyle parseStyle( anchor: parseTextAnchor( getAttribute(attributes, 'text-anchor', def: 'inherit'), ), + decoration: parseTextDecoration( + getAttribute(attributes, 'text-decoration', def: null), + ), + decorationColor: parseColor( + getAttribute(attributes, 'text-decoration-color', def: null), + ), + decorationStyle: parseTextDecorationStyle( + getAttribute(attributes, 'text-decoration-style', def: null), + ), ), blendMode: _blendModes[getAttribute(attributes, 'mix-blend-mode')!], ); diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index 95804b18..0243aaab 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -5,7 +5,6 @@ import 'package:flutter_svg/src/utilities/xml.dart'; import 'package:test/test.dart'; import 'package:xml/xml_events.dart'; - void main() { test('Xlink href tests', () { final XmlStartElementEvent el = @@ -17,8 +16,10 @@ void main() { 'xlink:href="http://localhost" />') .first as XmlStartElementEvent; - expect(getHrefAttribute(el.attributes.toAttributeMap()), 'http://localhost'); - expect(getHrefAttribute(elXlink.attributes.toAttributeMap()), 'http://localhost'); + expect( + getHrefAttribute(el.attributes.toAttributeMap()), 'http://localhost'); + expect(getHrefAttribute(elXlink.attributes.toAttributeMap()), + 'http://localhost'); }); test('Attribute and style tests', () { @@ -77,17 +78,37 @@ void main() { final XmlStartElementEvent svgWithNoSizeInfo = parseEvents('').first as XmlStartElementEvent; - expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())!.size, + expect( + parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())! + .size, const Size(50, 50)); - expect(parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxRect, rect); - expect(parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxOffset, Offset.zero); - expect(parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())!.viewBoxRect, + expect( + parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxRect, + rect); + expect( + parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxOffset, + Offset.zero); + expect( + parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())! + .viewBoxRect, + rect); + expect( + parseViewBox(svgWithWidthHeight.attributes.toAttributeMap())! + .viewBoxRect, + rect); + expect( + parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap(), + nullOk: true), + null); + expect(() => parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap()), + throwsStateError); + expect( + parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())! + .viewBoxRect, rect); - expect(parseViewBox(svgWithWidthHeight.attributes.toAttributeMap())!.viewBoxRect, rect); - expect(parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap(), nullOk: true), null); - expect(() => parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap()), throwsStateError); - expect(parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())!.viewBoxRect, rect); - expect(parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())!.viewBoxOffset, + expect( + parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())! + .viewBoxOffset, const Offset(-42.0, -56.0)); }); @@ -113,7 +134,8 @@ void main() { expect(parseTileMode(none.attributes.toAttributeMap()), TileMode.clamp); expect(parseTileMode(reflect.attributes.toAttributeMap()), TileMode.mirror); - expect(parseTileMode(repeat.attributes.toAttributeMap()), TileMode.repeated); + expect( + parseTileMode(repeat.attributes.toAttributeMap()), TileMode.repeated); }); test('@stroke-dashoffset tests', () { @@ -154,4 +176,25 @@ void main() { expect(parseFontStyle(null), isNull); expect(() => parseFontStyle('invalid'), throwsUnsupportedError); }); + + test('text-decoration tests', () { + expect(parseTextDecoration('none'), TextDecoration.none); + expect(parseTextDecoration('line-through'), TextDecoration.lineThrough); + expect(parseTextDecoration('overline'), TextDecoration.overline); + expect(parseTextDecoration('underline'), TextDecoration.underline); + + expect(parseTextDecoration(null), isNull); + expect(() => parseTextDecoration('invalid'), throwsUnsupportedError); + }); + + test('text-decoration-style tests', () { + expect(parseTextDecorationStyle('solid'), TextDecorationStyle.solid); + expect(parseTextDecorationStyle('dashed'), TextDecorationStyle.dashed); + expect(parseTextDecorationStyle('dotted'), TextDecorationStyle.dotted); + expect(parseTextDecorationStyle('double'), TextDecorationStyle.double); + expect(parseTextDecorationStyle('wavy'), TextDecorationStyle.wavy); + + expect(parseTextDecorationStyle(null), isNull); + expect(() => parseTextDecorationStyle('invalid'), throwsUnsupportedError); + }); } From 38ca86ea768b09d684beff1e19b944ce699212fd Mon Sep 17 00:00:00 2001 From: Niklas Schulze Date: Tue, 1 Jun 2021 17:59:12 +0200 Subject: [PATCH 015/142] Add support for xml:space (#563) --- lib/src/svg/parser_state.dart | 16 ++++++++++++---- test/svg_parsers_test.dart | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index d72b61bf..28891752 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -20,6 +20,8 @@ typedef _ParseFunc = Future? Function( SvgParserState parserState, bool warningsAsErrors); typedef _PathFunc = Path? Function(Map attributes); +final RegExp _trimPattern = RegExp(r'[\r|\n|\t]'); + const Map _svgElementParsers = { 'svg': _Elements.svg, 'g': _Elements.g, @@ -623,7 +625,13 @@ class _Elements { if (event is XmlCDATAEvent) { _processText(event.text.trim()); } else if (event is XmlTextEvent) { - _processText(event.text.trim()); + final String? space = + getAttribute(parserState.attributes, 'space', def: null); + if (space != 'preserve') { + _processText(event.text.trim()); + } else { + _processText(event.text.replaceAll(_trimPattern, '')); + } } if (event is XmlStartElementEvent) { _processStartElement(event); @@ -677,8 +685,7 @@ class _Paths { return parsePathFromPoints(attributes, false); } - static Path? parsePathFromPoints( - Map attributes, bool close) { + static Path? parsePathFromPoints(Map attributes, bool close) { final String? points = getAttribute(attributes, 'points'); if (points == '') { return null; @@ -764,7 +771,8 @@ class SvgParserState { final XmlEvent event = _eventIterator.current; bool isSelfClosing = false; if (event is XmlStartElementEvent) { - final Map attributeMap = event.attributes.toAttributeMap(); + final Map attributeMap = + event.attributes.toAttributeMap(); if (getAttribute(attributeMap, 'display') == 'none' || getAttribute(attributeMap, 'visibility') == 'hidden') { print('SVG Warning: Discarding:\n\n $event\n\n' diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index f87b02be..a6f1e5ba 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -258,4 +258,19 @@ void main() { final SvgParser parser = SvgParser(); expect(await parser.parse(svgStr), isA()); }); + + test('Respects whitespace attribute', () async { + const String svgStr = ''' + + + +'''; + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse(svgStr); + + expect(find(root, 'preserve-space') != null, true); + // Empty text elements get removed + expect(find(root, 'remove-space') != null, false); + }); } From f75eaeabaef1ffd5b52c679043b714787ee1d914 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Thu, 15 Jul 2021 09:31:40 -0700 Subject: [PATCH 016/142] change golden file compares to allow +/- 1 in color components (#575) * change golden file compares to allow +/- 1 in color components * accept format results (only for files changed here) * explicitly require rawRgba bytes --- test/golden_svg_test.dart | 21 ++++++++++++++++----- tool/gen_golden.dart | 17 ++++++++++++++--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/test/golden_svg_test.dart b/test/golden_svg_test.dart index e72e43a9..dc0eaef0 100644 --- a/test/golden_svg_test.dart +++ b/test/golden_svg_test.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'dart:typed_data'; +import 'dart:ui'; import 'package:path/path.dart'; @@ -28,16 +29,26 @@ String getSvgAssetName(String goldenFileName) { .replaceAll('.png', '.svg'); } +bool colorComponentsSimilar(int a, int b) => (a - b).abs() <= 1; + void main() { test('SVG Rendering matches golden files', () async { for (File goldenFile in getGoldenFileNames()) { final File svgAssetFile = File(getSvgAssetName(goldenFile.path)); final Uint8List bytes = - await golden.getSvgPngBytes(await svgAssetFile.readAsString()); - - final Uint8List goldenBytes = await goldenFile.readAsBytes(); - - expect(bytes, orderedEquals(goldenBytes), + await golden.getSvgRgbaBytes(await svgAssetFile.readAsString()); + + final Codec testImageCodec = + await instantiateImageCodec(await goldenFile.readAsBytes()); + final Image testImage = (await testImageCodec.getNextFrame()).image; + final ByteData? goldenRgba = + await testImage.toByteData(format: ImageByteFormat.rawRgba); + final Uint8List goldenBytes = goldenRgba!.buffer.asUint8List(); + + expect( + bytes, + pairwiseCompare(goldenBytes, colorComponentsSimilar, + 'components nearly equal to'), reason: '${goldenFile.path} does not match rendered output of ${svgAssetFile.path}!'); } diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index 79eb8725..afb04a1d 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -13,7 +13,7 @@ import 'package:flutter_svg/src/vector_drawable.dart'; import 'package:flutter_svg/svg.dart'; import 'package:path/path.dart' as path; -Future getSvgPngBytes(String svgData) async { +Future getSvgImage(String svgData) async { final PictureRecorder rec = PictureRecorder(); final Canvas canvas = Canvas(rec); @@ -29,13 +29,24 @@ Future getSvgPngBytes(String svgData) async { final Picture pict = rec.endRecording(); - final Image image = - await pict.toImage(size.width.toInt(), size.height.toInt()); + return await pict.toImage(size.width.toInt(), size.height.toInt()); +} + +Future getSvgPngBytes(String svgData) async { + final Image image = await getSvgImage(svgData); final ByteData bytes = (await image.toByteData(format: ImageByteFormat.png))!; return bytes.buffer.asUint8List(); } +Future getSvgRgbaBytes(String svgData) async { + final Image image = await getSvgImage(svgData); + final ByteData bytes = + (await image.toByteData(format: ImageByteFormat.rawRgba))!; + + return bytes.buffer.asUint8List(); +} + Iterable getSvgFileNames() sync* { final Directory dir = Directory('./example/assets'); for (FileSystemEntity fe in dir.listSync(recursive: true)) { From 08d248b4680ab19a0cf0bf8a2a39df2fba5aa4ad Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 16 Aug 2021 11:09:30 -0700 Subject: [PATCH 017/142] pub get --- .cirrus.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 938eb390..c1dfcb3a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -11,8 +11,7 @@ test_task: matrix: - image: cirrusci/flutter:dev - image: cirrusci/flutter:stable - pub_cache: - folder: ~/.pub-cache + pub_script: flutter pub get analyze_script: flutter analyze . test_script: flutter test --coverage coveralls_script: ./.ci/coveralls.sh From 5de1f00cf362e29e2b305aac5bfd21a2e3714d35 Mon Sep 17 00:00:00 2001 From: Nikita Mishkov Date: Mon, 16 Aug 2021 21:29:43 +0300 Subject: [PATCH 018/142] Unused parameter `bounds` of method draw() (#584) * updated README --- README.md | 3 ++- lib/src/utilities/xml.dart | 6 +++--- lib/src/vector_drawable.dart | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 05704721..2d06fb48 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,8 @@ svgRoot.scaleCanvasToViewBox(canvas); // Optional, but probably normally desireable: ensure the SVG isn't rendered // outside of the viewbox bounds svgRoot.clipCanvasToViewBox(canvas); -svgRoot.draw(canvas, size); +// The second parameter is not used +svgRoot.draw(canvas, null); ``` The `SvgPicture` helps to automate this logic, and it provides some convenience diff --git a/lib/src/utilities/xml.dart b/lib/src/utilities/xml.dart index 018972b5..61a57cf6 100644 --- a/lib/src/utilities/xml.dart +++ b/lib/src/utilities/xml.dart @@ -63,7 +63,7 @@ String _getAttribute( extension AttributeMapXmlEventAttributeExtension on List { /// Converts the List to an attribute map. Map toAttributeMap() => { - for (final XmlEventAttribute attribute in this) - attribute.localName: attribute.value.trim(), - }; + for (final XmlEventAttribute attribute in this) + attribute.localName: attribute.value.trim(), + }; } diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 8016b72d..59f27853 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -885,6 +885,10 @@ class DrawableRoot implements DrawableParent { bool get hasDrawableContent => children.isNotEmpty == true && !viewport.viewBox.isEmpty; + /// Draws the contents or children of this [Drawable] to the `canvas`, using + /// the `parentPaint` to optionally override the child's paint. + /// + /// The `bounds` is not used. @override void draw(Canvas canvas, Rect bounds) { if (!hasDrawableContent) { From 50d2d69bc1bf2215b755f268adfdc3b83e74886b Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Mon, 16 Aug 2021 12:17:12 -0700 Subject: [PATCH 019/142] add a simple scrolling benchmark for the example (#583) * add a simple scrolling benchmark for the example * fix analyzer errors and remove print statements * pub get Co-authored-by: Dan Field --- example/README.md | 4 ++++ example/pubspec.yaml | 2 ++ example/test_driver/bench.dart | 7 +++++++ example/test_driver/bench_test.dart | 27 +++++++++++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 example/test_driver/bench.dart create mode 100644 example/test_driver/bench_test.dart diff --git a/example/README.md b/example/README.md index 64a12f6b..5a322939 100644 --- a/example/README.md +++ b/example/README.md @@ -6,3 +6,7 @@ A new Flutter project. For help getting started with Flutter, view our online [documentation](https://flutter.io/). + +## Benchmarking + +`flutter drive --profile --endless-trace-buffer --target test_driver/bench.dart` diff --git a/example/pubspec.yaml b/example/pubspec.yaml index c93f4bba..57954c78 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -6,6 +6,8 @@ publish_to: none dependencies: flutter: sdk: flutter + flutter_driver: + sdk: flutter flutter_svg: path: ../ diff --git a/example/test_driver/bench.dart b/example/test_driver/bench.dart new file mode 100644 index 00000000..7854092a --- /dev/null +++ b/example/test_driver/bench.dart @@ -0,0 +1,7 @@ +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_svg_example/main.dart' as app; + +void main() { + enableFlutterDriverExtension(); + app.main(); +} diff --git a/example/test_driver/bench_test.dart b/example/test_driver/bench_test.dart new file mode 100644 index 00000000..f63172bc --- /dev/null +++ b/example/test_driver/bench_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter_driver/flutter_driver.dart'; + +Future main() async { + final SerializableFinder view = find.byType('GridView'); + + final FlutterDriver driver = await FlutterDriver.connect(); + try { + await driver.waitUntilFirstFrameRasterized(); + await Future.delayed(const Duration(milliseconds: 1000)); + await driver.forceGC(); + await driver.clearTimeline(); + await Future.delayed(const Duration(milliseconds: 1000)); + + final Timeline timeline = await driver.traceAction(() async { + await driver.scroll( + view, + 0, -3400, + const Duration(seconds: 10), + timeout: const Duration(seconds: 15), + ); + }); + final TimelineSummary summary = TimelineSummary.summarize(timeline); + await summary.writeTimelineToFile('bench', pretty: true); + } finally { + await driver.close(); + } +} From 2b422b0cbf748b29ef92f76874c627ee2db49674 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 16 Aug 2021 12:21:24 -0700 Subject: [PATCH 020/142] ignore avoid_classe_with_only_static_members for now --- example/linux/flutter/generated_plugin_registrant.cc | 2 ++ example/linux/flutter/generated_plugin_registrant.h | 2 ++ example/windows/flutter/generated_plugin_registrant.cc | 2 ++ example/windows/flutter/generated_plugin_registrant.h | 2 ++ lib/src/svg/parser_state.dart | 2 ++ 5 files changed, 10 insertions(+) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index d38195aa..e71a16d2 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h index 9bf74789..e0f0a47b 100644 --- a/example/linux/flutter/generated_plugin_registrant.h +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 4bfa0f3a..8b6d4680 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h index 9846246b..dc139d85 100644 --- a/example/windows/flutter/generated_plugin_registrant.h +++ b/example/windows/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 28891752..d7aa1f05 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -77,6 +77,7 @@ class _TextInfo { String toString() => '$runtimeType{$offset, $style, $transform}'; } +// ignore: avoid_classes_with_only_static_members class _Elements { static Future? svg(SvgParserState parserState, bool warningsAsErrors) { final DrawableViewport? viewBox = parseViewBox(parserState.attributes); @@ -642,6 +643,7 @@ class _Elements { } } +// ignore: avoid_classes_with_only_static_members class _Paths { static Path circle(Map attributes) { final double cx = parseDouble(getAttribute(attributes, 'cx', def: '0'))!; From 86ab68f80785c714c1d9c8b82ab6fbd6e1a32b09 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 23 Aug 2021 10:55:59 -0700 Subject: [PATCH 021/142] update opacity --- golden/simple/use_opacity_grid.png | Bin 957 -> 959 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/golden/simple/use_opacity_grid.png b/golden/simple/use_opacity_grid.png index 759ee8ea264591a0e63eb92bdb0d9dea951aa7da..e9bd18ccbc1f0e4ecb0fc17a2e280982b604f678 100644 GIT binary patch literal 959 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_tI#PZ!6KiaBp@Z}dve6k-4HIBx?-m(wK;9u00Tv+V47jt9*R-Y29g{@}3l zI&w|vub5RCCr``_FM~I!cYAwWHn|38IU5tH=aD zGS7bb{rBIEINSZ5Kki7${NE?H(ZYV)cBzxkuPxYq^rvI|R%}ySTQtw*9X4<(X!)FXnAeuB^1&wtahdp1P8f)m*=r zn3yAP-{$7z=DIEo(%iMQL!zdAuAlm|=g*UKbJxBoQ&M{L?w#HzoBrRwf3FD9GPJgi zF7aN>u5x-)L~LyBn*RR&$AA9p`7l97R`%%2moJm=W^GNXuit;5kL{s_g+;}h^XJYz z`tV`HhY2RL&t`0m>i_!nYw4A&txVQZEssBa`m}N1u3cTdy}gH=jXtS{ExstR>a$IK z**cE1X~ir4+3C3M+_6Jq)$Y6RHW#~|*p#y(Z~JZ5(oZVqKQG*M{k5%ic*{g)BVOPA zPo6zn_Cjpl%d*|B+dnMIzrRoP?jhs7aqC}*#hDa2y!!epVDE+v0=swbwqLXG`>mTd zJ+Ha`c%SOMGp6tC*|SZ%DmU%3+p|7d>YBpUtkM;FQ@u9s*bxz6?tgDuOkP~}(H_tq4>#f(X`#I0QI@|q)^W3Y%iT7TA zT@C20+E&u<;;@o+AuFX}u zInQM+yZ&$S+-iPWS^Rq&d?cnaC*O3Eemwi$vs2k? zeVM_!R+(&+4k~{7a_7&`UteDqMpgZq7rFQDjP$2M+(IlYlprz_G*Fw}vU*1SUz)G} Sx<~4OO!0K}b6Mw<&;$Si+=Q$E literal 957 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_tJIPZ!6KiaBp@pY>AC6k&VtSi`A%(S#fkwkeG4cY30WdAaU2?qn~2bjbTd zkkSs(P4inbV>C@fzIYk<7`}Dk;GF6DLH%Ei#LFd4zinn;(e!v)acK2@_eepYRb+zw zYgWdszb<|A>SuYuc>UkU>;Fn_++wh)U+UEL({=gY+<*6}HAe2eFOmNB_K9^o`xzJ; zS#YD4nf-e-Pj9lYwCuDwpPZks9~K^7UluPPwEp_zSFg0f!orfOt9QRBQ&L)VGskW5 z#g5&(ci*^mt1D<_NQt-L#s7S>&!*|<=p6a=tLoxg7Z;b^cl&J4FTVZOZDmN;&6_tD zMN8Q!L{2+;>((vj+L{`f=g*(Fwm*6CLc`DBU;fqU)2DCTzpuYxah(MpAD`T-&6_t{ z*x2aUsC?h=@$T-OJ1$FuG(nPjdU|rNUcY{QB zYt-6B(G{V)@9OPp6}Ot}cTsmw){BOa)mIy<3JVR(%FFAcoaMjPoZq;4b8vuq|2+NZ zeKkLYX3w6@TKf6L&w0s0-xQt}RW6t}Z(iThrAwQ3Reo8>zHF0Dchp+3%6aZvqiU=F z8$N4qcz698(2Fk{dOj*H`0ZP@`f8Wg(of(1C7;<`^d4Og#Tav^;h9VtGmaq2mbqW*kJW{>Bno9Rejyx zy?-&A@F^i~p=DM7|5)$Zudsb>NB(_as`w*kXm1Wm72Dtcz4z?-uUcQG%~ksi&t;|M zm@j$uTu0_^e!b+&mnp#1(vhCp$;!#ZL Date: Tue, 14 Sep 2021 17:05:55 -0700 Subject: [PATCH 022/142] Add hacky support for currentColor (#588) * add support for currentColor * refactor to support passing colors down from parent * add another circle to show override works * revert strokeColor change for avd Co-authored-by: Lee Standen --- example/assets/svg_currentcolor.svg | 7 +++++++ .../linux/flutter/generated_plugin_registrant.cc | 2 -- .../linux/flutter/generated_plugin_registrant.h | 2 -- example/test_driver/bench_test.dart | 3 ++- .../flutter/generated_plugin_registrant.cc | 2 -- .../flutter/generated_plugin_registrant.h | 2 -- golden/svg_currentcolor.png | Bin 0 -> 4234 bytes lib/src/svg/colors.dart | 4 ++++ lib/src/svg/xml_parsers.dart | 4 +++- test/colors_svg_test.dart | 2 ++ 10 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 example/assets/svg_currentcolor.svg create mode 100644 golden/svg_currentcolor.png diff --git a/example/assets/svg_currentcolor.svg b/example/assets/svg_currentcolor.svg new file mode 100644 index 00000000..850efed2 --- /dev/null +++ b/example/assets/svg_currentcolor.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index e71a16d2..d38195aa 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #include "generated_plugin_registrant.h" diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h index e0f0a47b..9bf74789 100644 --- a/example/linux/flutter/generated_plugin_registrant.h +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/test_driver/bench_test.dart b/example/test_driver/bench_test.dart index f63172bc..b23125b7 100644 --- a/example/test_driver/bench_test.dart +++ b/example/test_driver/bench_test.dart @@ -14,7 +14,8 @@ Future main() async { final Timeline timeline = await driver.traceAction(() async { await driver.scroll( view, - 0, -3400, + 0, + -3400, const Duration(seconds: 10), timeout: const Duration(seconds: 15), ); diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 8b6d4680..4bfa0f3a 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #include "generated_plugin_registrant.h" diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h index dc139d85..9846246b 100644 --- a/example/windows/flutter/generated_plugin_registrant.h +++ b/example/windows/flutter/generated_plugin_registrant.h @@ -2,8 +2,6 @@ // Generated file. Do not edit. // -// clang-format off - #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/golden/svg_currentcolor.png b/golden/svg_currentcolor.png new file mode 100644 index 0000000000000000000000000000000000000000..47d93874deebc2b7ef8c7aec566ac79354514efd GIT binary patch literal 4234 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 literal 0 HcmV?d00001 diff --git a/lib/src/svg/colors.dart b/lib/src/svg/colors.dart index 323475c0..4863e2d1 100644 --- a/lib/src/svg/colors.dart +++ b/lib/src/svg/colors.dart @@ -15,6 +15,10 @@ Color? parseColor(String? colorString) { return null; } + if (colorString.toLowerCase() == 'currentcolor') { + return null; + } + // handle hex colors e.g. #fff or #ffffff. This supports #RRGGBBAA if (colorString[0] == '#') { if (colorString.length == 4) { diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index 876ecd36..fff792da 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -217,7 +217,8 @@ DrawablePaint? parseStroke( PaintingStyle.stroke, color: rawStroke == '' ? (parentStroke?.color ?? colorBlack).withOpacity(opacity) - : parseColor(rawStroke)!.withOpacity(opacity), + : (parseColor(rawStroke) ?? parentStroke?.color ?? colorBlack) + .withOpacity(opacity), strokeCap: rawStrokeCap == 'null' ? parentStroke?.strokeCap ?? StrokeCap.butt : StrokeCap.values.firstWhere( @@ -267,6 +268,7 @@ DrawablePaint? parseFill( opacity: opacity, ); } + if (rawFill == '' && parentFill == DrawablePaint.empty) { return null; } diff --git a/test/colors_svg_test.dart b/test/colors_svg_test.dart index ab02451d..45c431eb 100644 --- a/test/colors_svg_test.dart +++ b/test/colors_svg_test.dart @@ -28,6 +28,8 @@ void main() { expect(parseColor('hsl(192,55%,29%)'), const Color(0xFF216273)); expect(parseColor('hsl(297,55%,29%)'), const Color(0xFF6F2173)); expect(parseColor('hsla(0,0%,100%, 0.0)'), const Color(0x00FFFFFF)); + expect(parseColor('currentColor'), null); + expect(parseColor('currentcolor'), null); expect(() => parseColor('invalid name'), throwsStateError); }); } From d2ca8bdc35ec4aac33a878852715b4a27e36851c Mon Sep 17 00:00:00 2001 From: Bartosz Selwesiuk Date: Sat, 2 Oct 2021 00:15:50 +0200 Subject: [PATCH 023/142] Add support for `currentColor` to `SvgPicture` (#602) --- lib/avd.dart | 199 +++++++++++++++++++--- lib/parser.dart | 6 +- lib/src/picture_provider.dart | 102 ++++++++++-- lib/src/svg/default_theme.dart | 41 +++++ lib/src/svg/parser_state.dart | 42 ++++- lib/src/svg/theme.dart | 24 +++ lib/src/svg/xml_parsers.dart | 19 ++- lib/src/vector_drawable.dart | 20 ++- lib/svg.dart | 197 +++++++++++++--------- pubspec.yaml | 1 + test/default_theme_test.dart | 79 +++++++++ test/picture_cache_test.dart | 6 +- test/picture_provider_test.dart | 146 ++++++++++++++++ test/svg_parsers_test.dart | 285 +++++++++++++++++++++++++++++++- test/theme_test.dart | 33 ++++ test/vector_drawable_test.dart | 2 + test/widget_svg_test.dart | 2 + test/xml_svg_test.dart | 39 +++++ tool/gen_golden.dart | 3 +- 19 files changed, 1115 insertions(+), 131 deletions(-) create mode 100644 lib/src/svg/default_theme.dart create mode 100644 lib/src/svg/theme.dart create mode 100644 test/default_theme_test.dart create mode 100644 test/picture_provider_test.dart create mode 100644 test/theme_test.dart diff --git a/lib/avd.dart b/lib/avd.dart index 33c88f89..fff441d8 100644 --- a/lib/avd.dart +++ b/lib/avd.dart @@ -2,15 +2,17 @@ import 'dart:convert'; import 'dart:typed_data'; import 'dart:ui' show Picture; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart' show AssetBundle; import 'package:flutter/widgets.dart'; import 'package:xml/xml.dart'; -import './svg.dart'; import 'src/avd/xml_parsers.dart'; import 'src/avd_parser.dart'; import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; +import 'src/render_picture.dart'; +import 'src/unbounded_color_filtered.dart'; import 'src/vector_drawable.dart'; /// Instance for [Avd]'s utility methods, which can produce [DrawableRoot] or @@ -95,24 +97,27 @@ class Avd { /// [PictureProvider]. /// /// Support for AVD is incomplete and experimental at this time. -class AvdPicture extends SvgPicture { - /// Instantiates a widget that renders an SVG picture using the - /// `pictureProvider`. +class AvdPicture extends StatefulWidget { + /// Instantiates a widget that renders an AVD picture using the `pictureProvider`. + /// + /// If `matchTextDirection` is set to true, the picture will be flipped + /// horizontally in [TextDirection.rtl] contexts. + /// + /// The `allowDrawingOutsideOfViewBox` parameter should be used with caution - + /// if set to true, it will not clip the canvas used internally to the view box, + /// meaning the picture may draw beyond the intended area and lead to undefined + /// behavior or additional memory overhead. + /// + /// A custom `placeholderBuilder` can be specified for cases where decoding or + /// acquiring data may take a noticeably long time, e.g. for a network picture. const AvdPicture( - PictureProvider pictureProvider, { + this.pictureProvider, { Key? key, - bool matchTextDirection = false, - bool allowDrawingOutsideViewBox = false, - WidgetBuilder? placeholderBuilder, - ColorFilter? colorFilter, - }) : super( - pictureProvider, - key: key, - matchTextDirection: matchTextDirection, - allowDrawingOutsideViewBox: allowDrawingOutsideViewBox, - placeholderBuilder: placeholderBuilder, - colorFilter: colorFilter, - ); + this.matchTextDirection = false, + this.allowDrawingOutsideViewBox = false, + this.placeholderBuilder, + this.colorFilter, + }) : super(key: key); /// Draws an [AvdPicture] from a raw string of XML. AvdPicture.string(String bytes, @@ -125,8 +130,8 @@ class AvdPicture extends SvgPicture { : this( StringPicture( allowDrawingOutsideViewBox == true - ? avdStringDecoderOutsideViewBox - : avdStringDecoder, + ? (_) => avdStringDecoderOutsideViewBox + : (_) => avdStringDecoder, bytes, ), colorFilter: _getColorFilter(color, colorBlendMode), @@ -148,8 +153,8 @@ class AvdPicture extends SvgPicture { : this( ExactAssetPicture( allowDrawingOutsideViewBox == true - ? avdStringDecoderOutsideViewBox - : avdStringDecoder, + ? (_) => avdStringDecoderOutsideViewBox + : (_) => avdStringDecoder, assetName, bundle: bundle, package: package, @@ -160,6 +165,11 @@ class AvdPicture extends SvgPicture { placeholderBuilder: placeholderBuilder, key: key); + /// The default placeholder for an AVD that may take time to parse or + /// retrieve, e.g. from a network location. + static WidgetBuilder defaultPlaceholderBuilder = + (BuildContext ctx) => const LimitedBox(); + static ColorFilter? _getColorFilter(Color? color, BlendMode colorBlendMode) => color == null ? null : ColorFilter.mode(color, colorBlendMode); @@ -182,4 +192,151 @@ class AvdPicture extends SvgPicture { static final PictureInfoDecoder avdStringDecoderOutsideViewBox = (String data, ColorFilter? colorFilter, String key) => avd.avdPictureStringDecoder(data, true, colorFilter, key); + + /// The [PictureProvider] used to resolve the AVD. + final PictureProvider pictureProvider; + + /// The placeholder to use while fetching, decoding, and parsing the AVD data. + final WidgetBuilder? placeholderBuilder; + + /// If true, will horizontally flip the picture in [TextDirection.rtl] contexts. + final bool matchTextDirection; + + /// If true, will allow the AVD to be drawn outside of the clip boundary of its + /// viewBox. + final bool allowDrawingOutsideViewBox; + + /// The color filter, if any, to apply to this widget. + final ColorFilter? colorFilter; + + @override + State createState() => _AvdPictureState(); +} + +class _AvdPictureState extends State { + PictureInfo? _picture; + PictureStream? _pictureStream; + bool _isListeningToStream = false; + + @override + void didChangeDependencies() { + _resolveImage(); + + if (TickerMode.of(context)) { + _listenToStream(); + } else { + _stopListeningToStream(); + } + super.didChangeDependencies(); + } + + @override + void didUpdateWidget(AvdPicture oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.pictureProvider != oldWidget.pictureProvider) { + _resolveImage(); + } + } + + @override + void reassemble() { + _resolveImage(); // in case the image cache was flushed + super.reassemble(); + } + + void _resolveImage() { + final PictureStream newStream = widget.pictureProvider + .resolve(createLocalPictureConfiguration(context)); + assert(newStream != null); // ignore: unnecessary_null_comparison + _updateSourceStream(newStream); + } + + void _handleImageChanged(PictureInfo? imageInfo, bool synchronousCall) { + setState(() { + _picture = imageInfo; + }); + } + + // Update _pictureStream to newStream, and moves the stream listener + // registration from the old stream to the new stream (if a listener was + // registered). + void _updateSourceStream(PictureStream newStream) { + if (_pictureStream?.key == newStream.key) { + return; + } + + if (_isListeningToStream) + _pictureStream!.removeListener(_handleImageChanged); + + _pictureStream = newStream; + if (_isListeningToStream) { + _pictureStream!.addListener(_handleImageChanged); + } + } + + void _listenToStream() { + if (_isListeningToStream) { + return; + } + _pictureStream!.addListener(_handleImageChanged); + _isListeningToStream = true; + } + + void _stopListeningToStream() { + if (!_isListeningToStream) { + return; + } + _pictureStream!.removeListener(_handleImageChanged); + _isListeningToStream = false; + } + + @override + void dispose() { + assert(_pictureStream != null); + _stopListeningToStream(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + late Widget child; + if (_picture != null) { + final Rect viewport = Offset.zero & _picture!.viewport.size; + + child = SizedBox( + width: viewport.width, + height: viewport.height, + child: FittedBox( + clipBehavior: Clip.hardEdge, + child: SizedBox.fromSize( + size: viewport.size, + child: RawPicture( + _picture, + matchTextDirection: widget.matchTextDirection, + allowDrawingOutsideViewBox: widget.allowDrawingOutsideViewBox, + ), + ), + ), + ); + + if (widget.pictureProvider.colorFilter == null && + widget.colorFilter != null) { + child = UnboundedColorFiltered( + colorFilter: widget.colorFilter, + child: child, + ); + } + } else { + child = AvdPicture.defaultPlaceholderBuilder(context); + } + return child; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder description) { + super.debugFillProperties(description); + description.add( + DiagnosticsProperty('stream', _pictureStream), + ); + } } diff --git a/lib/parser.dart b/lib/parser.dart index 22cd1fdf..d720192f 100644 --- a/lib/parser.dart +++ b/lib/parser.dart @@ -1,11 +1,12 @@ import 'package:xml/xml_events.dart' as xml show parseEvents; import 'src/svg/parser_state.dart'; +import 'src/svg/theme.dart'; import 'src/vector_drawable.dart'; /// Parses SVG data into a [DrawableRoot]. class SvgParser { - /// Parses SVG from a string to a [DrawableRoot]. + /// Parses SVG from a string to a [DrawableRoot] with the provided [theme]. /// /// The [key] parameter is used for debugging purposes. /// @@ -17,11 +18,12 @@ class SvgParser { /// Defaults to false. Future parse( String str, { + SvgTheme? theme, String? key, bool warningsAsErrors = false, }) async { final SvgParserState state = - SvgParserState(xml.parseEvents(str), key, warningsAsErrors); + SvgParserState(xml.parseEvents(str), theme, key, warningsAsErrors); return await state.parse(); } } diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 926e91c9..503d6c3f 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -27,6 +27,12 @@ typedef PictureInfoDecoder = Future Function( String key, ); +/// The signature of a builder that returns a [PictureInfoDecoder] +/// based on the [currentColor]. +typedef PictureInfoDecoderBuilder = PictureInfoDecoder Function( + Color? currentColor, +); + /// Creates an [PictureConfiguration] based on the given [BuildContext] (and /// optionally size). /// @@ -299,7 +305,7 @@ class PictureConfiguration { abstract class PictureProvider { /// Abstract const constructor. This constructor enables subclasses to provide /// const constructors so that they can be used in const expressions. - const PictureProvider(this.colorFilter); + PictureProvider(this.colorFilter); /// The [PictureCache] for [Picture] objects created by [PictureProvider] /// implementations. @@ -316,6 +322,14 @@ abstract class PictureProvider { /// The color filter to apply to the picture, if any. final ColorFilter? colorFilter; + /// The default color applied to SVG elements that inherit the color property. + @visibleForTesting + Color? get currentColor => _currentColor; + Color? _currentColor; + + /// Sets the [_currentColor] to [color]. + set currentColor(Color? color); + /// Resolves this Picture provider using the given `configuration`, returning /// an [PictureStream]. /// @@ -433,12 +447,23 @@ abstract class AssetBundlePictureProvider extends PictureProvider { /// Abstract const constructor. This constructor enables subclasses to provide /// const constructors so that they can be used in const expressions. - const AssetBundlePictureProvider(this.decoder, ColorFilter? colorFilter) - : assert(decoder != null), // ignore: unnecessary_null_comparison + AssetBundlePictureProvider(this.decoderBuilder, ColorFilter? colorFilter) + : assert(decoderBuilder != null), // ignore: unnecessary_null_comparison + decoder = decoderBuilder(null), super(colorFilter); + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + /// The decoder to use to turn a string into a [PictureInfo] object. - final PictureInfoDecoder decoder; + @visibleForTesting + PictureInfoDecoder decoder; + + @override + set currentColor(Color? color) { + _currentColor = color; + decoder = decoderBuilder(_currentColor); + } /// Converts a key into an [PictureStreamCompleter], and begins fetching the /// picture using [_loadAsync]. @@ -488,13 +513,18 @@ class NetworkPicture extends PictureProvider { /// Creates an object that fetches the picture at the given URL. /// /// The arguments must not be null. - const NetworkPicture(this.decoder, this.url, + NetworkPicture(this.decoderBuilder, this.url, {this.headers, ColorFilter? colorFilter}) : assert(url != null), // ignore: unnecessary_null_comparison + decoder = decoderBuilder(null), super(colorFilter); + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + /// The decoder to use to turn a [Uint8List] into a [PictureInfo] object. - final PictureInfoDecoder decoder; + @visibleForTesting + PictureInfoDecoder decoder; /// The URL from which the picture will be fetched. final String url; @@ -502,6 +532,12 @@ class NetworkPicture extends PictureProvider { /// The HTTP headers that will be used with [HttpClient.get] to fetch picture from network. final Map? headers; + @override + set currentColor(Color? color) { + _currentColor = color; + decoder = decoderBuilder(_currentColor); + } + @override Future obtainKey(PictureConfiguration picture) { return SynchronousFuture(this); @@ -521,6 +557,7 @@ class NetworkPicture extends PictureProvider { {PictureErrorListener? onError}) async { assert(key == this); final Uint8List bytes = await httpGet(url, headers: headers); + if (onError != null) { return decoder( bytes, @@ -562,16 +599,27 @@ class FilePicture extends PictureProvider { /// Creates an object that decodes a [File] as a picture. /// /// The arguments must not be null. - const FilePicture(this.decoder, this.file, {ColorFilter? colorFilter}) - : assert(decoder != null), // ignore: unnecessary_null_comparison + FilePicture(this.decoderBuilder, this.file, {ColorFilter? colorFilter}) + : assert(decoderBuilder != null), // ignore: unnecessary_null_comparison assert(file != null), // ignore: unnecessary_null_comparison + decoder = decoderBuilder(null), super(colorFilter); /// The file to decode into a picture. final File file; + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + /// The [PictureInfoDecoder] to use for loading this picture. - final PictureInfoDecoder decoder; + @visibleForTesting + PictureInfoDecoder decoder; + + @override + set currentColor(Color? color) { + _currentColor = color; + decoder = decoderBuilder(_currentColor); + } @override Future obtainKey(PictureConfiguration picture) { @@ -642,16 +690,27 @@ class MemoryPicture extends PictureProvider { /// Creates an object that decodes a [Uint8List] buffer as a picture. /// /// The arguments must not be null. - const MemoryPicture(this.decoder, this.bytes, {ColorFilter? colorFilter}) + MemoryPicture(this.decoderBuilder, this.bytes, {ColorFilter? colorFilter}) : assert(bytes != null), // ignore: unnecessary_null_comparison + decoder = decoderBuilder(null), super(colorFilter); + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + /// The [PictureInfoDecoder] to use when drawing this picture. - final PictureInfoDecoder decoder; + @visibleForTesting + PictureInfoDecoder decoder; /// The bytes to decode into a picture. final Uint8List bytes; + @override + set currentColor(Color? color) { + _currentColor = color; + decoder = decoderBuilder(_currentColor); + } + @override Future obtainKey(PictureConfiguration picture) { return SynchronousFuture(this); @@ -712,16 +771,27 @@ class StringPicture extends PictureProvider { /// Creates an object that decodes a [Uint8List] buffer as a picture. /// /// The arguments must not be null. - const StringPicture(this.decoder, this.string, {ColorFilter? colorFilter}) + StringPicture(this.decoderBuilder, this.string, {ColorFilter? colorFilter}) : assert(string != null), // ignore: unnecessary_null_comparison + decoder = decoderBuilder(null), super(colorFilter); + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + /// The [PictureInfoDecoder] to use for decoding this picture. - final PictureInfoDecoder decoder; + @visibleForTesting + PictureInfoDecoder decoder; /// The string to decode into a picture. final String string; + @override + set currentColor(Color? color) { + _currentColor = color; + decoder = decoderBuilder(_currentColor); + } + @override Future obtainKey(PictureConfiguration picture) { return SynchronousFuture(this); @@ -850,14 +920,14 @@ class ExactAssetPicture extends AssetBundlePictureProvider { /// The [package] argument must be non-null when fetching an asset that is /// included in a package. See the documentation for the [ExactAssetPicture] class /// itself for details. - const ExactAssetPicture( - PictureInfoDecoder decoder, + ExactAssetPicture( + PictureInfoDecoderBuilder decoderBuilder, this.assetName, { this.bundle, this.package, ColorFilter? colorFilter, }) : assert(assetName != null), // ignore: unnecessary_null_comparison - super(decoder, colorFilter); + super(decoderBuilder, colorFilter); /// The name of the asset. final String assetName; diff --git a/lib/src/svg/default_theme.dart b/lib/src/svg/default_theme.dart new file mode 100644 index 00000000..e85cca7e --- /dev/null +++ b/lib/src/svg/default_theme.dart @@ -0,0 +1,41 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; + +/// The SVG theme to apply to descendant [SvgPicture] widgets +/// which don't have explicit theme values. +class DefaultSvgTheme extends InheritedTheme { + /// Creates a default SVG theme for the given subtree + /// using the provided [theme]. + const DefaultSvgTheme({ + Key? key, + required Widget child, + required this.theme, + }) : super(key: key, child: child); + + /// The SVG theme to apply. + final SvgTheme theme; + + /// The closest instance of this class that encloses the given context. + /// + /// Typical usage is as follows: + /// + /// ```dart + /// DefaultSvgTheme theme = DefaultSvgTheme.of(context); + /// ``` + static DefaultSvgTheme? of(BuildContext context) { + return context.dependOnInheritedWidgetOfExactType(); + } + + @override + bool updateShouldNotify(DefaultSvgTheme oldWidget) { + return theme != oldWidget.theme; + } + + @override + Widget wrap(BuildContext context, Widget child) { + return DefaultSvgTheme( + theme: theme, + child: child, + ); + } +} diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index d7aa1f05..a2514352 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -6,6 +6,7 @@ import 'package:path_drawing/path_drawing.dart'; import 'package:vector_math/vector_math_64.dart'; import 'package:xml/xml_events.dart' hide parseEvents; +import '../svg/theme.dart'; import '../utilities/errors.dart'; import '../utilities/numbers.dart'; import '../utilities/xml.dart'; @@ -83,6 +84,12 @@ class _Elements { final DrawableViewport? viewBox = parseViewBox(parserState.attributes); final String? id = parserState.attribute('id', def: ''); + final Color? color = + parseColor(parserState.attribute('color', def: null)) ?? + // Fallback to the currentColor from theme if no color is defined + // on the root SVG element. + parserState.theme?.currentColor; + // TODO(dnfield): Support nested SVG elements. https://github.com/dnfield/flutter_svg/issues/132 if (parserState._root != null) { const String errorMessage = 'Unsupported nested element.'; @@ -102,6 +109,7 @@ class _Elements { library: 'SVG', context: ErrorDescription('in _Element.svg'), )); + parserState._parentDrawables.addLast( _SvgGroupTuple( 'svg', @@ -114,7 +122,9 @@ class _Elements { parserState._definitions, viewBox!.viewBoxRect, null, + currentColor: color, ), + color: color, ), ), ); @@ -131,7 +141,9 @@ class _Elements { parserState._definitions, viewBox.viewBoxRect, null, + currentColor: color, ), + color: color, ); parserState.addGroup(parserState._currentStartElement!, parserState._root); return null; @@ -139,6 +151,9 @@ class _Elements { static Future? g(SvgParserState parserState, bool warningsAsErrors) { final DrawableParent parent = parserState.currentGroup!; + final Color? color = + parseColor(parserState.attribute('color', def: null)) ?? parent.color; + final DrawableGroup group = DrawableGroup( parserState.attribute('id', def: ''), [], @@ -148,8 +163,10 @@ class _Elements { parserState._definitions, parserState.rootBounds, parent.style, + currentColor: color, ), transform: parseTransform(parserState.attribute('transform'))?.storage, + color: color, ); if (!parserState._inDefs) { parent.children!.add(group); @@ -161,6 +178,9 @@ class _Elements { static Future? symbol( SvgParserState parserState, bool warningsAsErrors) { final DrawableParent parent = parserState.currentGroup!; + final Color? color = + parseColor(parserState.attribute('color', def: null)) ?? parent.color; + final DrawableGroup group = DrawableGroup( parserState.attribute('id', def: ''), [], @@ -170,8 +190,10 @@ class _Elements { parserState._definitions, null, parent.style, + currentColor: color, ), transform: parseTransform(parserState.attribute('transform'))?.storage, + color: color, ); parserState.addGroup(parserState._currentStartElement!, group); return null; @@ -190,6 +212,7 @@ class _Elements { parserState._definitions, parserState.rootBounds, parent!.style, + currentColor: parent.color, ); final Matrix4 transform = @@ -221,6 +244,8 @@ class _Elements { List colors, List offsets, ) { + final DrawableParent parent = parserState.currentGroup!; + for (XmlEvent event in parserState._readSubtree()) { if (event is XmlEndElementEvent) { continue; @@ -233,6 +258,7 @@ class _Elements { ); final Color stopColor = parseColor(getAttribute(parserState.attributes, 'stop-color')) ?? + parent.color ?? colorBlack; colors.add(stopColor.withOpacity(parseDouble(rawOpacity)!)); @@ -529,6 +555,7 @@ class _Elements { parserState._definitions, parserState.rootBounds, parentStyle, + currentColor: parent.color, ), size: size, transform: parseTransform(parserState.attribute('transform'))?.storage, @@ -731,11 +758,19 @@ class _SvgGroupTuple { /// Maintains state while pushing an [XmlPushReader] through the SVG tree. class SvgParserState { /// Creates a new [SvgParserState]. - SvgParserState(Iterable events, this._key, this._warningsAsErrors) - // ignore: unnecessary_null_comparison - : assert(events != null), + SvgParserState( + Iterable events, + this.theme, + this._key, + this._warningsAsErrors, + ) + // ignore: unnecessary_null_comparison + : assert(events != null), _eventIterator = events.iterator; + /// A theme used when parsing SVG elements. + final SvgTheme? theme; + final Iterator _eventIterator; final String? _key; final bool _warningsAsErrors; @@ -893,6 +928,7 @@ class SvgParserState { path.getBounds(), parentStyle, defaultFillColor: colorBlack, + currentColor: parent.color, ), transform: parseTransform(getAttribute(attributes, 'transform'))?.storage, ); diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart new file mode 100644 index 00000000..ed206005 --- /dev/null +++ b/lib/src/svg/theme.dart @@ -0,0 +1,24 @@ +import 'dart:ui'; + +/// A theme used when decoding an SVG picture. +class SvgTheme { + /// Instantiates an SVG theme with the [currentColor]. + const SvgTheme({ + this.currentColor, + }); + + /// The default color applied to SVG elements that inherit the color property. + /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword + final Color? currentColor; + + @override + bool operator ==(dynamic other) { + if (other.runtimeType != runtimeType) { + return false; + } + return other is SvgTheme && currentColor == other.currentColor; + } + + @override + int get hashCode => currentColor.hashCode; +} diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index fff792da..d46d987b 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -178,6 +178,7 @@ DrawablePaint? parseStroke( Rect? bounds, DrawableDefinitionServer definitions, DrawablePaint? parentStroke, + Color? currentColor, ) { final String rawStroke = getAttribute(attributes, 'stroke')!; final String? rawStrokeOpacity = getAttribute( @@ -217,7 +218,10 @@ DrawablePaint? parseStroke( PaintingStyle.stroke, color: rawStroke == '' ? (parentStroke?.color ?? colorBlack).withOpacity(opacity) - : (parseColor(rawStroke) ?? parentStroke?.color ?? colorBlack) + : (parseColor(rawStroke) ?? + currentColor ?? + parentStroke?.color ?? + colorBlack) .withOpacity(opacity), strokeCap: rawStrokeCap == 'null' ? parentStroke?.strokeCap ?? StrokeCap.butt @@ -249,6 +253,7 @@ DrawablePaint? parseFill( DrawableDefinitionServer definitions, DrawablePaint? parentFill, Color? defaultFillColor, + Color? currentColor, ) { final String rawFill = getAttribute(el, 'fill')!; final String? rawFillOpacity = getAttribute(el, 'fill-opacity', def: '1.0'); @@ -284,6 +289,7 @@ DrawablePaint? parseFill( opacity, rawOpacity != '' || rawFillOpacity != '', defaultFillColor, + currentColor, ), ); } @@ -294,9 +300,13 @@ Color? _determineFillColor( double opacity, bool explicitOpacity, Color? defaultFillColor, + Color? currentColor, ) { - final Color? color = - parseColor(rawFill) ?? parentFillColor ?? defaultFillColor; + final Color? color = parseColor(rawFill) ?? + currentColor ?? + parentFillColor ?? + defaultFillColor; + if (explicitOpacity && color != null) { return color.withOpacity(opacity); } @@ -465,6 +475,7 @@ DrawableStyle parseStyle( Rect? bounds, DrawableStyle? parentStyle, { Color? defaultFillColor, + Color? currentColor, }) { return DrawableStyle.mergeAndBlend( parentStyle, @@ -474,6 +485,7 @@ DrawableStyle parseStyle( bounds, definitions, parentStyle?.stroke, + currentColor, ), dashArray: parseDashArray(attributes), dashOffset: parseDashOffset(attributes), @@ -484,6 +496,7 @@ DrawableStyle parseStyle( definitions, parentStyle?.fill, defaultFillColor, + currentColor, ), pathFillType: parseFillRule( attributes, diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 59f27853..bb9faf74 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -55,6 +55,12 @@ abstract class DrawableParent implements DrawableStyleable { /// /// Each child may itself have children. List? get children; + + /// The default color used to provide a potential indirect color value + /// for the `fill`, `stroke` and `stop-color` of descendant elements. + /// + /// See: https://www.w3.org/TR/SVG11/color.html#ColorProperty + Color? get color; } /// Styling information for vector drawing. @@ -840,6 +846,7 @@ class DrawableRoot implements DrawableParent { this.definitions, this.style, { this.transform, + this.color, }); /// The expected coordinates used by child paths for drawing. @@ -851,6 +858,9 @@ class DrawableRoot implements DrawableParent { @override final Float64List? transform; + @override + final Color? color; + @override final List children; @@ -986,7 +996,13 @@ class DrawableRoot implements DrawableParent { /// `stroke`, or `fill`. class DrawableGroup implements DrawableStyleable, DrawableParent { /// Creates a new DrawableGroup. - const DrawableGroup(this.id, this.children, this.style, {this.transform}); + const DrawableGroup( + this.id, + this.children, + this.style, { + this.transform, + this.color, + }); @override final String? id; @@ -997,6 +1013,8 @@ class DrawableGroup implements DrawableStyleable, DrawableParent { final DrawableStyle? style; @override final Float64List? transform; + @override + final Color? color; @override bool get hasDrawableContent => children != null && children!.isNotEmpty; diff --git a/lib/svg.dart b/lib/svg.dart index 7a7faca4..bbc51d9c 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -8,11 +8,13 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart' show AssetBundle; import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/src/svg/default_theme.dart'; import 'parser.dart'; import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; import 'src/render_picture.dart'; +import 'src/svg/theme.dart'; import 'src/unbounded_color_filtered.dart'; import 'src/vector_drawable.dart'; @@ -48,9 +50,10 @@ class Svg { Uint8List raw, bool allowDrawingOutsideOfViewBox, ColorFilter? colorFilter, + SvgTheme theme, String key, ) async { - final DrawableRoot svgRoot = await fromSvgBytes(raw, key); + final DrawableRoot svgRoot = await fromSvgBytes(raw, theme, key); final Picture pic = svgRoot.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter, @@ -73,11 +76,13 @@ class Svg { /// /// The [key] will be used for debugging purposes. Future svgPictureStringDecoder( - String raw, - bool allowDrawingOutsideOfViewBox, - ColorFilter? colorFilter, - String key) async { - final DrawableRoot svg = await fromSvgString(raw, key); + String raw, + bool allowDrawingOutsideOfViewBox, + ColorFilter? colorFilter, + SvgTheme theme, + String key, + ) async { + final DrawableRoot svg = await fromSvgString(raw, theme, key); return PictureInfo( picture: svg.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, @@ -93,13 +98,17 @@ class Svg { /// UTF8 encoding). /// /// The `key` will be used for debugging purposes. - Future fromSvgBytes(Uint8List raw, String key) async { + Future fromSvgBytes( + Uint8List raw, + SvgTheme theme, + String key, + ) async { // TODO(dnfield): do utf decoding in another thread? // Might just have to live with potentially slow(ish) decoding, this is causing errors. // See: https://github.com/dart-lang/sdk/issues/31954 // See: https://github.com/flutter/flutter/blob/bf3bd7667f07709d0b817ebfcb6972782cfef637/packages/flutter/lib/src/services/asset_bundle.dart#L66 // if (raw.lengthInBytes < 20 * 1024) { - return fromSvgString(utf8.decode(raw), key); + return fromSvgString(utf8.decode(raw), theme, key); // } else { // final String str = // await compute(_utf8Decode, raw, debugLabel: 'UTF8 decode for SVG'); @@ -114,9 +123,13 @@ class Svg { /// Creates a [DrawableRoot] from a string of SVG data. /// /// The `key` is used for debugging purposes. - Future fromSvgString(String rawSvg, String key) async { + Future fromSvgString( + String rawSvg, + SvgTheme theme, + String key, + ) async { final SvgParser parser = SvgParser(); - return await parser.parse(rawSvg, key: key); + return await parser.parse(rawSvg, theme: theme, key: key); } } @@ -186,45 +199,6 @@ Future precachePicture( /// filtering used into the key (meaning the same SVG with two different `color` /// arguments applied would be two cache entries). class SvgPicture extends StatefulWidget { - /// Instantiates a widget that renders an SVG picture using the `pictureProvider`. - /// - /// Either the [width] and [height] arguments should be specified, or the - /// widget should be placed in a context that sets tight layout constraints. - /// Otherwise, the image dimensions will change as the image is loaded, which - /// will result in ugly layout changes. - /// - /// If `matchTextDirection` is set to true, the picture will be flipped - /// horizontally in [TextDirection.rtl] contexts. - /// - /// The `allowDrawingOutsideOfViewBox` parameter should be used with caution - - /// if set to true, it will not clip the canvas used internally to the view box, - /// meaning the picture may draw beyond the intended area and lead to undefined - /// behavior or additional memory overhead. - /// - /// A custom `placeholderBuilder` can be specified for cases where decoding or - /// acquiring data may take a noticeably long time, e.g. for a network picture. - /// - /// The `semanticsLabel` can be used to identify the purpose of this picture for - /// screen reading software. - /// - /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. - const SvgPicture( - this.pictureProvider, { - Key? key, - this.width, - this.height, - this.fit = BoxFit.contain, - this.alignment = Alignment.center, - this.matchTextDirection = false, - this.allowDrawingOutsideViewBox = false, - this.placeholderBuilder, - this.semanticsLabel, - this.excludeFromSemantics = false, - this.clipBehavior = Clip.hardEdge, - this.colorFilter, - this.cacheColorFilter = false, - }) : super(key: key); - /// Instantiates a widget that renders an SVG picture from an [AssetBundle]. /// /// The key will be derived from the `assetName`, `package`, and `bundle` @@ -251,6 +225,9 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// + /// The `currentColor` argument, if provided, will override the default color + /// of any SVG element that inherits its color. + /// /// ## Assets in packages /// /// To create the widget with an asset from a package, the [package] argument @@ -320,10 +297,11 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, + this.currentColor, }) : pictureProvider = ExactAssetPicture( allowDrawingOutsideViewBox == true - ? svgStringDecoderOutsideViewBox - : svgStringDecoder, + ? svgStringDecoderOutsideViewBoxBuilder + : svgStringDecoderBuilder, assetName, bundle: bundle, package: package, @@ -357,6 +335,9 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// + /// The `currentColor` argument, if provided, will override the default color + /// of any SVG element that inherits its color. + /// /// All network images are cached regardless of HTTP headers. /// /// An optional `headers` argument can be used to send custom HTTP headers @@ -380,10 +361,11 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, + this.currentColor, }) : pictureProvider = NetworkPicture( allowDrawingOutsideViewBox == true - ? svgByteDecoderOutsideViewBox - : svgByteDecoder, + ? svgByteDecoderOutsideViewBoxBuilder + : svgByteDecoderBuilder, url, headers: headers, colorFilter: svg.cacheColorFilterOverride ?? cacheColorFilter @@ -416,6 +398,9 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// + /// The `currentColor` argument, if provided, will override the default color + /// of any SVG element that inherits its color. + /// /// On Android, this may require the /// `android.permission.READ_EXTERNAL_STORAGE` permission. /// @@ -436,10 +421,11 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, + this.currentColor, }) : pictureProvider = FilePicture( allowDrawingOutsideViewBox == true - ? svgByteDecoderOutsideViewBox - : svgByteDecoder, + ? svgByteDecoderOutsideViewBoxBuilder + : svgByteDecoderBuilder, file, colorFilter: svg.cacheColorFilterOverride ?? cacheColorFilter ? _getColorFilter(color, colorBlendMode) @@ -471,6 +457,9 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// + /// The `currentColor` argument, if provided, will override the default color + /// of any SVG element that inherits its color. + /// /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. SvgPicture.memory( Uint8List bytes, { @@ -488,10 +477,11 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, + this.currentColor, }) : pictureProvider = MemoryPicture( allowDrawingOutsideViewBox == true - ? svgByteDecoderOutsideViewBox - : svgByteDecoder, + ? svgByteDecoderOutsideViewBoxBuilder + : svgByteDecoderBuilder, bytes, colorFilter: svg.cacheColorFilterOverride ?? cacheColorFilter ? _getColorFilter(color, colorBlendMode) @@ -523,9 +513,12 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// + /// The `currentColor` argument, if provided, will override the default color + /// of any SVG element that inherits its color. + /// /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. SvgPicture.string( - String bytes, { + String string, { Key? key, this.width, this.height, @@ -540,11 +533,12 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, + this.currentColor, }) : pictureProvider = StringPicture( allowDrawingOutsideViewBox == true - ? svgStringDecoderOutsideViewBox - : svgStringDecoder, - bytes, + ? svgStringDecoderOutsideViewBoxBuilder + : svgStringDecoderBuilder, + string, colorFilter: svg.cacheColorFilterOverride ?? cacheColorFilter ? _getColorFilter(color, colorBlendMode) : null, @@ -560,25 +554,53 @@ class SvgPicture extends StatefulWidget { static ColorFilter? _getColorFilter(Color? color, BlendMode colorBlendMode) => color == null ? null : ColorFilter.mode(color, colorBlendMode); - /// A [PictureInfoDecoder] for [Uint8List]s that will clip to the viewBox. - static final PictureInfoDecoder svgByteDecoder = - (Uint8List bytes, ColorFilter? colorFilter, String key) => - svg.svgPictureDecoder(bytes, false, colorFilter, key); - - /// A [PictureInfoDecoder] for strings that will clip to the viewBox. - static final PictureInfoDecoder svgStringDecoder = - (String data, ColorFilter? colorFilter, String key) => - svg.svgPictureStringDecoder(data, false, colorFilter, key); - - /// A [PictureInfoDecoder] for [Uint8List]s that will not clip to the viewBox. - static final PictureInfoDecoder svgByteDecoderOutsideViewBox = - (Uint8List bytes, ColorFilter? colorFilter, String key) => - svg.svgPictureDecoder(bytes, true, colorFilter, key); - - /// A [PictureInfoDecoder] for [String]s that will not clip to the viewBox. - static final PictureInfoDecoder svgStringDecoderOutsideViewBox = - (String data, ColorFilter? colorFilter, String key) => - svg.svgPictureStringDecoder(data, true, colorFilter, key); + /// A [PictureInfoDecoderBuilder] for [Uint8List]s that will clip to the viewBox. + static final PictureInfoDecoderBuilder svgByteDecoderBuilder = + (Color? currentColor) => + (Uint8List bytes, ColorFilter? colorFilter, String key) => + svg.svgPictureDecoder( + bytes, + false, + colorFilter, + SvgTheme(currentColor: currentColor), + key, + ); + + /// A [PictureInfoDecoderBuilder] for strings that will clip to the viewBox. + static final PictureInfoDecoderBuilder svgStringDecoderBuilder = + (Color? currentColor) => + (String data, ColorFilter? colorFilter, String key) => + svg.svgPictureStringDecoder( + data, + false, + colorFilter, + SvgTheme(currentColor: currentColor), + key, + ); + + /// A [PictureInfoDecoderBuilder] for [Uint8List]s that will not clip to the viewBox. + static final PictureInfoDecoderBuilder + svgByteDecoderOutsideViewBoxBuilder = (Color? currentColor) => + (Uint8List bytes, ColorFilter? colorFilter, String key) => + svg.svgPictureDecoder( + bytes, + true, + colorFilter, + SvgTheme(currentColor: currentColor), + key, + ); + + /// A [PictureInfoDecoderBuilder] for [String]s that will not clip to the viewBox. + static final PictureInfoDecoderBuilder + svgStringDecoderOutsideViewBoxBuilder = (Color? currentColor) => + (String data, ColorFilter? colorFilter, String key) => + svg.svgPictureStringDecoder( + data, + true, + colorFilter, + SvgTheme(currentColor: currentColor), + key, + ); /// If specified, the width to use for the SVG. If unspecified, the SVG /// will take the width of its parent. @@ -664,6 +686,10 @@ class SvgPicture extends StatefulWidget { /// This defaults to false and must not be null. final bool cacheColorFilter; + /// The default color applied to SVG elements that inherit the color property. + /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword + final Color? currentColor; + @override State createState() => _SvgPictureState(); } @@ -675,6 +701,7 @@ class _SvgPictureState extends State { @override void didChangeDependencies() { + _updatePictureProvider(); _resolveImage(); if (TickerMode.of(context)) { @@ -689,16 +716,26 @@ class _SvgPictureState extends State { void didUpdateWidget(SvgPicture oldWidget) { super.didUpdateWidget(oldWidget); if (widget.pictureProvider != oldWidget.pictureProvider) { + _updatePictureProvider(); _resolveImage(); } } @override void reassemble() { + _updatePictureProvider(); _resolveImage(); // in case the image cache was flushed super.reassemble(); } + /// Updates the `currentColor` of the picture provider based on either + /// the widget's `currentColor` property or [DefaultSvgTheme]. + void _updatePictureProvider() { + final SvgTheme? svgTheme = DefaultSvgTheme.of(context)?.theme; + final Color? currentColor = widget.currentColor ?? svgTheme?.currentColor; + widget.pictureProvider.currentColor = currentColor; + } + void _resolveImage() { final PictureStream newStream = widget.pictureProvider .resolve(createLocalPictureConfiguration(context)); diff --git a/pubspec.yaml b/pubspec.yaml index 153f7a90..87ac0858 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + mocktail: ^0.1.4 path: ^1.8.0 test: ^1.16.0 diff --git a/test/default_theme_test.dart b/test/default_theme_test.dart new file mode 100644 index 00000000..b5cd4fc6 --- /dev/null +++ b/test/default_theme_test.dart @@ -0,0 +1,79 @@ +// ignore_for_file: prefer_const_constructors + +import 'dart:ui'; + +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/src/svg/default_theme.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('DefaultSvgTheme', () { + testWidgets('changes propagate to SvgPicture', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + currentColor: Color(0xFF733821), + ); + + final SvgPicture svgPictureWidget = SvgPicture.string(''' + + +'''); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.currentColor, + equals(svgTheme.currentColor), + ); + + const SvgTheme anotherSvgTheme = SvgTheme( + currentColor: Color(0xFF05290E), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: anotherSvgTheme, + child: svgPictureWidget, + )); + + svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.currentColor, + equals(anotherSvgTheme.currentColor), + ); + }); + + testWidgets( + 'currentColor widget property takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + currentColor: Color(0xFF733821), + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + currentColor: Color(0xFF05290E), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.currentColor, + equals(Color(0xFF05290E)), + ); + }); + }); +} diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index 2876fb38..89542ced 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -75,7 +75,7 @@ void main() { expect(PictureProvider.cache.count, 0); await precachePicture( StringPicture( - SvgPicture.svgStringDecoder, + SvgPicture.svgStringDecoderBuilder, svgString, ), tester.element(find.text('test_text')), @@ -110,7 +110,7 @@ void main() { expect(PictureProvider.cache.count, 0); await precachePicture( StringPicture( - SvgPicture.svgStringDecoder, + SvgPicture.svgStringDecoderBuilder, svgString, ), null, @@ -135,7 +135,7 @@ void main() { await precachePicture( StringPicture( - SvgPicture.svgStringDecoder, + SvgPicture.svgStringDecoderBuilder, svgString, ), tester.element(find.text('test_text')), diff --git a/test/picture_provider_test.dart b/test/picture_provider_test.dart new file mode 100644 index 00000000..01e4a5c8 --- /dev/null +++ b/test/picture_provider_test.dart @@ -0,0 +1,146 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +class MockPictureInfo extends Mock implements PictureInfo {} + +class MockFile extends Mock implements File {} + +void main() { + group('PictureProvider', () { + Color? currentColor; + + PictureInfoDecoder decoderBuilder(Color? color) { + currentColor = color; + return (T bytes, ColorFilter? colorFilter, String key) async => + MockPictureInfo(); + } + + test( + 'NetworkPicture rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () async { + const Color color = Color(0xFFB0E3BE); + final NetworkPicture networkPicture = + NetworkPicture(decoderBuilder, 'url'); + + final PictureInfoDecoder decoder = networkPicture.decoder; + + expect(decoder, isNotNull); + + // Update the currentColor of PictureProvider. + networkPicture.currentColor = color; + + expect( + decoder, + isNot(equals(networkPicture.decoder)), + ); + + expect( + currentColor, + equals(color), + ); + }); + + test( + 'FilePicture rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () async { + const Color color = Color(0xFFB0E3BE); + final FilePicture filePicture = FilePicture(decoderBuilder, MockFile()); + + final PictureInfoDecoder decoder = filePicture.decoder; + + expect(decoder, isNotNull); + + // Update the currentColor of PictureProvider. + filePicture.currentColor = color; + + expect( + decoder, + isNot(equals(filePicture.decoder)), + ); + + expect( + currentColor, + equals(color), + ); + }); + + test( + 'MemoryPicture rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () async { + const Color color = Color(0xFFB0E3BE); + final MemoryPicture memoryPicture = + MemoryPicture(decoderBuilder, Uint8List(0)); + + final PictureInfoDecoder decoder = memoryPicture.decoder; + + expect(decoder, isNotNull); + + // Update the currentColor of PictureProvider. + memoryPicture.currentColor = color; + + expect( + decoder, + isNot(equals(memoryPicture.decoder)), + ); + + expect( + currentColor, + equals(color), + ); + }); + + test( + 'StringPicture rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () async { + const Color color = Color(0xFFB0E3BE); + final StringPicture stringPicture = StringPicture(decoderBuilder, ''); + + final PictureInfoDecoder decoder = stringPicture.decoder; + + expect(decoder, isNotNull); + + // Update the currentColor of PictureProvider. + stringPicture.currentColor = color; + + expect( + decoder, + isNot(equals(stringPicture.decoder)), + ); + + expect( + currentColor, + equals(color), + ); + }); + + test( + 'ExactAssetPicture rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () async { + const Color color = Color(0xFFB0E3BE); + final ExactAssetPicture exactAssetPicture = + ExactAssetPicture(decoderBuilder, ''); + + final PictureInfoDecoder decoder = exactAssetPicture.decoder; + + expect(decoder, isNotNull); + + // Update the currentColor of PictureProvider. + exactAssetPicture.currentColor = color; + + expect( + decoder, + isNot(equals(exactAssetPicture.decoder)), + ); + + expect( + currentColor, + equals(color), + ); + }); + }); +} diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index a6f1e5ba..60614f43 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -1,7 +1,8 @@ -import 'dart:ui' show PathFillType; +import 'dart:ui' show Color, PathFillType; import 'package:flutter_svg/parser.dart'; import 'package:flutter_svg/src/svg/parsers.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_svg/src/vector_drawable.dart'; import 'package:test/test.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -273,4 +274,286 @@ void main() { // Empty text elements get removed expect(find(root, 'remove-space') != null, false); }); + + group('currentColor', () { + group('stroke', () { + test( + 'respects currentColor from SvgTheme ' + 'when no color attribute exists on the parent', () async { + const String svgStr = ''' + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.stroke?.color, + equals(currentColor), + ); + }); + + test( + 'respects currentColor from SvgTheme ' + 'when the parent uses currentColor', () async { + const String svgStr = ''' + + + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.stroke?.color, + equals(currentColor), + ); + }); + + test( + 'respects currentColor from the parent ' + 'when the parent overrides currentColor', () async { + const String svgStr = ''' + + + + +'''; + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.stroke?.color, + equals(const Color(0xffC460B7)), + ); + }); + }); + + group('fill', () { + test( + 'respects currentColor from SvgTheme ' + 'when no color attribute exists on the parent', () async { + const String svgStr = ''' + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.fill?.color, + equals(currentColor), + ); + }); + + test( + 'respects currentColor from SvgTheme ' + 'when the parent uses currentColor', () async { + const String svgStr = ''' + + + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.fill?.color, + equals(currentColor), + ); + }); + + test( + 'respects currentColor from the parent ' + 'when the parent overrides currentColor', () async { + const String svgStr = ''' + + + + +'''; + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + ); + + final DrawableShape? circle = find(root, 'circle'); + + expect(circle, isNotNull); + + expect( + circle!.style.fill?.color, + equals(const Color(0xFFC460B7)), + ); + }); + }); + + group('stop-color', () { + test( + 'respects currentColor from SvgTheme ' + 'when no color attribute exists on the parent', () async { + const String svgStr = ''' + + + + + + + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableLinearGradient? gradient = + root.definitions.getGradient('url(#gradient-1)'); + + expect(gradient, isNotNull); + + expect( + gradient!.colors?[0], + equals(currentColor.withOpacity(0.5)), + ); + + expect( + gradient.colors?[1], + equals(currentColor.withOpacity(0.8)), + ); + }); + + test( + 'respects currentColor from SvgTheme ' + 'when the parent uses currentColor', () async { + const String svgStr = ''' + + + + + + + + +'''; + + const Color currentColor = Color(0xFFB0E3BE); + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: currentColor), + ); + + final DrawableLinearGradient? gradient = + root.definitions.getGradient('url(#gradient-1)'); + + expect(gradient, isNotNull); + + expect( + gradient!.colors?[0], + equals(currentColor.withOpacity(0.5)), + ); + + expect( + gradient.colors?[1], + equals(currentColor.withOpacity(0.8)), + ); + }); + + test( + 'respects currentColor from the parent ' + 'when the parent overrides currentColor', () async { + const String svgStr = ''' + + + + + + + + + + +'''; + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + ); + + final DrawableLinearGradient? gradient = + root.definitions.getGradient('url(#gradient-1)'); + + expect(gradient, isNotNull); + + expect( + gradient!.colors?[0], + equals(const Color(0xFFC460B7).withOpacity(0.5)), + ); + + expect( + gradient.colors?[1], + equals(const Color(0xFFC460B7).withOpacity(0.8)), + ); + }); + }); + }); } diff --git a/test/theme_test.dart b/test/theme_test.dart new file mode 100644 index 00000000..af2d270f --- /dev/null +++ b/test/theme_test.dart @@ -0,0 +1,33 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; +import 'package:test/test.dart'; + +void main() { + group('SvgTheme', () { + group('constructor', () { + test('sets currentColor', () { + const Color currentColor = Color(0xFFB0E3BE); + + expect( + SvgTheme(currentColor: currentColor).currentColor, + equals(currentColor), + ); + }); + }); + + test('supports value equality', () { + expect( + SvgTheme( + currentColor: Color(0xFF6F2173), + ), + equals( + SvgTheme( + currentColor: Color(0xFF6F2173), + ), + ), + ); + }); + }); +} diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index b2c2dcfd..8aa45d5d 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -34,6 +35,7 @@ void main() { ''', false, const ColorFilter.mode(Color(0xFF00FF00), BlendMode.color), + const SvgTheme(), 'test', ); final Image image = await info.picture.toImage(2, 2); diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index ed89f9fe..0fbc5f7c 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_svg/src/unbounded_color_filtered.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -566,6 +567,7 @@ void main() { (WidgetTester tester) async { await svg.fromSvgString( '', + const SvgTheme(), 'test'); final UnsupportedError error = tester.takeException() as UnsupportedError; expect(error.message, 'Unsupported nested element.'); diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index 0243aaab..46001688 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/svg/xml_parsers.dart'; import 'package:flutter_svg/src/utilities/xml.dart'; import 'package:test/test.dart'; @@ -197,4 +198,42 @@ void main() { expect(parseTextDecorationStyle(null), isNull); expect(() => parseTextDecorationStyle('invalid'), throwsUnsupportedError); }); + + group('parseStyle', () { + test('uses currentColor for stroke color', () { + const Color currentColor = Color(0xFFB0E3BE); + final XmlStartElementEvent svg = + parseEvents('').first + as XmlStartElementEvent; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + currentColor: currentColor, + ); + + expect(svgStyle.stroke?.color, equals(currentColor)); + }); + + test('uses currentColor for fill color', () { + const Color currentColor = Color(0xFFB0E3BE); + final XmlStartElementEvent svg = + parseEvents('').first + as XmlStartElementEvent; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + currentColor: currentColor, + ); + + expect(svgStyle.fill?.color, equals(currentColor)); + }); + }); } diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index afb04a1d..c9fd1d9b 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -9,6 +9,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_svg/src/vector_drawable.dart'; import 'package:flutter_svg/svg.dart'; import 'package:path/path.dart' as path; @@ -20,7 +21,7 @@ Future getSvgImage(String svgData) async { const Size size = Size(200.0, 200.0); final DrawableRoot svgRoot = - await svg.fromSvgString(svgData, 'GenGoldenTest'); + await svg.fromSvgString(svgData, const SvgTheme(), 'GenGoldenTest'); svgRoot.scaleCanvasToViewBox(canvas, size); svgRoot.clipCanvasToViewBox(canvas); From 1d632866c8111ebfdad7910429e646243a71ca46 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 8 Oct 2021 16:15:54 -0700 Subject: [PATCH 024/142] Update flutter_svg.dart --- lib/flutter_svg.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/flutter_svg.dart b/lib/flutter_svg.dart index f1171ffa..338ad186 100644 --- a/lib/flutter_svg.dart +++ b/lib/flutter_svg.dart @@ -1,4 +1,6 @@ export 'src/picture_provider.dart'; export 'src/picture_stream.dart'; +export 'src/svg/default_theme.dart'; +export 'src/svg/theme.dart'; export 'src/vector_drawable.dart'; export 'svg.dart'; From d4a001f30f0a050d3766a983511b1f2500815870 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 11 Oct 2021 11:56:39 -0700 Subject: [PATCH 025/142] Make the SvgTheme change less breaking (#606) --- .../flutter/generated_plugin_registrant.cc | 2 + .../flutter/generated_plugin_registrant.h | 2 + .../flutter/generated_plugin_registrant.cc | 2 + .../flutter/generated_plugin_registrant.h | 2 + lib/avd.dart | 1 - lib/svg.dart | 79 ++++++++++++++----- test/default_theme_test.dart | 2 - test/vector_drawable_test.dart | 3 +- test/widget_svg_test.dart | 9 +-- tool/gen_golden.dart | 3 +- 10 files changed, 73 insertions(+), 32 deletions(-) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index d38195aa..e71a16d2 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h index 9bf74789..e0f0a47b 100644 --- a/example/linux/flutter/generated_plugin_registrant.h +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc index 4bfa0f3a..8b6d4680 100644 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h index 9846246b..dc139d85 100644 --- a/example/windows/flutter/generated_plugin_registrant.h +++ b/example/windows/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/lib/avd.dart b/lib/avd.dart index fff441d8..d997667d 100644 --- a/lib/avd.dart +++ b/lib/avd.dart @@ -3,7 +3,6 @@ import 'dart:typed_data'; import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart' show AssetBundle; import 'package:flutter/widgets.dart'; import 'package:xml/xml.dart'; diff --git a/lib/svg.dart b/lib/svg.dart index bbc51d9c..729deb42 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -6,7 +6,6 @@ import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart' show AssetBundle; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/src/svg/default_theme.dart'; @@ -50,10 +49,10 @@ class Svg { Uint8List raw, bool allowDrawingOutsideOfViewBox, ColorFilter? colorFilter, - SvgTheme theme, - String key, - ) async { - final DrawableRoot svgRoot = await fromSvgBytes(raw, theme, key); + String key, { + SvgTheme theme = const SvgTheme(), + }) async { + final DrawableRoot svgRoot = await fromSvgBytes(raw, key, theme: theme); final Picture pic = svgRoot.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter, @@ -79,10 +78,10 @@ class Svg { String raw, bool allowDrawingOutsideOfViewBox, ColorFilter? colorFilter, - SvgTheme theme, - String key, - ) async { - final DrawableRoot svg = await fromSvgString(raw, theme, key); + String key, { + SvgTheme theme = const SvgTheme(), + }) async { + final DrawableRoot svg = await fromSvgString(raw, key, theme: theme); return PictureInfo( picture: svg.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, @@ -100,15 +99,15 @@ class Svg { /// The `key` will be used for debugging purposes. Future fromSvgBytes( Uint8List raw, - SvgTheme theme, - String key, - ) async { + String key, { + SvgTheme theme = const SvgTheme(), + }) async { // TODO(dnfield): do utf decoding in another thread? // Might just have to live with potentially slow(ish) decoding, this is causing errors. // See: https://github.com/dart-lang/sdk/issues/31954 // See: https://github.com/flutter/flutter/blob/bf3bd7667f07709d0b817ebfcb6972782cfef637/packages/flutter/lib/src/services/asset_bundle.dart#L66 // if (raw.lengthInBytes < 20 * 1024) { - return fromSvgString(utf8.decode(raw), theme, key); + return fromSvgString(utf8.decode(raw), key, theme: theme); // } else { // final String str = // await compute(_utf8Decode, raw, debugLabel: 'UTF8 decode for SVG'); @@ -125,9 +124,9 @@ class Svg { /// The `key` is used for debugging purposes. Future fromSvgString( String rawSvg, - SvgTheme theme, - String key, - ) async { + String key, { + SvgTheme theme = const SvgTheme(), + }) async { final SvgParser parser = SvgParser(); return await parser.parse(rawSvg, theme: theme, key: key); } @@ -199,6 +198,46 @@ Future precachePicture( /// filtering used into the key (meaning the same SVG with two different `color` /// arguments applied would be two cache entries). class SvgPicture extends StatefulWidget { + /// Instantiates a widget that renders an SVG picture using the `pictureProvider`. + /// + /// Either the [width] and [height] arguments should be specified, or the + /// widget should be placed in a context that sets tight layout constraints. + /// Otherwise, the image dimensions will change as the image is loaded, which + /// will result in ugly layout changes. + /// + /// If `matchTextDirection` is set to true, the picture will be flipped + /// horizontally in [TextDirection.rtl] contexts. + /// + /// The `allowDrawingOutsideOfViewBox` parameter should be used with caution - + /// if set to true, it will not clip the canvas used internally to the view box, + /// meaning the picture may draw beyond the intended area and lead to undefined + /// behavior or additional memory overhead. + /// + /// A custom `placeholderBuilder` can be specified for cases where decoding or + /// acquiring data may take a noticeably long time, e.g. for a network picture. + /// + /// The `semanticsLabel` can be used to identify the purpose of this picture for + /// screen reading software. + /// + /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. + const SvgPicture( + this.pictureProvider, { + Key? key, + this.width, + this.height, + this.fit = BoxFit.contain, + this.alignment = Alignment.center, + this.matchTextDirection = false, + this.allowDrawingOutsideViewBox = false, + this.placeholderBuilder, + this.colorFilter, + this.semanticsLabel, + this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, + this.cacheColorFilter = false, + this.currentColor, + }) : super(key: key); + /// Instantiates a widget that renders an SVG picture from an [AssetBundle]. /// /// The key will be derived from the `assetName`, `package`, and `bundle` @@ -562,8 +601,8 @@ class SvgPicture extends StatefulWidget { bytes, false, colorFilter, - SvgTheme(currentColor: currentColor), key, + theme: SvgTheme(currentColor: currentColor), ); /// A [PictureInfoDecoderBuilder] for strings that will clip to the viewBox. @@ -574,8 +613,8 @@ class SvgPicture extends StatefulWidget { data, false, colorFilter, - SvgTheme(currentColor: currentColor), key, + theme: SvgTheme(currentColor: currentColor), ); /// A [PictureInfoDecoderBuilder] for [Uint8List]s that will not clip to the viewBox. @@ -586,8 +625,8 @@ class SvgPicture extends StatefulWidget { bytes, true, colorFilter, - SvgTheme(currentColor: currentColor), key, + theme: SvgTheme(currentColor: currentColor), ); /// A [PictureInfoDecoderBuilder] for [String]s that will not clip to the viewBox. @@ -598,8 +637,8 @@ class SvgPicture extends StatefulWidget { data, true, colorFilter, - SvgTheme(currentColor: currentColor), key, + theme: SvgTheme(currentColor: currentColor), ); /// If specified, the width to use for the SVG. If unspecified, the SVG diff --git a/test/default_theme_test.dart b/test/default_theme_test.dart index b5cd4fc6..5680a757 100644 --- a/test/default_theme_test.dart +++ b/test/default_theme_test.dart @@ -3,8 +3,6 @@ import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/default_theme.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index 8aa45d5d..32f62b91 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -35,8 +34,8 @@ void main() { ''', false, const ColorFilter.mode(Color(0xFF00FF00), BlendMode.color), - const SvgTheme(), 'test', + theme: const SvgTheme(), ); final Image image = await info.picture.toImage(2, 2); final ByteData data = (await image.toByteData())!; diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 0fbc5f7c..df94eb65 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -5,10 +5,8 @@ import 'dart:typed_data'; import 'dart:ui' show window; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_svg/src/unbounded_color_filtered.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -566,9 +564,10 @@ void main() { testWidgets('Nested SVG elements report a FlutterError', (WidgetTester tester) async { await svg.fromSvgString( - '', - const SvgTheme(), - 'test'); + '', + 'test', + theme: const SvgTheme(), + ); final UnsupportedError error = tester.takeException() as UnsupportedError; expect(error.message, 'Unsupported nested element.'); }); diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index c9fd1d9b..afb04a1d 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -9,7 +9,6 @@ import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_svg/src/vector_drawable.dart'; import 'package:flutter_svg/svg.dart'; import 'package:path/path.dart' as path; @@ -21,7 +20,7 @@ Future getSvgImage(String svgData) async { const Size size = Size(200.0, 200.0); final DrawableRoot svgRoot = - await svg.fromSvgString(svgData, const SvgTheme(), 'GenGoldenTest'); + await svg.fromSvgString(svgData, 'GenGoldenTest'); svgRoot.scaleCanvasToViewBox(canvas, size); svgRoot.clipCanvasToViewBox(canvas); From bbc34d1aea8c744cad3d83a236e30688109b2fee Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 12 Oct 2021 22:12:47 -0700 Subject: [PATCH 026/142] bumps --- CHANGELOG.md | 8 ++++++++ pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f464bfcc..0f592133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGES +## 0.23.0 + +- Support for currentColor +- Some API breaks around PictureProvider to support currentColor +- Support for `xml:space` +- Support for `text-decoration` +- Support for `font-style` + ## 0.22.1 - Pick up performance improvements in path_parsing 0.2.1 diff --git a/pubspec.yaml b/pubspec.yaml index 87ac0858..b2212def 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.22.1 +version: 0.23.0 dependencies: flutter: From 02b8595a5b1f1d97c8af5e4a2f84e790bcd8b460 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 12 Oct 2021 22:16:25 -0700 Subject: [PATCH 027/142] Bump again --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f592133..0137c0ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 0.23.0+1 + +- Missing commit that reduced breakages introduced in 0.23.0 + ## 0.23.0 - Support for currentColor diff --git a/pubspec.yaml b/pubspec.yaml index b2212def..fdb963fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.23.0 +version: 0.23.0+1 dependencies: flutter: From 12e2be462d7a689fbd96f4f5a59be5b2e52c7a56 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 12 Oct 2021 22:39:03 -0700 Subject: [PATCH 028/142] Improve performance when an animation is present over the SVG (#592) - Use repaint boundaries and layers to make sure that SVGs are more raster cache friendly with current limitations in Flutter - Avoid repatining SVG every time an overlapping animation moves - Release picture memory eagerly --- .../macos/Runner.xcodeproj/project.pbxproj | 14 +- example/test_driver/repaint.dart | 19 +++ example/test_driver/repaint_test.dart | 21 +++ lib/avd.dart | 33 +++-- lib/src/picture_cache.dart | 20 ++- lib/src/picture_stream.dart | 49 +++++-- lib/src/render_picture.dart | 133 +++++++++++++----- lib/src/unbounded_color_filtered.dart | 54 ------- lib/src/vector_drawable.dart | 9 +- lib/svg.dart | 39 ++--- test/golden_widget/columns_and_rows.png | Bin 25781 -> 6193 bytes test/golden_widget/flutter_logo.asset.png | Bin 10330 -> 10130 bytes test/golden_widget/flutter_logo.memory.png | Bin 10330 -> 10130 bytes test/golden_widget/flutter_logo.network.png | Bin 10330 -> 10130 bytes ...go.string.color_filter.blendmode_color.png | Bin 9223 -> 9032 bytes .../flutter_logo.string.color_filter.png | Bin 7618 -> 7518 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3404 -> 3411 bytes test/golden_widget/flutter_logo.string.png | Bin 10330 -> 10130 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3490 -> 3496 bytes test/picture_cache_test.dart | 46 +++++- test/picture_stream_test.dart | 89 +++++++++++- test/vector_drawable_test.dart | 16 +++ test/widget_svg_test.dart | 3 +- 23 files changed, 385 insertions(+), 160 deletions(-) create mode 100644 example/test_driver/repaint.dart create mode 100644 example/test_driver/repaint_test.dart delete mode 100644 lib/src/unbounded_color_filtered.dart diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 331479d3..ef1b05f4 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -26,10 +26,6 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; }; - 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; }; - D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -49,8 +45,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */, - 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */, ); name = "Bundle Framework"; runOnlyForDeploymentPostprocessing = 0; @@ -69,13 +63,11 @@ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; }; 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -83,8 +75,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D73912F022F37F9E000D13A0 /* App.framework in Frameworks */, - 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -138,8 +128,6 @@ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - D73912EF22F37F9E000D13A0 /* App.framework */, - 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */, ); path = Flutter; sourceTree = ""; @@ -260,7 +248,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; }; 33CC111E2044C6BF0003C045 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; diff --git a/example/test_driver/repaint.dart b/example/test_driver/repaint.dart new file mode 100644 index 00000000..45891f37 --- /dev/null +++ b/example/test_driver/repaint.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +void main() { + enableFlutterDriverExtension(); + runApp( + Directionality( + textDirection: TextDirection.ltr, + child: Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset('assets/wikimedia/Ghostscript_Tiger.svg'), + const CircularProgressIndicator(), + ], + ), + ), + ); +} diff --git a/example/test_driver/repaint_test.dart b/example/test_driver/repaint_test.dart new file mode 100644 index 00000000..99bc518e --- /dev/null +++ b/example/test_driver/repaint_test.dart @@ -0,0 +1,21 @@ +import 'package:flutter_driver/flutter_driver.dart'; + +Future main() async { + final FlutterDriver driver = await FlutterDriver.connect(); + try { + await driver.waitUntilFirstFrameRasterized(); + await Future.delayed(const Duration(milliseconds: 1000)); + await driver.forceGC(); + await driver.clearTimeline(); + await Future.delayed(const Duration(milliseconds: 1000)); + + final Timeline timeline = await driver.traceAction(() async { + // animate + await Future.delayed(const Duration(seconds: 10)); + }); + final TimelineSummary summary = TimelineSummary.summarize(timeline); + await summary.writeTimelineToFile('repaint', pretty: true); + } finally { + await driver.close(); + } +} diff --git a/lib/avd.dart b/lib/avd.dart index d997667d..a38a0f27 100644 --- a/lib/avd.dart +++ b/lib/avd.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:xml/xml.dart'; @@ -11,7 +12,6 @@ import 'src/avd_parser.dart'; import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; import 'src/render_picture.dart'; -import 'src/unbounded_color_filtered.dart'; import 'src/vector_drawable.dart'; /// Instance for [Avd]'s utility methods, which can produce [DrawableRoot] or @@ -35,7 +35,14 @@ class Avd { final Picture pic = avdRoot.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter); - return PictureInfo(picture: pic, viewport: avdRoot.viewport.viewBoxRect); + final LayerHandle handle = LayerHandle(); + handle.layer = PictureLayer(avdRoot.viewport.viewBoxRect) + ..picture = pic + ..isComplexHint = true; + return PictureInfo( + layerHandle: handle, + viewport: avdRoot.viewport.viewBoxRect, + ); } /// Decodes an Android Vector Drawable from a [String] to a [PictureInfo] @@ -46,13 +53,19 @@ class Avd { ColorFilter? colorFilter, String key, ) async { - final DrawableRoot avd = fromAvdString(raw, key); + final DrawableRoot avdRoot = fromAvdString(raw, key); + final Picture pic = avdRoot.toPicture( + clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, + colorFilter: colorFilter, + ); + final LayerHandle handle = LayerHandle(); + handle.layer = PictureLayer(avdRoot.viewport.viewBoxRect) + ..picture = pic + ..isComplexHint = true; return PictureInfo( - picture: avd.toPicture( - clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, - colorFilter: colorFilter), - viewport: avd.viewport.viewBoxRect, - size: avd.viewport.size, + layerHandle: handle, + viewport: avdRoot.viewport.viewBoxRect, + size: avdRoot.viewport.size, ); } @@ -320,8 +333,8 @@ class _AvdPictureState extends State { if (widget.pictureProvider.colorFilter == null && widget.colorFilter != null) { - child = UnboundedColorFiltered( - colorFilter: widget.colorFilter, + child = ColorFiltered( + colorFilter: widget.colorFilter!, child: child, ); } diff --git a/lib/src/picture_cache.dart b/lib/src/picture_cache.dart index a06d7a2c..239cf9a4 100644 --- a/lib/src/picture_cache.dart +++ b/lib/src/picture_cache.dart @@ -2,7 +2,7 @@ import 'picture_stream.dart'; const int _kDefaultSize = 1000; -/// A cache for [Picture] objects. +/// A cache for [PictureLayer] objects. /// /// By default, this caches up to 1000 objects. class PictureCache { @@ -30,10 +30,10 @@ class PictureCache { } _maximumSize = value; if (maximumSize == 0) { - _cache.clear(); + clear(); } else { while (_cache.length > maximumSize) { - _cache.remove(_cache.keys.first); + _cache.remove(_cache.keys.first)!.cached = false; } } } @@ -43,6 +43,10 @@ class PictureCache { /// This is useful if, for instance, the root asset bundle has been updated /// and therefore new images must be obtained. void clear() { + for (final PictureStreamCompleter completer in _cache.values) { + assert(completer.cached); + completer.cached = false; + } _cache.clear(); } @@ -52,7 +56,9 @@ class PictureCache { /// /// The arguments must not be null. The `loader` cannot return null. PictureStreamCompleter putIfAbsent( - Object key, PictureStreamCompleter loader()) { + Object key, + PictureStreamCompleter loader(), + ) { assert(key != null); // ignore: unnecessary_null_comparison assert(loader != null); // ignore: unnecessary_null_comparison PictureStreamCompleter? result = _cache[key]; @@ -61,13 +67,15 @@ class PictureCache { // and thus move it to the end of the list. _cache.remove(key); } else { - if (_cache.length == maximumSize && maximumSize > 0) - _cache.remove(_cache.keys.first); + if (_cache.length == maximumSize && maximumSize > 0) { + _cache.remove(_cache.keys.first)!.cached = false; + } result = loader(); } if (maximumSize > 0) { assert(_cache.length < maximumSize); _cache[key] = result; + result.cached = true; } assert(_cache.length <= maximumSize); return result; diff --git a/lib/src/picture_stream.dart b/lib/src/picture_stream.dart index 1219b562..09769adc 100644 --- a/lib/src/picture_stream.dart +++ b/lib/src/picture_stream.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:ui' show Picture, Rect, hashValues, Size; import 'package:flutter/foundation.dart'; +import 'package:flutter/rendering.dart'; /// The signature of a method that listens for errors on picture stream resolution. typedef PictureErrorListener = void Function( @@ -25,17 +26,22 @@ class _PictureListenerPair { class PictureInfo { /// Creates a new PictureInfo object. const PictureInfo({ - required this.picture, + required this.layerHandle, required this.viewport, this.size = Size.infinite, - }) : assert(picture != null), // ignore: unnecessary_null_comparison + }) : assert(layerHandle != null), // ignore: unnecessary_null_comparison assert(viewport != null), // ignore: unnecessary_null_comparison assert(size != null); // ignore: unnecessary_null_comparison + /// The [PictureLayer] that holds the [picture]. + final LayerHandle layerHandle; + /// The raw picture. /// - /// This is the object to pass to the [Canvas.drawPicture] when painting. - final Picture picture; + /// This picture's lifecycle will be managed by the provider. It will be + /// reused as long as the picture does not change, and disposed when the + /// provider loses all of its listeners or it is unset. + Picture get picture => layerHandle.layer!.picture!; /// The viewport enclosing the coordinates used in the picture. final Rect viewport; @@ -45,7 +51,7 @@ class PictureInfo { final Size size; @override - int get hashCode => hashValues(picture, viewport, size); + int get hashCode => hashValues(layerHandle, viewport, size); @override bool operator ==(Object other) { @@ -53,7 +59,7 @@ class PictureInfo { return false; } return other is PictureInfo && - other.picture == picture && + other.layerHandle == layerHandle && other.viewport == viewport && other.size == size; } @@ -195,6 +201,21 @@ abstract class PictureStreamCompleter with Diagnosticable { final List<_PictureListenerPair> _listeners = <_PictureListenerPair>[]; PictureInfo? _current; + bool _cached = false; + + /// Whether or not this completer is in the [PictureCache]. + bool get cached => _cached; + set cached(bool value) { + if (value == _cached) { + return; + } + if (!value && _listeners.isEmpty) { + _current?.layerHandle.layer = null; + _current = null; + } + _cached = value; + } + /// Adds a listener callback that is called whenever a new concrete [PictureInfo] /// object is available. If a concrete image is already available, this object /// will call the listener synchronously. @@ -226,11 +247,16 @@ abstract class PictureStreamCompleter with Diagnosticable { _listeners.removeWhere( (_PictureListenerPair pair) => pair.listener == listener, ); + if (_listeners.isEmpty && !cached) { + _current?.layerHandle.layer = null; + _current = null; + } } /// Calls all the registered listeners to notify them of a new picture. @protected void setPicture(PictureInfo? picture) { + _current?.layerHandle.layer = null; _current = picture; if (_listeners.isEmpty) { return; @@ -264,19 +290,18 @@ abstract class PictureStreamCompleter with Diagnosticable { )); } - /// Accumulates a list of strings describing the object's state. Subclasses - /// should override this to have their information included in [toString]. @override - void debugFillProperties(DiagnosticPropertiesBuilder description) { - super.debugFillProperties(description); - description.add(DiagnosticsProperty('current', _current, + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('current', _current, ifNull: 'unresolved', showName: false)); - description.add(ObjectFlagProperty>( + properties.add(ObjectFlagProperty>( 'listeners', _listeners, ifPresent: '${_listeners.length} listener${_listeners.length == 1 ? "" : "s"}', )); + properties.add(FlagProperty('cached', value: cached, ifTrue: 'cached')); } } diff --git a/lib/src/render_picture.dart b/lib/src/render_picture.dart index a1cfc2ad..4ce5cf08 100644 --- a/lib/src/render_picture.dart +++ b/lib/src/render_picture.dart @@ -1,5 +1,6 @@ import 'dart:math' as math; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'picture_stream.dart'; @@ -63,10 +64,11 @@ class RenderPicture extends RenderBox { bool matchTextDirection = false, TextDirection? textDirection, bool? allowDrawingOutsideViewBox, - }) : _picture = picture, - _matchTextDirection = matchTextDirection, + }) : _matchTextDirection = matchTextDirection, _textDirection = textDirection, - _allowDrawingOutsideViewBox = allowDrawingOutsideViewBox; + _allowDrawingOutsideViewBox = allowDrawingOutsideViewBox { + this.picture = picture; + } /// Optional color to use to draw a thin rectangle around the canvas. /// @@ -124,6 +126,13 @@ class RenderPicture extends RenderBox { return; } _picture = val; + assert(() { + if (_picture != null && _picture!.layerHandle.layer != null) { + assert(_picture!.layerHandle.layer!.isComplexHint == true); + assert(_picture!.layerHandle.layer!.willChangeHint == false); + } + return true; + }()); markNeedsPaint(); } @@ -149,23 +158,80 @@ class RenderPicture extends RenderBox { @override bool get sizedByParent => true; - // TODO(goderbauer): Remove the ignore when https://github.com/flutter/flutter/pull/70656 has landed. @override - // ignore: override_on_non_overriding_member Size computeDryLayout(BoxConstraints constraints) { return constraints.smallest; } + @override + bool get isRepaintBoundary => true; + + final LayerHandle _transformHandle = + LayerHandle(); + + final LayerHandle _clipHandle = LayerHandle(); + + void _addPicture(PaintingContext context, Offset offset) { + assert(picture != null); + if (allowDrawingOutsideViewBox != true) { + final Rect viewportRect = Offset.zero & _picture!.viewport.size; + _clipHandle.layer = context.pushClipRect( + needsCompositing, + offset, + viewportRect, + (PaintingContext context, Offset offset) { + context.addLayer(picture!.layerHandle.layer!); + }, + oldLayer: _clipHandle.layer, + ); + } else { + _clipHandle.layer = null; + context.addLayer(picture!.layerHandle.layer!); + } + } + + @override + void dispose() { + _transformHandle.layer = null; + super.dispose(); + } + @override void paint(PaintingContext context, Offset offset) { if (picture == null || size == Size.zero) { return; } - context.canvas.save(); - context.canvas.translate(offset.dx, offset.dy); + + bool needsTransform = false; + final Matrix4 transform = Matrix4.identity(); + if (_flipHorizontally) { - context.canvas.translate(size.width, 0.0); - context.canvas.scale(-1.0, 1.0); + needsTransform = true; + transform + ..translate(size.width, 0.0) + ..scale(-1.0, 1.0); + } + + if (scaleCanvasToViewBox( + transform, + size, + _picture!.viewport, + _picture!.size, + )) { + needsTransform = true; + } + + if (needsTransform) { + _transformHandle.layer = context.pushTransform( + needsCompositing, + offset, + transform, + _addPicture, + oldLayer: _transformHandle.layer, + ); + } else { + _transformHandle.layer = null; + _addPicture(context, offset); } // this is sometimes useful for debugging, e.g. to draw @@ -181,41 +247,34 @@ class RenderPicture extends RenderBox { } return true; }()); - scaleCanvasToViewBox( - context.canvas, - size, - _picture!.viewport, - _picture!.size, - ); - final Rect viewportRect = Offset.zero & _picture!.viewport.size; - if (allowDrawingOutsideViewBox != true) { - context.canvas.clipRect(viewportRect); - } - context.canvas.drawPicture(picture!.picture); - context.canvas.restore(); } } -/// Scales a [Canvas] to a given [viewBox] based on the [desiredSize] +/// Scales a matrix to the given [viewBox] based on the [desiredSize] /// of the widget. -void scaleCanvasToViewBox( - Canvas canvas, +/// +/// Returns true if the supplied matrix was modified. +bool scaleCanvasToViewBox( + Matrix4 matrix, Size desiredSize, Rect viewBox, Size pictureSize, ) { - if (desiredSize != viewBox.size) { - final double scale = math.min( - desiredSize.width / viewBox.width, - desiredSize.height / viewBox.height, - ); - final Size scaledHalfViewBoxSize = viewBox.size * scale / 2.0; - final Size halfDesiredSize = desiredSize / 2.0; - final Offset shift = Offset( - halfDesiredSize.width - scaledHalfViewBoxSize.width, - halfDesiredSize.height - scaledHalfViewBoxSize.height, - ); - canvas.translate(shift.dx, shift.dy); - canvas.scale(scale, scale); + if (desiredSize == viewBox.size) { + return false; } + final double scale = math.min( + desiredSize.width / viewBox.width, + desiredSize.height / viewBox.height, + ); + final Size scaledHalfViewBoxSize = viewBox.size * scale / 2.0; + final Size halfDesiredSize = desiredSize / 2.0; + final Offset shift = Offset( + halfDesiredSize.width - scaledHalfViewBoxSize.width, + halfDesiredSize.height - scaledHalfViewBoxSize.height, + ); + matrix + ..translate(shift.dx, shift.dy) + ..scale(scale, scale); + return true; } diff --git a/lib/src/unbounded_color_filtered.dart b/lib/src/unbounded_color_filtered.dart deleted file mode 100644 index 1787897f..00000000 --- a/lib/src/unbounded_color_filtered.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; - -/// Supports SvgPicture - not meant for public use, visible for testing. -@visibleForTesting -class UnboundedColorFiltered extends SingleChildRenderObjectWidget { - /// Supports SvgPicture - not meant for public use, visible for testing. - const UnboundedColorFiltered({ - Key? key, - required this.colorFilter, - required Widget child, - }) : super(key: key, child: child); - - /// The color filter to apply. - final ColorFilter? colorFilter; - - @override - _UnboundedColorFilteredRenderBox createRenderObject(BuildContext context) => - _UnboundedColorFilteredRenderBox(colorFilter); - - @override - void updateRenderObject( - BuildContext context, - covariant _UnboundedColorFilteredRenderBox renderObject, - ) { - renderObject.colorFilter = colorFilter; - } -} - -class _UnboundedColorFilteredRenderBox extends RenderProxyBox { - _UnboundedColorFilteredRenderBox( - this._colorFilter, - ); - - ColorFilter? _colorFilter; - ColorFilter? get colorFilter => _colorFilter; - set colorFilter(ColorFilter? value) { - if (value == _colorFilter) { - return; - } - _colorFilter = value; - markNeedsPaint(); - } - - @override - void paint(PaintingContext context, Offset offset) { - final Paint paint = Paint()..colorFilter = colorFilter; - context.canvas.saveLayer(offset & size, paint); - if (child != null) { - context.paintChild(child!, offset); - } - context.canvas.restore(); - } -} diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index bb9faf74..4eabe0b2 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -878,12 +878,15 @@ class DrawableRoot implements DrawableParent { /// the smaller dimension and translate to center the image along the larger /// dimension. void scaleCanvasToViewBox(Canvas canvas, Size desiredSize) { - render_picture.scaleCanvasToViewBox( - canvas, + final Matrix4 transform = Matrix4.identity(); + if (render_picture.scaleCanvasToViewBox( + transform, desiredSize, viewport.viewBoxRect, viewport.size, - ); + )) { + canvas.transform(transform.storage); + } } /// Clips the canvas to a rect corresponding to the `viewBox`. diff --git a/lib/svg.dart b/lib/svg.dart index 729deb42..514d6307 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -14,7 +14,6 @@ import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; import 'src/render_picture.dart'; import 'src/svg/theme.dart'; -import 'src/unbounded_color_filtered.dart'; import 'src/vector_drawable.dart'; /// Instance for [Svg]'s utility methods, which can produce a [DrawableRoot] @@ -57,8 +56,12 @@ class Svg { clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter, ); + final LayerHandle handle = LayerHandle(); + handle.layer = PictureLayer(svgRoot.viewport.viewBoxRect) + ..picture = pic + ..isComplexHint = true; return PictureInfo( - picture: pic, + layerHandle: handle, viewport: svgRoot.viewport.viewBoxRect, size: svgRoot.viewport.size, ); @@ -81,15 +84,20 @@ class Svg { String key, { SvgTheme theme = const SvgTheme(), }) async { - final DrawableRoot svg = await fromSvgString(raw, key, theme: theme); + final DrawableRoot svgRoot = await fromSvgString(raw, key, theme: theme); + final Picture pic = svgRoot.toPicture( + clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, + colorFilter: colorFilter, + size: svgRoot.viewport.viewBox, + ); + final LayerHandle handle = LayerHandle(); + handle.layer = PictureLayer(svgRoot.viewport.viewBoxRect) + ..picture = pic + ..isComplexHint = true; return PictureInfo( - picture: svg.toPicture( - clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, - colorFilter: colorFilter, - size: svg.viewport.viewBox, - ), - viewport: svg.viewport.viewBoxRect, - size: svg.viewport.size, + layerHandle: handle, + viewport: svgRoot.viewport.viewBoxRect, + size: svgRoot.viewport.size, ); } @@ -742,12 +750,7 @@ class _SvgPictureState extends State { void didChangeDependencies() { _updatePictureProvider(); _resolveImage(); - - if (TickerMode.of(context)) { - _listenToStream(); - } else { - _stopListeningToStream(); - } + _listenToStream(); super.didChangeDependencies(); } @@ -865,8 +868,8 @@ class _SvgPictureState extends State { if (widget.pictureProvider.colorFilter == null && widget.colorFilter != null) { - child = UnboundedColorFiltered( - colorFilter: widget.colorFilter, + child = ColorFiltered( + colorFilter: widget.colorFilter!, child: child, ); } diff --git a/test/golden_widget/columns_and_rows.png b/test/golden_widget/columns_and_rows.png index ffad57343e0b99518f7b3afee9a57b3ab78aa0ed..b97f0f8049ec67aedf1c1939d20f438687bdf1a4 100644 GIT binary patch literal 6193 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 diff --git a/test/golden_widget/flutter_logo.asset.png b/test/golden_widget/flutter_logo.asset.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 zcmcIq`#)6O_dhcxj#AE`C@~k8=qgHb8DpMtDY-nP>r?4Tl2ppA7#W$0iczWDLP+X1fi}&WkHh|c-R;IQT$wNc}Q;M>~?sd`SDh)M&VC@dPE`!6IsExT74k7 zv)(>-`(S9bWPEvj`pk-xmrw0pe=CD_Y?7|-x`v0dm7ZTNJ3d|g+`f!|bQfysn>m}i zm^gFw%a8>8Va`{i+W& zr_9dDUK^Sok02DL3PJG}-cF!$*HCFfj0m9&Labg+v~PfHwZ-Atpj-!2e;Xp2HIP_S z((5~*s*{1)K)A*$34>^`^*Kqnsq1i&4=4dHUkF}m^C?tkl7TFss*p*1qRd1lDd8cc zp;TI$0Wr2JKvsoMgm?+XggjzEoo9nTLQpxb%|&D#iT1zcF(HLWL7Eqp=AK4$rI&(G z)R=^+9VmSX<>yFHl3~ZQ!JmiwBQ1bWA(n^G2*eZuO6UioCMizAwFE(-J+39iNw}7d z(-uww2AZU(gKJ4J9b8L_(?R>0px|yzr7_7AtcyS>D3Jo>9YjMVVHF@-WC~)Vpq)qo zVh96nMWlf13I1dXyuuMmTRbth?(l_(za0_H27odpmJ+f6601QHmq%w_$I+JTj4XUGxJrRN|EOBdcz^EveWWh53)X15;5YD$KCXQdFiKzePM!xcu8(HO&UsS_^{D7Og3m?)#j2R#baM?`?- z?W5AXE|9n|W$uu;ZD6~B#PtW<>m;rz;Qk;3!)RzMS)H+?2;~-;4j!G!ok0vJ*Mv%2 zmqegq@aB6*PJa<3@hnmAkc%*OI;80VFij*0OaYP1LA5%F#Yqu0D36hfe=9MN z2yJefFTtzWT^`dT85lryoJ=NBAq5Gik|9`QOlLJ>d8Da9I~k&iwUEmq@taUgPe@R4 z)}~Nph*uz@VlONfPWUS`4V=joNNA`684Fj5X+W+C#1@of*u^T~PrNb^16yG+LM#s? z*-FT*BB7H15OT$&_!n2mb(#=)Larhy&IfH3={DaEY$rrOaGDTTfGsIr16wi$$UG$` zMy8;677c~v4ci1HPnSZakgy(1E|W}wa22$ZDTqCVgfod0Aco3Jj7$M{3JvvNMXca7 z9V*R~*l{4$YzkF_oI73#Ncc38fR7LfpGr>O4;Y22PTJ;KQEA3xQFnhvLwzQ2Oq=fkx2L|lI>wSGd7$UFfNx$dpFS@ zhlDSk@Ym(KTN49@JdwxNO_(a8*gAM|!~Tcs1ma;*6oWW1qE#RgWKUIW87=(9SmDrH znOjOxmdiT0ZRF>ZMZ>)n*zO<;B$9Y3m$i&;c{F(Q%FeOi_sv4(3ibYX19GE7o>$9- z#glNJVxNZb=OGMx{U}B1&W5Y^?paD3$6D^LeW)pa$68ptoU|#ClSC^1!{mNezzN$L zH$@yMk^6=*$tqq3Wk4)Vn@^=(AwsK*RBWO%;$Uvk@%(71ORUVBA`Im**v6*)=dHw4 zA!_i1w+~fxiI@hYHkg5Gh&P4yy=ZlWNV&FdgHyy7tNVpbTbOdGx zksq%lBwU{@vj6@30V<#$A8l3oO;?{vt7P(^K29VIPqWY1)pL5~)Fsd*7{fyGk`71;U|M~0D&}&=~ z)VzuC?BLl>1m$kx*$bYnL<;};N5b<8QQv?5S7H4!dBJuQ^tm2XnjxKK!Tz0XQwnuv zR4nWv$#G?H7tOd`?EREmkt6mGW zh%55v{_a0j9{YgNZ(04GKEsZ}V%ezJslN#r(7<7p2zG=M`F2LJHX*t*{CB{ttO89W zt}Vy1_w9Ex#ja32x3kM?X2a~T910m6w^>=?&tl;*qr#ci}O%M33tgYy>v92qT zQ#gx+BmA<-&_QPNHlC<@x`gtFE|-bYZ_y;DDuyJBS-cNRKsSfWgt!pUeIs-#5{eGS z#7?65FgBhNX*|Zd;~?PbL-p6@RWdoZ)^j+zd~`RR;S9%3tEgCg;8BZr5t}3xzCkf` zl}KB1>h&;=R%R{WMuF#Ae-UK5=Xt3J-MXnsW~B}{P44(fOmfO$4DaCDN&)vJ4ejIq zNr$j^F2Xx_rNnTCLAG$=&!vN;-+QFPRDg!O~B2-Nr2pj9zHPHP#$VR1*;-4-4Z$9L?k@rdjQ@;Qwg|Q36LG| z(nbmiZjW$o-;@}|L-3;J-@rYUmjO4sgWw4pPMJ3+P+0CII5(GR63SmNCyGTecvxY0 zrwXZ3WQG>kUC6V6d4DAg&&W}G0dfN07hEKWG~!*rc2@We#nkdJJpA@BAQ$@uV-)v5 zw|`~gx|xo+ZcLd`>`g;e($3)BD&T3d3yV^84}i_d&DVsEpf?_==xzbJTc-$}C1D4; zP|($Q($?TqTsPxgJSdTi6(ixi?a_D?`8Z>EZ*Vt*=Q$l7Udte^ z5*9}|0zCFy$MGY@2iccHnq<6=A(S;Iz%5#8B1YR|q{v4tt}yP+X*>Wr<2;>}G>0P$ zl*c}Q;E}2mN~|OZeE@cfFOHC^S4yl-h!U<%KF1kp5tV$64(}saRnVEm37$ApEzUa~ zUJq^sSbvfAy)bYz-Au7N%tdg`N${1;>!CA>Ti}oh>oY$pwm(WSO?~4gMZ~?W#CF~x zlZ@eA`b$6QyNUfR;>RGoAUNEdD6!4qm%$}L^#TgDT1j$~&i2rUQx+VSy~3p*^ys%R z38e&%_J+!g3m8jPiNT!>Cpaz1Ykm5DU1)-{qamHaij1AvBohfY2OdlgkIvH9kx=+L zTsX#ZcyrBpC34t#gt9I|ie9gVj(d7Z&@)KILIq`JDXBCyEmm>YFpn-RF6uPojX8e_wj@#wQV`=M}A}0Bm z;NSufVwZ!LvnHGwtpu@u zUcv3)&dlIIQ^bsGu+U}nAc?XLg6d1tae~{GnfT3|vHMFfM2Lgp6WIl7V8_&fV_~c` zP3Alw7{+7F;d2KtVxK*!lpa}~u@@@1*R(*} z8)L1i-JD0GAGds(Io>!v_OH`uWzs`UWv(`KDLQZY^Q#7(_g+_W)33El@p7EYZOcQg z&m@C<6h8(i97QkMACpMTf`axm4u!Xu=6DWXFe_+OW#Q)q13k8AVRA`neVz1b$Lfr^ zZWUu@L5f`hHxXhoX^Pra)y)q>a~=70t9|{++bv^t zZC3U@7q{B1EJaJF{(+#})$O6U4`v@Ni%cB|lRR(5t= z$FnL|w~VW{B-NE>k@Ac}SM%QFk^AGBOHt1;h5mC-uCAiLw`vf0l|zi>|JYK&xb zs&Cx#u>Yz3edAFh#2>EdtTEPCUo}S2@>z`*^Elb*WhUlB9X}TY8ul*MV7Ph5aNfD~ zYHfT!z=wGU6YLLBUQCO-AW*O>=A(nFk>;6%SpVU*M!kzO=4y<5>)a(5HlHVSfr|{t zyxWpr&98Hc#_QfYEh@;4Ik(B7d+6$w0YUkqg2ZTXbE}hFcdj)`+;!NB@=iXJN~7PG z26b`FdXMB=FxsD5Flvk#epO+H$~|2xMaU$K$vwqKPng7r3wAs&on+goS!%m-$ASXW zLu2`2xh`5fAzT1*Z}L&qq3prO7&GgycvTct* z-=Z-RbBD8B@oc)wInS^ieI4B?bcRvpCWi$@*;k%6m)py>rdWQm%V|x@>1RY?Y29Eu zlW#XOarDCLc}2h4mjza?3k=v_WxMq54{s&L?#`hH9*?pPict#e;E?1$L<$>k7a0YA zYYgjYkak^w@iCJ8S+$@b(W0}XZJ9&pp}vuX=H{;lts_2bsFmU8$$9vx zci&7pwGTcKtP4lmkHIuvo7tS6eP!WH^E%(nZZP4l>ESyAAqTEb=P9vnc6M9L4js%0 zI~ZoJ%Gi+-xYV+DUq@uUlrU<85t+reTXjYnpE`6^_q;;og+Mn4PqP^DM~5siVNwPr ziF~{Hzd{sk8%LLoHy|OxPNiQ(b6CLbGG7JQpzRB3YRZiAc%2t>_>0W&!0cGuXQ~?2G32>*dn-j=x)EKD+2p>vf|o@yqMHz3XbVbv+l(T($F1cWH@p z^R`PXDnh1#6Wk0}8`4j|AM1*Eecy82NwX`)vw7Rtot$S_LW3_S@9V4@Z9dj~yQx`vCnxI{$J01DbBS5=>+ulI3?pR?Bfy>n`wkY{ z!{S$gqD|xQzm~x!n)NB00^Qd7y~@2Za40$d%gCcLwKaldRgKIdClQha`ygXG(KXMo z!6$7Si-r`Pp4$fa-!JuO*`_pWP6)?ySu(sSqfds^Bxcpcd^?niQjB3EHy>A#&ls6MTlE|<<7Q_2?FFy4Si*O}*03y0pD@I*a=Y@@~s7dp;1 z?%%l$sA10z)?8k5srhY@t%&?!pv2no=~JQQaLbL+k;<;Njp+k*fcNv+sUOqv`)Q|5!$?Vyx~BQ|E~ow zO;Xyg#&ivsaQf$FB%Hai5c{^M|5)~&)O&CC^xDl@wzg*TZ4Dp696lPG1OS)cP5>B% z1w9H0GUl{66_`H$BJjSqZMeJhwNt^zz4zWc$WIJR+_m#Y{^@DKJ;o4l^04F|Ip^3n zY>&Nyu)h8+LuSpA`uC1ig7Sa+7Z;9rcYV)1x23}T&+nGctOsfWKRUdBj|pOWJ;^Rtm~f0?(fN;QP3)=qKZH=aSsq z%wz46C64cF4m~uCY>S`669&LQ6(60&3TX~WzcJcV)fKa)XtX6^QF(=+eEt(tPJc(= zt(=-y*Nl5r$0NMWqHCi2(jK1GTqDjb^k2Gk(xbb_F?Wq;VP|P=`4_Fr8l(+vyHcea z3kuTTdp4zKdv^DkBn-tLk4c!?dYjS8*lX{)JEOkCCfK=1-{RVyjKYo$^w*1Ff#l5X zp01pB?5Gk!#B!+QSYWB2WU<++#Y2MOtM$)~lkeaCnw53$&E`-oi))R^ns4{6D5#Bo z+vjg|(2-4Bcf_D29+C(hWDdP#kE>T$6VtTDM#su5!d_G&wC zJWkNuQ@GUPL$GP|_tF}x0G-~V^l?~7@HMhpD>OQ`SsK43@NDJAz`H-nZ8aU-G7E=o zKGq$YTVK@UGiz_XlExH_Rcr_|wW@CcukwW02;T*?G~Wr>!Rfejzkl7w{2u?{pJj?y zBm*1Y92#v)tXi*0r_T32&?-Y!X*zO#Ph<8CPS1YtH@%z0-^^Pp1#dTI<$ho7wo$(} zAp86ExNK9m{x#XzXG#?rN6)c;y3=lYpK zMyXiiNZBgU>Qc&^)&2Xt%H`}nK0Y-qmveSnuDQM`mCh(8JRU3fnuyA65gPKf7bESb)66Lz$%%!_Xgl&UPeO#%F(b%4~VPW4~eolaI#1$8d$e z)akc^1()OAytH7J8fh*|ap;e}pV2XFq+h$%rMYwGPq2G6&zwuyZ&UVAvQLc}@Gl~i+`K<@da^zh`0%l{*h5(+lsEKGx}>c?))CbSh>+@WGJq~*75mKsh$`O z?>Uemr&nf5zvV4>`#$DUbIa|lhx>c=4ChLoET&VpOS~1GC7h0V%UnWx>+Xz}n7M@Zzif8BULprq9?r5i zhLIy1w0R3ph&%r2ztjKWQ_Z{PZoB@wa}>oj77siB668&$Q=he-Wu&>QT9+M^{JDG6 zijB(}&fVMd*rHZ!VHT2*CWUV4PH(S$nzy$0sl*^WEMbp0e& zHf-9_S7r!eL^sr6^!I1FhBhZaPP(Km`z24VL}F^X-BkF7I!)`V``}pE(C~?(zSh8? z?EAIvQ#p^B&VuUc&_(kFM7T{{H0Zk5^h3kw%9_iJ6mwlpTOu01Rk8;uKG_aOZa$0W zZt_SA@%^W{d-QG6wA>$I`Pm&oQHqx^mVrXUbi|~FXn1pX_*GVRgAON>C*qFR!iifL zZ!_MkbtB`LTv$eK$6oO8atW?_Qadc(Q~2}Eby&97UKGe6s=-aRmcKmuz4|lavKi3f zR$bcgD+Lr$efaCFV&fjoC6;U4YEzFZUNTUoj>0bE!Q1*90_nh$(NTuI!*F9$gdQKo zFGk#1K}9`ZK2?m?Go0K;9VAvNY}#;X!6d{!A3s7S=F~El=@*9d#7on54T!j5@f3=? zK2bruGlwK|-5TxSb7DjS)~47!3%U07-IPW3AB#2=CA$Pa{(iGqlz>IzKQA$)^WY%# zH~bXfnzaZ!g@!+XU!v?%X7ROoO!&0Moxv7G^3f9b6-b#4(Y_Aa*GFM&B^CykXiPKG zAGVQqctm>_{-YQzUZkCfdml`%E8$RS@TpYzj_|6U3cqi$iNpc&4uUqCjvKhcg(rL( z#@&kHha8BpBLP+cxc($A+`J*CByIuNULbMd>QGoo;!Xp$D8cqC+)bf>5CD(B^diw2 zToqE7vkA6vkqEysBKjJJ_N|0}9@Idt7vX;mPFq+C%3{;0Iq<83zQct03UbtUloWC8 zaYBUqQKT=16mjioLOhRa;R^~NsN!NGA-3Woi3>Nkhysb534zIyY}Z3HRzyBN!_P3> zefcOo3WFSeM{5TKrE16vQ0UFNlX*Do`?>vBy{6GJ3cZ^x`Zf0Ara#Wjw OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.memory.png b/test/golden_widget/flutter_logo.memory.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.network.png b/test/golden_widget/flutter_logo.network.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png b/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png index 4b39a25ab1399bfa99098785e967d1bce267cb05..d46b6ded9b7b4cbe558dcf475ae18bbc7c50b096 100644 GIT binary patch literal 9032 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 Ju1IB({|EC_!h-++ literal 9223 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 diff --git a/test/golden_widget/flutter_logo.string.color_filter.png b/test/golden_widget/flutter_logo.string.color_filter.png index d80af0975390b8ab1d09108ebb7d44780e376578..0f02fbfe18a983b802848cc90e92329fd572b611 100644 GIT binary patch literal 7518 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 literal 7618 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 diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/test/golden_widget/flutter_logo.string.ltr.png index e4402865634cfd5469cab823e5056404bd347fb8..7e70b9565dee51aef6a52f03b7b7119a82c15361 100644 GIT binary patch literal 3411 zcmeH{`CC(G7RTQNlnfY2SY)e)B!hs`qAgN^hTMrM2?!b^iZW~p2!bpM%9cuoLMJ3s zmQg?uQYcGNS`btE6n%nehfw#z6h$#e4NK69F@z9`s6FYwQQlwji~Cw0;`> zLzVK$W6i_pzU9-IG!U|KRvh@NJJ9~!^QNS-mOb7$g>#1YwftY>n`6FQyRbpN^o8g_ z;4=nV#8QW?z@3?bqF2_%FXeemW8d4wgw1K#e~{HLQvTC01AQ*~lenfB4r8U7L6 z7CRgsdjV-loW(x)S=3A||&Ek^r z=0cUo8u`*ObiHH|H97!jDz!%WZWwYD1E2u-7l0)b5G|rO5`aDcs{zbN05}4W0{F}X zN*9r7Kxmmc0V6`yfhvS+chcb$+ihLZHd-KZ%z-2uA;~@{ zlY$8l&mMr<1fZu)p#Zi4_|gQ1oeX$1-({)OO*vE>Rp~va?0fF#YsbD{xQyW)3nA?A zMG~bT_R7-p6!Gt0x6AL}Qv2y}JR-~_oV!m==ihedxzD(q`=Y##Q!{$qoFB{bahayel?6Jg(F16SS9HHM`%UCcpy+vZhf=QnY4{PgRem3ob4 z)b^LF>1mG^jQ_s2sOO05Efl%n12H0@ILdE9eL-oJ!5FK1VB>jSbnm(}h3R7$eJ<5V zzx~>FspAKKJ}RS*Q-&$c)%PKJmoJ43K9(ReklS;VJiFzlA&Hw-#;| z&Ac%WUa8bIwp2}_exmT*X#ZCU9UmCp-1uogH&jKt^NpA!3?hTU@fCzTy^7qxEiBN z*3tvP4MeGgBy5AFR7H4`Poz8<>;(%xlJ>aApS*K}vw45y2ghaGTt;LZ^?qpOTkWd= zQ0N2-t>+sFem$8pD)m3Rw8whfX^FF<>xWMs_Dv7did^=V4;0L%9S=DFEU%h?YiHu{ ziZ)+yMY2_^Kg)@bT?iZ3Z}lSMc})1~^~v=k8J{o`AM!FnwN)U{0R&>z zgk1+x4Fo6)*Un>CK0D8$(bSwzKW-?y!X?Bnt zA%jftT=9c7BWtq3OBppJzl3e3Gvmzuc_`YZrLTBMNLai`S mgdK&aD`&-l6$iip#uDYjYr3_J@>F}1AHg5*Vt2CQiv9o@we9f$ literal 3404 zcmeH|`&&|X9LK+hY%;A7Ej3qyNa}igGA~(E5#m7wGqu(-)6|-)P`fBzf@zY~25Lz% zua&deEZ1Y!R&!b|S47%W63Q%1%P2214ND``xzB0O{)+ki&q@lq9 z^G$3_5JK~LT+T*>=1>tLY$1LGq%<{aKU^@u#sD_D*tTR4Zj1zM-X7eyu+mVpJw$1M=DOs z_ZnF}I7;<8>8YsN!a0$BR!#SNO_H_y-wBEeG<)pF7r67}!6S+7-F$gTOLvi=t)c&v z%6Me#wa>Lbi+b|}G$>?t%{uUZcfhGO_Tlq8nhh>koHx6iTRYd(@vS3AZgC&`i zDp`PdA( z+54hSDZ;20eRIT7kntM_Uo=pFuox!*2LXJ9gCYP_0BZpl09b#AuyPjw+X0AhPzb;g zfHQzpx-V+VhAj~|fGi`tbR=7a5gH2>#z<&JMF})e^--2|iZN{CQFWuZ83I$F6Lz)l>{0dN4s0dN5DoCRCN zdK420F|r{>t_4O2-3~z$?OAAfAV`lJ5m|GkB&399&s*!T#x)jHv6ozjUz5yzCjU+<{zYOSrA-b}@EnUK@% zD@opARW+lX_oZEPe9g6Gy6^PJ$vEs13OwtqBlDfLS34YdJ}HKK!=^`D=fpTcXu9H# zrNWps2(^znz4Vvs5j6nE!IUzFB{{P#MFM0O5KhuDGw=(8R+_cucF@mOV!G_}I znp4rT0^SjD)&!glOgK*@gArncIn^Da#op6zsrRCgna3oxlclSjbXe$T5RqWWmYwOd z7dog9tjX`R5C%Z1^K|Hg%VpJZ+BTuW>k*q2Slsc zZT>dOlKRNs0L-g@XdxE=1Rh(Cw-c6AvX zgB5S|1NC8e30t9rRfQ4h$xoJoHRTiF(t1Yf4;j>lpjc}6Flwe(b=w$0*OgI*iHk)V z`f)4Qzs9PVJ!@uej%H5jYNirG$ZwE!G)R=ob+D1udwD+bjB4|VRZ5iH!pHtPmGwdX6Vt4K=k>JY_v$GN_jin8Adu87K(vC&TzzPvX)RVP=?4EY4rdXok1uxWI PNw^z4zhKTqc1+ek!J+%< diff --git a/test/golden_widget/flutter_logo.string.png b/test/golden_widget/flutter_logo.string.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/test/golden_widget/flutter_logo.string.rtl.png index 6c8dd292777c2640514e08b937b8d3d764a80b9e..e65700f87fa6172382fd53a21970ffacf71e87d1 100644 GIT binary patch literal 3496 zcmeHJ>0gsq7QP8lf+K}Qlk#KBhR7fcrF2}{03ikvs6Zz2(@H8TP=taYxUdf?#F~I? zqcXJ!LBWx+EQ-SfRFFaCIvW2_Tx+FuV=^~N1I5M$)O?WZfEKG`!7^P5(NHS@%;xRLB0iy+|^$5?@N z1O1uxE9onVR8Zl->v`=@zewL4GE{MPfK(l0A;`^ctRPEM?_fxAUH?F9WDSDWHJM7bj0C>A~5l?;~>91QuI+I zfyj9X&ezKkt`d>(EoJ6(L}74|1p%CJ!O5~c2RZsk(UU+BWMTp)2>d``27*=)cy9ue ztz6{rH-zIzkx5_@HqgZ@dU{t2vU3{=r;($sf9xBv*V&)*WvIjH^7Ak zf+RVBW`~J6dVy)E;6#jR=o}PT40k9e5RnaufnuOOWnplKIWiqp<$%T=G+KMGxqxto zcY{qy<@_Q-Rma-Dd9;ZYRvhB^bzJ0;*FB!i9`RQ-iVW>Ve(m(m;|tH9&OB)Dn5}MN z_u1UFzdjZkapRU!;*9P%6kjfVw3tpr(82u`6ehK$O>Awl`6 zUEF;+`9-l=_Qo_OPg8HHIYvT7IAfup`^{fhwA@ZeA8cteN8*`F@c-dbZm7cVu zIcxI@!uIAa+r;7u%)yvpjNT=z1dti*n;`2N-mA5whA4%;Mgmyg%NB;NI0_ zh9)nc3Sb^+{lrv8Q#N*#0B`SL)utVM*BzK@O>@p6>9pEFeUh;R2NUBsEuZpyXL#wk zykh)e{_;!&DK(iIcR49)DUBpX8*L$zBecb5-L%H~h zIelO=s4@7s>_8SVK=-TPe`dD*ti4a56HotTsVVQ54FV@AvChm%!fMIqg+ zP=-}raJo~?<L#l~$=kMv`lQJky_(pQiRabJt)OzVq9Ou=tTIH^r{`vx+8V zA%ty7faI81av$1~Y0k;viKWtW4=$Poc&6%=o-6YydX+KS29%>5cku`n+rAt+pO-eH z_0!2Z%5Cef6gDKR^jr^YUTND~G6}iuV*vqTqtcw3O8L~;WcS#SHdk7knM$BNRTZ3W zS5xZQIMQr+yU)34xHX5B9xt!7gcbX_P%~ee{ zCMuFsSLeIfF@b65CXBaGG^J`!P~LuO7<@9?;QB7S-!hd+{kE6{1vB+N7P&KGFk@`| zImYWJ9{`-ImFHj6RZ*4N&hO&blv#x#^iAg&(^8Qga}i_hzdi?!KlT|O#vO1E{m)ib zU!A*;V&Us^?3FVO2{Wx44095DA_cv}VVCZ0C)am&w;T2zl53T;jCYTp4lZ*ck_kj2 zH|6CQsaH3BY&qvI{)fxbMDgJC2o;TBRVk}9L_WMd`6OdiUtLSNwT{yWbW~AnXoc!4 zKkyIff1w~Pj1Sq~0||1mAvPeoH$2o{(8wU5xk_e+MDW^?VJZbB0FW9`*~W=w4}_*J z(W;w@MqI5(ar%^P-9w7ryym5nkhe(a4h~4YD~?1YQ0%|?KVPDA2#40zS_RfB0DsQ> YSB+27^+L(4GaIXiuXg~ihI=^kzdytZE&u=k literal 3490 zcmeHH`CF4$7QP7xX{-$&AR?fUunPi?;#kWPGYPAe41-9l3brT=5*4vw5t6T%N}^&& z#9>XrO3``70+KO?5lCw(%!;JJYAn)z}hiFuVjVYO51eg??1$7ohXy{ zwye2xdWP{OzdSY&mFf|`UHNEq zP+It{{!>1Qi;)e>m~0B-I5QD7K#aJt0N@1R2tWt`Yyesb0Gv>F0pI|DApy{tD1-%o zApmRuij|1uvKAw^9(IDAATg@uePn_wOz9{w04Qw)1(I_4l%Oz}Xakd=fcvv1KrsRe z3n+RB-T+Q|!vM%40D=lmdT9Xs3_zNh9a`$S< zf+9ilodS`5Gk}ODkchfSA(gE$q@ec>EHu8AL~gweI|B|()aVH@4HOf!mjOFQpwa}-jHJ;do{fVxl|Rnr-UxM1me`iG|O?&&xa7|>Gqbg;Fr zZ(<}YM;Sk(i5BU;nH$Ki^4T-gx6P7wvo=5O)DUq21#m;^gDY{55VOrIc`YXmP z*_u|_ye%pA;IUZw(4QAwKk1%2V#6PkgTVRUE$J8*`1D-v|9YmRhs<30Q`QQuN$rAF zpgl)8G#htAG_3x4P_SOR-2%NQu8b|d9xO)Y5-7YSR#TDp=o4fONmGNw*Z;_Vey?NN zcMz3@8d8`$q`49kTl6gvbbT0O_yGq;=KDDI>i|0=VK+WI3XeUrob1c+t9m)ul(~W zaYP6kM|lx4Mr_V({A93LLctwGmMD&;k7*)?Q~x z-!G9lK_BiXnrzC9zW@BvFHBz9_fr_%cWD=rxK_6t>$^J}4^6xqMr6ZLLG;M@XZefz zX-QpEgZ5!wMe~Qg|9m&7LDg#s0}HeH2c8LZ;~HT`lI~J*+UrBE6*7Ns0YkPCZM6k2 z2ft`}+eK?p)oY*r+N6w`=V#DNwSPgCV{w}9Y>OQ*_K z)QY~YarQ$|=io?OrNvY=K`FwCsP|HH-e#6Z$%pQV!qSqXabX$gxF-mW{-d+=?JE%J zHX0d7+-C8WS5453d7*`Y+-MRc?<=n!=wFO+2%Ye$rdl0r#;H_(a|c=$-_;AS3Sfi5*+;^Rmw^2RO`*gzb;1nv}cjs zzkaa!b$;%PMuE{}4aS{cCcV2H)&GI*p5t$^Y5rkQ{pH4V zT@HsEe8@=(V9Rm=X^|834S(d(`xeV=H(U)s2FG6t4)gyo6!jO&WW zXYBa{YiGiQ-bWA7GUvN*4jk+@fakqe{vNmJHS(2K!p+8;}1L#rBU%tb2U>j}+Fx-mWp!?z+yAC`si x;c2P`T6$a&8V$e^LbqUZc`a99xdKpux^YoYx0dT9P&g9x2 1', () { + final PictureCache cache = PictureCache(); + expect(cache.maximumSize, equals(1000)); + + final MockPictureStreamCompleter completer1 = MockPictureStreamCompleter(); + final MockPictureStreamCompleter completer2 = MockPictureStreamCompleter(); + expect(completer1.cached, false); + expect(completer2.cached, false); + expect(cache.putIfAbsent(1, () => completer1), completer1); + expect(completer1.cached, true); + expect(completer2.cached, false); + + expect(cache.putIfAbsent(1, () => completer1), completer1); + expect(completer1.cached, true); + expect(completer2.cached, false); + + expect(cache.putIfAbsent(2, () => completer2), completer2); + expect(completer1.cached, true); + expect(completer2.cached, true); + + cache.maximumSize = 1; + + expect(completer1.cached, false); + expect(completer2.cached, true); + + cache.clear(); + expect(completer1.cached, false); + expect(completer2.cached, false); + }); + + test('Cache Tests with size = 1', () { final PictureCache cache = PictureCache(); expect(cache.maximumSize, equals(1000)); cache.maximumSize = 1; @@ -157,10 +187,22 @@ void main() { final MockPictureStreamCompleter completer1 = MockPictureStreamCompleter(); final MockPictureStreamCompleter completer2 = MockPictureStreamCompleter(); + expect(completer1.cached, false); + expect(completer2.cached, false); expect(cache.putIfAbsent(1, () => completer1), completer1); + expect(completer1.cached, true); + expect(completer2.cached, false); + expect(cache.putIfAbsent(1, () => completer1), completer1); + expect(completer1.cached, true); + expect(completer2.cached, false); + expect(cache.putIfAbsent(2, () => completer2), completer2); + expect(completer1.cached, false); + expect(completer2.cached, true); cache.clear(); + expect(completer1.cached, false); + expect(completer2.cached, false); }); } diff --git a/test/picture_stream_test.dart b/test/picture_stream_test.dart index 6f10c681..d9629156 100644 --- a/test/picture_stream_test.dart +++ b/test/picture_stream_test.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:flutter/rendering.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:test/test.dart'; @@ -9,19 +10,101 @@ void main() { final Canvas canvas = Canvas(recorder); canvas.drawPaint(Paint()..color = const Color(0xFFFA0000)); final Picture picture = recorder.endRecording(); - + final LayerHandle layer = LayerHandle(); + layer.layer = PictureLayer(Rect.zero)..picture = picture; final PictureInfo info1 = PictureInfo( - picture: picture, + layerHandle: layer, viewport: Rect.zero, size: Size.zero, ); final PictureInfo info2 = PictureInfo( - picture: picture, + layerHandle: layer, viewport: Rect.zero, size: Size.zero, ); expect(info1.hashCode, equals(info2.hashCode)); expect(info1, equals(info2)); }); + + test('Completer disposes layer when removed from cache and no listeners', + () async { + final LayerHandle layer = LayerHandle(); + layer.layer = PictureLayer(Rect.zero); + final PictureInfo info = PictureInfo( + layerHandle: layer, + viewport: Rect.zero, + size: Size.zero, + ); + + final OneFramePictureStreamCompleter completer = + OneFramePictureStreamCompleter(Future.value(info)); + + await null; // wait an event turn for future to resolve. + + expect(layer.layer, isNotNull); + expect(completer.cached, false); + + completer.cached = true; + expect(layer.layer, isNotNull); + completer.cached = false; + expect(layer.layer, null); + }); + + test( + 'Completer disposes layer when removed from cache and no listeners after having a listener', + () async { + final LayerHandle layer = LayerHandle(); + layer.layer = PictureLayer(Rect.zero); + final PictureInfo info = PictureInfo( + layerHandle: layer, + viewport: Rect.zero, + size: Size.zero, + ); + + final OneFramePictureStreamCompleter completer = + OneFramePictureStreamCompleter(Future.value(info)); + + await null; // wait an event turn for future to resolve. + + expect(layer.layer, isNotNull); + expect(completer.cached, false); + + void _listener(PictureInfo? image, bool syncCall) {} + completer.addListener(_listener); + completer.cached = true; + + completer.removeListener(_listener); + expect(layer.layer, isNotNull); + completer.cached = false; + expect(layer.layer, isNull); + }); + + test('Completer disposes layer when last listener drops and not in cache', + () async { + final LayerHandle layer = LayerHandle(); + layer.layer = PictureLayer(Rect.zero); + final PictureInfo info = PictureInfo( + layerHandle: layer, + viewport: Rect.zero, + size: Size.zero, + ); + + final OneFramePictureStreamCompleter completer = + OneFramePictureStreamCompleter(Future.value(info)); + + await null; // wait an event turn for future to resolve. + + expect(layer.layer, isNotNull); + expect(completer.cached, false); + + void _listener(PictureInfo? image, bool syncCall) {} + completer.addListener(_listener); + completer.cached = true; + + completer.cached = false; + expect(layer.layer, isNotNull); + completer.removeListener(_listener); + expect(layer.layer, isNull); + }); } diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index 32f62b91..1468de98 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -48,4 +48,20 @@ void main() { ]; expect(data.buffer.asUint8List(), expected); }); + + test('SvgPictureDecoder sets isComplexHint', () async { + final PictureInfo info = await svg.svgPictureStringDecoder( + ''' + + + +''', + false, + null, + 'test', + theme: const SvgTheme(), + ); + + expect(info.layerHandle.layer!.isComplexHint, true); + }); } diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index df94eb65..a258efa5 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -7,7 +7,6 @@ import 'dart:ui' show window; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/unbounded_color_filtered.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -42,7 +41,7 @@ void main() { ); await tester.pumpAndSettle(); expect(PictureProvider.cache.count, 1); - expect(find.byType(UnboundedColorFiltered), findsNothing); + expect(find.byType(ColorFiltered), findsNothing); }); testWidgets('SvgPicture does not invalidate the cache when color changes', From 87221450d73ec6b4f9cb23f5bdec712a151a36f0 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 13 Oct 2021 00:36:34 -0700 Subject: [PATCH 029/142] Fix layer reuse, add regression test (#608) * Fix layer reuse, add regression test * Make golden a little more tolerant --- lib/avd.dart | 12 +-- lib/src/picture_stream.dart | 65 ++++++++----- lib/src/render_picture.dart | 14 ++- lib/svg.dart | 12 +-- test/golden_widget/columns_and_rows.png | Bin 6193 -> 23184 bytes test/golden_widget/text_color_filter.png | Bin 2322 -> 2316 bytes test/golden_widget/two_of_same.png | Bin 0 -> 2010 bytes test/picture_stream_test.dart | 62 +++++-------- test/vector_drawable_test.dart | 4 +- test/widget_svg_test.dart | 112 ++++++++++++++++++----- 10 files changed, 167 insertions(+), 114 deletions(-) create mode 100644 test/golden_widget/two_of_same.png diff --git a/lib/avd.dart b/lib/avd.dart index a38a0f27..85864a61 100644 --- a/lib/avd.dart +++ b/lib/avd.dart @@ -35,12 +35,8 @@ class Avd { final Picture pic = avdRoot.toPicture( clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter); - final LayerHandle handle = LayerHandle(); - handle.layer = PictureLayer(avdRoot.viewport.viewBoxRect) - ..picture = pic - ..isComplexHint = true; return PictureInfo( - layerHandle: handle, + picture: pic, viewport: avdRoot.viewport.viewBoxRect, ); } @@ -58,12 +54,8 @@ class Avd { clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter, ); - final LayerHandle handle = LayerHandle(); - handle.layer = PictureLayer(avdRoot.viewport.viewBoxRect) - ..picture = pic - ..isComplexHint = true; return PictureInfo( - layerHandle: handle, + picture: pic, viewport: avdRoot.viewport.viewBoxRect, size: avdRoot.viewport.size, ); diff --git a/lib/src/picture_stream.dart b/lib/src/picture_stream.dart index 09769adc..e7e1cafd 100644 --- a/lib/src/picture_stream.dart +++ b/lib/src/picture_stream.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' show Picture, Rect, hashValues, Size; +import 'dart:ui' show Picture, Rect, Size; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; @@ -22,26 +22,25 @@ class _PictureListenerPair { } /// Represents information about a ui.Picture to be drawn on a canvas. -@immutable class PictureInfo { /// Creates a new PictureInfo object. - const PictureInfo({ - required this.layerHandle, + PictureInfo({ + required Picture picture, required this.viewport, this.size = Size.infinite, - }) : assert(layerHandle != null), // ignore: unnecessary_null_comparison + }) : assert(picture != null), // ignore: unnecessary_null_comparison assert(viewport != null), // ignore: unnecessary_null_comparison - assert(size != null); // ignore: unnecessary_null_comparison - - /// The [PictureLayer] that holds the [picture]. - final LayerHandle layerHandle; + assert(size != null), // ignore: unnecessary_null_comparison + _picture = picture; /// The raw picture. /// /// This picture's lifecycle will be managed by the provider. It will be /// reused as long as the picture does not change, and disposed when the - /// provider loses all of its listeners or it is unset. - Picture get picture => layerHandle.layer!.picture!; + /// provider loses all of its listeners or it is unset. Once it has been + /// disposed, it will return null. + Picture? get picture => _picture; + Picture? _picture; /// The viewport enclosing the coordinates used in the picture. final Rect viewport; @@ -50,18 +49,18 @@ class PictureInfo { /// [viewport.size]. final Size size; - @override - int get hashCode => hashValues(layerHandle, viewport, size); + /// Creates a [PictureLayer] that will suitably manage the lifecycle of the + /// [picture]. + PictureLayer createLayer() { + return _NonOwningPictureLayer(viewport) + ..picture = picture + ..isComplexHint = true; + } - @override - bool operator ==(Object other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is PictureInfo && - other.layerHandle == layerHandle && - other.viewport == viewport && - other.size == size; + void _dispose() { + assert(_picture != null); + _picture!.dispose(); + _picture = null; } } @@ -210,7 +209,7 @@ abstract class PictureStreamCompleter with Diagnosticable { return; } if (!value && _listeners.isEmpty) { - _current?.layerHandle.layer = null; + _current?._dispose(); _current = null; } _cached = value; @@ -248,7 +247,7 @@ abstract class PictureStreamCompleter with Diagnosticable { (_PictureListenerPair pair) => pair.listener == listener, ); if (_listeners.isEmpty && !cached) { - _current?.layerHandle.layer = null; + _current?._dispose(); _current = null; } } @@ -256,7 +255,7 @@ abstract class PictureStreamCompleter with Diagnosticable { /// Calls all the registered listeners to notify them of a new picture. @protected void setPicture(PictureInfo? picture) { - _current?.layerHandle.layer = null; + _current?._dispose(); _current = picture; if (_listeners.isEmpty) { return; @@ -339,3 +338,19 @@ class OneFramePictureStreamCompleter extends PictureStreamCompleter { }); } } + +class _NonOwningPictureLayer extends PictureLayer { + _NonOwningPictureLayer(Rect canvasBounds) : super(canvasBounds); + + @override + Picture? get picture => _picture; + + Picture? _picture; + + @override + set picture(Picture? picture) { + markNeedsAddToScene(); + // Do not dispose the picture, it's owned by the stream/cache. + _picture = picture; + } +} diff --git a/lib/src/render_picture.dart b/lib/src/render_picture.dart index 4ce5cf08..b37fdcfc 100644 --- a/lib/src/render_picture.dart +++ b/lib/src/render_picture.dart @@ -126,10 +126,11 @@ class RenderPicture extends RenderBox { return; } _picture = val; + _pictureHandle.layer = _picture?.createLayer(); assert(() { - if (_picture != null && _picture!.layerHandle.layer != null) { - assert(_picture!.layerHandle.layer!.isComplexHint == true); - assert(_picture!.layerHandle.layer!.willChangeHint == false); + if (_pictureHandle.layer != null) { + assert(_pictureHandle.layer!.isComplexHint); + assert(!_pictureHandle.layer!.willChangeHint); } return true; }()); @@ -171,8 +172,11 @@ class RenderPicture extends RenderBox { final LayerHandle _clipHandle = LayerHandle(); + final LayerHandle _pictureHandle = LayerHandle(); + void _addPicture(PaintingContext context, Offset offset) { assert(picture != null); + assert(_pictureHandle.layer != null); if (allowDrawingOutsideViewBox != true) { final Rect viewportRect = Offset.zero & _picture!.viewport.size; _clipHandle.layer = context.pushClipRect( @@ -180,13 +184,13 @@ class RenderPicture extends RenderBox { offset, viewportRect, (PaintingContext context, Offset offset) { - context.addLayer(picture!.layerHandle.layer!); + context.addLayer(_pictureHandle.layer!); }, oldLayer: _clipHandle.layer, ); } else { _clipHandle.layer = null; - context.addLayer(picture!.layerHandle.layer!); + context.addLayer(_pictureHandle.layer!); } } diff --git a/lib/svg.dart b/lib/svg.dart index 514d6307..4f9ec2aa 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -56,12 +56,8 @@ class Svg { clipToViewBox: allowDrawingOutsideOfViewBox == true ? false : true, colorFilter: colorFilter, ); - final LayerHandle handle = LayerHandle(); - handle.layer = PictureLayer(svgRoot.viewport.viewBoxRect) - ..picture = pic - ..isComplexHint = true; return PictureInfo( - layerHandle: handle, + picture: pic, viewport: svgRoot.viewport.viewBoxRect, size: svgRoot.viewport.size, ); @@ -90,12 +86,8 @@ class Svg { colorFilter: colorFilter, size: svgRoot.viewport.viewBox, ); - final LayerHandle handle = LayerHandle(); - handle.layer = PictureLayer(svgRoot.viewport.viewBoxRect) - ..picture = pic - ..isComplexHint = true; return PictureInfo( - layerHandle: handle, + picture: pic, viewport: svgRoot.viewport.viewBoxRect, size: svgRoot.viewport.size, ); diff --git a/test/golden_widget/columns_and_rows.png b/test/golden_widget/columns_and_rows.png index b97f0f8049ec67aedf1c1939d20f438687bdf1a4..34053145e281c2d6bf83eb6acc305fd547a1555f 100644 GIT binary patch literal 23184 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 OB;)Do=d#Wzp$Pykcd0!9 literal 2322 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq`R>r;B4q#hkZy4*EI;inw0n-Y8pjADM;h*fhT5Ge5tQW%%&s+iG^8ht@kc07*$kCI*HS z77hl634#g?3=VFig1`V71*0J_8UmvsF!Vye{B0ONLxcMV)6aXWnE(Ht^D|;Ei1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq}in)5S5QV$R#^hFlB^JS>i1|JPr;b;!#`F#VK+(=A+Fc y#K3TbLx6!n!L4D?_+iu`qaiRF0?-iH&a?a?lgM5T7GQnMz~JfX=d#Wzp$PyJc`eoe literal 0 HcmV?d00001 diff --git a/test/picture_stream_test.dart b/test/picture_stream_test.dart index d9629156..51ca1919 100644 --- a/test/picture_stream_test.dart +++ b/test/picture_stream_test.dart @@ -1,38 +1,18 @@ import 'dart:ui'; -import 'package:flutter/rendering.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:test/test.dart'; void main() { - test('PictureInfo Tests', () { + test('Completer disposes layer when removed from cache and no listeners', + () async { final PictureRecorder recorder = PictureRecorder(); final Canvas canvas = Canvas(recorder); canvas.drawPaint(Paint()..color = const Color(0xFFFA0000)); final Picture picture = recorder.endRecording(); - final LayerHandle layer = LayerHandle(); - layer.layer = PictureLayer(Rect.zero)..picture = picture; - final PictureInfo info1 = PictureInfo( - layerHandle: layer, - viewport: Rect.zero, - size: Size.zero, - ); - final PictureInfo info2 = PictureInfo( - layerHandle: layer, - viewport: Rect.zero, - size: Size.zero, - ); - expect(info1.hashCode, equals(info2.hashCode)); - expect(info1, equals(info2)); - }); - - test('Completer disposes layer when removed from cache and no listeners', - () async { - final LayerHandle layer = LayerHandle(); - layer.layer = PictureLayer(Rect.zero); final PictureInfo info = PictureInfo( - layerHandle: layer, + picture: picture, viewport: Rect.zero, size: Size.zero, ); @@ -42,22 +22,25 @@ void main() { await null; // wait an event turn for future to resolve. - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); expect(completer.cached, false); completer.cached = true; - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); completer.cached = false; - expect(layer.layer, null); + expect(info.picture, null); }); test( 'Completer disposes layer when removed from cache and no listeners after having a listener', () async { - final LayerHandle layer = LayerHandle(); - layer.layer = PictureLayer(Rect.zero); + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + canvas.drawPaint(Paint()..color = const Color(0xFFFA0000)); + final Picture picture = recorder.endRecording(); + final PictureInfo info = PictureInfo( - layerHandle: layer, + picture: picture, viewport: Rect.zero, size: Size.zero, ); @@ -67,7 +50,7 @@ void main() { await null; // wait an event turn for future to resolve. - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); expect(completer.cached, false); void _listener(PictureInfo? image, bool syncCall) {} @@ -75,17 +58,20 @@ void main() { completer.cached = true; completer.removeListener(_listener); - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); completer.cached = false; - expect(layer.layer, isNull); + expect(info.picture, isNull); }); test('Completer disposes layer when last listener drops and not in cache', () async { - final LayerHandle layer = LayerHandle(); - layer.layer = PictureLayer(Rect.zero); + final PictureRecorder recorder = PictureRecorder(); + final Canvas canvas = Canvas(recorder); + canvas.drawPaint(Paint()..color = const Color(0xFFFA0000)); + final Picture picture = recorder.endRecording(); + final PictureInfo info = PictureInfo( - layerHandle: layer, + picture: picture, viewport: Rect.zero, size: Size.zero, ); @@ -95,7 +81,7 @@ void main() { await null; // wait an event turn for future to resolve. - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); expect(completer.cached, false); void _listener(PictureInfo? image, bool syncCall) {} @@ -103,8 +89,8 @@ void main() { completer.cached = true; completer.cached = false; - expect(layer.layer, isNotNull); + expect(info.picture, isNotNull); completer.removeListener(_listener); - expect(layer.layer, isNull); + expect(info.picture, isNull); }); } diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index 1468de98..4adfcc05 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -37,7 +37,7 @@ void main() { 'test', theme: const SvgTheme(), ); - final Image image = await info.picture.toImage(2, 2); + final Image image = await info.picture!.toImage(2, 2); final ByteData data = (await image.toByteData())!; const List expected = [ @@ -62,6 +62,6 @@ void main() { theme: const SvgTheme(), ); - expect(info.layerHandle.layer!.isComplexHint, true); + expect(info.createLayer().isComplexHint, true); }); } diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index a258efa5..198d7931 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -10,6 +10,30 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; +class _TolerantComparator extends LocalFileComparator { + _TolerantComparator(Uri testFile) : super(testFile); + + @override + Future compare(Uint8List imageBytes, Uri golden) async { + final ComparisonResult result = await GoldenFileComparator.compareLists( + imageBytes, + await getGoldenBytes(golden), + ); + if (!result.passed) { + final String error = await generateFailureOutput(result, golden, basedir); + if (result.diffPercent >= .06) { + throw FlutterError(error); + } else { + print( + 'Warning - golden differed less than .06% (${result.diffPercent}%), ' + 'ignoring failure but producing output'); + print(error); + } + } + return true; + } +} + Future _checkWidgetAndGolden(Key key, String filename) async { final Finder widgetFinder = find.byKey(key); expect(widgetFinder, findsOneWidget); @@ -20,6 +44,16 @@ void main() { late FakeHttpClientResponse fakeResponse; late FakeHttpClientRequest fakeRequest; late FakeHttpClient fakeHttpClient; + + setUpAll(() { + final LocalFileComparator oldComparator = + goldenFileComparator as LocalFileComparator; + final _TolerantComparator newComparator = _TolerantComparator( + Uri.parse(oldComparator.basedir.toString() + 'test')); + expect(oldComparator.basedir, newComparator.basedir); + goldenFileComparator = newComparator; + }); + setUp(() { PictureProvider.cache.clear(); svg.cacheColorFilterOverride = null; @@ -558,7 +592,7 @@ void main() { await tester.pumpAndSettle(); await _checkWidgetAndGolden(key, 'text_color_filter.png'); - }, skip: !isLinux); + }); testWidgets('Nested SVG elements report a FlutterError', (WidgetTester tester) async { @@ -717,6 +751,27 @@ void main() { await tester.pumpAndSettle(); expect(renderObject.clipBehavior, equals(Clip.antiAlias)); }); + + testWidgets('SvgPicture - two of the same', (WidgetTester tester) async { + // Regression test to make sure the same SVG can render twice in the same + // view. If layers are incorrectly reused, this will fail. + await tester.pumpWidget(RepaintBoundary( + child: Directionality( + textDirection: TextDirection.ltr, + child: Row( + children: [ + SvgPicture.string(simpleSvg), + SvgPicture.string(simpleSvg), + ], + ), + ))); + await tester.pumpAndSettle(); + + await expectLater( + find.byType(RepaintBoundary), + matchesGoldenFile('golden_widget/two_of_same.png'), + ); + }); } class FakeAssetBundle extends Fake implements AssetBundle { @@ -788,29 +843,37 @@ class FakeHttpClientResponse extends Fake implements HttpClientResponse { } } -const String svgStr = - ''' - - - - - - - - - - - - - - - - - - -'''; +const String simpleSvg = ''' + + + +'''; + +const String svgStr = ''' + + + + + + + + + + + + + + + + + + + + +'''; -const String stickFigureSvgStr = ''' +const String stickFigureSvgStr = ''' + svg/stick_figure @@ -827,6 +890,7 @@ const String stickFigureSvgStr = ''' -'''; + +'''; final Uint8List svgBytes = utf8.encode(svgStr) as Uint8List; From 0974e60330522b2c65d774e3bdb73cc4e8521482 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 15 Oct 2021 21:11:31 -0700 Subject: [PATCH 030/142] Make new painting method opt in to allow migration --- lib/src/render_picture.dart | 70 ++++++++++++++++++++++++++- lib/src/unbounded_color_filtered.dart | 54 +++++++++++++++++++++ lib/svg.dart | 29 +++++++++-- 3 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 lib/src/unbounded_color_filtered.dart diff --git a/lib/src/render_picture.dart b/lib/src/render_picture.dart index b37fdcfc..c12d3903 100644 --- a/lib/src/render_picture.dart +++ b/lib/src/render_picture.dart @@ -14,8 +14,17 @@ class RawPicture extends LeafRenderObjectWidget { Key? key, this.matchTextDirection = false, this.allowDrawingOutsideViewBox = false, + this.useLegacyPaint = true, }) : super(key: key); + /// Whether to use a less efficient, but completely visually compatible, + /// method of painting the picture. + /// + /// This flag is intended to assist clients with migration to the layer based + /// painting method. Once all known clients have been migrated, it will be + /// deprecated and become a no-op. + final bool useLegacyPaint; + /// The picture to paint. final PictureInfo? picture; @@ -34,11 +43,13 @@ class RawPicture extends LeafRenderObjectWidget { matchTextDirection: matchTextDirection, textDirection: matchTextDirection ? Directionality.of(context) : null, allowDrawingOutsideViewBox: allowDrawingOutsideViewBox, + useLegacyPaint: useLegacyPaint, ); } @override void updateRenderObject(BuildContext context, RenderPicture renderObject) { + assert(renderObject.useLegacyPaint == useLegacyPaint); renderObject ..picture = picture ..matchTextDirection = matchTextDirection @@ -64,12 +75,21 @@ class RenderPicture extends RenderBox { bool matchTextDirection = false, TextDirection? textDirection, bool? allowDrawingOutsideViewBox, + this.useLegacyPaint = true, }) : _matchTextDirection = matchTextDirection, _textDirection = textDirection, _allowDrawingOutsideViewBox = allowDrawingOutsideViewBox { this.picture = picture; } + /// Whether to use a less efficient, but completely visually compatible, + /// method of painting the picture. + /// + /// This flag is intended to assist clients with migration to the layer based + /// painting method. Once all known clients have been migrated, it will be + /// deprecated and become a no-op. + final bool useLegacyPaint; + /// Optional color to use to draw a thin rectangle around the canvas. /// /// Only applied if asserts are enabled (e.g. debug mode). @@ -165,7 +185,7 @@ class RenderPicture extends RenderBox { } @override - bool get isRepaintBoundary => true; + bool get isRepaintBoundary => !useLegacyPaint; final LayerHandle _transformHandle = LayerHandle(); @@ -197,11 +217,59 @@ class RenderPicture extends RenderBox { @override void dispose() { _transformHandle.layer = null; + _pictureHandle.layer = null; + _clipHandle.layer = null; super.dispose(); } + void _legacyPaintif(PaintingContext context, Offset offset) { + if (picture == null || picture!.picture == null || size == Size.zero) { + return; + } + context.canvas.save(); + context.canvas.translate(offset.dx, offset.dy); + if (_flipHorizontally) { + context.canvas.translate(size.width, 0.0); + context.canvas.scale(-1.0, 1.0); + } + + // this is sometimes useful for debugging, e.g. to draw + // a thin red border around the drawing. + assert(() { + if (RenderPicture.debugRectColor != null && + RenderPicture.debugRectColor!.alpha > 0) { + context.canvas.drawRect( + Offset.zero & size, + Paint() + ..color = debugRectColor! + ..style = PaintingStyle.stroke); + } + return true; + }()); + final Matrix4 transform = Matrix4.identity(); + if (scaleCanvasToViewBox( + transform, + size, + _picture!.viewport, + _picture!.size, + )) { + context.canvas.transform(transform.storage); + } + final Rect viewportRect = Offset.zero & _picture!.viewport.size; + if (allowDrawingOutsideViewBox != true) { + context.canvas.clipRect(viewportRect); + } + context.canvas.drawPicture(picture!.picture!); + context.canvas.restore(); + } + @override void paint(PaintingContext context, Offset offset) { + if (useLegacyPaint) { + _legacyPaintif(context, offset); + return; + } + if (picture == null || size == Size.zero) { return; } diff --git a/lib/src/unbounded_color_filtered.dart b/lib/src/unbounded_color_filtered.dart new file mode 100644 index 00000000..1787897f --- /dev/null +++ b/lib/src/unbounded_color_filtered.dart @@ -0,0 +1,54 @@ +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +/// Supports SvgPicture - not meant for public use, visible for testing. +@visibleForTesting +class UnboundedColorFiltered extends SingleChildRenderObjectWidget { + /// Supports SvgPicture - not meant for public use, visible for testing. + const UnboundedColorFiltered({ + Key? key, + required this.colorFilter, + required Widget child, + }) : super(key: key, child: child); + + /// The color filter to apply. + final ColorFilter? colorFilter; + + @override + _UnboundedColorFilteredRenderBox createRenderObject(BuildContext context) => + _UnboundedColorFilteredRenderBox(colorFilter); + + @override + void updateRenderObject( + BuildContext context, + covariant _UnboundedColorFilteredRenderBox renderObject, + ) { + renderObject.colorFilter = colorFilter; + } +} + +class _UnboundedColorFilteredRenderBox extends RenderProxyBox { + _UnboundedColorFilteredRenderBox( + this._colorFilter, + ); + + ColorFilter? _colorFilter; + ColorFilter? get colorFilter => _colorFilter; + set colorFilter(ColorFilter? value) { + if (value == _colorFilter) { + return; + } + _colorFilter = value; + markNeedsPaint(); + } + + @override + void paint(PaintingContext context, Offset offset) { + final Paint paint = Paint()..colorFilter = colorFilter; + context.canvas.saveLayer(offset & size, paint); + if (child != null) { + context.paintChild(child!, offset); + } + context.canvas.restore(); + } +} diff --git a/lib/svg.dart b/lib/svg.dart index 4f9ec2aa..98cabccd 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -14,6 +14,7 @@ import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; import 'src/render_picture.dart'; import 'src/svg/theme.dart'; +import 'src/unbounded_color_filtered.dart'; import 'src/vector_drawable.dart'; /// Instance for [Svg]'s utility methods, which can produce a [DrawableRoot] @@ -236,6 +237,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : super(key: key); /// Instantiates a widget that renders an SVG picture from an [AssetBundle]. @@ -337,6 +339,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : pictureProvider = ExactAssetPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -401,6 +404,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : pictureProvider = NetworkPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -461,6 +465,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : pictureProvider = FilePicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -517,6 +522,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : pictureProvider = MemoryPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -573,6 +579,7 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, + this.useLegacyPaint = true, }) : pictureProvider = StringPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -585,6 +592,14 @@ class SvgPicture extends StatefulWidget { colorFilter = _getColorFilter(color, colorBlendMode), super(key: key); + /// Whether to use a less efficient, but completely visually compatible, + /// method of painting the picture. + /// + /// This flag is intended to assist clients with migration to the layer based + /// painting method. Once all known clients have been migrated, it will be + /// deprecated and become a no-op. + final bool useLegacyPaint; + /// The default placeholder for a SVG that may take time to parse or /// retrieve, e.g. from a network location. static WidgetBuilder defaultPlaceholderBuilder = @@ -853,6 +868,7 @@ class _SvgPictureState extends State { _picture, matchTextDirection: widget.matchTextDirection, allowDrawingOutsideViewBox: widget.allowDrawingOutsideViewBox, + useLegacyPaint: widget.useLegacyPaint, ), ), ), @@ -860,10 +876,15 @@ class _SvgPictureState extends State { if (widget.pictureProvider.colorFilter == null && widget.colorFilter != null) { - child = ColorFiltered( - colorFilter: widget.colorFilter!, - child: child, - ); + child = widget.useLegacyPaint + ? UnboundedColorFiltered( + colorFilter: widget.colorFilter, + child: child, + ) + : ColorFiltered( + colorFilter: widget.colorFilter!, + child: child, + ); } } else { child = widget.placeholderBuilder == null From fbe927893187af4afadb5bd38bc847bae9b5dea6 Mon Sep 17 00:00:00 2001 From: Sarbagya Dhaubanjar Date: Thu, 28 Oct 2021 22:41:42 +0545 Subject: [PATCH 031/142] Conditionally import `File` from `dart:io` (#613) * added conditional `File` * replaced usage of `dart:io` with conditional file --- lib/src/picture_provider.dart | 2 +- lib/src/utilities/_file_io.dart | 1 + lib/src/utilities/_file_none.dart | 13 +++++++++++++ lib/src/utilities/file.dart | 1 + lib/svg.dart | 4 ++-- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 lib/src/utilities/_file_io.dart create mode 100644 lib/src/utilities/_file_none.dart create mode 100644 lib/src/utilities/file.dart diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 503d6c3f..13e650fe 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:io'; import 'dart:typed_data'; import 'dart:ui' show BlendMode, Color, ColorFilter, Locale, Rect, TextDirection, hashValues; @@ -15,6 +14,7 @@ import 'package:flutter/widgets.dart' import 'picture_cache.dart'; import 'picture_stream.dart'; +import 'utilities/file.dart'; import 'utilities/http.dart'; /// The signature of a function that can decode raw SVG data into a [Picture]. diff --git a/lib/src/utilities/_file_io.dart b/lib/src/utilities/_file_io.dart new file mode 100644 index 00000000..3da0f6ad --- /dev/null +++ b/lib/src/utilities/_file_io.dart @@ -0,0 +1 @@ +export 'dart:io' show File; diff --git a/lib/src/utilities/_file_none.dart b/lib/src/utilities/_file_none.dart new file mode 100644 index 00000000..595e0f8d --- /dev/null +++ b/lib/src/utilities/_file_none.dart @@ -0,0 +1,13 @@ +import 'dart:typed_data'; + +/// Fake File for Web +abstract class File { + /// Get the path of the file. + String get path; + + /// Reads the entire file contents as a list of bytes. + /// + /// Returns a `Future` that completes with the list of bytes that + /// is the contents of the file. + Future readAsBytes(); +} diff --git a/lib/src/utilities/file.dart b/lib/src/utilities/file.dart new file mode 100644 index 00000000..e469e274 --- /dev/null +++ b/lib/src/utilities/file.dart @@ -0,0 +1 @@ +export '_file_io.dart' if (dart.library.html) '_file_none.dart'; diff --git a/lib/svg.dart b/lib/svg.dart index 98cabccd..f8b179fa 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -1,20 +1,20 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:io' show File; import 'dart:typed_data'; import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_svg/src/svg/default_theme.dart'; import 'parser.dart'; import 'src/picture_provider.dart'; import 'src/picture_stream.dart'; import 'src/render_picture.dart'; +import 'src/svg/default_theme.dart'; import 'src/svg/theme.dart'; import 'src/unbounded_color_filtered.dart'; +import 'src/utilities/file.dart'; import 'src/vector_drawable.dart'; /// Instance for [Svg]'s utility methods, which can produce a [DrawableRoot] From 01f99740d463aeba415b2b189ddfa885b410a7ae Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 3 Nov 2021 17:03:55 -0700 Subject: [PATCH 032/142] Remove difficult to use flag --- lib/src/render_picture.dart | 70 +-------------------------- lib/src/unbounded_color_filtered.dart | 54 --------------------- lib/svg.dart | 29 ++--------- 3 files changed, 5 insertions(+), 148 deletions(-) delete mode 100644 lib/src/unbounded_color_filtered.dart diff --git a/lib/src/render_picture.dart b/lib/src/render_picture.dart index c12d3903..b37fdcfc 100644 --- a/lib/src/render_picture.dart +++ b/lib/src/render_picture.dart @@ -14,17 +14,8 @@ class RawPicture extends LeafRenderObjectWidget { Key? key, this.matchTextDirection = false, this.allowDrawingOutsideViewBox = false, - this.useLegacyPaint = true, }) : super(key: key); - /// Whether to use a less efficient, but completely visually compatible, - /// method of painting the picture. - /// - /// This flag is intended to assist clients with migration to the layer based - /// painting method. Once all known clients have been migrated, it will be - /// deprecated and become a no-op. - final bool useLegacyPaint; - /// The picture to paint. final PictureInfo? picture; @@ -43,13 +34,11 @@ class RawPicture extends LeafRenderObjectWidget { matchTextDirection: matchTextDirection, textDirection: matchTextDirection ? Directionality.of(context) : null, allowDrawingOutsideViewBox: allowDrawingOutsideViewBox, - useLegacyPaint: useLegacyPaint, ); } @override void updateRenderObject(BuildContext context, RenderPicture renderObject) { - assert(renderObject.useLegacyPaint == useLegacyPaint); renderObject ..picture = picture ..matchTextDirection = matchTextDirection @@ -75,21 +64,12 @@ class RenderPicture extends RenderBox { bool matchTextDirection = false, TextDirection? textDirection, bool? allowDrawingOutsideViewBox, - this.useLegacyPaint = true, }) : _matchTextDirection = matchTextDirection, _textDirection = textDirection, _allowDrawingOutsideViewBox = allowDrawingOutsideViewBox { this.picture = picture; } - /// Whether to use a less efficient, but completely visually compatible, - /// method of painting the picture. - /// - /// This flag is intended to assist clients with migration to the layer based - /// painting method. Once all known clients have been migrated, it will be - /// deprecated and become a no-op. - final bool useLegacyPaint; - /// Optional color to use to draw a thin rectangle around the canvas. /// /// Only applied if asserts are enabled (e.g. debug mode). @@ -185,7 +165,7 @@ class RenderPicture extends RenderBox { } @override - bool get isRepaintBoundary => !useLegacyPaint; + bool get isRepaintBoundary => true; final LayerHandle _transformHandle = LayerHandle(); @@ -217,59 +197,11 @@ class RenderPicture extends RenderBox { @override void dispose() { _transformHandle.layer = null; - _pictureHandle.layer = null; - _clipHandle.layer = null; super.dispose(); } - void _legacyPaintif(PaintingContext context, Offset offset) { - if (picture == null || picture!.picture == null || size == Size.zero) { - return; - } - context.canvas.save(); - context.canvas.translate(offset.dx, offset.dy); - if (_flipHorizontally) { - context.canvas.translate(size.width, 0.0); - context.canvas.scale(-1.0, 1.0); - } - - // this is sometimes useful for debugging, e.g. to draw - // a thin red border around the drawing. - assert(() { - if (RenderPicture.debugRectColor != null && - RenderPicture.debugRectColor!.alpha > 0) { - context.canvas.drawRect( - Offset.zero & size, - Paint() - ..color = debugRectColor! - ..style = PaintingStyle.stroke); - } - return true; - }()); - final Matrix4 transform = Matrix4.identity(); - if (scaleCanvasToViewBox( - transform, - size, - _picture!.viewport, - _picture!.size, - )) { - context.canvas.transform(transform.storage); - } - final Rect viewportRect = Offset.zero & _picture!.viewport.size; - if (allowDrawingOutsideViewBox != true) { - context.canvas.clipRect(viewportRect); - } - context.canvas.drawPicture(picture!.picture!); - context.canvas.restore(); - } - @override void paint(PaintingContext context, Offset offset) { - if (useLegacyPaint) { - _legacyPaintif(context, offset); - return; - } - if (picture == null || size == Size.zero) { return; } diff --git a/lib/src/unbounded_color_filtered.dart b/lib/src/unbounded_color_filtered.dart deleted file mode 100644 index 1787897f..00000000 --- a/lib/src/unbounded_color_filtered.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart'; - -/// Supports SvgPicture - not meant for public use, visible for testing. -@visibleForTesting -class UnboundedColorFiltered extends SingleChildRenderObjectWidget { - /// Supports SvgPicture - not meant for public use, visible for testing. - const UnboundedColorFiltered({ - Key? key, - required this.colorFilter, - required Widget child, - }) : super(key: key, child: child); - - /// The color filter to apply. - final ColorFilter? colorFilter; - - @override - _UnboundedColorFilteredRenderBox createRenderObject(BuildContext context) => - _UnboundedColorFilteredRenderBox(colorFilter); - - @override - void updateRenderObject( - BuildContext context, - covariant _UnboundedColorFilteredRenderBox renderObject, - ) { - renderObject.colorFilter = colorFilter; - } -} - -class _UnboundedColorFilteredRenderBox extends RenderProxyBox { - _UnboundedColorFilteredRenderBox( - this._colorFilter, - ); - - ColorFilter? _colorFilter; - ColorFilter? get colorFilter => _colorFilter; - set colorFilter(ColorFilter? value) { - if (value == _colorFilter) { - return; - } - _colorFilter = value; - markNeedsPaint(); - } - - @override - void paint(PaintingContext context, Offset offset) { - final Paint paint = Paint()..colorFilter = colorFilter; - context.canvas.saveLayer(offset & size, paint); - if (child != null) { - context.paintChild(child!, offset); - } - context.canvas.restore(); - } -} diff --git a/lib/svg.dart b/lib/svg.dart index f8b179fa..ec1d11a9 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -13,7 +13,6 @@ import 'src/picture_stream.dart'; import 'src/render_picture.dart'; import 'src/svg/default_theme.dart'; import 'src/svg/theme.dart'; -import 'src/unbounded_color_filtered.dart'; import 'src/utilities/file.dart'; import 'src/vector_drawable.dart'; @@ -237,7 +236,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : super(key: key); /// Instantiates a widget that renders an SVG picture from an [AssetBundle]. @@ -339,7 +337,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : pictureProvider = ExactAssetPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -404,7 +401,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : pictureProvider = NetworkPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -465,7 +461,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : pictureProvider = FilePicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -522,7 +517,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : pictureProvider = MemoryPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -579,7 +573,6 @@ class SvgPicture extends StatefulWidget { this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, this.currentColor, - this.useLegacyPaint = true, }) : pictureProvider = StringPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -592,14 +585,6 @@ class SvgPicture extends StatefulWidget { colorFilter = _getColorFilter(color, colorBlendMode), super(key: key); - /// Whether to use a less efficient, but completely visually compatible, - /// method of painting the picture. - /// - /// This flag is intended to assist clients with migration to the layer based - /// painting method. Once all known clients have been migrated, it will be - /// deprecated and become a no-op. - final bool useLegacyPaint; - /// The default placeholder for a SVG that may take time to parse or /// retrieve, e.g. from a network location. static WidgetBuilder defaultPlaceholderBuilder = @@ -868,7 +853,6 @@ class _SvgPictureState extends State { _picture, matchTextDirection: widget.matchTextDirection, allowDrawingOutsideViewBox: widget.allowDrawingOutsideViewBox, - useLegacyPaint: widget.useLegacyPaint, ), ), ), @@ -876,15 +860,10 @@ class _SvgPictureState extends State { if (widget.pictureProvider.colorFilter == null && widget.colorFilter != null) { - child = widget.useLegacyPaint - ? UnboundedColorFiltered( - colorFilter: widget.colorFilter, - child: child, - ) - : ColorFiltered( - colorFilter: widget.colorFilter!, - child: child, - ); + child = ColorFiltered( + colorFilter: widget.colorFilter!, + child: child, + ); } } else { child = widget.placeholderBuilder == null From 17507b8ef15c4413af14f7c44ef02e116599ae6e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 3 Nov 2021 17:04:56 -0700 Subject: [PATCH 033/142] version bumps --- CHANGELOG.md | 7 +++++++ pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0137c0ab..75dcdadd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGES +## 1.0.0 + +- New widget/RenderObject implementation to avoid rebuilds/paints when + near or overlapping an animating widget. Also should improve raster + cacheability. +- Correctly list web as a supported platform. + ## 0.23.0+1 - Missing commit that reduced breakages introduced in 0.23.0 diff --git a/pubspec.yaml b/pubspec.yaml index fdb963fa..465f037a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 0.23.0+1 +version: 1.0.0 dependencies: flutter: From f225dfc3f0481583f07186d146b8db5f24294b4f Mon Sep 17 00:00:00 2001 From: Dan Field Date: Sun, 7 Nov 2021 20:39:44 -0800 Subject: [PATCH 034/142] Fix issues with hashing mutable objects --- analysis_options.yaml | 1 + lib/src/picture_cache.dart | 5 + lib/src/picture_provider.dart | 378 ++++++++++++++++---------------- lib/src/svg/theme.dart | 3 + test/picture_provider_test.dart | 15 ++ 5 files changed, 212 insertions(+), 190 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 07d880c9..5863ac2b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -50,6 +50,7 @@ linter: # - avoid_catching_errors # we do this commonly - avoid_classes_with_only_static_members # - avoid_double_and_int_checks # only useful when targeting JS runtime + - avoid_equals_and_hash_code_on_mutable_classes - avoid_empty_else - avoid_field_initializers_in_const_classes - avoid_function_literals_in_foreach_calls diff --git a/lib/src/picture_cache.dart b/lib/src/picture_cache.dart index 239cf9a4..93c6cda3 100644 --- a/lib/src/picture_cache.dart +++ b/lib/src/picture_cache.dart @@ -50,6 +50,11 @@ class PictureCache { _cache.clear(); } + /// Evicts a single entry from the cache, returning true if successful. + bool evict(Object key) { + return _cache.remove(key) != null; + } + /// Returns the previously cached [PictureStream] for the given key, if available; /// if not, calls the given callback to obtain it first. In either case, the /// key is moved to the "most recently used" position. diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 13e650fe..8e9424ed 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -14,6 +14,7 @@ import 'package:flutter/widgets.dart' import 'picture_cache.dart'; import 'picture_stream.dart'; +import 'svg/theme.dart'; import 'utilities/file.dart'; import 'utilities/http.dart'; @@ -302,10 +303,18 @@ class PictureConfiguration { /// } /// ``` @optionalTypeArgs -abstract class PictureProvider { +abstract class PictureProvider { /// Abstract const constructor. This constructor enables subclasses to provide /// const constructors so that they can be used in const expressions. - PictureProvider(this.colorFilter); + PictureProvider(this.colorFilter, {required this.decoderBuilder}) + : decoder = decoderBuilder(null); + + /// The decoder builder to build a [decoder] when [currentColor] changes. + final PictureInfoDecoderBuilder decoderBuilder; + + /// The [PictureInfoDecoder] to use for loading this picture. + @visibleForTesting + PictureInfoDecoder decoder; /// The [PictureCache] for [Picture] objects created by [PictureProvider] /// implementations. @@ -328,7 +337,19 @@ abstract class PictureProvider { Color? _currentColor; /// Sets the [_currentColor] to [color]. - set currentColor(Color? color); + set currentColor(Color? color) { + if (_currentColor == color) { + return; + } + decoder = decoderBuilder(color); + _currentColor = color; + if (_lastKey != null) { + cache.evict(_lastKey!); + _lastKey = null; + } + } + + T? _lastKey; /// Resolves this Picture provider using the given `configuration`, returning /// an [PictureStream]. @@ -342,10 +363,9 @@ abstract class PictureProvider { // ignore: unnecessary_null_comparison assert(picture != null); final PictureStream stream = PictureStream(); - T? obtainedKey; obtainKey(picture).then( (T key) { - obtainedKey = key; + _lastKey = key; stream.setCompleter( cache.putIfAbsent( key!, @@ -367,7 +387,7 @@ abstract class PictureProvider { informationCollector: () sync* { yield DiagnosticsProperty( 'Picture provider', this); - yield DiagnosticsProperty('Picture key', obtainedKey, + yield DiagnosticsProperty('Picture key', _lastKey, defaultValue: null); })); }); @@ -394,18 +414,65 @@ abstract class PictureProvider { String toString() => '$runtimeType()'; } +/// An immutable key representing the current state of a [PictureProvider]. +@immutable +class PictureKey { + /// Creates a new immutable key reprenseting the current state of a + /// [PictureProvider] for the [PictureCache]. + const PictureKey( + this.keyData, { + required this.colorFilter, + required this.theme, + }); + + /// Some unique identifier for the source of this picture, e.g. a file name or + /// URL. + /// + /// If this is an iterable, it is assumed that the iterable will not be + /// modified after creating this object. + final T keyData; + + /// The color filter applied when this key was created. + final ColorFilter? colorFilter; + + /// The theme used when this key was created. + final SvgTheme theme; + + @override + bool operator ==(dynamic other) { + if (other.runtimeType != runtimeType) { + return false; + } + return other is PictureKey && + keyData == other.keyData && + colorFilter == other.colorFilter && + theme == other.theme; + } + + @override + int get hashCode => hashValues(keyData.hashCode, colorFilter, theme); + + @override + String toString() => + 'PictureKey($keyData, colorFilter: $colorFilter, theme: $theme)'; +} + /// Key for the picture obtained by an [AssetPicture] or [ExactAssetPicture]. /// /// This is used to identify the precise resource in the [pictureCache]. @immutable -class AssetBundlePictureKey { +class AssetBundlePictureKey extends PictureKey { /// Creates the key for an [AssetPicture] or [AssetBundlePictureProvider]. /// /// The arguments must not be null. - const AssetBundlePictureKey( - {required this.bundle, required this.name, this.colorFilter}) - : assert(bundle != null), // ignore: unnecessary_null_comparison - assert(name != null); // ignore: unnecessary_null_comparison + const AssetBundlePictureKey({ + required this.bundle, + required String name, + ColorFilter? colorFilter, + required SvgTheme theme, + }) : assert(bundle != null), // ignore: unnecessary_null_comparison + assert(name != null), // ignore: unnecessary_null_comparison + super(name, colorFilter: colorFilter, theme: theme); /// The bundle from which the picture will be obtained. /// @@ -415,10 +482,7 @@ class AssetBundlePictureKey { /// The key to use to obtain the resource from the [bundle]. This is the /// argument passed to [AssetBundle.load]. - final String name; - - /// The [ColorFilter], if any, to be applied to the drawing. - final ColorFilter? colorFilter; + String get name => keyData; @override bool operator ==(dynamic other) { @@ -428,15 +492,16 @@ class AssetBundlePictureKey { return other is AssetBundlePictureKey && bundle == other.bundle && name == other.name && - colorFilter == other.colorFilter; + colorFilter == other.colorFilter && + theme == other.theme; } @override - int get hashCode => hashValues(bundle, name, colorFilter); + int get hashCode => hashValues(bundle, name, colorFilter, theme); @override String toString() => - '$runtimeType(bundle: $bundle, name: "$name", colorFilter: $colorFilter)'; + '$runtimeType(bundle: $bundle, name: "$name", colorFilter: $colorFilter, theme: $theme)'; } /// A subclass of [PictureProvider] that knows about [AssetBundle]s. @@ -444,26 +509,13 @@ class AssetBundlePictureKey { /// This factors out the common logic of [AssetBundle]-based [PictureProvider] /// classes, simplifying what subclasses must implement to just [obtainKey]. abstract class AssetBundlePictureProvider - extends PictureProvider { + extends PictureProvider { /// Abstract const constructor. This constructor enables subclasses to provide /// const constructors so that they can be used in const expressions. - AssetBundlePictureProvider(this.decoderBuilder, ColorFilter? colorFilter) + AssetBundlePictureProvider(PictureInfoDecoderBuilder decoderBuilder, + ColorFilter? colorFilter) : assert(decoderBuilder != null), // ignore: unnecessary_null_comparison - decoder = decoderBuilder(null), - super(colorFilter); - - /// The decoder builder to build a [decoder] when [currentColor] changes. - final PictureInfoDecoderBuilder decoderBuilder; - - /// The decoder to use to turn a string into a [PictureInfo] object. - @visibleForTesting - PictureInfoDecoder decoder; - - @override - set currentColor(Color? color) { - _currentColor = color; - decoder = decoderBuilder(_currentColor); - } + super(colorFilter, decoderBuilder: decoderBuilder); /// Converts a key into an [PictureStreamCompleter], and begins fetching the /// picture using [_loadAsync]. @@ -499,6 +551,32 @@ abstract class AssetBundlePictureProvider } } +/// The [PictureKey.keyData] for a [NetworkPicture]. +@immutable +class NetworkPictureKeyData { + /// Creates [PictureKey.keyData] for a [NetworkPicture]. + const NetworkPictureKeyData({required this.url, required this.headers}); + + /// The URL to request. + final String url; + + /// The headers include in the GET request to [url]. + final Map? headers; + + @override + bool operator ==(dynamic other) { + if (other.runtimeType != runtimeType) { + return false; + } + return other is NetworkPictureKeyData && + other.url == url && + other.headers == headers; + } + + @override + int get hashCode => hashValues(url, headers); +} + /// Fetches the given URL from the network, associating it with the given scale. /// /// The picture will be cached regardless of cache headers from the server. @@ -509,22 +587,15 @@ abstract class AssetBundlePictureProvider // TODO(ianh): Find some way to honour cache headers to the extent that when the // last reference to a picture is released, we proactively evict the picture from // our cache if the headers describe the picture as having expired at that point. -class NetworkPicture extends PictureProvider { +class NetworkPicture + extends PictureProvider, Uint8List> { /// Creates an object that fetches the picture at the given URL. /// /// The arguments must not be null. - NetworkPicture(this.decoderBuilder, this.url, + NetworkPicture(PictureInfoDecoderBuilder decoderBuilder, this.url, {this.headers, ColorFilter? colorFilter}) : assert(url != null), // ignore: unnecessary_null_comparison - decoder = decoderBuilder(null), - super(colorFilter); - - /// The decoder builder to build a [decoder] when [currentColor] changes. - final PictureInfoDecoderBuilder decoderBuilder; - - /// The decoder to use to turn a [Uint8List] into a [PictureInfo] object. - @visibleForTesting - PictureInfoDecoder decoder; + super(colorFilter, decoderBuilder: decoderBuilder); /// The URL from which the picture will be fetched. final String url; @@ -533,29 +604,36 @@ class NetworkPicture extends PictureProvider { final Map? headers; @override - set currentColor(Color? color) { - _currentColor = color; - decoder = decoderBuilder(_currentColor); - } - - @override - Future obtainKey(PictureConfiguration picture) { - return SynchronousFuture(this); + Future> obtainKey( + PictureConfiguration picture) { + return SynchronousFuture>( + PictureKey( + NetworkPictureKeyData(url: url, headers: headers), + colorFilter: colorFilter, + theme: SvgTheme( + currentColor: currentColor, + ), + ), + ); } @override - PictureStreamCompleter load(NetworkPicture key, + PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError), informationCollector: () sync* { yield DiagnosticsProperty('Picture provider', this); - yield DiagnosticsProperty('Picture key', key); + yield DiagnosticsProperty>( + 'Picture key', + key, + ); }); } - Future _loadAsync(NetworkPicture key, + Future _loadAsync(PictureKey key, {PictureErrorListener? onError}) async { - assert(key == this); + assert(url == key.keyData.url); + assert(headers == key.keyData.headers); final Uint8List bytes = await httpGet(url, headers: headers); if (onError != null) { @@ -571,19 +649,6 @@ class NetworkPicture extends PictureProvider { return decoder(bytes, colorFilter, key.toString()); } - @override - bool operator ==(dynamic other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is NetworkPicture && - url == other.url && - colorFilter == other.colorFilter; - } - - @override - int get hashCode => hashValues(url.hashCode, colorFilter); - @override String toString() => '$runtimeType("$url", headers: $headers, colorFilter: $colorFilter)'; @@ -595,39 +660,34 @@ class NetworkPicture extends PictureProvider { /// See also: /// /// * [SvgPicture.file] for a shorthand of an [SvgPicture] widget backed by [FilePicture]. -class FilePicture extends PictureProvider { +class FilePicture extends PictureProvider, Uint8List> { /// Creates an object that decodes a [File] as a picture. /// /// The arguments must not be null. - FilePicture(this.decoderBuilder, this.file, {ColorFilter? colorFilter}) + FilePicture(PictureInfoDecoderBuilder decoderBuilder, this.file, + {ColorFilter? colorFilter}) : assert(decoderBuilder != null), // ignore: unnecessary_null_comparison assert(file != null), // ignore: unnecessary_null_comparison - decoder = decoderBuilder(null), - super(colorFilter); + super(colorFilter, decoderBuilder: decoderBuilder); /// The file to decode into a picture. final File file; - /// The decoder builder to build a [decoder] when [currentColor] changes. - final PictureInfoDecoderBuilder decoderBuilder; - - /// The [PictureInfoDecoder] to use for loading this picture. - @visibleForTesting - PictureInfoDecoder decoder; - - @override - set currentColor(Color? color) { - _currentColor = color; - decoder = decoderBuilder(_currentColor); - } - @override - Future obtainKey(PictureConfiguration picture) { - return SynchronousFuture(this); + Future> obtainKey(PictureConfiguration picture) { + return SynchronousFuture>( + PictureKey( + file.path, + colorFilter: colorFilter, + theme: SvgTheme( + currentColor: currentColor, + ), + ), + ); } @override - PictureStreamCompleter load(FilePicture key, + PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError), informationCollector: () sync* { @@ -635,9 +695,9 @@ class FilePicture extends PictureProvider { }); } - Future _loadAsync(FilePicture key, + Future _loadAsync(PictureKey key, {PictureErrorListener? onError}) async { - assert(key == this); + assert(key.keyData == file.path); final Uint8List data = await file.readAsBytes(); if (data.isEmpty) { @@ -656,19 +716,6 @@ class FilePicture extends PictureProvider { return decoder(data, colorFilter, key.toString()); } - @override - bool operator ==(dynamic other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is FilePicture && - file.path == other.file.path && - other.colorFilter == colorFilter; - } - - @override - int get hashCode => hashValues(file.path.hashCode, colorFilter); - @override String toString() => '$runtimeType("${file.path}", colorFilter: $colorFilter)'; @@ -686,45 +733,40 @@ class FilePicture extends PictureProvider { /// See also: /// /// * [SvgPicture.memory] for a shorthand of an [SvgPicture] widget backed by [MemoryPicture]. -class MemoryPicture extends PictureProvider { +class MemoryPicture extends PictureProvider, Uint8List> { /// Creates an object that decodes a [Uint8List] buffer as a picture. /// /// The arguments must not be null. - MemoryPicture(this.decoderBuilder, this.bytes, {ColorFilter? colorFilter}) + MemoryPicture(PictureInfoDecoderBuilder decoderBuilder, this.bytes, + {ColorFilter? colorFilter}) : assert(bytes != null), // ignore: unnecessary_null_comparison - decoder = decoderBuilder(null), - super(colorFilter); - - /// The decoder builder to build a [decoder] when [currentColor] changes. - final PictureInfoDecoderBuilder decoderBuilder; - - /// The [PictureInfoDecoder] to use when drawing this picture. - @visibleForTesting - PictureInfoDecoder decoder; + super(colorFilter, decoderBuilder: decoderBuilder); /// The bytes to decode into a picture. final Uint8List bytes; @override - set currentColor(Color? color) { - _currentColor = color; - decoder = decoderBuilder(_currentColor); - } - - @override - Future obtainKey(PictureConfiguration picture) { - return SynchronousFuture(this); + Future> obtainKey(PictureConfiguration picture) { + return SynchronousFuture>( + PictureKey( + bytes, + colorFilter: colorFilter, + theme: SvgTheme( + currentColor: currentColor, + ), + ), + ); } @override - PictureStreamCompleter load(MemoryPicture key, + PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError)); } - Future _loadAsync(MemoryPicture key, + Future _loadAsync(PictureKey key, {PictureErrorListener? onError}) async { - assert(key == this); + assert(key.keyData == bytes); if (onError != null) { return decoder( bytes, @@ -738,19 +780,6 @@ class MemoryPicture extends PictureProvider { return decoder(bytes, colorFilter, key.toString()); } - @override - bool operator ==(dynamic other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is MemoryPicture && - bytes == other.bytes && - colorFilter == other.colorFilter; - } - - @override - int get hashCode => hashValues(bytes.hashCode, colorFilter); - @override String toString() => '$runtimeType(${describeIdentity(bytes)})'; } @@ -767,47 +796,42 @@ class MemoryPicture extends PictureProvider { /// See also: /// /// * [SvgPicture.string] for a shorthand of an [SvgPicture] widget backed by [StringPicture]. -class StringPicture extends PictureProvider { +class StringPicture extends PictureProvider, String> { /// Creates an object that decodes a [Uint8List] buffer as a picture. /// /// The arguments must not be null. - StringPicture(this.decoderBuilder, this.string, {ColorFilter? colorFilter}) + StringPicture(PictureInfoDecoderBuilder decoderBuilder, this.string, + {ColorFilter? colorFilter}) : assert(string != null), // ignore: unnecessary_null_comparison - decoder = decoderBuilder(null), - super(colorFilter); - - /// The decoder builder to build a [decoder] when [currentColor] changes. - final PictureInfoDecoderBuilder decoderBuilder; - - /// The [PictureInfoDecoder] to use for decoding this picture. - @visibleForTesting - PictureInfoDecoder decoder; + super(colorFilter, decoderBuilder: decoderBuilder); /// The string to decode into a picture. final String string; @override - set currentColor(Color? color) { - _currentColor = color; - decoder = decoderBuilder(_currentColor); - } - - @override - Future obtainKey(PictureConfiguration picture) { - return SynchronousFuture(this); + Future> obtainKey(PictureConfiguration picture) { + return SynchronousFuture>( + PictureKey( + string, + colorFilter: colorFilter, + theme: SvgTheme( + currentColor: currentColor, + ), + ), + ); } @override - PictureStreamCompleter load(StringPicture key, + PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError)); } Future _loadAsync( - StringPicture key, { + PictureKey key, { PictureErrorListener? onError, }) { - assert(key == this); + assert(key.keyData == string); if (onError != null) { return decoder( string, @@ -821,19 +845,6 @@ class StringPicture extends PictureProvider { return decoder(string, colorFilter, key.toString()); } - @override - bool operator ==(dynamic other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is StringPicture && - string == other.string && - colorFilter == other.colorFilter; - } - - @override - int get hashCode => hashValues(string.hashCode, colorFilter); - @override String toString() => '$runtimeType(${describeIdentity(string)}, colorFilter: $colorFilter)'; @@ -958,24 +969,11 @@ class ExactAssetPicture extends AssetBundlePictureProvider { bundle: bundle ?? picture.bundle ?? rootBundle, name: keyName, colorFilter: colorFilter, + theme: SvgTheme(currentColor: currentColor), ), ); } - @override - bool operator ==(dynamic other) { - if (other.runtimeType != runtimeType) { - return false; - } - return other is ExactAssetPicture && - keyName == other.keyName && - bundle == other.bundle && - colorFilter == other.colorFilter; - } - - @override - int get hashCode => hashValues(keyName, bundle, colorFilter); - @override String toString() => '$runtimeType(name: "$keyName", bundle: $bundle, colorFilter: $colorFilter)'; diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart index ed206005..49eb71e6 100644 --- a/lib/src/svg/theme.dart +++ b/lib/src/svg/theme.dart @@ -1,6 +1,9 @@ import 'dart:ui'; +import 'package:meta/meta.dart'; + /// A theme used when decoding an SVG picture. +@immutable class SvgTheme { /// Instantiates an SVG theme with the [currentColor]. const SvgTheme({ diff --git a/test/picture_provider_test.dart b/test/picture_provider_test.dart index 01e4a5c8..baedd2f4 100644 --- a/test/picture_provider_test.dart +++ b/test/picture_provider_test.dart @@ -142,5 +142,20 @@ void main() { equals(color), ); }); + + test('Evicts from cache when currentColor changes', () async { + expect(PictureProvider.cache.count, 0); + const Color color = Color(0xFFB0E3BE); + final StringPicture stringPicture = StringPicture(decoderBuilder, ''); + + final PictureStream stream = + stringPicture.resolve(createLocalPictureConfiguration(null)); + + await null; + expect(PictureProvider.cache.count, 1); + + stringPicture.currentColor = color; + expect(PictureProvider.cache.count, 0); + }); }); } From 666b171cbe22046e27775aeac440f89e5744688a Mon Sep 17 00:00:00 2001 From: Bartosz Selwesiuk Date: Thu, 18 Nov 2021 21:37:40 +0100 Subject: [PATCH 035/142] Add support for em units (#605) * feat: add parseDoubleWithUnits to calculate em values * feat: add fontSize to SvgTheme * feat: add fontSize to SvgPicture and PictureProvider * feat: use parseDoubleWithUnits with SVG elements that support em/ex * fix: PictureProvider should rebuild if currentColor is null * test: fix tests after introducing fontSize * test: add DefaultSvgTheme fontSize tests * fix: update SvgTheme hashCode to include fontSize * refactor: replace currentColor and fontSize SvgPicture properties with SvgTheme * test: fix parseDashOffset tests * test: add parseStyle fontSize tests (stroke width, dash array, dash offset) * test: update parseStyle test names * test: add missing DefaultSvgTheme tests * fix: do not print a warning when using em units on the root svg width/height * test: add SvgParser fontSize tests (svg, use, text, radialGradient, linearGradient, image) * test: add SvgPicture fontSize tests for shapes (circle, rect, ellipse, line) * test: PictureProvider rebuilds a decoder when fontSize changes * test: use SvgTheme.empty in tests * test: add relative font size tests * build: update path_drawing to ^0.5.1+1 * feat: use default SvgTheme * fix: typo * refactor: make PictureInfoDecoderBuilder receive an SvgTheme rather than a list of properties * test: fix PictureProvider tests that use SvgTheme * fix: initialize default decoder when PictureProvider is created * feat: PictureProvider loadAsync should return non-nullable PictureInfo * feat: fallback to default SvgTheme if null theme is set * feat: make PictureProvider theme non nullable --- lib/parser.dart | 2 +- lib/src/picture_provider.dart | 49 +++-- lib/src/svg/parser_state.dart | 202 ++++++++++++++----- lib/src/svg/parsers.dart | 14 +- lib/src/svg/theme.dart | 16 +- lib/src/svg/xml_parsers.dart | 68 +++++-- lib/src/utilities/numbers.dart | 51 ++++- lib/svg.dart | 101 ++++++---- pubspec.yaml | 2 +- test/default_theme_test.dart | 100 +++++++++- test/error_test.dart | 5 +- test/golden_widget/circle.em.png | Bin 0 -> 10223 bytes test/golden_widget/ellipse.em.png | Bin 0 -> 6672 bytes test/golden_widget/line.em.png | Bin 0 -> 6500 bytes test/golden_widget/rect.em.png | Bin 0 -> 4071 bytes test/picture_cache_test.dart | 27 ++- test/picture_provider_test.dart | 315 ++++++++++++++++++------------ test/svg_parsers_test.dart | 284 ++++++++++++++++++++++++--- test/theme_test.dart | 30 ++- test/vector_drawable_test.dart | 2 - test/widget_svg_test.dart | 102 +++++++++- test/xml_svg_test.dart | 161 +++++++++++++-- tool/gen_golden.dart | 7 +- 23 files changed, 1194 insertions(+), 344 deletions(-) create mode 100644 test/golden_widget/circle.em.png create mode 100644 test/golden_widget/ellipse.em.png create mode 100644 test/golden_widget/line.em.png create mode 100644 test/golden_widget/rect.em.png diff --git a/lib/parser.dart b/lib/parser.dart index d720192f..ee2e4eb2 100644 --- a/lib/parser.dart +++ b/lib/parser.dart @@ -18,7 +18,7 @@ class SvgParser { /// Defaults to false. Future parse( String str, { - SvgTheme? theme, + SvgTheme theme = const SvgTheme(), String? key, bool warningsAsErrors = false, }) async { diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 8e9424ed..e3951191 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -29,9 +29,9 @@ typedef PictureInfoDecoder = Future Function( ); /// The signature of a builder that returns a [PictureInfoDecoder] -/// based on the [currentColor]. +/// based on the provided [theme]. typedef PictureInfoDecoderBuilder = PictureInfoDecoder Function( - Color? currentColor, + SvgTheme theme, ); /// Creates an [PictureConfiguration] based on the given [BuildContext] (and @@ -307,9 +307,10 @@ abstract class PictureProvider { /// Abstract const constructor. This constructor enables subclasses to provide /// const constructors so that they can be used in const expressions. PictureProvider(this.colorFilter, {required this.decoderBuilder}) - : decoder = decoderBuilder(null); + : _theme = const SvgTheme(), + decoder = decoderBuilder(const SvgTheme()); - /// The decoder builder to build a [decoder] when [currentColor] changes. + /// The decoder builder to build a [decoder] when [theme] changes. final PictureInfoDecoderBuilder decoderBuilder; /// The [PictureInfoDecoder] to use for loading this picture. @@ -331,18 +332,23 @@ abstract class PictureProvider { /// The color filter to apply to the picture, if any. final ColorFilter? colorFilter; - /// The default color applied to SVG elements that inherit the color property. + /// The default theme used when parsing SVG elements. @visibleForTesting - Color? get currentColor => _currentColor; - Color? _currentColor; + SvgTheme get theme => _theme; + SvgTheme _theme; - /// Sets the [_currentColor] to [color]. - set currentColor(Color? color) { - if (_currentColor == color) { + /// Sets the [_theme] to [theme]. + /// + /// A theme is used when parsing SVG elements. Changing the theme + /// rebuilds a [decoder] using [decoderBuilder] and the new theme. + /// This will make the decoded SVG picture use properties from + /// the new theme. + set theme(SvgTheme theme) { + if (_theme == theme) { return; } - decoder = decoderBuilder(color); - _currentColor = color; + decoder = decoderBuilder(theme); + _theme = theme; if (_lastKey != null) { cache.evict(_lastKey!); _lastKey = null; @@ -537,6 +543,7 @@ abstract class AssetBundlePictureProvider Future _loadAsync( AssetBundlePictureKey key, PictureErrorListener? onError) async { final String data = await key.bundle.loadString(key.name); + if (onError != null) { return decoder( data, @@ -610,9 +617,7 @@ class NetworkPicture PictureKey( NetworkPictureKeyData(url: url, headers: headers), colorFilter: colorFilter, - theme: SvgTheme( - currentColor: currentColor, - ), + theme: theme, ), ); } @@ -679,9 +684,7 @@ class FilePicture extends PictureProvider, Uint8List> { PictureKey( file.path, colorFilter: colorFilter, - theme: SvgTheme( - currentColor: currentColor, - ), + theme: theme, ), ); } @@ -751,9 +754,7 @@ class MemoryPicture extends PictureProvider, Uint8List> { PictureKey( bytes, colorFilter: colorFilter, - theme: SvgTheme( - currentColor: currentColor, - ), + theme: theme, ), ); } @@ -814,9 +815,7 @@ class StringPicture extends PictureProvider, String> { PictureKey( string, colorFilter: colorFilter, - theme: SvgTheme( - currentColor: currentColor, - ), + theme: theme, ), ); } @@ -969,7 +968,7 @@ class ExactAssetPicture extends AssetBundlePictureProvider { bundle: bundle ?? picture.bundle ?? rootBundle, name: keyName, colorFilter: colorFilter, - theme: SvgTheme(currentColor: currentColor), + theme: theme, ), ); } diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index a2514352..c1952765 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -19,7 +19,8 @@ final Set _unhandledElements = {'title', 'desc'}; typedef _ParseFunc = Future? Function( SvgParserState parserState, bool warningsAsErrors); -typedef _PathFunc = Path? Function(Map attributes); +typedef _PathFunc = Path? Function( + Map attributes, double fontSize); final RegExp _trimPattern = RegExp(r'[\r|\n|\t]'); @@ -50,15 +51,22 @@ const Map _svgPathFuncs = { Offset _parseCurrentOffset(SvgParserState parserState, Offset? lastOffset) { final String? x = parserState.attribute('x', def: null); final String? y = parserState.attribute('y', def: null); + final double fontSize = parserState.fontSize; return Offset( x != null - ? parseDouble(x)! - : parseDouble(parserState.attribute('dx', def: '0'))! + + ? parseDoubleWithUnits(x, fontSize: fontSize)! + : parseDoubleWithUnits( + parserState.attribute('dx', def: '0'), + fontSize: fontSize, + )! + (lastOffset?.dx ?? 0), y != null - ? parseDouble(y)! - : parseDouble(parserState.attribute('dy', def: '0'))! + + ? parseDoubleWithUnits(y, fontSize: fontSize)! + : parseDoubleWithUnits( + parserState.attribute('dy', def: '0'), + fontSize: fontSize, + )! + (lastOffset?.dy ?? 0), ); } @@ -81,14 +89,18 @@ class _TextInfo { // ignore: avoid_classes_with_only_static_members class _Elements { static Future? svg(SvgParserState parserState, bool warningsAsErrors) { - final DrawableViewport? viewBox = parseViewBox(parserState.attributes); + final DrawableViewport? viewBox = parseViewBox( + parserState.attributes, + fontSize: parserState.fontSize, + ); + final String? id = parserState.attribute('id', def: ''); final Color? color = parseColor(parserState.attribute('color', def: null)) ?? // Fallback to the currentColor from theme if no color is defined // on the root SVG element. - parserState.theme?.currentColor; + parserState.theme.currentColor; // TODO(dnfield): Support nested SVG elements. https://github.com/dnfield/flutter_svg/issues/132 if (parserState._root != null) { @@ -123,6 +135,7 @@ class _Elements { viewBox!.viewBoxRect, null, currentColor: color, + fontSize: parserState.fontSize, ), color: color, ), @@ -142,6 +155,7 @@ class _Elements { viewBox.viewBoxRect, null, currentColor: color, + fontSize: parserState.fontSize, ), color: color, ); @@ -164,6 +178,7 @@ class _Elements { parserState.rootBounds, parent.style, currentColor: color, + fontSize: parserState.fontSize, ), transform: parseTransform(parserState.attribute('transform'))?.storage, color: color, @@ -191,6 +206,7 @@ class _Elements { null, parent.style, currentColor: color, + fontSize: parserState.fontSize, ), transform: parseTransform(parserState.attribute('transform'))?.storage, color: color, @@ -213,14 +229,21 @@ class _Elements { parserState.rootBounds, parent!.style, currentColor: parent.color, + fontSize: parserState.fontSize, ); final Matrix4 transform = parseTransform(parserState.attribute('transform')) ?? Matrix4.identity(); transform.translate( - parseDouble(parserState.attribute('x', def: '0')), - parseDouble(parserState.attribute('y', def: '0'))!, + parseDoubleWithUnits( + parserState.attribute('x', def: '0'), + fontSize: parserState.fontSize, + ), + parseDoubleWithUnits( + parserState.attribute('y', def: '0'), + fontSize: parserState.fontSize, + )!, ); final DrawableStyleable ref = @@ -277,6 +300,7 @@ class _Elements { SvgParserState parserState, bool warningsAsErrors, ) { + final double fontSize = parserState.fontSize; final String? gradientUnits = getAttribute( parserState.attributes, 'gradientUnits', @@ -327,24 +351,24 @@ class _Elements { cx = isPercentage(rawCx!) ? parsePercentage(rawCx) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDouble(rawCx)!; + : parseDoubleWithUnits(rawCx, fontSize: fontSize)!; cy = isPercentage(rawCy!) ? parsePercentage(rawCy) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDouble(rawCy)!; + : parseDoubleWithUnits(rawCy, fontSize: fontSize)!; r = isPercentage(rawR!) ? parsePercentage(rawR) * ((parserState.rootBounds.height + parserState.rootBounds.width) / 2) - : parseDouble(rawR)!; + : parseDoubleWithUnits(rawR, fontSize: fontSize)!; fx = isPercentage(rawFx!) ? parsePercentage(rawFx) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDouble(rawFx)!; + : parseDoubleWithUnits(rawFx, fontSize: fontSize)!; fy = isPercentage(rawFy!) ? parsePercentage(rawFy) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDouble(rawFy)!; + : parseDoubleWithUnits(rawFy, fontSize: fontSize)!; } parserState._definitions.addGradient( @@ -368,6 +392,7 @@ class _Elements { static Future? linearGradient( SvgParserState parserState, bool warningsAsErrors) { + final double fontSize = parserState.fontSize; final String? gradientUnits = getAttribute( parserState.attributes, 'gradientUnits', @@ -420,22 +445,22 @@ class _Elements { isPercentage(x1!) ? parsePercentage(x1) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDouble(x1)!, + : parseDoubleWithUnits(x1, fontSize: fontSize)!, isPercentage(y1!) ? parsePercentage(y1) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDouble(y1)!, + : parseDoubleWithUnits(y1, fontSize: fontSize)!, ); toOffset = Offset( isPercentage(x2!) ? parsePercentage(x2) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDouble(x2)!, + : parseDoubleWithUnits(x2, fontSize: fontSize)!, isPercentage(y2!) ? parsePercentage(y2) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDouble(y2)!, + : parseDoubleWithUnits(y2, fontSize: fontSize)!, ); } @@ -472,7 +497,7 @@ class _Elements { if (pathFn != null) { final Path nextPath = applyTransformIfNeeded( - pathFn(parserState.attributes), + pathFn(parserState.attributes, parserState.fontSize), parserState.attributes, )!; nextPath.fillType = @@ -530,17 +555,30 @@ class _Elements { static Future image( SvgParserState parserState, bool warningsAsErrors) async { + final double fontSize = parserState.fontSize; final String? href = getHrefAttribute(parserState.attributes); if (href == null) { return; } final Offset offset = Offset( - parseDouble(parserState.attribute('x', def: '0'))!, - parseDouble(parserState.attribute('y', def: '0'))!, + parseDoubleWithUnits( + parserState.attribute('x', def: '0'), + fontSize: fontSize, + )!, + parseDoubleWithUnits( + parserState.attribute('y', def: '0'), + fontSize: fontSize, + )!, ); final Size size = Size( - parseDouble(parserState.attribute('width', def: '0'))!, - parseDouble(parserState.attribute('height', def: '0'))!, + parseDoubleWithUnits( + parserState.attribute('width', def: '0'), + fontSize: fontSize, + )!, + parseDoubleWithUnits( + parserState.attribute('height', def: '0'), + fontSize: fontSize, + )!, ); final Image image = await resolveImage(href); final DrawableParent parent = parserState._parentDrawables.last.drawable!; @@ -556,6 +594,7 @@ class _Elements { parserState.rootBounds, parentStyle, currentColor: parent.color, + fontSize: parserState.fontSize, ), size: size, transform: parseTransform(parserState.attribute('transform'))?.storage, @@ -631,13 +670,17 @@ class _Elements { } } + final DrawableStyle? parentStyle = + lastTextInfo?.style ?? parserState.currentGroup!.style; + textInfos.add(_TextInfo( parseStyle( parserState._key, parserState.attributes, parserState._definitions, parserState.rootBounds, - lastTextInfo?.style ?? parserState.currentGroup!.style, + parentStyle, + fontSize: parserState.fontSize, ), currentOffset, transform, @@ -672,24 +715,45 @@ class _Elements { // ignore: avoid_classes_with_only_static_members class _Paths { - static Path circle(Map attributes) { - final double cx = parseDouble(getAttribute(attributes, 'cx', def: '0'))!; - final double cy = parseDouble(getAttribute(attributes, 'cy', def: '0'))!; - final double r = parseDouble(getAttribute(attributes, 'r', def: '0'))!; + static Path circle(Map attributes, double fontSize) { + final double cx = parseDoubleWithUnits( + getAttribute(attributes, 'cx', def: '0'), + fontSize: fontSize, + )!; + final double cy = parseDoubleWithUnits( + getAttribute(attributes, 'cy', def: '0'), + fontSize: fontSize, + )!; + final double r = parseDoubleWithUnits( + getAttribute(attributes, 'r', def: '0'), + fontSize: fontSize, + )!; final Rect oval = Rect.fromCircle(center: Offset(cx, cy), radius: r); return Path()..addOval(oval); } - static Path path(Map attributes) { + static Path path(Map attributes, double fontSize) { final String d = getAttribute(attributes, 'd')!; return parseSvgPathData(d); } - static Path rect(Map attributes) { - final double x = parseDouble(getAttribute(attributes, 'x', def: '0'))!; - final double y = parseDouble(getAttribute(attributes, 'y', def: '0'))!; - final double w = parseDouble(getAttribute(attributes, 'width', def: '0'))!; - final double h = parseDouble(getAttribute(attributes, 'height', def: '0'))!; + static Path rect(Map attributes, double fontSize) { + final double x = parseDoubleWithUnits( + getAttribute(attributes, 'x', def: '0'), + fontSize: fontSize, + )!; + final double y = parseDoubleWithUnits( + getAttribute(attributes, 'y', def: '0'), + fontSize: fontSize, + )!; + final double w = parseDoubleWithUnits( + getAttribute(attributes, 'width', def: '0'), + fontSize: fontSize, + )!; + final double h = parseDoubleWithUnits( + getAttribute(attributes, 'height', def: '0'), + fontSize: fontSize, + )!; final Rect rect = Rect.fromLTWH(x, y, w, h); String? rxRaw = getAttribute(attributes, 'rx', def: null); String? ryRaw = getAttribute(attributes, 'ry', def: null); @@ -697,8 +761,14 @@ class _Paths { ryRaw ??= rxRaw; if (rxRaw != null && rxRaw != '') { - final double rx = parseDouble(rxRaw)!; - final double ry = parseDouble(ryRaw)!; + final double rx = parseDoubleWithUnits( + rxRaw, + fontSize: fontSize, + )!; + final double ry = parseDoubleWithUnits( + ryRaw, + fontSize: fontSize, + )!; return Path()..addRRect(RRect.fromRectXY(rect, rx, ry)); } @@ -706,11 +776,11 @@ class _Paths { return Path()..addRect(rect); } - static Path? polygon(Map attributes) { + static Path? polygon(Map attributes, double fontSize) { return parsePathFromPoints(attributes, true); } - static Path? polyline(Map attributes) { + static Path? polyline(Map attributes, double fontSize) { return parsePathFromPoints(attributes, false); } @@ -724,21 +794,45 @@ class _Paths { return parseSvgPathData(path); } - static Path ellipse(Map attributes) { - final double cx = parseDouble(getAttribute(attributes, 'cx', def: '0'))!; - final double cy = parseDouble(getAttribute(attributes, 'cy', def: '0'))!; - final double rx = parseDouble(getAttribute(attributes, 'rx', def: '0'))!; - final double ry = parseDouble(getAttribute(attributes, 'ry', def: '0'))!; + static Path ellipse(Map attributes, double fontSize) { + final double cx = parseDoubleWithUnits( + getAttribute(attributes, 'cx', def: '0'), + fontSize: fontSize, + )!; + final double cy = parseDoubleWithUnits( + getAttribute(attributes, 'cy', def: '0'), + fontSize: fontSize, + )!; + final double rx = parseDoubleWithUnits( + getAttribute(attributes, 'rx', def: '0'), + fontSize: fontSize, + )!; + final double ry = parseDoubleWithUnits( + getAttribute(attributes, 'ry', def: '0'), + fontSize: fontSize, + )!; final Rect r = Rect.fromLTWH(cx - rx, cy - ry, rx * 2, ry * 2); return Path()..addOval(r); } - static Path line(Map attributes) { - final double x1 = parseDouble(getAttribute(attributes, 'x1', def: '0'))!; - final double x2 = parseDouble(getAttribute(attributes, 'x2', def: '0'))!; - final double y1 = parseDouble(getAttribute(attributes, 'y1', def: '0'))!; - final double y2 = parseDouble(getAttribute(attributes, 'y2', def: '0'))!; + static Path line(Map attributes, double fontSize) { + final double x1 = parseDoubleWithUnits( + getAttribute(attributes, 'x1', def: '0'), + fontSize: fontSize, + )!; + final double x2 = parseDoubleWithUnits( + getAttribute(attributes, 'x2', def: '0'), + fontSize: fontSize, + )!; + final double y1 = parseDoubleWithUnits( + getAttribute(attributes, 'y1', def: '0'), + fontSize: fontSize, + )!; + final double y2 = parseDoubleWithUnits( + getAttribute(attributes, 'y2', def: '0'), + fontSize: fontSize, + )!; return Path() ..moveTo(x1, y1) @@ -768,8 +862,8 @@ class SvgParserState { : assert(events != null), _eventIterator = events.iterator; - /// A theme used when parsing SVG elements. - final SvgTheme? theme; + /// The theme used when parsing SVG elements. + final SvgTheme theme; final Iterator _eventIterator; final String? _key; @@ -917,7 +1011,7 @@ class SvgParserState { final DrawableParent parent = _parentDrawables.last.drawable!; final DrawableStyle? parentStyle = parent.style; - final Path path = pathFunc(attributes)!; + final Path path = pathFunc(attributes, fontSize)!; final DrawableStyleable drawable = DrawableShape( getAttribute(attributes, 'id', def: ''), path, @@ -929,6 +1023,7 @@ class SvgParserState { parentStyle, defaultFillColor: colorBlack, currentColor: parent.color, + fontSize: fontSize, ), transform: parseTransform(getAttribute(attributes, 'transform'))?.storage, ); @@ -993,3 +1088,8 @@ class SvgParserState { } } } + +extension on SvgParserState { + /// Retrieves the font size of the current [theme]. + double get fontSize => theme.fontSize; +} diff --git a/lib/src/svg/parsers.dart b/lib/src/svg/parsers.dart index ce39f759..36e89e87 100644 --- a/lib/src/svg/parsers.dart +++ b/lib/src/svg/parsers.dart @@ -20,12 +20,22 @@ final Map _kTextSizeMap = { }; /// Parses a `font-size` attribute. -double? parseFontSize(String? raw, {double? parentValue}) { +/// +/// Uses [fontSize] to calculate the font size including em units. +double? parseFontSize( + String? raw, { + required double fontSize, + double? parentValue, +}) { if (raw == null || raw == '') { return null; } - double? ret = parseDouble(raw, tryParse: true); + double? ret = parseDoubleWithUnits( + raw, + tryParse: true, + fontSize: fontSize, + ); if (ret != null) { return ret; } diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart index 49eb71e6..1cde53d9 100644 --- a/lib/src/svg/theme.dart +++ b/lib/src/svg/theme.dart @@ -5,23 +5,33 @@ import 'package:meta/meta.dart'; /// A theme used when decoding an SVG picture. @immutable class SvgTheme { - /// Instantiates an SVG theme with the [currentColor]. + /// Instantiates an SVG theme with the [currentColor] + /// and [fontSize]. + /// + /// Defaults the [fontSize] to 14. const SvgTheme({ this.currentColor, + this.fontSize = 14, }); /// The default color applied to SVG elements that inherit the color property. /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword final Color? currentColor; + /// The font size used when calculating em units of SVG elements. + /// See: https://www.w3.org/TR/SVG11/coords.html#Units + final double fontSize; + @override bool operator ==(dynamic other) { if (other.runtimeType != runtimeType) { return false; } - return other is SvgTheme && currentColor == other.currentColor; + return other is SvgTheme && + currentColor == other.currentColor && + fontSize == other.fontSize; } @override - int get hashCode => currentColor.hashCode; + int get hashCode => hashValues(currentColor, fontSize); } diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index d46d987b..de53a91f 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -10,23 +10,29 @@ import '../vector_drawable.dart'; import 'colors.dart'; import 'parsers.dart'; -double _parseRawWidthHeight(String? raw) { +double _parseRawWidthHeight( + String? raw, { + required double fontSize, +}) { if (raw == '100%' || raw == '') { return double.infinity; } assert(() { final RegExp notDigits = RegExp(r'[^\d\.]'); - if (!raw!.endsWith('px') && raw.contains(notDigits)) { + if (!raw!.endsWith('px') && + !raw.endsWith('em') && + raw.contains(notDigits)) { print( 'Warning: Flutter SVG only supports the following formats for `width` and `height` on the SVG root:\n' ' width="100%"\n' + ' width="100em"\n' ' width="100px"\n' ' width="100" (where the number will be treated as pixels).\n' 'The supplied value ($raw) will be discarded and treated as if it had not been specified.'); } return true; }()); - return double.tryParse(raw!.replaceAll('px', '')) ?? double.infinity; + return parseDoubleWithUnits(raw, fontSize: fontSize) ?? double.infinity; } /// Parses an SVG @viewBox attribute (e.g. 0 0 100 100) to a [Rect]. @@ -38,6 +44,7 @@ double _parseRawWidthHeight(String? raw) { /// on the root SVG element should be treated in accordance with the specification. DrawableViewport? parseViewBox( Map svg, { + required double fontSize, bool nullOk = false, }) { final String? viewBox = getAttribute(svg, 'viewBox'); @@ -56,8 +63,15 @@ DrawableViewport? parseViewBox( ' $svg'); } - final double width = _parseRawWidthHeight(rawWidth); - final double height = _parseRawWidthHeight(rawHeight); + final double width = _parseRawWidthHeight( + rawWidth, + fontSize: fontSize, + ); + + final double height = _parseRawWidthHeight( + rawHeight, + fontSize: fontSize, + ); if (viewBox == '') { return DrawableViewport( @@ -111,8 +125,9 @@ TileMode parseTileMode(Map attributes) { /// /// Does not currently support percentages. CircularIntervalList? parseDashArray( - Map attributes, -) { + Map attributes, { + required double fontSize, +}) { final String? rawDashArray = getAttribute(attributes, 'stroke-dasharray'); if (rawDashArray == '') { return null; @@ -121,24 +136,28 @@ CircularIntervalList? parseDashArray( } final List parts = rawDashArray!.split(RegExp(r'[ ,]+')); - return CircularIntervalList( - parts.map((String part) => parseDouble(part)!).toList()); + return CircularIntervalList(parts + .map((String part) => parseDoubleWithUnits(part, fontSize: fontSize)!) + .toList()); } /// Parses a @stroke-dashoffset into a [DashOffset]. -DashOffset? parseDashOffset(Map attributes) { +DashOffset? parseDashOffset( + Map attributes, { + required double fontSize, +}) { final String? rawDashOffset = getAttribute(attributes, 'stroke-dashoffset'); if (rawDashOffset == '') { return null; } if (rawDashOffset!.endsWith('%')) { - final double percentage = - parseDouble(rawDashOffset.substring(0, rawDashOffset.length - 1))! / - 100; - return DashOffset.percentage(percentage); + return DashOffset.percentage(parsePercentage(rawDashOffset)); } else { - return DashOffset.absolute(parseDouble(rawDashOffset)!); + return DashOffset.absolute(parseDoubleWithUnits( + rawDashOffset, + fontSize: fontSize, + )!); } } @@ -179,6 +198,7 @@ DrawablePaint? parseStroke( DrawableDefinitionServer definitions, DrawablePaint? parentStroke, Color? currentColor, + double fontSize, ) { final String rawStroke = getAttribute(attributes, 'stroke')!; final String? rawStrokeOpacity = getAttribute( @@ -240,7 +260,10 @@ DrawablePaint? parseStroke( : parseDouble(rawMiterLimit), strokeWidth: rawStrokeWidth == '' ? parentStroke?.strokeWidth ?? 1.0 - : parseDouble(rawStrokeWidth), + : parseDoubleWithUnits( + rawStrokeWidth, + fontSize: fontSize, + ), ); return paint; } @@ -474,6 +497,7 @@ DrawableStyle parseStyle( DrawableDefinitionServer definitions, Rect? bounds, DrawableStyle? parentStyle, { + required double fontSize, Color? defaultFillColor, Color? currentColor, }) { @@ -486,9 +510,16 @@ DrawableStyle parseStyle( definitions, parentStyle?.stroke, currentColor, + fontSize, + ), + dashArray: parseDashArray( + attributes, + fontSize: fontSize, + ), + dashOffset: parseDashOffset( + attributes, + fontSize: fontSize, ), - dashArray: parseDashArray(attributes), - dashOffset: parseDashOffset(attributes), fill: parseFill( key, attributes, @@ -511,6 +542,7 @@ DrawableStyle parseStyle( fontSize: parseFontSize( getAttribute(attributes, 'font-size'), parentValue: parentStyle?.textStyle?.fontSize, + fontSize: fontSize, ), fontWeight: parseFontWeight( getAttribute(attributes, 'font-weight', def: null), diff --git a/lib/src/utilities/numbers.dart b/lib/src/utilities/numbers.dart index fc3e1744..1b3f2f1a 100644 --- a/lib/src/utilities/numbers.dart +++ b/lib/src/utilities/numbers.dart @@ -1,16 +1,51 @@ -/// Parses a `String` to a `double`. +/// Parses a [rawDouble] `String` to a `double`. /// -/// Passing `null` will return `null`. +/// The [rawDouble] might include a unit (`px` or `em`) +/// which is stripped off when parsed to a `double`. /// -/// Will strip off a `px` prefix. -double? parseDouble(String? maybeDouble, {bool tryParse = false}) { +/// Passing `null` will return `null`. +double? parseDouble(String? rawDouble, {bool tryParse = false}) { assert(tryParse != null); // ignore: unnecessary_null_comparison - if (maybeDouble == null) { + if (rawDouble == null) { return null; } - maybeDouble = maybeDouble.replaceFirst('px', '').trim(); + + rawDouble = rawDouble.replaceFirst('em', '').replaceFirst('px', '').trim(); + if (tryParse) { - return double.tryParse(maybeDouble); + return double.tryParse(rawDouble); + } + return double.parse(rawDouble); +} + +/// Parses a [rawDouble] `String` to a `double` +/// taking into account absolute and relative units +/// (`px` or `em`). +/// +/// Passing an `em` value will calculate the result +/// relative to the provided [fontSize]: +/// 1 em = 1 * [fontSize]. +/// +/// The [rawDouble] might include a unit which is +/// stripped off when parsed to a `double`. +/// +/// Passing `null` will return `null`. +double? parseDoubleWithUnits( + String? rawDouble, { + required double fontSize, + bool tryParse = false, +}) { + double unit = 1.0; + + // 1 em unit is equal to the current font size. + if (rawDouble?.contains('em') ?? false) { + unit = fontSize; } - return double.parse(maybeDouble); + + final double? value = parseDouble( + rawDouble, + tryParse: tryParse, + ); + + return value != null ? value * unit : null; } diff --git a/lib/svg.dart b/lib/svg.dart index ec1d11a9..b0201824 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -43,6 +43,9 @@ class Svg { /// /// The `colorFilter` property will be applied to any [Paint] objects used during drawing. /// + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. + /// /// The [key] will be used for debugging purposes. Future svgPictureDecoder( Uint8List raw, @@ -72,6 +75,9 @@ class Svg { /// /// The `colorFilter` property will be applied to any [Paint] objects used during drawing. /// + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. + /// /// The [key] will be used for debugging purposes. Future svgPictureStringDecoder( String raw, @@ -235,7 +241,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : super(key: key); /// Instantiates a widget that renders an SVG picture from an [AssetBundle]. @@ -264,8 +270,8 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// - /// The `currentColor` argument, if provided, will override the default color - /// of any SVG element that inherits its color. + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. /// /// ## Assets in packages /// @@ -336,7 +342,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : pictureProvider = ExactAssetPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -374,8 +380,8 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// - /// The `currentColor` argument, if provided, will override the default color - /// of any SVG element that inherits its color. + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. /// /// All network images are cached regardless of HTTP headers. /// @@ -400,7 +406,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : pictureProvider = NetworkPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -437,8 +443,8 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// - /// The `currentColor` argument, if provided, will override the default color - /// of any SVG element that inherits its color. + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. /// /// On Android, this may require the /// `android.permission.READ_EXTERNAL_STORAGE` permission. @@ -460,7 +466,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : pictureProvider = FilePicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -496,8 +502,8 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// - /// The `currentColor` argument, if provided, will override the default color - /// of any SVG element that inherits its color. + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. /// /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. SvgPicture.memory( @@ -516,7 +522,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : pictureProvider = MemoryPicture( allowDrawingOutsideViewBox == true ? svgByteDecoderOutsideViewBoxBuilder @@ -552,8 +558,8 @@ class SvgPicture extends StatefulWidget { /// The `color` and `colorBlendMode` arguments, if specified, will be used to set a /// [ColorFilter] on any [Paint]s created for this drawing. /// - /// The `currentColor` argument, if provided, will override the default color - /// of any SVG element that inherits its color. + /// The `theme` argument, if provided, will override the default theme + /// used when parsing SVG elements. /// /// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored. SvgPicture.string( @@ -572,7 +578,7 @@ class SvgPicture extends StatefulWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, this.cacheColorFilter = false, - this.currentColor, + this.theme, }) : pictureProvider = StringPicture( allowDrawingOutsideViewBox == true ? svgStringDecoderOutsideViewBoxBuilder @@ -595,50 +601,49 @@ class SvgPicture extends StatefulWidget { /// A [PictureInfoDecoderBuilder] for [Uint8List]s that will clip to the viewBox. static final PictureInfoDecoderBuilder svgByteDecoderBuilder = - (Color? currentColor) => + (SvgTheme theme) => (Uint8List bytes, ColorFilter? colorFilter, String key) => svg.svgPictureDecoder( bytes, false, colorFilter, key, - theme: SvgTheme(currentColor: currentColor), + theme: theme, ); /// A [PictureInfoDecoderBuilder] for strings that will clip to the viewBox. static final PictureInfoDecoderBuilder svgStringDecoderBuilder = - (Color? currentColor) => - (String data, ColorFilter? colorFilter, String key) => - svg.svgPictureStringDecoder( - data, - false, - colorFilter, - key, - theme: SvgTheme(currentColor: currentColor), - ); + (SvgTheme theme) => (String data, ColorFilter? colorFilter, String key) => + svg.svgPictureStringDecoder( + data, + false, + colorFilter, + key, + theme: theme, + ); /// A [PictureInfoDecoderBuilder] for [Uint8List]s that will not clip to the viewBox. static final PictureInfoDecoderBuilder - svgByteDecoderOutsideViewBoxBuilder = (Color? currentColor) => + svgByteDecoderOutsideViewBoxBuilder = (SvgTheme theme) => (Uint8List bytes, ColorFilter? colorFilter, String key) => svg.svgPictureDecoder( bytes, true, colorFilter, key, - theme: SvgTheme(currentColor: currentColor), + theme: theme, ); /// A [PictureInfoDecoderBuilder] for [String]s that will not clip to the viewBox. static final PictureInfoDecoderBuilder - svgStringDecoderOutsideViewBoxBuilder = (Color? currentColor) => + svgStringDecoderOutsideViewBoxBuilder = (SvgTheme theme) => (String data, ColorFilter? colorFilter, String key) => svg.svgPictureStringDecoder( data, true, colorFilter, key, - theme: SvgTheme(currentColor: currentColor), + theme: theme, ); /// If specified, the width to use for the SVG. If unspecified, the SVG @@ -725,9 +730,8 @@ class SvgPicture extends StatefulWidget { /// This defaults to false and must not be null. final bool cacheColorFilter; - /// The default color applied to SVG elements that inherit the color property. - /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword - final Color? currentColor; + /// The theme used when parsing SVG elements. + final SvgTheme? theme; @override State createState() => _SvgPictureState(); @@ -762,12 +766,31 @@ class _SvgPictureState extends State { super.reassemble(); } - /// Updates the `currentColor` of the picture provider based on either - /// the widget's `currentColor` property or [DefaultSvgTheme]. + /// Updates the `currentColor` of the picture provider based on + /// either the widget's [SvgTheme] or an inherited [DefaultSvgTheme]. + /// + /// Updates the `fontSize` of the picture provider based on + /// either the widget's [SvgTheme], an inherited [DefaultSvgTheme] + /// or an inherited [DefaultTextStyle]. If the property does not exist, + /// then the font size defaults to 14. void _updatePictureProvider() { - final SvgTheme? svgTheme = DefaultSvgTheme.of(context)?.theme; - final Color? currentColor = widget.currentColor ?? svgTheme?.currentColor; - widget.pictureProvider.currentColor = currentColor; + final SvgTheme? defaultSvgTheme = DefaultSvgTheme.of(context)?.theme; + final TextStyle defaultTextStyle = DefaultTextStyle.of(context).style; + + final Color? currentColor = + widget.theme?.currentColor ?? defaultSvgTheme?.currentColor; + + final double fontSize = widget.theme?.fontSize ?? + defaultSvgTheme?.fontSize ?? + defaultTextStyle.fontSize ?? + // Fallback to the default font size if a font size is missing in DefaultTextStyle. + // See: https://api.flutter.dev/flutter/painting/TextStyle/fontSize.html + 14.0; + + widget.pictureProvider.theme = SvgTheme( + currentColor: currentColor, + fontSize: fontSize, + ); } void _resolveImage() { diff --git a/pubspec.yaml b/pubspec.yaml index 465f037a..a1819e04 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ dependencies: flutter: sdk: flutter meta: ^1.3.0 - path_drawing: ^0.5.1 + path_drawing: ^0.5.1+1 vector_math: ^2.1.0 xml: ^5.0.0 diff --git a/test/default_theme_test.dart b/test/default_theme_test.dart index 5680a757..2ee9dc98 100644 --- a/test/default_theme_test.dart +++ b/test/default_theme_test.dart @@ -2,6 +2,7 @@ import 'dart:ui'; +import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -10,11 +11,12 @@ void main() { testWidgets('changes propagate to SvgPicture', (WidgetTester tester) async { const SvgTheme svgTheme = SvgTheme( currentColor: Color(0xFF733821), + fontSize: 14.0, ); final SvgPicture svgPictureWidget = SvgPicture.string(''' - + '''); await tester.pumpWidget(DefaultSvgTheme( @@ -25,12 +27,13 @@ void main() { SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); expect(svgPicture, isNotNull); expect( - svgPicture.pictureProvider.currentColor, - equals(svgTheme.currentColor), + svgPicture.pictureProvider.theme, + equals(svgTheme), ); const SvgTheme anotherSvgTheme = SvgTheme( currentColor: Color(0xFF05290E), + fontSize: 12.0, ); await tester.pumpWidget(DefaultSvgTheme( @@ -41,16 +44,17 @@ void main() { svgPicture = tester.firstWidget(find.byType(SvgPicture)); expect(svgPicture, isNotNull); expect( - svgPicture.pictureProvider.currentColor, - equals(anotherSvgTheme.currentColor), + svgPicture.pictureProvider.theme, + equals(anotherSvgTheme), ); }); testWidgets( - 'currentColor widget property takes precedence over ' + 'currentColor from the widget\'s theme takes precedence over ' 'the theme from DefaultSvgTheme', (WidgetTester tester) async { const SvgTheme svgTheme = SvgTheme( currentColor: Color(0xFF733821), + fontSize: 14.0, ); final SvgPicture svgPictureWidget = SvgPicture.string( @@ -58,7 +62,10 @@ void main() { ''', - currentColor: Color(0xFF05290E), + theme: SvgTheme( + currentColor: Color(0xFF05290E), + fontSize: 14.0, + ), ); await tester.pumpWidget(DefaultSvgTheme( @@ -69,9 +76,86 @@ void main() { final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); expect(svgPicture, isNotNull); expect( - svgPicture.pictureProvider.currentColor, + svgPicture.pictureProvider.theme.currentColor, equals(Color(0xFF05290E)), ); }); + + testWidgets( + 'fontSize from the widget\'s theme takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + fontSize: 14.0, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + theme: SvgTheme( + fontSize: 12.0, + ), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.theme.fontSize, + equals(12.0), + ); + }); + + testWidgets( + 'fontSize defaults to the font size from DefaultTextStyle ' + 'if no widget\'s theme or DefaultSvgTheme is provided', + (WidgetTester tester) async { + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + ); + + await tester.pumpWidget( + DefaultTextStyle( + style: TextStyle(fontSize: 26.0), + child: svgPictureWidget, + ), + ); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.theme.fontSize, + equals(26.0), + ); + }); + + testWidgets( + 'fontSize defaults to 14 ' + 'if no widget\'s theme, DefaultSvgTheme or DefaultTextStyle is provided', + (WidgetTester tester) async { + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + ); + + await tester.pumpWidget(svgPictureWidget); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.theme.fontSize, + equals(14.0), + ); + }); }); } diff --git a/test/error_test.dart b/test/error_test.dart index 97e5220c..c4d2c9b6 100644 --- a/test/error_test.dart +++ b/test/error_test.dart @@ -23,7 +23,10 @@ void main() { '''; final SvgParser parser = SvgParser(); - await parser.parse(svgStr, key: 'some_svg.svg'); + await parser.parse( + svgStr, + key: 'some_svg.svg', + ); expect( error.context.toString(), diff --git a/test/golden_widget/circle.em.png b/test/golden_widget/circle.em.png new file mode 100644 index 0000000000000000000000000000000000000000..b25ef06cfb940ee7bd201e48bdd5aa440269056a GIT binary patch literal 10223 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 E08E}cL;wH) literal 0 HcmV?d00001 diff --git a/test/golden_widget/ellipse.em.png b/test/golden_widget/ellipse.em.png new file mode 100644 index 0000000000000000000000000000000000000000..ce31c666904280716471bcd8b3b654b2c55787f6 GIT binary patch literal 6672 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 I8~LgK1wH#CDgXcg literal 0 HcmV?d00001 diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index cfdda243..b0358fd5 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -1,6 +1,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/picture_cache.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:xml/xml.dart'; @@ -73,11 +74,16 @@ void main() { ); expect(PictureProvider.cache.count, 0); + + final PictureProvider pictureProvider = StringPicture( + SvgPicture.svgStringDecoderBuilder, + svgString, + )..theme = const SvgTheme( + fontSize: 14.0, + ); + await precachePicture( - StringPicture( - SvgPicture.svgStringDecoderBuilder, - svgString, - ), + pictureProvider, tester.element(find.text('test_text')), ); expect(PictureProvider.cache.count, 1); @@ -133,11 +139,16 @@ void main() { expect(error, isInstanceOf()); } + final PictureProvider pictureProvider = StringPicture( + SvgPicture.svgStringDecoderBuilder, + svgString, + )..theme = const SvgTheme( + currentColor: Color(0xFF05290E), + fontSize: 14.0, + ); + await precachePicture( - StringPicture( - SvgPicture.svgStringDecoderBuilder, - svgString, - ), + pictureProvider, tester.element(find.text('test_text')), onError: errorListener, ); diff --git a/test/picture_provider_test.dart b/test/picture_provider_test.dart index baedd2f4..b72ac51f 100644 --- a/test/picture_provider_test.dart +++ b/test/picture_provider_test.dart @@ -1,8 +1,11 @@ +// ignore_for_file: prefer_const_constructors + import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/src/svg/theme.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; @@ -12,149 +15,211 @@ class MockFile extends Mock implements File {} void main() { group('PictureProvider', () { - Color? currentColor; + SvgTheme? currentTheme; - PictureInfoDecoder decoderBuilder(Color? color) { - currentColor = color; + PictureInfoDecoder decoderBuilder(SvgTheme theme) { + currentTheme = theme; return (T bytes, ColorFilter? colorFilter, String key) async => MockPictureInfo(); } - test( - 'NetworkPicture rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () async { - const Color color = Color(0xFFB0E3BE); - final NetworkPicture networkPicture = - NetworkPicture(decoderBuilder, 'url'); - - final PictureInfoDecoder decoder = networkPicture.decoder; - - expect(decoder, isNotNull); - - // Update the currentColor of PictureProvider. - networkPicture.currentColor = color; - - expect( - decoder, - isNot(equals(networkPicture.decoder)), - ); - - expect( - currentColor, - equals(color), - ); + group( + 'rebuilds the decoder using decoderBuilder ' + 'when currentColor changes', () { + test('NetworkPicture', () async { + const Color color = Color(0xFFB0E3BE); + final NetworkPicture networkPicture = + NetworkPicture(decoderBuilder, 'url') + ..theme = SvgTheme(fontSize: 14.0); + + final PictureInfoDecoder? decoder = networkPicture.decoder; + + // Update the theme of PictureProvider to include currentColor. + networkPicture.theme = SvgTheme( + currentColor: color, + fontSize: 14.0, + ); + + expect(networkPicture.decoder, isNotNull); + expect(networkPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.currentColor, equals(color)); + }); + + test('FilePicture', () async { + const Color color = Color(0xFFB0E3BE); + final FilePicture filePicture = FilePicture(decoderBuilder, MockFile()) + ..theme = SvgTheme(fontSize: 14.0); + + final PictureInfoDecoder? decoder = filePicture.decoder; + + // Update the theme of PictureProvider to include currentColor. + filePicture.theme = SvgTheme( + currentColor: color, + fontSize: 14.0, + ); + + expect(filePicture.decoder, isNotNull); + expect(filePicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.currentColor, equals(color)); + }); + + test('MemoryPicture', () async { + const Color color = Color(0xFFB0E3BE); + final MemoryPicture memoryPicture = + MemoryPicture(decoderBuilder, Uint8List(0)) + ..theme = SvgTheme(fontSize: 14.0); + + final PictureInfoDecoder? decoder = memoryPicture.decoder; + + // Update the theme of PictureProvider to include currentColor. + memoryPicture.theme = SvgTheme( + currentColor: color, + fontSize: 14.0, + ); + + expect(memoryPicture.decoder, isNotNull); + expect(memoryPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.currentColor, equals(color)); + }); + + test('StringPicture', () async { + const Color color = Color(0xFFB0E3BE); + final StringPicture stringPicture = StringPicture(decoderBuilder, '') + ..theme = SvgTheme(fontSize: 14.0); + + final PictureInfoDecoder? decoder = stringPicture.decoder; + + // Update the theme of PictureProvider to include currentColor. + stringPicture.theme = SvgTheme( + currentColor: color, + fontSize: 14.0, + ); + + expect(stringPicture.decoder, isNotNull); + expect(stringPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.currentColor, equals(color)); + }); + + test('ExactAssetPicture', () async { + const Color color = Color(0xFFB0E3BE); + final ExactAssetPicture exactAssetPicture = + ExactAssetPicture(decoderBuilder, '') + ..theme = SvgTheme(fontSize: 14.0); + + final PictureInfoDecoder? decoder = exactAssetPicture.decoder; + + // Update the theme of PictureProvider to include currentColor. + exactAssetPicture.theme = SvgTheme( + currentColor: color, + fontSize: 14.0, + ); + + expect(exactAssetPicture.decoder, isNotNull); + expect(exactAssetPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.currentColor, equals(color)); + }); }); - test( - 'FilePicture rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () async { - const Color color = Color(0xFFB0E3BE); - final FilePicture filePicture = FilePicture(decoderBuilder, MockFile()); - - final PictureInfoDecoder decoder = filePicture.decoder; - - expect(decoder, isNotNull); - - // Update the currentColor of PictureProvider. - filePicture.currentColor = color; - - expect( - decoder, - isNot(equals(filePicture.decoder)), - ); - - expect( - currentColor, - equals(color), - ); + group( + 'rebuilds the decoder using decoderBuilder ' + 'when fontSize changes', () { + test('NetworkPicture', () async { + const double fontSize = 26.0; + final NetworkPicture networkPicture = + NetworkPicture(decoderBuilder, 'url'); + + final PictureInfoDecoder? decoder = networkPicture.decoder; + + // Update the theme of PictureProvider to include fontSize. + networkPicture.theme = SvgTheme( + fontSize: fontSize, + ); + + expect(networkPicture.decoder, isNotNull); + expect(networkPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.fontSize, equals(fontSize)); + }); + + test('FilePicture', () async { + const double fontSize = 26.0; + final FilePicture filePicture = FilePicture(decoderBuilder, MockFile()); + + final PictureInfoDecoder? decoder = filePicture.decoder; + + // Update the theme of PictureProvider to include fontSize. + filePicture.theme = SvgTheme( + fontSize: fontSize, + ); + + expect(filePicture.decoder, isNotNull); + expect(filePicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.fontSize, equals(fontSize)); + }); + + test('MemoryPicture', () async { + const double fontSize = 26.0; + final MemoryPicture memoryPicture = + MemoryPicture(decoderBuilder, Uint8List(0)); + + final PictureInfoDecoder? decoder = memoryPicture.decoder; + + // Update the theme of PictureProvider to include fontSize. + memoryPicture.theme = SvgTheme( + fontSize: fontSize, + ); + + expect(memoryPicture.decoder, isNotNull); + expect(memoryPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.fontSize, equals(fontSize)); + }); + + test('StringPicture', () async { + const double fontSize = 26.0; + final StringPicture stringPicture = StringPicture(decoderBuilder, ''); + + final PictureInfoDecoder? decoder = stringPicture.decoder; + + // Update the theme of PictureProvider to include fontSize. + stringPicture.theme = SvgTheme( + fontSize: fontSize, + ); + + expect(stringPicture.decoder, isNotNull); + expect(stringPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.fontSize, equals(fontSize)); + }); + + test('ExactAssetPicture', () async { + const double fontSize = 26.0; + final ExactAssetPicture exactAssetPicture = + ExactAssetPicture(decoderBuilder, ''); + + final PictureInfoDecoder? decoder = exactAssetPicture.decoder; + + // Update the theme of PictureProvider to include fontSize. + exactAssetPicture.theme = SvgTheme( + fontSize: fontSize, + ); + + expect(exactAssetPicture.decoder, isNotNull); + expect(exactAssetPicture.decoder, isNot(equals(decoder))); + expect(currentTheme?.fontSize, equals(fontSize)); + }); }); - test( - 'MemoryPicture rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () async { - const Color color = Color(0xFFB0E3BE); - final MemoryPicture memoryPicture = - MemoryPicture(decoderBuilder, Uint8List(0)); - - final PictureInfoDecoder decoder = memoryPicture.decoder; - - expect(decoder, isNotNull); - - // Update the currentColor of PictureProvider. - memoryPicture.currentColor = color; - - expect( - decoder, - isNot(equals(memoryPicture.decoder)), - ); - - expect( - currentColor, - equals(color), - ); - }); - - test( - 'StringPicture rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () async { - const Color color = Color(0xFFB0E3BE); - final StringPicture stringPicture = StringPicture(decoderBuilder, ''); - - final PictureInfoDecoder decoder = stringPicture.decoder; - - expect(decoder, isNotNull); - - // Update the currentColor of PictureProvider. - stringPicture.currentColor = color; - - expect( - decoder, - isNot(equals(stringPicture.decoder)), - ); - - expect( - currentColor, - equals(color), - ); - }); - - test( - 'ExactAssetPicture rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () async { - const Color color = Color(0xFFB0E3BE); - final ExactAssetPicture exactAssetPicture = - ExactAssetPicture(decoderBuilder, ''); - - final PictureInfoDecoder decoder = exactAssetPicture.decoder; - - expect(decoder, isNotNull); - - // Update the currentColor of PictureProvider. - exactAssetPicture.currentColor = color; - - expect( - decoder, - isNot(equals(exactAssetPicture.decoder)), - ); - - expect( - currentColor, - equals(color), - ); - }); - - test('Evicts from cache when currentColor changes', () async { + test('Evicts from cache when theme changes', () async { expect(PictureProvider.cache.count, 0); const Color color = Color(0xFFB0E3BE); final StringPicture stringPicture = StringPicture(decoderBuilder, ''); - final PictureStream stream = + final PictureStream _ = stringPicture.resolve(createLocalPictureConfiguration(null)); await null; expect(PictureProvider.cache.count, 1); - stringPicture.currentColor = color; + stringPicture.theme = SvgTheme(currentColor: color); + expect(PictureProvider.cache.count, 0); }); }); diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index 60614f43..0472f620 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' show Color, PathFillType; +import 'dart:ui' show Color, Offset, PathFillType, Size; import 'package:flutter_svg/parser.dart'; import 'package:flutter_svg/src/svg/parsers.dart'; @@ -113,29 +113,52 @@ void main() { } test('Font size parsing tests', () { - expect(parseFontSize(null), isNull); - expect(parseFontSize(''), isNull); - expect(parseFontSize('1'), 1); - expect(parseFontSize(' 1 '), 1); - expect(parseFontSize('xx-small'), 10); - expect(parseFontSize('x-small'), 12); - expect(parseFontSize('small'), 14); - expect(parseFontSize('medium'), 18); - expect(parseFontSize('large'), 22); - expect(parseFontSize('x-large'), 26); - expect(parseFontSize('xx-large'), 32); - - expect(parseFontSize('larger'), parseFontSize('large')); - expect(parseFontSize('larger', parentValue: parseFontSize('large')), - parseFontSize('large')! * 1.2); - expect(parseFontSize('smaller'), parseFontSize('small')); - expect(parseFontSize('smaller', parentValue: parseFontSize('large')), - parseFontSize('large')! / 1.2); - - expect(() => parseFontSize('invalid'), + const double fontSize = 14.0; + expect(parseFontSize(null, fontSize: fontSize), isNull); + expect(parseFontSize('', fontSize: fontSize), isNull); + expect(parseFontSize('1', fontSize: fontSize), 1); + expect(parseFontSize(' 1 ', fontSize: fontSize), 1); + expect(parseFontSize('xx-small', fontSize: fontSize), 10); + expect(parseFontSize('x-small', fontSize: fontSize), 12); + expect(parseFontSize('small', fontSize: fontSize), 14); + expect(parseFontSize('medium', fontSize: fontSize), 18); + expect(parseFontSize('large', fontSize: fontSize), 22); + expect(parseFontSize('x-large', fontSize: fontSize), 26); + expect(parseFontSize('xx-large', fontSize: fontSize), 32); + + expect(parseFontSize('larger', fontSize: fontSize), + parseFontSize('large', fontSize: fontSize)); + expect( + parseFontSize('larger', + fontSize: fontSize, + parentValue: parseFontSize('large', fontSize: fontSize)), + parseFontSize('large', fontSize: fontSize)! * 1.2); + expect(parseFontSize('smaller', fontSize: fontSize), + parseFontSize('small', fontSize: fontSize)); + expect( + parseFontSize('smaller', + fontSize: fontSize, + parentValue: parseFontSize('large', fontSize: fontSize)), + parseFontSize('large', fontSize: fontSize)! / 1.2); + + expect(() => parseFontSize('invalid', fontSize: fontSize), throwsA(const TypeMatcher())); }); + test('relative font size tests', () { + const double fontSize = 26.0; + + expect( + parseFontSize('4em', fontSize: fontSize), + equals(4 * fontSize), + ); + + expect( + parseFontSize(' 2em ', fontSize: fontSize), + equals(2 * fontSize), + ); + }); + test('Check no child with id for svg', () async { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( @@ -200,6 +223,7 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse(svgStr); + expect(root.id!.isEmpty, true); expect(find(root, 'Page-1') != null, true); expect(find(root, 'iPhone-8') != null, true); @@ -290,7 +314,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -318,7 +345,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -344,7 +374,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + theme: const SvgTheme( + currentColor: Color(0xFFB0E3BE), + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -372,7 +405,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -400,7 +436,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -426,7 +465,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + theme: const SvgTheme( + currentColor: Color(0xFFB0E3BE), + fontSize: 14.0, + ), ); final DrawableShape? circle = find(root, 'circle'); @@ -460,7 +502,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableLinearGradient? gradient = @@ -498,7 +543,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: currentColor), + theme: const SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ), ); final DrawableLinearGradient? gradient = @@ -536,7 +584,10 @@ void main() { final SvgParser parser = SvgParser(); final DrawableRoot root = await parser.parse( svgStr, - theme: const SvgTheme(currentColor: Color(0xFFB0E3BE)), + theme: const SvgTheme( + currentColor: Color(0xFFB0E3BE), + fontSize: 14.0, + ), ); final DrawableLinearGradient? gradient = @@ -556,4 +607,177 @@ void main() { }); }); }); + + group('calculates em units based on the font size for', () { + test('svg (width, height)', () async { + const String svgStr = ''' + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + expect(root.viewport.width, equals(fontSize * 5)); + expect(root.viewport.height, equals(fontSize * 6)); + }); + + test('use (x, y)', () async { + const String svgStr = ''' + + + + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + final DrawableGroup? circle = find(root, 'anotherCircle'); + + const double expectedX = fontSize * 2; + const double expectedY = fontSize * 4; + + expect(circle, isNotNull); + expect( + circle!.transform, + equals( + (Matrix4.identity()..translate(expectedX, expectedY)).storage, + ), + ); + }); + + test('text (x, y)', () async { + const String svgStr = ''' + + Test + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + final DrawableText? text = find(root, 'text'); + + const Offset expectedOffset = Offset(fontSize * 2, fontSize * 4); + + expect(text, isNotNull); + expect(text!.offset, equals(expectedOffset)); + }); + + test('radialGradient (cx, cy, r, fx, fy)', () async { + const String svgStr = ''' + + + + + + + + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + final DrawableRadialGradient? gradient = + root.definitions.getGradient('url(#gradient)'); + + expect(gradient, isNotNull); + + const Offset expectedOffset = Offset(fontSize * 1, fontSize * 2); + const double expectedRadius = fontSize * 1.1; + const Offset expectedFocal = Offset(fontSize * 1.5, fontSize * 1.6); + + expect(gradient, isNotNull); + expect(gradient!.center, equals(expectedOffset)); + expect(gradient.radius, equals(expectedRadius)); + expect(gradient.focal, equals(expectedFocal)); + }); + + test('linearGradient (x1, y1, x2, y2)', () async { + const String svgStr = ''' + + + + + + + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + final DrawableLinearGradient? gradient = + root.definitions.getGradient('url(#gradient)'); + + expect(gradient, isNotNull); + + const Offset expectedFromOffset = Offset(fontSize * 1, fontSize * 1.75); + const Offset expectedToOffset = Offset(fontSize * 1.5, fontSize * 1.6); + + expect(gradient, isNotNull); + expect(gradient!.from, equals(expectedFromOffset)); + expect(gradient.to, equals(expectedToOffset)); + }); + + test('image (x, y, width, height)', () async { + const String svgStr = ''' + + + +'''; + + const double fontSize = 26.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + ), + ); + + final DrawableRasterImage? image = + find(root, 'image'); + + const Offset expectedOffset = Offset(fontSize * 1, fontSize * 0.5); + const Size expectedSize = Size(fontSize * 2, fontSize * 1.5); + + expect(image, isNotNull); + expect(image!.offset, equals(expectedOffset)); + expect(image.size, equals(expectedSize)); + }); + }); } diff --git a/test/theme_test.dart b/test/theme_test.dart index af2d270f..998d45dd 100644 --- a/test/theme_test.dart +++ b/test/theme_test.dart @@ -11,20 +11,48 @@ void main() { const Color currentColor = Color(0xFFB0E3BE); expect( - SvgTheme(currentColor: currentColor).currentColor, + SvgTheme( + currentColor: currentColor, + fontSize: 14.0, + ).currentColor, equals(currentColor), ); }); + + test('sets fontSize', () { + const double fontSize = 14.0; + + expect( + SvgTheme( + currentColor: Color(0xFFB0E3BE), + fontSize: fontSize, + ).fontSize, + equals(fontSize), + ); + }); + + test( + 'sets fontSize to 14 ' + 'by default', () { + expect( + SvgTheme(), + equals( + SvgTheme(fontSize: 14.0), + ), + ); + }); }); test('supports value equality', () { expect( SvgTheme( currentColor: Color(0xFF6F2173), + fontSize: 14.0, ), equals( SvgTheme( currentColor: Color(0xFF6F2173), + fontSize: 14.0, ), ), ); diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index 4adfcc05..250ab0cf 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -35,7 +35,6 @@ void main() { false, const ColorFilter.mode(Color(0xFF00FF00), BlendMode.color), 'test', - theme: const SvgTheme(), ); final Image image = await info.picture!.toImage(2, 2); final ByteData data = (await image.toByteData())!; @@ -59,7 +58,6 @@ void main() { false, null, 'test', - theme: const SvgTheme(), ); expect(info.createLayer().isComplexHint, true); diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 198d7931..bb51e695 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -597,10 +597,8 @@ void main() { testWidgets('Nested SVG elements report a FlutterError', (WidgetTester tester) async { await svg.fromSvgString( - '', - 'test', - theme: const SvgTheme(), - ); + '', + 'test'); final UnsupportedError error = tester.takeException() as UnsupportedError; expect(error.message, 'Unsupported nested element.'); }); @@ -752,6 +750,102 @@ void main() { expect(renderObject.clipBehavior, equals(Clip.antiAlias)); }); + group('SvgPicture respects em units', () { + testWidgets('circle (cx, cy, r)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme(fontSize: 600), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'circle.em.png'); + }); + + testWidgets('rect (x, y, width, height, rx, ry)', + (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme(fontSize: 100), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'rect.em.png'); + }); + + testWidgets('ellipse (cx, cy, rx, ry)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme(fontSize: 100), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'ellipse.em.png'); + }); + + testWidgets('line (x1, x2, y1, y2)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme(fontSize: 100), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'line.em.png'); + }); + }); + testWidgets('SvgPicture - two of the same', (WidgetTester tester) async { // Regression test to make sure the same SVG can render twice in the same // view. If layers are incorrectly reused, this will fail. diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index 46001688..f208960b 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/svg/xml_parsers.dart'; import 'package:flutter_svg/src/utilities/xml.dart'; +import 'package:path_drawing/path_drawing.dart'; import 'package:test/test.dart'; import 'package:xml/xml_events.dart'; @@ -80,35 +81,65 @@ void main() { parseEvents('').first as XmlStartElementEvent; expect( - parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())! + parseViewBox( + svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(), + fontSize: 14.0, + )! .size, const Size(50, 50)); expect( - parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxRect, + parseViewBox( + svgWithViewBox.attributes.toAttributeMap(), + fontSize: 14.0, + )! + .viewBoxRect, rect); expect( - parseViewBox(svgWithViewBox.attributes.toAttributeMap())!.viewBoxOffset, + parseViewBox( + svgWithViewBox.attributes.toAttributeMap(), + fontSize: 14.0, + )! + .viewBoxOffset, Offset.zero); expect( - parseViewBox(svgWithViewBoxAndWidthHeight.attributes.toAttributeMap())! + parseViewBox( + svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(), + fontSize: 14.0, + )! .viewBoxRect, rect); expect( - parseViewBox(svgWithWidthHeight.attributes.toAttributeMap())! + parseViewBox( + svgWithWidthHeight.attributes.toAttributeMap(), + fontSize: 14.0, + )! .viewBoxRect, rect); expect( - parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap(), - nullOk: true), + parseViewBox( + svgWithNoSizeInfo.attributes.toAttributeMap(), + fontSize: 14.0, + nullOk: true, + ), null); - expect(() => parseViewBox(svgWithNoSizeInfo.attributes.toAttributeMap()), + expect( + () => parseViewBox( + svgWithNoSizeInfo.attributes.toAttributeMap(), + fontSize: 14.0, + ), throwsStateError); expect( - parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())! + parseViewBox( + svgWithViewBoxMinXMinY.attributes.toAttributeMap(), + fontSize: 14.0, + )! .viewBoxRect, rect); expect( - parseViewBox(svgWithViewBoxMinXMinY.attributes.toAttributeMap())! + parseViewBox( + svgWithViewBoxMinXMinY.attributes.toAttributeMap(), + fontSize: 14.0, + )! .viewBoxOffset, const Offset(-42.0, -56.0)); }); @@ -147,9 +178,21 @@ void main() { parseEvents('').first as XmlStartElementEvent; - // TODO(dnfield): DashOffset is completely opaque right now, maybe expose the raw value? - expect(parseDashOffset(abs.attributes.toAttributeMap()), isNotNull); - expect(parseDashOffset(pct.attributes.toAttributeMap()), isNotNull); + expect( + parseDashOffset( + abs.attributes.toAttributeMap(), + fontSize: 14.0, + ), + equals(const DashOffset.absolute(20.0)), + ); + + expect( + parseDashOffset( + pct.attributes.toAttributeMap(), + fontSize: 14.0, + ), + equals(DashOffset.percentage(0.2)), + ); }); test('font-weight tests', () { @@ -213,9 +256,13 @@ void main() { null, null, currentColor: currentColor, + fontSize: 14.0, ); - expect(svgStyle.stroke?.color, equals(currentColor)); + expect( + svgStyle.stroke?.color, + equals(currentColor), + ); }); test('uses currentColor for fill color', () { @@ -231,9 +278,93 @@ void main() { null, null, currentColor: currentColor, + fontSize: 14.0, + ); + + expect( + svgStyle.fill?.color, + equals(currentColor), + ); + }); + + test( + 'calculates em units based on the font size ' + 'for stroke width', () { + final XmlStartElementEvent svg = + parseEvents('').first + as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, ); - expect(svgStyle.fill?.color, equals(currentColor)); + expect( + svgStyle.stroke?.strokeWidth, + equals(fontSize * 2), + ); + }); + + test( + 'calculates em units based on the font size ' + 'for dash array', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + ); + + expect( + [ + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + ], + equals([ + fontSize * 0.2, + fontSize * 0.5, + 10, + ]), + ); + }); + + test( + 'calculates em units based on the font size ' + 'for dash offset', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + ); + + expect( + svgStyle.dashOffset, + equals(const DashOffset.absolute(fontSize * 0.15)), + ); }); }); } diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart index afb04a1d..80f4faff 100644 --- a/tool/gen_golden.dart +++ b/tool/gen_golden.dart @@ -19,8 +19,11 @@ Future getSvgImage(String svgData) async { const Size size = Size(200.0, 200.0); - final DrawableRoot svgRoot = - await svg.fromSvgString(svgData, 'GenGoldenTest'); + final DrawableRoot svgRoot = await svg.fromSvgString( + svgData, + 'GenGoldenTest', + ); + svgRoot.scaleCanvasToViewBox(canvas, size); svgRoot.clipCanvasToViewBox(canvas); From 3cd92c6cf747c64d8d6624c3e7f4029db8cb3c4a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 29 Nov 2021 16:47:37 -0800 Subject: [PATCH 036/142] Update picture_provider.dart --- lib/src/picture_provider.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index e3951191..d6edfa70 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -333,7 +333,6 @@ abstract class PictureProvider { final ColorFilter? colorFilter; /// The default theme used when parsing SVG elements. - @visibleForTesting SvgTheme get theme => _theme; SvgTheme _theme; From 5e484da0b0829c515aabd20b7d0975ab9bbfe718 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 29 Nov 2021 23:07:35 -0800 Subject: [PATCH 037/142] Update picture_provider.dart --- lib/src/picture_provider.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index d6edfa70..00d732b1 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -314,7 +314,6 @@ abstract class PictureProvider { final PictureInfoDecoderBuilder decoderBuilder; /// The [PictureInfoDecoder] to use for loading this picture. - @visibleForTesting PictureInfoDecoder decoder; /// The [PictureCache] for [Picture] objects created by [PictureProvider] From b02ee6f3afa5a7bcd764f86cc703e367104389a5 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 30 Nov 2021 11:29:13 -0800 Subject: [PATCH 038/142] Update xml_parsers.dart --- lib/src/svg/xml_parsers.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index de53a91f..7126866f 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -32,7 +32,8 @@ double _parseRawWidthHeight( } return true; }()); - return parseDoubleWithUnits(raw, fontSize: fontSize) ?? double.infinity; + return parseDoubleWithUnits(raw, fontSize: fontSize, tryParse: true) ?? + double.infinity; } /// Parses an SVG @viewBox attribute (e.g. 0 0 100 100) to a [Rect]. From 8d1ec8492fe9bfb527ba82b15e11cf1ccaa4ba17 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 30 Nov 2021 22:53:04 -0800 Subject: [PATCH 039/142] update readme --- README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/README.md b/README.md index 2d06fb48..8b13abb6 100644 --- a/README.md +++ b/README.md @@ -135,19 +135,6 @@ try { - You want to load SVGs dynamically from network sources at runtime. - You want to paint SVG data and render it to an image. -## TODO - -This list is not very well ordered. I'm mainly picking up things that seem -interesting or useful, or where I've gotten a request to fix something/example -of something that's broken. - -- Support Radial gradients that use percentages in the offsets. -- Dash path with percentage dasharray values (need good examples). -- Markers. -- Filters/effects (will require upstream engine changes, but doable). -- Android Vector Drawable support beyond PoC - I'm willing to put more time into - this if there's actually demand, but it doesn't come up often. - ## Out of scope/non-goals - SMIL animations. That just seems crazy. I think it'll be possible to animate From 1c47efa5324efadf93e08a1abd186d1911a41458 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Dec 2021 10:37:30 -0800 Subject: [PATCH 040/142] Version bump information --- CHANGELOG.md | 2 ++ lib/src/svg/xml_parsers.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75dcdadd..69d1cbf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ near or overlapping an animating widget. Also should improve raster cacheability. - Correctly list web as a supported platform. +- Support for em/ex units. +- Stable 1.0.0 release. ## 0.23.0+1 diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index 7126866f..fd4872a8 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -32,7 +32,7 @@ double _parseRawWidthHeight( } return true; }()); - return parseDoubleWithUnits(raw, fontSize: fontSize, tryParse: true) ?? + return parseDoubleWithUnits(raw, fontSize: fontSize, tryParse: true) ?? double.infinity; } diff --git a/pubspec.yaml b/pubspec.yaml index a1819e04..7007f00f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ dependencies: flutter: sdk: flutter meta: ^1.3.0 - path_drawing: ^0.5.1+1 + path_drawing: ^1.0.0 vector_math: ^2.1.0 xml: ^5.0.0 From fa5f0c3f4b4a669d6344a6836259a3c063a1650b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=C3=A0o=20Ho=C3=A0ng=20S=C6=A1n?= Date: Fri, 3 Dec 2021 22:37:21 +0700 Subject: [PATCH 041/142] Requires Flutter >=2.4.0 for LayerHandle usage. (#611) See https://github.com/flutter/flutter/commit/025397ae3f925b316991912977367d3263cc4432 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7007f00f..7ca0bf79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,7 @@ dev_dependencies: environment: sdk: '>=2.12.0 <3.0.0' - flutter: ">=1.24.0-6.0.pre" + flutter: ">=2.4.0-0.0.pre" ## For developing features that require new functionality in engine: # dependency_overrides: From dc9e644a3652c4200a7d6dd523ee88e8823080ba Mon Sep 17 00:00:00 2001 From: Bartosz Selwesiuk Date: Wed, 8 Dec 2021 18:31:31 +0100 Subject: [PATCH 042/142] Add support for ex units (#618) * feat: add xHeight to SvgTheme * test: add SvgTheme xHeight tests * feat: use xHeight when updating PictureProvider in SvgPicture * test: add xHeight to DefaultSvgTheme and PictureProvider tests * feat: add support for parsing ex units * test: fix existing tests after introducing xHeight * test: add DefaultSvgTheme xHeight tests * test: add parseStyle xHeight tests (stroke width, dash array, dash offset) * test: add SvgParser xHeight tests (svg, use, text, radialGradient, linearGradient, image) * test: add SvgPicture xHeight tests for shapes (circle, rect, ellipse, line) * test: PictureProvider rebuilds a decoder when the theme changes * test: fix relative font size tests * test: add ex font size tests * test: fix DefaultSvgTheme tests * revert: SvgTheme equals operator should use runtimeType --- lib/src/svg/parser_state.dart | 105 ++++-- lib/src/svg/parsers.dart | 5 +- lib/src/svg/theme.dart | 14 +- lib/src/svg/xml_parsers.dart | 32 +- lib/src/utilities/numbers.dart | 19 +- lib/svg.dart | 6 + test/default_theme_test.dart | 55 ++++ .../{circle.em.png => circle.em_ex.png} | Bin .../{ellipse.em.png => ellipse.em_ex.png} | Bin .../{line.em.png => line.em_ex.png} | Bin .../{rect.em.png => rect.em_ex.png} | Bin test/picture_cache_test.dart | 1 + test/picture_provider_test.dart | 127 ++------ test/svg_parsers_test.dart | 305 ++++++++++++++++-- test/theme_test.dart | 27 ++ test/widget_svg_test.dart | 118 ++++++- test/xml_svg_test.dart | 246 +++++++++----- 17 files changed, 812 insertions(+), 248 deletions(-) rename test/golden_widget/{circle.em.png => circle.em_ex.png} (100%) rename test/golden_widget/{ellipse.em.png => ellipse.em_ex.png} (100%) rename test/golden_widget/{line.em.png => line.em_ex.png} (100%) rename test/golden_widget/{rect.em.png => rect.em_ex.png} (100%) diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index c1952765..d805df1e 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -20,7 +20,7 @@ final Set _unhandledElements = {'title', 'desc'}; typedef _ParseFunc = Future? Function( SvgParserState parserState, bool warningsAsErrors); typedef _PathFunc = Path? Function( - Map attributes, double fontSize); + Map attributes, double fontSize, double xHeight); final RegExp _trimPattern = RegExp(r'[\r|\n|\t]'); @@ -52,20 +52,31 @@ Offset _parseCurrentOffset(SvgParserState parserState, Offset? lastOffset) { final String? x = parserState.attribute('x', def: null); final String? y = parserState.attribute('y', def: null); final double fontSize = parserState.fontSize; + final double xHeight = parserState.xHeight; return Offset( x != null - ? parseDoubleWithUnits(x, fontSize: fontSize)! + ? parseDoubleWithUnits( + x, + fontSize: fontSize, + xHeight: xHeight, + )! : parseDoubleWithUnits( parserState.attribute('dx', def: '0'), fontSize: fontSize, + xHeight: xHeight, )! + (lastOffset?.dx ?? 0), y != null - ? parseDoubleWithUnits(y, fontSize: fontSize)! + ? parseDoubleWithUnits( + y, + fontSize: fontSize, + xHeight: xHeight, + )! : parseDoubleWithUnits( parserState.attribute('dy', def: '0'), fontSize: fontSize, + xHeight: xHeight, )! + (lastOffset?.dy ?? 0), ); @@ -92,6 +103,7 @@ class _Elements { final DrawableViewport? viewBox = parseViewBox( parserState.attributes, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ); final String? id = parserState.attribute('id', def: ''); @@ -136,6 +148,7 @@ class _Elements { null, currentColor: color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), color: color, ), @@ -156,6 +169,7 @@ class _Elements { null, currentColor: color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), color: color, ); @@ -179,6 +193,7 @@ class _Elements { parent.style, currentColor: color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), transform: parseTransform(parserState.attribute('transform'))?.storage, color: color, @@ -207,6 +222,7 @@ class _Elements { parent.style, currentColor: color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), transform: parseTransform(parserState.attribute('transform'))?.storage, color: color, @@ -230,6 +246,7 @@ class _Elements { parent!.style, currentColor: parent.color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ); final Matrix4 transform = @@ -239,10 +256,12 @@ class _Elements { parseDoubleWithUnits( parserState.attribute('x', def: '0'), fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), parseDoubleWithUnits( parserState.attribute('y', def: '0'), fontSize: parserState.fontSize, + xHeight: parserState.xHeight, )!, ); @@ -301,6 +320,7 @@ class _Elements { bool warningsAsErrors, ) { final double fontSize = parserState.fontSize; + final double xHeight = parserState.xHeight; final String? gradientUnits = getAttribute( parserState.attributes, 'gradientUnits', @@ -351,24 +371,24 @@ class _Elements { cx = isPercentage(rawCx!) ? parsePercentage(rawCx) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDoubleWithUnits(rawCx, fontSize: fontSize)!; + : parseDoubleWithUnits(rawCx, fontSize: fontSize, xHeight: xHeight)!; cy = isPercentage(rawCy!) ? parsePercentage(rawCy) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDoubleWithUnits(rawCy, fontSize: fontSize)!; + : parseDoubleWithUnits(rawCy, fontSize: fontSize, xHeight: xHeight)!; r = isPercentage(rawR!) ? parsePercentage(rawR) * ((parserState.rootBounds.height + parserState.rootBounds.width) / 2) - : parseDoubleWithUnits(rawR, fontSize: fontSize)!; + : parseDoubleWithUnits(rawR, fontSize: fontSize, xHeight: xHeight)!; fx = isPercentage(rawFx!) ? parsePercentage(rawFx) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDoubleWithUnits(rawFx, fontSize: fontSize)!; + : parseDoubleWithUnits(rawFx, fontSize: fontSize, xHeight: xHeight)!; fy = isPercentage(rawFy!) ? parsePercentage(rawFy) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDoubleWithUnits(rawFy, fontSize: fontSize)!; + : parseDoubleWithUnits(rawFy, fontSize: fontSize, xHeight: xHeight)!; } parserState._definitions.addGradient( @@ -393,6 +413,7 @@ class _Elements { static Future? linearGradient( SvgParserState parserState, bool warningsAsErrors) { final double fontSize = parserState.fontSize; + final double xHeight = parserState.xHeight; final String? gradientUnits = getAttribute( parserState.attributes, 'gradientUnits', @@ -445,22 +466,22 @@ class _Elements { isPercentage(x1!) ? parsePercentage(x1) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDoubleWithUnits(x1, fontSize: fontSize)!, + : parseDoubleWithUnits(x1, fontSize: fontSize, xHeight: xHeight)!, isPercentage(y1!) ? parsePercentage(y1) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDoubleWithUnits(y1, fontSize: fontSize)!, + : parseDoubleWithUnits(y1, fontSize: fontSize, xHeight: xHeight)!, ); toOffset = Offset( isPercentage(x2!) ? parsePercentage(x2) * parserState.rootBounds.width + parserState.rootBounds.left - : parseDoubleWithUnits(x2, fontSize: fontSize)!, + : parseDoubleWithUnits(x2, fontSize: fontSize, xHeight: xHeight)!, isPercentage(y2!) ? parsePercentage(y2) * parserState.rootBounds.height + parserState.rootBounds.top - : parseDoubleWithUnits(y2, fontSize: fontSize)!, + : parseDoubleWithUnits(y2, fontSize: fontSize, xHeight: xHeight)!, ); } @@ -497,7 +518,11 @@ class _Elements { if (pathFn != null) { final Path nextPath = applyTransformIfNeeded( - pathFn(parserState.attributes, parserState.fontSize), + pathFn( + parserState.attributes, + parserState.fontSize, + parserState.xHeight, + ), parserState.attributes, )!; nextPath.fillType = @@ -556,6 +581,7 @@ class _Elements { static Future image( SvgParserState parserState, bool warningsAsErrors) async { final double fontSize = parserState.fontSize; + final double xHeight = parserState.xHeight; final String? href = getHrefAttribute(parserState.attributes); if (href == null) { return; @@ -564,20 +590,24 @@ class _Elements { parseDoubleWithUnits( parserState.attribute('x', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!, parseDoubleWithUnits( parserState.attribute('y', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!, ); final Size size = Size( parseDoubleWithUnits( parserState.attribute('width', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!, parseDoubleWithUnits( parserState.attribute('height', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!, ); final Image image = await resolveImage(href); @@ -595,6 +625,7 @@ class _Elements { parentStyle, currentColor: parent.color, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), size: size, transform: parseTransform(parserState.attribute('transform'))?.storage, @@ -681,6 +712,7 @@ class _Elements { parserState.rootBounds, parentStyle, fontSize: parserState.fontSize, + xHeight: parserState.xHeight, ), currentOffset, transform, @@ -715,44 +747,57 @@ class _Elements { // ignore: avoid_classes_with_only_static_members class _Paths { - static Path circle(Map attributes, double fontSize) { + static Path circle( + Map attributes, + double fontSize, + double xHeight, + ) { final double cx = parseDoubleWithUnits( getAttribute(attributes, 'cx', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double cy = parseDoubleWithUnits( getAttribute(attributes, 'cy', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double r = parseDoubleWithUnits( getAttribute(attributes, 'r', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final Rect oval = Rect.fromCircle(center: Offset(cx, cy), radius: r); return Path()..addOval(oval); } - static Path path(Map attributes, double fontSize) { + static Path path( + Map attributes, double fontSize, double xHeight) { final String d = getAttribute(attributes, 'd')!; return parseSvgPathData(d); } - static Path rect(Map attributes, double fontSize) { + static Path rect( + Map attributes, double fontSize, double xHeight) { final double x = parseDoubleWithUnits( getAttribute(attributes, 'x', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double y = parseDoubleWithUnits( getAttribute(attributes, 'y', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double w = parseDoubleWithUnits( getAttribute(attributes, 'width', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double h = parseDoubleWithUnits( getAttribute(attributes, 'height', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final Rect rect = Rect.fromLTWH(x, y, w, h); String? rxRaw = getAttribute(attributes, 'rx', def: null); @@ -764,10 +809,12 @@ class _Paths { final double rx = parseDoubleWithUnits( rxRaw, fontSize: fontSize, + xHeight: xHeight, )!; final double ry = parseDoubleWithUnits( ryRaw, fontSize: fontSize, + xHeight: xHeight, )!; return Path()..addRRect(RRect.fromRectXY(rect, rx, ry)); @@ -776,11 +823,13 @@ class _Paths { return Path()..addRect(rect); } - static Path? polygon(Map attributes, double fontSize) { + static Path? polygon( + Map attributes, double fontSize, double xHeight) { return parsePathFromPoints(attributes, true); } - static Path? polyline(Map attributes, double fontSize) { + static Path? polyline( + Map attributes, double fontSize, double xHeight) { return parsePathFromPoints(attributes, false); } @@ -794,44 +843,54 @@ class _Paths { return parseSvgPathData(path); } - static Path ellipse(Map attributes, double fontSize) { + static Path ellipse( + Map attributes, double fontSize, double xHeight) { final double cx = parseDoubleWithUnits( getAttribute(attributes, 'cx', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double cy = parseDoubleWithUnits( getAttribute(attributes, 'cy', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double rx = parseDoubleWithUnits( getAttribute(attributes, 'rx', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double ry = parseDoubleWithUnits( getAttribute(attributes, 'ry', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final Rect r = Rect.fromLTWH(cx - rx, cy - ry, rx * 2, ry * 2); return Path()..addOval(r); } - static Path line(Map attributes, double fontSize) { + static Path line( + Map attributes, double fontSize, double xHeight) { final double x1 = parseDoubleWithUnits( getAttribute(attributes, 'x1', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double x2 = parseDoubleWithUnits( getAttribute(attributes, 'x2', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double y1 = parseDoubleWithUnits( getAttribute(attributes, 'y1', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; final double y2 = parseDoubleWithUnits( getAttribute(attributes, 'y2', def: '0'), fontSize: fontSize, + xHeight: xHeight, )!; return Path() @@ -1011,7 +1070,7 @@ class SvgParserState { final DrawableParent parent = _parentDrawables.last.drawable!; final DrawableStyle? parentStyle = parent.style; - final Path path = pathFunc(attributes, fontSize)!; + final Path path = pathFunc(attributes, fontSize, xHeight)!; final DrawableStyleable drawable = DrawableShape( getAttribute(attributes, 'id', def: ''), path, @@ -1024,6 +1083,7 @@ class SvgParserState { defaultFillColor: colorBlack, currentColor: parent.color, fontSize: fontSize, + xHeight: xHeight, ), transform: parseTransform(getAttribute(attributes, 'transform'))?.storage, ); @@ -1092,4 +1152,7 @@ class SvgParserState { extension on SvgParserState { /// Retrieves the font size of the current [theme]. double get fontSize => theme.fontSize; + + /// Retrieves the x-height of the current [theme]. + double get xHeight => theme.xHeight; } diff --git a/lib/src/svg/parsers.dart b/lib/src/svg/parsers.dart index 36e89e87..14d226d9 100644 --- a/lib/src/svg/parsers.dart +++ b/lib/src/svg/parsers.dart @@ -21,10 +21,12 @@ final Map _kTextSizeMap = { /// Parses a `font-size` attribute. /// -/// Uses [fontSize] to calculate the font size including em units. +/// Uses [fontSize] and [xHeight] to calculate the font size +/// that includes em or ex units. double? parseFontSize( String? raw, { required double fontSize, + required double xHeight, double? parentValue, }) { if (raw == null || raw == '') { @@ -35,6 +37,7 @@ double? parseFontSize( raw, tryParse: true, fontSize: fontSize, + xHeight: xHeight, ); if (ret != null) { return ret; diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart index 1cde53d9..9ab6dbdd 100644 --- a/lib/src/svg/theme.dart +++ b/lib/src/svg/theme.dart @@ -12,7 +12,8 @@ class SvgTheme { const SvgTheme({ this.currentColor, this.fontSize = 14, - }); + double? xHeight, + }) : xHeight = xHeight ?? fontSize / 2; /// The default color applied to SVG elements that inherit the color property. /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword @@ -22,16 +23,23 @@ class SvgTheme { /// See: https://www.w3.org/TR/SVG11/coords.html#Units final double fontSize; + /// The x-height (corpus size) of the font used when calculating ex units of SVG elements. + /// Defaults to [fontSize] / 2 if not provided. + /// See: https://www.w3.org/TR/SVG11/coords.html#Units, https://en.wikipedia.org/wiki/X-height + final double xHeight; + @override bool operator ==(dynamic other) { if (other.runtimeType != runtimeType) { return false; } + return other is SvgTheme && currentColor == other.currentColor && - fontSize == other.fontSize; + fontSize == other.fontSize && + xHeight == other.xHeight; } @override - int get hashCode => hashValues(currentColor, fontSize); + int get hashCode => hashValues(currentColor, fontSize, xHeight); } diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index fd4872a8..68fc881e 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -13,6 +13,7 @@ import 'parsers.dart'; double _parseRawWidthHeight( String? raw, { required double fontSize, + required double xHeight, }) { if (raw == '100%' || raw == '') { return double.infinity; @@ -21,18 +22,21 @@ double _parseRawWidthHeight( final RegExp notDigits = RegExp(r'[^\d\.]'); if (!raw!.endsWith('px') && !raw.endsWith('em') && + !raw.endsWith('ex') && raw.contains(notDigits)) { print( 'Warning: Flutter SVG only supports the following formats for `width` and `height` on the SVG root:\n' ' width="100%"\n' ' width="100em"\n' + ' width="100ex"\n' ' width="100px"\n' ' width="100" (where the number will be treated as pixels).\n' 'The supplied value ($raw) will be discarded and treated as if it had not been specified.'); } return true; }()); - return parseDoubleWithUnits(raw, fontSize: fontSize, tryParse: true) ?? + return parseDoubleWithUnits(raw, + fontSize: fontSize, xHeight: xHeight, tryParse: true) ?? double.infinity; } @@ -46,6 +50,7 @@ double _parseRawWidthHeight( DrawableViewport? parseViewBox( Map svg, { required double fontSize, + required double xHeight, bool nullOk = false, }) { final String? viewBox = getAttribute(svg, 'viewBox'); @@ -64,15 +69,11 @@ DrawableViewport? parseViewBox( ' $svg'); } - final double width = _parseRawWidthHeight( - rawWidth, - fontSize: fontSize, - ); + final double width = + _parseRawWidthHeight(rawWidth, fontSize: fontSize, xHeight: xHeight); - final double height = _parseRawWidthHeight( - rawHeight, - fontSize: fontSize, - ); + final double height = + _parseRawWidthHeight(rawHeight, fontSize: fontSize, xHeight: xHeight); if (viewBox == '') { return DrawableViewport( @@ -128,6 +129,7 @@ TileMode parseTileMode(Map attributes) { CircularIntervalList? parseDashArray( Map attributes, { required double fontSize, + required double xHeight, }) { final String? rawDashArray = getAttribute(attributes, 'stroke-dasharray'); if (rawDashArray == '') { @@ -138,7 +140,8 @@ CircularIntervalList? parseDashArray( final List parts = rawDashArray!.split(RegExp(r'[ ,]+')); return CircularIntervalList(parts - .map((String part) => parseDoubleWithUnits(part, fontSize: fontSize)!) + .map((String part) => + parseDoubleWithUnits(part, fontSize: fontSize, xHeight: xHeight)!) .toList()); } @@ -146,6 +149,7 @@ CircularIntervalList? parseDashArray( DashOffset? parseDashOffset( Map attributes, { required double fontSize, + required double xHeight, }) { final String? rawDashOffset = getAttribute(attributes, 'stroke-dashoffset'); if (rawDashOffset == '') { @@ -158,6 +162,7 @@ DashOffset? parseDashOffset( return DashOffset.absolute(parseDoubleWithUnits( rawDashOffset, fontSize: fontSize, + xHeight: xHeight, )!); } } @@ -200,6 +205,7 @@ DrawablePaint? parseStroke( DrawablePaint? parentStroke, Color? currentColor, double fontSize, + double xHeight, ) { final String rawStroke = getAttribute(attributes, 'stroke')!; final String? rawStrokeOpacity = getAttribute( @@ -264,6 +270,7 @@ DrawablePaint? parseStroke( : parseDoubleWithUnits( rawStrokeWidth, fontSize: fontSize, + xHeight: xHeight, ), ); return paint; @@ -499,6 +506,7 @@ DrawableStyle parseStyle( Rect? bounds, DrawableStyle? parentStyle, { required double fontSize, + required double xHeight, Color? defaultFillColor, Color? currentColor, }) { @@ -512,14 +520,17 @@ DrawableStyle parseStyle( parentStyle?.stroke, currentColor, fontSize, + xHeight, ), dashArray: parseDashArray( attributes, fontSize: fontSize, + xHeight: xHeight, ), dashOffset: parseDashOffset( attributes, fontSize: fontSize, + xHeight: xHeight, ), fill: parseFill( key, @@ -544,6 +555,7 @@ DrawableStyle parseStyle( getAttribute(attributes, 'font-size'), parentValue: parentStyle?.textStyle?.fontSize, fontSize: fontSize, + xHeight: xHeight, ), fontWeight: parseFontWeight( getAttribute(attributes, 'font-weight', def: null), diff --git a/lib/src/utilities/numbers.dart b/lib/src/utilities/numbers.dart index 1b3f2f1a..9d88071a 100644 --- a/lib/src/utilities/numbers.dart +++ b/lib/src/utilities/numbers.dart @@ -1,6 +1,6 @@ /// Parses a [rawDouble] `String` to a `double`. /// -/// The [rawDouble] might include a unit (`px` or `em`) +/// The [rawDouble] might include a unit (`px`, `em` or `ex`) /// which is stripped off when parsed to a `double`. /// /// Passing `null` will return `null`. @@ -10,7 +10,11 @@ double? parseDouble(String? rawDouble, {bool tryParse = false}) { return null; } - rawDouble = rawDouble.replaceFirst('em', '').replaceFirst('px', '').trim(); + rawDouble = rawDouble + .replaceFirst('em', '') + .replaceFirst('ex', '') + .replaceFirst('px', '') + .trim(); if (tryParse) { return double.tryParse(rawDouble); @@ -20,12 +24,16 @@ double? parseDouble(String? rawDouble, {bool tryParse = false}) { /// Parses a [rawDouble] `String` to a `double` /// taking into account absolute and relative units -/// (`px` or `em`). +/// (`px`, `em` or `ex`). /// /// Passing an `em` value will calculate the result /// relative to the provided [fontSize]: /// 1 em = 1 * [fontSize]. /// +/// Passing an `ex` value will calculate the result +/// relative to the provided [xHeight]: +/// 1 ex = 1 * [xHeight]. +/// /// The [rawDouble] might include a unit which is /// stripped off when parsed to a `double`. /// @@ -33,6 +41,7 @@ double? parseDouble(String? rawDouble, {bool tryParse = false}) { double? parseDoubleWithUnits( String? rawDouble, { required double fontSize, + required double xHeight, bool tryParse = false, }) { double unit = 1.0; @@ -41,6 +50,10 @@ double? parseDoubleWithUnits( if (rawDouble?.contains('em') ?? false) { unit = fontSize; } + // 1 ex unit is equal to the current x-height. + else if (rawDouble?.contains('ex') ?? false) { + unit = xHeight; + } final double? value = parseDouble( rawDouble, diff --git a/lib/svg.dart b/lib/svg.dart index b0201824..0863dc36 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -787,9 +787,15 @@ class _SvgPictureState extends State { // See: https://api.flutter.dev/flutter/painting/TextStyle/fontSize.html 14.0; + final double xHeight = widget.theme?.xHeight ?? + defaultSvgTheme?.xHeight ?? + // Fallback to the font size divided by 2. + fontSize / 2; + widget.pictureProvider.theme = SvgTheme( currentColor: currentColor, fontSize: fontSize, + xHeight: xHeight, ); } diff --git a/test/default_theme_test.dart b/test/default_theme_test.dart index 2ee9dc98..fd0074f6 100644 --- a/test/default_theme_test.dart +++ b/test/default_theme_test.dart @@ -12,6 +12,7 @@ void main() { const SvgTheme svgTheme = SvgTheme( currentColor: Color(0xFF733821), fontSize: 14.0, + xHeight: 6.0, ); final SvgPicture svgPictureWidget = SvgPicture.string(''' @@ -34,6 +35,7 @@ void main() { const SvgTheme anotherSvgTheme = SvgTheme( currentColor: Color(0xFF05290E), fontSize: 12.0, + xHeight: 7.0, ); await tester.pumpWidget(DefaultSvgTheme( @@ -157,5 +159,58 @@ void main() { equals(14.0), ); }); + + testWidgets( + 'xHeight from the widget\'s theme takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + fontSize: 14.0, + xHeight: 6.5, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + theme: SvgTheme( + fontSize: 12.0, + xHeight: 7.0, + ), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.theme.xHeight, + equals(7.0), + ); + }); + + testWidgets( + 'xHeight defaults to the font size divided by 2 (7.0) ' + 'if no widget\'s theme or DefaultSvgTheme is provided', + (WidgetTester tester) async { + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + ); + + await tester.pumpWidget(svgPictureWidget); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + svgPicture.pictureProvider.theme.xHeight, + equals(7.0), + ); + }); }); } diff --git a/test/golden_widget/circle.em.png b/test/golden_widget/circle.em_ex.png similarity index 100% rename from test/golden_widget/circle.em.png rename to test/golden_widget/circle.em_ex.png diff --git a/test/golden_widget/ellipse.em.png b/test/golden_widget/ellipse.em_ex.png similarity index 100% rename from test/golden_widget/ellipse.em.png rename to test/golden_widget/ellipse.em_ex.png diff --git a/test/golden_widget/line.em.png b/test/golden_widget/line.em_ex.png similarity index 100% rename from test/golden_widget/line.em.png rename to test/golden_widget/line.em_ex.png diff --git a/test/golden_widget/rect.em.png b/test/golden_widget/rect.em_ex.png similarity index 100% rename from test/golden_widget/rect.em.png rename to test/golden_widget/rect.em_ex.png diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index b0358fd5..cb8fd5da 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -80,6 +80,7 @@ void main() { svgString, )..theme = const SvgTheme( fontSize: 14.0, + xHeight: 7.0, ); await precachePicture( diff --git a/test/picture_provider_test.dart b/test/picture_provider_test.dart index b72ac51f..7b78caef 100644 --- a/test/picture_provider_test.dart +++ b/test/picture_provider_test.dart @@ -25,7 +25,7 @@ void main() { group( 'rebuilds the decoder using decoderBuilder ' - 'when currentColor changes', () { + 'when the theme changes', () { test('NetworkPicture', () async { const Color color = Color(0xFFB0E3BE); final NetworkPicture networkPicture = @@ -34,15 +34,17 @@ void main() { final PictureInfoDecoder? decoder = networkPicture.decoder; - // Update the theme of PictureProvider to include currentColor. - networkPicture.theme = SvgTheme( + const SvgTheme newTheme = SvgTheme( currentColor: color, fontSize: 14.0, + xHeight: 6.5, ); + networkPicture.theme = newTheme; + expect(networkPicture.decoder, isNotNull); expect(networkPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.currentColor, equals(color)); + expect(currentTheme, equals(newTheme)); }); test('FilePicture', () async { @@ -52,15 +54,17 @@ void main() { final PictureInfoDecoder? decoder = filePicture.decoder; - // Update the theme of PictureProvider to include currentColor. - filePicture.theme = SvgTheme( + const SvgTheme newTheme = SvgTheme( currentColor: color, fontSize: 14.0, + xHeight: 6.5, ); + filePicture.theme = newTheme; + expect(filePicture.decoder, isNotNull); expect(filePicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.currentColor, equals(color)); + expect(currentTheme, equals(newTheme)); }); test('MemoryPicture', () async { @@ -71,15 +75,17 @@ void main() { final PictureInfoDecoder? decoder = memoryPicture.decoder; - // Update the theme of PictureProvider to include currentColor. - memoryPicture.theme = SvgTheme( + const SvgTheme newTheme = SvgTheme( currentColor: color, fontSize: 14.0, + xHeight: 6.5, ); + memoryPicture.theme = newTheme; + expect(memoryPicture.decoder, isNotNull); expect(memoryPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.currentColor, equals(color)); + expect(currentTheme, equals(newTheme)); }); test('StringPicture', () async { @@ -89,15 +95,17 @@ void main() { final PictureInfoDecoder? decoder = stringPicture.decoder; - // Update the theme of PictureProvider to include currentColor. - stringPicture.theme = SvgTheme( + const SvgTheme newTheme = SvgTheme( currentColor: color, fontSize: 14.0, + xHeight: 6.5, ); + stringPicture.theme = newTheme; + expect(stringPicture.decoder, isNotNull); expect(stringPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.currentColor, equals(color)); + expect(currentTheme, equals(newTheme)); }); test('ExactAssetPicture', () async { @@ -108,102 +116,17 @@ void main() { final PictureInfoDecoder? decoder = exactAssetPicture.decoder; - // Update the theme of PictureProvider to include currentColor. - exactAssetPicture.theme = SvgTheme( + const SvgTheme newTheme = SvgTheme( currentColor: color, fontSize: 14.0, + xHeight: 6.5, ); - expect(exactAssetPicture.decoder, isNotNull); - expect(exactAssetPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.currentColor, equals(color)); - }); - }); - - group( - 'rebuilds the decoder using decoderBuilder ' - 'when fontSize changes', () { - test('NetworkPicture', () async { - const double fontSize = 26.0; - final NetworkPicture networkPicture = - NetworkPicture(decoderBuilder, 'url'); - - final PictureInfoDecoder? decoder = networkPicture.decoder; - - // Update the theme of PictureProvider to include fontSize. - networkPicture.theme = SvgTheme( - fontSize: fontSize, - ); - - expect(networkPicture.decoder, isNotNull); - expect(networkPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.fontSize, equals(fontSize)); - }); - - test('FilePicture', () async { - const double fontSize = 26.0; - final FilePicture filePicture = FilePicture(decoderBuilder, MockFile()); - - final PictureInfoDecoder? decoder = filePicture.decoder; - - // Update the theme of PictureProvider to include fontSize. - filePicture.theme = SvgTheme( - fontSize: fontSize, - ); - - expect(filePicture.decoder, isNotNull); - expect(filePicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.fontSize, equals(fontSize)); - }); - - test('MemoryPicture', () async { - const double fontSize = 26.0; - final MemoryPicture memoryPicture = - MemoryPicture(decoderBuilder, Uint8List(0)); - - final PictureInfoDecoder? decoder = memoryPicture.decoder; - - // Update the theme of PictureProvider to include fontSize. - memoryPicture.theme = SvgTheme( - fontSize: fontSize, - ); - - expect(memoryPicture.decoder, isNotNull); - expect(memoryPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.fontSize, equals(fontSize)); - }); - - test('StringPicture', () async { - const double fontSize = 26.0; - final StringPicture stringPicture = StringPicture(decoderBuilder, ''); - - final PictureInfoDecoder? decoder = stringPicture.decoder; - - // Update the theme of PictureProvider to include fontSize. - stringPicture.theme = SvgTheme( - fontSize: fontSize, - ); - - expect(stringPicture.decoder, isNotNull); - expect(stringPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.fontSize, equals(fontSize)); - }); - - test('ExactAssetPicture', () async { - const double fontSize = 26.0; - final ExactAssetPicture exactAssetPicture = - ExactAssetPicture(decoderBuilder, ''); - - final PictureInfoDecoder? decoder = exactAssetPicture.decoder; - - // Update the theme of PictureProvider to include fontSize. - exactAssetPicture.theme = SvgTheme( - fontSize: fontSize, - ); + exactAssetPicture.theme = newTheme; expect(exactAssetPicture.decoder, isNotNull); expect(exactAssetPicture.decoder, isNot(equals(decoder))); - expect(currentTheme?.fontSize, equals(fontSize)); + expect(currentTheme, equals(newTheme)); }); }); diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index 0472f620..2e2dd4c8 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -114,49 +114,115 @@ void main() { test('Font size parsing tests', () { const double fontSize = 14.0; - expect(parseFontSize(null, fontSize: fontSize), isNull); - expect(parseFontSize('', fontSize: fontSize), isNull); - expect(parseFontSize('1', fontSize: fontSize), 1); - expect(parseFontSize(' 1 ', fontSize: fontSize), 1); - expect(parseFontSize('xx-small', fontSize: fontSize), 10); - expect(parseFontSize('x-small', fontSize: fontSize), 12); - expect(parseFontSize('small', fontSize: fontSize), 14); - expect(parseFontSize('medium', fontSize: fontSize), 18); - expect(parseFontSize('large', fontSize: fontSize), 22); - expect(parseFontSize('x-large', fontSize: fontSize), 26); - expect(parseFontSize('xx-large', fontSize: fontSize), 32); - - expect(parseFontSize('larger', fontSize: fontSize), - parseFontSize('large', fontSize: fontSize)); + const double xHeight = 7.0; + + expect( + parseFontSize(null, fontSize: fontSize, xHeight: xHeight), + isNull, + ); + expect( + parseFontSize('', fontSize: fontSize, xHeight: xHeight), + isNull, + ); + expect( + parseFontSize('1', fontSize: fontSize, xHeight: xHeight), + equals(1), + ); + expect( + parseFontSize(' 1 ', fontSize: fontSize, xHeight: xHeight), + equals(1), + ); + expect( + parseFontSize('xx-small', fontSize: fontSize, xHeight: xHeight), + equals(10), + ); + expect( + parseFontSize('x-small', fontSize: fontSize, xHeight: xHeight), + equals(12), + ); + expect( + parseFontSize('small', fontSize: fontSize, xHeight: xHeight), + equals(14), + ); + expect( + parseFontSize('medium', fontSize: fontSize, xHeight: xHeight), + equals(18), + ); + expect( + parseFontSize('large', fontSize: fontSize, xHeight: xHeight), + equals(22), + ); + expect( + parseFontSize('x-large', fontSize: fontSize, xHeight: xHeight), + equals(26), + ); + expect( + parseFontSize('xx-large', fontSize: fontSize, xHeight: xHeight), + equals(32), + ); + expect( - parseFontSize('larger', - fontSize: fontSize, - parentValue: parseFontSize('large', fontSize: fontSize)), - parseFontSize('large', fontSize: fontSize)! * 1.2); - expect(parseFontSize('smaller', fontSize: fontSize), - parseFontSize('small', fontSize: fontSize)); + parseFontSize('larger', fontSize: fontSize, xHeight: xHeight), + equals(parseFontSize('large', fontSize: fontSize, xHeight: xHeight)), + ); + expect( + parseFontSize( + 'larger', + fontSize: fontSize, + xHeight: xHeight, + parentValue: + parseFontSize('large', fontSize: fontSize, xHeight: xHeight), + ), + equals( + parseFontSize('large', fontSize: fontSize, xHeight: xHeight)! * 1.2, + ), + ); expect( - parseFontSize('smaller', - fontSize: fontSize, - parentValue: parseFontSize('large', fontSize: fontSize)), - parseFontSize('large', fontSize: fontSize)! / 1.2); + parseFontSize('smaller', fontSize: fontSize, xHeight: xHeight), + equals( + parseFontSize('small', fontSize: fontSize, xHeight: xHeight), + ), + ); + expect( + parseFontSize( + 'smaller', + fontSize: fontSize, + xHeight: xHeight, + parentValue: + parseFontSize('large', fontSize: fontSize, xHeight: xHeight), + ), + equals( + parseFontSize('large', fontSize: fontSize, xHeight: xHeight)! / 1.2, + ), + ); - expect(() => parseFontSize('invalid', fontSize: fontSize), + expect(() => parseFontSize('invalid', fontSize: fontSize, xHeight: xHeight), throwsA(const TypeMatcher())); }); test('relative font size tests', () { const double fontSize = 26.0; + const double xHeight = 14.0; expect( - parseFontSize('4em', fontSize: fontSize), + parseFontSize('4em', fontSize: fontSize, xHeight: xHeight), equals(4 * fontSize), ); expect( - parseFontSize(' 2em ', fontSize: fontSize), + parseFontSize(' 2em ', fontSize: fontSize, xHeight: xHeight), equals(2 * fontSize), ); + + expect( + parseFontSize('4ex', fontSize: fontSize, xHeight: xHeight), + equals(4 * xHeight), + ); + + expect( + parseFontSize(' 2ex ', fontSize: fontSize, xHeight: xHeight), + equals(2 * xHeight), + ); }); test('Check no child with id for svg', () async { @@ -780,4 +846,189 @@ BAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" x="1em" y="0.5em" width="2em" height="1.5em" / expect(image.size, equals(expectedSize)); }); }); + + group('calculates ex units based on the x-height for', () { + test('svg (width, height)', () async { + const String svgStr = ''' + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + expect(root.viewport.width, equals(xHeight * 5)); + expect(root.viewport.height, equals(xHeight * 6)); + }); + + test('use (x, y)', () async { + const String svgStr = ''' + + + + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + final DrawableGroup? circle = find(root, 'anotherCircle'); + + const double expectedX = xHeight * 2; + const double expectedY = xHeight * 4; + + expect(circle, isNotNull); + expect( + circle!.transform, + equals( + (Matrix4.identity()..translate(expectedX, expectedY)).storage, + ), + ); + }); + + test('text (x, y)', () async { + const String svgStr = ''' + + Test + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + final DrawableText? text = find(root, 'text'); + + const Offset expectedOffset = Offset(xHeight * 2, xHeight * 4); + + expect(text, isNotNull); + expect(text!.offset, equals(expectedOffset)); + }); + + test('radialGradient (cx, cy, r, fx, fy)', () async { + const String svgStr = ''' + + + + + + + + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + final DrawableRadialGradient? gradient = + root.definitions.getGradient('url(#gradient)'); + + expect(gradient, isNotNull); + + const Offset expectedOffset = Offset(xHeight * 1, xHeight * 2); + const double expectedRadius = xHeight * 1.1; + const Offset expectedFocal = Offset(xHeight * 1.5, xHeight * 1.6); + + expect(gradient, isNotNull); + expect(gradient!.center, equals(expectedOffset)); + expect(gradient.radius, equals(expectedRadius)); + expect(gradient.focal, equals(expectedFocal)); + }); + + test('linearGradient (x1, y1, x2, y2)', () async { + const String svgStr = ''' + + + + + + + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + final DrawableLinearGradient? gradient = + root.definitions.getGradient('url(#gradient)'); + + expect(gradient, isNotNull); + + const Offset expectedFromOffset = Offset(xHeight * 1, xHeight * 1.75); + const Offset expectedToOffset = Offset(xHeight * 1.5, xHeight * 1.6); + + expect(gradient, isNotNull); + expect(gradient!.from, equals(expectedFromOffset)); + expect(gradient.to, equals(expectedToOffset)); + }); + + test('image (x, y, width, height)', () async { + const String svgStr = ''' + + + +'''; + + const double fontSize = 26.0; + const double xHeight = 11.0; + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse( + svgStr, + theme: const SvgTheme( + fontSize: fontSize, + xHeight: xHeight, + ), + ); + + final DrawableRasterImage? image = + find(root, 'image'); + + const Offset expectedOffset = Offset(xHeight * 1, xHeight * 0.5); + const Size expectedSize = Size(xHeight * 2, xHeight * 1.5); + + expect(image, isNotNull); + expect(image!.offset, equals(expectedOffset)); + expect(image.size, equals(expectedSize)); + }); + }); } diff --git a/test/theme_test.dart b/test/theme_test.dart index 998d45dd..71b88879 100644 --- a/test/theme_test.dart +++ b/test/theme_test.dart @@ -41,6 +41,31 @@ void main() { ), ); }); + + test('sets xHeight', () { + const double xHeight = 8.0; + + expect( + SvgTheme( + fontSize: 26.0, + xHeight: xHeight, + ).xHeight, + equals(xHeight), + ); + }); + + test( + 'sets xHeight as fontSize divided by 2 ' + 'by default', () { + const double fontSize = 16.0; + + expect( + SvgTheme( + fontSize: fontSize, + ).xHeight, + equals(fontSize / 2), + ); + }); }); test('supports value equality', () { @@ -48,11 +73,13 @@ void main() { SvgTheme( currentColor: Color(0xFF6F2173), fontSize: 14.0, + xHeight: 6.0, ), equals( SvgTheme( currentColor: Color(0xFF6F2173), fontSize: 14.0, + xHeight: 6.0, ), ), ); diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index bb51e695..4508a2cd 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -771,7 +771,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'circle.em.png'); + await _checkWidgetAndGolden(key, 'circle.em_ex.png'); }); testWidgets('rect (x, y, width, height, rx, ry)', @@ -795,7 +795,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'rect.em.png'); + await _checkWidgetAndGolden(key, 'rect.em_ex.png'); }); testWidgets('ellipse (cx, cy, rx, ry)', (WidgetTester tester) async { @@ -818,10 +818,10 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'ellipse.em.png'); + await _checkWidgetAndGolden(key, 'ellipse.em_ex.png'); }); - testWidgets('line (x1, x2, y1, y2)', (WidgetTester tester) async { + testWidgets('line (x1, y1, x2, y2)', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); const String svgStr = ''' @@ -842,7 +842,115 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'line.em.png'); + await _checkWidgetAndGolden(key, 'line.em_ex.png'); + }); + }); + + group('SvgPicture respects ex units', () { + testWidgets('circle (cx, cy, r)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme( + fontSize: 1500, + xHeight: 600, + ), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'circle.em_ex.png'); + }); + + testWidgets('rect (x, y, width, height, rx, ry)', + (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme( + fontSize: 300, + xHeight: 100, + ), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'rect.em_ex.png'); + }); + + testWidgets('ellipse (cx, cy, rx, ry)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme( + fontSize: 300, + xHeight: 100, + ), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'ellipse.em_ex.png'); + }); + + testWidgets('line (x1, y1, x2, y2)', (WidgetTester tester) async { + final GlobalKey key = GlobalKey(); + + const String svgStr = ''' + + + + +'''; + + await tester.pumpWidget( + RepaintBoundary( + key: key, + child: SvgPicture.string( + svgStr, + theme: const SvgTheme( + fontSize: 300, + xHeight: 100, + ), + ), + ), + ); + + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'line.em_ex.png'); }); }); diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index f208960b..81733bcf 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -84,6 +84,7 @@ void main() { parseViewBox( svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .size, const Size(50, 50)); @@ -91,6 +92,7 @@ void main() { parseViewBox( svgWithViewBox.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxRect, rect); @@ -98,6 +100,7 @@ void main() { parseViewBox( svgWithViewBox.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxOffset, Offset.zero); @@ -105,6 +108,7 @@ void main() { parseViewBox( svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxRect, rect); @@ -112,6 +116,7 @@ void main() { parseViewBox( svgWithWidthHeight.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxRect, rect); @@ -119,6 +124,7 @@ void main() { parseViewBox( svgWithNoSizeInfo.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, nullOk: true, ), null); @@ -126,12 +132,14 @@ void main() { () => parseViewBox( svgWithNoSizeInfo.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, ), throwsStateError); expect( parseViewBox( svgWithViewBoxMinXMinY.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxRect, rect); @@ -139,6 +147,7 @@ void main() { parseViewBox( svgWithViewBoxMinXMinY.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, )! .viewBoxOffset, const Offset(-42.0, -56.0)); @@ -182,6 +191,7 @@ void main() { parseDashOffset( abs.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, ), equals(const DashOffset.absolute(20.0)), ); @@ -190,6 +200,7 @@ void main() { parseDashOffset( pct.attributes.toAttributeMap(), fontSize: 14.0, + xHeight: 7.0, ), equals(DashOffset.percentage(0.2)), ); @@ -257,6 +268,7 @@ void main() { null, currentColor: currentColor, fontSize: 14.0, + xHeight: 7.0, ); expect( @@ -279,6 +291,7 @@ void main() { null, currentColor: currentColor, fontSize: 14.0, + xHeight: 7.0, ); expect( @@ -287,84 +300,165 @@ void main() { ); }); - test( - 'calculates em units based on the font size ' - 'for stroke width', () { - final XmlStartElementEvent svg = - parseEvents('').first - as XmlStartElementEvent; - - const double fontSize = 26.0; - - final DrawableStyle svgStyle = parseStyle( - 'test', - svg.attributes.toAttributeMap(), - DrawableDefinitionServer(), - null, - null, - fontSize: fontSize, - ); - - expect( - svgStyle.stroke?.strokeWidth, - equals(fontSize * 2), - ); - }); - - test( - 'calculates em units based on the font size ' - 'for dash array', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - - final DrawableStyle svgStyle = parseStyle( - 'test', - svg.attributes.toAttributeMap(), - DrawableDefinitionServer(), - null, - null, - fontSize: fontSize, - ); - - expect( - [ - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - ], - equals([ - fontSize * 0.2, - fontSize * 0.5, - 10, - ]), - ); + group('calculates em units based on the font size for', () { + test('stroke width', () { + final XmlStartElementEvent svg = + parseEvents('').first + as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: 7.0, + ); + + expect( + svgStyle.stroke?.strokeWidth, + equals(fontSize * 2), + ); + }); + + test('dash array', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: 7.0, + ); + + expect( + [ + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + ], + equals([ + fontSize * 0.2, + fontSize * 0.5, + 10, + ]), + ); + }); + + test('dash offset', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: 7.0, + ); + + expect( + svgStyle.dashOffset, + equals(const DashOffset.absolute(fontSize * 0.15)), + ); + }); }); - test( - 'calculates em units based on the font size ' - 'for dash offset', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - - final DrawableStyle svgStyle = parseStyle( - 'test', - svg.attributes.toAttributeMap(), - DrawableDefinitionServer(), - null, - null, - fontSize: fontSize, - ); - - expect( - svgStyle.dashOffset, - equals(const DashOffset.absolute(fontSize * 0.15)), - ); + group('calculates ex units based on the x-height for', () { + test('stroke width', () { + final XmlStartElementEvent svg = + parseEvents('').first + as XmlStartElementEvent; + + const double fontSize = 26.0; + const double xHeight = 11.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: xHeight, + ); + + expect( + svgStyle.stroke?.strokeWidth, + equals(xHeight * 2), + ); + }); + + test('dash array', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + const double xHeight = 11.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: xHeight, + ); + + expect( + [ + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + svgStyle.dashArray!.next, + ], + equals([ + xHeight * 0.2, + xHeight * 0.5, + 10, + ]), + ); + }); + + test('dash offset', () { + final XmlStartElementEvent svg = parseEvents( + '', + ).first as XmlStartElementEvent; + + const double fontSize = 26.0; + const double xHeight = 11.0; + + final DrawableStyle svgStyle = parseStyle( + 'test', + svg.attributes.toAttributeMap(), + DrawableDefinitionServer(), + null, + null, + fontSize: fontSize, + xHeight: xHeight, + ); + + expect( + svgStyle.dashOffset, + equals(const DashOffset.absolute(xHeight * 0.15)), + ); + }); }); }); } From c482b3ffdc0833d671de42ebc520d291648b1e28 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Jan 2022 13:03:56 -0800 Subject: [PATCH 043/142] Fix but in element fills, analysis cleanup --- CHANGELOG.md | 5 +++++ .../assets/simple/fill_inheritence_test.svg | 4 ++++ example/assets/simple/use_fill_test.svg | 8 +++++++ golden/simple/fill_inheritence_test.png | Bin 0 -> 588 bytes golden/simple/use_fill_test.png | Bin 0 -> 718 bytes lib/src/svg/xml_parsers.dart | 21 ++++++++++-------- lib/src/vector_drawable.dart | 3 +++ test/default_theme_test.dart | 2 -- test/picture_cache_test.dart | 1 - test/picture_provider_test.dart | 1 - 10 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 example/assets/simple/fill_inheritence_test.svg create mode 100644 example/assets/simple/use_fill_test.svg create mode 100644 golden/simple/fill_inheritence_test.png create mode 100644 golden/simple/use_fill_test.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 69d1cbf2..ccd25bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## UNRELEASED + +- Fix bug with incorrect fills in some cases of `` elements. +- Analysis cleanup of Dart code. + ## 1.0.0 - New widget/RenderObject implementation to avoid rebuilds/paints when diff --git a/example/assets/simple/fill_inheritence_test.svg b/example/assets/simple/fill_inheritence_test.svg new file mode 100644 index 00000000..93a82227 --- /dev/null +++ b/example/assets/simple/fill_inheritence_test.svg @@ -0,0 +1,4 @@ + + + + diff --git a/example/assets/simple/use_fill_test.svg b/example/assets/simple/use_fill_test.svg new file mode 100644 index 00000000..3bf0fe96 --- /dev/null +++ b/example/assets/simple/use_fill_test.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/golden/simple/fill_inheritence_test.png b/golden/simple/fill_inheritence_test.png new file mode 100644 index 0000000000000000000000000000000000000000..ccdf26fc6206c013092eb2e9145c0f2a8a63d7a1 GIT binary patch literal 588 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>pxif47srr_Id89SVZfqx%Ztxj?kO`9=!B1p#5)z4*}Q$iB}$hBh0 literal 0 HcmV?d00001 diff --git a/golden/simple/use_fill_test.png b/golden/simple/use_fill_test.png new file mode 100644 index 0000000000000000000000000000000000000000..aafff9f160b3ee38cd8c65150a40c482ff01fc5f GIT binary patch literal 718 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_q`IPZ!6KiaBquZ}eqx6mUJrHc>p~SZ+$eL|(RYk}oWEq_(W;df>e_{mbR3 zY~BxxpWkJEU@y$U(&!*SXQE~LU1q;xncd8bg=d#Wzp$Py5 Cx3{SP literal 0 HcmV?d00001 diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index fd4872a8..27b70841 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -298,7 +298,17 @@ DrawablePaint? parseFill( ); } - if (rawFill == '' && parentFill == DrawablePaint.empty) { + final Color? fillColor = _determineFillColor( + parentFill?.color, + rawFill, + opacity, + rawOpacity != '' || rawFillOpacity != '', + defaultFillColor, + currentColor, + ); + + if (rawFill == '' && + (fillColor == null || parentFill == DrawablePaint.empty)) { return null; } if (rawFill == 'none') { @@ -307,14 +317,7 @@ DrawablePaint? parseFill( return DrawablePaint( PaintingStyle.fill, - color: _determineFillColor( - parentFill?.color, - rawFill, - opacity, - rawOpacity != '' || rawFillOpacity != '', - defaultFillColor, - currentColor, - ), + color: fillColor, ); } diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 4eabe0b2..000b31aa 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -326,6 +326,9 @@ class DrawablePaint { @override String toString() { + if (identical(this, DrawablePaint.empty)) { + return 'DrawablePaint{}'; + } return 'DrawablePaint{$style, color: $color, shader: $shader, blendMode: $blendMode, ' 'colorFilter: $colorFilter, isAntiAlias: $isAntiAlias, filterQuality: $filterQuality, ' 'maskFilter: $maskFilter, strokeCap: $strokeCap, strokeJoin: $strokeJoin, ' diff --git a/test/default_theme_test.dart b/test/default_theme_test.dart index 2ee9dc98..f64098e4 100644 --- a/test/default_theme_test.dart +++ b/test/default_theme_test.dart @@ -1,7 +1,5 @@ // ignore_for_file: prefer_const_constructors -import 'dart:ui'; - import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/picture_cache_test.dart b/test/picture_cache_test.dart index b0358fd5..29e1bdd4 100644 --- a/test/picture_cache_test.dart +++ b/test/picture_cache_test.dart @@ -1,7 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/src/picture_cache.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:xml/xml.dart'; diff --git a/test/picture_provider_test.dart b/test/picture_provider_test.dart index b72ac51f..07568600 100644 --- a/test/picture_provider_test.dart +++ b/test/picture_provider_test.dart @@ -5,7 +5,6 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; From 24e06f60db4368ec8c34fc0de461ecd1e08da0c7 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Jan 2022 16:12:24 -0800 Subject: [PATCH 044/142] Fix bug where empty group can affect rendering --- CHANGELOG.md | 1 + example/assets/simple/empty_group.svg | 6 ++++++ golden/simple/empty_group.png | Bin 0 -> 1888 bytes lib/src/svg/parser_state.dart | 5 ++++- 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 example/assets/simple/empty_group.svg create mode 100644 golden/simple/empty_group.png diff --git a/CHANGELOG.md b/CHANGELOG.md index ccd25bf3..3086e9fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Fix bug with incorrect fills in some cases of `` elements. - Analysis cleanup of Dart code. +- Fix bug where self-closing `` tags could alter rendering. ## 1.0.0 diff --git a/example/assets/simple/empty_group.svg b/example/assets/simple/empty_group.svg new file mode 100644 index 00000000..893be543 --- /dev/null +++ b/example/assets/simple/empty_group.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/golden/simple/empty_group.png b/golden/simple/empty_group.png new file mode 100644 index 0000000000000000000000000000000000000000..53c52b10b268d7d4c31a2b65bcbae279fb2e66c8 GIT binary patch literal 1888 zcmeHI`#aMM7+)-wijlcwG^-`z=%OaM48tyuOC#jcoR-^22WJZj-?@}l&AoGoI(#!6 zRI=3M(kUUKgmE;ES*@a6VshPCPyfXE;k?iDzVGvS-skze@B8`TeKS4WT(+ugSAjqv zTZsfbMV>ppJ4{I)YkX@<cFQ#B^3llw!U- znjdtOrIsWZgJ!lvuL_-iBGi{I3@-eW059se-}vS!!TF@vB`R|As9zHm#l%2YQr>r; zOZrSVmGNT6TO;Se5w4xrw`C3k(=19rPSM^jKwMk{vPCU2N@sEu{m==9jjGfhrCLwT zWwj)gHx~Po8YqH^Rvbz-j@DOaHMcI^EL@ei2B*GUAjBytM1zNSo7pa>@{7m9KaUqq zM$c@4iafeNi)ux#1v2Z(l>lg;XRXXl`^G{P3x$HDu<(Kad> zaKa`$f~dA$0Tw+p*ysoYp>!H$X2!i5g~6jR>aK+0wXxXoyQg8`u5zPYYm2@7hWOrv zJwxd@(qDSH^^d+JY}sO%l>>Vq)1Zb>`T9_I!>j|t{5w&D44aKi!z_(W24m-J6y$v} zK}Er~ARQo&_?0!eXfwh3%_#tfBq_IjQg=1Gn~hN# zS`n~}!RGeG+8tjJkEm1uKh(u>jcSUQJjOGFdF6h!?ErvN^|i{1S|QK%tm3-31%aH@ z3-FE&B;`IyenA~JxqR;|qPB2{0yGB4Ut%K3H$R<9%%8aCSSm_LDMNMLE*fRkNqZUl zo2x7@1#;3Pc+{PtT%n1`G7lz3{QZI0pm+UU(^6)Ed&|=%?~8EYG5VYVIpW}SXY$0( zrVE!N^e-ZS$ESq>{3Z-WV(a~jbmc~kl^7<*_;rDe0|j;L9hHpb5qfXEoLn1^GPjox zdxjXE=(zsqX4nz_GyhN*DDXJN^!nhzaGsTU;Ic0}w599n#hn?r=JKm0zjCQQOlbxy zeUV|ze+GPmp|fP3TqB`w|A0+=;5s&`f;q1xIP9zgSaU)1nh;8iC@}u(j%mU+l~-zrL5J=`?=8z)1>VcJKKp2o;(0cTKXBsq zXyz$K*h_MIhE+tAc`bY8(3vRByBFjpHIBHP(HF9s`V)Ok! zrVHLt{EDvc{xovuq&brfqEkqLRSn|fMhGv(_-!R}oEz`6R0Fdh_xkyXl2EXZ5nI|IGGAth5-C*emf?&3oZnB3W8*dC&kBS;re7 zH(MS}%l_&BK+3Lh3^s0oD(JwV`{1x36kL9=QUDx85r8NuZ1}(MpOj=(ZEPUK? g(SvgParserState parserState, bool warningsAsErrors) { + // if (parserState._currentStartElement?.isSelfClosing == true) { + // return null; + // } final DrawableParent parent = parserState.currentGroup!; final Color? color = parseColor(parserState.attribute('color', def: null)) ?? parent.color; @@ -916,7 +919,7 @@ class SvgParserState { this.theme, this._key, this._warningsAsErrors, - ) + ) // ignore: unnecessary_null_comparison : assert(events != null), _eventIterator = events.iterator; From c728d6036b79f0a92c644bafc49050082468701a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Jan 2022 16:13:45 -0800 Subject: [PATCH 045/142] oops --- example/assets/simple/empty_group.svg | 2 +- golden/simple/empty_group.png | Bin 1888 -> 4013 bytes lib/src/svg/parser_state.dart | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/assets/simple/empty_group.svg b/example/assets/simple/empty_group.svg index 893be543..af423cf0 100644 --- a/example/assets/simple/empty_group.svg +++ b/example/assets/simple/empty_group.svg @@ -3,4 +3,4 @@ - \ No newline at end of file + diff --git a/golden/simple/empty_group.png b/golden/simple/empty_group.png index 53c52b10b268d7d4c31a2b65bcbae279fb2e66c8..a99844327c1bfac8f198f09e248975e2ffc2e37a 100644 GIT binary patch literal 4013 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 literal 1888 zcmeHI`#aMM7+)-wijlcwG^-`z=%OaM48tyuOC#jcoR-^22WJZj-?@}l&AoGoI(#!6 zRI=3M(kUUKgmE;ES*@a6VshPCPyfXE;k?iDzVGvS-skze@B8`TeKS4WT(+ugSAjqv zTZsfbMV>ppJ4{I)YkX@<cFQ#B^3llw!U- znjdtOrIsWZgJ!lvuL_-iBGi{I3@-eW059se-}vS!!TF@vB`R|As9zHm#l%2YQr>r; zOZrSVmGNT6TO;Se5w4xrw`C3k(=19rPSM^jKwMk{vPCU2N@sEu{m==9jjGfhrCLwT zWwj)gHx~Po8YqH^Rvbz-j@DOaHMcI^EL@ei2B*GUAjBytM1zNSo7pa>@{7m9KaUqq zM$c@4iafeNi)ux#1v2Z(l>lg;XRXXl`^G{P3x$HDu<(Kad> zaKa`$f~dA$0Tw+p*ysoYp>!H$X2!i5g~6jR>aK+0wXxXoyQg8`u5zPYYm2@7hWOrv zJwxd@(qDSH^^d+JY}sO%l>>Vq)1Zb>`T9_I!>j|t{5w&D44aKi!z_(W24m-J6y$v} zK}Er~ARQo&_?0!eXfwh3%_#tfBq_IjQg=1Gn~hN# zS`n~}!RGeG+8tjJkEm1uKh(u>jcSUQJjOGFdF6h!?ErvN^|i{1S|QK%tm3-31%aH@ z3-FE&B;`IyenA~JxqR;|qPB2{0yGB4Ut%K3H$R<9%%8aCSSm_LDMNMLE*fRkNqZUl zo2x7@1#;3Pc+{PtT%n1`G7lz3{QZI0pm+UU(^6)Ed&|=%?~8EYG5VYVIpW}SXY$0( zrVE!N^e-ZS$ESq>{3Z-WV(a~jbmc~kl^7<*_;rDe0|j;L9hHpb5qfXEoLn1^GPjox zdxjXE=(zsqX4nz_GyhN*DDXJN^!nhzaGsTU;Ic0}w599n#hn?r=JKm0zjCQQOlbxy zeUV|ze+GPmp|fP3TqB`w|A0+=;5s&`f;q1xIP9zgSaU)1nh;8iC@}u(j%mU+l~-zrL5J=`?=8z)1>VcJKKp2o;(0cTKXBsq zXyz$K*h_MIhE+tAc`bY8(3vRByBFjpHIBHP(HF9s`V)Ok! zrVHLt{EDvc{xovuq&brfqEkqLRSn|fMhGv(_-!R}oEz`6R0Fdh_xkyXl2EXZ5nI|IGGAth5-C*emf?&3oZnB3W8*dC&kBS;re7 zH(MS}%l_&BK+3Lh3^s0oD(JwV`{1x36kL9=QUDx85r8NuZ1}(MpOj=(ZEPUK? g(SvgParserState parserState, bool warningsAsErrors) { - // if (parserState._currentStartElement?.isSelfClosing == true) { - // return null; - // } + if (parserState._currentStartElement?.isSelfClosing == true) { + return null; + } final DrawableParent parent = parserState.currentGroup!; final Color? color = parseColor(parserState.attribute('color', def: null)) ?? parent.color; From 65dbfc69ece50e680b40ee57532f5addc94fc587 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Jan 2022 16:41:02 -0800 Subject: [PATCH 046/142] Avoid invalid dasharrays --- CHANGELOG.md | 1 + example/assets/simple/invalid_dash_array.svg | 3 +++ golden/simple/invalid_dash_array.png | Bin 0 -> 2732 bytes lib/src/svg/xml_parsers.dart | 16 ++++++++++++---- 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 example/assets/simple/invalid_dash_array.svg create mode 100644 golden/simple/invalid_dash_array.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 3086e9fe..03875dfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Fix bug with incorrect fills in some cases of `` elements. - Analysis cleanup of Dart code. - Fix bug where self-closing `` tags could alter rendering. +- Fix bug where an invalid `@stroke-dasharray` could cause an infinite loop. ## 1.0.0 diff --git a/example/assets/simple/invalid_dash_array.svg b/example/assets/simple/invalid_dash_array.svg new file mode 100644 index 00000000..24b0b96c --- /dev/null +++ b/example/assets/simple/invalid_dash_array.svg @@ -0,0 +1,3 @@ +a + + \ No newline at end of file diff --git a/golden/simple/invalid_dash_array.png b/golden/simple/invalid_dash_array.png new file mode 100644 index 0000000000000000000000000000000000000000..afb5d1ec3a8f32bba6f10a71d10257e9efd812ba GIT binary patch literal 2732 zcmeHJ|3A~)AJ@1n<@@zL+d}zzx#&h_8Lg1MNHyOnVZK(jW@7SLS8T#iTE3T1GT&1| ztxMT3T(si)cCn>l+Z{3A;`8q3&*$;^3qI%ZIOjah<9vCZ=kuKNJTHpJ85ae49eF7! zDFruIlqXQLeq^vLP}X?YmH^c*oTrPkRBiu0KG2ZCIlEl|1BnO@AxlZgquo$W7vhTq z69Z>;`P%QqMx4J4%5)TEDW$4^s9LC?8XoOBqM9wu&E@76Z49h@ENZ01DE4`pC|4OD zqGW*dv4&vNET@j6m)x_Wy~^aS7lcle2o7NmBBJA5v(4a_g_~3PlH%8~L?Y2#s((d} zp(GWKkpUTlWjvI@k6_A3C)mGkBc*;KNy&r6=bF)yP37y9(ygOXeix(g>jjoQm&L9q zl;R#2&zkREC=_7o{CG$ASjt?(-W( z`1tm(C25t!mZ{{QruGWB*;8q%b~4zmA?(5H%bC@|fx%hGGk|h8*XJji1K;Aya-yIe z2T~J5r=8MocB`wfs^%=wzSi2*5B7#u<3_)KpO`_NeekxJaK6sBy7%%lcfc}_;Rfh7 ze#@zccdZ0E3}BeEpE~RW>Z*|A9qBq>@4C;ROZToa3rqGvHK>L(%O3Qqqo?r$2Yct7 zHZ=ol8bq?V8Lhs7wAO_K%!luZbaeG{^Q%5hl$+(5H8!@Iz#+e+_&+>r70W<9lNQfM za*#p(8qo4ufe;TMzY;Yq;Ta>}2#BPjFg=?73(`IfDt9gjU07g9V8TN!5W+FXdjGdD zv+Bar3U7+SQGj^3QZDH6-tr5ztYuBJ(;uu3+Z*B}%p``+g&Gb|w6jJyk5Lo01exFW zyGncTxiI}og0;!r7;M!?$_ei1y-h43`27k2zzN|6O|mAjn}H6!lO8;^IF17iQRNv|HTU_S-nOg?d@>L%62AHxe!FuX`MkMR{Ez8xIpKqYYrT{cz%9dk z)3(Lgj(O{m3->$2Ee}LI;7`@~R;O+Ew@#3>6jg#9+i9IAj5cTbzM#i~IuPte`|L>0 zqG<+S*^qoHs0$ZRcO%>jEf?HMVRdz{`%wJC96`;)uY&L7aYzs4J0d5-^81h7-tZ5u z^VTKvcf5z)AA#kfq^*jRZ)^`v0y8T2Xmt`b8f=w28=7WEaC2MMm0pdflB1)8V_=!g z_`r)=U!V$=j%}=?XHMHs7tl%N2p3T|djHI#>3N!~_Oh*N&3jJzPF^pT9-7 zc~5&+qfpNL$MYck>vc$!^saU!Y=6kcp*0vnjUDw#c4#;z&SZJvmetRR_3pfr#@i)< z4TqI&6MJy`N1QZM8Bb_*1=M?D-#M*=^Oc1x*^QZB>~k;G+ba(@GHVVPmYT?Vz3air6{i8Wh~gC>=KKNZjcO969eAV)m;w7 zH&rF4)Ogfz3XgX7RWgqx7R?$ll-?=f__0UK_h~aAk1qqOav}pXAmzm5Q4H|P05-qj z2f{*HygW~Dg^w(DiN)fEDY@yi$Qp~}?_-XItpn3218bYS==lsTx*1Jd$<*s6Mql+g zMQA@?f_N=T{3}K16->immLuWX?0da9k0NuIKPk*~8iG02fd0M6%RaVIf3c~o;c(sz% zGF@lTb%v>%1?d$kA698e15=0Lh+K(tj4C zZno$AY(uF(Wl57HmHwx|P43ixL?poT|L>v7|2zJdR%=i*cYgG1UPu`baZ0%zKZB}u HzI6NFKJe#r literal 0 HcmV?d00001 diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index 0403421c..cd0cc1fa 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -139,10 +139,18 @@ CircularIntervalList? parseDashArray( } final List parts = rawDashArray!.split(RegExp(r'[ ,]+')); - return CircularIntervalList(parts - .map((String part) => - parseDoubleWithUnits(part, fontSize: fontSize, xHeight: xHeight)!) - .toList()); + final List doubles = []; + for (final String part in parts) { + final double dashOffset = + parseDoubleWithUnits(part, fontSize: fontSize, xHeight: xHeight)!; + if (dashOffset != 0) { + doubles.add(dashOffset); + } + } + if (doubles.isEmpty) { + return null; + } + return CircularIntervalList(doubles); } /// Parses a @stroke-dashoffset into a [DashOffset]. From 7c14bf7bf9712f0205f9bf68e9de8605ea47ae0d Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Jan 2022 11:36:23 -0800 Subject: [PATCH 047/142] Fix bug in dash array update: zero values should be acceptable in some cases --- example/assets/simple/dash_zero.svg | 3 +++ golden/simple/dash_zero.png | Bin 0 -> 775 bytes lib/src/svg/xml_parsers.dart | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 example/assets/simple/dash_zero.svg create mode 100644 golden/simple/dash_zero.png diff --git a/example/assets/simple/dash_zero.svg b/example/assets/simple/dash_zero.svg new file mode 100644 index 00000000..b4c59255 --- /dev/null +++ b/example/assets/simple/dash_zero.svg @@ -0,0 +1,3 @@ + + + diff --git a/golden/simple/dash_zero.png b/golden/simple/dash_zero.png new file mode 100644 index 0000000000000000000000000000000000000000..65f09b1ccfb2651847388280262e9104f0962dfe GIT binary patch literal 775 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_q{$o-U3d6?5L+y_mb$ON8yg=J4;fJDAjEXK)=5WhqZ6chKtaR*>Dn6683C z&x3Vli39si{nr`ct5esuh^l=5EhlJYtiS)*nU4-EK*Pxg2kw7;`}OPB(pR1bBzCRq z{{8#+j(z+3u4b8fovn9U$z*(CTkf0hzb$0=7GM2SzQyZ<_|hqlo<3FWTJ+g zm*%QfQn@kq8-Iv|tq!%ZwLN|=7AWEh)NOw+pY>tzid9;hbh=NU zKFxpiV&>qR*Jh=2Lp?$);6O*-efW;YyQ*d1Zu;E>SJU?AOoSg~w(?3Y^m zuOat1I5rn%eJYJLKlvl~_OZ0hol`E|Hod*)jN4_Ci9u3t^OfF9{{Q&VuxnAru64?X z^u+d9e)ZUPJ2xd#OpuAG*{1mb17jm26B9EF3mXT=wzqIKc%qfk!|6i`F0JtscH`hMzE~O?6C3L~@A>4jiF@OYr)~cEa+YxG8K-Hfg@uKJr=J#0`WWn0 zXd_p@b6p_E{ki83{jYcu4)kd{)TkdK%c{bsH5gR;UUr%HeB<3b`xx!>pCfd{(!WQu zwA{3=U6#-ze#+L~-u?dfboL{9V)0J*zZVu43%dsLtTS0&Fz2_T9OFZ83%UM{aqE+J y#`IO~i&dYizfkA&j=g*5zS+Bv{4@g6`Tnc?rrvXt^NvI~fViHnelF{r5}E*%OC+%X literal 0 HcmV?d00001 diff --git a/lib/src/svg/xml_parsers.dart b/lib/src/svg/xml_parsers.dart index cd0cc1fa..7ae94990 100644 --- a/lib/src/svg/xml_parsers.dart +++ b/lib/src/svg/xml_parsers.dart @@ -140,14 +140,16 @@ CircularIntervalList? parseDashArray( final List parts = rawDashArray!.split(RegExp(r'[ ,]+')); final List doubles = []; + bool atLeastOneNonZeroDash = false; for (final String part in parts) { final double dashOffset = parseDoubleWithUnits(part, fontSize: fontSize, xHeight: xHeight)!; if (dashOffset != 0) { - doubles.add(dashOffset); + atLeastOneNonZeroDash = true; } + doubles.add(dashOffset); } - if (doubles.isEmpty) { + if (doubles.isEmpty || !atLeastOneNonZeroDash) { return null; } return CircularIntervalList(doubles); From 38c638fd5b218c1c6537e02d5286a96e7a940543 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 11 Jan 2022 15:38:57 -0800 Subject: [PATCH 048/142] Fix nested g in defs; sync*; v1.0.1 --- CHANGELOG.md | 4 +- example/assets/simple/group_in_defs.svg | 11 +++ golden/simple/group_in_defs.png | Bin 0 -> 1717 bytes lib/src/picture_provider.dart | 59 ++++++++-------- lib/src/svg/parser_state.dart | 90 +++++++++++------------- pubspec.yaml | 2 +- 6 files changed, 89 insertions(+), 77 deletions(-) create mode 100644 example/assets/simple/group_in_defs.svg create mode 100644 golden/simple/group_in_defs.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 03875dfa..9dfda1da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # CHANGES -## UNRELEASED +## 1.0.1 - Fix bug with incorrect fills in some cases of `` elements. - Analysis cleanup of Dart code. - Fix bug where self-closing `` tags could alter rendering. - Fix bug where an invalid `@stroke-dasharray` could cause an infinite loop. +- Fix bugs related to nested `` elements in ``. +- Remove unnecessary `sync*` related code. ## 1.0.0 diff --git a/example/assets/simple/group_in_defs.svg b/example/assets/simple/group_in_defs.svg new file mode 100644 index 00000000..243c4b3e --- /dev/null +++ b/example/assets/simple/group_in_defs.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/golden/simple/group_in_defs.png b/golden/simple/group_in_defs.png new file mode 100644 index 0000000000000000000000000000000000000000..6a448570ed257ead006953f91be6d1918ad1c228 GIT binary patch literal 1717 zcmeHI`%}_c6h~JO-{vT$Yd~(Rl$wRws;epaWZTlovNTOd`4$n85^5zSTAQi))?6Q$ zR+y%^MyqC)r75oRm>u6z5a~imKG5==?zh>0V1L*j_s+TZGk4CNIp=)t=iGZU_+Ws6 zuB9#n0x`e``W^zY=j(*Sz_tDumkojj{ZPO@2v=nF0o-WO_u&u2!I1=yNrOOOQFve6 z;l#43H}crhK&xNW?X>Bqc&NWwvK{0I;l8G?&h(2K^!M54G7&Io$UQDY<6+ro28J*;nDed9wYJ; z08l02vc;jrXTMV^06;DYH}ymK<=!Ws0f1Pm<3%I{UmX+8kBby8FQTcEvGMV{Zc5Rn zwJ7i;TN!HF<%WEl0GOxIMMxB?o=Z`!UMUc#jW1d4XDja}!8Bt_ZgR*6FS08HAFHl{ zP{R3jMHS7lslc^zd8@0JAF3|(5=YK8^TZWiywI0HHa}(zGRg}{AF_sb7c@)O^n+^#1Je10|dx zXM@~2!F$$gsdVSwtRKiFV|{&n1D!9Rw^{=o`>@5Xf)h06_P)4D;@cE|y?eE_T@F1P zz7J%2?R$E+7STmblKL5;=%;??2-`4?8PaiR2(*{t5={L#t>{>8%E#Lx(ys2BA|tY%#IEE>$WJtgvlor9h60y#?qbV$bIg&7pqk#%04$u!>KNXaom?X7z^z%}7F zZpr4?+|Uri#AuqhI{YbDmC`z+-vHC@sO(Dkm@%twII+Au%6Cn9@f z@lo@au|sQbe3TA39^$F#Y0!pBHKhjnz6= zFzj7Twp?T6s#Fw;q{v%S`6YhQH4D_dthBtmm3uQ9>c8w6$X3R?T6K?nvbQqSMkwrd zj~Q_mR+%}f+$u~9ro~!1jNT~X)G(LlNP_H^V*9?t*OR@O>-oo(5ytHn_`Dc1irw1T zPu^9S@T6@tC+#5nu!;4OMq^R&)X70M3 z$W1a8&wEy!$YfF(k@Owr{T}9a;`vczoS7eyDlySMQEn6OfecDWNU(J({nUU-?^h?5 zT}mJTHbxT%`kkxo`*tGzi%8WRGG~3IxCTFjPN$1%Yq82Q=9d*lfw<+#lSU6QwOvNX zK*{l}wFguQ-QK66+ZG>}l~Rp*7bJAgL4i*SRl=58OPcCGGigj&#W+6i71*nobkU}J w2&z-tV9 { return; } FlutterError.reportError(FlutterErrorDetails( - exception: exception, - stack: stack, - library: 'SVG', - context: ErrorDescription('while resolving a picture'), - silent: true, // could be a network error or whatnot - informationCollector: () sync* { - yield DiagnosticsProperty( - 'Picture provider', this); - yield DiagnosticsProperty('Picture key', _lastKey, - defaultValue: null); - })); + exception: exception, + stack: stack, + library: 'SVG', + context: ErrorDescription('while resolving a picture'), + silent: true, // could be a network error or whatnot + informationCollector: () => [ + DiagnosticsProperty('Picture provider', this), + DiagnosticsProperty('Picture key', _lastKey, defaultValue: null), + ], + )); }); return stream; } @@ -526,11 +525,13 @@ abstract class AssetBundlePictureProvider @override PictureStreamCompleter load(AssetBundlePictureKey key, {PictureErrorListener? onError}) { - return OneFramePictureStreamCompleter(_loadAsync(key, onError), - informationCollector: () sync* { - yield DiagnosticsProperty('Picture provider', this); - yield DiagnosticsProperty('Picture key', key); - }); + return OneFramePictureStreamCompleter( + _loadAsync(key, onError), + informationCollector: () => [ + DiagnosticsProperty('Picture provider', this), + DiagnosticsProperty('Picture key', key), + ], + ); } /// Fetches the picture from the asset bundle, decodes it, and returns a @@ -623,14 +624,14 @@ class NetworkPicture @override PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { - return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError), - informationCollector: () sync* { - yield DiagnosticsProperty('Picture provider', this); - yield DiagnosticsProperty>( - 'Picture key', - key, - ); - }); + return OneFramePictureStreamCompleter( + _loadAsync(key, onError: onError), + informationCollector: () => [ + DiagnosticsProperty('Picture provider', this), + DiagnosticsProperty>( + 'Picture key', key), + ], + ); } Future _loadAsync(PictureKey key, @@ -690,10 +691,12 @@ class FilePicture extends PictureProvider, Uint8List> { @override PictureStreamCompleter load(PictureKey key, {PictureErrorListener? onError}) { - return OneFramePictureStreamCompleter(_loadAsync(key, onError: onError), - informationCollector: () sync* { - yield DiagnosticsProperty('Path', file.path); - }); + return OneFramePictureStreamCompleter( + _loadAsync(key, onError: onError), + informationCollector: () => [ + DiagnosticsProperty('Path', file.path), + ], + ); } Future _loadAsync(PictureKey key, diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 283a1a32..651e7a15 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -122,14 +122,13 @@ class _Elements { } FlutterError.reportError(FlutterErrorDetails( exception: UnsupportedError(errorMessage), - informationCollector: () sync* { - yield ErrorDescription( - 'The root element contained an unsupported nested SVG element.'); - if (parserState._key != null) { - yield ErrorDescription(''); - yield DiagnosticsProperty('Picture key', parserState._key); - } - }, + informationCollector: () => [ + ErrorDescription( + 'The root element contained an unsupported nested SVG element.'), + if (parserState._key != null) ErrorDescription(''), + if (parserState._key != null) + DiagnosticsProperty('Picture key', parserState._key), + ], library: 'SVG', context: ErrorDescription('in _Element.svg'), )); @@ -201,9 +200,7 @@ class _Elements { transform: parseTransform(parserState.attribute('transform'))?.storage, color: color, ); - if (!parserState._inDefs) { - parent.children!.add(group); - } + parent.children!.add(group); parserState.addGroup(parserState._currentStartElement!, group); return null; } @@ -276,11 +273,9 @@ class _Elements { style, transform: transform.storage, ); + parserState.checkForIri(group); - final bool isIri = parserState.checkForIri(group); - if (!parserState._inDefs || !isIri) { - parent.children!.add(group); - } + parent.children!.add(group); return null; } @@ -562,15 +557,13 @@ class _Elements { } FlutterError.reportError(FlutterErrorDetails( exception: UnsupportedError(errorMessage), - informationCollector: () sync* { - yield ErrorDescription( - 'The element contained an unsupported child ${event.name}'); - if (parserState._key != null) { - yield ErrorDescription(''); - yield DiagnosticsProperty( - 'Picture key', parserState._key); - } - }, + informationCollector: () => [ + ErrorDescription( + 'The element contained an unsupported child ${event.name}'), + if (parserState._key != null) ErrorDescription(''), + if (parserState._key != null) + DiagnosticsProperty('Picture key', parserState._key), + ], library: 'SVG', context: ErrorDescription('in _Element.clipPath'), )); @@ -633,10 +626,9 @@ class _Elements { size: size, transform: parseTransform(parserState.attribute('transform'))?.storage, ); - final bool isIri = parserState.checkForIri(drawable); - if (!parserState._inDefs || !isIri) { - parserState.currentGroup!.children!.add(drawable); - } + parserState.checkForIri(drawable); + + parserState.currentGroup!.children!.add(drawable); } static Future text( @@ -933,7 +925,6 @@ class SvgParserState { final DrawableDefinitionServer _definitions = DrawableDefinitionServer(); final Queue<_SvgGroupTuple> _parentDrawables = ListQueue<_SvgGroupTuple>(10); DrawableRoot? _root; - bool _inDefs = false; late Map _currentAttributes; XmlStartElementEvent? _currentStartElement; @@ -1090,19 +1081,27 @@ class SvgParserState { ), transform: parseTransform(getAttribute(attributes, 'transform'))?.storage, ); - final bool isIri = checkForIri(drawable); - if (!_inDefs || !isIri) { - parent.children!.add(drawable); - } + checkForIri(drawable); + parent.children!.add(drawable); return true; } /// Potentially handles a starting element. bool startElement(XmlStartElementEvent event) { if (event.name == 'defs') { - // we won't get a call to `endElement()` if we're in a '' - _inDefs = !event.isSelfClosing; - return true; + if (!event.isSelfClosing) { + addGroup( + event, + DrawableGroup( + '__defs__${event.hashCode}', + [], + null, + color: currentGroup?.color, + transform: currentGroup?.transform, + ), + ); + return true; + } } return addShape(event); } @@ -1112,9 +1111,6 @@ class SvgParserState { if (event.name == _parentDrawables.last.name) { _parentDrawables.removeLast(); } - if (event.name == 'defs') { - _inDefs = false; - } } /// Prints an error for unhandled elements. @@ -1132,17 +1128,17 @@ class SvgParserState { FlutterError.reportError(FlutterErrorDetails( exception: UnimplementedError( 'The w6zG~W4O+^ z>i?NY?oXf^Puc~+fDM$VgRNBpOZj{2cMP~gCqWAX4 z7>%$ux8@a&_B(pt``KSt;r+sR-$N;jdpY>|pyvPiN)9ohd*>mVST3wMo)){`B(&eX z1?zZJ-4u9NZ|~j1rdZYq4R$?swf}<6(#ex%7r{kh%U@kT)&kWuAszS%oJts=*OcL9 zaZwK<5DZw%1IFHXgFplP6JiL^dk8+SgM$D?8X+gE4172hXh!WeqIO>}$I9?Nry$*S zQ#f)RuH{P7RwA3v9f<-w>{PSzom;>(i&^l{E0(&Xp4A-*q-@{W1oE3K;1zb{&n28dSC2$N+6auXe0}e4b z)KLJ?5c*>@9K#I^)W;uU_Z`enquTUxr>mNq z1{0_puF-M7j${rs!dxxo3EelGodF1TvjV;Zpo;s{5f1pyCuRp=HDZ?s#IA4f?h|-p zGd|Mq^4hDa@Bh!c4ZE?O&x&XZ_ptZGYK4$9F4~{%R!}G1leCBx`dtNUS|K zL-7J5s4W@%mhXg1!}a4PD%!t&Qn%f_oquRajn3@C*)`o&K9o7V6DwzVMEhjVdDJ1fjhr#@=lp#@4EBqi=CCQ>73>R(>QKPNM&_Jpe5G`n4wegeC`FYEPJ{|vwS>$-`fuRSp3927qOv|NC3T3G-0 zA{K`|+tQy1yqE$ShWt8ny&5~)%ITb@^+x$w0)f&om;P8B)@}=Wzy59BwUfZ1vqw87 za2lB8J(&*l#(V}Id8SyQ0C(2amzkz3EqG&Ed0Jq1)$|&>4_|NIe=5|n=3?siFV0fI z{As5DLW^gs|B-b4C;Hd(SM-S~GQhzb>HgF2|2Usww0nL^;x@1eaB)=+Clj+$fF@H( z-fqP??~QMT$KI-#m;QC*&6vkp&8699G3)Bq0*kFZXINw=b9OVaed(3(3kS|IZ)CM? zJdnW&%t8MveBuK21uiYj)_a{Fnw0OErMzMN?d$QoPwkhOwcP&p+t>P)4tHlYw-pPN z^oJ=uc$Sl>pv@fZH~ZqxSvdhF@F1s=oZawpr^-#l{IIOGG=T%QXjtwPhIg-F@k@uIlr?J->Ia zpEUQ*=4g|XYn4Gez&aHr*;t$u3oODPmc2Ku)2Og|xjc%w;q!Zz+zY)*3{7V8bK4;& zYV82FZ+8?v)`J|G1w4I0fWdKg|2b#iaazCv;|?(W-q}$o&Y}Q5d@BRk^jL7#{kbCK zSgkyu;=DV+or2)AxCBgq-nj5=@n^`%T#V+xBGEkW4lCqrE)LMv#f;AvD__cQ@Eg3`~x| zW+h9mofSXCq5|M)9|ez(#X?-sxB%Go8};sJ?2abp(Y!lyi>k)|{M*Z$c{e1-K4ky` MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 From 1e053b954b0b7c8f2a0777850dac11616c5aa9a3 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 23 May 2022 09:21:49 -0700 Subject: [PATCH 065/142] remove stale files --- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes example/android/gradlew | 160 ------------------ example/android/gradlew.bat | 90 ---------- pubspec.yaml | 2 +- 4 files changed, 1 insertion(+), 251 deletions(-) delete mode 100644 example/android/gradle/wrapper/gradle-wrapper.jar delete mode 100755 example/android/gradlew delete mode 100644 example/android/gradlew.bat diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372aef5e24af05341d49695ee84e5f9b594659..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53636 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ⅅ8zCNKueM5c!$)^mKpZNR!eIlFST57ePGQcqCqedAQ3UaUEzpjM--5V4YO zY22VxQm%$2NDnwfK+jkz=i2>NjAM6&P1DdcO<*Xs1-lzdXWn#LGSxwhPH7N%D8-zCgpFWt@`LgNYI+Fh^~nSiQmwH0^>E>*O$47MqfQza@Ce z1wBw;igLc#V2@y-*~Hp?jA1)+MYYyAt|DV_8RQCrRY@sAviO}wv;3gFdO>TE(=9o? z=S(r=0oT`w24=ihA=~iFV5z$ZG74?rmYn#eanx(!Hkxcr$*^KRFJKYYB&l6$WVsJ^ z-Iz#HYmE)Da@&seqG1fXsTER#adA&OrD2-T(z}Cwby|mQf{0v*v3hq~pzF`U`jenT z=XHXeB|fa?Ws$+9ADO0rco{#~+`VM?IXg7N>M0w1fyW1iiKTA@p$y zSiAJ%-Mg{m>&S4r#Tw@?@7ck}#oFo-iZJCWc`hw_J$=rw?omE{^tc59ftd`xq?jzf zo0bFUI=$>O!45{!c4?0KsJmZ#$vuYpZLo_O^oHTmmLMm0J_a{Nn`q5tG1m=0ecv$T z5H7r0DZGl6be@aJ+;26EGw9JENj0oJ5K0=^f-yBW2I0jqVIU};NBp*gF7_KlQnhB6 z##d$H({^HXj@il`*4^kC42&3)(A|tuhs;LygA-EWFSqpe+%#?6HG6}mE215Z4mjO2 zY2^?5$<8&k`O~#~sSc5Fy`5hg5#e{kG>SAbTxCh{y32fHkNryU_c0_6h&$zbWc63T z7|r?X7_H!9XK!HfZ+r?FvBQ$x{HTGS=1VN<>Ss-7M3z|vQG|N}Frv{h-q623@Jz*@ ziXlZIpAuY^RPlu&=nO)pFhML5=ut~&zWDSsn%>mv)!P1|^M!d5AwmSPIckoY|0u9I zTDAzG*U&5SPf+@c_tE_I!~Npfi$?gX(kn=zZd|tUZ_ez(xP+)xS!8=k(<{9@<+EUx zYQgZhjn(0qA#?~Q+EA9oh_Jx5PMfE3#KIh#*cFIFQGi)-40NHbJO&%ZvL|LAqU=Rw zf?Vr4qkUcKtLr^g-6*N-tfk+v8@#Lpl~SgKyH!+m9?T8B>WDWK22;!i5&_N=%f{__ z-LHb`v-LvKqTJZCx~z|Yg;U_f)VZu~q7trb%C6fOKs#eJosw&b$nmwGwP;Bz`=zK4 z>U3;}T_ptP)w=vJaL8EhW;J#SHA;fr13f=r#{o)`dRMOs-T;lp&Toi@u^oB_^pw=P zp#8Geo2?@!h2EYHY?L;ayT}-Df0?TeUCe8Cto{W0_a>!7Gxmi5G-nIIS;X{flm2De z{SjFG%knZoVa;mtHR_`*6)KEf=dvOT3OgT7C7&-4P#4X^B%VI&_57cBbli()(%zZC?Y0b;?5!f22UleQ=9h4_LkcA!Xsqx@q{ko&tvP_V@7epFs}AIpM{g??PA>U(sk$Gum>2Eu zD{Oy{$OF%~?B6>ixQeK9I}!$O0!T3#Ir8MW)j2V*qyJ z8Bg17L`rg^B_#rkny-=<3fr}Y42+x0@q6POk$H^*p3~Dc@5uYTQ$pfaRnIT}Wxb;- zl!@kkZkS=l)&=y|21veY8yz$t-&7ecA)TR|=51BKh(@n|d$EN>18)9kSQ|GqP?aeM ztXd9C&Md$PPF*FVs*GhoHM2L@D$(Qf%%x zwQBUt!jM~GgwluBcwkgwQ!249uPkNz3u@LSYZgmpHgX|P#8!iKk^vSKZ;?)KE$92d z2U>y}VWJ0&zjrIqddM3dz-nU%>bL&KU%SA|LiiUU7Ka|c=jF|vQ1V)Jz`JZe*j<5U6~RVuBEVJoY~ z&GE+F$f>4lN=X4-|9v*5O*Os>>r87u z!_1NSV?_X&HeFR1fOFb8_P)4lybJ6?1BWK`Tv2;4t|x1<#@17UO|hLGnrB%nu)fDk zfstJ4{X4^Y<8Lj<}g2^kksSefQTMuTo?tJLCh zC~>CR#a0hADw!_Vg*5fJwV{~S(j8)~sn>Oyt(ud2$1YfGck77}xN@3U_#T`q)f9!2 zf>Ia;Gwp2_C>WokU%(z2ec8z94pZyhaK+e>3a9sj^-&*V494;p9-xk+u1Jn#N_&xs z59OI2w=PuTErv|aNcK*>3l^W*p3}fjXJjJAXtBA#%B(-0--s;1U#f8gFYW!JL+iVG zV0SSx5w8eVgE?3Sg@eQv)=x<+-JgpVixZQNaZr}3b8sVyVs$@ndkF5FYKka@b+YAh z#nq_gzlIDKEs_i}H4f)(VQ!FSB}j>5znkVD&W0bOA{UZ7h!(FXrBbtdGA|PE1db>s z$!X)WY)u#7P8>^7Pjjj-kXNBuJX3(pJVetTZRNOnR5|RT5D>xmwxhAn)9KF3J05J; z-Mfb~dc?LUGqozC2p!1VjRqUwwDBnJhOua3vCCB-%ykW_ohSe?$R#dz%@Gym-8-RA zjMa_SJSzIl8{9dV+&63e9$4;{=1}w2=l+_j_Dtt@<(SYMbV-18&%F@Zl7F_5! z@xwJ0wiDdO%{}j9PW1(t+8P7Ud79yjY>x>aZYWJL_NI?bI6Y02`;@?qPz_PRqz(7v``20`- z033Dy|4;y6di|>cz|P-z|6c&3f&g^OAt8aN0Zd&0yZ>dq2aFCsE<~Ucf$v{sL=*++ zBxFSa2lfA+Y%U@B&3D=&CBO&u`#*nNc|PCY7XO<}MnG0VR764XrHtrb5zwC*2F!Lp zE<~Vj0;z!S-|3M4DFxuQ=`ShTf28<9p!81(0hFbGNqF%0gg*orez9!qt8e%o@Yfl@ zhvY}{@3&f??}7<`p>FyU;7?VkKbh8_=csozU=|fH&szgZ{=NDCylQ>EH^x5!K3~-V z)_2Y>0uJ`Z0Pb58y`RL+&n@m9tJ)O<%q#&u#DAIt+-rRt0eSe1MTtMl@W)H$b3D)@ z*A-1bUgZI)>HdcI4&W>P4W5{-j=s5p5`cbQ+{(g0+RDnz!TR^mxSLu_y#SDVKrj8i zA^hi6>jMGM;`$9Vfb-Yf!47b)Ow`2OKtNB=z|Kxa$5O}WPo;(Dc^`q(7X8kkeFyO8 z{XOq^07=u|7*P2`m;>PIFf=i80MKUxsN{d2cX0M+REsE*20+WQ79T9&cqT>=I_U% z{=8~^Isg(Nzo~`4iQfIb_#CVCD>#5h>=-Z#5dH}WxYzn%0)GAm6L2WdUdP=0_h>7f z(jh&7%1i(ZOn+}D8$iGK4Vs{pmHl_w4Qm-46H9>4^{3dz^DZDh+dw)6Xd@CpQNK$j z{CU;-cmpK=egplZ3y3%y=sEnCJ^eYVKXzV8H2_r*fJ*%*B;a1_lOpt6)IT1IAK2eB z{rie|uDJUrbgfUE>~C>@RO|m5ex55F{=~Bb4Cucp{ok7Yf9V}QuZ`#Gc|WaqsQlK- zKaV)iMRR__&Ak2Z=IM9R9g5$WM4u{a^C-7uX*!myEym z#_#p^T!P~#Dx$%^K>Y_nj_3J*E_LwJ60-5Xu=LkJAwcP@|0;a&+|+ZX`Jbj9P5;T% z|KOc}4*#4o{U?09`9Hz`Xo-I!P=9XfIrr*MQ}y=$!qgv?_J38^bNb4kM&_OVg^_=Eu-qG5U(fw0KMgH){C8pazq~51rN97hf#20-7=aK0)N|UM H-+%o-(+5aQ diff --git a/example/android/gradlew b/example/android/gradlew deleted file mode 100755 index 9d82f789..00000000 --- a/example/android/gradlew +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat deleted file mode 100644 index aec99730..00000000 --- a/example/android/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/pubspec.yaml b/pubspec.yaml index 2a161fa4..e6df26dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ dev_dependencies: environment: sdk: '>=2.17.0-0 <3.0.0' - flutter: ">=2.11.0-0.1.pre <3.0.0" + flutter: ">=2.11.0-0.1.pre" ## For developing features that require new functionality in engine: # dependency_overrides: From e25f0da6f8b65a5977871acfab68e7ec805591a6 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 17 Jun 2022 14:37:39 -0700 Subject: [PATCH 066/142] update goldens for fractional translation (#721) Co-authored-by: Jonah --- test/golden_widget/columns_and_rows.png | Bin 23184 -> 25764 bytes test/golden_widget/flutter_logo.asset.png | Bin 10130 -> 10330 bytes test/golden_widget/flutter_logo.memory.png | Bin 10130 -> 10330 bytes test/golden_widget/flutter_logo.network.png | Bin 10130 -> 10330 bytes ...go.string.color_filter.blendmode_color.png | Bin 9032 -> 9168 bytes .../flutter_logo.string.color_filter.png | Bin 7518 -> 7618 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3411 -> 3404 bytes test/golden_widget/flutter_logo.string.png | Bin 10130 -> 10330 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3496 -> 3490 bytes 9 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/golden_widget/columns_and_rows.png b/test/golden_widget/columns_and_rows.png index 34053145e281c2d6bf83eb6acc305fd547a1555f..d4baaddf86b636c9e296dce515657b0d4ff1654e 100644 GIT binary patch literal 25764 zcmbq*2UJu`v+f`QDgvS;0U45_0wNj7Dl%jQlqeucB!lEMpeUdSLy#<>WR#pUl0lL% z63CU(Q-TkbH6ud|b}yd&6L~FiEldPaHlk4#`?l z8zN`+w4Z*J5`Rq%dq~nvn{umT{4s9x^9+_`?wt1fer0$W`?p(ZQhFn8x9gT=+3B?H zcw^nR?Q0Mcl_`4L8p=y}bEFBIo&qcM7E6jEPc=Vd3&* z7m}NqVwy2XdWxYc{O~Qoy*BNmjXYYI`%@2r41z!{PX)>W?7R}}G+w;^Il|7~VeP^C zwDSI;Y7uQ#Y4Yh06^ASPruR9g-Y6U6JZ-}1GQ`g(I~2RnQ(^6lg+;5^JA206Af20* zs_j7Cf^gHJBxCDEW@XruJeIW155;#iI;GOSOuZX#uh1tZI0x&k6(@(WSbxP*bMEfx zf1#~yx=nAv=cmXjz4DpWXvL95Mu?-?=^#Ju3|fFD)Q9*Cv)NEbWW zN_D;BI==CDt5~QNYQ^pWTTy?C#LoP%@03yQu9Q;&@sYy_G&0TaVjXXPxx?HwO>MA# zWJ^-{$1U&dzEIeo$1onhp}H-!lAYS5F};GY)&6@hk?~kYrbL@-Lw;*WFad#uHGT8I z1naiF5PO~)8w-g%7FU}z4uvZZAQ@N-VS-7#S7Mr5LeE?=AcgesJdJP`56w!2@cq<$UI1z zlt!hWbiGI-yfQfPvzHKw)0h1w>=yqsOg6a#}b z#(^ELe|xRcLRNa`4r8XM-@z2sG-A^;>i!uRqYv0wYQ5rsVvV0|=ybpD8;89%u6mrM zx30lP$tW+uEE|>xHWUt=w@fQ$^b`e1Hxi71(3o3TikyQLzJ(gMgXP?-9(BbZVR^AZ zFr(niG2i>=`skzd~C#Hp{s#xkvl+E*wok;zS{D3_tX1u03IaSwfq` z_q?nR99WT6+h_+{!KgsT=58Kv;Bo88Vb9^v@1tn#NO)0+E&uCxl0|9g;oiOQI*QZZ z7){Hr3i6MzN@|xy|2kvvLnQ+*=7RyHAIcZK%m=TdiWScrXBx=
t*%$@hS!C00^JF1i0X6&Mk*F7tCFiuKoiJG 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�u9vbX{zc#lGCFlb@L2Onwq@UnkgLn5^=% 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 OceTRWk)O+RKm31$8ZSuz literal 10130 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 diff --git a/test/golden_widget/flutter_logo.memory.png b/test/golden_widget/flutter_logo.memory.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 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 OceTRWk)O+RKm31$8ZSuz literal 10130 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 diff --git a/test/golden_widget/flutter_logo.network.png b/test/golden_widget/flutter_logo.network.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 zcmcIq`#)6O_dhcxj#AE`C@~k8=qgHb8DpMtDY-nP>r?4Tl2ppA7#W$0iczWDLP+X1fi}&WkHh|c-R;IQT$wNc}Q;M>~?sd`SDh)M&VC@dPE`!6IsExT74k7 zv)(>-`(S9bWPEvj`pk-xmrw0pe=CD_Y?7|-x`v0dm7ZTNJ3d|g+`f!|bQfysn>m}i zm^gFw%a8>8Va`{i+W& zr_9dDUK^Sok02DL3PJG}-cF!$*HCFfj0m9&Labg+v~PfHwZ-Atpj-!2e;Xp2HIP_S z((5~*s*{1)K)A*$34>^`^*Kqnsq1i&4=4dHUkF}m^C?tkl7TFss*p*1qRd1lDd8cc zp;TI$0Wr2JKvsoMgm?+XggjzEoo9nTLQpxb%|&D#iT1zcF(HLWL7Eqp=AK4$rI&(G z)R=^+9VmSX<>yFHl3~ZQ!JmiwBQ1bWA(n^G2*eZuO6UioCMizAwFE(-J+39iNw}7d z(-uww2AZU(gKJ4J9b8L_(?R>0px|yzr7_7AtcyS>D3Jo>9YjMVVHF@-WC~)Vpq)qo zVh96nMWlf13I1dXyuuMmTRbth?(l_(za0_H27odpmJ+f6601QHmq%w_$I+JTj4XUGxJrRN|EOBdcz^EveWWh53)X15;5YD$KCXQdFiKzePM!xcu8(HO&UsS_^{D7Og3m?)#j2R#baM?`?- z?W5AXE|9n|W$uu;ZD6~B#PtW<>m;rz;Qk;3!)RzMS)H+?2;~-;4j!G!ok0vJ*Mv%2 zmqegq@aB6*PJa<3@hnmAkc%*OI;80VFij*0OaYP1LA5%F#Yqu0D36hfe=9MN z2yJefFTtzWT^`dT85lryoJ=NBAq5Gik|9`QOlLJ>d8Da9I~k&iwUEmq@taUgPe@R4 z)}~Nph*uz@VlONfPWUS`4V=joNNA`684Fj5X+W+C#1@of*u^T~PrNb^16yG+LM#s? z*-FT*BB7H15OT$&_!n2mb(#=)Larhy&IfH3={DaEY$rrOaGDTTfGsIr16wi$$UG$` zMy8;677c~v4ci1HPnSZakgy(1E|W}wa22$ZDTqCVgfod0Aco3Jj7$M{3JvvNMXca7 z9V*R~*l{4$YzkF_oI73#Ncc38fR7LfpGr>O4;Y22PTJ;KQEA3xQFnhvLwzQ2Oq=fkx2L|lI>wSGd7$UFfNx$dpFS@ zhlDSk@Ym(KTN49@JdwxNO_(a8*gAM|!~Tcs1ma;*6oWW1qE#RgWKUIW87=(9SmDrH znOjOxmdiT0ZRF>ZMZ>)n*zO<;B$9Y3m$i&;c{F(Q%FeOi_sv4(3ibYX19GE7o>$9- z#glNJVxNZb=OGMx{U}B1&W5Y^?paD3$6D^LeW)pa$68ptoU|#ClSC^1!{mNezzN$L zH$@yMk^6=*$tqq3Wk4)Vn@^=(AwsK*RBWO%;$Uvk@%(71ORUVBA`Im**v6*)=dHw4 zA!_i1w+~fxiI@hYHkg5Gh&P4yy=ZlWNV&FdgHyy7tNVpbTbOdGx zksq%lBwU{@vj6@30V<#$A8l3oO;?{vt7P(^K29VIPqWY1)pL5~)Fsd*7{fyGk`71;U|M~0D&}&=~ z)VzuC?BLl>1m$kx*$bYnL<;};N5b<8QQv?5S7H4!dBJuQ^tm2XnjxKK!Tz0XQwnuv zR4nWv$#G?H7tOd`?EREmkt6mGW zh%55v{_a0j9{YgNZ(04GKEsZ}V%ezJslN#r(7<7p2zG=M`F2LJHX*t*{CB{ttO89W zt}Vy1_w9Ex#ja32x3kM?X2a~T910m6w^>=?&tl;*qr#ci}O%M33tgYy>v92qT zQ#gx+BmA<-&_QPNHlC<@x`gtFE|-bYZ_y;DDuyJBS-cNRKsSfWgt!pUeIs-#5{eGS z#7?65FgBhNX*|Zd;~?PbL-p6@RWdoZ)^j+zd~`RR;S9%3tEgCg;8BZr5t}3xzCkf` zl}KB1>h&;=R%R{WMuF#Ae-UK5=Xt3J-MXnsW~B}{P44(fOmfO$4DaCDN&)vJ4ejIq zNr$j^F2Xx_rNnTCLAG$=&!vN;-+QFPRDg!O~B2-Nr2pj9zHPHP#$VR1*;-4-4Z$9L?k@rdjQ@;Qwg|Q36LG| z(nbmiZjW$o-;@}|L-3;J-@rYUmjO4sgWw4pPMJ3+P+0CII5(GR63SmNCyGTecvxY0 zrwXZ3WQG>kUC6V6d4DAg&&W}G0dfN07hEKWG~!*rc2@We#nkdJJpA@BAQ$@uV-)v5 zw|`~gx|xo+ZcLd`>`g;e($3)BD&T3d3yV^84}i_d&DVsEpf?_==xzbJTc-$}C1D4; zP|($Q($?TqTsPxgJSdTi6(ixi?a_D?`8Z>EZ*Vt*=Q$l7Udte^ z5*9}|0zCFy$MGY@2iccHnq<6=A(S;Iz%5#8B1YR|q{v4tt}yP+X*>Wr<2;>}G>0P$ zl*c}Q;E}2mN~|OZeE@cfFOHC^S4yl-h!U<%KF1kp5tV$64(}saRnVEm37$ApEzUa~ zUJq^sSbvfAy)bYz-Au7N%tdg`N${1;>!CA>Ti}oh>oY$pwm(WSO?~4gMZ~?W#CF~x zlZ@eA`b$6QyNUfR;>RGoAUNEdD6!4qm%$}L^#TgDT1j$~&i2rUQx+VSy~3p*^ys%R z38e&%_J+!g3m8jPiNT!>Cpaz1Ykm5DU1)-{qamHaij1AvBohfY2OdlgkIvH9kx=+L zTsX#ZcyrBpC34t#gt9I|ie9gVj(d7Z&@)KILIq`JDXBCyEmm>YFpn-RF6uPojX8e_wj@#wQV`=M}A}0Bm z;NSufVwZ!LvnHGwtpu@u zUcv3)&dlIIQ^bsGu+U}nAc?XLg6d1tae~{GnfT3|vHMFfM2Lgp6WIl7V8_&fV_~c` zP3Alw7{+7F;d2KtVxK*!lpa}~u@@@1*R(*} z8)L1i-JD0GAGds(Io>!v_OH`uWzs`UWv(`KDLQZY^Q#7(_g+_W)33El@p7EYZOcQg z&m@C<6h8(i97QkMACpMTf`axm4u!Xu=6DWXFe_+OW#Q)q13k8AVRA`neVz1b$Lfr^ zZWUu@L5f`hHxXhoX^Pra)y)q>a~=70t9|{++bv^t zZC3U@7q{B1EJaJF{(+#})$O6U4`v@Ni%cB|lRR(5t= z$FnL|w~VW{B-NE>k@Ac}SM%QFk^AGBOHt1;h5mC-uCAiLw`vf0l|zi>|JYK&xb zs&Cx#u>Yz3edAFh#2>EdtTEPCUo}S2@>z`*^Elb*WhUlB9X}TY8ul*MV7Ph5aNfD~ zYHfT!z=wGU6YLLBUQCO-AW*O>=A(nFk>;6%SpVU*M!kzO=4y<5>)a(5HlHVSfr|{t zyxWpr&98Hc#_QfYEh@;4Ik(B7d+6$w0YUkqg2ZTXbE}hFcdj)`+;!NB@=iXJN~7PG z26b`FdXMB=FxsD5Flvk#epO+H$~|2xMaU$K$vwqKPng7r3wAs&on+goS!%m-$ASXW zLu2`2xh`5fAzT1*Z}L&qq3prO7&GgycvTct* z-=Z-RbBD8B@oc)wInS^ieI4B?bcRvpCWi$@*;k%6m)py>rdWQm%V|x@>1RY?Y29Eu zlW#XOarDCLc}2h4mjza?3k=v_WxMq54{s&L?#`hH9*?pPict#e;E?1$L<$>k7a0YA zYYgjYkak^w@iCJ8S+$@b(W0}XZJ9&pp}vuX=H{;lts_2bsFmU8$$9vx zci&7pwGTcKtP4lmkHIuvo7tS6eP!WH^E%(nZZP4l>ESyAAqTEb=P9vnc6M9L4js%0 zI~ZoJ%Gi+-xYV+DUq@uUlrU<85t+reTXjYnpE`6^_q;;og+Mn4PqP^DM~5siVNwPr ziF~{Hzd{sk8%LLoHy|OxPNiQ(b6CLbGG7JQpzRB3YRZiAc%2t>_>0W&!0cGuXQ~?2G32>*dn-j=x)EKD+2p>vf|o@yqMHz3XbVbv+l(T($F1cWH@p z^R`PXDnh1#6Wk0}8`4j|AM1*Eecy82NwX`)vw7Rtot$S_LW3_S@9V4@Z9dj~yQx`vCnxI{$J01DbBS5=>+ulI3?pR?Bfy>n`wkY{ z!{S$gqD|xQzm~x!n)NB00^Qd7y~@2Za40$d%gCcLwKaldRgKIdClQha`ygXG(KXMo z!6$7Si-r`Pp4$fa-!JuO*`_pWP6)?ySu(sSqfds^Bxcpcd^?niQjB3EHy>A#&ls6MTlE|<<7Q_2?FFy4Si*O}*03y0pD@I*a=Y@@~s7dp;1 z?%%l$sA10z)?8k5srhY@t%&?!pv2no=~JQQaLbL+k;<;Njp+k*fcNv+sUOqv`)Q|5!$?Vyx~BQ|E~ow zO;Xyg#&ivsaQf$FB%Hai5c{^M|5)~&)O&CC^xDl@wzg*TZ4Dp696lPG1OS)cP5>B% z1w9H0GUl{66_`H$BJjSqZMeJhwNt^zz4zWc$WIJR+_m#Y{^@DKJ;o4l^04F|Ip^3n zY>&Nyu)h8+LuSpA`uC1ig7Sa+7Z;9rcYV)1x23}T&+nGctOsfWKRUdBj|pOWJ;^Rtm~f0?(fN;QP3)=qKZH=aSsq z%wz46C64cF4m~uCY>S`669&LQ6(60&3TX~WzcJcV)fKa)XtX6^QF(=+eEt(tPJc(= zt(=-y*Nl5r$0NMWqHCi2(jK1GTqDjb^k2Gk(xbb_F?Wq;VP|P=`4_Fr8l(+vyHcea z3kuTTdp4zKdv^DkBn-tLk4c!?dYjS8*lX{)JEOkCCfK=1-{RVyjKYo$^w*1Ff#l5X zp01pB?5Gk!#B!+QSYWB2WU<++#Y2MOtM$)~lkeaCnw53$&E`-oi))R^ns4{6D5#Bo z+vjg|(2-4Bcf_D29+C(hWDdP#kE>T$6VtTDM#su5!d_G&wC zJWkNuQ@GUPL$GP|_tF}x0G-~V^l?~7@HMhpD>OQ`SsK43@NDJAz`H-nZ8aU-G7E=o zKGq$YTVK@UGiz_XlExH_Rcr_|wW@CcukwW02;T*?G~Wr>!Rfejzkl7w{2u?{pJj?y zBm*1Y92#v)tXi*0r_T32&?-Y!X*zO#Ph<8CPS1YtH@%z0-^^Pp1#dTI<$ho7wo$(} zAp86ExNK9m{x#XzXG#?rN6)c;y3=lYpK zMyXiiNZBgU>Qc&^)&2Xt%H`}nK0Y-qmveSnuDQM`mCh(8JRU3fnuyA65gPKf7bESb)66Lz$%%!_Xgl&UPeO#%F(b%4~VPW4~eolaI#1$8d$e z)akc^1()OAytH7J8fh*|ap;e}pV2XFq+h$%rMYwGPq2G6&zwuyZ&UVAvQLc}@Gl~i+`K<@da^zh`0%l{*h5(+lsEKGx}>c?))CbSh>+@WGJq~*75mKsh$`O z?>Uemr&nf5zvV4>`#$DUbIa|lhx>c=4ChLoET&VpOS~1GC7h0V%UnWx>+Xz}n7M@Zzif8BULprq9?r5i zhLIy1w0R3ph&%r2ztjKWQ_Z{PZoB@wa}>oj77siB668&$Q=he-Wu&>QT9+M^{JDG6 zijB(}&fVMd*rHZ!VHT2*CWUV4PH(S$nzy$0sl*^WEMbp0e& zHf-9_S7r!eL^sr6^!I1FhBhZaPP(Km`z24VL}F^X-BkF7I!)`V``}pE(C~?(zSh8? z?EAIvQ#p^B&VuUc&_(kFM7T{{H0Zk5^h3kw%9_iJ6mwlpTOu01Rk8;uKG_aOZa$0W zZt_SA@%^W{d-QG6wA>$I`Pm&oQHqx^mVrXUbi|~FXn1pX_*GVRgAON>C*qFR!iifL zZ!_MkbtB`LTv$eK$6oO8atW?_Qadc(Q~2}Eby&97UKGe6s=-aRmcKmuz4|lavKi3f zR$bcgD+Lr$efaCFV&fjoC6;U4YEzFZUNTUoj>0bE!Q1*90_nh$(NTuI!*F9$gdQKo zFGk#1K}9`ZK2?m?Go0K;9VAvNY}#;X!6d{!A3s7S=F~El=@*9d#7on54T!j5@f3=? zK2bruGlwK|-5TxSb7DjS)~47!3%U07-IPW3AB#2=CA$Pa{(iGqlz>IzKQA$)^WY%# zH~bXfnzaZ!g@!+XU!v?%X7ROoO!&0Moxv7G^3f9b6-b#4(Y_Aa*GFM&B^CykXiPKG zAGVQqctm>_{-YQzUZkCfdml`%E8$RS@TpYzj_|6U3cqi$iNpc&4uUqCjvKhcg(rL( z#@&kHha8BpBLP+cxc($A+`J*CByIuNULbMd>QGoo;!Xp$D8cqC+)bf>5CD(B^diw2 zToqE7vkA6vkqEysBKjJJ_N|0}9@Idt7vX;mPFq+C%3{;0Iq<83zQct03UbtUloWC8 zaYBUqQKT=16mjioLOhRa;R^~NsN!NGA-3Woi3>Nkhysb534zIyY}Z3HRzyBN!_P3> zefcOo3WFSeM{5TKrE16vQ0UFNlX*Do`?>vBy{6GJ3cZ^x`Zf0Ara#Wjw OceTRWk)O+RKm31$8ZSuz literal 10130 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 diff --git a/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png b/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png index d46b6ded9b7b4cbe558dcf475ae18bbc7c50b096..6b12ded3f96226de0bef22a1502715fdd3b1c757 100644 GIT binary patch literal 9168 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 Ju1IB({|EC_!h-++ diff --git a/test/golden_widget/flutter_logo.string.color_filter.png b/test/golden_widget/flutter_logo.string.color_filter.png index 0f02fbfe18a983b802848cc90e92329fd572b611..d80af0975390b8ab1d09108ebb7d44780e376578 100644 GIT binary patch literal 7618 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 literal 7518 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 diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/test/golden_widget/flutter_logo.string.ltr.png index 7e70b9565dee51aef6a52f03b7b7119a82c15361..e4402865634cfd5469cab823e5056404bd347fb8 100644 GIT binary patch literal 3404 zcmeH|`&&|X9LK+hY%;A7Ej3qyNa}igGA~(E5#m7wGqu(-)6|-)P`fBzf@zY~25Lz% zua&deEZ1Y!R&!b|S47%W63Q%1%P2214ND``xzB0O{)+ki&q@lq9 z^G$3_5JK~LT+T*>=1>tLY$1LGq%<{aKU^@u#sD_D*tTR4Zj1zM-X7eyu+mVpJw$1M=DOs z_ZnF}I7;<8>8YsN!a0$BR!#SNO_H_y-wBEeG<)pF7r67}!6S+7-F$gTOLvi=t)c&v z%6Me#wa>Lbi+b|}G$>?t%{uUZcfhGO_Tlq8nhh>koHx6iTRYd(@vS3AZgC&`i zDp`PdA( z+54hSDZ;20eRIT7kntM_Uo=pFuox!*2LXJ9gCYP_0BZpl09b#AuyPjw+X0AhPzb;g zfHQzpx-V+VhAj~|fGi`tbR=7a5gH2>#z<&JMF})e^--2|iZN{CQFWuZ83I$F6Lz)l>{0dN4s0dN5DoCRCN zdK420F|r{>t_4O2-3~z$?OAAfAV`lJ5m|GkB&399&s*!T#x)jHv6ozjUz5yzCjU+<{zYOSrA-b}@EnUK@% zD@opARW+lX_oZEPe9g6Gy6^PJ$vEs13OwtqBlDfLS34YdJ}HKK!=^`D=fpTcXu9H# zrNWps2(^znz4Vvs5j6nE!IUzFB{{P#MFM0O5KhuDGw=(8R+_cucF@mOV!G_}I znp4rT0^SjD)&!glOgK*@gArncIn^Da#op6zsrRCgna3oxlclSjbXe$T5RqWWmYwOd z7dog9tjX`R5C%Z1^K|Hg%VpJZ+BTuW>k*q2Slsc zZT>dOlKRNs0L-g@XdxE=1Rh(Cw-c6AvX zgB5S|1NC8e30t9rRfQ4h$xoJoHRTiF(t1Yf4;j>lpjc}6Flwe(b=w$0*OgI*iHk)V z`f)4Qzs9PVJ!@uej%H5jYNirG$ZwE!G)R=ob+D1udwD+bjB4|VRZ5iH!pHtPmGwdX6Vt4K=k>JY_v$GN_jin8Adu87K(vC&TzzPvX)RVP=?4EY4rdXok1uxWI PNw^z4zhKTqc1+ek!J+%< literal 3411 zcmeH{`CC(G7RTQNlnfY2SY)e)B!hs`qAgN^hTMrM2?!b^iZW~p2!bpM%9cuoLMJ3s zmQg?uQYcGNS`btE6n%nehfw#z6h$#e4NK69F@z9`s6FYwQQlwji~Cw0;`> zLzVK$W6i_pzU9-IG!U|KRvh@NJJ9~!^QNS-mOb7$g>#1YwftY>n`6FQyRbpN^o8g_ z;4=nV#8QW?z@3?bqF2_%FXeemW8d4wgw1K#e~{HLQvTC01AQ*~lenfB4r8U7L6 z7CRgsdjV-loW(x)S=3A||&Ek^r z=0cUo8u`*ObiHH|H97!jDz!%WZWwYD1E2u-7l0)b5G|rO5`aDcs{zbN05}4W0{F}X zN*9r7Kxmmc0V6`yfhvS+chcb$+ihLZHd-KZ%z-2uA;~@{ zlY$8l&mMr<1fZu)p#Zi4_|gQ1oeX$1-({)OO*vE>Rp~va?0fF#YsbD{xQyW)3nA?A zMG~bT_R7-p6!Gt0x6AL}Qv2y}JR-~_oV!m==ihedxzD(q`=Y##Q!{$qoFB{bahayel?6Jg(F16SS9HHM`%UCcpy+vZhf=QnY4{PgRem3ob4 z)b^LF>1mG^jQ_s2sOO05Efl%n12H0@ILdE9eL-oJ!5FK1VB>jSbnm(}h3R7$eJ<5V zzx~>FspAKKJ}RS*Q-&$c)%PKJmoJ43K9(ReklS;VJiFzlA&Hw-#;| z&Ac%WUa8bIwp2}_exmT*X#ZCU9UmCp-1uogH&jKt^NpA!3?hTU@fCzTy^7qxEiBN z*3tvP4MeGgBy5AFR7H4`Poz8<>;(%xlJ>aApS*K}vw45y2ghaGTt;LZ^?qpOTkWd= zQ0N2-t>+sFem$8pD)m3Rw8whfX^FF<>xWMs_Dv7did^=V4;0L%9S=DFEU%h?YiHu{ ziZ)+yMY2_^Kg)@bT?iZ3Z}lSMc})1~^~v=k8J{o`AM!FnwN)U{0R&>z zgk1+x4Fo6)*Un>CK0D8$(bSwzKW-?y!X?Bnt zA%jftT=9c7BWtq3OBppJzl3e3Gvmzuc_`YZrLTBMNLai`S mgdK&aD`&-l6$iip#uDYjYr3_J@>F}1AHg5*Vt2CQiv9o@we9f$ diff --git a/test/golden_widget/flutter_logo.string.png b/test/golden_widget/flutter_logo.string.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 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 OceTRWk)O+RKm31$8ZSuz literal 10130 zcmcI~i$7HB_y3+TW$R`SLZ#+HqLU(&#F(aGCf@iXCgCbEXVYQxc# z?#6!;ymklI%i8<9tZfV5T8mmxy2i#>_e_;jI*$&YplVQWY&-Xtec{4M^-8+uHtc9q zw*AgoJO9cb4NU#O670AA519u1K%NLWyXkjs5>=;rs-g3?Of=)~o`4+{{SHT*1|8f} z{j0uMylB_XHL0z==fBJT^S$Qa{rVJO^?&&%e%&8TL0;Zi9@4hEIR05@^FZ)i!;Ce> zgCz%={9KzaQ1)R=WP`mBJ1bB3qtZkRqm+3nj1627;yhQj%C;rK4#kk0Y!13c=uD?j zxu&IxtSIG$+FT?nT+Y;ytvW$Nkup_=Scj99h)~kKTOuT-iZfN2h#Coc2te5cD3gom z#o>J@`tt$lR|3fle|wU6YYa%%7>@J-rBF*g5S{WR2*u+iq3UKQLJZvqd@XwrfgG4h zu?5kL5O488)FVX)5H(5B8bp*79YqM1N*J3%XCh)<+^v#lVE0$j*i7I>!tTXYV+qyG z5CI+?=f#`@?Ifz#d@h2n!ow!&g8q+*2&B&hXLk@#FK2`50fM*pIf#n}L7-r*2zj{z zkE?THzJBv`VQV0*rRG7$2GA;m`?m{9tiI5Gp1kyqj z6a7UZO{Y+u>4aN1Ap#4@xE`jV+(`tJECAIbLF)i?5((-Hpw0y71^`tfKoMM%oDE$N zph<+&B7M-r2u(u)XmWA$h&rq%g$4KsBKE+9LV$`qK@1~;B2vZQlHyGKEr~T#3Eq;T zDgKsN2O?AaEh$ciw;u@F9;>M|rXk^0eKD$r=J# z1p*a?mA)6|1q3-9oY_kDFQK6&CkZZ0GYU1IB%q0as7v(HguNtxGAUvpvPn@BL@FsV zDOA4+Q4hpv7YppF5vqET2&JAJ@e{zCn7POl9j@pz z8LcZc)Y+8OyogY4&L`%^2~{Td92r6?m6k=$tqpL3Y$PW^G>WCqCc@%8i$dK%>@>(i z0Bs>buK}nD0h$G%(In_O0F5U=!T&@75h`1KB`lqs4J8x`RgG9~$VC=c#3md;1Ssb5 zmFOgbz1+~7Fk0e5rD-lA@ISbL2pc`@Ss(ZyY7wHxd=N?hJ$8afM$N+jL>j5Ek4i(G z2nzKOARe&}kY&1DQ9fxb7sc@N17JP&fGWwh93pUq_bOFp36C7c4@%evl;n+4X%|UeYO6(vBB^>6cwf`uz#f9A!5-EUaj{g98&5+w zkRIxtN5Y~>d}~#vvp$J*luBC&ePD;%uu8<;Nh0~8SXLzAmNT59=g7F;)aIsBNw?3@ zP&E=X3qZq3(2W49M}i)w(x#B0aDb?hv%w<`G)bo&=uBtQ5zz|JBxggu2nh=#Czcye zR3ailwN{HtxTKiE6_p^Qcnic566=;N=uU{MKzBl11G=QRmn-7>5wwvxDol(VtrB$_ zN+Z`ILf-F^KVj?0e+^ICQ-+`Do>9BZ?lg_?m zQ>d22l1IFgkg$0qfdC*NB>~LY-1OBXm$@p;m*jCKidDioCSa9mXu$;R0xE6G1gtiN zYCytv0IWI*O9QgTBv~d6^&(ZVNF>aGv=vTgO2SC8Tq^B<6YYsen88GUU9QIjmnTYC zJxQPhK{2-kqE`tQ#0XLpff!GUB_I;8@nx4d!{3+O*z;!0vH1<9_L<|ucjL{8pEopX zAk{=XH$Upkcro7F)6=7voLDs&Y+z_DbT-julDo3@=?J-IT$y70`_YmEjbFbE7opw> zNZ5RwecYl_#Z^(tH zxmiT!OWLMPMX{U2ye5s6s8Ge^X1_U7Ib4O|H;uxp{!e$aFyso64GYv;BGOA0VS+mo z`{{)BO(vg5s0bk5#TYPeJ*L}m_0F%uo?;9VFJBk%_$Xwq6VDV1PX^EQAI~fbZzdnT z{Ih)$g=Y%SKilVnJA4#URIso=@imPQ+3H5|9n{Vo8h~&qN`& ztDvD9Ratu-g`~Uq@~DGnhab=OFckEslS?PuD}Y7Ip+EiW=d**TM2-G5>c=xInG!Af zQ2jH>^rg%n-h`_%CGqGiCHDsfy9%bqa z3p8qbdRCSxK8aM;gP^2FN*sPP9H~kfx+gpOJyvFBSwHx#gd?L&S~_X!@m=Px)j>y5 z7GLx40AslGXbR`GN$0o6J2daBGMpiYqeM!kgJtznsTjTD)S@s2qKDG&PL{=&8Oe-T zyp9OD=&2Hh^2N8fLa#eKp+hA0P=}KanOHcTC507oi_TDGix)>KXMrOkemS*8`}Fh{ zPoDUtu8cC1&cqVYBsS-6J)5J;NB3b2JV^_SlIU=jKF9E$DW!@VY~c{uD1eZ&J#hnv zKue!ORdC)Z25ws-<6t%}12ve(+zm5XU_iYU4CE`xD3He)GB@&}>(vPPMT~W8wGg4w zPG0XoVg3YY;s!QGD#O9e^^ioL!DR8)%D7u*v2p~mbj_@*Y`)N|ny{))XOzH2P+=1v zw@Sq$@@ujjiN%4Ztl-R>Ql_fUZ$U81)2Bt_;EbN^}&$y^-mh<&0a<^n;K{ zmPRS#8RHanHV?*g5>8J4v>bV@%T4!tY=gT`klTqdN^Bq}Nxy*muZENJsxMW{hYQEK z4iloQ6uQoWq1kIK;#!+W;eJiR37@nU!gZJFoU}MB2XJB;ThwsFveC@RyT0JK|}Lj&9Ume*KDglUv|e* z79WE?$5ru5l`5klN@7u}`117Sq9sVWS4+msH>Qrm*JNhFw|#01g54`1HA-I&x3>8$ z85`MN{w)f4A;CLL-XTUer^%7y3%HQ9FfOaGa#R^yNE(^ivg)byLrY~8F_bKp(ix9c zSbs+;<9RM53+O7b)_jf#?*Ap{O9guDHi;bJk+(Az33=1>?5UuIyS6TBpPg;l{2rY!SE?MYr)maNoY8q=wu7`v}CzQ7>b+v z4Q^FiS|U9AXR%ro^uVv1IvlrE47{lYn#@}wOat(yEV!XV`K+F+fj2=mg5T;43W%m? zXkv28(_>&-bD=EZY$01^vjX>cqY9G?XT3o=9fvqiT=2ZBm*EgM0Ub(IGxnO zBsQFH$Vt{Ut<*EszqV^|=tyx(<(Dyy(QR|Ni>NfcSoDhhX#pqsadGlGJJ4~oyAkMq z^hM=?kT{fb6A;)@*u$^y6XH1Xw$US%F~ZEp9hxyNwGIN?gyjB~p#33zBTaQL>Zqk~ z`}!>kd)xp1$h_^GZr=dSc|kHGyKJ8UtFfA(14Z4V#qVl&D&Q42YgJak#|H=8Lprjx zwHc1S$-397clen&`WyDf>r&3@(hqe9FE9Q_;Y(NhXUZ^K&sw6eL&tmGU0@vlTw^)z z@#%?fcbu@osc?2>nN;uEtIUJGE_Q`qLa(6|{Gz`Qj*O!Nq;{jftXeDfXy!WKnjKya zPK9rSnwkubEaB){)r`0gy;dH**Hfe*8iOI9%@*&o7|A`wczCGuc7xpP?z@ftX1#Y9 z>{@Nc`j7F?64HJXepBAB!s1%P_{^j~)m48c9ZQb0F5KSjSZL>CZvM>pzzg4Jg`s}6 zdCg-hw+ojb!BAE>%t!yNKOOf%YjdB`{G`h9cwLCwT}Y?@vYSkUFU zwKW_F>Hhdj+DJun+A+UFk`M1!FcRqTqYE6%q~_qPyKc9jJg>R4*ghR!xvA){Z|}<8 z3O-m=GL~L^?bdhjY-8iQB~7|KQ7=@sba?fBUCWCHzMivBOO1(prR8wPcScjHSgOOR zx$Do_bxVtp@M1q7b)E-xAt&*x?uKIdUw=Be55Ia}E^Sh3_X&A2)OIE=S3M*=Rn_qp^V>m4n0Tk0-8D;xJN(DaW4}7GdASon$UPV zIjQls?$(|vi0ovWA|KbkOY@tVkou?9n!uSS@s$g*Y#A_d+%xUOa)CSu-pR8 zk4br##-TWr>zkvpk9M}<{_!8tH9O7d&ar+?l5_}+ibNo!^A zL2Pa<{j5v!`^DO2(kHGnStW3Z6q&-|J>2=G*srTx`s8VE=cM+8bZ?pD$u@9T2i$dJ zd%1-SmySP#;FM`Id`!%RL7yMRHN?jy%$U`+9M9DZ)j&^y?WGygTRJXm`zst`sJ|&l zo4Ek?1T{-Sg$63C**gDAvyipNZF?}Tns+HU;O?i474N%!ceQ!;7Gz_aXEThVFs3<7 zhDmglTBmsOW@(JV3ogD8nx$oKj*%R~Rv zgoZYLZxvJxUTo-Icn#L+{wG6*kr;C!eyE~RAEj}NBja={`O*qr-!9+ex+(2K{?@*O zDs(CzCc#oVYjjwap=<#_(zs^=bBjjdq1OWc{O%sFRl{u?`VJ8`t081(__kId-#Zj= zKU$?r%$l2Beox{wTFkYvjlvToku6?-WoK@+D*8SoNGtl{X|JC0BGs4U-|@l0&!O0A zPY0o<2WnIKw#!2ThWg?-!JWmUjST|j7ei(iUVgrRZM?U)tu@Pquu2E3=OZP7qa7dZ zL33OhTPp1;$jQzPtgXIhdH#gJ?$3s9-|cK#$0f)+;!z*z4q-)%&}9AA?(5ctI~-G& z&t(UtnZ3#lTt1&C;y~QaM@b%q^nV=%v}Qqji>JA{x&v&1HLo@mj(l-dXS9y$?{0mS zX)^CLmJXjv;Nqea$KV8vXE;?#rB@qopI>Zd<&)FcTfvvcD@SALL7=0}_F8Er>?jiC zy&qg45O6+eoL^$up3#*XxO=YZ+&(@^l(Sj%yGe|Y?j~vKSeGF7_K@wVjCsaWD=+Pw zT6JOcV+letxa2D`SH zWi@=Mk0q6=R~tErk-1PSw!~ODLr+}49P7${5#qIsqr3j5O@eCWgD-K zhl%u3n|`-mx#;*CPp9C4;(1Ad_w|-0n^<*!?g;NYwz|ICce$z05evIF&ocHu^-M-7 zMA=`Lw<~!3m$YMD&x5QU!A|TQO7rr)Gt}=btysb6EPpp*wRz8*qTI#;4J}vcjhdd2 zqy08w!~lGOOP6Ky_+Pu{1$}NBijNx&HMzGwCwZuIQ?25R#YurPjX2MI5^u*Gsi~87 z2JCy35UAalY>mDQ=jI(k4(C|%#(MuwJO2H7(3reDybt!Y*jwK&TI@UL<9e{gGiAVL z#g5r&YnH?~-Pq%^;MKQEj75CLkZjRz3vwT8YjtWIk%qRHE8>T6m!32pU19d|yK|{( z)!^0Efa3>++u`4`?e;fXY@`-+suwJx@N5HK(cm>mJ6>4|T0M9Do|BZlDPi?wjqylq zj%urkooj7pe~Wy$|EYXur?0tXO2@?oJiN%q<=*F)4;J-DNz)#+7gv-?y@DDWPJD7q zUSyVL(cR|b8k{@yM{?D5jhgA5LjkLg>tBw!f7^2on^vAKapjA86X&s-M_U%m3+?S0 zlG`fQ=FF%Xax?ko=8DG)d!pav;o|P=m#d0GZtzjO?1;H# z(|a42jCHm;H3dtb#>XX3 z;QoW#=kkor*tB{PLeY%8A}Bvn{8hG~DELixXwaDKc|lHr-`l#YlRo{ep3;8*UCNpz zJ&!C#zrR|NsS&u}&h^rT=|>cEmH}T!*oC<#XR}VXdIlaGs!pi9k-FTtx4J33?{UW; z`q0Cmb7+02!S=b^)1K`=w?LIuGW+|w870VL*`F^S8(jMoTa@QHvrlH!@Z0aRx-+Z2 z6O(r>FkL^sR`E;RKS4@C|4cFzKe?Xh(($7YgZx232%Z~;u>rQ=Ww0-4aR(I?o z_JMQp*auCB(Fe9o`CYkf_L@rXL>uYa!naA6LQI#J`Nkk?DzgiMhItPIhyU?8(tdJB zh`~+RQQ?};rLe8b@5ri6jJ25wp*Nn77(cnAp*K~)QI8395J;0w`waG%6$E|eEh(Pd z1%ZXSNIFJmw`IyNo)KwnKUy?CuuZgR?vNYCY`vFfSGapeYM_&QSL@c@v*^?c*b63g z8uK}ehQ_)eMUq*Jd5>jsleP#;ZVTay6@qAorASW zefrx&?PsS2@3dPPm_K_FoeJNzoo_8>do@C$6Ui|*@AeIOa?Jk|Z+5fa9=j!ln*$R0 zV(vGH!jrdWB#tefU%pg7g;?pC-pF&ReDEgo)5)#1@>k#XZCgf<#IoROr?+hm{jQHN zGcneo(06T`edU9#F8)0SGCx(sz-7jNc*O}7ma{?LS7c`SEY`bHX_M3@yJ5wpz{QW2 z#Z(n9yLRv1?!%FB(ExVV^_a-6EmD$e!?D?2)A2pmr~Q4dPe9M>M3;nT{#M2EED0L+ z`RFyptny{_yVc=+musQ5&S$rk#Q@dw%PIK>5gK;$=zYbk3SIi${lc!4!uj1Pp@-i- zklhb@*KyrO=m)!7-PdSk=PQTVUUhQK%Z2kVn-6|AF%RA28(7t4xki{jgHGM}^`^3O z_C|a}H7`HDxOV&ZYbNI7pH1GbfV}^MmkwW;PoY!G`u=Mu<^2 z7>rq)c4=kVHX$S`VONiRQ_OmQ6-|nZgJ}2!jG2N*?oJuT?E_AW8Bxk_wR!1oJqS|4 zFW2EDuU}%H@o(s_2OOmhQ-i9FW=APMgm&8=Dw3Hvz-}8+4jpq39cgkZ+8;3XI%56v z^|g`8!=Pc-LqoL826KwXZ_DJLgOulC3_g>WuD3GS9YGF0I{Hsd#O_d8u9dCNAlRf1 zNq3KbvN|?gb|APnzGw-pK6ND(5u}Wqg8nA+id}_RbUdaPUPwizUJm**bhvSyaR___ zP@_{L+N+Qf7mcR=)FanTLW;?EpL&pzJBuH6J|2HGD~1ENXlrqa$Ai^~-_@zV2Y)@1 zEbC!JEA!|qL)#t|j;><^(c^|VOtwmsO`H5=yMibtrMSE5_ZzR? zhx8g>feX-6sPpXY`o49nW1o*jQO1{lMYGs6;&&U?V(cs$hX3jUN=0HF9{v*#t~y&R z;iK>^5-GPK+MS_&a}>r?VPQ~aVXma}Y@t6CK?-<8dlUQyWs5csT_fhgXHO(o1&6{* zM(~Lg@AYyjpf2E}P~Yi*PvhyvgaQ0(>PvkB%N%TVq@XMvI`uNZ_LH!$0rofvn**>= zMZ#fC0k(;RodU2ZfdyZA5p*>{<`$@4iNwuHVt}j`Vc;&HLT6xD@*3KICHm*%Ki=^s z`tOA+3YJO`z<=j6Eu0YdK-{LCBt`sfG$BGw5}6iDiul{Jgt!1INz={~q7)aC3DF*0 znCwLGIstaAG28|G$4XoyA{_8l9nm9U6`{S1P7DH+X%W3d0sx#nM3CJ8^#f-U+!=8+ zfJQICox#h)T=?VyfrSD9l0|Uk?F6Ka1X31U7}Mbs3k>Huh`@$5IFl=|Ig5M=P&FLX il!y@WfBZMxJ5Fhu`EUSvIOhv)YK`?;{%xK|`2PcsaC$QU diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/test/golden_widget/flutter_logo.string.rtl.png index e65700f87fa6172382fd53a21970ffacf71e87d1..6c8dd292777c2640514e08b937b8d3d764a80b9e 100644 GIT binary patch literal 3490 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 YSB+27^+L(4GaIXiuXg~ihI=^kzdytZE&u=k From 1e3777c2bcd2eff8af5addfa2ba4bd547951f90d Mon Sep 17 00:00:00 2001 From: Aliaksandr Luferau Date: Tue, 21 Jun 2022 19:33:44 +0300 Subject: [PATCH 067/142] Added the flutter_lints to the development dependency for project 'example' (#723) Co-authored-by: aluferau --- example/pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 57954c78..f90020e3 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -11,6 +11,9 @@ dependencies: flutter_svg: path: ../ +dev_dependencies: + flutter_lints: ^2.0.1 + # The following section is specific to Flutter. flutter: uses-material-design: true From 28073a23965a86d4bbe4d96cc549dd40665a4aef Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 21 Jun 2022 10:46:28 -0700 Subject: [PATCH 068/142] Fix 720 (#724) * Fix 720 * use Object.hash --- lib/src/picture_provider.dart | 10 ++++----- lib/src/svg/theme.dart | 2 +- lib/src/vector_drawable.dart | 4 ++-- test/vector_drawable_test.dart | 37 ++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 783161c4..6273a233 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'dart:ui' - show BlendMode, Color, ColorFilter, Locale, Rect, TextDirection, hashValues; + show BlendMode, Color, ColorFilter, Locale, Rect, TextDirection; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -157,7 +157,7 @@ class PictureConfiguration { @override int get hashCode => - hashValues(bundle, locale, viewBox, platform, colorFilter); + Object.hash(bundle, locale, viewBox, platform, colorFilter); @override String toString() { @@ -455,7 +455,7 @@ class PictureKey { } @override - int get hashCode => hashValues(keyData.hashCode, colorFilter, theme); + int get hashCode => Object.hash(keyData.hashCode, colorFilter, theme); @override String toString() => @@ -502,7 +502,7 @@ class AssetBundlePictureKey extends PictureKey { } @override - int get hashCode => hashValues(bundle, name, colorFilter, theme); + int get hashCode => Object.hash(bundle, name, colorFilter, theme); @override String toString() => @@ -582,7 +582,7 @@ class NetworkPictureKeyData { } @override - int get hashCode => hashValues(url, headers); + int get hashCode => Object.hash(url, headers); } /// Fetches the given URL from the network, associating it with the given scale. diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart index f5cba20e..b33a5f9e 100644 --- a/lib/src/svg/theme.dart +++ b/lib/src/svg/theme.dart @@ -41,7 +41,7 @@ class SvgTheme { } @override - int get hashCode => hashValues(currentColor, fontSize, xHeight); + int get hashCode => Object.hash(currentColor, fontSize, xHeight); @override String toString() { diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 8be73efc..0fdadbdd 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1288,12 +1288,12 @@ class DrawableShape implements DrawableStyleable { if (style.mask != null) { canvas.saveLayer(null, Paint()); } - if (style.fill?.color != null) { + if (style.fill?.style != null) { assert(style.fill!.style == PaintingStyle.fill); canvas.drawPath(path, style.fill!.toFlutterPaint()); } - if (style.stroke?.color != null) { + if (style.stroke?.style != null) { assert(style.stroke!.style == PaintingStyle.stroke); if (style.dashArray != null && !identical(style.dashArray, DrawableStyle.emptyDashArray)) { diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index c7efeb5b..03a85409 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg/src/svg/parser_state.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -115,4 +116,40 @@ void main() { recorder.endRecording(); }); + + test('draws even if color is null', () async { + final DrawableShape shape = DrawableShape( + 'test', + Path()..addRect(const Rect.fromLTRB(0, 0, 50, 50)), + const DrawableStyle( + fill: DrawablePaint(PaintingStyle.fill), + stroke: DrawablePaint(PaintingStyle.stroke), + ), + ); + + final PathRecordingCanvas canvas = PathRecordingCanvas(); + shape.draw(canvas, Rect.largest); + + expect(canvas.paths.length, 2); + expect(canvas.paints.length, 2); + expect(canvas.paints.first.style, PaintingStyle.fill); + expect(canvas.paints.first.color, colorBlack); + expect(canvas.paints.last.style, PaintingStyle.stroke); + expect(canvas.paints.last.color, colorBlack); + }); +} + +class PathRecordingCanvas implements Canvas { + final List paths = []; + final List paints = []; + + @override + dynamic noSuchMethod(Invocation invocation) { + if (invocation.memberName == #drawPath) { + paths.add(invocation.positionalArguments.first as Path); + paints.add(invocation.positionalArguments.last as Paint); + return; + } + return super.noSuchMethod(invocation); + } } From 48178f4841a67a61367bf8d8cf3a02ccfca4209b Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 28 Jun 2022 09:59:12 -0700 Subject: [PATCH 069/142] version bumps --- CHANGELOG.md | 6 ++++++ pubspec.yaml | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37e4bc32..203bdebd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGES +## 1.1.1 + +- Fix a bug introduced in 1.1.0 related to fill/stroke inheritence. +- Explicit dev_dependency on flutter_lints +- Avoid deprecated API from Flutter. + ## 1.1.0 - Respect stroke* properties when a paint definition is used for a stroke. diff --git a/pubspec.yaml b/pubspec.yaml index e6df26dd..595a99ea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 1.1.0 +version: 1.1.1 dependencies: flutter: @@ -19,7 +19,7 @@ dev_dependencies: test: ^1.21.1 environment: - sdk: '>=2.17.0-0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' flutter: ">=2.11.0-0.1.pre" ## For developing features that require new functionality in engine: From 177667a1c0f03b6e5b5256ef8db62b84dc63eafb Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 28 Jun 2022 11:16:47 -0700 Subject: [PATCH 070/142] fix whitespace, update simple example to be simpler --- example/lib/simple.dart | 30 ++++++++++++++++++++++++++++-- lib/src/svg/parser_state.dart | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/example/lib/simple.dart b/example/lib/simple.dart index b51da3e6..815f8d34 100644 --- a/example/lib/simple.dart +++ b/example/lib/simple.dart @@ -1,12 +1,38 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +const String svgString = ''' + + + + + + + + + + + + + + + + + + + + +'''; + void main() { runApp(MaterialApp( home: Scaffold( body: Center( - child: SvgPicture.asset('assets/flutter_logo.svg', - width: 500, height: 500), + child: SvgPicture.string( + svgString, + width: 500, + height: 500, + ), ), ), )); diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 3f6b4381..c5d1da31 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -792,7 +792,7 @@ class SvgParserState { this.theme, this._key, this._warningsAsErrors, - ) + ) // ignore: unnecessary_null_comparison : assert(events != null), _eventIterator = events.iterator; From 5c3c99ab46da39ec40d756b10b69f495a698a59c Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 1 Jul 2022 20:10:06 -0700 Subject: [PATCH 071/142] Update currentColor handling. (#730) * Update currentColor handling. Default currentColor to black, mirroring Chrome's behavior. Update callsites to parseColor so that they account for currentColor. Avoid setting a default currentColor on the root element when parsing. Avoid painting when Paint.color == null. --- CHANGELOG.md | 6 ++++++ lib/avd.dart | 2 +- lib/src/svg/parser_state.dart | 36 +++++++++++++++++---------------- lib/src/svg/theme.dart | 4 ++-- lib/src/utilities/_http_io.dart | 2 +- lib/src/vector_drawable.dart | 4 ++-- lib/svg.dart | 6 +++--- pubspec.yaml | 2 +- test/colors_svg_test.dart | 6 ++++-- test/vector_drawable_test.dart | 11 +++------- 10 files changed, 42 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 203bdebd..4b8e15b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGES +## 1.1.1+1 + +- Fix regression introduced in 1.1.1 +- Update fix for fill/stroke inheritence when currentColor is specified in the + SVG but not in the theme. + ## 1.1.1 - Fix a bug introduced in 1.1.0 related to fill/stroke inheritence. diff --git a/lib/avd.dart b/lib/avd.dart index bfd3f67a..2567ef7d 100644 --- a/lib/avd.dart +++ b/lib/avd.dart @@ -1,5 +1,5 @@ import 'dart:convert'; -import 'dart:typed_data'; +import 'dart:typed_data'; // ignore: unnecessary_import import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index c5d1da31..975b726b 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -87,11 +87,10 @@ class _Elements { final String? id = parserState.attribute('id', def: ''); - final Color? color = - parserState.parseColor(parserState.attribute('color', def: null)) ?? - // Fallback to the currentColor from theme if no color is defined - // on the root SVG element. - parserState.theme.currentColor; + final Color? color = parserState.parseColor( + parserState.attribute('color', def: null), + currentColor: parserState.theme.currentColor, + ); // TODO(dnfield): Support nested SVG elements. https://github.com/dnfield/flutter_svg/issues/132 if (parserState._root != null) { @@ -144,9 +143,10 @@ class _Elements { return null; } final DrawableParent parent = parserState.currentGroup!; - final Color? color = - parserState.parseColor(parserState.attribute('color', def: null)) ?? - parent.color; + final Color? color = parserState.parseColor( + parserState.attribute('color', def: null), + currentColor: parent.color ?? parserState.theme.currentColor) ?? + parent.color; final DrawableGroup group = DrawableGroup( parserState.attribute('id', def: ''), @@ -164,9 +164,10 @@ class _Elements { static Future? symbol( SvgParserState parserState, bool warningsAsErrors) { final DrawableParent parent = parserState.currentGroup!; - final Color? color = - parserState.parseColor(parserState.attribute('color', def: null)) ?? - parent.color; + final Color? color = parserState.parseColor( + parserState.attribute('color', def: null), + currentColor: parent.color ?? parserState.theme.currentColor) ?? + parent.color; final DrawableGroup group = DrawableGroup( parserState.attribute('id', def: ''), @@ -240,7 +241,8 @@ class _Elements { def: '1', )!; final Color stopColor = parserState.parseColor( - getAttribute(parserState.attributes, 'stop-color')) ?? + getAttribute(parserState.attributes, 'stop-color'), + currentColor: parent.color ?? parserState.theme.currentColor) ?? parent.color ?? colorBlack; colors.add(stopColor.withOpacity(parseDouble(rawOpacity)!)); @@ -1339,7 +1341,7 @@ class SvgParserState { ); strokeColor = definitionPaint.color; } else { - strokeColor = parseColor(rawStroke); + strokeColor = parseColor(rawStroke, currentColor: currentColor); } final DrawablePaint paint = DrawablePaint( @@ -1433,8 +1435,7 @@ class SvgParserState { Color? defaultFillColor, Color? currentColor, ) { - final Color? color = parseColor(rawFill) ?? - currentColor ?? + final Color? color = parseColor(rawFill, currentColor: currentColor) ?? parentFillColor ?? defaultFillColor; @@ -1634,6 +1635,7 @@ class SvgParserState { ), decorationColor: parseColor( getAttribute(attributes, 'text-decoration-color', def: null), + currentColor: currentColor, ), decorationStyle: parseTextDecorationStyle( getAttribute(attributes, 'text-decoration-style', def: null), @@ -1644,7 +1646,7 @@ class SvgParserState { } /// Converts a SVG Color String (either a # prefixed color string or a named color) to a [Color]. - Color? parseColor(String? colorString) { + Color? parseColor(String? colorString, {Color? currentColor}) { if (colorString == null || colorString.isEmpty) { return null; } @@ -1655,7 +1657,7 @@ class SvgParserState { if (colorString.toLowerCase() == 'currentcolor') { _compatibilityTester.usesCurrentColor = true; - return null; + return currentColor ?? theme.currentColor; } // handle hex colors e.g. #fff or #ffffff. This supports #RRGGBBAA diff --git a/lib/src/svg/theme.dart b/lib/src/svg/theme.dart index b33a5f9e..607f814e 100644 --- a/lib/src/svg/theme.dart +++ b/lib/src/svg/theme.dart @@ -10,14 +10,14 @@ class SvgTheme { /// /// Defaults the [fontSize] to 14. const SvgTheme({ - this.currentColor, + this.currentColor = const Color(0xFF000000), this.fontSize = 14, double? xHeight, }) : xHeight = xHeight ?? fontSize / 2; /// The default color applied to SVG elements that inherit the color property. /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword - final Color? currentColor; + final Color currentColor; /// The font size used when calculating em units of SVG elements. /// See: https://www.w3.org/TR/SVG11/coords.html#Units diff --git a/lib/src/utilities/_http_io.dart b/lib/src/utilities/_http_io.dart index fbc06cd2..458a2072 100644 --- a/lib/src/utilities/_http_io.dart +++ b/lib/src/utilities/_http_io.dart @@ -1,5 +1,5 @@ import 'dart:io'; -import 'dart:typed_data'; +import 'dart:typed_data'; // ignore: unnecessary_import import 'package:flutter/foundation.dart'; diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 0fdadbdd..8be73efc 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1288,12 +1288,12 @@ class DrawableShape implements DrawableStyleable { if (style.mask != null) { canvas.saveLayer(null, Paint()); } - if (style.fill?.style != null) { + if (style.fill?.color != null) { assert(style.fill!.style == PaintingStyle.fill); canvas.drawPath(path, style.fill!.toFlutterPaint()); } - if (style.stroke?.style != null) { + if (style.stroke?.color != null) { assert(style.stroke!.style == PaintingStyle.stroke); if (style.dashArray != null && !identical(style.dashArray, DrawableStyle.emptyDashArray)) { diff --git a/lib/svg.dart b/lib/svg.dart index cb607dba..d48ae395 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:typed_data'; +import 'dart:typed_data'; // ignore: unnecessary_import import 'dart:ui' show Picture; import 'package:flutter/foundation.dart'; @@ -780,8 +780,8 @@ class _SvgPictureState extends State { final SvgTheme? defaultSvgTheme = DefaultSvgTheme.of(context)?.theme; final TextStyle defaultTextStyle = DefaultTextStyle.of(context).style; - final Color? currentColor = - widget.theme?.currentColor ?? defaultSvgTheme?.currentColor; + final Color currentColor = + widget.theme?.currentColor ?? defaultSvgTheme?.currentColor ?? const Color(0xFF000000); final double fontSize = widget.theme?.fontSize ?? defaultSvgTheme?.fontSize ?? diff --git a/pubspec.yaml b/pubspec.yaml index 595a99ea..4c5ce623 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 1.1.1 +version: 1.1.1+1 dependencies: flutter: diff --git a/test/colors_svg_test.dart b/test/colors_svg_test.dart index 4f93c26c..65aff311 100644 --- a/test/colors_svg_test.dart +++ b/test/colors_svg_test.dart @@ -44,8 +44,10 @@ void main() { const Color(0xFF6F2173)); expect(testSvgParserState.parseColor('hsla(0,0%,100%, 0.0)'), const Color(0x00FFFFFF)); - expect(testSvgParserState.parseColor('currentColor'), null); - expect(testSvgParserState.parseColor('currentcolor'), null); + expect(testSvgParserState.parseColor('currentColor'), + testSvgParserState.theme.currentColor); + expect(testSvgParserState.parseColor('currentcolor'), + testSvgParserState.theme.currentColor); expect( () => testSvgParserState.parseColor('invalid name'), throwsStateError); }); diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart index 03a85409..72a6adf2 100644 --- a/test/vector_drawable_test.dart +++ b/test/vector_drawable_test.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/parser_state.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -117,7 +116,7 @@ void main() { recorder.endRecording(); }); - test('draws even if color is null', () async { + test('Does not draw if color is null', () async { final DrawableShape shape = DrawableShape( 'test', Path()..addRect(const Rect.fromLTRB(0, 0, 50, 50)), @@ -130,12 +129,8 @@ void main() { final PathRecordingCanvas canvas = PathRecordingCanvas(); shape.draw(canvas, Rect.largest); - expect(canvas.paths.length, 2); - expect(canvas.paints.length, 2); - expect(canvas.paints.first.style, PaintingStyle.fill); - expect(canvas.paints.first.color, colorBlack); - expect(canvas.paints.last.style, PaintingStyle.stroke); - expect(canvas.paints.last.color, colorBlack); + expect(canvas.paths.length, 0); + expect(canvas.paints.length, 0); }); } From 6bbe047a1cd330db70f33a1b5e9bd6f58ae89da6 Mon Sep 17 00:00:00 2001 From: matthewyan Date: Mon, 4 Jul 2022 15:36:36 +0800 Subject: [PATCH 072/142] format code (#554) --- example/lib/main.dart | 18 ++++++++++-------- lib/src/vector_drawable.dart | 13 +++++++------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 6a1cc8c0..e8cf2283 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -113,8 +113,9 @@ class _MyHomePageState extends State<_MyHomePage> { SvgPicture.network( uriName, placeholderBuilder: (BuildContext context) => Container( - padding: const EdgeInsets.all(30.0), - child: const CircularProgressIndicator()), + padding: const EdgeInsets.all(30.0), + child: const CircularProgressIndicator(), + ), ), ); } @@ -137,12 +138,13 @@ class _MyHomePageState extends State<_MyHomePage> { ), body: Column(children: [ Slider( - min: 5.0, - max: MediaQuery.of(context).size.width - 10.0, - value: _dimension, - onChanged: (double val) { - setState(() => _dimension = val); - }), + min: 5.0, + max: MediaQuery.of(context).size.width - 10.0, + value: _dimension, + onChanged: (double val) { + setState(() => _dimension = val); + }, + ), Expanded( child: GridView.extent( shrinkWrap: true, diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 8be73efc..1ff13d6a 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1298,12 +1298,13 @@ class DrawableShape implements DrawableStyleable { if (style.dashArray != null && !identical(style.dashArray, DrawableStyle.emptyDashArray)) { canvas.drawPath( - dashPath( - path, - dashArray: style.dashArray!, - dashOffset: style.dashOffset, - ), - style.stroke!.toFlutterPaint()); + dashPath( + path, + dashArray: style.dashArray!, + dashOffset: style.dashOffset, + ), + style.stroke!.toFlutterPaint(), + ); } else { canvas.drawPath(path, style.stroke!.toFlutterPaint()); } From 1413a9a3dd9e023c3376f0f1ca8899d428659bcd Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 6 Jul 2022 14:38:44 -0700 Subject: [PATCH 073/142] missing unused import --- lib/src/picture_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index 6273a233..bf46e315 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:typed_data'; +import 'dart:typed_data'; // ignore: unnecessary_import import 'dart:ui' show BlendMode, Color, ColorFilter, Locale, Rect, TextDirection; From 509f86b5f176b120ce63e67627d65911c922c93e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 3 Aug 2022 17:41:49 -0700 Subject: [PATCH 074/142] bump path_parsing --- CHANGELOG.md | 4 ++++ pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8e15b2..f47c0700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 1.1.2 + +- Update path parsing/drawing dependencies to fix arc parsing bug. + ## 1.1.1+1 - Fix regression introduced in 1.1.1 diff --git a/pubspec.yaml b/pubspec.yaml index 4c5ce623..9e8b5d41 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,13 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 1.1.1+1 +version: 1.1.2 dependencies: flutter: sdk: flutter meta: ^1.7.0 - path_drawing: ^1.0.0 + path_drawing: ^1.0.1 vector_math: ^2.1.2 xml: ^6.0.1 From f9fc52cffec7c9fb64074b13ea9496a89da0b369 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 3 Aug 2022 17:58:24 -0700 Subject: [PATCH 075/142] update goldens --- golden/svg_currentcolor.png | Bin 4234 -> 4192 bytes test/golden_widget/columns_and_rows.png | Bin 25764 -> 23184 bytes test/golden_widget/flutter_logo.asset.png | Bin 10330 -> 10130 bytes test/golden_widget/flutter_logo.memory.png | Bin 10330 -> 10130 bytes test/golden_widget/flutter_logo.network.png | Bin 10330 -> 10130 bytes ...go.string.color_filter.blendmode_color.png | Bin 9168 -> 9032 bytes .../flutter_logo.string.color_filter.png | Bin 7618 -> 7518 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3404 -> 3411 bytes test/golden_widget/flutter_logo.string.png | Bin 10330 -> 10130 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3490 -> 3496 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/golden/svg_currentcolor.png b/golden/svg_currentcolor.png index 47d93874deebc2b7ef8c7aec566ac79354514efd..5411bae167ed586b3c9762a7dccef763ffb8b9e5 100644 GIT binary patch literal 4192 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 diff --git a/test/golden_widget/columns_and_rows.png b/test/golden_widget/columns_and_rows.png index d4baaddf86b636c9e296dce515657b0d4ff1654e..34053145e281c2d6bf83eb6acc305fd547a1555f 100644 GIT binary patch literal 23184 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
t*%$@hS!C00^JF1i0X6&Mk*F7tCFiuKoiJG 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�u9vbX{zc#lGCFlb@L2Onwq@UnkgLn5^=% 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 literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.memory.png b/test/golden_widget/flutter_logo.memory.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.network.png b/test/golden_widget/flutter_logo.network.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 zcmcI~i$7HB_y3+TW$R`SLZ#+HqLU(&#F(aGCf@iXCgCbEXVYQxc# z?#6!;ymklI%i8<9tZfV5T8mmxy2i#>_e_;jI*$&YplVQWY&-Xtec{4M^-8+uHtc9q zw*AgoJO9cb4NU#O670AA519u1K%NLWyXkjs5>=;rs-g3?Of=)~o`4+{{SHT*1|8f} z{j0uMylB_XHL0z==fBJT^S$Qa{rVJO^?&&%e%&8TL0;Zi9@4hEIR05@^FZ)i!;Ce> zgCz%={9KzaQ1)R=WP`mBJ1bB3qtZkRqm+3nj1627;yhQj%C;rK4#kk0Y!13c=uD?j zxu&IxtSIG$+FT?nT+Y;ytvW$Nkup_=Scj99h)~kKTOuT-iZfN2h#Coc2te5cD3gom z#o>J@`tt$lR|3fle|wU6YYa%%7>@J-rBF*g5S{WR2*u+iq3UKQLJZvqd@XwrfgG4h zu?5kL5O488)FVX)5H(5B8bp*79YqM1N*J3%XCh)<+^v#lVE0$j*i7I>!tTXYV+qyG z5CI+?=f#`@?Ifz#d@h2n!ow!&g8q+*2&B&hXLk@#FK2`50fM*pIf#n}L7-r*2zj{z zkE?THzJBv`VQV0*rRG7$2GA;m`?m{9tiI5Gp1kyqj z6a7UZO{Y+u>4aN1Ap#4@xE`jV+(`tJECAIbLF)i?5((-Hpw0y71^`tfKoMM%oDE$N zph<+&B7M-r2u(u)XmWA$h&rq%g$4KsBKE+9LV$`qK@1~;B2vZQlHyGKEr~T#3Eq;T zDgKsN2O?AaEh$ciw;u@F9;>M|rXk^0eKD$r=J# z1p*a?mA)6|1q3-9oY_kDFQK6&CkZZ0GYU1IB%q0as7v(HguNtxGAUvpvPn@BL@FsV zDOA4+Q4hpv7YppF5vqET2&JAJ@e{zCn7POl9j@pz z8LcZc)Y+8OyogY4&L`%^2~{Td92r6?m6k=$tqpL3Y$PW^G>WCqCc@%8i$dK%>@>(i z0Bs>buK}nD0h$G%(In_O0F5U=!T&@75h`1KB`lqs4J8x`RgG9~$VC=c#3md;1Ssb5 zmFOgbz1+~7Fk0e5rD-lA@ISbL2pc`@Ss(ZyY7wHxd=N?hJ$8afM$N+jL>j5Ek4i(G z2nzKOARe&}kY&1DQ9fxb7sc@N17JP&fGWwh93pUq_bOFp36C7c4@%evl;n+4X%|UeYO6(vBB^>6cwf`uz#f9A!5-EUaj{g98&5+w zkRIxtN5Y~>d}~#vvp$J*luBC&ePD;%uu8<;Nh0~8SXLzAmNT59=g7F;)aIsBNw?3@ zP&E=X3qZq3(2W49M}i)w(x#B0aDb?hv%w<`G)bo&=uBtQ5zz|JBxggu2nh=#Czcye zR3ailwN{HtxTKiE6_p^Qcnic566=;N=uU{MKzBl11G=QRmn-7>5wwvxDol(VtrB$_ zN+Z`ILf-F^KVj?0e+^ICQ-+`Do>9BZ?lg_?m zQ>d22l1IFgkg$0qfdC*NB>~LY-1OBXm$@p;m*jCKidDioCSa9mXu$;R0xE6G1gtiN zYCytv0IWI*O9QgTBv~d6^&(ZVNF>aGv=vTgO2SC8Tq^B<6YYsen88GUU9QIjmnTYC zJxQPhK{2-kqE`tQ#0XLpff!GUB_I;8@nx4d!{3+O*z;!0vH1<9_L<|ucjL{8pEopX zAk{=XH$Upkcro7F)6=7voLDs&Y+z_DbT-julDo3@=?J-IT$y70`_YmEjbFbE7opw> zNZ5RwecYl_#Z^(tH zxmiT!OWLMPMX{U2ye5s6s8Ge^X1_U7Ib4O|H;uxp{!e$aFyso64GYv;BGOA0VS+mo z`{{)BO(vg5s0bk5#TYPeJ*L}m_0F%uo?;9VFJBk%_$Xwq6VDV1PX^EQAI~fbZzdnT z{Ih)$g=Y%SKilVnJA4#URIso=@imPQ+3H5|9n{Vo8h~&qN`& ztDvD9Ratu-g`~Uq@~DGnhab=OFckEslS?PuD}Y7Ip+EiW=d**TM2-G5>c=xInG!Af zQ2jH>^rg%n-h`_%CGqGiCHDsfy9%bqa z3p8qbdRCSxK8aM;gP^2FN*sPP9H~kfx+gpOJyvFBSwHx#gd?L&S~_X!@m=Px)j>y5 z7GLx40AslGXbR`GN$0o6J2daBGMpiYqeM!kgJtznsTjTD)S@s2qKDG&PL{=&8Oe-T zyp9OD=&2Hh^2N8fLa#eKp+hA0P=}KanOHcTC507oi_TDGix)>KXMrOkemS*8`}Fh{ zPoDUtu8cC1&cqVYBsS-6J)5J;NB3b2JV^_SlIU=jKF9E$DW!@VY~c{uD1eZ&J#hnv zKue!ORdC)Z25ws-<6t%}12ve(+zm5XU_iYU4CE`xD3He)GB@&}>(vPPMT~W8wGg4w zPG0XoVg3YY;s!QGD#O9e^^ioL!DR8)%D7u*v2p~mbj_@*Y`)N|ny{))XOzH2P+=1v zw@Sq$@@ujjiN%4Ztl-R>Ql_fUZ$U81)2Bt_;EbN^}&$y^-mh<&0a<^n;K{ zmPRS#8RHanHV?*g5>8J4v>bV@%T4!tY=gT`klTqdN^Bq}Nxy*muZENJsxMW{hYQEK z4iloQ6uQoWq1kIK;#!+W;eJiR37@nU!gZJFoU}MB2XJB;ThwsFveC@RyT0JK|}Lj&9Ume*KDglUv|e* z79WE?$5ru5l`5klN@7u}`117Sq9sVWS4+msH>Qrm*JNhFw|#01g54`1HA-I&x3>8$ z85`MN{w)f4A;CLL-XTUer^%7y3%HQ9FfOaGa#R^yNE(^ivg)byLrY~8F_bKp(ix9c zSbs+;<9RM53+O7b)_jf#?*Ap{O9guDHi;bJk+(Az33=1>?5UuIyS6TBpPg;l{2rY!SE?MYr)maNoY8q=wu7`v}CzQ7>b+v z4Q^FiS|U9AXR%ro^uVv1IvlrE47{lYn#@}wOat(yEV!XV`K+F+fj2=mg5T;43W%m? zXkv28(_>&-bD=EZY$01^vjX>cqY9G?XT3o=9fvqiT=2ZBm*EgM0Ub(IGxnO zBsQFH$Vt{Ut<*EszqV^|=tyx(<(Dyy(QR|Ni>NfcSoDhhX#pqsadGlGJJ4~oyAkMq z^hM=?kT{fb6A;)@*u$^y6XH1Xw$US%F~ZEp9hxyNwGIN?gyjB~p#33zBTaQL>Zqk~ z`}!>kd)xp1$h_^GZr=dSc|kHGyKJ8UtFfA(14Z4V#qVl&D&Q42YgJak#|H=8Lprjx zwHc1S$-397clen&`WyDf>r&3@(hqe9FE9Q_;Y(NhXUZ^K&sw6eL&tmGU0@vlTw^)z z@#%?fcbu@osc?2>nN;uEtIUJGE_Q`qLa(6|{Gz`Qj*O!Nq;{jftXeDfXy!WKnjKya zPK9rSnwkubEaB){)r`0gy;dH**Hfe*8iOI9%@*&o7|A`wczCGuc7xpP?z@ftX1#Y9 z>{@Nc`j7F?64HJXepBAB!s1%P_{^j~)m48c9ZQb0F5KSjSZL>CZvM>pzzg4Jg`s}6 zdCg-hw+ojb!BAE>%t!yNKOOf%YjdB`{G`h9cwLCwT}Y?@vYSkUFU zwKW_F>Hhdj+DJun+A+UFk`M1!FcRqTqYE6%q~_qPyKc9jJg>R4*ghR!xvA){Z|}<8 z3O-m=GL~L^?bdhjY-8iQB~7|KQ7=@sba?fBUCWCHzMivBOO1(prR8wPcScjHSgOOR zx$Do_bxVtp@M1q7b)E-xAt&*x?uKIdUw=Be55Ia}E^Sh3_X&A2)OIE=S3M*=Rn_qp^V>m4n0Tk0-8D;xJN(DaW4}7GdASon$UPV zIjQls?$(|vi0ovWA|KbkOY@tVkou?9n!uSS@s$g*Y#A_d+%xUOa)CSu-pR8 zk4br##-TWr>zkvpk9M}<{_!8tH9O7d&ar+?l5_}+ibNo!^A zL2Pa<{j5v!`^DO2(kHGnStW3Z6q&-|J>2=G*srTx`s8VE=cM+8bZ?pD$u@9T2i$dJ zd%1-SmySP#;FM`Id`!%RL7yMRHN?jy%$U`+9M9DZ)j&^y?WGygTRJXm`zst`sJ|&l zo4Ek?1T{-Sg$63C**gDAvyipNZF?}Tns+HU;O?i474N%!ceQ!;7Gz_aXEThVFs3<7 zhDmglTBmsOW@(JV3ogD8nx$oKj*%R~Rv zgoZYLZxvJxUTo-Icn#L+{wG6*kr;C!eyE~RAEj}NBja={`O*qr-!9+ex+(2K{?@*O zDs(CzCc#oVYjjwap=<#_(zs^=bBjjdq1OWc{O%sFRl{u?`VJ8`t081(__kId-#Zj= zKU$?r%$l2Beox{wTFkYvjlvToku6?-WoK@+D*8SoNGtl{X|JC0BGs4U-|@l0&!O0A zPY0o<2WnIKw#!2ThWg?-!JWmUjST|j7ei(iUVgrRZM?U)tu@Pquu2E3=OZP7qa7dZ zL33OhTPp1;$jQzPtgXIhdH#gJ?$3s9-|cK#$0f)+;!z*z4q-)%&}9AA?(5ctI~-G& z&t(UtnZ3#lTt1&C;y~QaM@b%q^nV=%v}Qqji>JA{x&v&1HLo@mj(l-dXS9y$?{0mS zX)^CLmJXjv;Nqea$KV8vXE;?#rB@qopI>Zd<&)FcTfvvcD@SALL7=0}_F8Er>?jiC zy&qg45O6+eoL^$up3#*XxO=YZ+&(@^l(Sj%yGe|Y?j~vKSeGF7_K@wVjCsaWD=+Pw zT6JOcV+letxa2D`SH zWi@=Mk0q6=R~tErk-1PSw!~ODLr+}49P7${5#qIsqr3j5O@eCWgD-K zhl%u3n|`-mx#;*CPp9C4;(1Ad_w|-0n^<*!?g;NYwz|ICce$z05evIF&ocHu^-M-7 zMA=`Lw<~!3m$YMD&x5QU!A|TQO7rr)Gt}=btysb6EPpp*wRz8*qTI#;4J}vcjhdd2 zqy08w!~lGOOP6Ky_+Pu{1$}NBijNx&HMzGwCwZuIQ?25R#YurPjX2MI5^u*Gsi~87 z2JCy35UAalY>mDQ=jI(k4(C|%#(MuwJO2H7(3reDybt!Y*jwK&TI@UL<9e{gGiAVL z#g5r&YnH?~-Pq%^;MKQEj75CLkZjRz3vwT8YjtWIk%qRHE8>T6m!32pU19d|yK|{( z)!^0Efa3>++u`4`?e;fXY@`-+suwJx@N5HK(cm>mJ6>4|T0M9Do|BZlDPi?wjqylq zj%urkooj7pe~Wy$|EYXur?0tXO2@?oJiN%q<=*F)4;J-DNz)#+7gv-?y@DDWPJD7q zUSyVL(cR|b8k{@yM{?D5jhgA5LjkLg>tBw!f7^2on^vAKapjA86X&s-M_U%m3+?S0 zlG`fQ=FF%Xax?ko=8DG)d!pav;o|P=m#d0GZtzjO?1;H# z(|a42jCHm;H3dtb#>XX3 z;QoW#=kkor*tB{PLeY%8A}Bvn{8hG~DELixXwaDKc|lHr-`l#YlRo{ep3;8*UCNpz zJ&!C#zrR|NsS&u}&h^rT=|>cEmH}T!*oC<#XR}VXdIlaGs!pi9k-FTtx4J33?{UW; z`q0Cmb7+02!S=b^)1K`=w?LIuGW+|w870VL*`F^S8(jMoTa@QHvrlH!@Z0aRx-+Z2 z6O(r>FkL^sR`E;RKS4@C|4cFzKe?Xh(($7YgZx232%Z~;u>rQ=Ww0-4aR(I?o z_JMQp*auCB(Fe9o`CYkf_L@rXL>uYa!naA6LQI#J`Nkk?DzgiMhItPIhyU?8(tdJB zh`~+RQQ?};rLe8b@5ri6jJ25wp*Nn77(cnAp*K~)QI8395J;0w`waG%6$E|eEh(Pd z1%ZXSNIFJmw`IyNo)KwnKUy?CuuZgR?vNYCY`vFfSGapeYM_&QSL@c@v*^?c*b63g z8uK}ehQ_)eMUq*Jd5>jsleP#;ZVTay6@qAorASW zefrx&?PsS2@3dPPm_K_FoeJNzoo_8>do@C$6Ui|*@AeIOa?Jk|Z+5fa9=j!ln*$R0 zV(vGH!jrdWB#tefU%pg7g;?pC-pF&ReDEgo)5)#1@>k#XZCgf<#IoROr?+hm{jQHN zGcneo(06T`edU9#F8)0SGCx(sz-7jNc*O}7ma{?LS7c`SEY`bHX_M3@yJ5wpz{QW2 z#Z(n9yLRv1?!%FB(ExVV^_a-6EmD$e!?D?2)A2pmr~Q4dPe9M>M3;nT{#M2EED0L+ z`RFyptny{_yVc=+musQ5&S$rk#Q@dw%PIK>5gK;$=zYbk3SIi${lc!4!uj1Pp@-i- zklhb@*KyrO=m)!7-PdSk=PQTVUUhQK%Z2kVn-6|AF%RA28(7t4xki{jgHGM}^`^3O z_C|a}H7`HDxOV&ZYbNI7pH1GbfV}^MmkwW;PoY!G`u=Mu<^2 z7>rq)c4=kVHX$S`VONiRQ_OmQ6-|nZgJ}2!jG2N*?oJuT?E_AW8Bxk_wR!1oJqS|4 zFW2EDuU}%H@o(s_2OOmhQ-i9FW=APMgm&8=Dw3Hvz-}8+4jpq39cgkZ+8;3XI%56v z^|g`8!=Pc-LqoL826KwXZ_DJLgOulC3_g>WuD3GS9YGF0I{Hsd#O_d8u9dCNAlRf1 zNq3KbvN|?gb|APnzGw-pK6ND(5u}Wqg8nA+id}_RbUdaPUPwizUJm**bhvSyaR___ zP@_{L+N+Qf7mcR=)FanTLW;?EpL&pzJBuH6J|2HGD~1ENXlrqa$Ai^~-_@zV2Y)@1 zEbC!JEA!|qL)#t|j;><^(c^|VOtwmsO`H5=yMibtrMSE5_ZzR? zhx8g>feX-6sPpXY`o49nW1o*jQO1{lMYGs6;&&U?V(cs$hX3jUN=0HF9{v*#t~y&R z;iK>^5-GPK+MS_&a}>r?VPQ~aVXma}Y@t6CK?-<8dlUQyWs5csT_fhgXHO(o1&6{* zM(~Lg@AYyjpf2E}P~Yi*PvhyvgaQ0(>PvkB%N%TVq@XMvI`uNZ_LH!$0rofvn**>= zMZ#fC0k(;RodU2ZfdyZA5p*>{<`$@4iNwuHVt}j`Vc;&HLT6xD@*3KICHm*%Ki=^s z`tOA+3YJO`z<=j6Eu0YdK-{LCBt`sfG$BGw5}6iDiul{Jgt!1INz={~q7)aC3DF*0 znCwLGIstaAG28|G$4XoyA{_8l9nm9U6`{S1P7DH+X%W3d0sx#nM3CJ8^#f-U+!=8+ zfJQICox#h)T=?VyfrSD9l0|Uk?F6Ka1X31U7}Mbs3k>Huh`@$5IFl=|Ig5M=P&FLX il!y@WfBZMxJ5Fhu`EUSvIOhv)YK`?;{%xK|`2PcsaC$QU literal 10330 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 OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png b/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png index 6b12ded3f96226de0bef22a1502715fdd3b1c757..d46b6ded9b7b4cbe558dcf475ae18bbc7c50b096 100644 GIT binary patch literal 9032 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 Ju1IB({|EC_!h-++ literal 9168 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 literal 7618 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 diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/test/golden_widget/flutter_logo.string.ltr.png index e4402865634cfd5469cab823e5056404bd347fb8..7e70b9565dee51aef6a52f03b7b7119a82c15361 100644 GIT binary patch literal 3411 zcmeH{`CC(G7RTQNlnfY2SY)e)B!hs`qAgN^hTMrM2?!b^iZW~p2!bpM%9cuoLMJ3s zmQg?uQYcGNS`btE6n%nehfw#z6h$#e4NK69F@z9`s6FYwQQlwji~Cw0;`> zLzVK$W6i_pzU9-IG!U|KRvh@NJJ9~!^QNS-mOb7$g>#1YwftY>n`6FQyRbpN^o8g_ z;4=nV#8QW?z@3?bqF2_%FXeemW8d4wgw1K#e~{HLQvTC01AQ*~lenfB4r8U7L6 z7CRgsdjV-loW(x)S=3A||&Ek^r z=0cUo8u`*ObiHH|H97!jDz!%WZWwYD1E2u-7l0)b5G|rO5`aDcs{zbN05}4W0{F}X zN*9r7Kxmmc0V6`yfhvS+chcb$+ihLZHd-KZ%z-2uA;~@{ zlY$8l&mMr<1fZu)p#Zi4_|gQ1oeX$1-({)OO*vE>Rp~va?0fF#YsbD{xQyW)3nA?A zMG~bT_R7-p6!Gt0x6AL}Qv2y}JR-~_oV!m==ihedxzD(q`=Y##Q!{$qoFB{bahayel?6Jg(F16SS9HHM`%UCcpy+vZhf=QnY4{PgRem3ob4 z)b^LF>1mG^jQ_s2sOO05Efl%n12H0@ILdE9eL-oJ!5FK1VB>jSbnm(}h3R7$eJ<5V zzx~>FspAKKJ}RS*Q-&$c)%PKJmoJ43K9(ReklS;VJiFzlA&Hw-#;| z&Ac%WUa8bIwp2}_exmT*X#ZCU9UmCp-1uogH&jKt^NpA!3?hTU@fCzTy^7qxEiBN z*3tvP4MeGgBy5AFR7H4`Poz8<>;(%xlJ>aApS*K}vw45y2ghaGTt;LZ^?qpOTkWd= zQ0N2-t>+sFem$8pD)m3Rw8whfX^FF<>xWMs_Dv7did^=V4;0L%9S=DFEU%h?YiHu{ ziZ)+yMY2_^Kg)@bT?iZ3Z}lSMc})1~^~v=k8J{o`AM!FnwN)U{0R&>z zgk1+x4Fo6)*Un>CK0D8$(bSwzKW-?y!X?Bnt zA%jftT=9c7BWtq3OBppJzl3e3Gvmzuc_`YZrLTBMNLai`S mgdK&aD`&-l6$iip#uDYjYr3_J@>F}1AHg5*Vt2CQiv9o@we9f$ literal 3404 zcmeH|`&&|X9LK+hY%;A7Ej3qyNa}igGA~(E5#m7wGqu(-)6|-)P`fBzf@zY~25Lz% zua&deEZ1Y!R&!b|S47%W63Q%1%P2214ND``xzB0O{)+ki&q@lq9 z^G$3_5JK~LT+T*>=1>tLY$1LGq%<{aKU^@u#sD_D*tTR4Zj1zM-X7eyu+mVpJw$1M=DOs z_ZnF}I7;<8>8YsN!a0$BR!#SNO_H_y-wBEeG<)pF7r67}!6S+7-F$gTOLvi=t)c&v z%6Me#wa>Lbi+b|}G$>?t%{uUZcfhGO_Tlq8nhh>koHx6iTRYd(@vS3AZgC&`i zDp`PdA( z+54hSDZ;20eRIT7kntM_Uo=pFuox!*2LXJ9gCYP_0BZpl09b#AuyPjw+X0AhPzb;g zfHQzpx-V+VhAj~|fGi`tbR=7a5gH2>#z<&JMF})e^--2|iZN{CQFWuZ83I$F6Lz)l>{0dN4s0dN5DoCRCN zdK420F|r{>t_4O2-3~z$?OAAfAV`lJ5m|GkB&399&s*!T#x)jHv6ozjUz5yzCjU+<{zYOSrA-b}@EnUK@% zD@opARW+lX_oZEPe9g6Gy6^PJ$vEs13OwtqBlDfLS34YdJ}HKK!=^`D=fpTcXu9H# zrNWps2(^znz4Vvs5j6nE!IUzFB{{P#MFM0O5KhuDGw=(8R+_cucF@mOV!G_}I znp4rT0^SjD)&!glOgK*@gArncIn^Da#op6zsrRCgna3oxlclSjbXe$T5RqWWmYwOd z7dog9tjX`R5C%Z1^K|Hg%VpJZ+BTuW>k*q2Slsc zZT>dOlKRNs0L-g@XdxE=1Rh(Cw-c6AvX zgB5S|1NC8e30t9rRfQ4h$xoJoHRTiF(t1Yf4;j>lpjc}6Flwe(b=w$0*OgI*iHk)V z`f)4Qzs9PVJ!@uej%H5jYNirG$ZwE!G)R=ob+D1udwD+bjB4|VRZ5iH!pHtPmGwdX6Vt4K=k>JY_v$GN_jin8Adu87K(vC&TzzPvX)RVP=?4EY4rdXok1uxWI PNw^z4zhKTqc1+ek!J+%< diff --git a/test/golden_widget/flutter_logo.string.png b/test/golden_widget/flutter_logo.string.png index 7b88eeff0280f9170d14a57356ba73fe922ededb..fc9ffa27529c1c7d62c7faecff5822448e6a262e 100644 GIT binary patch literal 10130 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 literal 10330 zcmcIq`#)6O_dhcxj#AE`C@~k8=qgHb8DpMtDY-nP>r?4Tl2ppA7#W$0iczWDLP+X1fi}&WkHh|c-R;IQT$wNc}Q;M>~?sd`SDh)M&VC@dPE`!6IsExT74k7 zv)(>-`(S9bWPEvj`pk-xmrw0pe=CD_Y?7|-x`v0dm7ZTNJ3d|g+`f!|bQfysn>m}i zm^gFw%a8>8Va`{i+W& zr_9dDUK^Sok02DL3PJG}-cF!$*HCFfj0m9&Labg+v~PfHwZ-Atpj-!2e;Xp2HIP_S z((5~*s*{1)K)A*$34>^`^*Kqnsq1i&4=4dHUkF}m^C?tkl7TFss*p*1qRd1lDd8cc zp;TI$0Wr2JKvsoMgm?+XggjzEoo9nTLQpxb%|&D#iT1zcF(HLWL7Eqp=AK4$rI&(G z)R=^+9VmSX<>yFHl3~ZQ!JmiwBQ1bWA(n^G2*eZuO6UioCMizAwFE(-J+39iNw}7d z(-uww2AZU(gKJ4J9b8L_(?R>0px|yzr7_7AtcyS>D3Jo>9YjMVVHF@-WC~)Vpq)qo zVh96nMWlf13I1dXyuuMmTRbth?(l_(za0_H27odpmJ+f6601QHmq%w_$I+JTj4XUGxJrRN|EOBdcz^EveWWh53)X15;5YD$KCXQdFiKzePM!xcu8(HO&UsS_^{D7Og3m?)#j2R#baM?`?- z?W5AXE|9n|W$uu;ZD6~B#PtW<>m;rz;Qk;3!)RzMS)H+?2;~-;4j!G!ok0vJ*Mv%2 zmqegq@aB6*PJa<3@hnmAkc%*OI;80VFij*0OaYP1LA5%F#Yqu0D36hfe=9MN z2yJefFTtzWT^`dT85lryoJ=NBAq5Gik|9`QOlLJ>d8Da9I~k&iwUEmq@taUgPe@R4 z)}~Nph*uz@VlONfPWUS`4V=joNNA`684Fj5X+W+C#1@of*u^T~PrNb^16yG+LM#s? z*-FT*BB7H15OT$&_!n2mb(#=)Larhy&IfH3={DaEY$rrOaGDTTfGsIr16wi$$UG$` zMy8;677c~v4ci1HPnSZakgy(1E|W}wa22$ZDTqCVgfod0Aco3Jj7$M{3JvvNMXca7 z9V*R~*l{4$YzkF_oI73#Ncc38fR7LfpGr>O4;Y22PTJ;KQEA3xQFnhvLwzQ2Oq=fkx2L|lI>wSGd7$UFfNx$dpFS@ zhlDSk@Ym(KTN49@JdwxNO_(a8*gAM|!~Tcs1ma;*6oWW1qE#RgWKUIW87=(9SmDrH znOjOxmdiT0ZRF>ZMZ>)n*zO<;B$9Y3m$i&;c{F(Q%FeOi_sv4(3ibYX19GE7o>$9- z#glNJVxNZb=OGMx{U}B1&W5Y^?paD3$6D^LeW)pa$68ptoU|#ClSC^1!{mNezzN$L zH$@yMk^6=*$tqq3Wk4)Vn@^=(AwsK*RBWO%;$Uvk@%(71ORUVBA`Im**v6*)=dHw4 zA!_i1w+~fxiI@hYHkg5Gh&P4yy=ZlWNV&FdgHyy7tNVpbTbOdGx zksq%lBwU{@vj6@30V<#$A8l3oO;?{vt7P(^K29VIPqWY1)pL5~)Fsd*7{fyGk`71;U|M~0D&}&=~ z)VzuC?BLl>1m$kx*$bYnL<;};N5b<8QQv?5S7H4!dBJuQ^tm2XnjxKK!Tz0XQwnuv zR4nWv$#G?H7tOd`?EREmkt6mGW zh%55v{_a0j9{YgNZ(04GKEsZ}V%ezJslN#r(7<7p2zG=M`F2LJHX*t*{CB{ttO89W zt}Vy1_w9Ex#ja32x3kM?X2a~T910m6w^>=?&tl;*qr#ci}O%M33tgYy>v92qT zQ#gx+BmA<-&_QPNHlC<@x`gtFE|-bYZ_y;DDuyJBS-cNRKsSfWgt!pUeIs-#5{eGS z#7?65FgBhNX*|Zd;~?PbL-p6@RWdoZ)^j+zd~`RR;S9%3tEgCg;8BZr5t}3xzCkf` zl}KB1>h&;=R%R{WMuF#Ae-UK5=Xt3J-MXnsW~B}{P44(fOmfO$4DaCDN&)vJ4ejIq zNr$j^F2Xx_rNnTCLAG$=&!vN;-+QFPRDg!O~B2-Nr2pj9zHPHP#$VR1*;-4-4Z$9L?k@rdjQ@;Qwg|Q36LG| z(nbmiZjW$o-;@}|L-3;J-@rYUmjO4sgWw4pPMJ3+P+0CII5(GR63SmNCyGTecvxY0 zrwXZ3WQG>kUC6V6d4DAg&&W}G0dfN07hEKWG~!*rc2@We#nkdJJpA@BAQ$@uV-)v5 zw|`~gx|xo+ZcLd`>`g;e($3)BD&T3d3yV^84}i_d&DVsEpf?_==xzbJTc-$}C1D4; zP|($Q($?TqTsPxgJSdTi6(ixi?a_D?`8Z>EZ*Vt*=Q$l7Udte^ z5*9}|0zCFy$MGY@2iccHnq<6=A(S;Iz%5#8B1YR|q{v4tt}yP+X*>Wr<2;>}G>0P$ zl*c}Q;E}2mN~|OZeE@cfFOHC^S4yl-h!U<%KF1kp5tV$64(}saRnVEm37$ApEzUa~ zUJq^sSbvfAy)bYz-Au7N%tdg`N${1;>!CA>Ti}oh>oY$pwm(WSO?~4gMZ~?W#CF~x zlZ@eA`b$6QyNUfR;>RGoAUNEdD6!4qm%$}L^#TgDT1j$~&i2rUQx+VSy~3p*^ys%R z38e&%_J+!g3m8jPiNT!>Cpaz1Ykm5DU1)-{qamHaij1AvBohfY2OdlgkIvH9kx=+L zTsX#ZcyrBpC34t#gt9I|ie9gVj(d7Z&@)KILIq`JDXBCyEmm>YFpn-RF6uPojX8e_wj@#wQV`=M}A}0Bm z;NSufVwZ!LvnHGwtpu@u zUcv3)&dlIIQ^bsGu+U}nAc?XLg6d1tae~{GnfT3|vHMFfM2Lgp6WIl7V8_&fV_~c` zP3Alw7{+7F;d2KtVxK*!lpa}~u@@@1*R(*} z8)L1i-JD0GAGds(Io>!v_OH`uWzs`UWv(`KDLQZY^Q#7(_g+_W)33El@p7EYZOcQg z&m@C<6h8(i97QkMACpMTf`axm4u!Xu=6DWXFe_+OW#Q)q13k8AVRA`neVz1b$Lfr^ zZWUu@L5f`hHxXhoX^Pra)y)q>a~=70t9|{++bv^t zZC3U@7q{B1EJaJF{(+#})$O6U4`v@Ni%cB|lRR(5t= z$FnL|w~VW{B-NE>k@Ac}SM%QFk^AGBOHt1;h5mC-uCAiLw`vf0l|zi>|JYK&xb zs&Cx#u>Yz3edAFh#2>EdtTEPCUo}S2@>z`*^Elb*WhUlB9X}TY8ul*MV7Ph5aNfD~ zYHfT!z=wGU6YLLBUQCO-AW*O>=A(nFk>;6%SpVU*M!kzO=4y<5>)a(5HlHVSfr|{t zyxWpr&98Hc#_QfYEh@;4Ik(B7d+6$w0YUkqg2ZTXbE}hFcdj)`+;!NB@=iXJN~7PG z26b`FdXMB=FxsD5Flvk#epO+H$~|2xMaU$K$vwqKPng7r3wAs&on+goS!%m-$ASXW zLu2`2xh`5fAzT1*Z}L&qq3prO7&GgycvTct* z-=Z-RbBD8B@oc)wInS^ieI4B?bcRvpCWi$@*;k%6m)py>rdWQm%V|x@>1RY?Y29Eu zlW#XOarDCLc}2h4mjza?3k=v_WxMq54{s&L?#`hH9*?pPict#e;E?1$L<$>k7a0YA zYYgjYkak^w@iCJ8S+$@b(W0}XZJ9&pp}vuX=H{;lts_2bsFmU8$$9vx zci&7pwGTcKtP4lmkHIuvo7tS6eP!WH^E%(nZZP4l>ESyAAqTEb=P9vnc6M9L4js%0 zI~ZoJ%Gi+-xYV+DUq@uUlrU<85t+reTXjYnpE`6^_q;;og+Mn4PqP^DM~5siVNwPr ziF~{Hzd{sk8%LLoHy|OxPNiQ(b6CLbGG7JQpzRB3YRZiAc%2t>_>0W&!0cGuXQ~?2G32>*dn-j=x)EKD+2p>vf|o@yqMHz3XbVbv+l(T($F1cWH@p z^R`PXDnh1#6Wk0}8`4j|AM1*Eecy82NwX`)vw7Rtot$S_LW3_S@9V4@Z9dj~yQx`vCnxI{$J01DbBS5=>+ulI3?pR?Bfy>n`wkY{ z!{S$gqD|xQzm~x!n)NB00^Qd7y~@2Za40$d%gCcLwKaldRgKIdClQha`ygXG(KXMo z!6$7Si-r`Pp4$fa-!JuO*`_pWP6)?ySu(sSqfds^Bxcpcd^?niQjB3EHy>A#&ls6MTlE|<<7Q_2?FFy4Si*O}*03y0pD@I*a=Y@@~s7dp;1 z?%%l$sA10z)?8k5srhY@t%&?!pv2no=~JQQaLbL+k;<;Njp+k*fcNv+sUOqv`)Q|5!$?Vyx~BQ|E~ow zO;Xyg#&ivsaQf$FB%Hai5c{^M|5)~&)O&CC^xDl@wzg*TZ4Dp696lPG1OS)cP5>B% z1w9H0GUl{66_`H$BJjSqZMeJhwNt^zz4zWc$WIJR+_m#Y{^@DKJ;o4l^04F|Ip^3n zY>&Nyu)h8+LuSpA`uC1ig7Sa+7Z;9rcYV)1x23}T&+nGctOsfWKRUdBj|pOWJ;^Rtm~f0?(fN;QP3)=qKZH=aSsq z%wz46C64cF4m~uCY>S`669&LQ6(60&3TX~WzcJcV)fKa)XtX6^QF(=+eEt(tPJc(= zt(=-y*Nl5r$0NMWqHCi2(jK1GTqDjb^k2Gk(xbb_F?Wq;VP|P=`4_Fr8l(+vyHcea z3kuTTdp4zKdv^DkBn-tLk4c!?dYjS8*lX{)JEOkCCfK=1-{RVyjKYo$^w*1Ff#l5X zp01pB?5Gk!#B!+QSYWB2WU<++#Y2MOtM$)~lkeaCnw53$&E`-oi))R^ns4{6D5#Bo z+vjg|(2-4Bcf_D29+C(hWDdP#kE>T$6VtTDM#su5!d_G&wC zJWkNuQ@GUPL$GP|_tF}x0G-~V^l?~7@HMhpD>OQ`SsK43@NDJAz`H-nZ8aU-G7E=o zKGq$YTVK@UGiz_XlExH_Rcr_|wW@CcukwW02;T*?G~Wr>!Rfejzkl7w{2u?{pJj?y zBm*1Y92#v)tXi*0r_T32&?-Y!X*zO#Ph<8CPS1YtH@%z0-^^Pp1#dTI<$ho7wo$(} zAp86ExNK9m{x#XzXG#?rN6)c;y3=lYpK zMyXiiNZBgU>Qc&^)&2Xt%H`}nK0Y-qmveSnuDQM`mCh(8JRU3fnuyA65gPKf7bESb)66Lz$%%!_Xgl&UPeO#%F(b%4~VPW4~eolaI#1$8d$e z)akc^1()OAytH7J8fh*|ap;e}pV2XFq+h$%rMYwGPq2G6&zwuyZ&UVAvQLc}@Gl~i+`K<@da^zh`0%l{*h5(+lsEKGx}>c?))CbSh>+@WGJq~*75mKsh$`O z?>Uemr&nf5zvV4>`#$DUbIa|lhx>c=4ChLoET&VpOS~1GC7h0V%UnWx>+Xz}n7M@Zzif8BULprq9?r5i zhLIy1w0R3ph&%r2ztjKWQ_Z{PZoB@wa}>oj77siB668&$Q=he-Wu&>QT9+M^{JDG6 zijB(}&fVMd*rHZ!VHT2*CWUV4PH(S$nzy$0sl*^WEMbp0e& zHf-9_S7r!eL^sr6^!I1FhBhZaPP(Km`z24VL}F^X-BkF7I!)`V``}pE(C~?(zSh8? z?EAIvQ#p^B&VuUc&_(kFM7T{{H0Zk5^h3kw%9_iJ6mwlpTOu01Rk8;uKG_aOZa$0W zZt_SA@%^W{d-QG6wA>$I`Pm&oQHqx^mVrXUbi|~FXn1pX_*GVRgAON>C*qFR!iifL zZ!_MkbtB`LTv$eK$6oO8atW?_Qadc(Q~2}Eby&97UKGe6s=-aRmcKmuz4|lavKi3f zR$bcgD+Lr$efaCFV&fjoC6;U4YEzFZUNTUoj>0bE!Q1*90_nh$(NTuI!*F9$gdQKo zFGk#1K}9`ZK2?m?Go0K;9VAvNY}#;X!6d{!A3s7S=F~El=@*9d#7on54T!j5@f3=? zK2bruGlwK|-5TxSb7DjS)~47!3%U07-IPW3AB#2=CA$Pa{(iGqlz>IzKQA$)^WY%# zH~bXfnzaZ!g@!+XU!v?%X7ROoO!&0Moxv7G^3f9b6-b#4(Y_Aa*GFM&B^CykXiPKG zAGVQqctm>_{-YQzUZkCfdml`%E8$RS@TpYzj_|6U3cqi$iNpc&4uUqCjvKhcg(rL( z#@&kHha8BpBLP+cxc($A+`J*CByIuNULbMd>QGoo;!Xp$D8cqC+)bf>5CD(B^diw2 zToqE7vkA6vkqEysBKjJJ_N|0}9@Idt7vX;mPFq+C%3{;0Iq<83zQct03UbtUloWC8 zaYBUqQKT=16mjioLOhRa;R^~NsN!NGA-3Woi3>Nkhysb534zIyY}Z3HRzyBN!_P3> zefcOo3WFSeM{5TKrE16vQ0UFNlX*Do`?>vBy{6GJ3cZ^x`Zf0Ara#Wjw OceTRWk)O+RKm31$8ZSuz diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/test/golden_widget/flutter_logo.string.rtl.png index 6c8dd292777c2640514e08b937b8d3d764a80b9e..e65700f87fa6172382fd53a21970ffacf71e87d1 100644 GIT binary patch literal 3496 zcmeHJ>0gsq7QP8lf+K}Qlk#KBhR7fcrF2}{03ikvs6Zz2(@H8TP=taYxUdf?#F~I? zqcXJ!LBWx+EQ-SfRFFaCIvW2_Tx+FuV=^~N1I5M$)O?WZfEKG`!7^P5(NHS@%;xRLB0iy+|^$5?@N z1O1uxE9onVR8Zl->v`=@zewL4GE{MPfK(l0A;`^ctRPEM?_fxAUH?F9WDSDWHJM7bj0C>A~5l?;~>91QuI+I zfyj9X&ezKkt`d>(EoJ6(L}74|1p%CJ!O5~c2RZsk(UU+BWMTp)2>d``27*=)cy9ue ztz6{rH-zIzkx5_@HqgZ@dU{t2vU3{=r;($sf9xBv*V&)*WvIjH^7Ak zf+RVBW`~J6dVy)E;6#jR=o}PT40k9e5RnaufnuOOWnplKIWiqp<$%T=G+KMGxqxto zcY{qy<@_Q-Rma-Dd9;ZYRvhB^bzJ0;*FB!i9`RQ-iVW>Ve(m(m;|tH9&OB)Dn5}MN z_u1UFzdjZkapRU!;*9P%6kjfVw3tpr(82u`6ehK$O>Awl`6 zUEF;+`9-l=_Qo_OPg8HHIYvT7IAfup`^{fhwA@ZeA8cteN8*`F@c-dbZm7cVu zIcxI@!uIAa+r;7u%)yvpjNT=z1dti*n;`2N-mA5whA4%;Mgmyg%NB;NI0_ zh9)nc3Sb^+{lrv8Q#N*#0B`SL)utVM*BzK@O>@p6>9pEFeUh;R2NUBsEuZpyXL#wk zykh)e{_;!&DK(iIcR49)DUBpX8*L$zBecb5-L%H~h zIelO=s4@7s>_8SVK=-TPe`dD*ti4a56HotTsVVQ54FV@AvChm%!fMIqg+ zP=-}raJo~?<L#l~$=kMv`lQJky_(pQiRabJt)OzVq9Ou=tTIH^r{`vx+8V zA%ty7faI81av$1~Y0k;viKWtW4=$Poc&6%=o-6YydX+KS29%>5cku`n+rAt+pO-eH z_0!2Z%5Cef6gDKR^jr^YUTND~G6}iuV*vqTqtcw3O8L~;WcS#SHdk7knM$BNRTZ3W zS5xZQIMQr+yU)34xHX5B9xt!7gcbX_P%~ee{ zCMuFsSLeIfF@b65CXBaGG^J`!P~LuO7<@9?;QB7S-!hd+{kE6{1vB+N7P&KGFk@`| zImYWJ9{`-ImFHj6RZ*4N&hO&blv#x#^iAg&(^8Qga}i_hzdi?!KlT|O#vO1E{m)ib zU!A*;V&Us^?3FVO2{Wx44095DA_cv}VVCZ0C)am&w;T2zl53T;jCYTp4lZ*ck_kj2 zH|6CQsaH3BY&qvI{)fxbMDgJC2o;TBRVk}9L_WMd`6OdiUtLSNwT{yWbW~AnXoc!4 zKkyIff1w~Pj1Sq~0||1mAvPeoH$2o{(8wU5xk_e+MDW^?VJZbB0FW9`*~W=w4}_*J z(W;w@MqI5(ar%^P-9w7ryym5nkhe(a4h~4YD~?1YQ0%|?KVPDA2#40zS_RfB0DsQ> YSB+27^+L(4GaIXiuXg~ihI=^kzdytZE&u=k literal 3490 zcmeHH`CF4$7QP7xX{-$&AR?fUunPi?;#kWPGYPAe41-9l3brT=5*4vw5t6T%N}^&& z#9>XrO3``70+KO?5lCw(%!;JJYAn)z}hiFuVjVYO51eg??1$7ohXy{ zwye2xdWP{OzdSY&mFf|`UHNEq zP+It{{!>1Qi;)e>m~0B-I5QD7K#aJt0N@1R2tWt`Yyesb0Gv>F0pI|DApy{tD1-%o zApmRuij|1uvKAw^9(IDAATg@uePn_wOz9{w04Qw)1(I_4l%Oz}Xakd=fcvv1KrsRe z3n+RB-T+Q|!vM%40D=lmdT9Xs3_zNh9a`$S< zf+9ilodS`5Gk}ODkchfSA(gE$q@ec>EHu8AL~gweI|B|()aVH@4HOf!mjOFQpwa}-jHJ;do{fVxl|Rnr-UxM1me`iG|O?&&xa7|>Gqbg;Fr zZ(<}YM;Sk(i5BU;nH$Ki^4T-gx6P7wvo=5O)DUq21#m;^gDY{55VOrIc`YXmP z*_u|_ye%pA;IUZw(4QAwKk1%2V#6PkgTVRUE$J8*`1D-v|9YmRhs<30Q`QQuN$rAF zpgl)8G#htAG_3x4P_SOR-2%NQu8b|d9xO)Y5-7YSR#TDp=o4fONmGNw*Z;_Vey?NN zcMz3@8d8`$q`49kTl6gvbbT0O_yGq;=KDDI>i|0=VK+WI3XeUrob1c+t9m)ul(~W zaYP6kM|lx4Mr_V({A93LLctwGmMD&;k7*)?Q~x z-!G9lK_BiXnrzC9zW@BvFHBz9_fr_%cWD=rxK_6t>$^J}4^6xqMr6ZLLG;M@XZefz zX-QpEgZ5!wMe~Qg|9m&7LDg#s0}HeH2c8LZ;~HT`lI~J*+UrBE6*7Ns0YkPCZM6k2 z2ft`}+eK?p)oY*r+N6w`=V#DNwSPgCV{w}9Y>OQ*_K z)QY~YarQ$|=io?OrNvY=K`FwCsP|HH-e#6Z$%pQV!qSqXabX$gxF-mW{-d+=?JE%J zHX0d7+-C8WS5453d7*`Y+-MRc?<=n!=wFO+2%Ye$rdl0r#;H_(a|c=$-_;AS3Sfi5*+;^Rmw^2RO`*gzb;1nv}cjs zzkaa!b$;%PMuE{}4aS{cCcV2H)&GI*p5t$^Y5rkQ{pH4V zT@HsEe8@=(V9Rm=X^|834S(d(`xeV=H(U)s2FG6t4)gyo6!jO&WW zXYBa{YiGiQ-bWA7GUvN*4jk+@fakqe{vNmJHS(2K!p+8;}1L#rBU%tb2U>j}+Fx-mWp!?z+yAC`si x;c2P`T6$a&8V$e^LbqUZc`a99xdKpux^YoYx0dT9P&g9x2 Date: Fri, 5 Aug 2022 11:22:57 -0700 Subject: [PATCH 076/142] handle PT values (#747) --- lib/src/svg/parser_state.dart | 23 +++++++++++++++++++---- lib/src/utilities/numbers.dart | 1 + test/xml_svg_test.dart | 5 +++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 975b726b..26c59e56 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -1028,6 +1028,16 @@ class SvgParserState { } } + /// The number of pixels per CSS inch. + static const int kCssPixelsPerInch = 96; + + /// The number of points per CSS inch. + static const int kCssPointsPerInch = 72; + + /// The multiplicand to convert from CSS points to pixels. + static const double kPointsToPixelFactor = + kCssPixelsPerInch / kCssPointsPerInch; + /// Parses a `rawDouble` `String` to a `double` /// taking into account absolute and relative units /// (`px`, `em` or `ex`). @@ -1048,18 +1058,23 @@ class SvgParserState { String? rawDouble, { bool tryParse = false, }) { - double unit = 1.0; + if (rawDouble == null) { + return null; + } + double unit = 1.0; // 1 rem unit is equal to the root font size. // 1 em unit is equal to the current font size. // 1 ex unit is equal to the current x-height. - if (rawDouble?.contains('rem') ?? false) { + if (rawDouble.contains('pt')) { + unit = kPointsToPixelFactor; + } else if (rawDouble.contains('rem')) { _compatibilityTester.usesFontSize = true; unit = theme.fontSize; - } else if (rawDouble?.contains('em') ?? false) { + } else if (rawDouble.contains('em')) { _compatibilityTester.usesFontSize = true; unit = theme.fontSize; - } else if (rawDouble?.contains('ex') ?? false) { + } else if (rawDouble.contains('ex')) { _compatibilityTester.usesFontSize = true; unit = theme.xHeight; } diff --git a/lib/src/utilities/numbers.dart b/lib/src/utilities/numbers.dart index 0e94f226..23e2b406 100644 --- a/lib/src/utilities/numbers.dart +++ b/lib/src/utilities/numbers.dart @@ -15,6 +15,7 @@ double? parseDouble(String? rawDouble, {bool tryParse = false}) { .replaceFirst('em', '') .replaceFirst('ex', '') .replaceFirst('px', '') + .replaceFirst('pt', '') .trim(); if (tryParse) { diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart index 0f891ad4..2d8992cb 100644 --- a/test/xml_svg_test.dart +++ b/test/xml_svg_test.dart @@ -427,4 +427,9 @@ void main() { }); }); }); + + test('Handles pt values', () { + final TestSvgParserState state = TestSvgParserState(); + expect(state.parseDoubleWithUnits('1pt'), 1 + 1 / 3); + }); } From 1a36ae76f1559f913705c0516c90528b9ed6a00d Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 5 Aug 2022 11:23:51 -0700 Subject: [PATCH 077/142] bumps --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f47c0700..00dcddfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 1.1.3 + +- Handle `pt` values. + ## 1.1.2 - Update path parsing/drawing dependencies to fix arc parsing bug. diff --git a/pubspec.yaml b/pubspec.yaml index 9e8b5d41..098e8c70 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 1.1.2 +version: 1.1.3 dependencies: flutter: From 43f7ac70dffcc772302b50400d94e3a3fe66f132 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 17 Aug 2022 11:40:36 -0700 Subject: [PATCH 078/142] Default image width/height correclty (#750) --- CHANGELOG.md | 4 ++++ lib/src/svg/parser_state.dart | 12 +++++------- pubspec.yaml | 2 +- test/svg_parsers_test.dart | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00dcddfa..9b0d6c27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 1.1.4 + +- Handle default image width/height properly. + ## 1.1.3 - Handle `pt` values. diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 26c59e56..79d930f9 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -521,15 +521,13 @@ class _Elements { parserState.attribute('y', def: '0'), )!, ); + final Image image = await resolveImage(href); final Size size = Size( - parserState.parseDoubleWithUnits( - parserState.attribute('width', def: '0'), - )!, - parserState.parseDoubleWithUnits( - parserState.attribute('height', def: '0'), - )!, + parserState.parseDoubleWithUnits(parserState.attribute('width')) ?? + image.width.toDouble(), + parserState.parseDoubleWithUnits(parserState.attribute('height')) ?? + image.height.toDouble(), ); - final Image image = await resolveImage(href); final DrawableParent parent = parserState._parentDrawables.last.drawable!; final DrawableStyle? parentStyle = parent.style; final DrawableRasterImage drawable = DrawableRasterImage( diff --git a/pubspec.yaml b/pubspec.yaml index 098e8c70..aeaa3a40 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. homepage: https://github.com/dnfield/flutter_svg -version: 1.1.3 +version: 1.1.4 dependencies: flutter: diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index 406161d3..9ca75d9f 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -1183,4 +1183,20 @@ BAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" x="1ex" y="0.5ex" width="2ex" height="1.5ex" / expect(circle.style.stroke!.strokeWidth, 5); expect(circle.style.stroke!.strokeMiterLimit, 8); }); + + test('Defaults image height/width when not specified', () async { + // 1x1 PNG image from png-pixel.com. + const String svgStr = ''' + + +'''; + + final SvgParser parser = SvgParser(); + final DrawableRoot root = await parser.parse(svgStr); + + expect(root.children.length, 1); + final DrawableRasterImage image = root.children.first as DrawableRasterImage; + expect(image.size!.width, image.image.width); + expect(image.size!.height, image.image.height); + }); } From fc382c857994a98ab40ef70db0e0578001a27882 Mon Sep 17 00:00:00 2001 From: Joachim Nohl <43643339+nohli@users.noreply.github.com> Date: Tue, 6 Sep 2022 16:36:04 +0200 Subject: [PATCH 079/142] Update pub.dev links (#767) Co-authored-by: Daniel Flores Medina <78251680+Dev-dfm@users.noreply.github.com> Co-authored-by: Daniel Flores Medina <78251680+Dev-dfm@users.noreply.github.com> --- pubspec.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index aeaa3a40..40606f71 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. -homepage: https://github.com/dnfield/flutter_svg +repository: https://github.com/dnfield/flutter_svg +issue_tracker: https://github.com/dnfield/flutter_svg/issues version: 1.1.4 dependencies: From f1fff6b22fc0edb710ec79faef30ec8bc31449fd Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 9 Sep 2022 10:09:46 -0700 Subject: [PATCH 080/142] Colors (#773) * be more permissive about color strings * fix test * update goldens --- CHANGELOG.md | 4 ++++ lib/src/svg/parser_state.dart | 8 ++++++-- lib/svg.dart | 5 +++-- pubspec.yaml | 2 +- test/colors_svg_test.dart | 5 +++-- test/golden_widget/columns_and_rows.png | Bin 23184 -> 25764 bytes test/golden_widget/flutter_logo.asset.png | Bin 10130 -> 10330 bytes test/golden_widget/flutter_logo.memory.png | Bin 10130 -> 10330 bytes test/golden_widget/flutter_logo.network.png | Bin 10130 -> 10330 bytes ...go.string.color_filter.blendmode_color.png | Bin 9032 -> 9168 bytes .../flutter_logo.string.color_filter.png | Bin 7518 -> 7618 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3411 -> 3404 bytes test/golden_widget/flutter_logo.string.png | Bin 10130 -> 10330 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3496 -> 3490 bytes test/svg_parsers_test.dart | 3 ++- 15 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b0d6c27..6f683e14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 1.1.5 + +- More permissive about color strings. + ## 1.1.4 - Handle default image width/height properly. diff --git a/lib/src/svg/parser_state.dart b/lib/src/svg/parser_state.dart index 79d930f9..e9a4a5e6 100644 --- a/lib/src/svg/parser_state.dart +++ b/lib/src/svg/parser_state.dart @@ -792,7 +792,7 @@ class SvgParserState { this.theme, this._key, this._warningsAsErrors, - ) + ) // ignore: unnecessary_null_comparison : assert(events != null), _eventIterator = events.iterator; @@ -1796,7 +1796,11 @@ class SvgParserState { return namedColor; } - throw StateError('Could not parse "$colorString" as a color.'); + // This is an error, but browsers are permissive here, so we can be too. + // See for example https://github.com/dnfield/flutter_svg/issues/764 - a + // user may be working with a network based SVG that uses the string "null" + // which is not part of the specification. + return null; } } diff --git a/lib/svg.dart b/lib/svg.dart index d48ae395..43daf847 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -780,8 +780,9 @@ class _SvgPictureState extends State { final SvgTheme? defaultSvgTheme = DefaultSvgTheme.of(context)?.theme; final TextStyle defaultTextStyle = DefaultTextStyle.of(context).style; - final Color currentColor = - widget.theme?.currentColor ?? defaultSvgTheme?.currentColor ?? const Color(0xFF000000); + final Color currentColor = widget.theme?.currentColor ?? + defaultSvgTheme?.currentColor ?? + const Color(0xFF000000); final double fontSize = widget.theme?.fontSize ?? defaultSvgTheme?.fontSize ?? diff --git a/pubspec.yaml b/pubspec.yaml index 40606f71..4e7ea31e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 1.1.4 +version: 1.1.5 dependencies: flutter: diff --git a/test/colors_svg_test.dart b/test/colors_svg_test.dart index 65aff311..031de49c 100644 --- a/test/colors_svg_test.dart +++ b/test/colors_svg_test.dart @@ -48,7 +48,8 @@ void main() { testSvgParserState.theme.currentColor); expect(testSvgParserState.parseColor('currentcolor'), testSvgParserState.theme.currentColor); - expect( - () => testSvgParserState.parseColor('invalid name'), throwsStateError); + + expect(testSvgParserState.parseColor('invalid name'), null); + expect(testSvgParserState.parseColor('null'), null); }); } diff --git a/test/golden_widget/columns_and_rows.png b/test/golden_widget/columns_and_rows.png index 34053145e281c2d6bf83eb6acc305fd547a1555f..d4baaddf86b636c9e296dce515657b0d4ff1654e 100644 GIT binary patch literal 25764 zcmbq*2UJu`v+f`QDgvS;0U45_0wNj7Dl%jQlqeucB!lEMpeUdSLy#<>WR#pUl0lL% z63CU(Q-TkbH6ud|b}yd&6L~FiEldPaHlk4#`?l z8zN`+w4Z*J5`Rq%dq~nvn{umT{4s9x^9+_`?wt1fer0$W`?p(ZQhFn8x9gT=+3B?H zcw^nR?Q0Mcl_`4L8p=y}bEFBIo&qcM7E6jEPc=Vd3&* z7m}NqVwy2XdWxYc{O~Qoy*BNmjXYYI`%@2r41z!{PX)>W?7R}}G+w;^Il|7~VeP^C zwDSI;Y7uQ#Y4Yh06^ASPruR9g-Y6U6JZ-}1GQ`g(I~2RnQ(^6lg+;5^JA206Af20* zs_j7Cf^gHJBxCDEW@XruJeIW155;#iI;GOSOuZX#uh1tZI0x&k6(@(WSbxP*bMEfx zf1#~yx=nAv=cmXjz4DpWXvL95Mu?-?=^#Ju3|fFD)Q9*Cv)NEbWW zN_D;BI==CDt5~QNYQ^pWTTy?C#LoP%@03yQu9Q;&@sYy_G&0TaVjXXPxx?HwO>MA# zWJ^-{$1U&dzEIeo$1onhp}H-!lAYS5F};GY)&6@hk?~kYrbL@-Lw;*WFad#uHGT8I z1naiF5PO~)8w-g%7FU}z4uvZZAQ@N-VS-7#S7Mr5LeE?=AcgesJdJP`56w!2@cq<$UI1z zlt!hWbiGI-yfQfPvzHKw)0h1w>=yqsOg6a#}b z#(^ELe|xRcLRNa`4r8XM-@z2sG-A^;>i!uRqYv0wYQ5rsVvV0|=ybpD8;89%u6mrM zx30lP$tW+uEE|>xHWUt=w@fQ$^b`e1Hxi71(3o3TikyQLzJ(gMgXP?-9(BbZVR^AZ zFr(niG2i>=`skzd~C#Hp{s#xkvl+E*wok;zS{D3_tX1u03IaSwfq` z_q?nR99WT6+h_+{!KgsT=58Kv;Bo88Vb9^v@1tn#NO)0+E&uCxl0|9g;oiOQI*QZZ z7){Hr3i6MzN@|xy|2kvvLnQ+*=7RyHAIcZK%m=TdiWScrXBx=
t*%$@hS!C00^JF1i0X6&Mk*F7tCFiuKoiJG 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�u9vbX{zc#lGCFlb@L2Onwq@UnkgLn5^=% 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 OceTRWk)O+RKm31$8ZSuz literal 10130 zcmcI~i$7HB_y3+TW$R`SLZ#+HqLU(&#F(aGCf@iXCgCbEXVYQxc# z?#6!;ymklI%i8<9tZfV5T8mmxy2i#>_e_;jI*$&YplVQWY&-Xtec{4M^-8+uHtc9q zw*AgoJO9cb4NU#O670AA519u1K%NLWyXkjs5>=;rs-g3?Of=)~o`4+{{SHT*1|8f} z{j0uMylB_XHL0z==fBJT^S$Qa{rVJO^?&&%e%&8TL0;Zi9@4hEIR05@^FZ)i!;Ce> zgCz%={9KzaQ1)R=WP`mBJ1bB3qtZkRqm+3nj1627;yhQj%C;rK4#kk0Y!13c=uD?j zxu&IxtSIG$+FT?nT+Y;ytvW$Nkup_=Scj99h)~kKTOuT-iZfN2h#Coc2te5cD3gom z#o>J@`tt$lR|3fle|wU6YYa%%7>@J-rBF*g5S{WR2*u+iq3UKQLJZvqd@XwrfgG4h zu?5kL5O488)FVX)5H(5B8bp*79YqM1N*J3%XCh)<+^v#lVE0$j*i7I>!tTXYV+qyG z5CI+?=f#`@?Ifz#d@h2n!ow!&g8q+*2&B&hXLk@#FK2`50fM*pIf#n}L7-r*2zj{z zkE?THzJBv`VQV0*rRG7$2GA;m`?m{9tiI5Gp1kyqj z6a7UZO{Y+u>4aN1Ap#4@xE`jV+(`tJECAIbLF)i?5((-Hpw0y71^`tfKoMM%oDE$N zph<+&B7M-r2u(u)XmWA$h&rq%g$4KsBKE+9LV$`qK@1~;B2vZQlHyGKEr~T#3Eq;T zDgKsN2O?AaEh$ciw;u@F9;>M|rXk^0eKD$r=J# z1p*a?mA)6|1q3-9oY_kDFQK6&CkZZ0GYU1IB%q0as7v(HguNtxGAUvpvPn@BL@FsV zDOA4+Q4hpv7YppF5vqET2&JAJ@e{zCn7POl9j@pz z8LcZc)Y+8OyogY4&L`%^2~{Td92r6?m6k=$tqpL3Y$PW^G>WCqCc@%8i$dK%>@>(i z0Bs>buK}nD0h$G%(In_O0F5U=!T&@75h`1KB`lqs4J8x`RgG9~$VC=c#3md;1Ssb5 zmFOgbz1+~7Fk0e5rD-lA@ISbL2pc`@Ss(ZyY7wHxd=N?hJ$8afM$N+jL>j5Ek4i(G z2nzKOARe&}kY&1DQ9fxb7sc@N17JP&fGWwh93pUq_bOFp36C7c4@%evl;n+4X%|UeYO6(vBB^>6cwf`uz#f9A!5-EUaj{g98&5+w zkRIxtN5Y~>d}~#vvp$J*luBC&ePD;%uu8<;Nh0~8SXLzAmNT59=g7F;)aIsBNw?3@ zP&E=X3qZq3(2W49M}i)w(x#B0aDb?hv%w<`G)bo&=uBtQ5zz|JBxggu2nh=#Czcye zR3ailwN{HtxTKiE6_p^Qcnic566=;N=uU{MKzBl11G=QRmn-7>5wwvxDol(VtrB$_ zN+Z`ILf-F^KVj?0e+^ICQ-+`Do>9BZ?lg_?m zQ>d22l1IFgkg$0qfdC*NB>~LY-1OBXm$@p;m*jCKidDioCSa9mXu$;R0xE6G1gtiN zYCytv0IWI*O9QgTBv~d6^&(ZVNF>aGv=vTgO2SC8Tq^B<6YYsen88GUU9QIjmnTYC zJxQPhK{2-kqE`tQ#0XLpff!GUB_I;8@nx4d!{3+O*z;!0vH1<9_L<|ucjL{8pEopX zAk{=XH$Upkcro7F)6=7voLDs&Y+z_DbT-julDo3@=?J-IT$y70`_YmEjbFbE7opw> zNZ5RwecYl_#Z^(tH zxmiT!OWLMPMX{U2ye5s6s8Ge^X1_U7Ib4O|H;uxp{!e$aFyso64GYv;BGOA0VS+mo z`{{)BO(vg5s0bk5#TYPeJ*L}m_0F%uo?;9VFJBk%_$Xwq6VDV1PX^EQAI~fbZzdnT z{Ih)$g=Y%SKilVnJA4#URIso=@imPQ+3H5|9n{Vo8h~&qN`& ztDvD9Ratu-g`~Uq@~DGnhab=OFckEslS?PuD}Y7Ip+EiW=d**TM2-G5>c=xInG!Af zQ2jH>^rg%n-h`_%CGqGiCHDsfy9%bqa z3p8qbdRCSxK8aM;gP^2FN*sPP9H~kfx+gpOJyvFBSwHx#gd?L&S~_X!@m=Px)j>y5 z7GLx40AslGXbR`GN$0o6J2daBGMpiYqeM!kgJtznsTjTD)S@s2qKDG&PL{=&8Oe-T zyp9OD=&2Hh^2N8fLa#eKp+hA0P=}KanOHcTC507oi_TDGix)>KXMrOkemS*8`}Fh{ zPoDUtu8cC1&cqVYBsS-6J)5J;NB3b2JV^_SlIU=jKF9E$DW!@VY~c{uD1eZ&J#hnv zKue!ORdC)Z25ws-<6t%}12ve(+zm5XU_iYU4CE`xD3He)GB@&}>(vPPMT~W8wGg4w zPG0XoVg3YY;s!QGD#O9e^^ioL!DR8)%D7u*v2p~mbj_@*Y`)N|ny{))XOzH2P+=1v zw@Sq$@@ujjiN%4Ztl-R>Ql_fUZ$U81)2Bt_;EbN^}&$y^-mh<&0a<^n;K{ zmPRS#8RHanHV?*g5>8J4v>bV@%T4!tY=gT`klTqdN^Bq}Nxy*muZENJsxMW{hYQEK z4iloQ6uQoWq1kIK;#!+W;eJiR37@nU!gZJFoU}MB2XJB;ThwsFveC@RyT0JK|}Lj&9Ume*KDglUv|e* z79WE?$5ru5l`5klN@7u}`117Sq9sVWS4+msH>Qrm*JNhFw|#01g54`1HA-I&x3>8$ z85`MN{w)f4A;CLL-XTUer^%7y3%HQ9FfOaGa#R^yNE(^ivg)byLrY~8F_bKp(ix9c zSbs+;<9RM53+O7b)_jf#?*Ap{O9guDHi;bJk+(Az33=1>?5UuIyS6TBpPg;l{2rY!SE?MYr)maNoY8q=wu7`v}CzQ7>b+v z4Q^FiS|U9AXR%ro^uVv1IvlrE47{lYn#@}wOat(yEV!XV`K+F+fj2=mg5T;43W%m? zXkv28(_>&-bD=EZY$01^vjX>cqY9G?XT3o=9fvqiT=2ZBm*EgM0Ub(IGxnO zBsQFH$Vt{Ut<*EszqV^|=tyx(<(Dyy(QR|Ni>NfcSoDhhX#pqsadGlGJJ4~oyAkMq z^hM=?kT{fb6A;)@*u$^y6XH1Xw$US%F~ZEp9hxyNwGIN?gyjB~p#33zBTaQL>Zqk~ z`}!>kd)xp1$h_^GZr=dSc|kHGyKJ8UtFfA(14Z4V#qVl&D&Q42YgJak#|H=8Lprjx zwHc1S$-397clen&`WyDf>r&3@(hqe9FE9Q_;Y(NhXUZ^K&sw6eL&tmGU0@vlTw^)z z@#%?fcbu@osc?2>nN;uEtIUJGE_Q`qLa(6|{Gz`Qj*O!Nq;{jftXeDfXy!WKnjKya zPK9rSnwkubEaB){)r`0gy;dH**Hfe*8iOI9%@*&o7|A`wczCGuc7xpP?z@ftX1#Y9 z>{@Nc`j7F?64HJXepBAB!s1%P_{^j~)m48c9ZQb0F5KSjSZL>CZvM>pzzg4Jg`s}6 zdCg-hw+ojb!BAE>%t!yNKOOf%YjdB`{G`h9cwLCwT}Y?@vYSkUFU zwKW_F>Hhdj+DJun+A+UFk`M1!FcRqTqYE6%q~_qPyKc9jJg>R4*ghR!xvA){Z|}<8 z3O-m=GL~L^?bdhjY-8iQB~7|KQ7=@sba?fBUCWCHzMivBOO1(prR8wPcScjHSgOOR zx$Do_bxVtp@M1q7b)E-xAt&*x?uKIdUw=Be55Ia}E^Sh3_X&A2)OIE=S3M*=Rn_qp^V>m4n0Tk0-8D;xJN(DaW4}7GdASon$UPV zIjQls?$(|vi0ovWA|KbkOY@tVkou?9n!uSS@s$g*Y#A_d+%xUOa)CSu-pR8 zk4br##-TWr>zkvpk9M}<{_!8tH9O7d&ar+?l5_}+ibNo!^A zL2Pa<{j5v!`^DO2(kHGnStW3Z6q&-|J>2=G*srTx`s8VE=cM+8bZ?pD$u@9T2i$dJ zd%1-SmySP#;FM`Id`!%RL7yMRHN?jy%$U`+9M9DZ)j&^y?WGygTRJXm`zst`sJ|&l zo4Ek?1T{-Sg$63C**gDAvyipNZF?}Tns+HU;O?i474N%!ceQ!;7Gz_aXEThVFs3<7 zhDmglTBmsOW@(JV3ogD8nx$oKj*%R~Rv zgoZYLZxvJxUTo-Icn#L+{wG6*kr;C!eyE~RAEj}NBja={`O*qr-!9+ex+(2K{?@*O zDs(CzCc#oVYjjwap=<#_(zs^=bBjjdq1OWc{O%sFRl{u?`VJ8`t081(__kId-#Zj= zKU$?r%$l2Beox{wTFkYvjlvToku6?-WoK@+D*8SoNGtl{X|JC0BGs4U-|@l0&!O0A zPY0o<2WnIKw#!2ThWg?-!JWmUjST|j7ei(iUVgrRZM?U)tu@Pquu2E3=OZP7qa7dZ zL33OhTPp1;$jQzPtgXIhdH#gJ?$3s9-|cK#$0f)+;!z*z4q-)%&}9AA?(5ctI~-G& z&t(UtnZ3#lTt1&C;y~QaM@b%q^nV=%v}Qqji>JA{x&v&1HLo@mj(l-dXS9y$?{0mS zX)^CLmJXjv;Nqea$KV8vXE;?#rB@qopI>Zd<&)FcTfvvcD@SALL7=0}_F8Er>?jiC zy&qg45O6+eoL^$up3#*XxO=YZ+&(@^l(Sj%yGe|Y?j~vKSeGF7_K@wVjCsaWD=+Pw zT6JOcV+letxa2D`SH zWi@=Mk0q6=R~tErk-1PSw!~ODLr+}49P7${5#qIsqr3j5O@eCWgD-K zhl%u3n|`-mx#;*CPp9C4;(1Ad_w|-0n^<*!?g;NYwz|ICce$z05evIF&ocHu^-M-7 zMA=`Lw<~!3m$YMD&x5QU!A|TQO7rr)Gt}=btysb6EPpp*wRz8*qTI#;4J}vcjhdd2 zqy08w!~lGOOP6Ky_+Pu{1$}NBijNx&HMzGwCwZuIQ?25R#YurPjX2MI5^u*Gsi~87 z2JCy35UAalY>mDQ=jI(k4(C|%#(MuwJO2H7(3reDybt!Y*jwK&TI@UL<9e{gGiAVL z#g5r&YnH?~-Pq%^;MKQEj75CLkZjRz3vwT8YjtWIk%qRHE8>T6m!32pU19d|yK|{( z)!^0Efa3>++u`4`?e;fXY@`-+suwJx@N5HK(cm>mJ6>4|T0M9Do|BZlDPi?wjqylq zj%urkooj7pe~Wy$|EYXur?0tXO2@?oJiN%q<=*F)4;J-DNz)#+7gv-?y@DDWPJD7q zUSyVL(cR|b8k{@yM{?D5jhgA5LjkLg>tBw!f7^2on^vAKapjA86X&s-M_U%m3+?S0 zlG`fQ=FF%Xax?ko=8DG)d!pav;o|P=m#d0GZtzjO?1;H# z(|a42jCHm;H3dtb#>XX3 z;QoW#=kkor*tB{PLeY%8A}Bvn{8hG~DELixXwaDKc|lHr-`l#YlRo{ep3;8*UCNpz zJ&!C#zrR|NsS&u}&h^rT=|>cEmH}T!*oC<#XR}VXdIlaGs!pi9k-FTtx4J33?{UW; z`q0Cmb7+02!S=b^)1K`=w?LIuGW+|w870VL*`F^S8(jMoTa@QHvrlH!@Z0aRx-+Z2 z6O(r>FkL^sR`E;RKS4@C|4cFzKe?Xh(($7YgZx232%Z~;u>rQ=Ww0-4aR(I?o z_JMQp*auCB(Fe9o`CYkf_L@rXL>uYa!naA6LQI#J`Nkk?DzgiMhItPIhyU?8(tdJB zh`~+RQQ?};rLe8b@5ri6jJ25wp*Nn77(cnAp*K~)QI8395J;0w`waG%6$E|eEh(Pd z1%ZXSNIFJmw`IyNo)KwnKUy?CuuZgR?vNYCY`vFfSGapeYM_&QSL@c@v*^?c*b63g z8uK}ehQ_)eMUq*Jd5>jsleP#;ZVTay6@qAorASW zefrx&?PsS2@3dPPm_K_FoeJNzoo_8>do@C$6Ui|*@AeIOa?Jk|Z+5fa9=j!ln*$R0 zV(vGH!jrdWB#tefU%pg7g;?pC-pF&ReDEgo)5)#1@>k#XZCgf<#IoROr?+hm{jQHN zGcneo(06T`edU9#F8)0SGCx(sz-7jNc*O}7ma{?LS7c`SEY`bHX_M3@yJ5wpz{QW2 z#Z(n9yLRv1?!%FB(ExVV^_a-6EmD$e!?D?2)A2pmr~Q4dPe9M>M3;nT{#M2EED0L+ z`RFyptny{_yVc=+musQ5&S$rk#Q@dw%PIK>5gK;$=zYbk3SIi${lc!4!uj1Pp@-i- zklhb@*KyrO=m)!7-PdSk=PQTVUUhQK%Z2kVn-6|AF%RA28(7t4xki{jgHGM}^`^3O z_C|a}H7`HDxOV&ZYbNI7pH1GbfV}^MmkwW;PoY!G`u=Mu<^2 z7>rq)c4=kVHX$S`VONiRQ_OmQ6-|nZgJ}2!jG2N*?oJuT?E_AW8Bxk_wR!1oJqS|4 zFW2EDuU}%H@o(s_2OOmhQ-i9FW=APMgm&8=Dw3Hvz-}8+4jpq39cgkZ+8;3XI%56v z^|g`8!=Pc-LqoL826KwXZ_DJLgOulC3_g>WuD3GS9YGF0I{Hsd#O_d8u9dCNAlRf1 zNq3KbvN|?gb|APnzGw-pK6ND(5u}Wqg8nA+id}_RbUdaPUPwizUJm**bhvSyaR___ zP@_{L+N+Qf7mcR=)FanTLW;?EpL&pzJBuH6J|2HGD~1ENXlrqa$Ai^~-_@zV2Y)@1 zEbC!JEA!|qL)#t|j;><^(c^|VOtwmsO`H5=yMibtrMSE5_ZzR? zhx8g>feX-6sPpXY`o49nW1o*jQO1{lMYGs6;&&U?V(cs$hX3jUN=0HF9{v*#t~y&R z;iK>^5-GPK+MS_&a}>r?VPQ~aVXma}Y@t6CK?-<8dlUQyWs5csT_fhgXHO(o1&6{* zM(~Lg@AYyjpf2E}P~Yi*PvhyvgaQ0(>PvkB%N%TVq@XMvI`uNZ_LH!$0rofvn**>= zMZ#fC0k(;RodU2ZfdyZA5p*>{<`$@4iNwuHVt}j`Vc;&HLT6xD@*3KICHm*%Ki=^s z`tOA+3YJO`z<=j6Eu0YdK-{LCBt`sfG$BGw5}6iDiul{Jgt!1INz={~q7)aC3DF*0 znCwLGIstaAG28|G$4XoyA{_8l9nm9U6`{S1P7DH+X%W3d0sx#nM3CJ8^#f-U+!=8+ zfJQICox#h)T=?VyfrSD9l0|Uk?F6Ka1X31U7}Mbs3k>Huh`@$5IFl=|Ig5M=P&FLX il!y@WfBZMxJ5Fhu`EUSvIOhv)YK`?;{%xK|`2PcsaC$QU diff --git a/test/golden_widget/flutter_logo.memory.png b/test/golden_widget/flutter_logo.memory.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 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 OceTRWk)O+RKm31$8ZSuz literal 10130 zcmcI~i$7HB_y3+TW$R`SLZ#+HqLU(&#F(aGCf@iXCgCbEXVYQxc# z?#6!;ymklI%i8<9tZfV5T8mmxy2i#>_e_;jI*$&YplVQWY&-Xtec{4M^-8+uHtc9q zw*AgoJO9cb4NU#O670AA519u1K%NLWyXkjs5>=;rs-g3?Of=)~o`4+{{SHT*1|8f} z{j0uMylB_XHL0z==fBJT^S$Qa{rVJO^?&&%e%&8TL0;Zi9@4hEIR05@^FZ)i!;Ce> zgCz%={9KzaQ1)R=WP`mBJ1bB3qtZkRqm+3nj1627;yhQj%C;rK4#kk0Y!13c=uD?j zxu&IxtSIG$+FT?nT+Y;ytvW$Nkup_=Scj99h)~kKTOuT-iZfN2h#Coc2te5cD3gom z#o>J@`tt$lR|3fle|wU6YYa%%7>@J-rBF*g5S{WR2*u+iq3UKQLJZvqd@XwrfgG4h zu?5kL5O488)FVX)5H(5B8bp*79YqM1N*J3%XCh)<+^v#lVE0$j*i7I>!tTXYV+qyG z5CI+?=f#`@?Ifz#d@h2n!ow!&g8q+*2&B&hXLk@#FK2`50fM*pIf#n}L7-r*2zj{z zkE?THzJBv`VQV0*rRG7$2GA;m`?m{9tiI5Gp1kyqj z6a7UZO{Y+u>4aN1Ap#4@xE`jV+(`tJECAIbLF)i?5((-Hpw0y71^`tfKoMM%oDE$N zph<+&B7M-r2u(u)XmWA$h&rq%g$4KsBKE+9LV$`qK@1~;B2vZQlHyGKEr~T#3Eq;T zDgKsN2O?AaEh$ciw;u@F9;>M|rXk^0eKD$r=J# z1p*a?mA)6|1q3-9oY_kDFQK6&CkZZ0GYU1IB%q0as7v(HguNtxGAUvpvPn@BL@FsV zDOA4+Q4hpv7YppF5vqET2&JAJ@e{zCn7POl9j@pz z8LcZc)Y+8OyogY4&L`%^2~{Td92r6?m6k=$tqpL3Y$PW^G>WCqCc@%8i$dK%>@>(i z0Bs>buK}nD0h$G%(In_O0F5U=!T&@75h`1KB`lqs4J8x`RgG9~$VC=c#3md;1Ssb5 zmFOgbz1+~7Fk0e5rD-lA@ISbL2pc`@Ss(ZyY7wHxd=N?hJ$8afM$N+jL>j5Ek4i(G z2nzKOARe&}kY&1DQ9fxb7sc@N17JP&fGWwh93pUq_bOFp36C7c4@%evl;n+4X%|UeYO6(vBB^>6cwf`uz#f9A!5-EUaj{g98&5+w zkRIxtN5Y~>d}~#vvp$J*luBC&ePD;%uu8<;Nh0~8SXLzAmNT59=g7F;)aIsBNw?3@ zP&E=X3qZq3(2W49M}i)w(x#B0aDb?hv%w<`G)bo&=uBtQ5zz|JBxggu2nh=#Czcye zR3ailwN{HtxTKiE6_p^Qcnic566=;N=uU{MKzBl11G=QRmn-7>5wwvxDol(VtrB$_ zN+Z`ILf-F^KVj?0e+^ICQ-+`Do>9BZ?lg_?m zQ>d22l1IFgkg$0qfdC*NB>~LY-1OBXm$@p;m*jCKidDioCSa9mXu$;R0xE6G1gtiN zYCytv0IWI*O9QgTBv~d6^&(ZVNF>aGv=vTgO2SC8Tq^B<6YYsen88GUU9QIjmnTYC zJxQPhK{2-kqE`tQ#0XLpff!GUB_I;8@nx4d!{3+O*z;!0vH1<9_L<|ucjL{8pEopX zAk{=XH$Upkcro7F)6=7voLDs&Y+z_DbT-julDo3@=?J-IT$y70`_YmEjbFbE7opw> zNZ5RwecYl_#Z^(tH zxmiT!OWLMPMX{U2ye5s6s8Ge^X1_U7Ib4O|H;uxp{!e$aFyso64GYv;BGOA0VS+mo z`{{)BO(vg5s0bk5#TYPeJ*L}m_0F%uo?;9VFJBk%_$Xwq6VDV1PX^EQAI~fbZzdnT z{Ih)$g=Y%SKilVnJA4#URIso=@imPQ+3H5|9n{Vo8h~&qN`& ztDvD9Ratu-g`~Uq@~DGnhab=OFckEslS?PuD}Y7Ip+EiW=d**TM2-G5>c=xInG!Af zQ2jH>^rg%n-h`_%CGqGiCHDsfy9%bqa z3p8qbdRCSxK8aM;gP^2FN*sPP9H~kfx+gpOJyvFBSwHx#gd?L&S~_X!@m=Px)j>y5 z7GLx40AslGXbR`GN$0o6J2daBGMpiYqeM!kgJtznsTjTD)S@s2qKDG&PL{=&8Oe-T zyp9OD=&2Hh^2N8fLa#eKp+hA0P=}KanOHcTC507oi_TDGix)>KXMrOkemS*8`}Fh{ zPoDUtu8cC1&cqVYBsS-6J)5J;NB3b2JV^_SlIU=jKF9E$DW!@VY~c{uD1eZ&J#hnv zKue!ORdC)Z25ws-<6t%}12ve(+zm5XU_iYU4CE`xD3He)GB@&}>(vPPMT~W8wGg4w zPG0XoVg3YY;s!QGD#O9e^^ioL!DR8)%D7u*v2p~mbj_@*Y`)N|ny{))XOzH2P+=1v zw@Sq$@@ujjiN%4Ztl-R>Ql_fUZ$U81)2Bt_;EbN^}&$y^-mh<&0a<^n;K{ zmPRS#8RHanHV?*g5>8J4v>bV@%T4!tY=gT`klTqdN^Bq}Nxy*muZENJsxMW{hYQEK z4iloQ6uQoWq1kIK;#!+W;eJiR37@nU!gZJFoU}MB2XJB;ThwsFveC@RyT0JK|}Lj&9Ume*KDglUv|e* z79WE?$5ru5l`5klN@7u}`117Sq9sVWS4+msH>Qrm*JNhFw|#01g54`1HA-I&x3>8$ z85`MN{w)f4A;CLL-XTUer^%7y3%HQ9FfOaGa#R^yNE(^ivg)byLrY~8F_bKp(ix9c zSbs+;<9RM53+O7b)_jf#?*Ap{O9guDHi;bJk+(Az33=1>?5UuIyS6TBpPg;l{2rY!SE?MYr)maNoY8q=wu7`v}CzQ7>b+v z4Q^FiS|U9AXR%ro^uVv1IvlrE47{lYn#@}wOat(yEV!XV`K+F+fj2=mg5T;43W%m? zXkv28(_>&-bD=EZY$01^vjX>cqY9G?XT3o=9fvqiT=2ZBm*EgM0Ub(IGxnO zBsQFH$Vt{Ut<*EszqV^|=tyx(<(Dyy(QR|Ni>NfcSoDhhX#pqsadGlGJJ4~oyAkMq z^hM=?kT{fb6A;)@*u$^y6XH1Xw$US%F~ZEp9hxyNwGIN?gyjB~p#33zBTaQL>Zqk~ z`}!>kd)xp1$h_^GZr=dSc|kHGyKJ8UtFfA(14Z4V#qVl&D&Q42YgJak#|H=8Lprjx zwHc1S$-397clen&`WyDf>r&3@(hqe9FE9Q_;Y(NhXUZ^K&sw6eL&tmGU0@vlTw^)z z@#%?fcbu@osc?2>nN;uEtIUJGE_Q`qLa(6|{Gz`Qj*O!Nq;{jftXeDfXy!WKnjKya zPK9rSnwkubEaB){)r`0gy;dH**Hfe*8iOI9%@*&o7|A`wczCGuc7xpP?z@ftX1#Y9 z>{@Nc`j7F?64HJXepBAB!s1%P_{^j~)m48c9ZQb0F5KSjSZL>CZvM>pzzg4Jg`s}6 zdCg-hw+ojb!BAE>%t!yNKOOf%YjdB`{G`h9cwLCwT}Y?@vYSkUFU zwKW_F>Hhdj+DJun+A+UFk`M1!FcRqTqYE6%q~_qPyKc9jJg>R4*ghR!xvA){Z|}<8 z3O-m=GL~L^?bdhjY-8iQB~7|KQ7=@sba?fBUCWCHzMivBOO1(prR8wPcScjHSgOOR zx$Do_bxVtp@M1q7b)E-xAt&*x?uKIdUw=Be55Ia}E^Sh3_X&A2)OIE=S3M*=Rn_qp^V>m4n0Tk0-8D;xJN(DaW4}7GdASon$UPV zIjQls?$(|vi0ovWA|KbkOY@tVkou?9n!uSS@s$g*Y#A_d+%xUOa)CSu-pR8 zk4br##-TWr>zkvpk9M}<{_!8tH9O7d&ar+?l5_}+ibNo!^A zL2Pa<{j5v!`^DO2(kHGnStW3Z6q&-|J>2=G*srTx`s8VE=cM+8bZ?pD$u@9T2i$dJ zd%1-SmySP#;FM`Id`!%RL7yMRHN?jy%$U`+9M9DZ)j&^y?WGygTRJXm`zst`sJ|&l zo4Ek?1T{-Sg$63C**gDAvyipNZF?}Tns+HU;O?i474N%!ceQ!;7Gz_aXEThVFs3<7 zhDmglTBmsOW@(JV3ogD8nx$oKj*%R~Rv zgoZYLZxvJxUTo-Icn#L+{wG6*kr;C!eyE~RAEj}NBja={`O*qr-!9+ex+(2K{?@*O zDs(CzCc#oVYjjwap=<#_(zs^=bBjjdq1OWc{O%sFRl{u?`VJ8`t081(__kId-#Zj= zKU$?r%$l2Beox{wTFkYvjlvToku6?-WoK@+D*8SoNGtl{X|JC0BGs4U-|@l0&!O0A zPY0o<2WnIKw#!2ThWg?-!JWmUjST|j7ei(iUVgrRZM?U)tu@Pquu2E3=OZP7qa7dZ zL33OhTPp1;$jQzPtgXIhdH#gJ?$3s9-|cK#$0f)+;!z*z4q-)%&}9AA?(5ctI~-G& z&t(UtnZ3#lTt1&C;y~QaM@b%q^nV=%v}Qqji>JA{x&v&1HLo@mj(l-dXS9y$?{0mS zX)^CLmJXjv;Nqea$KV8vXE;?#rB@qopI>Zd<&)FcTfvvcD@SALL7=0}_F8Er>?jiC zy&qg45O6+eoL^$up3#*XxO=YZ+&(@^l(Sj%yGe|Y?j~vKSeGF7_K@wVjCsaWD=+Pw zT6JOcV+letxa2D`SH zWi@=Mk0q6=R~tErk-1PSw!~ODLr+}49P7${5#qIsqr3j5O@eCWgD-K zhl%u3n|`-mx#;*CPp9C4;(1Ad_w|-0n^<*!?g;NYwz|ICce$z05evIF&ocHu^-M-7 zMA=`Lw<~!3m$YMD&x5QU!A|TQO7rr)Gt}=btysb6EPpp*wRz8*qTI#;4J}vcjhdd2 zqy08w!~lGOOP6Ky_+Pu{1$}NBijNx&HMzGwCwZuIQ?25R#YurPjX2MI5^u*Gsi~87 z2JCy35UAalY>mDQ=jI(k4(C|%#(MuwJO2H7(3reDybt!Y*jwK&TI@UL<9e{gGiAVL z#g5r&YnH?~-Pq%^;MKQEj75CLkZjRz3vwT8YjtWIk%qRHE8>T6m!32pU19d|yK|{( z)!^0Efa3>++u`4`?e;fXY@`-+suwJx@N5HK(cm>mJ6>4|T0M9Do|BZlDPi?wjqylq zj%urkooj7pe~Wy$|EYXur?0tXO2@?oJiN%q<=*F)4;J-DNz)#+7gv-?y@DDWPJD7q zUSyVL(cR|b8k{@yM{?D5jhgA5LjkLg>tBw!f7^2on^vAKapjA86X&s-M_U%m3+?S0 zlG`fQ=FF%Xax?ko=8DG)d!pav;o|P=m#d0GZtzjO?1;H# z(|a42jCHm;H3dtb#>XX3 z;QoW#=kkor*tB{PLeY%8A}Bvn{8hG~DELixXwaDKc|lHr-`l#YlRo{ep3;8*UCNpz zJ&!C#zrR|NsS&u}&h^rT=|>cEmH}T!*oC<#XR}VXdIlaGs!pi9k-FTtx4J33?{UW; z`q0Cmb7+02!S=b^)1K`=w?LIuGW+|w870VL*`F^S8(jMoTa@QHvrlH!@Z0aRx-+Z2 z6O(r>FkL^sR`E;RKS4@C|4cFzKe?Xh(($7YgZx232%Z~;u>rQ=Ww0-4aR(I?o z_JMQp*auCB(Fe9o`CYkf_L@rXL>uYa!naA6LQI#J`Nkk?DzgiMhItPIhyU?8(tdJB zh`~+RQQ?};rLe8b@5ri6jJ25wp*Nn77(cnAp*K~)QI8395J;0w`waG%6$E|eEh(Pd z1%ZXSNIFJmw`IyNo)KwnKUy?CuuZgR?vNYCY`vFfSGapeYM_&QSL@c@v*^?c*b63g z8uK}ehQ_)eMUq*Jd5>jsleP#;ZVTay6@qAorASW zefrx&?PsS2@3dPPm_K_FoeJNzoo_8>do@C$6Ui|*@AeIOa?Jk|Z+5fa9=j!ln*$R0 zV(vGH!jrdWB#tefU%pg7g;?pC-pF&ReDEgo)5)#1@>k#XZCgf<#IoROr?+hm{jQHN zGcneo(06T`edU9#F8)0SGCx(sz-7jNc*O}7ma{?LS7c`SEY`bHX_M3@yJ5wpz{QW2 z#Z(n9yLRv1?!%FB(ExVV^_a-6EmD$e!?D?2)A2pmr~Q4dPe9M>M3;nT{#M2EED0L+ z`RFyptny{_yVc=+musQ5&S$rk#Q@dw%PIK>5gK;$=zYbk3SIi${lc!4!uj1Pp@-i- zklhb@*KyrO=m)!7-PdSk=PQTVUUhQK%Z2kVn-6|AF%RA28(7t4xki{jgHGM}^`^3O z_C|a}H7`HDxOV&ZYbNI7pH1GbfV}^MmkwW;PoY!G`u=Mu<^2 z7>rq)c4=kVHX$S`VONiRQ_OmQ6-|nZgJ}2!jG2N*?oJuT?E_AW8Bxk_wR!1oJqS|4 zFW2EDuU}%H@o(s_2OOmhQ-i9FW=APMgm&8=Dw3Hvz-}8+4jpq39cgkZ+8;3XI%56v z^|g`8!=Pc-LqoL826KwXZ_DJLgOulC3_g>WuD3GS9YGF0I{Hsd#O_d8u9dCNAlRf1 zNq3KbvN|?gb|APnzGw-pK6ND(5u}Wqg8nA+id}_RbUdaPUPwizUJm**bhvSyaR___ zP@_{L+N+Qf7mcR=)FanTLW;?EpL&pzJBuH6J|2HGD~1ENXlrqa$Ai^~-_@zV2Y)@1 zEbC!JEA!|qL)#t|j;><^(c^|VOtwmsO`H5=yMibtrMSE5_ZzR? zhx8g>feX-6sPpXY`o49nW1o*jQO1{lMYGs6;&&U?V(cs$hX3jUN=0HF9{v*#t~y&R z;iK>^5-GPK+MS_&a}>r?VPQ~aVXma}Y@t6CK?-<8dlUQyWs5csT_fhgXHO(o1&6{* zM(~Lg@AYyjpf2E}P~Yi*PvhyvgaQ0(>PvkB%N%TVq@XMvI`uNZ_LH!$0rofvn**>= zMZ#fC0k(;RodU2ZfdyZA5p*>{<`$@4iNwuHVt}j`Vc;&HLT6xD@*3KICHm*%Ki=^s z`tOA+3YJO`z<=j6Eu0YdK-{LCBt`sfG$BGw5}6iDiul{Jgt!1INz={~q7)aC3DF*0 znCwLGIstaAG28|G$4XoyA{_8l9nm9U6`{S1P7DH+X%W3d0sx#nM3CJ8^#f-U+!=8+ zfJQICox#h)T=?VyfrSD9l0|Uk?F6Ka1X31U7}Mbs3k>Huh`@$5IFl=|Ig5M=P&FLX il!y@WfBZMxJ5Fhu`EUSvIOhv)YK`?;{%xK|`2PcsaC$QU diff --git a/test/golden_widget/flutter_logo.network.png b/test/golden_widget/flutter_logo.network.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 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 OceTRWk)O+RKm31$8ZSuz literal 10130 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 diff --git a/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png b/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png index d46b6ded9b7b4cbe558dcf475ae18bbc7c50b096..6b12ded3f96226de0bef22a1502715fdd3b1c757 100644 GIT binary patch literal 9168 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 Ju1IB({|EC_!h-++ diff --git a/test/golden_widget/flutter_logo.string.color_filter.png b/test/golden_widget/flutter_logo.string.color_filter.png index 0f02fbfe18a983b802848cc90e92329fd572b611..d80af0975390b8ab1d09108ebb7d44780e376578 100644 GIT binary patch literal 7618 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 literal 7518 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 diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/test/golden_widget/flutter_logo.string.ltr.png index 7e70b9565dee51aef6a52f03b7b7119a82c15361..e4402865634cfd5469cab823e5056404bd347fb8 100644 GIT binary patch literal 3404 zcmeH|`&&|X9LK+hY%;A7Ej3qyNa}igGA~(E5#m7wGqu(-)6|-)P`fBzf@zY~25Lz% zua&deEZ1Y!R&!b|S47%W63Q%1%P2214ND``xzB0O{)+ki&q@lq9 z^G$3_5JK~LT+T*>=1>tLY$1LGq%<{aKU^@u#sD_D*tTR4Zj1zM-X7eyu+mVpJw$1M=DOs z_ZnF}I7;<8>8YsN!a0$BR!#SNO_H_y-wBEeG<)pF7r67}!6S+7-F$gTOLvi=t)c&v z%6Me#wa>Lbi+b|}G$>?t%{uUZcfhGO_Tlq8nhh>koHx6iTRYd(@vS3AZgC&`i zDp`PdA( z+54hSDZ;20eRIT7kntM_Uo=pFuox!*2LXJ9gCYP_0BZpl09b#AuyPjw+X0AhPzb;g zfHQzpx-V+VhAj~|fGi`tbR=7a5gH2>#z<&JMF})e^--2|iZN{CQFWuZ83I$F6Lz)l>{0dN4s0dN5DoCRCN zdK420F|r{>t_4O2-3~z$?OAAfAV`lJ5m|GkB&399&s*!T#x)jHv6ozjUz5yzCjU+<{zYOSrA-b}@EnUK@% zD@opARW+lX_oZEPe9g6Gy6^PJ$vEs13OwtqBlDfLS34YdJ}HKK!=^`D=fpTcXu9H# zrNWps2(^znz4Vvs5j6nE!IUzFB{{P#MFM0O5KhuDGw=(8R+_cucF@mOV!G_}I znp4rT0^SjD)&!glOgK*@gArncIn^Da#op6zsrRCgna3oxlclSjbXe$T5RqWWmYwOd z7dog9tjX`R5C%Z1^K|Hg%VpJZ+BTuW>k*q2Slsc zZT>dOlKRNs0L-g@XdxE=1Rh(Cw-c6AvX zgB5S|1NC8e30t9rRfQ4h$xoJoHRTiF(t1Yf4;j>lpjc}6Flwe(b=w$0*OgI*iHk)V z`f)4Qzs9PVJ!@uej%H5jYNirG$ZwE!G)R=ob+D1udwD+bjB4|VRZ5iH!pHtPmGwdX6Vt4K=k>JY_v$GN_jin8Adu87K(vC&TzzPvX)RVP=?4EY4rdXok1uxWI PNw^z4zhKTqc1+ek!J+%< literal 3411 zcmeH{`CC(G7RTQNlnfY2SY)e)B!hs`qAgN^hTMrM2?!b^iZW~p2!bpM%9cuoLMJ3s zmQg?uQYcGNS`btE6n%nehfw#z6h$#e4NK69F@z9`s6FYwQQlwji~Cw0;`> zLzVK$W6i_pzU9-IG!U|KRvh@NJJ9~!^QNS-mOb7$g>#1YwftY>n`6FQyRbpN^o8g_ z;4=nV#8QW?z@3?bqF2_%FXeemW8d4wgw1K#e~{HLQvTC01AQ*~lenfB4r8U7L6 z7CRgsdjV-loW(x)S=3A||&Ek^r z=0cUo8u`*ObiHH|H97!jDz!%WZWwYD1E2u-7l0)b5G|rO5`aDcs{zbN05}4W0{F}X zN*9r7Kxmmc0V6`yfhvS+chcb$+ihLZHd-KZ%z-2uA;~@{ zlY$8l&mMr<1fZu)p#Zi4_|gQ1oeX$1-({)OO*vE>Rp~va?0fF#YsbD{xQyW)3nA?A zMG~bT_R7-p6!Gt0x6AL}Qv2y}JR-~_oV!m==ihedxzD(q`=Y##Q!{$qoFB{bahayel?6Jg(F16SS9HHM`%UCcpy+vZhf=QnY4{PgRem3ob4 z)b^LF>1mG^jQ_s2sOO05Efl%n12H0@ILdE9eL-oJ!5FK1VB>jSbnm(}h3R7$eJ<5V zzx~>FspAKKJ}RS*Q-&$c)%PKJmoJ43K9(ReklS;VJiFzlA&Hw-#;| z&Ac%WUa8bIwp2}_exmT*X#ZCU9UmCp-1uogH&jKt^NpA!3?hTU@fCzTy^7qxEiBN z*3tvP4MeGgBy5AFR7H4`Poz8<>;(%xlJ>aApS*K}vw45y2ghaGTt;LZ^?qpOTkWd= zQ0N2-t>+sFem$8pD)m3Rw8whfX^FF<>xWMs_Dv7did^=V4;0L%9S=DFEU%h?YiHu{ ziZ)+yMY2_^Kg)@bT?iZ3Z}lSMc})1~^~v=k8J{o`AM!FnwN)U{0R&>z zgk1+x4Fo6)*Un>CK0D8$(bSwzKW-?y!X?Bnt zA%jftT=9c7BWtq3OBppJzl3e3Gvmzuc_`YZrLTBMNLai`S mgdK&aD`&-l6$iip#uDYjYr3_J@>F}1AHg5*Vt2CQiv9o@we9f$ diff --git a/test/golden_widget/flutter_logo.string.png b/test/golden_widget/flutter_logo.string.png index fc9ffa27529c1c7d62c7faecff5822448e6a262e..7b88eeff0280f9170d14a57356ba73fe922ededb 100644 GIT binary patch literal 10330 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 OceTRWk)O+RKm31$8ZSuz literal 10130 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 diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/test/golden_widget/flutter_logo.string.rtl.png index e65700f87fa6172382fd53a21970ffacf71e87d1..6c8dd292777c2640514e08b937b8d3d764a80b9e 100644 GIT binary patch literal 3490 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 YSB+27^+L(4GaIXiuXg~ihI=^kzdytZE&u=k diff --git a/test/svg_parsers_test.dart b/test/svg_parsers_test.dart index 9ca75d9f..2c20fd2c 100644 --- a/test/svg_parsers_test.dart +++ b/test/svg_parsers_test.dart @@ -1195,7 +1195,8 @@ BAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" x="1ex" y="0.5ex" width="2ex" height="1.5ex" / final DrawableRoot root = await parser.parse(svgStr); expect(root.children.length, 1); - final DrawableRasterImage image = root.children.first as DrawableRasterImage; + final DrawableRasterImage image = + root.children.first as DrawableRasterImage; expect(image.size!.width, image.image.width); expect(image.size!.height, image.image.height); }); From 215e0f4f4ca04a58fc507c57d01ed7fa88a4244d Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Sat, 22 Oct 2022 13:25:39 -0700 Subject: [PATCH 081/142] Strokes with zero width should not be painted (#798) Fix #797 --- example/assets/simple/zero_width_strokes.svg | 3 +++ golden/simple/zero_width_strokes.png | Bin 0 -> 619 bytes lib/src/vector_drawable.dart | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 example/assets/simple/zero_width_strokes.svg create mode 100644 golden/simple/zero_width_strokes.png diff --git a/example/assets/simple/zero_width_strokes.svg b/example/assets/simple/zero_width_strokes.svg new file mode 100644 index 00000000..36e37d8d --- /dev/null +++ b/example/assets/simple/zero_width_strokes.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/golden/simple/zero_width_strokes.png b/golden/simple/zero_width_strokes.png new file mode 100644 index 0000000000000000000000000000000000000000..c27fed45024c3d41be01e5e67e8ec08b96073ddf GIT binary patch literal 619 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_mZkPZ!6KiaBpDZxlSBAaG#Agumr=Vh`>(Df&J*mYw#Dx$oa?#t%l#4h9@7 fqr?aagBIT4o2)%mwSV>j6AXi=tDnm{r-UW|Rn?0s literal 0 HcmV?d00001 diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 1ff13d6a..03968c26 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1293,7 +1293,10 @@ class DrawableShape implements DrawableStyleable { canvas.drawPath(path, style.fill!.toFlutterPaint()); } - if (style.stroke?.color != null) { + if (style.stroke?.color != null && + (style.stroke!.strokeWidth == null || + (style.stroke!.strokeWidth != null && + style.stroke!.strokeWidth! > 0))) { assert(style.stroke!.style == PaintingStyle.stroke); if (style.dashArray != null && !identical(style.dashArray, DrawableStyle.emptyDashArray)) { From 791e624b1267926816b8b21ea24da3d21edf0da5 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 24 Oct 2022 10:24:30 -0700 Subject: [PATCH 082/142] Transform clip path when applied to a group (#794) * Transform clip path when applied to a group Fix #136, #343, #566 * Golden test added --- example/assets/simple/clip_path_transform.svg | 17 +++++++++++++++++ golden/simple/clip_path_transform.png | Bin 0 -> 5307 bytes lib/src/vector_drawable.dart | 4 ++++ 3 files changed, 21 insertions(+) create mode 100644 example/assets/simple/clip_path_transform.svg create mode 100644 golden/simple/clip_path_transform.png diff --git a/example/assets/simple/clip_path_transform.svg b/example/assets/simple/clip_path_transform.svg new file mode 100644 index 00000000..80a791eb --- /dev/null +++ b/example/assets/simple/clip_path_transform.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/golden/simple/clip_path_transform.png b/golden/simple/clip_path_transform.png new file mode 100644 index 0000000000000000000000000000000000000000..9aa0955409a18a8015c519fa9e26bfc8a8331e76 GIT binary patch literal 5307 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 literal 0 HcmV?d00001 diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 03968c26..985bab77 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1098,6 +1098,10 @@ class DrawableGroup implements DrawableStyleable, DrawableParent { if (style?.clipPath?.isNotEmpty == true) { for (Path clipPath in style!.clipPath!) { + if (transform != null) { + clipPath = clipPath.transform(transform!); + } + canvas.save(); canvas.clipPath(clipPath); if (children!.length > 1) { From d43b6b8a638454318dbee1a41a683ad604419f61 Mon Sep 17 00:00:00 2001 From: Feodor Fitsner Date: Mon, 24 Oct 2022 22:09:32 -0700 Subject: [PATCH 083/142] Apply image transform before translate and scale (#790) * Apply image transform before translate and scale * Added golden test * Fix SVG * Update image.png --- .../simple/image_transform_before_translate.svg | 5 +++++ golden/simple/image.png | Bin 693 -> 695 bytes .../simple/image_transform_before_translate.png | Bin 0 -> 675 bytes lib/src/vector_drawable.dart | 4 ++-- 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 example/assets/simple/image_transform_before_translate.svg create mode 100644 golden/simple/image_transform_before_translate.png diff --git a/example/assets/simple/image_transform_before_translate.svg b/example/assets/simple/image_transform_before_translate.svg new file mode 100644 index 00000000..f74b1a25 --- /dev/null +++ b/example/assets/simple/image_transform_before_translate.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/golden/simple/image.png b/golden/simple/image.png index a14ff426a01582502ef9bada94335e93eff71747..116280a365107c13fa007f4f86da98e8cdb55d4b 100644 GIT binary patch delta 245 zcmdnWx}9}`qjRFCi(^Q|oVRy3cC{FYI9xny^#A|qnPCMxd{fSxuw0sO;nAlJ6&BCt zeCGf0;{QALhPj+9O%4is^y~|JPWS)Onx7&wV`8C_h@*nQx!(%=_nqIE_4V)D$u?b_ zOpZYDiS;5dB*wqX==rVA(kqJ*Qw7fJ#?cD!)&-EaE7QT@0nE5X&uQ) Q`x$`1)78&qol`;+0LHOyk^lez literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_q{hPZ!6KiaBp@8+I`p3NSdH{_#J4TJT}nxjqUvL!R!=XijrDy=L$CI)?vM z^XwSz_$UalFgfBS9+v)M=-=u$KjE0wS$|_k1rC-b2Li;I?~eOw=O<_V`uojuU0Rca z00&DWor#Lx`y0N$`MLF&y9Ll0F=tsC6$Ch#2oMJM*=KI@KX}v!rgZ1UsQdd@|5s)y zntk5DrDzV&<4?@yU%$8RK)>~W`Ih}Hg}lOqgM)|=8zM>$N!NypPRoq+e#-y^p00i_ I>zopr04t)dUH||9 diff --git a/golden/simple/image_transform_before_translate.png b/golden/simple/image_transform_before_translate.png new file mode 100644 index 0000000000000000000000000000000000000000..d1517c05ddaa61f2ed3b9daf6025e23a62b73839 GIT binary patch literal 675 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k4M?tyST_$yF%}28J29*~C-V}>VJUX<4B-HR z8jh3>1_mZyPZ!6KiaBquD&{!_GPnfVIfjRn*k;JQjN5Qma$gQ(XF50k?OEABPBuT8 zBigfbX6m21p0l%e*Vmt&w_(=#+oj)F{@pky$FSZ?W)E9&Vn}3`}PX44$rjF6*2U FngAK6j^6+P literal 0 HcmV?d00001 diff --git a/lib/src/vector_drawable.dart b/lib/src/vector_drawable.dart index 985bab77..28ae5a7b 100644 --- a/lib/src/vector_drawable.dart +++ b/lib/src/vector_drawable.dart @@ -1205,11 +1205,11 @@ class DrawableRasterImage implements DrawableStyleable { halfDesiredSize.height - scaledHalfImageSize.height, ); canvas.save(); - canvas.translate(offset.dx + shift.dx, offset.dy + shift.dy); - canvas.scale(scale, scale); if (transform != null) { canvas.transform(transform!); } + canvas.translate(offset.dx + shift.dx, offset.dy + shift.dy); + canvas.scale(scale, scale); } canvas.drawImage(image, Offset.zero, Paint()); if (scale != 1.0 || offset != Offset.zero || transform != null) { From 3753ff989c1f7c6ef4781d0772b4a3fe0dde9345 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 25 Oct 2022 00:37:19 -0700 Subject: [PATCH 084/142] version bumps --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f683e14..910b111e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 1.1.6 + +- Fix transforms on image tags, clipPaths. +- Avoid painting zero-width strokes. + ## 1.1.5 - More permissive about color strings. diff --git a/pubspec.yaml b/pubspec.yaml index 4e7ea31e..04cef40e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 1.1.5 +version: 1.1.6 dependencies: flutter: From b285441709edea5bf106303c4b3b0a83f84dc432 Mon Sep 17 00:00:00 2001 From: Dawid Wysocki <62249621+TortillaZHawaii@users.noreply.github.com> Date: Tue, 25 Oct 2022 10:48:07 +0200 Subject: [PATCH 085/142] Fix typo (#799) --- lib/src/picture_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/picture_provider.dart b/lib/src/picture_provider.dart index bf46e315..bb6cb12d 100644 --- a/lib/src/picture_provider.dart +++ b/lib/src/picture_provider.dart @@ -422,7 +422,7 @@ abstract class PictureProvider { /// An immutable key representing the current state of a [PictureProvider]. @immutable class PictureKey { - /// Creates a new immutable key reprenseting the current state of a + /// Creates a new immutable key representing the current state of a /// [PictureProvider] for the [PictureCache]. const PictureKey( this.keyData, { From 2c9223dcbf0e5f29c99ad94ca6e58d719804dc18 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 18 Nov 2022 14:57:08 -0800 Subject: [PATCH 086/142] Start using VG (#782) Use vector_graphics. Flutter_svg 2.0! --- .cirrus.yml | 17 - .github/workflows/ci.yml | 27 + CHANGELOG.md | 25 + README.md | 85 +- example/.metadata | 28 +- example/ios/Flutter/Flutter.podspec | 18 - example/lib/main.dart | 9 +- example/lib/simple.dart | 28 +- example/macos/.gitignore | 1 + .../macos/Runner.xcodeproj/project.pbxproj | 29 +- .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Runner.xcscheme | 22 +- .../AppIcon.appiconset/app_icon_1024.png | Bin 46993 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 3276 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 1429 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 5933 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1243 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 14800 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 1874 -> 2218 bytes example/macos/Runner/Base.lproj/MainMenu.xib | 4 + example/macos/Runner/Configs/AppInfo.xcconfig | 2 +- .../macos/Runner/DebugProfile.entitlements | 6 - example/macos/Runner/Release.entitlements | 6 - example/pubspec.yaml | 14 +- golden/dart.png | Bin 3651 -> 0 bytes golden/deborah_ufw/new-action-expander.png | Bin 4655 -> 0 bytes golden/deborah_ufw/new-camera.png | Bin 5049 -> 0 bytes golden/deborah_ufw/new-gif-button.png | Bin 5167 -> 0 bytes golden/deborah_ufw/new-gif.png | Bin 3143 -> 0 bytes golden/deborah_ufw/new-image.png | Bin 4493 -> 0 bytes golden/deborah_ufw/new-mention.png | Bin 4420 -> 0 bytes golden/deborah_ufw/new-pause-button.png | Bin 4513 -> 0 bytes golden/deborah_ufw/new-play-button.png | Bin 4696 -> 0 bytes golden/deborah_ufw/new-send-circle.png | Bin 5591 -> 0 bytes golden/deborah_ufw/numeric_25.png | Bin 2053 -> 0 bytes golden/flutter_logo.png | Bin 2763 -> 0 bytes golden/noto-emoji/emoji_u1f600.png | Bin 9294 -> 0 bytes golden/simple/blend_and_mask.png | Bin 6005 -> 0 bytes golden/simple/blend_mode_devil.png | Bin 24137 -> 0 bytes golden/simple/clip_path.png | Bin 2618 -> 0 bytes golden/simple/clip_path_2.png | Bin 2271 -> 0 bytes golden/simple/clip_path_3.png | Bin 2691 -> 0 bytes golden/simple/clip_path_transform.png | Bin 5307 -> 0 bytes golden/simple/dash_path.png | Bin 794 -> 0 bytes golden/simple/dash_zero.png | Bin 775 -> 0 bytes golden/simple/ellipse.png | Bin 3847 -> 0 bytes golden/simple/empty_defs.png | Bin 492 -> 0 bytes golden/simple/empty_group.png | Bin 4013 -> 0 bytes golden/simple/equation.png | Bin 3060 -> 0 bytes golden/simple/fill-rule-inherit.png | Bin 5300 -> 0 bytes golden/simple/fill_inheritence_test.png | Bin 588 -> 0 bytes golden/simple/group_composite_opacity.png | Bin 6635 -> 0 bytes golden/simple/group_fill_opacity.png | Bin 5155 -> 0 bytes golden/simple/group_in_defs.png | Bin 1717 -> 0 bytes golden/simple/group_mask.png | Bin 2146 -> 0 bytes golden/simple/group_opacity.png | Bin 3772 -> 0 bytes golden/simple/group_opacity_transform.png | Bin 749 -> 0 bytes golden/simple/hidden.png | Bin 1960 -> 0 bytes golden/simple/href-fill.png | Bin 2021 -> 0 bytes golden/simple/image.png | Bin 695 -> 0 bytes golden/simple/image_def.png | Bin 1193 -> 0 bytes .../image_transform_before_translate.png | Bin 675 -> 0 bytes golden/simple/implicit_fill_with_opacity.png | Bin 699 -> 0 bytes golden/simple/invalid_dash_array.png | Bin 2732 -> 0 bytes golden/simple/linear_gradient.png | Bin 1838 -> 0 bytes golden/simple/linear_gradient_2.png | Bin 763 -> 0 bytes ...gradient_absolute_user_space_translate.png | Bin 5718 -> 0 bytes ...gradient_percentage_bounding_translate.png | Bin 2046 -> 0 bytes ...adient_percentage_user_space_translate.png | Bin 2083 -> 0 bytes golden/simple/linear_gradient_xlink.png | Bin 4748 -> 0 bytes golden/simple/male.png | Bin 4057 -> 0 bytes golden/simple/mask.png | Bin 4953 -> 0 bytes golden/simple/mask_with_gradient.png | Bin 648 -> 0 bytes golden/simple/mask_with_use.png | Bin 633 -> 0 bytes golden/simple/mask_with_use2.png | Bin 1368 -> 0 bytes golden/simple/nested_group.png | Bin 4013 -> 0 bytes golden/simple/opacity_on_path.png | Bin 1443 -> 0 bytes golden/simple/radial_gradient.png | Bin 3267 -> 0 bytes ...gradient_absolute_user_space_translate.png | Bin 13507 -> 0 bytes golden/simple/radial_gradient_focal.png | Bin 12308 -> 0 bytes ...gradient_percentage_bounding_translate.png | Bin 7056 -> 0 bytes ...adient_percentage_user_space_translate.png | Bin 13092 -> 0 bytes golden/simple/radial_gradient_xlink.png | Bin 3267 -> 0 bytes golden/simple/radial_ref_linear_gradient.png | Bin 7808 -> 0 bytes golden/simple/rect_rrect.png | Bin 2594 -> 0 bytes golden/simple/rect_rrect_no_ry.png | Bin 1731 -> 0 bytes golden/simple/stroke_inherit_circles.png | Bin 5710 -> 0 bytes golden/simple/style_attr.png | Bin 1085 -> 0 bytes golden/simple/text.png | Bin 457 -> 0 bytes golden/simple/text_2.png | Bin 892 -> 0 bytes golden/simple/text_3.png | Bin 431 -> 0 bytes golden/simple/text_4.png | Bin 1022 -> 0 bytes golden/simple/text_5.png | Bin 563 -> 0 bytes golden/simple/text_6.png | Bin 692 -> 0 bytes golden/simple/use_circles.png | Bin 2496 -> 0 bytes golden/simple/use_circles_def.png | Bin 1975 -> 0 bytes golden/simple/use_emc2.png | Bin 2494 -> 0 bytes golden/simple/use_fill.png | Bin 873 -> 0 bytes golden/simple/use_fill_test.png | Bin 718 -> 0 bytes golden/simple/use_opacity_grid.png | Bin 957 -> 0 bytes golden/simple/width_height_viewbox.png | Bin 2213 -> 0 bytes golden/simple/zero_width_strokes.png | Bin 619 -> 0 bytes golden/svg_currentcolor.png | Bin 4192 -> 0 bytes golden/text_transform.png | Bin 3457 -> 0 bytes golden/w3samples/aa.png | Bin 4862 -> 0 bytes golden/w3samples/alphachannel.png | Bin 4920 -> 0 bytes golden/wikimedia/Firefox_Logo_2017.png | Bin 23087 -> 0 bytes .../wikimedia/Flag_of_the_United_States.png | Bin 2379 -> 0 bytes golden/wikimedia/Ghostscript_Tiger.png | Bin 39026 -> 0 bytes golden/wikimedia/chess_knight.png | Bin 4744 -> 0 bytes lib/avd.dart | 348 --- lib/flutter_svg.dart | 5 - lib/parser.dart | 29 - lib/src/avd/xml_parsers.dart | 273 --- lib/src/avd_parser.dart | 74 - lib/src/{picture_cache.dart => cache.dart} | 60 +- lib/src/loaders.dart | 287 +++ lib/src/picture_provider.dart | 982 --------- lib/src/picture_stream.dart | 442 ---- lib/src/render_picture.dart | 291 --- lib/src/svg/default_theme.dart | 41 - lib/src/svg/parser_state.dart | 1960 ----------------- lib/src/svg/parsers.dart | 220 -- lib/src/svg/theme.dart | 50 - lib/src/utilities/_compute_io.dart | 8 + lib/src/utilities/_compute_none.dart | 2 + lib/src/utilities/_file_none.dart | 3 + lib/src/utilities/compute.dart | 24 + lib/src/vector_drawable.dart | 1367 ------------ lib/svg.dart | 645 +----- pubspec.yaml | 20 +- test/cache_test.dart | 80 + test/colors_svg_test.dart | 55 - test/default_theme_test.dart | 214 -- test/error_test.dart | 37 - test/golden_svg_test.dart | 56 - test/golden_widget/circle.em_ex.png | Bin 10223 -> 10224 bytes test/golden_widget/circle.em_ex2.png | Bin 0 -> 10224 bytes test/golden_widget/columns_and_rows.png | Bin 25764 -> 25790 bytes test/golden_widget/ellipse.em_ex.png | Bin 6672 -> 6534 bytes test/golden_widget/ellipse.em_ex2.png | Bin 0 -> 6534 bytes test/golden_widget/flutter_logo.asset.png | Bin 10330 -> 10275 bytes test/golden_widget/flutter_logo.memory.png | Bin 10330 -> 10275 bytes test/golden_widget/flutter_logo.natural.png | Bin 25892 -> 25928 bytes test/golden_widget/flutter_logo.network.png | Bin 10330 -> 10275 bytes ...go.string.color_filter.blendmode_color.png | Bin 9168 -> 9344 bytes .../flutter_logo.string.color_filter.png | Bin 7618 -> 7599 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3404 -> 3389 bytes test/golden_widget/flutter_logo.string.png | Bin 10330 -> 10275 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3490 -> 3389 bytes test/golden_widget/line.em_ex2.png | Bin 0 -> 6500 bytes test/golden_widget/rect.em_ex.png | Bin 4071 -> 4070 bytes test/golden_widget/rect.em_ex2.png | Bin 0 -> 4070 bytes .../stick_figure.withclipping.png | Bin 20023 -> 20024 bytes test/loaders_test.dart | 31 + test/picture_cache_test.dart | 219 -- test/picture_provider_test.dart | 199 -- test/picture_stream_test.dart | 134 -- test/render_picture_test.dart | 59 - test/svg_parsers_test.dart | 1203 ---------- test/theme_test.dart | 88 - test/vector_drawable_test.dart | 150 -- test/widget_svg_test.dart | 372 +--- test/xml_svg_test.dart | 435 ---- tool/gen_golden.dart | 86 - vector_graphics.md | 169 ++ 166 files changed, 919 insertions(+), 10127 deletions(-) delete mode 100644 .cirrus.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 example/ios/Flutter/Flutter.podspec delete mode 100644 example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 golden/dart.png delete mode 100644 golden/deborah_ufw/new-action-expander.png delete mode 100644 golden/deborah_ufw/new-camera.png delete mode 100644 golden/deborah_ufw/new-gif-button.png delete mode 100644 golden/deborah_ufw/new-gif.png delete mode 100644 golden/deborah_ufw/new-image.png delete mode 100644 golden/deborah_ufw/new-mention.png delete mode 100644 golden/deborah_ufw/new-pause-button.png delete mode 100644 golden/deborah_ufw/new-play-button.png delete mode 100644 golden/deborah_ufw/new-send-circle.png delete mode 100644 golden/deborah_ufw/numeric_25.png delete mode 100644 golden/flutter_logo.png delete mode 100644 golden/noto-emoji/emoji_u1f600.png delete mode 100644 golden/simple/blend_and_mask.png delete mode 100644 golden/simple/blend_mode_devil.png delete mode 100644 golden/simple/clip_path.png delete mode 100644 golden/simple/clip_path_2.png delete mode 100644 golden/simple/clip_path_3.png delete mode 100644 golden/simple/clip_path_transform.png delete mode 100644 golden/simple/dash_path.png delete mode 100644 golden/simple/dash_zero.png delete mode 100644 golden/simple/ellipse.png delete mode 100644 golden/simple/empty_defs.png delete mode 100644 golden/simple/empty_group.png delete mode 100644 golden/simple/equation.png delete mode 100644 golden/simple/fill-rule-inherit.png delete mode 100644 golden/simple/fill_inheritence_test.png delete mode 100644 golden/simple/group_composite_opacity.png delete mode 100644 golden/simple/group_fill_opacity.png delete mode 100644 golden/simple/group_in_defs.png delete mode 100644 golden/simple/group_mask.png delete mode 100644 golden/simple/group_opacity.png delete mode 100644 golden/simple/group_opacity_transform.png delete mode 100644 golden/simple/hidden.png delete mode 100644 golden/simple/href-fill.png delete mode 100644 golden/simple/image.png delete mode 100644 golden/simple/image_def.png delete mode 100644 golden/simple/image_transform_before_translate.png delete mode 100644 golden/simple/implicit_fill_with_opacity.png delete mode 100644 golden/simple/invalid_dash_array.png delete mode 100644 golden/simple/linear_gradient.png delete mode 100644 golden/simple/linear_gradient_2.png delete mode 100644 golden/simple/linear_gradient_absolute_user_space_translate.png delete mode 100644 golden/simple/linear_gradient_percentage_bounding_translate.png delete mode 100644 golden/simple/linear_gradient_percentage_user_space_translate.png delete mode 100644 golden/simple/linear_gradient_xlink.png delete mode 100644 golden/simple/male.png delete mode 100644 golden/simple/mask.png delete mode 100644 golden/simple/mask_with_gradient.png delete mode 100644 golden/simple/mask_with_use.png delete mode 100644 golden/simple/mask_with_use2.png delete mode 100644 golden/simple/nested_group.png delete mode 100644 golden/simple/opacity_on_path.png delete mode 100644 golden/simple/radial_gradient.png delete mode 100644 golden/simple/radial_gradient_absolute_user_space_translate.png delete mode 100644 golden/simple/radial_gradient_focal.png delete mode 100644 golden/simple/radial_gradient_percentage_bounding_translate.png delete mode 100644 golden/simple/radial_gradient_percentage_user_space_translate.png delete mode 100644 golden/simple/radial_gradient_xlink.png delete mode 100644 golden/simple/radial_ref_linear_gradient.png delete mode 100644 golden/simple/rect_rrect.png delete mode 100644 golden/simple/rect_rrect_no_ry.png delete mode 100644 golden/simple/stroke_inherit_circles.png delete mode 100644 golden/simple/style_attr.png delete mode 100644 golden/simple/text.png delete mode 100644 golden/simple/text_2.png delete mode 100644 golden/simple/text_3.png delete mode 100644 golden/simple/text_4.png delete mode 100644 golden/simple/text_5.png delete mode 100644 golden/simple/text_6.png delete mode 100644 golden/simple/use_circles.png delete mode 100644 golden/simple/use_circles_def.png delete mode 100644 golden/simple/use_emc2.png delete mode 100644 golden/simple/use_fill.png delete mode 100644 golden/simple/use_fill_test.png delete mode 100644 golden/simple/use_opacity_grid.png delete mode 100644 golden/simple/width_height_viewbox.png delete mode 100644 golden/simple/zero_width_strokes.png delete mode 100644 golden/svg_currentcolor.png delete mode 100644 golden/text_transform.png delete mode 100644 golden/w3samples/aa.png delete mode 100644 golden/w3samples/alphachannel.png delete mode 100644 golden/wikimedia/Firefox_Logo_2017.png delete mode 100644 golden/wikimedia/Flag_of_the_United_States.png delete mode 100644 golden/wikimedia/Ghostscript_Tiger.png delete mode 100644 golden/wikimedia/chess_knight.png delete mode 100644 lib/avd.dart delete mode 100644 lib/parser.dart delete mode 100644 lib/src/avd/xml_parsers.dart delete mode 100644 lib/src/avd_parser.dart rename lib/src/{picture_cache.dart => cache.dart} (69%) create mode 100644 lib/src/loaders.dart delete mode 100644 lib/src/picture_provider.dart delete mode 100644 lib/src/picture_stream.dart delete mode 100644 lib/src/render_picture.dart delete mode 100644 lib/src/svg/default_theme.dart delete mode 100644 lib/src/svg/parser_state.dart delete mode 100644 lib/src/svg/parsers.dart delete mode 100644 lib/src/svg/theme.dart create mode 100644 lib/src/utilities/_compute_io.dart create mode 100644 lib/src/utilities/_compute_none.dart create mode 100644 lib/src/utilities/compute.dart delete mode 100644 lib/src/vector_drawable.dart create mode 100644 test/cache_test.dart delete mode 100644 test/colors_svg_test.dart delete mode 100644 test/default_theme_test.dart delete mode 100644 test/error_test.dart delete mode 100644 test/golden_svg_test.dart create mode 100644 test/golden_widget/circle.em_ex2.png create mode 100644 test/golden_widget/ellipse.em_ex2.png create mode 100644 test/golden_widget/line.em_ex2.png create mode 100644 test/golden_widget/rect.em_ex2.png create mode 100644 test/loaders_test.dart delete mode 100644 test/picture_cache_test.dart delete mode 100644 test/picture_provider_test.dart delete mode 100644 test/picture_stream_test.dart delete mode 100644 test/render_picture_test.dart delete mode 100644 test/svg_parsers_test.dart delete mode 100644 test/theme_test.dart delete mode 100644 test/vector_drawable_test.dart delete mode 100644 test/xml_svg_test.dart delete mode 100644 tool/gen_golden.dart create mode 100644 vector_graphics.md diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index dc3e8bab..00000000 --- a/.cirrus.yml +++ /dev/null @@ -1,17 +0,0 @@ -env: - CI_NAME: "CirrusCI" - CI_BUILD_NUMBER: $CIRRUS_TASK_ID - CI_BUILD_URL: "https://cirrus-ci.com/task/$CIRRUS_TASK_ID" - CI_BRANCH: $CIRRUS_BRANCH - CI_PULL_REQUEST: $CIRRUS_PR - COVERALLS_REPO_TOKEN: ENCRYPTED[61ba3fee193a9ed6116e0f61bbe26fe8c0452287e5dfd86c728e2f1f24327818d6c74c956d7b9cbf3bd6236489af0fd1] - -test_task: - container: - matrix: - - image: cirrusci/flutter:beta - - image: cirrusci/flutter:stable - pub_script: flutter pub get - analyze_script: flutter analyze . - test_script: flutter test --coverage - coveralls_script: ./.ci/coveralls.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..dd151b8e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: analyze and test + +on: + push: + branches: [master] + paths-ignore: + - '**/*.md' + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 + with: + channel: 'beta' + - run: flutter --version + - run: flutter pub get + - run: flutter format --set-exit-if-changed . + - run: flutter analyze . + - run: flutter test --coverage + # - uses: romeovs/lcov-reporter-action@v0.2.16 + # with: + # lcov-file: ./packages/vector_graphics_codec/coverage/lcov.info + # github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 910b111e..630117fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # CHANGES +## 2.0.0 + +- Use parsing backend from `vector_graphics_compiler`. + - Out of order defs now supported. + - Patterns supported. + - Many optimizations added. + - **REGRESSION**: Lost support for `dx` and `dy` on `text`. See + https://github.com/dnfield/vector_graphics/issues/44 if this is important to + you. +- Parse SVG data in background isolate by default. +- Use widgets/rendering strategy from `vector_graphics`. +- Much less caching. +- More tests work without special handling - most of parsing is now sync, + and the loaders know how to avoid using `compute` in tests. For SVGs that + contain images, `vg.waitForPendingDecodes` is available. + +**DEPRECATIONS** + +- The `VectorDrawable` classes have gone away. +- The `AvdPicture` and related classes/parser have gone away. +- The `PictureCache` and `PictureStream` classes have gone away. +- The `PicturePovider` class exists only for access to a no-op cache. +- Several static members on `SvgPicture` and the `svg` utility class have gone + away. + ## 1.1.6 - Fix transforms on image tags, clipPaths. diff --git a/README.md b/README.md index b3b63f19..45bf30b7 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,22 @@ # flutter_svg -[![Pub](https://img.shields.io/pub/v/flutter_svg.svg)](https://pub.dartlang.org/packages/flutter_svg) [![Build Status](https://travis-ci.org/dnfield/flutter_svg.svg?branch=master)](https://travis-ci.org/dnfield/flutter_svg) [![Coverage Status](https://coveralls.io/repos/github/dnfield/flutter_svg/badge.svg?branch=master)](https://coveralls.io/github/dnfield/flutter_svg?branch=master) +[![Pub](https://img.shields.io/pub/v/flutter_svg.svg)](https://pub.dartlang.org/packages/flutter_svg) [![Coverage Status](https://coveralls.io/repos/github/dnfield/flutter_svg/badge.svg?branch=master)](https://coveralls.io/github/dnfield/flutter_svg?branch=master) Flutter Logo which can be rendered by this package! -Draw SVG (and _some_ Android VectorDrawable (XML)) files on a Flutter Widget. +Draw SVG files using Flutter. ## Getting Started -This is a Dart-native rendering library. Issues/PRs will be raised in Flutter -and flutter/engine as necessary for features that are not good candidates for -Dart implementations (especially if they're impossible to implement without -engine support). However, not everything that Skia can easily do needs to be -done by Skia; for example, the Path parsing logic here isn't much slower than -doing it in native, and Skia isn't always doing low level GPU accelerated work -where you might think it is (e.g. Dash Paths). - -All of the SVGs in the `assets/` folder (except the text related one(s)) now -have corresponding PNGs in the `golden/` folder that were rendered using -`flutter test tool/gen_golden.dart` and compared against their rendering output -in Chrome. Automated tests will continue to compare these to ensure code changes -do not break known-good renderings. +This package provides a wrapper around Dart implementations of SVG parsing, +including SVG path data. In particular, it provides efficient `BytesLoader` +implementations for [`package:vector_graphics`](https://pub.dev/packages/vector_graphics). +This package is easier to use but not as performant as using the +`vector_graphics` and `vector_graphics_compiler` packages directly. Those +packages allow you to do ahead-of-time compilation and optimization of SVGs, +and offer some more performant rasterization strategies at runtime. Basic usage (to create an SVG rendering widget from an asset): @@ -74,60 +68,33 @@ If you'd like to render the SVG to some other canvas, you can do something like: ```dart import 'package:flutter_svg/flutter_svg.dart'; -final String rawSvg = '''...'''; -final DrawableRoot svgRoot = await svg.fromSvgString(rawSvg, rawSvg); - -// If you only want the final Picture output, just use -final Picture picture = svgRoot.toPicture(); - -// Otherwise, if you want to draw it to a canvas: -// Optional, but probably normally desirable: scale the canvas dimensions to -// the SVG's viewbox -svgRoot.scaleCanvasToViewBox(canvas); - -// Optional, but probably normally desireable: ensure the SVG isn't rendered -// outside of the viewbox bounds -svgRoot.clipCanvasToViewBox(canvas); -// The second parameter is not used -svgRoot.draw(canvas, null); +final String rawSvg = '''...'''; +final PictureInfo pictureInfo = await vg.loadPicture(SvgStringLoader(rawSvg), null); + +canvas.drawPicture(pictureInfo.picture); +pictureInfo.picture.dispose(); ``` The `SvgPicture` helps to automate this logic, and it provides some convenience -wrappers for getting assets from multiple sources and caching the resultant -`Picture`. _It does not render the data to an `Image` at any point_; you -certainly can do that in Flutter, but you then lose some of the benefit of -having a vector format to begin with. +wrappers for getting assets from multiple sources. Unlike the `vector_graphics` +package, this package _does not render the data to an `Image` at any point_. +This carries a performance penalty for some common use cases, but also allows +for more flexibility around scaling. See [main.dart](/../master/example/lib/main.dart) for a complete sample. ## Check SVG compatibility -As not all SVG features are supported by this library (see below), sometimes we have to dynamically -check if an SVG contains any unsupported features resulting in broken images. -You might also want to throw errors in tests, but only warn about them at runtime. -This can be done by using the snippet below: +The SVG parsing implementation is provided by the `vector_graphics_compiler` +package. Compatibility testing can be achieved via the following: -```dart -final SvgParser parser = SvgParser(); -try { - parser.parse(svgString, warningsAsErrors: true); - print('SVG is supported'); -} catch (e) { - print('SVG contains unsupported features'); -} +```sh +# Use the same $VERSION as the version found in flutter_svg's pubspec. +dart pub global activate vector_graphics_compiler $VERSION +dart pub global run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETED --no-optimize-masks --no-optimize-clips --no-optimize-overdraw --no-tessellate ``` -> Note: -> The library currently only detects unsupported elements (like the ` - - - - - - - - - - - - -'''; - final SvgParser parser = SvgParser(); - expect( - parser.parse(svgStr, warningsAsErrors: true), - throwsA(anything), - ); - }); - - test('Warns about unsupported elements by default', () async { - const String svgStr = ''' - - - svg/stick_figure - Created with Sketch. - - - - - - - - - - - - - -'''; - - final SvgParser parser = SvgParser(); - expect(await parser.parse(svgStr), isA()); - }); - - test('Respects whitespace attribute', () async { - const String svgStr = ''' - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse(svgStr); - - expect(find(root, 'preserve-space') != null, true); - // Empty text elements get removed - expect(find(root, 'remove-space') != null, false); - }); - - group('currentColor', () { - group('stroke', () { - test( - 'respects currentColor from SvgTheme ' - 'when no color attribute exists on the parent', () async { - const String svgStr = ''' - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.stroke?.color, - equals(currentColor), - ); - }); - - test( - 'respects currentColor from SvgTheme ' - 'when the parent uses currentColor', () async { - const String svgStr = ''' - - - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.stroke?.color, - equals(currentColor), - ); - }); - - test( - 'respects currentColor from the parent ' - 'when the parent overrides currentColor', () async { - const String svgStr = ''' - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: Color(0xFFB0E3BE), - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.stroke?.color, - equals(const Color(0xffC460B7)), - ); - }); - }); - - group('fill', () { - test( - 'respects currentColor from SvgTheme ' - 'when no color attribute exists on the parent', () async { - const String svgStr = ''' - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.fill?.color, - equals(currentColor), - ); - }); - - test( - 'respects currentColor from SvgTheme ' - 'when the parent uses currentColor', () async { - const String svgStr = ''' - - - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.fill?.color, - equals(currentColor), - ); - }); - - test( - 'respects currentColor from the parent ' - 'when the parent overrides currentColor', () async { - const String svgStr = ''' - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: Color(0xFFB0E3BE), - fontSize: 14.0, - ), - ); - - final DrawableShape? circle = find(root, 'circle'); - - expect(circle, isNotNull); - - expect( - circle!.style.fill?.color, - equals(const Color(0xFFC460B7)), - ); - }); - }); - - group('stop-color', () { - test( - 'respects currentColor from SvgTheme ' - 'when no color attribute exists on the parent', () async { - const String svgStr = ''' - - - - - - - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableLinearGradient? gradient = - root.definitions.getGradient('url(#gradient-1)'); - - expect(gradient, isNotNull); - - expect( - gradient!.colors?[0], - equals(currentColor.withOpacity(0.5)), - ); - - expect( - gradient.colors?[1], - equals(currentColor.withOpacity(0.8)), - ); - }); - - test( - 'respects currentColor from SvgTheme ' - 'when the parent uses currentColor', () async { - const String svgStr = ''' - - - - - - - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ), - ); - - final DrawableLinearGradient? gradient = - root.definitions.getGradient('url(#gradient-1)'); - - expect(gradient, isNotNull); - - expect( - gradient!.colors?[0], - equals(currentColor.withOpacity(0.5)), - ); - - expect( - gradient.colors?[1], - equals(currentColor.withOpacity(0.8)), - ); - }); - - test( - 'respects currentColor from the parent ' - 'when the parent overrides currentColor', () async { - const String svgStr = ''' - - - - - - - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - currentColor: Color(0xFFB0E3BE), - fontSize: 14.0, - ), - ); - - final DrawableLinearGradient? gradient = - root.definitions.getGradient('url(#gradient-1)'); - - expect(gradient, isNotNull); - - expect( - gradient!.colors?[0], - equals(const Color(0xFFC460B7).withOpacity(0.5)), - ); - - expect( - gradient.colors?[1], - equals(const Color(0xFFC460B7).withOpacity(0.8)), - ); - }); - }); - }); - - group('calculates em units based on the font size for', () { - test('svg (width, height)', () async { - const String svgStr = ''' - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - expect(root.viewport.width, equals(fontSize * 5)); - expect(root.viewport.height, equals(fontSize * 6)); - }); - - test('use (x, y)', () async { - const String svgStr = ''' - - - - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - final DrawableGroup? circle = find(root, 'anotherCircle'); - - const double expectedX = fontSize * 2; - const double expectedY = fontSize * 4; - - expect(circle, isNotNull); - expect( - circle!.transform, - equals( - (Matrix4.identity()..translate(expectedX, expectedY)).storage, - ), - ); - }); - - test('text (x, y)', () async { - const String svgStr = ''' - - Test - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - final DrawableText? text = find(root, 'text'); - - const Offset expectedOffset = Offset(fontSize * 2, fontSize * 4); - - expect(text, isNotNull); - expect(text!.offset, equals(expectedOffset)); - }); - - test('radialGradient (cx, cy, r, fx, fy)', () async { - const String svgStr = ''' - - - - - - - - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - final DrawableRadialGradient? gradient = - root.definitions.getGradient('url(#gradient)'); - - expect(gradient, isNotNull); - - const Offset expectedOffset = Offset(fontSize * 1, fontSize * 2); - const double expectedRadius = fontSize * 1.1; - const Offset expectedFocal = Offset(fontSize * 1.5, fontSize * 1.6); - - expect(gradient, isNotNull); - expect(gradient!.center, equals(expectedOffset)); - expect(gradient.radius, equals(expectedRadius)); - expect(gradient.focal, equals(expectedFocal)); - }); - - test('linearGradient (x1, y1, x2, y2)', () async { - const String svgStr = ''' - - - - - - - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - final DrawableLinearGradient? gradient = - root.definitions.getGradient('url(#gradient)'); - - expect(gradient, isNotNull); - - const Offset expectedFromOffset = Offset(fontSize * 1, fontSize * 1.75); - const Offset expectedToOffset = Offset(fontSize * 1.5, fontSize * 1.6); - - expect(gradient, isNotNull); - expect(gradient!.from, equals(expectedFromOffset)); - expect(gradient.to, equals(expectedToOffset)); - }); - - test('image (x, y, width, height)', () async { - const String svgStr = ''' - - - -'''; - - const double fontSize = 26.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - ), - ); - - final DrawableRasterImage? image = - find(root, 'image'); - - const Offset expectedOffset = Offset(fontSize * 1, fontSize * 0.5); - const Size expectedSize = Size(fontSize * 2, fontSize * 1.5); - - expect(image, isNotNull); - expect(image!.offset, equals(expectedOffset)); - expect(image.size, equals(expectedSize)); - }); - }); - - group('calculates ex units based on the x-height for', () { - test('svg (width, height)', () async { - const String svgStr = ''' - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - expect(root.viewport.width, equals(xHeight * 5)); - expect(root.viewport.height, equals(xHeight * 6)); - }); - - test('use (x, y)', () async { - const String svgStr = ''' - - - - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - final DrawableGroup? circle = find(root, 'anotherCircle'); - - const double expectedX = xHeight * 2; - const double expectedY = xHeight * 4; - - expect(circle, isNotNull); - expect( - circle!.transform, - equals( - (Matrix4.identity()..translate(expectedX, expectedY)).storage, - ), - ); - }); - - test('text (x, y)', () async { - const String svgStr = ''' - - Test - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - final DrawableText? text = find(root, 'text'); - - const Offset expectedOffset = Offset(xHeight * 2, xHeight * 4); - - expect(text, isNotNull); - expect(text!.offset, equals(expectedOffset)); - }); - - test('radialGradient (cx, cy, r, fx, fy)', () async { - const String svgStr = ''' - - - - - - - - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - final DrawableRadialGradient? gradient = - root.definitions.getGradient('url(#gradient)'); - - expect(gradient, isNotNull); - - const Offset expectedOffset = Offset(xHeight * 1, xHeight * 2); - const double expectedRadius = xHeight * 1.1; - const Offset expectedFocal = Offset(xHeight * 1.5, xHeight * 1.6); - - expect(gradient, isNotNull); - expect(gradient!.center, equals(expectedOffset)); - expect(gradient.radius, equals(expectedRadius)); - expect(gradient.focal, equals(expectedFocal)); - }); - - test('linearGradient (x1, y1, x2, y2)', () async { - const String svgStr = ''' - - - - - - - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - final DrawableLinearGradient? gradient = - root.definitions.getGradient('url(#gradient)'); - - expect(gradient, isNotNull); - - const Offset expectedFromOffset = Offset(xHeight * 1, xHeight * 1.75); - const Offset expectedToOffset = Offset(xHeight * 1.5, xHeight * 1.6); - - expect(gradient, isNotNull); - expect(gradient!.from, equals(expectedFromOffset)); - expect(gradient.to, equals(expectedToOffset)); - }); - - test('image (x, y, width, height)', () async { - const String svgStr = ''' - - - -'''; - - const double fontSize = 26.0; - const double xHeight = 11.0; - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: const SvgTheme( - fontSize: fontSize, - xHeight: xHeight, - ), - ); - - final DrawableRasterImage? image = - find(root, 'image'); - - const Offset expectedOffset = Offset(xHeight * 1, xHeight * 0.5); - const Size expectedSize = Size(xHeight * 2, xHeight * 1.5); - - expect(image, isNotNull); - expect(image!.offset, equals(expectedOffset)); - expect(image.size, equals(expectedSize)); - }); - }); - - test('Tracks current color', () async { - const String svgStr = ''' - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - const SvgTheme oldTheme = SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ); - - final SvgTheme newTheme = SvgTheme( - currentColor: currentColor.withAlpha(50), - fontSize: 14.0, - ); - - const SvgTheme newTheme2 = SvgTheme( - currentColor: currentColor, - fontSize: 15.0, - ); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: oldTheme, - ); - - expect(root.compatibilityTester.isCompatible(oldTheme, newTheme), false); - expect(root.compatibilityTester.isCompatible(oldTheme, newTheme2), true); - }); - - test('Tracks em/ex', () async { - const String svgStr = ''' - - -'''; - - const Color currentColor = Color(0xFFB0E3BE); - - const SvgTheme oldTheme = SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ); - - final SvgTheme newTheme = SvgTheme( - currentColor: currentColor.withAlpha(50), - fontSize: 14.0, - ); - - const SvgTheme newTheme2 = SvgTheme( - currentColor: currentColor, - fontSize: 15.0, - ); - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse( - svgStr, - theme: oldTheme, - ); - - expect(root.compatibilityTester.isCompatible(oldTheme, newTheme), true); - expect(root.compatibilityTester.isCompatible(oldTheme, newTheme2), false); - }); - - test('Preserves stroke-width when gradient is used', () async { - const String svgStr = ''' - - - - - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse(svgStr); - - expect(root.children.length, 1); - final DrawableShape circle = root.children.first as DrawableShape; - expect(circle.style.stroke!.strokeWidth, 10); - expect(circle.style.stroke!.strokeMiterLimit, 4); - }); - - test('Preserves stroke properties from group with no "stroke"', () async { - const String svgStr = ''' - - - - - - - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse(svgStr); - - expect(root.children.length, 1); - expect(root.children.length, 1); - final DrawableGroup group = root.children.first as DrawableGroup; - final DrawableShape circle = group.children!.first as DrawableShape; - expect(circle.style.stroke!.strokeWidth, 10); - expect(circle.style.stroke!.strokeMiterLimit, 8); - }); - - test('Takes stroke properties from shape when group has them', () async { - const String svgStr = ''' - - - - - - - - - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse(svgStr); - - expect(root.children.length, 1); - expect(root.children.length, 1); - final DrawableGroup group = root.children.first as DrawableGroup; - final DrawableShape circle = group.children!.first as DrawableShape; - expect(circle.style.stroke!.strokeWidth, 5); - expect(circle.style.stroke!.strokeMiterLimit, 8); - }); - - test('Defaults image height/width when not specified', () async { - // 1x1 PNG image from png-pixel.com. - const String svgStr = ''' - - -'''; - - final SvgParser parser = SvgParser(); - final DrawableRoot root = await parser.parse(svgStr); - - expect(root.children.length, 1); - final DrawableRasterImage image = - root.children.first as DrawableRasterImage; - expect(image.size!.width, image.image.width); - expect(image.size!.height, image.image.height); - }); -} diff --git a/test/theme_test.dart b/test/theme_test.dart deleted file mode 100644 index 71b88879..00000000 --- a/test/theme_test.dart +++ /dev/null @@ -1,88 +0,0 @@ -// ignore_for_file: prefer_const_constructors - -import 'package:flutter/material.dart'; -import 'package:flutter_svg/src/svg/theme.dart'; -import 'package:test/test.dart'; - -void main() { - group('SvgTheme', () { - group('constructor', () { - test('sets currentColor', () { - const Color currentColor = Color(0xFFB0E3BE); - - expect( - SvgTheme( - currentColor: currentColor, - fontSize: 14.0, - ).currentColor, - equals(currentColor), - ); - }); - - test('sets fontSize', () { - const double fontSize = 14.0; - - expect( - SvgTheme( - currentColor: Color(0xFFB0E3BE), - fontSize: fontSize, - ).fontSize, - equals(fontSize), - ); - }); - - test( - 'sets fontSize to 14 ' - 'by default', () { - expect( - SvgTheme(), - equals( - SvgTheme(fontSize: 14.0), - ), - ); - }); - - test('sets xHeight', () { - const double xHeight = 8.0; - - expect( - SvgTheme( - fontSize: 26.0, - xHeight: xHeight, - ).xHeight, - equals(xHeight), - ); - }); - - test( - 'sets xHeight as fontSize divided by 2 ' - 'by default', () { - const double fontSize = 16.0; - - expect( - SvgTheme( - fontSize: fontSize, - ).xHeight, - equals(fontSize / 2), - ); - }); - }); - - test('supports value equality', () { - expect( - SvgTheme( - currentColor: Color(0xFF6F2173), - fontSize: 14.0, - xHeight: 6.0, - ), - equals( - SvgTheme( - currentColor: Color(0xFF6F2173), - fontSize: 14.0, - xHeight: 6.0, - ), - ), - ); - }); - }); -} diff --git a/test/vector_drawable_test.dart b/test/vector_drawable_test.dart deleted file mode 100644 index 72a6adf2..00000000 --- a/test/vector_drawable_test.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('DrawableRoot can mergeStyle', () { - const DrawableStyle styleA = DrawableStyle( - groupOpacity: 0.5, - pathFillType: PathFillType.evenOdd, - ); - const DrawableStyle styleB = DrawableStyle( - pathFillType: PathFillType.nonZero, - ); - DrawableRoot root = DrawableRoot( - '', // No id - const DrawableViewport(Size(100, 100), Size(100, 100)), - [], - DrawableDefinitionServer(), - styleA, - ); - expect(root.style!.pathFillType, styleA.pathFillType); - root = root.mergeStyle(styleB); - expect(root.style!.pathFillType, styleB.pathFillType); - }); - - test('SvgPictureDecoder uses color filter properly', () async { - final PictureInfo info = await svg.svgPictureStringDecoder( - ''' - - - -''', - false, - const ColorFilter.mode(Color(0xFF00FF00), BlendMode.color), - 'test', - ); - final Image image = await info.picture!.toImage(2, 2); - final ByteData data = (await image.toByteData())!; - - const List expected = [ - 0, 48, 0, 255, // - 0, 48, 0, 255, - 0, 48, 0, 255, - 0, 48, 0, 255, - ]; - expect(data.buffer.asUint8List(), expected); - }); - - test('SvgPictureDecoder sets isComplexHint', () async { - final PictureInfo info = await svg.svgPictureStringDecoder( - ''' - - - -''', - false, - null, - 'test', - ); - - expect(info.createLayer().isComplexHint, true); - }); - - test('mergeAndBlend gets strokeWidth right', () async { - final DrawableRoot root = await svg.fromSvgString( - ''' - - - -''', - 'test', - ); - - final DrawablePaint strokePaintA = - (root.children.first as DrawableShape).style.stroke!; - final DrawableRoot mergedRoot = root.mergeStyle( - const DrawableStyle( - stroke: DrawablePaint( - PaintingStyle.stroke, - color: Color(0xFFABCDEF), - ), - ), - ); - - final DrawablePaint strokePaintB = - (mergedRoot.children.first as DrawableShape).style.stroke!; - expect(strokePaintA.strokeWidth, strokePaintB.strokeWidth); - }); - - test('restore canvas accordingly', () async { - const String svgWithViewBox = ''' - - - -'''; - - final PictureRecorder recorder = PictureRecorder(); - final Canvas canvas = Canvas(recorder); - - canvas.save(); - - final DrawableRoot svgRoot = await svg.fromSvgString( - svgWithViewBox, - 'RestoreCanvasWithSvgViewBox', - ); - - svgRoot.scaleCanvasToViewBox(canvas, const Size.square(200)); - svgRoot.clipCanvasToViewBox(canvas); - - svgRoot.draw(canvas, svgRoot.viewport.viewBoxRect); - - expect(canvas.getSaveCount(), equals(2)); - - recorder.endRecording(); - }); - - test('Does not draw if color is null', () async { - final DrawableShape shape = DrawableShape( - 'test', - Path()..addRect(const Rect.fromLTRB(0, 0, 50, 50)), - const DrawableStyle( - fill: DrawablePaint(PaintingStyle.fill), - stroke: DrawablePaint(PaintingStyle.stroke), - ), - ); - - final PathRecordingCanvas canvas = PathRecordingCanvas(); - shape.draw(canvas, Rect.largest); - - expect(canvas.paths.length, 0); - expect(canvas.paints.length, 0); - }); -} - -class PathRecordingCanvas implements Canvas { - final List paths = []; - final List paints = []; - - @override - dynamic noSuchMethod(Invocation invocation) { - if (invocation.memberName == #drawPath) { - paths.add(invocation.positionalArguments.first as Path); - paints.add(invocation.positionalArguments.last as Paint); - return; - } - return super.noSuchMethod(invocation); - } -} diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index c9722652..35023413 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -1,10 +1,9 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'dart:typed_data'; import 'dart:ui' show window; -import 'package:flutter/rendering.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -55,8 +54,6 @@ void main() { }); setUp(() { - PictureProvider.cache.clear(); - svg.cacheColorFilterOverride = null; fakeResponse = FakeHttpClientResponse(); fakeRequest = FakeHttpClientRequest(fakeResponse); fakeHttpClient = FakeHttpClient(fakeRequest); @@ -65,7 +62,6 @@ void main() { testWidgets( 'SvgPicture does not use a color filtering widget when no color specified', (WidgetTester tester) async { - expect(PictureProvider.cache.count, 0); await tester.pumpWidget( SvgPicture.string( svgStr, @@ -74,91 +70,8 @@ void main() { ), ); await tester.pumpAndSettle(); - expect(PictureProvider.cache.count, 1); - expect(find.byType(ColorFiltered), findsNothing); - }); - - testWidgets('SvgPicture does not invalidate the cache when color changes', - (WidgetTester tester) async { - expect(PictureProvider.cache.count, 0); - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990000), - ), - ); - - expect(PictureProvider.cache.count, 1); - - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990099), - ), - ); - - expect(PictureProvider.cache.count, 1); - }); - - testWidgets( - 'SvgPicture does invalidate the cache when color changes and color filter is cached', - (WidgetTester tester) async { - expect(PictureProvider.cache.count, 0); - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990000), - cacheColorFilter: true, - ), - ); - - expect(PictureProvider.cache.count, 1); - - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990099), - cacheColorFilter: true, - ), - ); - - expect(PictureProvider.cache.count, 2); - }); - - testWidgets( - 'SvgPicture does invalidate the cache when color changes and color filter is cached (override)', - (WidgetTester tester) async { - svg.cacheColorFilterOverride = true; - expect(PictureProvider.cache.count, 0); - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990000), - ), - ); - expect(PictureProvider.cache.count, 1); - - await tester.pumpWidget( - SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - color: const Color(0xFF990099), - ), - ); - - expect(PictureProvider.cache.count, 2); + expect(find.byType(ColorFiltered), findsNothing); }); testWidgets('SvgPicture can work with a FittedBox', @@ -532,7 +445,10 @@ void main() { svgStr, width: 100.0, height: 100.0, - color: const Color(0xFF990000), + colorFilter: const ColorFilter.mode( + Color(0xFF990000), + BlendMode.srcIn, + ), ), ), ); @@ -551,8 +467,10 @@ void main() { svgStr, width: 100.0, height: 100.0, - color: const Color(0xFF990000), - colorBlendMode: BlendMode.color, + colorFilter: const ColorFilter.mode( + Color(0xFF990000), + BlendMode.color, + ), ), ), ); @@ -585,7 +503,10 @@ void main() { svgData, width: 100.0, height: 100.0, - color: const Color(0xFF990000), + colorFilter: const ColorFilter.mode( + Color(0xFF990000), + BlendMode.srcIn, + ), ), ), ); @@ -594,15 +515,6 @@ void main() { await _checkWidgetAndGolden(key, 'text_color_filter.png'); }); - testWidgets('Nested SVG elements report a FlutterError', - (WidgetTester tester) async { - await svg.fromSvgString( - '', - 'test'); - final UnsupportedError error = tester.takeException() as UnsupportedError; - expect(error.message, 'Unsupported nested element.'); - }); - testWidgets('Can take AlignmentDirectional', (WidgetTester tester) async { await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -614,142 +526,6 @@ void main() { expect(find.byType(SvgPicture), findsOneWidget); }); - testWidgets('SvgPicture.string respects clipBehavior', - (WidgetTester tester) async { - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.string(svgStr), - )); - await tester.pumpAndSettle(); - - // Check that the render object has received the default clip behavior. - final RenderFittedBox renderObject = - tester.allRenderObjects.whereType().first; - expect(renderObject.clipBehavior, equals(Clip.hardEdge)); - - // Pump a new widget to check that the render object can update its clip - // behavior. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.string(svgStr, clipBehavior: Clip.antiAlias), - ), - ); - await tester.pumpAndSettle(); - expect(renderObject.clipBehavior, equals(Clip.antiAlias)); - }); - - testWidgets('SvgPicture.asset respects clipBehavior', - (WidgetTester tester) async { - final FakeAssetBundle fakeAsset = FakeAssetBundle(); - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.asset( - 'test.svg', - bundle: fakeAsset, - ), - )); - await tester.pumpAndSettle(); - - // Check that the render object has received the default clip behavior. - final RenderFittedBox renderObject = - tester.allRenderObjects.whereType().first; - expect(renderObject.clipBehavior, equals(Clip.hardEdge)); - - // Pump a new widget to check that the render object can update its clip - // behavior. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.asset( - 'test.svg', - bundle: fakeAsset, - clipBehavior: Clip.antiAlias, - ), - ), - ); - await tester.pumpAndSettle(); - expect(renderObject.clipBehavior, equals(Clip.antiAlias)); - }); - - testWidgets('SvgPicture.memory respects clipBehavior', - (WidgetTester tester) async { - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.memory(svgBytes), - )); - await tester.pumpAndSettle(); - - // Check that the render object has received the default clip behavior. - final RenderFittedBox renderObject = - tester.allRenderObjects.whereType().first; - expect(renderObject.clipBehavior, equals(Clip.hardEdge)); - - // Pump a new widget to check that the render object can update its clip - // behavior. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.memory(svgBytes, clipBehavior: Clip.antiAlias), - ), - ); - await tester.pumpAndSettle(); - expect(renderObject.clipBehavior, equals(Clip.antiAlias)); - }); - - testWidgets('SvgPicture.network respects clipBehavior', - (WidgetTester tester) async { - await HttpOverrides.runZoned(() async { - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.network('test.svg'), - ), - ); - await tester.pumpAndSettle(); - - // Check that the render object has received the default clip behavior. - final RenderFittedBox renderObject = - tester.allRenderObjects.whereType().first; - expect(renderObject.clipBehavior, equals(Clip.hardEdge)); - - // Pump a new widget to check that the render object can update its clip - // behavior. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.network('test.svg', clipBehavior: Clip.antiAlias), - ), - ); - await tester.pumpAndSettle(); - expect(renderObject.clipBehavior, equals(Clip.antiAlias)); - }, createHttpClient: (SecurityContext? c) => fakeHttpClient); - }); - - testWidgets('SvgPicture respects clipBehavior', (WidgetTester tester) async { - await tester.pumpWidget(Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.string(svgStr), - )); - await tester.pumpAndSettle(); - - // Check that the render object has received the default clip behavior. - final RenderFittedBox renderObject = - tester.allRenderObjects.whereType().first; - expect(renderObject.clipBehavior, equals(Clip.hardEdge)); - - // Pump a new widget to check that the render object can update its clip - // behavior. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.string(svgStr, clipBehavior: Clip.antiAlias), - ), - ); - await tester.pumpAndSettle(); - expect(renderObject.clipBehavior, equals(Clip.antiAlias)); - }); - group('SvgPicture respects em units', () { testWidgets('circle (cx, cy, r)', (WidgetTester tester) async { final GlobalKey key = GlobalKey(); @@ -870,7 +646,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'circle.em_ex.png'); + await _checkWidgetAndGolden(key, 'circle.em_ex2.png'); }); testWidgets('rect (x, y, width, height, rx, ry)', @@ -897,7 +673,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'rect.em_ex.png'); + await _checkWidgetAndGolden(key, 'rect.em_ex2.png'); }); testWidgets('ellipse (cx, cy, rx, ry)', (WidgetTester tester) async { @@ -923,7 +699,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'ellipse.em_ex.png'); + await _checkWidgetAndGolden(key, 'ellipse.em_ex2.png'); }); testWidgets('line (x1, y1, x2, y2)', (WidgetTester tester) async { @@ -950,7 +726,7 @@ void main() { ); await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'line.em_ex.png'); + await _checkWidgetAndGolden(key, 'line.em_ex2.png'); }); }); @@ -974,113 +750,6 @@ void main() { matchesGoldenFile('golden_widget/two_of_same.png'), ); }); - - testWidgets( - 'Update widget without a cache does not result in an disposed picture', - (WidgetTester tester) async { - final int oldCacheSize = PictureProvider.cache.maximumSize; - PictureProvider.cache.maximumSize = 0; - final GlobalKey key = GlobalKey(); - - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture( - FakePictureProvider( - SvgPicture.svgStringDecoderBuilder, - simpleSvg, - ), - key: key), - ), - ); - - expect(find.byKey(key), findsOneWidget); - - // Update the widget with a new incompatible key. - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture( - FakePictureProvider( - SvgPicture.svgStringDecoderBuilder, - stickFigureSvgStr, - ), - key: key), - ), - ); - - expect(find.byKey(key), findsOneWidget); - await tester.pumpAndSettle(); - PictureProvider.cache.maximumSize = oldCacheSize; - }); - - testWidgets('state maintains a handle', (WidgetTester tester) async { - final int oldCacheSize = PictureProvider.cache.maximumSize; - PictureProvider.cache.maximumSize = 1; - final GlobalKey key = GlobalKey(); - final FakePictureProvider provider = FakePictureProvider( - SvgPicture.svgStringDecoderBuilder, - simpleSvg, - ); - - final PictureStream stream = provider.resolve( - createLocalPictureConfiguration(key.currentContext), - ); - final Completer completer = Completer(); - void listener(PictureInfo? info, bool syncCall) { - completer.complete(info!); - } - - stream.addListener(listener); - - final PictureInfo info = await completer.future; - expect(info.debugHandleCount, 1); - stream.removeListener(listener); - // Still in cache. - expect(info.debugHandleCount, 1); - - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture(provider, key: key), - ), - ); - expect(find.byKey(key), findsOneWidget); - expect(info.debugHandleCount, 3); - PictureProvider.cache.clear(); - expect(info.debugHandleCount, 3); - - await tester.pumpWidget(const SizedBox.shrink()); - expect(info.debugHandleCount, 0); - - PictureProvider.cache.maximumSize = oldCacheSize; - }); -} - -class FakePictureProvider extends StringPicture { - FakePictureProvider( - PictureInfoDecoderBuilder decoderBuilder, - String string, - ) : super(decoderBuilder, string); - - int resolveCount = 0; - - @override - PictureStream resolve( - PictureConfiguration picture, { - PictureErrorListener? onError, - }) { - resolveCount += 1; - return super.resolve(picture, onError: onError); - } - - @override - // ignore: hash_and_equals, avoid_equals_and_hash_code_on_mutable_classes - bool operator ==(Object other) { - // Picture providers should be compared based on key. Make sure tests don't - // cheat this check by using an identical provider. - return false; - } } class FakeAssetBundle extends Fake implements AssetBundle { @@ -1088,6 +757,11 @@ class FakeAssetBundle extends Fake implements AssetBundle { Future loadString(String key, {bool cache = true}) async { return svgStr; } + + @override + Future load(String key) async { + return Uint8List.fromList(utf8.encode(svgStr)).buffer.asByteData(); + } } class FakeHttpClient extends Fake implements HttpClient { diff --git a/test/xml_svg_test.dart b/test/xml_svg_test.dart deleted file mode 100644 index 2d8992cb..00000000 --- a/test/xml_svg_test.dart +++ /dev/null @@ -1,435 +0,0 @@ -import 'dart:ui'; - -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter_svg/src/svg/parser_state.dart'; -import 'package:flutter_svg/src/utilities/xml.dart'; -import 'package:path_drawing/path_drawing.dart'; -import 'package:test/test.dart'; -import 'package:xml/xml_events.dart'; - -class TestSvgParserState extends SvgParserState { - TestSvgParserState({double fontSize = 14, double? xHeight}) - : super( - [], - SvgTheme(fontSize: fontSize, xHeight: xHeight), - 'testKey', - false, - ); - - @override - late Map attributes; -} - -void main() { - test('Xlink href tests', () { - final XmlStartElementEvent el = - parseEvents('').first - as XmlStartElementEvent; - - final XmlStartElementEvent elXlink = - parseEvents('') - .first as XmlStartElementEvent; - - expect( - getHrefAttribute(el.attributes.toAttributeMap()), 'http://localhost'); - expect(getHrefAttribute(elXlink.attributes.toAttributeMap()), - 'http://localhost'); - }); - - test('Attribute and style tests', () { - final XmlStartElementEvent el = - parseEvents('') - .first as XmlStartElementEvent; - - final Map attributes = el.attributes.toAttributeMap(); - expect(getAttribute(attributes, 'stroke'), '#fff'); - expect(getAttribute(attributes, 'fill'), '#eee'); - expect(getAttribute(attributes, 'stroke-dashpattern'), '1 2'); - expect(getAttribute(attributes, 'stroke-opacity'), '1'); - expect(getAttribute(attributes, 'stroke-another'), ''); - expect(getAttribute(attributes, 'fill-opacity'), '.23'); - - expect(getAttribute(attributes, 'fill-opacity', checkStyle: false), ''); - expect(getAttribute(attributes, 'fill', checkStyle: false), '#eee'); - }); - - // if the parsing logic changes, we can simplify some methods. for now assert that whitespace in attributes is preserved - test('Attribute WhiteSpace test', () { - final XmlStartElementEvent xd = - parseEvents('').first - as XmlStartElementEvent; - - expect( - xd.attributes[0].value, - ' asdf', - reason: - 'XML Parsing implementation no longer preserves leading whitespace in attributes!', - ); - expect( - xd.attributes[1].value, - 'asdf ', - reason: - 'XML Parsing implementation no longer preserves trailing whitespace in attributes!', - ); - }); - - test('viewBox tests', () { - const Rect rect = Rect.fromLTWH(0.0, 0.0, 100.0, 100.0); - - final XmlStartElementEvent svgWithViewBox = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent svgWithViewBoxAndWidthHeight = - parseEvents('') - .first as XmlStartElementEvent; - final XmlStartElementEvent svgWithWidthHeight = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent svgWithViewBoxMinXMinY = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent svgWithNoSizeInfo = - parseEvents('').first as XmlStartElementEvent; - - final TestSvgParserState parserState = TestSvgParserState(); - - parserState.attributes = - svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.size, const Size(50, 50)); - - parserState.attributes = svgWithViewBox.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.viewBoxRect, rect); - - parserState.attributes = svgWithViewBox.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.viewBoxOffset, Offset.zero); - - parserState.attributes = - svgWithViewBoxAndWidthHeight.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.viewBoxRect, rect); - - parserState.attributes = svgWithWidthHeight.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.viewBoxRect, rect); - - parserState.attributes = svgWithNoSizeInfo.attributes.toAttributeMap(); - expect(parserState.parseViewBox(nullOk: true), null); - - parserState.attributes = svgWithNoSizeInfo.attributes.toAttributeMap(); - expect(() => parserState.parseViewBox(), throwsStateError); - - parserState.attributes = svgWithViewBoxMinXMinY.attributes.toAttributeMap(); - expect(parserState.parseViewBox()!.viewBoxRect, rect); - - parserState.attributes = svgWithViewBoxMinXMinY.attributes.toAttributeMap(); - expect( - parserState.parseViewBox()!.viewBoxOffset, - const Offset(-42.0, -56.0), - ); - }); - - test('TileMode tests', () { - final XmlStartElementEvent pad = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent reflect = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent repeat = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent invalid = - parseEvents('').first - as XmlStartElementEvent; - - final XmlStartElementEvent none = - parseEvents('').first as XmlStartElementEvent; - - final TestSvgParserState parserState = TestSvgParserState(); - parserState.attributes = pad.attributes.toAttributeMap(); - expect(parserState.parseTileMode(), TileMode.clamp); - - parserState.attributes = invalid.attributes.toAttributeMap(); - expect(parserState.parseTileMode(), TileMode.clamp); - - parserState.attributes = none.attributes.toAttributeMap(); - expect(parserState.parseTileMode(), TileMode.clamp); - - parserState.attributes = reflect.attributes.toAttributeMap(); - expect(parserState.parseTileMode(), TileMode.mirror); - - parserState.attributes = repeat.attributes.toAttributeMap(); - expect(parserState.parseTileMode(), TileMode.repeated); - }); - - test('@stroke-dashoffset tests', () { - final XmlStartElementEvent abs = - parseEvents('').first - as XmlStartElementEvent; - final XmlStartElementEvent pct = - parseEvents('').first - as XmlStartElementEvent; - - final TestSvgParserState parserState = TestSvgParserState(); - parserState.attributes = abs.attributes.toAttributeMap(); - expect( - parserState.parseDashOffset(), - equals(const DashOffset.absolute(20.0)), - ); - - parserState.attributes = pct.attributes.toAttributeMap(); - expect( - parserState.parseDashOffset(), - equals(DashOffset.percentage(0.2)), - ); - }); - - test('font-weight tests', () { - final TestSvgParserState parserState = TestSvgParserState(); - expect(parserState.parseFontWeight('100'), FontWeight.w100); - expect(parserState.parseFontWeight('200'), FontWeight.w200); - expect(parserState.parseFontWeight('300'), FontWeight.w300); - expect(parserState.parseFontWeight('400'), FontWeight.w400); - expect(parserState.parseFontWeight('500'), FontWeight.w500); - expect(parserState.parseFontWeight('600'), FontWeight.w600); - expect(parserState.parseFontWeight('700'), FontWeight.w700); - expect(parserState.parseFontWeight('800'), FontWeight.w800); - expect(parserState.parseFontWeight('900'), FontWeight.w900); - - expect(parserState.parseFontWeight('normal'), FontWeight.normal); - expect(parserState.parseFontWeight('bold'), FontWeight.bold); - - expect( - () => parserState.parseFontWeight('invalid'), throwsUnsupportedError); - }); - - test('font-style tests', () { - final TestSvgParserState parserState = TestSvgParserState(); - expect(parserState.parseFontStyle('normal'), FontStyle.normal); - expect(parserState.parseFontStyle('italic'), FontStyle.italic); - expect(parserState.parseFontStyle('oblique'), FontStyle.italic); - - expect(parserState.parseFontStyle(null), isNull); - expect(() => parserState.parseFontStyle('invalid'), throwsUnsupportedError); - }); - - test('text-decoration tests', () { - final TestSvgParserState parserState = TestSvgParserState(); - expect(parserState.parseTextDecoration('none'), TextDecoration.none); - expect(parserState.parseTextDecoration('line-through'), - TextDecoration.lineThrough); - expect( - parserState.parseTextDecoration('overline'), TextDecoration.overline); - expect( - parserState.parseTextDecoration('underline'), TextDecoration.underline); - - expect(parserState.parseTextDecoration(null), isNull); - expect(() => parserState.parseTextDecoration('invalid'), - throwsUnsupportedError); - }); - - test('text-decoration-style tests', () { - final TestSvgParserState parserState = TestSvgParserState(); - expect(parserState.parseTextDecorationStyle('solid'), - TextDecorationStyle.solid); - expect(parserState.parseTextDecorationStyle('dashed'), - TextDecorationStyle.dashed); - expect(parserState.parseTextDecorationStyle('dotted'), - TextDecorationStyle.dotted); - expect(parserState.parseTextDecorationStyle('double'), - TextDecorationStyle.double); - expect( - parserState.parseTextDecorationStyle('wavy'), TextDecorationStyle.wavy); - - expect(parserState.parseTextDecorationStyle(null), isNull); - expect(() => parserState.parseTextDecorationStyle('invalid'), - throwsUnsupportedError); - }); - - group('parseStyle', () { - test('uses currentColor for stroke color', () { - const Color currentColor = Color(0xFFB0E3BE); - final XmlStartElementEvent svg = - parseEvents('').first - as XmlStartElementEvent; - - final TestSvgParserState parserState = TestSvgParserState(); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle( - Rect.zero, - null, - currentColor: currentColor, - ); - - expect( - svgStyle.stroke?.color, - equals(currentColor), - ); - }); - - test('uses currentColor for fill color', () { - const Color currentColor = Color(0xFFB0E3BE); - final XmlStartElementEvent svg = - parseEvents('').first - as XmlStartElementEvent; - - final TestSvgParserState parserState = TestSvgParserState(); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle( - Rect.zero, - null, - currentColor: currentColor, - ); - - expect( - svgStyle.fill?.color, - equals(currentColor), - ); - }); - - group('calculates em units based on the font size for', () { - test('stroke width', () { - final XmlStartElementEvent svg = - parseEvents('').first - as XmlStartElementEvent; - - const double fontSize = 26.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - svgStyle.stroke?.strokeWidth, - equals(fontSize * 2), - ); - }); - - test('dash array', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - [ - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - ], - equals([ - fontSize * 0.2, - fontSize * 0.5, - 10, - ]), - ); - }); - - test('dash offset', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - svgStyle.dashOffset, - equals(const DashOffset.absolute(fontSize * 0.15)), - ); - }); - }); - - group('calculates ex units based on the x-height for', () { - test('stroke width', () { - final XmlStartElementEvent svg = - parseEvents('').first - as XmlStartElementEvent; - - const double fontSize = 26.0; - const double xHeight = 11.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - xHeight: xHeight, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - svgStyle.stroke?.strokeWidth, - equals(xHeight * 2), - ); - }); - - test('dash array', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - const double xHeight = 11.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - xHeight: xHeight, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - [ - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - svgStyle.dashArray!.next, - ], - equals([ - xHeight * 0.2, - xHeight * 0.5, - 10, - ]), - ); - }); - - test('dash offset', () { - final XmlStartElementEvent svg = parseEvents( - '', - ).first as XmlStartElementEvent; - - const double fontSize = 26.0; - const double xHeight = 11.0; - - final TestSvgParserState parserState = TestSvgParserState( - fontSize: fontSize, - xHeight: xHeight, - ); - parserState.attributes = svg.attributes.toAttributeMap(); - final DrawableStyle svgStyle = parserState.parseStyle(Rect.zero, null); - - expect( - svgStyle.dashOffset, - equals(const DashOffset.absolute(xHeight * 0.15)), - ); - }); - }); - }); - - test('Handles pt values', () { - final TestSvgParserState state = TestSvgParserState(); - expect(state.parseDoubleWithUnits('1pt'), 1 + 1 / 3); - }); -} diff --git a/tool/gen_golden.dart b/tool/gen_golden.dart deleted file mode 100644 index 80f4faff..00000000 --- a/tool/gen_golden.dart +++ /dev/null @@ -1,86 +0,0 @@ -// There's probably some better way to do this, but for now run `flutter test tool/gen_golden.dart -// should exclude files that -// - aren't rendering properly -// - have text (this doesn't render properly in the host setup?) -// The golden files should then be visually compared against Chrome's rendering output for correctness. -// The comparison may have to be made more tolerant if we want to use other sources of rendering for comparison... - -import 'dart:io'; -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:flutter_svg/src/vector_drawable.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:path/path.dart' as path; - -Future getSvgImage(String svgData) async { - final PictureRecorder rec = PictureRecorder(); - final Canvas canvas = Canvas(rec); - - const Size size = Size(200.0, 200.0); - - final DrawableRoot svgRoot = await svg.fromSvgString( - svgData, - 'GenGoldenTest', - ); - - svgRoot.scaleCanvasToViewBox(canvas, size); - svgRoot.clipCanvasToViewBox(canvas); - - canvas.drawPaint(Paint()..color = const Color(0xFFFFFFFF)); - svgRoot.draw(canvas, svgRoot.viewport.viewBoxRect); - - final Picture pict = rec.endRecording(); - - return await pict.toImage(size.width.toInt(), size.height.toInt()); -} - -Future getSvgPngBytes(String svgData) async { - final Image image = await getSvgImage(svgData); - final ByteData bytes = (await image.toByteData(format: ImageByteFormat.png))!; - - return bytes.buffer.asUint8List(); -} - -Future getSvgRgbaBytes(String svgData) async { - final Image image = await getSvgImage(svgData); - final ByteData bytes = - (await image.toByteData(format: ImageByteFormat.rawRgba))!; - - return bytes.buffer.asUint8List(); -} - -Iterable getSvgFileNames() sync* { - final Directory dir = Directory('./example/assets'); - for (FileSystemEntity fe in dir.listSync(recursive: true)) { - if (fe is File && fe.path.toLowerCase().endsWith('.svg')) { - // Skip text based tests unless we're on Linux - these have - // subtle platform specific differences. - if (fe.path.toLowerCase().contains('text') && !Platform.isLinux) { - continue; - } - yield fe; - } - } -} - -String getGoldenFileName(String svgAssetPath) { - return svgAssetPath - .replaceAll('/example\/assets/', '/golden/') - .replaceAll('\\example\\assets\\', '\\golden\\') - .replaceAll('.svg', '.png'); -} - -Future main() async { - for (File fe in getSvgFileNames()) { - final String pathName = getGoldenFileName(fe.path); - - final Directory goldenDir = Directory(path.dirname(pathName)); - if (!goldenDir.existsSync()) { - goldenDir.createSync(recursive: true); - } - final File output = File(pathName); - print(pathName); - await output.writeAsBytes(await getSvgPngBytes(await fe.readAsString())); - } -} diff --git a/vector_graphics.md b/vector_graphics.md new file mode 100644 index 00000000..46a12682 --- /dev/null +++ b/vector_graphics.md @@ -0,0 +1,169 @@ +# `vector_graphics`, or `flutter_svg` 2.0 + +Starting in version 2.0, `flutter_svg` migrated to using the +`vector_graphics_compiler` as an SVG parsing backend and the `vector_graphics` +runtime package for widget/render object responsibilities. + +The `vector_graphics` packages provide a compiler runtime that has no +dependencies on `dart:ui`, and so can run completely as a CLI application or in +a background isolate. It produces a binary file that has no versioning or +compatibility guarantees - meaning that the output of the compiler is only +suitable for use with the runtime and codec with the same exact git hash. This +allows for a compact, optimized, and further optimizable format. + +The ideal way to use that package is to convert your assets at compile time and +bundle them with your application, or store them on a server in a location that +is matched precisely to git hash of the package that produced them. This can +be challenging with the current state of the flutter_tools and Dart build +systems, as well as for developers who lack the resources to version and control +all of their network vector graphic assets. This package is meant to help bridge +the gap, as well as to help existing `flutter_svg` users benefit from more +optimizations and an easier migration path. + +## Why `vector_graphics`? + +SVG, as specified, is a nightmare. Parsing XML is slow, especially in comparison +to binary formats like Flat/Protocol Buffers and the like. SVG itself pulls in +many other web standards like CSS, JavaScript, and HTML. Even if you restrict +yourself to some static subset of SVG, the specification allows for a wide +latitude of insane but valid things. For example, the specification does nothing +to prevent or discourage an editor from inserting dozens of `` nodes, each +having a `transform`, that eventually transform their sole child back to the +identity matrix. And because the specification states that each group node can +have other inheritable attributes attached, each node must be examined and some +suitable data structure(s) must be allocated to account for how to pass on +those heritable attributes if any arise. On a slow, lost-cost mobile device, +this cuts into valuable frame-time if done on the UI isolate. And this doesn't +even mention that design tool may have snuck in any number of masks, which as +specified require at least two render target switches but frequently are used in +place of what could be achieved with a much cheaper clip. + +The basic problem is that SVG gives design tools a very large number of ways to +specify a drawing, and design tools are generally not written to produce SVG +that will be fast to render or fast to parse. Existing SVG optimization tools +tend to focus on network download size, and may lack internal capabilities to +examine the relationships between nodes to decide when and how they can be +optimized. + +The `vector_graphics` suite addresses this by focusing less on being fast at +parsing and more on being able to produce something that will be fast when it +finally gets to the UI isolate - and faster when Flutter's rasterizer goes to +render it. Some of the optimizations available that suite are currently only +available when directly using the `vector_graphics` package, both because of +challenges around packaging FFI libraries for various platforms and because +some of the optimization algorithms may be more expensive than just taking the +penalty of not using them. + +Additionally, the design that `flutter_svg` was using took inspiration from +`package:flutter`'s image related classes. This turned out to be a mistake. +There is no intention for `flutter_svg` to ever support animated/multi-frame +SVGs, and the way that Flutter ties together byte acquisition and image decoding +makes things a bit complicated. Instead, `vector_graphics` introduces the +concept of a `BytesLoader` class, which knows how to obtain encoded bytes to +feed to the runtime via an asynchronous method that optionally receives a +`BuildContext`. See the `loaders.dart` file in this package for examples. + +As of this writing, the optimizations that are available include: + +- Useless element/attribute pruning. +- Inheritance removal. +- Paint/path deduplication. +- Transform pre-calculation/collapsing. +- Elimination of XML parsing on the UI isolate. +- Elimination of UTF-8 and Base 64 decoding (i.e. for embedded images) on the UI + isolate. +- Path dashing is done completely on a background isolate. +- More use of 32-bit floats instead of 64-bit doubles, which saves on memory + with good visual fidelity. + +## What changes? + +Compared to prior releases of flutter_svg, the following changes can be +expected: + +- Loss of support for `text` elements that use `dx` or `dy` attributes, which + already was implemented only partially and incorrectly. +- Support for out of order `defs` and element references. +- Support for patterns. +- Gradients render slightly differently. This is likely due to a combination of + some precision differences and pre-calculating transforms. +- Some shapes, such as circles and rounded rects, render slightly differently. + This is due to precision differences and pre-calculation of curves. +- Golden tests may now show SVGs they did not used to show. this is because more + parsing and rendering is completely synchronous in tests, whereas previously + it was always at least partially async. +- Outside of tests (where the extra async makes life more confusing) and web + (which does not have isolates), parsing happens in a separate isolates. + +## What do I need to change in my code? + +### `precachePicture` + +This API doesn't exist anymore. If you were using it to pre-fetch bytes from +some `PictureProvider`, instead write a custom `BytesLoader` implementation +(or use an existing one) and use `vg.loadPicture`. However, there is currently +no provided widget to make drawing that picture easy, but generally speaking +you can use a `CustomPainter`. + +### `PictureProvider`s + +If you had a custom `PictureProvider`, you will now want a custom `BytesLoader`. +Consider overriding `SvgLoader`, which takes care of doing the right thing +with isolates for you and only requires you to implement a function to obtain +the SVG string that will be run in a non-UI isolate. See more examples in +`loaders.dart` in this package. + +### `PictureCache` + +Pictures are no longer cached, however the byte data for vector_graphics output +is cached in the `Cache` object. This is similar to but not quite the same as +the old picture cache. It is available via `svg.cache`. + +### Widget changes + +The `SvgPicture.clipBehavior` property is deprecated (no-op). + +The `SvgPicture.cacheColorFilter` property is deprecated (no-op). + +The `SvgPicture.*` constructors still have `color` and `colorBlendMode` +properties, which are deprecated. Instead use the `colorFilter` property. To +achieve the old behavior of the `color` property, use +`ColorFilter.mode(color, BlendMode.srcIn)`. + +The `SvgPicture.pictureProvider` property has been removed. Use the `loader` +property instead, if you must. + +### Golden testing + +Please limit your golden tests. In particular, try to make sure that you avoid +testing the same SVG over and over again in multiple different golden tests, +and try to make sure that you _only have as many golden files that as can be +reviewed by you and your team if they all changed in a single update_. In +general, this is somewhere around 10-20 golden files _per reviwer_, and that is +generously assuming that each reviewer will carefully examine the differences +in those 10-20 files. Assume that the reviewer will have no idea what the author +of the test intended, _even if the reviewer authored the test_. If your team +is 5 people, that means somewhere between 50-100 goldens. + +Anecdotally, I have missed important regressions in golden tests I wrote because +I wrote them several years ago and just forgot, and I was only looking for +change X which I verified but missed changes Y and Z that I hadn't thought about +in over a year. I have also worked with partner projects that use `flutter_svg` +that have _tens of thousands of golden images directly or indirectly involveing +SVGs_ and it is a _nightmare_ for everyone when some minor change comes along +that touches most of them. Very frequently in such projects, it becomes obvious +that _no one_ has ever looked at a large number of these golden tests, and they +actually harm test coverage because they falsely make broken code appear to have +coverage via a test that requires a human to double check its result. + +With that said, most golden testing should "just work," except if your SVGs have +images in them. In that case, "real" async work needs to get done, and at some +point the test in question will have to call + +```dart +await tester.runAsync(() => vg.waitForPendingDecodes()); +await tester.pump(); +``` + +to make sure that the image decode(s) finish and the placeholder widget is +replaced with the actual picture. From dd6876fced27cb7ceb4e89a90698fe54d32cc012 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 21 Nov 2022 09:27:57 -0800 Subject: [PATCH 087/142] Drop unused deps (#808) * Drop unnecessary deps * Remove unused deps * MORE --- pubspec.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index f13af394..5b767ef3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,18 +7,13 @@ version: 2.0.0 dependencies: flutter: sdk: flutter - meta: ^1.7.0 - path_drawing: ^1.0.1 vector_graphics: ^1.0.0 vector_graphics_codec: ^1.0.0 vector_graphics_compiler: ^1.0.0 - vector_math: ^2.1.2 dev_dependencies: flutter_test: sdk: flutter - path: ^1.8.1 - test: ^1.21.1 environment: sdk: '>=2.17.0 <3.0.0' From dc2041074f4c0e11136d933a0b3ab85c9ad0d31d Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 9 Dec 2022 18:25:07 -0800 Subject: [PATCH 088/142] update readme to add more details about precompiliation (#816) * update readme * update versions for prelease and remove unused code * re-word and combine --- CHANGELOG.md | 2 +- README.md | 33 ++++++++++++++---- lib/src/utilities/xml.dart | 69 -------------------------------------- pubspec.yaml | 6 ++-- 4 files changed, 30 insertions(+), 80 deletions(-) delete mode 100644 lib/src/utilities/xml.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 630117fc..4964bf39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGES -## 2.0.0 +## 2.0.0-dev.1 - Use parsing backend from `vector_graphics_compiler`. - Out of order defs now supported. diff --git a/README.md b/README.md index 45bf30b7..6cb20980 100644 --- a/README.md +++ b/README.md @@ -83,18 +83,37 @@ for more flexibility around scaling. See [main.dart](/../master/example/lib/main.dart) for a complete sample. -## Check SVG compatibility +## Precompiling and Optimizing SVGs -The SVG parsing implementation is provided by the `vector_graphics_compiler` -package. Compatibility testing can be achieved via the following: +The vector_graphics backend supports SVG compilation which produces a binary +format that is faster to parse and can optimize SVGs to reduce the amount of +clipping, masking, and overdraw. The SVG compilation is provided by +[`package:vector_graphics_compiler`](https://pub.dev/packages/vector_graphics_compiler). ```sh -# Use the same $VERSION as the version found in flutter_svg's pubspec. -dart pub global activate vector_graphics_compiler $VERSION -dart pub global run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETED --no-optimize-masks --no-optimize-clips --no-optimize-overdraw --no-tessellate +dart run vector_graphics_compiler -i assets/foo.svg -o assets/foo.svg.vec ``` -See the `vector_graphics_compiler` package for more details. +The output `foo.svg.vec` can be loaded using the default constructor of +`SvgPicture`. + +```dart +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:vector_graphics/vector_graphics.dart'; + +final Widget svg = SvgPicture( + AssetLoader(const AssetBytesLoader('assets/foo.svg.vec')) +); +``` + +### Check SVG compatibility + +An SVG can be tested for compatibility with the vector graphics backend by +running the compiler locally to see if any errors are thrown. + +```sh +dart run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETED --no-optimize-masks --no-optimize-clips --no-optimize-overdraw --no-tessellate +``` ## Out of scope/non-goals diff --git a/lib/src/utilities/xml.dart b/lib/src/utilities/xml.dart deleted file mode 100644 index 61a57cf6..00000000 --- a/lib/src/utilities/xml.dart +++ /dev/null @@ -1,69 +0,0 @@ -import 'package:xml/xml_events.dart'; - -/// The namespace for xlink from the SVG 1.1 spec. -const String kXlinkNamespace = 'http://www.w3.org/1999/xlink'; - -/// Get the `xlink:href` or `href` attribute, preferring `xlink`. -/// -/// SVG 1.1 specifies that these attributes should be in the xlink namespace. -/// SVG 2 deprecates that namespace. -String? getHrefAttribute(Map attributes) => getAttribute( - attributes, - 'href', - def: getAttribute(attributes, 'href'), - ); - -/// Gets the attribute, trims it, and returns the attribute or default if the attribute -/// is null or ''. -/// -/// Will look to the style first if it can. -String? getAttribute( - Map el, - String name, { - String? def = '', - bool checkStyle = true, -}) { - String raw = ''; - if (checkStyle) { - final String? style = _getAttribute(el, 'style'); - if (style != '' && style != null) { - // Probably possible to slightly optimize this (e.g. use indexOf instead of split), - // but handling potential whitespace will get complicated and this just works. - // I also don't feel like writing benchmarks for what is likely a micro-optimization. - final List styles = style.split(';'); - raw = styles.firstWhere( - (String str) => str.trimLeft().startsWith(name + ':'), - orElse: () => ''); - - if (raw != '') { - raw = raw.substring(raw.indexOf(':') + 1).trim(); - } - } - - if (raw == '') { - raw = _getAttribute(el, name); - } - } else { - raw = _getAttribute(el, name); - } - - return raw == '' ? def : raw; -} - -String _getAttribute( - Map attributes, - String localName, { - String def = '', -}) { - return attributes[localName] ?? def; -} - -/// Extension on List for easy conversion to an attribute -/// map. -extension AttributeMapXmlEventAttributeExtension on List { - /// Converts the List to an attribute map. - Map toAttributeMap() => { - for (final XmlEventAttribute attribute in this) - attribute.localName: attribute.value.trim(), - }; -} diff --git a/pubspec.yaml b/pubspec.yaml index 5b767ef3..db9b9323 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.0 +version: 2.0.0-dev.1 dependencies: flutter: @@ -16,8 +16,8 @@ dev_dependencies: sdk: flutter environment: - sdk: '>=2.17.0 <3.0.0' - flutter: ">=3.4.0-34.1.pre" + sdk: '>=2.19.0-0 <3.0.0' + flutter: ">=3.7.0-0" # dependency_overrides: # vector_graphics: From 3d48ca27226f41202421939fe4e997d55cd789cb Mon Sep 17 00:00:00 2001 From: Dan Field Date: Sun, 11 Dec 2022 14:27:31 -0800 Subject: [PATCH 089/142] Avoid anon closure (#817) --- lib/src/loaders.dart | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index 81750c3e..dac70c4c 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -35,25 +35,27 @@ abstract class SvgLoader extends BytesLoader { Future prepareMessage(BuildContext? context) => SynchronousFuture(null); + Future _load(BuildContext? context) { + return prepareMessage(context).then((T? message) { + return compute((T? message) { + return encodeSvg( + xml: provideSvg(message), + theme: theme, + colorMapper: colorMapper, + debugName: 'Svg loader', + enableClippingOptimizer: false, + enableMaskingOptimizer: false, + enableOverdrawOptimizer: false, + ).buffer.asByteData(); + }, message, debugLabel: 'Load Bytes'); + }); + } + /// This method intentionally avoids using `await` to avoid unnecessary event /// loop turns. This is meant to to help tests in particular. @override Future loadBytes(BuildContext? context) { - return svg.cache.putIfAbsent(cacheKey(context), () { - return prepareMessage(context).then((T? message) { - return compute((T? message) { - return encodeSvg( - xml: provideSvg(message), - theme: theme, - colorMapper: colorMapper, - debugName: 'Svg loader', - enableClippingOptimizer: false, - enableMaskingOptimizer: false, - enableOverdrawOptimizer: false, - ).buffer.asByteData(); - }, message, debugLabel: 'Load Bytes'); - }); - }); + return svg.cache.putIfAbsent(cacheKey(context), () => _load(context)); } } From 525507aa2fe3f2352b43a8474d4a3945114528a3 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 15 Dec 2022 20:07:41 -0800 Subject: [PATCH 090/142] Use strict analysis modes instead of deprecated 'strong-mode' options (#818) See https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks for more info. --- analysis_options.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 5863ac2b..611e6279 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -19,9 +19,9 @@ # Android Studio, and the `flutter analyze` command. analyzer: - strong-mode: - implicit-casts: false - implicit-dynamic: false + language: + strict-casts: true + strict-raw-types: true errors: # treat missing required parameters as a warning (not a hint) missing_required_param: warning From c3940832c70e7d3bed6e9ead407894e1187e6280 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 20 Jan 2023 11:01:22 -0800 Subject: [PATCH 091/142] more --- example/pubspec.yaml | 14 +++++++------- pubspec.yaml | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a4f3c406..6cfa385a 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -30,10 +30,10 @@ environment: sdk: '>=2.17.0-0 <3.0.0' flutter: ">=3.4.0-34.1.pre" -# dependency_overrides: -# vector_graphics_codec: -# path: ../../vector_graphics/packages/vector_graphics_codec -# vector_graphics_compiler: -# path: ../../vector_graphics/packages/vector_graphics_compiler -# vector_graphics: -# path: ../../vector_graphics/packages/vector_graphics +dependency_overrides: + vector_graphics_codec: + path: ../../vector_graphics/packages/vector_graphics_codec + vector_graphics_compiler: + path: ../../vector_graphics/packages/vector_graphics_compiler + vector_graphics: + path: ../../vector_graphics/packages/vector_graphics diff --git a/pubspec.yaml b/pubspec.yaml index db9b9323..73fe557a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.0-dev.1 +version: 2.0.0-dev.2 dependencies: flutter: sdk: flutter - vector_graphics: ^1.0.0 - vector_graphics_codec: ^1.0.0 - vector_graphics_compiler: ^1.0.0 + vector_graphics: ^1.0.0+1 + vector_graphics_codec: ^1.0.0+1 + vector_graphics_compiler: ^1.0.0+1 dev_dependencies: flutter_test: From 6ae078f727b55bdcfc951be6365f4a04e66428a3 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 20 Jan 2023 11:06:34 -0800 Subject: [PATCH 092/142] fix pubspec --- example/pubspec.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 6cfa385a..a4f3c406 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -30,10 +30,10 @@ environment: sdk: '>=2.17.0-0 <3.0.0' flutter: ">=3.4.0-34.1.pre" -dependency_overrides: - vector_graphics_codec: - path: ../../vector_graphics/packages/vector_graphics_codec - vector_graphics_compiler: - path: ../../vector_graphics/packages/vector_graphics_compiler - vector_graphics: - path: ../../vector_graphics/packages/vector_graphics +# dependency_overrides: +# vector_graphics_codec: +# path: ../../vector_graphics/packages/vector_graphics_codec +# vector_graphics_compiler: +# path: ../../vector_graphics/packages/vector_graphics_compiler +# vector_graphics: +# path: ../../vector_graphics/packages/vector_graphics From 8074ee7a5d61e187f3987686716e721dc9ac5e1c Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 20 Jan 2023 11:09:05 -0800 Subject: [PATCH 093/142] readme --- CHANGELOG.md | 4 +++- README.md | 2 +- pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4964bf39..8094075e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGES -## 2.0.0-dev.1 +## 2.0.0 - Use parsing backend from `vector_graphics_compiler`. - Out of order defs now supported. @@ -24,6 +24,8 @@ - The `PicturePovider` class exists only for access to a no-op cache. - Several static members on `SvgPicture` and the `svg` utility class have gone away. +- The `color` and `colorBlendMode` properties have been removed. Instead, use + the `colorFilter` property instead. ## 1.1.6 diff --git a/README.md b/README.md index 6cb20980..6cd82852 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ You can color/tint the image like so: final String assetName = 'assets/up_arrow.svg'; final Widget svgIcon = SvgPicture.asset( assetName, - color: Colors.red, + colorFilter: ColorFilter.mode(Colors.red, BlendMode.srcIn), semanticsLabel: 'A red up arrow' ); ``` diff --git a/pubspec.yaml b/pubspec.yaml index 73fe557a..0d5a9fed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.0-dev.2 +version: 2.0.0 dependencies: flutter: From c951f211866ae65e28d59db2d6c8a2b222c53fca Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Fri, 27 Jan 2023 11:23:22 +1100 Subject: [PATCH 094/142] Remove AssetLoader() precompiled asset example (#833) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6cd82852..d166a63b 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:vector_graphics/vector_graphics.dart'; final Widget svg = SvgPicture( - AssetLoader(const AssetBytesLoader('assets/foo.svg.vec')) + const AssetBytesLoader('assets/foo.svg.vec') ); ``` From c1e4773468365a66f5ec7252a4c1eddbb327c5ad Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Feb 2023 09:53:16 -0800 Subject: [PATCH 095/142] bumps --- pubspec.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 0d5a9fed..2d4a11f8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,17 +7,17 @@ version: 2.0.0 dependencies: flutter: sdk: flutter - vector_graphics: ^1.0.0+1 - vector_graphics_codec: ^1.0.0+1 - vector_graphics_compiler: ^1.0.0+1 + vector_graphics: ^1.0.1 + vector_graphics_codec: ^1.0.1 + vector_graphics_compiler: ^1.0.1 dev_dependencies: flutter_test: sdk: flutter environment: - sdk: '>=2.19.0-0 <3.0.0' - flutter: ">=3.7.0-0" + sdk: '>=2.19.0 <3.0.0' + flutter: ">=3.7.0" # dependency_overrides: # vector_graphics: From 59a78a85ec5a1fdb3431911cacc62e371bb6475e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Feb 2023 09:57:59 -0800 Subject: [PATCH 096/142] Fix CI --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- test/widget_svg_test.dart | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8094075e..944ed054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ - Several static members on `SvgPicture` and the `svg` utility class have gone away. - The `color` and `colorBlendMode` properties have been removed. Instead, use - the `colorFilter` property instead. + the `colorFilter` property. ## 1.1.6 diff --git a/pubspec.yaml b/pubspec.yaml index 2d4a11f8..938f3a1b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ dev_dependencies: sdk: flutter environment: - sdk: '>=2.19.0 <3.0.0' + sdk: '>=2.19.0-0 <3.0.0' flutter: ">=3.7.0" # dependency_overrides: diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index 35023413..efa5c053 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -107,7 +107,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: SvgPicture.string( @@ -127,7 +127,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: Center( key: key, child: SvgPicture.string( @@ -145,7 +145,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: Center( key: key, child: SvgPicture.string( @@ -163,7 +163,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: Directionality( @@ -204,7 +204,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: Directionality( @@ -245,7 +245,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: SvgPicture.memory( @@ -264,7 +264,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: SvgPicture.asset( @@ -286,7 +286,7 @@ void main() { Directionality( textDirection: TextDirection.ltr, child: MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: DefaultAssetBundle( bundle: fakeAsset, child: RepaintBoundary( @@ -309,7 +309,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: SvgPicture.network( @@ -328,7 +328,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: RepaintBoundary( key: key, child: SvgPicture.network('test.svg', @@ -365,7 +365,7 @@ void main() { fakeResponse.statusCode = 400; await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: MediaQueryData.fromView(window), child: SvgPicture.network( 'notFound.svg', ), From cc1f6193028caea26e2a32fa6ce1c4894eada1a2 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Feb 2023 10:02:09 -0800 Subject: [PATCH 097/142] more --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 938f3a1b..75ba02fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,8 +16,8 @@ dev_dependencies: sdk: flutter environment: - sdk: '>=2.19.0-0 <3.0.0' - flutter: ">=3.7.0" + sdk: '>=2.19.0-0 <4.0.0' + flutter: ">=3.7.0-0" # dependency_overrides: # vector_graphics: From c599bfe769f9249e1f17a389d320c53fee9a6f41 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Feb 2023 10:18:43 -0800 Subject: [PATCH 098/142] Fix CI (#835) --- .github/workflows/ci.yml | 2 +- test/widget_svg_test.dart | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd151b8e..59c56eb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3 - uses: subosito/flutter-action@v2 with: - channel: 'beta' + channel: 'stable' - run: flutter --version - run: flutter pub get - run: flutter format --set-exit-if-changed . diff --git a/test/widget_svg_test.dart b/test/widget_svg_test.dart index efa5c053..35023413 100644 --- a/test/widget_svg_test.dart +++ b/test/widget_svg_test.dart @@ -107,7 +107,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: SvgPicture.string( @@ -127,7 +127,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: Center( key: key, child: SvgPicture.string( @@ -145,7 +145,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: Center( key: key, child: SvgPicture.string( @@ -163,7 +163,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: Directionality( @@ -204,7 +204,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: Directionality( @@ -245,7 +245,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: SvgPicture.memory( @@ -264,7 +264,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: SvgPicture.asset( @@ -286,7 +286,7 @@ void main() { Directionality( textDirection: TextDirection.ltr, child: MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: DefaultAssetBundle( bundle: fakeAsset, child: RepaintBoundary( @@ -309,7 +309,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: SvgPicture.network( @@ -328,7 +328,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: RepaintBoundary( key: key, child: SvgPicture.network('test.svg', @@ -365,7 +365,7 @@ void main() { fakeResponse.statusCode = 400; await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromView(window), + data: MediaQueryData.fromWindow(window), child: SvgPicture.network( 'notFound.svg', ), From 127197b16442752a0e6b6797cf6d996b9ef53519 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 2 Feb 2023 22:06:49 -0800 Subject: [PATCH 099/142] Packages (#838) --- CHANGELOG.md | 4 ++++ lib/src/loaders.dart | 4 +++- pubspec.yaml | 2 +- test/loaders_test.dart | 26 ++++++++++++++++++++++++-- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 944ed054..5578c983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 2.0.0+1 + +- Fix bug in asset loading from packages. + ## 2.0.0 - Use parsing backend from `vector_graphics_compiler`. diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index dac70c4c..d7d456f7 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -213,7 +213,9 @@ class SvgAssetLoader extends SvgLoader { @override Future prepareMessage(BuildContext? context) { - return _resolveBundle(context).load(assetName); + return _resolveBundle(context).load( + packageName == null ? assetName : 'packages/$packageName/$assetName', + ); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 75ba02fa..845cd135 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.0 +version: 2.0.0+1 dependencies: flutter: diff --git a/test/loaders_test.dart b/test/loaders_test.dart index 39c748a0..46fafe1e 100644 --- a/test/loaders_test.dart +++ b/test/loaders_test.dart @@ -1,5 +1,4 @@ -import 'dart:typed_data'; - +import 'package:flutter/services.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -19,6 +18,29 @@ void main() { expect(identical(bytes, bytes2), false); svg.cache.maximumSize = 100; }); + + test('AssetLoader respects packages', () async { + final TestBundle bundle = TestBundle({ + 'foo': Uint8List(0).buffer.asByteData(), + 'packages/packageName/foo': Uint8List(1).buffer.asByteData(), + }); + final SvgAssetLoader loader = SvgAssetLoader('foo', assetBundle: bundle); + final SvgAssetLoader packageLoader = + SvgAssetLoader('foo', assetBundle: bundle, packageName: 'packageName'); + expect((await loader.prepareMessage(null))!.lengthInBytes, 0); + expect((await packageLoader.prepareMessage(null))!.lengthInBytes, 1); + }); +} + +class TestBundle extends Fake implements AssetBundle { + TestBundle(this.map); + + final Map map; + + @override + Future load(String key) async { + return map[key]!; + } } class TestLoader extends SvgLoader { From b9c47a0b869a477b7e2d14d9f2c43d5911975433 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 6 Feb 2023 11:14:33 -0800 Subject: [PATCH 100/142] fix gradle versions --- example/android/build.gradle | 2 +- example/android/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/android/build.gradle b/example/android/build.gradle index 44f45cd3..e688f0a6 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 939efa29..6b665338 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip From e7a09433aadab66f4f2fd97fc77c142a85477ee2 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 13 Feb 2023 09:09:31 -0800 Subject: [PATCH 101/142] Hide vector_graphics_compiler types (#853) --- CHANGELOG.md | 4 ++ lib/src/loaders.dart | 106 +++++++++++++++++++++++++++++++++++++++---- lib/svg.dart | 3 -- 3 files changed, 100 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5578c983..a2e397f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## Next + +- Fix internal Color representation leakage from `package:vector_graphics_compiler`. + ## 2.0.0+1 - Fix bug in asset loading from packages. diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index d7d456f7..48086f72 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -5,12 +5,93 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/src/utilities/http.dart'; import 'package:vector_graphics/vector_graphics.dart'; -import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'; +import 'package:vector_graphics_compiler/vector_graphics_compiler.dart' as vg; import '../svg.dart' show svg; import 'utilities/compute.dart'; import 'utilities/file.dart'; +/// A theme used when decoding an SVG picture. +@immutable +class SvgTheme { + /// Instantiates an SVG theme with the [currentColor] + /// and [fontSize]. + /// + /// Defaults the [fontSize] to 14. + const SvgTheme({ + this.currentColor, + this.fontSize = 14, + double? xHeight, + }) : xHeight = xHeight ?? fontSize / 2; + + /// The default color applied to SVG elements that inherit the color property. + /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword + final Color? currentColor; + + /// The font size used when calculating em units of SVG elements. + /// See: https://www.w3.org/TR/SVG11/coords.html#Units + final double fontSize; + + /// The x-height (corpus size) of the font used when calculating ex units of SVG elements. + /// Defaults to [fontSize] / 2 if not provided. + /// See: https://www.w3.org/TR/SVG11/coords.html#Units, https://en.wikipedia.org/wiki/X-height + final double xHeight; + + vg.SvgTheme _toVgTheme() { + return vg.SvgTheme( + currentColor: currentColor != null ? vg.Color(currentColor!.value) : null, + fontSize: fontSize, + xHeight: xHeight, + ); + } + + @override + bool operator ==(dynamic other) { + if (other.runtimeType != runtimeType) { + return false; + } + + return other is SvgTheme && + currentColor == other.currentColor && + fontSize == other.fontSize && + xHeight == other.xHeight; + } + + @override + int get hashCode => Object.hash(currentColor, fontSize, xHeight); + + @override + String toString() => + 'SvgTheme(currentColor: $currentColor, fontSize: $fontSize, xHeight: $xHeight)'; +} + +/// A class that transforms from one color to another during SVG parsing. +abstract class ColorMapper { + /// Returns a new color to use in place of [color] during SVG parsing. + /// + /// The SVG parser will call this method every time it parses a color + Color substitute( + String? id, + String elementName, + String attributeName, + Color color, + ); +} + +class _DelegateVgColorMapper extends vg.ColorMapper { + _DelegateVgColorMapper(this.colorMapper); + + final ColorMapper colorMapper; + + @override + vg.Color substitute( + String? id, String elementName, String attributeName, vg.Color color) { + final Color substituteColor = colorMapper.substitute( + id, elementName, attributeName, Color(color.value)); + return vg.Color(substituteColor.value); + } +} + /// A [BytesLoader] that parses a SVG data in an isolate and creates a /// vector_graphics binary representation. abstract class SvgLoader extends BytesLoader { @@ -38,15 +119,20 @@ abstract class SvgLoader extends BytesLoader { Future _load(BuildContext? context) { return prepareMessage(context).then((T? message) { return compute((T? message) { - return encodeSvg( - xml: provideSvg(message), - theme: theme, - colorMapper: colorMapper, - debugName: 'Svg loader', - enableClippingOptimizer: false, - enableMaskingOptimizer: false, - enableOverdrawOptimizer: false, - ).buffer.asByteData(); + return vg + .encodeSvg( + xml: provideSvg(message), + theme: theme._toVgTheme(), + colorMapper: colorMapper == null + ? null + : _DelegateVgColorMapper(colorMapper!), + debugName: 'Svg loader', + enableClippingOptimizer: false, + enableMaskingOptimizer: false, + enableOverdrawOptimizer: false, + ) + .buffer + .asByteData(); }, message, debugLabel: 'Load Bytes'); }); } diff --git a/lib/svg.dart b/lib/svg.dart index 3e2ca5c2..63162a78 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -3,7 +3,6 @@ import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:vector_graphics/vector_graphics_compat.dart'; -import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'; import 'src/cache.dart'; import 'src/loaders.dart'; @@ -11,8 +10,6 @@ import 'src/utilities/file.dart'; export 'package:vector_graphics/vector_graphics.dart' show BytesLoader, vg, VectorGraphicUtilities, PictureInfo; -export 'package:vector_graphics_compiler/vector_graphics_compiler.dart' - show SvgTheme; export 'src/cache.dart'; export 'src/loaders.dart'; From b977d27d5ab39ffe737e1ce8eb7ddb23ae87eb3c Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 13 Feb 2023 09:34:32 -0800 Subject: [PATCH 102/142] disable isolate parsing in debug mode (#854) Co-authored-by: Dan Field --- CHANGELOG.md | 1 + lib/src/utilities/_compute_io.dart | 8 -------- lib/src/utilities/_compute_none.dart | 2 -- lib/src/utilities/compute.dart | 11 +++++------ 4 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 lib/src/utilities/_compute_io.dart delete mode 100644 lib/src/utilities/_compute_none.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index a2e397f2..01e58d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next +- Disable Isolate parsing in debug mode. - Fix internal Color representation leakage from `package:vector_graphics_compiler`. ## 2.0.0+1 diff --git a/lib/src/utilities/_compute_io.dart b/lib/src/utilities/_compute_io.dart deleted file mode 100644 index 22e4f2e2..00000000 --- a/lib/src/utilities/_compute_io.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/foundation.dart'; - -/// Whether to use an isolate-spawning version of compute or not. -final bool isTest = - kDebugMode && Platform.executable.endsWith('flutter_tester') || - Platform.executable.endsWith('flutter_tester.exe'); diff --git a/lib/src/utilities/_compute_none.dart b/lib/src/utilities/_compute_none.dart deleted file mode 100644 index db635bb4..00000000 --- a/lib/src/utilities/_compute_none.dart +++ /dev/null @@ -1,2 +0,0 @@ -/// Whether to use an isolate-spawning version of compute or not. -const bool isTest = true; diff --git a/lib/src/utilities/compute.dart b/lib/src/utilities/compute.dart index 5a50b0eb..7b8eab69 100644 --- a/lib/src/utilities/compute.dart +++ b/lib/src/utilities/compute.dart @@ -2,8 +2,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart' as foundation; -import '_compute_io.dart' if (dart.library.html) '_compute_none.dart'; - Future _testCompute( foundation.ComputeCallback callback, Q message, {String? debugLabel}) { @@ -14,11 +12,12 @@ Future _testCompute( final FutureOr result = callback(message); if (result is Future) { return result; - } else { - return foundation.SynchronousFuture(result); } + return foundation.SynchronousFuture(result); } /// A compute implementation that does not spawn isolates in tests. -final foundation.ComputeImpl compute = - isTest ? _testCompute : foundation.compute; +const foundation.ComputeImpl compute = + (foundation.kDebugMode || foundation.kIsWeb) + ? _testCompute + : foundation.compute; From 06e814e5a49deaa375e62d86adc75b953f3cf765 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 13 Feb 2023 09:35:29 -0800 Subject: [PATCH 103/142] bumps for 2.0.1 --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01e58d88..a77d9434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGES -## Next +## 2.0.1 - Disable Isolate parsing in debug mode. - Fix internal Color representation leakage from `package:vector_graphics_compiler`. diff --git a/pubspec.yaml b/pubspec.yaml index 845cd135..c8f8a75f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.0+1 +version: 2.0.1 dependencies: flutter: From 461ed86df1c3ad65cd20572e87bb2d3c1c7a2013 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 13 Feb 2023 09:39:44 -0800 Subject: [PATCH 104/142] update readme --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d166a63b..3e7c72d4 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,12 @@ import 'package:flutter_svg/flutter_svg.dart'; final String rawSvg = '''...'''; final PictureInfo pictureInfo = await vg.loadPicture(SvgStringLoader(rawSvg), null); +// You can draw the picture to a canvas: canvas.drawPicture(pictureInfo.picture); + +// Or convert the picture to a an image: +final ui.Image image = pictureInfo.picture.toImage(...); + pictureInfo.picture.dispose(); ``` From c19005297fb78d49d5737e60bb1f4229812a0e20 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 21 Feb 2023 22:22:24 -0800 Subject: [PATCH 105/142] Consume new vector_graphics --- CHANGELOG.md | 5 +++++ lib/src/loaders.dart | 6 +++--- pubspec.yaml | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a77d9434..1aec2547 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 2.0.2 + +- Consume newer version of vector_graphics with multiple fixes around + inheritence, patterns, and currentColor handling. + ## 2.0.1 - Disable Isolate parsing in debug mode. diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index 48086f72..ce42884f 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -19,14 +19,14 @@ class SvgTheme { /// /// Defaults the [fontSize] to 14. const SvgTheme({ - this.currentColor, + this.currentColor = const Color(0xFF000000), this.fontSize = 14, double? xHeight, }) : xHeight = xHeight ?? fontSize / 2; /// The default color applied to SVG elements that inherit the color property. /// See: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword - final Color? currentColor; + final Color currentColor; /// The font size used when calculating em units of SVG elements. /// See: https://www.w3.org/TR/SVG11/coords.html#Units @@ -39,7 +39,7 @@ class SvgTheme { vg.SvgTheme _toVgTheme() { return vg.SvgTheme( - currentColor: currentColor != null ? vg.Color(currentColor!.value) : null, + currentColor: vg.Color(currentColor.value), fontSize: fontSize, xHeight: xHeight, ); diff --git a/pubspec.yaml b/pubspec.yaml index c8f8a75f..834a3e19 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.1 +version: 2.0.2 dependencies: flutter: sdk: flutter - vector_graphics: ^1.0.1 - vector_graphics_codec: ^1.0.1 - vector_graphics_compiler: ^1.0.1 + vector_graphics: ^1.1.0 + vector_graphics_codec: ^1.1.0 + vector_graphics_compiler: ^1.1.0 dev_dependencies: flutter_test: From d731f27012114603f135eae7ca5f69ff885988c4 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 9 Mar 2023 09:12:19 -0800 Subject: [PATCH 106/142] Fix faulty cache assertion, bump vg (#879) * Fix faulty cache assertion, bump vg * fixes --- CHANGELOG.md | 7 ++++++- analysis_options.yaml | 1 - lib/src/cache.dart | 3 +-- pubspec.yaml | 8 ++++---- test/cache_test.dart | 30 +++++++++++++++++++++++++++++- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1aec2547..8fdb2654 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ # CHANGES +## 2.0.3 + +- Require newer version of vector_graphics. +- Fix bug in cache that incorrectly fired assert. + ## 2.0.2 -- Consume newer version of vector_graphics with multiple fixes around +- Require newer version of vector_graphics with multiple fixes around inheritence, patterns, and currentColor handling. ## 2.0.1 diff --git a/analysis_options.yaml b/analysis_options.yaml index 611e6279..b2fb7f06 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -120,7 +120,6 @@ linter: - prefer_const_literals_to_create_immutables # - prefer_constructors_over_static_methods # not yet tested - prefer_contains - - prefer_equal_for_default_values # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods - prefer_final_fields - prefer_final_locals diff --git a/lib/src/cache.dart b/lib/src/cache.dart index 3eb9fba2..3623a35c 100644 --- a/lib/src/cache.dart +++ b/lib/src/cache.dart @@ -87,7 +87,6 @@ class Cache { pendingResult.then((ByteData data) { _pending.remove(key); _add(key, data); - result = data; // in case it was a synchronous future. }); } @@ -101,7 +100,7 @@ class Cache { void _add(Object key, ByteData result) { if (maximumSize > 0) { - assert(_cache.length < maximumSize); + assert(_cache.containsKey(key) || _cache.length < maximumSize); _cache[key] = result; } assert(_cache.length <= maximumSize); diff --git a/pubspec.yaml b/pubspec.yaml index 834a3e19..124330e8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.2 +version: 2.0.3 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.0 - vector_graphics_codec: ^1.1.0 - vector_graphics_compiler: ^1.1.0 + vector_graphics: ^1.1.3 + vector_graphics_codec: ^1.1.3 + vector_graphics_compiler: ^1.1.3 dev_dependencies: flutter_test: diff --git a/test/cache_test.dart b/test/cache_test.dart index a45f642f..b1f5801e 100644 --- a/test/cache_test.dart +++ b/test/cache_test.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:flutter_svg/src/cache.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -77,4 +77,32 @@ void main() { expect(cache.evict(2), false); expect(cache.evict(3), true); }); + + test('Adding beyond max with synchronous futures', () async { + final Cache cache = Cache(); + cache.maximumSize = 2; + final Future completerA = + SynchronousFuture(ByteData(1)); + final Future completerB = + SynchronousFuture(ByteData(2)); + final Future completerC = + SynchronousFuture(ByteData(3)); + + expect(cache.count, 0); + + cache.putIfAbsent(1, () => completerA); + expect(cache.count, 1); + + cache.putIfAbsent(2, () => completerB); + expect(cache.count, 2); + + cache.putIfAbsent(2, () => completerB); + expect(cache.count, 2); + + cache.putIfAbsent(3, () => completerC); + expect(cache.count, 2); + + cache.putIfAbsent(2, () => completerB); + expect(cache.count, 2); + }); } From f96f5f0bddbf5f15bae061628abd716f155e6d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kl=C3=B6ckner?= Date: Mon, 13 Mar 2023 17:18:38 +0100 Subject: [PATCH 107/142] Reintroduce clip behavior (#860) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reintroduce clipBehavior See https://github.com/dnfield/vector_graphics/pull/180 * Use vector_graphics PR, revert before merge * Update pubspec.yaml --------- Co-authored-by: Fabian Klöckner Co-authored-by: Dan Field --- lib/svg.dart | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/svg.dart b/lib/svg.dart index 63162a78..ae2d221d 100644 --- a/lib/svg.dart +++ b/lib/svg.dart @@ -83,8 +83,8 @@ class SvgPicture extends StatelessWidget { this.colorFilter, this.semanticsLabel, this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, this.theme = const SvgTheme(), - @deprecated Clip? clipBehavior, @deprecated bool cacheColorFilter = false, }) : super(key: key); @@ -178,11 +178,11 @@ class SvgPicture extends StatelessWidget { this.placeholderBuilder, this.semanticsLabel, this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, this.theme = const SvgTheme(), ui.ColorFilter? colorFilter, @deprecated ui.Color? color, @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, - @deprecated Clip? clipBehavior, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgAssetLoader( assetName, @@ -241,7 +241,7 @@ class SvgPicture extends StatelessWidget { @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, this.semanticsLabel, this.excludeFromSemantics = false, - @deprecated Clip? clipBehavior, + this.clipBehavior = Clip.hardEdge, @deprecated bool cacheColorFilter = false, this.theme = const SvgTheme(), }) : bytesLoader = SvgNetworkLoader(url, headers: headers, theme: theme), @@ -293,8 +293,8 @@ class SvgPicture extends StatelessWidget { @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, this.semanticsLabel, this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, this.theme = const SvgTheme(), - @deprecated Clip? clipBehavior, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgFileLoader(file, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -342,8 +342,8 @@ class SvgPicture extends StatelessWidget { @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, this.semanticsLabel, this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, this.theme = const SvgTheme(), - @deprecated Clip? clipBehavior, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgBytesLoader(bytes, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -391,8 +391,8 @@ class SvgPicture extends StatelessWidget { @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, this.semanticsLabel, this.excludeFromSemantics = false, + this.clipBehavior = Clip.hardEdge, this.theme = const SvgTheme(), - @deprecated Clip? clipBehavior, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgStringLoader(string, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -468,6 +468,14 @@ class SvgPicture extends StatelessWidget { /// application. final bool excludeFromSemantics; + /// The content will be clipped (or not) according to this option. + /// + /// See the enum [Clip] for details of all possible options and their common + /// use cases. + /// + /// Defaults to [Clip.hardEdge], and must not be null. + final Clip clipBehavior; + /// The color filter, if any, to apply to this widget. final ColorFilter? colorFilter; @@ -484,6 +492,7 @@ class SvgPicture extends StatelessWidget { alignment: alignment, semanticsLabel: semanticsLabel, excludeFromSemantics: excludeFromSemantics, + clipBehavior: clipBehavior, colorFilter: colorFilter, placeholderBuilder: placeholderBuilder, clipViewbox: !allowDrawingOutsideViewBox, From bd80505e60b11c1f0757d4dd27857b38ad22aecd Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 14 Mar 2023 14:32:34 -0700 Subject: [PATCH 108/142] Manage cache count correctly (#885) * Manage cache count correctly * Fix breakage --- lib/src/cache.dart | 10 ++++++---- test/cache_test.dart | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/src/cache.dart b/lib/src/cache.dart index 3623a35c..adfd9bb2 100644 --- a/lib/src/cache.dart +++ b/lib/src/cache.dart @@ -79,9 +79,6 @@ class Cache { // and thus move it to the end of the list. _cache.remove(key); } else { - if (_cache.length == maximumSize && maximumSize > 0) { - _cache.remove(_cache.keys.first); - } pendingResult = loader(); _pending[key] = pendingResult; pendingResult.then((ByteData data) { @@ -100,7 +97,12 @@ class Cache { void _add(Object key, ByteData result) { if (maximumSize > 0) { - assert(_cache.containsKey(key) || _cache.length < maximumSize); + if (_cache.containsKey(key)) { + _cache.remove(key); // update LRU. + } else if (_cache.length == maximumSize && maximumSize > 0) { + _cache.remove(_cache.keys.first); + } + assert(_cache.length < maximumSize); _cache[key] = result; } assert(_cache.length <= maximumSize); diff --git a/test/cache_test.dart b/test/cache_test.dart index b1f5801e..1a049107 100644 --- a/test/cache_test.dart +++ b/test/cache_test.dart @@ -105,4 +105,32 @@ void main() { cache.putIfAbsent(2, () => completerB); expect(cache.count, 2); }); + + test('Futures completing late/together', () async { + final Cache cache = Cache(); + cache.maximumSize = 2; + final Completer completerA = Completer(); + final Completer completerB = Completer(); + final Completer completerC = Completer(); + + expect(cache.count, 0); + + cache.putIfAbsent(1, () => completerA.future); + cache.putIfAbsent(2, () => completerB.future); + completerA.complete(ByteData(1)); + completerB.complete(ByteData(1)); + + expect(cache.count, 0); + await null; + expect(cache.count, 2); + + cache.putIfAbsent(3, () => completerC.future); + expect(cache.count, 2); + + completerC.complete(ByteData(1)); + expect(cache.count, 2); + + await null; + expect(cache.count, 2); + }); } From c6ec4639438270b5e5ee70b395d7c20094bdf061 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 14 Mar 2023 14:34:13 -0700 Subject: [PATCH 109/142] bumps --- CHANGELOG.md | 6 ++++++ pubspec.yaml | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fdb2654..971b04c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGES +## 2.0.4 + +- Newer version of vector_graphics. +- Caching bug fix. +- Reintroduce clipBehavior. + ## 2.0.3 - Require newer version of vector_graphics. diff --git a/pubspec.yaml b/pubspec.yaml index 124330e8..48e40bb3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.3 +version: 2.0.4 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.3 - vector_graphics_codec: ^1.1.3 - vector_graphics_compiler: ^1.1.3 + vector_graphics: ^1.1.4 + vector_graphics_codec: ^1.1.4 + vector_graphics_compiler: ^1.1.4 dev_dependencies: flutter_test: From 3916b9014410cded63f076a0d6d2bff5150df47a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 14 Mar 2023 15:07:56 -0700 Subject: [PATCH 110/142] Remove unecessary file --- lib/src/utilities/errors.dart | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 lib/src/utilities/errors.dart diff --git a/lib/src/utilities/errors.dart b/lib/src/utilities/errors.dart deleted file mode 100644 index e16c76e8..00000000 --- a/lib/src/utilities/errors.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/foundation.dart'; - -/// Reports a missing or undefined `` element. -void reportMissingDef(String? key, String? href, String methodName) { - FlutterError.onError!( - FlutterErrorDetails( - exception: FlutterError.fromParts([ - ErrorSummary('Failed to find definition for $href'), - ErrorDescription( - 'This library only supports and xlink:href references that ' - 'are defined ahead of their references.'), - ErrorHint( - 'This error can be caused when the desired definition is defined after the element ' - 'referring to it (e.g. at the end of the file), or defined in another file.'), - ErrorDescription( - 'This error is treated as non-fatal, but your SVG file will likely not render as intended'), - ]), - context: ErrorDescription('while parsing $key in $methodName'), - library: 'SVG', - ), - ); -} From 3df85436d4f11a0c8ece200ce2b0ac33d31e8c30 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 16 Mar 2023 09:54:06 -0700 Subject: [PATCH 111/142] Allow malformed UTF-8 (#889) --- lib/src/loaders.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index ce42884f..cab86f75 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -37,7 +37,8 @@ class SvgTheme { /// See: https://www.w3.org/TR/SVG11/coords.html#Units, https://en.wikipedia.org/wiki/X-height final double xHeight; - vg.SvgTheme _toVgTheme() { + /// Creates a [vg.SvgTheme] from this. + vg.SvgTheme toVgTheme() { return vg.SvgTheme( currentColor: vg.Color(currentColor.value), fontSize: fontSize, @@ -122,7 +123,7 @@ abstract class SvgLoader extends BytesLoader { return vg .encodeSvg( xml: provideSvg(message), - theme: theme._toVgTheme(), + theme: theme.toVgTheme(), colorMapper: colorMapper == null ? null : _DelegateVgColorMapper(colorMapper!), @@ -189,7 +190,7 @@ class SvgBytesLoader extends SvgLoader { final Uint8List bytes; @override - String provideSvg(void message) => utf8.decode(bytes); + String provideSvg(void message) => utf8.decode(bytes, allowMalformed: true); @override int get hashCode => Object.hash(svg, theme, colorMapper); @@ -219,7 +220,7 @@ class SvgFileLoader extends SvgLoader { @override String provideSvg(void message) { final Uint8List bytes = file.readAsBytesSync(); - return utf8.decode(bytes); + return utf8.decode(bytes, allowMalformed: true); } @override @@ -306,7 +307,7 @@ class SvgAssetLoader extends SvgLoader { @override String provideSvg(ByteData? message) => - utf8.decode(message!.buffer.asUint8List()); + utf8.decode(message!.buffer.asUint8List(), allowMalformed: true); @override Object cacheKey(BuildContext? context) { @@ -358,7 +359,8 @@ class SvgNetworkLoader extends SvgLoader { } @override - String provideSvg(Uint8List? message) => utf8.decode(message!); + String provideSvg(Uint8List? message) => + utf8.decode(message!, allowMalformed: true); @override int get hashCode => Object.hash(url, headers, theme, colorMapper); From 957b8a37165c79734ec31744bde1128414cc78ac Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 16 Mar 2023 10:57:01 -0700 Subject: [PATCH 112/142] Make cache respect SvgTheme (#890) --- lib/src/loaders.dart | 52 ++++++++++++++++++++++++++++++++++++++---- test/loaders_test.dart | 17 ++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index cab86f75..13356a27 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -18,6 +18,12 @@ class SvgTheme { /// and [fontSize]. /// /// Defaults the [fontSize] to 14. + // WARNING WARNING WARNING + // If this codebase ever decides to default the font size to something off the + // BuildContext, caching logic will have to be updated. The font size can + // temporarily and unexpectedly change during route transitions in common + // patterns used in `MaterialApp`. This busts caching and destroys + // performance. const SvgTheme({ this.currentColor = const Color(0xFF000000), this.fontSize = 14, @@ -144,6 +150,39 @@ abstract class SvgLoader extends BytesLoader { Future loadBytes(BuildContext? context) { return svg.cache.putIfAbsent(cacheKey(context), () => _load(context)); } + + @override + SvgCacheKey cacheKey(BuildContext? context) { + return SvgCacheKey(keyData: this, theme: theme); + } +} + +/// A [SvgTheme] aware cache key. +/// +/// The theme must be part of the cache key to ensure that otherwise similar +/// SVGs get cached separately. +@immutable +class SvgCacheKey { + /// See [SvgCacheKey]. + const SvgCacheKey({required this.theme, required this.keyData}); + + /// The theme for this cached SVG. + final SvgTheme theme; + + /// The other key data for the SVG. + /// + /// For most loaders, using the loader object itself is suitable. + final Object keyData; + + @override + int get hashCode => Object.hash(theme, keyData); + + @override + bool operator ==(Object other) { + return other is SvgCacheKey && + other.theme == theme && + other.keyData == keyData; + } } /// A [BytesLoader] that parses an SVG string in an isolate and creates a @@ -310,11 +349,14 @@ class SvgAssetLoader extends SvgLoader { utf8.decode(message!.buffer.asUint8List(), allowMalformed: true); @override - Object cacheKey(BuildContext? context) { - return _AssetByteLoaderCacheKey( - assetName, - packageName, - _resolveBundle(context), + SvgCacheKey cacheKey(BuildContext? context) { + return SvgCacheKey( + theme: theme, + keyData: _AssetByteLoaderCacheKey( + assetName, + packageName, + _resolveBundle(context), + ), ); } diff --git a/test/loaders_test.dart b/test/loaders_test.dart index 46fafe1e..9f11d051 100644 --- a/test/loaders_test.dart +++ b/test/loaders_test.dart @@ -3,11 +3,28 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { + setUp(() { + svg.cache.clear(); + svg.cache.maximumSize = 100; + }); + + test('SvgTheme updates the cache', () async { + const TestLoader loaderA = + TestLoader(theme: SvgTheme(currentColor: Color(0xFFABCDEF))); + const TestLoader loaderB = + TestLoader(theme: SvgTheme(currentColor: Color(0xFFFEDCBA))); + final ByteData bytesA = await loaderA.loadBytes(null); + final ByteData bytesB = await loaderB.loadBytes(null); + expect(identical(bytesA, bytesB), false); + expect(svg.cache.count, 2); + }); + test('Uses the cache', () async { const TestLoader loader = TestLoader(); final ByteData bytes = await loader.loadBytes(null); final ByteData bytes2 = await loader.loadBytes(null); expect(identical(bytes, bytes2), true); + expect(svg.cache.count, 1); }); test('Empty cache', () async { From b60fc1523324e86102702948b9420f078e4a124e Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 7 Apr 2023 20:49:14 -0700 Subject: [PATCH 113/142] Consider colorMapper for cache key data (#902) * Consider colorMapper for cache key data * format --- .github/workflows/ci.yml | 2 +- lib/src/loaders.dart | 24 ++++++++++++++++++++---- test/loaders_test.dart | 30 +++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59c56eb6..c691fbe3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: channel: 'stable' - run: flutter --version - run: flutter pub get - - run: flutter format --set-exit-if-changed . + - run: dart format --set-exit-if-changed . - run: flutter analyze . - run: flutter test --coverage # - uses: romeovs/lcov-reporter-action@v0.2.16 diff --git a/lib/src/loaders.dart b/lib/src/loaders.dart index 13356a27..5ebd8dd6 100644 --- a/lib/src/loaders.dart +++ b/lib/src/loaders.dart @@ -73,7 +73,14 @@ class SvgTheme { } /// A class that transforms from one color to another during SVG parsing. +/// +/// This object must be immutable so that it is suitable for use in the +/// [svg.cache]. +@immutable abstract class ColorMapper { + /// Allows const constructors on subclasses. + const ColorMapper(); + /// Returns a new color to use in place of [color] during SVG parsing. /// /// The SVG parser will call this method every time it parses a color @@ -153,7 +160,7 @@ abstract class SvgLoader extends BytesLoader { @override SvgCacheKey cacheKey(BuildContext? context) { - return SvgCacheKey(keyData: this, theme: theme); + return SvgCacheKey(keyData: this, theme: theme, colorMapper: colorMapper); } } @@ -164,7 +171,11 @@ abstract class SvgLoader extends BytesLoader { @immutable class SvgCacheKey { /// See [SvgCacheKey]. - const SvgCacheKey({required this.theme, required this.keyData}); + const SvgCacheKey({ + required this.theme, + required this.keyData, + required this.colorMapper, + }); /// The theme for this cached SVG. final SvgTheme theme; @@ -174,14 +185,18 @@ class SvgCacheKey { /// For most loaders, using the loader object itself is suitable. final Object keyData; + /// The color mapper for the SVG, if any. + final ColorMapper? colorMapper; + @override - int get hashCode => Object.hash(theme, keyData); + int get hashCode => Object.hash(theme, keyData, colorMapper); @override bool operator ==(Object other) { return other is SvgCacheKey && other.theme == theme && - other.keyData == keyData; + other.keyData == keyData && + other.colorMapper == colorMapper; } } @@ -352,6 +367,7 @@ class SvgAssetLoader extends SvgLoader { SvgCacheKey cacheKey(BuildContext? context) { return SvgCacheKey( theme: theme, + colorMapper: colorMapper, keyData: _AssetByteLoaderCacheKey( assetName, packageName, diff --git a/test/loaders_test.dart b/test/loaders_test.dart index 9f11d051..591b3b01 100644 --- a/test/loaders_test.dart +++ b/test/loaders_test.dart @@ -1,4 +1,5 @@ import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -8,6 +9,15 @@ void main() { svg.cache.maximumSize = 100; }); + test('ColorMapper updates the cache', () async { + const TestLoader loaderA = TestLoader(); + const TestLoader loaderB = TestLoader(colorMapper: _TestColorMapper()); + final ByteData bytesA = await loaderA.loadBytes(null); + final ByteData bytesB = await loaderB.loadBytes(null); + expect(identical(bytesA, bytesB), false); + expect(svg.cache.count, 2); + }); + test('SvgTheme updates the cache', () async { const TestLoader loaderA = TestLoader(theme: SvgTheme(currentColor: Color(0xFFABCDEF))); @@ -61,10 +71,28 @@ class TestBundle extends Fake implements AssetBundle { } class TestLoader extends SvgLoader { - const TestLoader({super.theme, super.colorMapper}); + const TestLoader({this.keyName = 'A', super.theme, super.colorMapper}); + + final String keyName; @override String provideSvg(void message) { return ''; } + + @override + SvgCacheKey cacheKey(BuildContext? context) { + return SvgCacheKey( + theme: theme, colorMapper: colorMapper, keyData: keyName); + } +} + +class _TestColorMapper extends ColorMapper { + const _TestColorMapper(); + + @override + Color substitute( + String? id, String elementName, String attributeName, Color color) { + return color; + } } From 016f1b600e321ff4fb3553943366d2a80618742f Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 10 Apr 2023 09:42:51 -0700 Subject: [PATCH 114/142] Bumps for 2.0.5 --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 971b04c3..d0f7a722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 2.0.5 + +- Allow malformed UTF-8 in loaders. +- Make the cache respect the SvgTheme and ColorMapper, if present. + ## 2.0.4 - Newer version of vector_graphics. diff --git a/pubspec.yaml b/pubspec.yaml index 48e40bb3..6801822a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.4 +version: 2.0.5 dependencies: flutter: From fd85e3ce4bb05d7f914a58fd40b17a007a0b83d3 Mon Sep 17 00:00:00 2001 From: SimonWeidemann <79831243+SimonWeidemann@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:16:18 +0200 Subject: [PATCH 115/142] Add svg finder (#880) * Extract flutter svg to package * Add flutter svg test library * Adjust readme * Update and rename ci.yml to flutter_svg.yml * Create flutter_svg_test.yml --------- Co-authored-by: Dan Field --- .github/workflows/{ci.yml => flutter_svg.yml} | 3 + .github/workflows/flutter_svg_test.yml | 30 +++ .gitignore | 1 - README.md | 149 ++------------ .../flutter_svg/CHANGELOG.md | 0 packages/flutter_svg/README.md | 147 ++++++++++++++ .../flutter_svg/example}/.gitignore | 0 .../flutter_svg/example}/.metadata | 0 .../flutter_svg/example}/README.md | 0 .../example}/analysis_options.yaml | 0 .../flutter_svg/example}/android/.gitignore | 0 .../example}/android/app/build.gradle | 0 .../android/app/src/debug/AndroidManifest.xml | 0 .../android/app/src/main/AndroidManifest.xml | 0 .../com/example/example/MainActivity.kt | 0 .../res/drawable-v21/launch_background.xml | 0 .../main/res/drawable/launch_background.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../app/src/main/res/values-night/styles.xml | 0 .../app/src/main/res/values/styles.xml | 0 .../app/src/profile/AndroidManifest.xml | 0 .../flutter_svg/example}/android/build.gradle | 0 .../example}/android/example_android.iml | 0 .../example}/android/gradle.properties | 0 .../gradle/wrapper/gradle-wrapper.properties | 0 .../example}/android/settings.gradle | 0 .../assets/android_vd/battery_charging.xml | 0 .../flutter_svg/example}/assets/dart.svg | 0 .../deborah_ufw/new-action-expander.svg | 0 .../assets/deborah_ufw/new-camera.svg | 0 .../assets/deborah_ufw/new-gif-button.svg | 0 .../example}/assets/deborah_ufw/new-gif.svg | 0 .../example}/assets/deborah_ufw/new-image.svg | 0 .../assets/deborah_ufw/new-mention.svg | 0 .../assets/deborah_ufw/new-pause-button.svg | 0 .../assets/deborah_ufw/new-play-button.svg | 0 .../assets/deborah_ufw/new-send-circle.svg | 0 .../assets/deborah_ufw/numeric_25.svg | 0 .../example}/assets/flutter_logo.svg | 0 .../assets/noto-emoji/emoji_u1f600.svg | 0 .../example}/assets/simple/blend_and_mask.svg | 0 .../assets/simple/blend_mode_devil.svg | 0 .../example}/assets/simple/clip_path.svg | 0 .../example}/assets/simple/clip_path_2.svg | 0 .../example}/assets/simple/clip_path_3.svg | 0 .../assets/simple/clip_path_transform.svg | 0 .../example}/assets/simple/dash_path.svg | 0 .../example}/assets/simple/dash_zero.svg | 0 .../example}/assets/simple/ellipse.svg | 0 .../example}/assets/simple/empty_defs.svg | 0 .../example}/assets/simple/empty_group.svg | 0 .../example}/assets/simple/equation.svg | 0 .../assets/simple/fill-rule-inherit.svg | 0 .../assets/simple/fill_inheritence_test.svg | 0 .../assets/simple/group_composite_opacity.svg | 0 .../assets/simple/group_fill_opacity.svg | 0 .../example}/assets/simple/group_in_defs.svg | 0 .../example}/assets/simple/group_mask.svg | 0 .../example}/assets/simple/group_opacity.svg | 0 .../assets/simple/group_opacity_transform.svg | 0 .../example}/assets/simple/hidden.svg | 0 .../example}/assets/simple/href-fill.svg | 0 .../example}/assets/simple/image.svg | 0 .../example}/assets/simple/image_def.svg | 0 .../image_transform_before_translate.svg | 0 .../simple/implicit_fill_with_opacity.svg | 0 .../assets/simple/invalid_dash_array.svg | 0 .../assets/simple/linear_gradient.svg | 0 .../assets/simple/linear_gradient_2.svg | 0 ...gradient_absolute_user_space_translate.svg | 0 ...gradient_percentage_bounding_translate.svg | 0 ...adient_percentage_user_space_translate.svg | 0 .../assets/simple/linear_gradient_xlink.svg | 0 .../example}/assets/simple/male.svg | 0 .../example}/assets/simple/mask.svg | 0 .../assets/simple/mask_with_gradient.svg | 0 .../example}/assets/simple/mask_with_use.svg | 0 .../example}/assets/simple/mask_with_use2.svg | 0 .../example}/assets/simple/nested_group.svg | 0 .../assets/simple/opacity_on_path.svg | 0 .../assets/simple/radial_gradient.svg | 0 ...gradient_absolute_user_space_translate.svg | 0 .../assets/simple/radial_gradient_focal.svg | 0 ...gradient_percentage_bounding_translate.svg | 0 ...adient_percentage_user_space_translate.svg | 0 .../assets/simple/radial_gradient_xlink.svg | 0 .../simple/radial_ref_linear_gradient.svg | 0 .../example}/assets/simple/rect_rrect.svg | 0 .../assets/simple/rect_rrect_no_ry.svg | 0 .../assets/simple/stroke_inherit_circles.svg | 0 .../example}/assets/simple/style_attr.svg | 0 .../example}/assets/simple/text.svg | 0 .../example}/assets/simple/text_2.svg | 0 .../example}/assets/simple/text_3.svg | 0 .../example}/assets/simple/text_4.svg | 0 .../example}/assets/simple/text_5.svg | 0 .../example}/assets/simple/text_6.svg | 0 .../example}/assets/simple/use_circles.svg | 0 .../assets/simple/use_circles_def.svg | 0 .../example}/assets/simple/use_emc2.svg | 0 .../example}/assets/simple/use_fill.svg | 0 .../example}/assets/simple/use_fill_test.svg | 0 .../assets/simple/use_opacity_grid.svg | 0 .../assets/simple/width_height_viewbox.svg | 0 .../assets/simple/zero_width_strokes.svg | 0 .../example}/assets/svg_currentcolor.svg | 0 .../example}/assets/text_transform.svg | 0 .../example}/assets/w3samples/aa.svg | 0 .../assets/w3samples/alphachannel.svg | 0 .../assets/wikimedia/Firefox_Logo_2017.svg | 0 .../wikimedia/Flag_of_the_United_States.svg | 0 .../assets/wikimedia/Ghostscript_Tiger.svg | 0 .../assets/wikimedia/chess_knight.svg | 0 .../flutter_svg/example}/example.iml | 0 .../flutter_svg/example}/example_android.iml | 0 .../flutter_svg/example}/ios/.gitignore | 0 .../ios/Flutter/AppFrameworkInfo.plist | 0 .../example}/ios/Flutter/Debug.xcconfig | 0 .../example}/ios/Flutter/Release.xcconfig | 0 .../ios/Runner.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/WorkspaceSettings.xcsettings | 0 .../example}/ios/Runner/AppDelegate.h | 0 .../example}/ios/Runner/AppDelegate.m | 0 .../example}/ios/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Icon-App-1024x1024@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin .../Icon-App-83.5x83.5@2x.png | Bin .../LaunchImage.imageset/Contents.json | 0 .../LaunchImage.imageset/LaunchImage.png | Bin .../LaunchImage.imageset/LaunchImage@2x.png | Bin .../LaunchImage.imageset/LaunchImage@3x.png | Bin .../LaunchImage.imageset/README.md | 0 .../Runner/Base.lproj/LaunchScreen.storyboard | 0 .../ios/Runner/Base.lproj/Main.storyboard | 0 .../example}/ios/Runner/Info.plist | 0 .../ios/Runner/Runner-Bridging-Header.h | 0 .../flutter_svg/example}/ios/Runner/main.m | 0 .../flutter_svg/example}/lib/main.dart | 0 .../flutter_svg/example}/lib/simple.dart | 0 .../flutter_svg/example}/linux/.gitignore | 0 .../flutter_svg/example}/linux/CMakeLists.txt | 0 .../example}/linux/flutter/CMakeLists.txt | 0 .../flutter/generated_plugin_registrant.cc | 0 .../flutter/generated_plugin_registrant.h | 0 .../linux/flutter/generated_plugins.cmake | 0 .../flutter_svg/example}/linux/main.cc | 0 .../example}/linux/my_application.cc | 0 .../example}/linux/my_application.h | 0 .../flutter_svg/example}/macos/.gitignore | 0 .../macos/Flutter/Flutter-Debug.xcconfig | 0 .../macos/Flutter/Flutter-Release.xcconfig | 0 .../Flutter/GeneratedPluginRegistrant.swift | 0 .../macos/Runner.xcodeproj/project.pbxproj | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../xcshareddata/xcschemes/Runner.xcscheme | 0 .../contents.xcworkspacedata | 0 .../xcshareddata/IDEWorkspaceChecks.plist | 0 .../example}/macos/Runner/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../AppIcon.appiconset/app_icon_1024.png | Bin .../AppIcon.appiconset/app_icon_128.png | Bin .../AppIcon.appiconset/app_icon_16.png | Bin .../AppIcon.appiconset/app_icon_256.png | Bin .../AppIcon.appiconset/app_icon_32.png | Bin .../AppIcon.appiconset/app_icon_512.png | Bin .../AppIcon.appiconset/app_icon_64.png | Bin .../macos/Runner/Base.lproj/MainMenu.xib | 0 .../macos/Runner/Configs/AppInfo.xcconfig | 0 .../macos/Runner/Configs/Debug.xcconfig | 0 .../macos/Runner/Configs/Release.xcconfig | 0 .../macos/Runner/Configs/Warnings.xcconfig | 0 .../macos/Runner/DebugProfile.entitlements | 0 .../example}/macos/Runner/Info.plist | 0 .../macos/Runner/MainFlutterWindow.swift | 0 .../macos/Runner/Release.entitlements | 0 .../flutter_svg/example}/pubspec.yaml | 0 .../example}/test_driver/bench.dart | 0 .../example}/test_driver/bench_test.dart | 0 .../example}/test_driver/repaint.dart | 0 .../example}/test_driver/repaint_test.dart | 0 .../flutter_svg/example}/web/favicon.png | Bin .../example}/web/icons/Icon-192.png | Bin .../example}/web/icons/Icon-512.png | Bin .../example}/web/icons/Icon-maskable-192.png | Bin .../example}/web/icons/Icon-maskable-512.png | Bin .../flutter_svg/example}/web/index.html | 0 .../flutter_svg/example}/web/manifest.json | 0 .../flutter_svg/example}/windows/.gitignore | 0 .../example}/windows/CMakeLists.txt | 0 .../example}/windows/flutter/CMakeLists.txt | 0 .../flutter/generated_plugin_registrant.cc | 0 .../flutter/generated_plugin_registrant.h | 0 .../windows/flutter/generated_plugins.cmake | 0 .../example}/windows/runner/CMakeLists.txt | 0 .../example}/windows/runner/Runner.rc | 0 .../windows/runner/flutter_window.cpp | 0 .../example}/windows/runner/flutter_window.h | 0 .../example}/windows/runner/main.cpp | 0 .../example}/windows/runner/resource.h | 0 .../windows/runner/resources/app_icon.ico | Bin .../example}/windows/runner/run_loop.cpp | 0 .../example}/windows/runner/run_loop.h | 0 .../windows/runner/runner.exe.manifest | 0 .../example}/windows/runner/utils.cpp | 0 .../example}/windows/runner/utils.h | 0 .../example}/windows/runner/win32_window.cpp | 0 .../example}/windows/runner/win32_window.h | 0 .../flutter_svg/flutter_svg.iml | 0 .../flutter_svg/flutter_svg_android.iml | 0 .../flutter_svg/lib}/flutter_svg.dart | 0 .../flutter_svg/lib}/src/cache.dart | 0 .../flutter_svg/lib}/src/loaders.dart | 0 .../lib}/src/utilities/_file_io.dart | 0 .../lib}/src/utilities/_file_none.dart | 0 .../lib}/src/utilities/_http_io.dart | 0 .../lib}/src/utilities/_http_web.dart | 0 .../lib}/src/utilities/compute.dart | 0 .../flutter_svg/lib}/src/utilities/file.dart | 0 .../flutter_svg/lib}/src/utilities/http.dart | 0 .../lib}/src/utilities/numbers.dart | 0 {lib => packages/flutter_svg/lib}/svg.dart | 0 .../flutter_svg/pubspec.yaml | 2 +- .../flutter_svg/test}/cache_test.dart | 0 .../text_color_filter_isolatedDiff.png | Bin 0 -> 2247 bytes .../failures/text_color_filter_maskedDiff.png | Bin 0 -> 2421 bytes .../text_color_filter_masterImage.png | Bin .../failures/text_color_filter_testImage.png | Bin 0 -> 2429 bytes .../test}/golden_widget/circle.em_ex.png | Bin .../test}/golden_widget/circle.em_ex2.png | Bin .../test}/golden_widget/columns_and_rows.png | Bin .../test}/golden_widget/ellipse.em_ex.png | Bin .../test}/golden_widget/ellipse.em_ex2.png | Bin .../golden_widget/flutter_logo.asset.png | Bin .../golden_widget/flutter_logo.memory.png | Bin .../golden_widget/flutter_logo.natural.png | Bin .../golden_widget/flutter_logo.network.png | Bin ...go.string.color_filter.blendmode_color.png | Bin .../flutter_logo.string.color_filter.png | Bin .../golden_widget/flutter_logo.string.ltr.png | Bin .../golden_widget/flutter_logo.string.png | Bin .../golden_widget/flutter_logo.string.rtl.png | Bin .../test}/golden_widget/line.em_ex.png | Bin .../test}/golden_widget/line.em_ex2.png | Bin .../test}/golden_widget/rect.em_ex.png | Bin .../test}/golden_widget/rect.em_ex2.png | Bin .../stick_figure.withclipping.png | Bin .../test/golden_widget/text_color_filter.png | Bin 0 -> 2396 bytes .../test}/golden_widget/two_of_same.png | Bin .../flutter_svg/test}/loaders_test.dart | 0 .../test}/no_width_height_test.dart | 0 .../flutter_svg/test}/widget_svg_test.dart | 0 packages/flutter_svg_test/README.md | 44 +++++ .../lib/flutter_svg_test.dart | 170 ++++++++++++++++ packages/flutter_svg_test/pubspec.yaml | 18 ++ .../flutter_svg_test/test/flutter_logo.svg | 20 ++ .../test/flutter_svg_test_test.dart | 183 ++++++++++++++++++ 279 files changed, 627 insertions(+), 140 deletions(-) rename .github/workflows/{ci.yml => flutter_svg.yml} (89%) create mode 100644 .github/workflows/flutter_svg_test.yml rename CHANGELOG.md => packages/flutter_svg/CHANGELOG.md (100%) create mode 100644 packages/flutter_svg/README.md rename {example => packages/flutter_svg/example}/.gitignore (100%) rename {example => packages/flutter_svg/example}/.metadata (100%) rename {example => packages/flutter_svg/example}/README.md (100%) rename {example => packages/flutter_svg/example}/analysis_options.yaml (100%) rename {example => packages/flutter_svg/example}/android/.gitignore (100%) rename {example => packages/flutter_svg/example}/android/app/build.gradle (100%) rename {example => packages/flutter_svg/example}/android/app/src/debug/AndroidManifest.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/AndroidManifest.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/kotlin/com/example/example/MainActivity.kt (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/drawable-v21/launch_background.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/drawable/launch_background.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/values-night/styles.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/main/res/values/styles.xml (100%) rename {example => packages/flutter_svg/example}/android/app/src/profile/AndroidManifest.xml (100%) rename {example => packages/flutter_svg/example}/android/build.gradle (100%) rename {example => packages/flutter_svg/example}/android/example_android.iml (100%) rename {example => packages/flutter_svg/example}/android/gradle.properties (100%) rename {example => packages/flutter_svg/example}/android/gradle/wrapper/gradle-wrapper.properties (100%) rename {example => packages/flutter_svg/example}/android/settings.gradle (100%) rename {example => packages/flutter_svg/example}/assets/android_vd/battery_charging.xml (100%) rename {example => packages/flutter_svg/example}/assets/dart.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-action-expander.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-camera.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-gif-button.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-gif.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-image.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-mention.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-pause-button.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-play-button.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/new-send-circle.svg (100%) rename {example => packages/flutter_svg/example}/assets/deborah_ufw/numeric_25.svg (100%) rename {example => packages/flutter_svg/example}/assets/flutter_logo.svg (100%) rename {example => packages/flutter_svg/example}/assets/noto-emoji/emoji_u1f600.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/blend_and_mask.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/blend_mode_devil.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/clip_path.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/clip_path_2.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/clip_path_3.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/clip_path_transform.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/dash_path.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/dash_zero.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/ellipse.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/empty_defs.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/empty_group.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/equation.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/fill-rule-inherit.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/fill_inheritence_test.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_composite_opacity.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_fill_opacity.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_in_defs.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_mask.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_opacity.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/group_opacity_transform.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/hidden.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/href-fill.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/image.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/image_def.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/image_transform_before_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/implicit_fill_with_opacity.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/invalid_dash_array.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient_2.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient_absolute_user_space_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient_percentage_bounding_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient_percentage_user_space_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/linear_gradient_xlink.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/male.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/mask.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/mask_with_gradient.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/mask_with_use.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/mask_with_use2.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/nested_group.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/opacity_on_path.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient_absolute_user_space_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient_focal.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient_percentage_bounding_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient_percentage_user_space_translate.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_gradient_xlink.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/radial_ref_linear_gradient.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/rect_rrect.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/rect_rrect_no_ry.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/stroke_inherit_circles.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/style_attr.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text_2.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text_3.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text_4.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text_5.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/text_6.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_circles.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_circles_def.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_emc2.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_fill.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_fill_test.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/use_opacity_grid.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/width_height_viewbox.svg (100%) rename {example => packages/flutter_svg/example}/assets/simple/zero_width_strokes.svg (100%) rename {example => packages/flutter_svg/example}/assets/svg_currentcolor.svg (100%) rename {example => packages/flutter_svg/example}/assets/text_transform.svg (100%) rename {example => packages/flutter_svg/example}/assets/w3samples/aa.svg (100%) rename {example => packages/flutter_svg/example}/assets/w3samples/alphachannel.svg (100%) rename {example => packages/flutter_svg/example}/assets/wikimedia/Firefox_Logo_2017.svg (100%) rename {example => packages/flutter_svg/example}/assets/wikimedia/Flag_of_the_United_States.svg (100%) rename {example => packages/flutter_svg/example}/assets/wikimedia/Ghostscript_Tiger.svg (100%) rename {example => packages/flutter_svg/example}/assets/wikimedia/chess_knight.svg (100%) rename {example => packages/flutter_svg/example}/example.iml (100%) rename {example => packages/flutter_svg/example}/example_android.iml (100%) rename {example => packages/flutter_svg/example}/ios/.gitignore (100%) rename {example => packages/flutter_svg/example}/ios/Flutter/AppFrameworkInfo.plist (100%) rename {example => packages/flutter_svg/example}/ios/Flutter/Debug.xcconfig (100%) rename {example => packages/flutter_svg/example}/ios/Flutter/Release.xcconfig (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcodeproj/project.pbxproj (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/flutter_svg/example}/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (100%) rename {example => packages/flutter_svg/example}/ios/Runner/AppDelegate.h (100%) rename {example => packages/flutter_svg/example}/ios/Runner/AppDelegate.m (100%) rename {example => packages/flutter_svg/example}/ios/Runner/AppDelegate.swift (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Base.lproj/LaunchScreen.storyboard (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Base.lproj/Main.storyboard (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Info.plist (100%) rename {example => packages/flutter_svg/example}/ios/Runner/Runner-Bridging-Header.h (100%) rename {example => packages/flutter_svg/example}/ios/Runner/main.m (100%) rename {example => packages/flutter_svg/example}/lib/main.dart (100%) rename {example => packages/flutter_svg/example}/lib/simple.dart (100%) rename {example => packages/flutter_svg/example}/linux/.gitignore (100%) rename {example => packages/flutter_svg/example}/linux/CMakeLists.txt (100%) rename {example => packages/flutter_svg/example}/linux/flutter/CMakeLists.txt (100%) rename {example => packages/flutter_svg/example}/linux/flutter/generated_plugin_registrant.cc (100%) rename {example => packages/flutter_svg/example}/linux/flutter/generated_plugin_registrant.h (100%) rename {example => packages/flutter_svg/example}/linux/flutter/generated_plugins.cmake (100%) rename {example => packages/flutter_svg/example}/linux/main.cc (100%) rename {example => packages/flutter_svg/example}/linux/my_application.cc (100%) rename {example => packages/flutter_svg/example}/linux/my_application.h (100%) rename {example => packages/flutter_svg/example}/macos/.gitignore (100%) rename {example => packages/flutter_svg/example}/macos/Flutter/Flutter-Debug.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Flutter/Flutter-Release.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Flutter/GeneratedPluginRegistrant.swift (100%) rename {example => packages/flutter_svg/example}/macos/Runner.xcodeproj/project.pbxproj (100%) rename {example => packages/flutter_svg/example}/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/flutter_svg/example}/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (100%) rename {example => packages/flutter_svg/example}/macos/Runner.xcworkspace/contents.xcworkspacedata (100%) rename {example => packages/flutter_svg/example}/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename {example => packages/flutter_svg/example}/macos/Runner/AppDelegate.swift (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Base.lproj/MainMenu.xib (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Configs/AppInfo.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Configs/Debug.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Configs/Release.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Configs/Warnings.xcconfig (100%) rename {example => packages/flutter_svg/example}/macos/Runner/DebugProfile.entitlements (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Info.plist (100%) rename {example => packages/flutter_svg/example}/macos/Runner/MainFlutterWindow.swift (100%) rename {example => packages/flutter_svg/example}/macos/Runner/Release.entitlements (100%) rename {example => packages/flutter_svg/example}/pubspec.yaml (100%) rename {example => packages/flutter_svg/example}/test_driver/bench.dart (100%) rename {example => packages/flutter_svg/example}/test_driver/bench_test.dart (100%) rename {example => packages/flutter_svg/example}/test_driver/repaint.dart (100%) rename {example => packages/flutter_svg/example}/test_driver/repaint_test.dart (100%) rename {example => packages/flutter_svg/example}/web/favicon.png (100%) rename {example => packages/flutter_svg/example}/web/icons/Icon-192.png (100%) rename {example => packages/flutter_svg/example}/web/icons/Icon-512.png (100%) rename {example => packages/flutter_svg/example}/web/icons/Icon-maskable-192.png (100%) rename {example => packages/flutter_svg/example}/web/icons/Icon-maskable-512.png (100%) rename {example => packages/flutter_svg/example}/web/index.html (100%) rename {example => packages/flutter_svg/example}/web/manifest.json (100%) rename {example => packages/flutter_svg/example}/windows/.gitignore (100%) rename {example => packages/flutter_svg/example}/windows/CMakeLists.txt (100%) rename {example => packages/flutter_svg/example}/windows/flutter/CMakeLists.txt (100%) rename {example => packages/flutter_svg/example}/windows/flutter/generated_plugin_registrant.cc (100%) rename {example => packages/flutter_svg/example}/windows/flutter/generated_plugin_registrant.h (100%) rename {example => packages/flutter_svg/example}/windows/flutter/generated_plugins.cmake (100%) rename {example => packages/flutter_svg/example}/windows/runner/CMakeLists.txt (100%) rename {example => packages/flutter_svg/example}/windows/runner/Runner.rc (100%) rename {example => packages/flutter_svg/example}/windows/runner/flutter_window.cpp (100%) rename {example => packages/flutter_svg/example}/windows/runner/flutter_window.h (100%) rename {example => packages/flutter_svg/example}/windows/runner/main.cpp (100%) rename {example => packages/flutter_svg/example}/windows/runner/resource.h (100%) rename {example => packages/flutter_svg/example}/windows/runner/resources/app_icon.ico (100%) rename {example => packages/flutter_svg/example}/windows/runner/run_loop.cpp (100%) rename {example => packages/flutter_svg/example}/windows/runner/run_loop.h (100%) rename {example => packages/flutter_svg/example}/windows/runner/runner.exe.manifest (100%) rename {example => packages/flutter_svg/example}/windows/runner/utils.cpp (100%) rename {example => packages/flutter_svg/example}/windows/runner/utils.h (100%) rename {example => packages/flutter_svg/example}/windows/runner/win32_window.cpp (100%) rename {example => packages/flutter_svg/example}/windows/runner/win32_window.h (100%) rename flutter_svg.iml => packages/flutter_svg/flutter_svg.iml (100%) rename flutter_svg_android.iml => packages/flutter_svg/flutter_svg_android.iml (100%) rename {lib => packages/flutter_svg/lib}/flutter_svg.dart (100%) rename {lib => packages/flutter_svg/lib}/src/cache.dart (100%) rename {lib => packages/flutter_svg/lib}/src/loaders.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/_file_io.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/_file_none.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/_http_io.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/_http_web.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/compute.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/file.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/http.dart (100%) rename {lib => packages/flutter_svg/lib}/src/utilities/numbers.dart (100%) rename {lib => packages/flutter_svg/lib}/svg.dart (100%) rename pubspec.yaml => packages/flutter_svg/pubspec.yaml (90%) rename {test => packages/flutter_svg/test}/cache_test.dart (100%) create mode 100644 packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png create mode 100644 packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png rename test/golden_widget/text_color_filter.png => packages/flutter_svg/test/failures/text_color_filter_masterImage.png (100%) create mode 100644 packages/flutter_svg/test/failures/text_color_filter_testImage.png rename {test => packages/flutter_svg/test}/golden_widget/circle.em_ex.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/circle.em_ex2.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/columns_and_rows.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/ellipse.em_ex.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/ellipse.em_ex2.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.asset.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.memory.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.natural.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.network.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.string.color_filter.blendmode_color.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.string.color_filter.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.string.ltr.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.string.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/flutter_logo.string.rtl.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/line.em_ex.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/line.em_ex2.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/rect.em_ex.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/rect.em_ex2.png (100%) rename {test => packages/flutter_svg/test}/golden_widget/stick_figure.withclipping.png (100%) create mode 100644 packages/flutter_svg/test/golden_widget/text_color_filter.png rename {test => packages/flutter_svg/test}/golden_widget/two_of_same.png (100%) rename {test => packages/flutter_svg/test}/loaders_test.dart (100%) rename {test => packages/flutter_svg/test}/no_width_height_test.dart (100%) rename {test => packages/flutter_svg/test}/widget_svg_test.dart (100%) create mode 100644 packages/flutter_svg_test/README.md create mode 100644 packages/flutter_svg_test/lib/flutter_svg_test.dart create mode 100644 packages/flutter_svg_test/pubspec.yaml create mode 100644 packages/flutter_svg_test/test/flutter_logo.svg create mode 100644 packages/flutter_svg_test/test/flutter_svg_test_test.dart diff --git a/.github/workflows/ci.yml b/.github/workflows/flutter_svg.yml similarity index 89% rename from .github/workflows/ci.yml rename to .github/workflows/flutter_svg.yml index c691fbe3..4ab36135 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/flutter_svg.yml @@ -11,6 +11,9 @@ on: jobs: build: runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/flutter_svg steps: - uses: actions/checkout@v3 - uses: subosito/flutter-action@v2 diff --git a/.github/workflows/flutter_svg_test.yml b/.github/workflows/flutter_svg_test.yml new file mode 100644 index 00000000..daeea37a --- /dev/null +++ b/.github/workflows/flutter_svg_test.yml @@ -0,0 +1,30 @@ +name: analyze and test flutter_svg_test + +on: + push: + branches: [master] + paths-ignore: + - '**/*.md' + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/flutter_svg_test + steps: + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 + with: + channel: 'stable' + - run: flutter --version + - run: flutter pub get + - run: dart format --set-exit-if-changed . + - run: flutter analyze . + - run: flutter test --coverage + # - uses: romeovs/lcov-reporter-action@v0.2.16 + # with: + # lcov-file: ./packages/vector_graphics_codec/coverage/lcov.info + # github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 8dd4cc08..c6346e7f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ pubspec.lock .pub/ build/ ios/.generated/ -packages .flutter-plugins doc/api/ coverage/ diff --git a/README.md b/README.md index 3e7c72d4..5aafb63f 100644 --- a/README.md +++ b/README.md @@ -8,117 +8,24 @@ Draw SVG files using Flutter. -## Getting Started +## Overview -This package provides a wrapper around Dart implementations of SVG parsing, +This library consists of two packages: +[**flutter_svg** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) +and +[**flutter_svg_test** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test). + +[flutter_svg](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test) +provides a wrapper around Dart implementations of SVG parsing, including SVG path data. In particular, it provides efficient `BytesLoader` implementations for [`package:vector_graphics`](https://pub.dev/packages/vector_graphics). -This package is easier to use but not as performant as using the +The package is easier to use but not as performant as using the `vector_graphics` and `vector_graphics_compiler` packages directly. Those packages allow you to do ahead-of-time compilation and optimization of SVGs, and offer some more performant rasterization strategies at runtime. -Basic usage (to create an SVG rendering widget from an asset): - -```dart -final String assetName = 'assets/image.svg'; -final Widget svg = SvgPicture.asset( - assetName, - semanticsLabel: 'Acme Logo' -); -``` - -You can color/tint the image like so: - -```dart -final String assetName = 'assets/up_arrow.svg'; -final Widget svgIcon = SvgPicture.asset( - assetName, - colorFilter: ColorFilter.mode(Colors.red, BlendMode.srcIn), - semanticsLabel: 'A red up arrow' -); -``` - -The default placeholder is an empty box (`LimitedBox`) - although if a `height` -or `width` is specified on the `SvgPicture`, a `SizedBox` will be used instead -(which ensures better layout experience). There is currently no way to show an -Error visually, however errors will get properly logged to the console in debug -mode. - -You can also specify a placeholder widget. The placeholder will display during -parsing/loading (normally only relevant for network access). - -```dart -// Will print error messages to the console. -final String assetName = 'assets/image_that_does_not_exist.svg'; -final Widget svg = SvgPicture.asset( - assetName, -); - -final Widget networkSvg = SvgPicture.network( - 'https://site-that-takes-a-while.com/image.svg', - semanticsLabel: 'A shark?!', - placeholderBuilder: (BuildContext context) => Container( - padding: const EdgeInsets.all(30.0), - child: const CircularProgressIndicator()), -); -``` - -If you'd like to render the SVG to some other canvas, you can do something like: - -```dart -import 'package:flutter_svg/flutter_svg.dart'; -final String rawSvg = '''...'''; -final PictureInfo pictureInfo = await vg.loadPicture(SvgStringLoader(rawSvg), null); - -// You can draw the picture to a canvas: -canvas.drawPicture(pictureInfo.picture); - -// Or convert the picture to a an image: -final ui.Image image = pictureInfo.picture.toImage(...); - -pictureInfo.picture.dispose(); -``` - -The `SvgPicture` helps to automate this logic, and it provides some convenience -wrappers for getting assets from multiple sources. Unlike the `vector_graphics` -package, this package _does not render the data to an `Image` at any point_. -This carries a performance penalty for some common use cases, but also allows -for more flexibility around scaling. - -See [main.dart](/../master/example/lib/main.dart) for a complete sample. - -## Precompiling and Optimizing SVGs - -The vector_graphics backend supports SVG compilation which produces a binary -format that is faster to parse and can optimize SVGs to reduce the amount of -clipping, masking, and overdraw. The SVG compilation is provided by -[`package:vector_graphics_compiler`](https://pub.dev/packages/vector_graphics_compiler). - -```sh -dart run vector_graphics_compiler -i assets/foo.svg -o assets/foo.svg.vec -``` - -The output `foo.svg.vec` can be loaded using the default constructor of -`SvgPicture`. - -```dart -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:vector_graphics/vector_graphics.dart'; - -final Widget svg = SvgPicture( - const AssetBytesLoader('assets/foo.svg.vec') -); -``` - -### Check SVG compatibility - -An SVG can be tested for compatibility with the vector graphics backend by -running the compiler locally to see if any errors are thrown. - -```sh -dart run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETED --no-optimize-masks --no-optimize-clips --no-optimize-overdraw --no-tessellate -``` +[**flutter_svg_test** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test) +provides a set of functions to find images generated by `flutter_svg` in widget tests. ## Out of scope/non-goals @@ -130,40 +37,6 @@ dart run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETE - Foreign elements - Rendering properties/hints -## Recommended Adobe Illustrator SVG Configuration -- In Styling: choose Presentation Attributes instead of Inline CSS because CSS is not fully supported. -- In Images: choose Embded not Linked to other file to get a single svg with no dependency to other files. -- In Objects IDs: choose layer names to add every layer name to svg tags or you can use minimal,it is optional. -![Export configuration](https://user-images.githubusercontent.com/2842459/62599914-91de9c00-b8fe-11e9-8fb7-4af57d5100f7.png) - -## SVG sample attribution - -SVGs in `/assets/w3samples` pulled from [W3 sample files](https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/) - -SVGs in `/assets/deborah_ufw` provided by @deborah-ufw - -SVGs in `/assets/simple` are pulled from trivial examples or generated to test -basic functionality - some of them come directly from the SVG 1.1 spec. Some -have also come or been adapted from issues raised in this repository. - -SVGs in `/assets/wikimedia` are pulled from [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) - -Android Drawables in `/assets/android_vd` are pulled from Android Documentation -and examples. - -The Flutter Logo created based on the Flutter Logo Widget © Google. - -The Dart logo is from -[dartlang.org](https://github.com/dart-lang/site-shared/blob/master/src/_assets/images/dart/logo%2Btext/horizontal/original.svg) -© Google - -SVGs in `/assets/noto-emoji` are from [Google i18n noto-emoji](https://github.com/googlei18n/noto-emoji), -licensed under the Apache license. - -Please submit SVGs that can't render properly (e.g. that don't render here the -way they do in chrome), as long as they're not using anything "probably out of -scope" (above). - ## Alternatives - [vector_graphics](https://pub.dev/packages/vector_graphics) which powers this package. diff --git a/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to packages/flutter_svg/CHANGELOG.md diff --git a/packages/flutter_svg/README.md b/packages/flutter_svg/README.md new file mode 100644 index 00000000..9ac9beb9 --- /dev/null +++ b/packages/flutter_svg/README.md @@ -0,0 +1,147 @@ +# flutter_svg + +[![Pub](https://img.shields.io/pub/v/flutter_svg.svg)](https://pub.dartlang.org/packages/flutter_svg) [![Coverage Status](https://coveralls.io/repos/github/dnfield/flutter_svg/badge.svg?branch=master)](https://coveralls.io/github/dnfield/flutter_svg?branch=master) + + +Flutter Logo which can be rendered by this package! + + +Draw SVG files using Flutter. + +## Getting Started + +Basic usage (to create an SVG rendering widget from an asset): + +```dart +final String assetName = 'assets/image.svg'; +final Widget svg = SvgPicture.asset( + assetName, + semanticsLabel: 'Acme Logo' +); +``` + +You can color/tint the image like so: + +```dart +final String assetName = 'assets/up_arrow.svg'; +final Widget svgIcon = SvgPicture.asset( + assetName, + colorFilter: ColorFilter.mode(Colors.red, BlendMode.srcIn), + semanticsLabel: 'A red up arrow' +); +``` + +The default placeholder is an empty box (`LimitedBox`) - although if a `height` +or `width` is specified on the `SvgPicture`, a `SizedBox` will be used instead +(which ensures better layout experience). There is currently no way to show an +Error visually, however errors will get properly logged to the console in debug +mode. + +You can also specify a placeholder widget. The placeholder will display during +parsing/loading (normally only relevant for network access). + +```dart +// Will print error messages to the console. +final String assetName = 'assets/image_that_does_not_exist.svg'; +final Widget svg = SvgPicture.asset( + assetName, +); + +final Widget networkSvg = SvgPicture.network( + 'https://site-that-takes-a-while.com/image.svg', + semanticsLabel: 'A shark?!', + placeholderBuilder: (BuildContext context) => Container( + padding: const EdgeInsets.all(30.0), + child: const CircularProgressIndicator()), +); +``` + +If you'd like to render the SVG to some other canvas, you can do something like: + +```dart +import 'package:flutter_svg/flutter_svg.dart'; +final String rawSvg = '''...'''; +final PictureInfo pictureInfo = await vg.loadPicture(SvgStringLoader(rawSvg), null); + +// You can draw the picture to a canvas: +canvas.drawPicture(pictureInfo.picture); + +// Or convert the picture to a an image: +final ui.Image image = pictureInfo.picture.toImage(...); + +pictureInfo.picture.dispose(); +``` + +The `SvgPicture` helps to automate this logic, and it provides some convenience +wrappers for getting assets from multiple sources. Unlike the `vector_graphics` +package, this package _does not render the data to an `Image` at any point_. +This carries a performance penalty for some common use cases, but also allows +for more flexibility around scaling. + +See [main.dart](/../master/example/lib/main.dart) for a complete sample. + +## Precompiling and Optimizing SVGs + +The vector_graphics backend supports SVG compilation which produces a binary +format that is faster to parse and can optimize SVGs to reduce the amount of +clipping, masking, and overdraw. The SVG compilation is provided by +[`package:vector_graphics_compiler`](https://pub.dev/packages/vector_graphics_compiler). + +```sh +dart run vector_graphics_compiler -i assets/foo.svg -o assets/foo.svg.vec +``` + +The output `foo.svg.vec` can be loaded using the default constructor of +`SvgPicture`. + +```dart +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:vector_graphics/vector_graphics.dart'; + +final Widget svg = SvgPicture( + const AssetBytesLoader('assets/foo.svg.vec') +); +``` + +### Check SVG compatibility + +An SVG can be tested for compatibility with the vector graphics backend by +running the compiler locally to see if any errors are thrown. + +```sh +dart run vector_graphics_compiler -i $SVG_FILE -o $TEMPORARY_OUTPUT_TO_BE_DELETED --no-optimize-masks --no-optimize-clips --no-optimize-overdraw --no-tessellate +``` + +## Recommended Adobe Illustrator SVG Configuration +- In Styling: choose Presentation Attributes instead of Inline CSS because CSS is not fully supported. +- In Images: choose Embded not Linked to other file to get a single svg with no dependency to other files. +- In Objects IDs: choose layer names to add every layer name to svg tags or you can use minimal,it is optional. +![Export configuration](https://user-images.githubusercontent.com/2842459/62599914-91de9c00-b8fe-11e9-8fb7-4af57d5100f7.png) + +## SVG sample attribution + +SVGs in `/assets/w3samples` pulled from [W3 sample files](https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/) + +SVGs in `/assets/deborah_ufw` provided by @deborah-ufw + +SVGs in `/assets/simple` are pulled from trivial examples or generated to test +basic functionality - some of them come directly from the SVG 1.1 spec. Some +have also come or been adapted from issues raised in this repository. + +SVGs in `/assets/wikimedia` are pulled from [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) + +Android Drawables in `/assets/android_vd` are pulled from Android Documentation +and examples. + +The Flutter Logo created based on the Flutter Logo Widget © Google. + +The Dart logo is from +[dartlang.org](https://github.com/dart-lang/site-shared/blob/master/src/_assets/images/dart/logo%2Btext/horizontal/original.svg) +© Google + +SVGs in `/assets/noto-emoji` are from [Google i18n noto-emoji](https://github.com/googlei18n/noto-emoji), +licensed under the Apache license. + +Please submit SVGs that can't render properly (e.g. that don't render here the +way they do in chrome), as long as they're not using anything "probably out of +scope" (above). diff --git a/example/.gitignore b/packages/flutter_svg/example/.gitignore similarity index 100% rename from example/.gitignore rename to packages/flutter_svg/example/.gitignore diff --git a/example/.metadata b/packages/flutter_svg/example/.metadata similarity index 100% rename from example/.metadata rename to packages/flutter_svg/example/.metadata diff --git a/example/README.md b/packages/flutter_svg/example/README.md similarity index 100% rename from example/README.md rename to packages/flutter_svg/example/README.md diff --git a/example/analysis_options.yaml b/packages/flutter_svg/example/analysis_options.yaml similarity index 100% rename from example/analysis_options.yaml rename to packages/flutter_svg/example/analysis_options.yaml diff --git a/example/android/.gitignore b/packages/flutter_svg/example/android/.gitignore similarity index 100% rename from example/android/.gitignore rename to packages/flutter_svg/example/android/.gitignore diff --git a/example/android/app/build.gradle b/packages/flutter_svg/example/android/app/build.gradle similarity index 100% rename from example/android/app/build.gradle rename to packages/flutter_svg/example/android/app/build.gradle diff --git a/example/android/app/src/debug/AndroidManifest.xml b/packages/flutter_svg/example/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from example/android/app/src/debug/AndroidManifest.xml rename to packages/flutter_svg/example/android/app/src/debug/AndroidManifest.xml diff --git a/example/android/app/src/main/AndroidManifest.xml b/packages/flutter_svg/example/android/app/src/main/AndroidManifest.xml similarity index 100% rename from example/android/app/src/main/AndroidManifest.xml rename to packages/flutter_svg/example/android/app/src/main/AndroidManifest.xml diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/flutter_svg/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt similarity index 100% rename from example/android/app/src/main/kotlin/com/example/example/MainActivity.kt rename to packages/flutter_svg/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/flutter_svg/example/android/app/src/main/res/drawable-v21/launch_background.xml similarity index 100% rename from example/android/app/src/main/res/drawable-v21/launch_background.xml rename to packages/flutter_svg/example/android/app/src/main/res/drawable-v21/launch_background.xml diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/packages/flutter_svg/example/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from example/android/app/src/main/res/drawable/launch_background.xml rename to packages/flutter_svg/example/android/app/src/main/res/drawable/launch_background.xml diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/flutter_svg/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to packages/flutter_svg/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/flutter_svg/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to packages/flutter_svg/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/flutter_svg/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to packages/flutter_svg/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/flutter_svg/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to packages/flutter_svg/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/flutter_svg/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to packages/flutter_svg/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/values-night/styles.xml b/packages/flutter_svg/example/android/app/src/main/res/values-night/styles.xml similarity index 100% rename from example/android/app/src/main/res/values-night/styles.xml rename to packages/flutter_svg/example/android/app/src/main/res/values-night/styles.xml diff --git a/example/android/app/src/main/res/values/styles.xml b/packages/flutter_svg/example/android/app/src/main/res/values/styles.xml similarity index 100% rename from example/android/app/src/main/res/values/styles.xml rename to packages/flutter_svg/example/android/app/src/main/res/values/styles.xml diff --git a/example/android/app/src/profile/AndroidManifest.xml b/packages/flutter_svg/example/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from example/android/app/src/profile/AndroidManifest.xml rename to packages/flutter_svg/example/android/app/src/profile/AndroidManifest.xml diff --git a/example/android/build.gradle b/packages/flutter_svg/example/android/build.gradle similarity index 100% rename from example/android/build.gradle rename to packages/flutter_svg/example/android/build.gradle diff --git a/example/android/example_android.iml b/packages/flutter_svg/example/android/example_android.iml similarity index 100% rename from example/android/example_android.iml rename to packages/flutter_svg/example/android/example_android.iml diff --git a/example/android/gradle.properties b/packages/flutter_svg/example/android/gradle.properties similarity index 100% rename from example/android/gradle.properties rename to packages/flutter_svg/example/android/gradle.properties diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/flutter_svg/example/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.properties rename to packages/flutter_svg/example/android/gradle/wrapper/gradle-wrapper.properties diff --git a/example/android/settings.gradle b/packages/flutter_svg/example/android/settings.gradle similarity index 100% rename from example/android/settings.gradle rename to packages/flutter_svg/example/android/settings.gradle diff --git a/example/assets/android_vd/battery_charging.xml b/packages/flutter_svg/example/assets/android_vd/battery_charging.xml similarity index 100% rename from example/assets/android_vd/battery_charging.xml rename to packages/flutter_svg/example/assets/android_vd/battery_charging.xml diff --git a/example/assets/dart.svg b/packages/flutter_svg/example/assets/dart.svg similarity index 100% rename from example/assets/dart.svg rename to packages/flutter_svg/example/assets/dart.svg diff --git a/example/assets/deborah_ufw/new-action-expander.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-action-expander.svg similarity index 100% rename from example/assets/deborah_ufw/new-action-expander.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-action-expander.svg diff --git a/example/assets/deborah_ufw/new-camera.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-camera.svg similarity index 100% rename from example/assets/deborah_ufw/new-camera.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-camera.svg diff --git a/example/assets/deborah_ufw/new-gif-button.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-gif-button.svg similarity index 100% rename from example/assets/deborah_ufw/new-gif-button.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-gif-button.svg diff --git a/example/assets/deborah_ufw/new-gif.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-gif.svg similarity index 100% rename from example/assets/deborah_ufw/new-gif.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-gif.svg diff --git a/example/assets/deborah_ufw/new-image.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-image.svg similarity index 100% rename from example/assets/deborah_ufw/new-image.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-image.svg diff --git a/example/assets/deborah_ufw/new-mention.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-mention.svg similarity index 100% rename from example/assets/deborah_ufw/new-mention.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-mention.svg diff --git a/example/assets/deborah_ufw/new-pause-button.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-pause-button.svg similarity index 100% rename from example/assets/deborah_ufw/new-pause-button.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-pause-button.svg diff --git a/example/assets/deborah_ufw/new-play-button.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-play-button.svg similarity index 100% rename from example/assets/deborah_ufw/new-play-button.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-play-button.svg diff --git a/example/assets/deborah_ufw/new-send-circle.svg b/packages/flutter_svg/example/assets/deborah_ufw/new-send-circle.svg similarity index 100% rename from example/assets/deborah_ufw/new-send-circle.svg rename to packages/flutter_svg/example/assets/deborah_ufw/new-send-circle.svg diff --git a/example/assets/deborah_ufw/numeric_25.svg b/packages/flutter_svg/example/assets/deborah_ufw/numeric_25.svg similarity index 100% rename from example/assets/deborah_ufw/numeric_25.svg rename to packages/flutter_svg/example/assets/deborah_ufw/numeric_25.svg diff --git a/example/assets/flutter_logo.svg b/packages/flutter_svg/example/assets/flutter_logo.svg similarity index 100% rename from example/assets/flutter_logo.svg rename to packages/flutter_svg/example/assets/flutter_logo.svg diff --git a/example/assets/noto-emoji/emoji_u1f600.svg b/packages/flutter_svg/example/assets/noto-emoji/emoji_u1f600.svg similarity index 100% rename from example/assets/noto-emoji/emoji_u1f600.svg rename to packages/flutter_svg/example/assets/noto-emoji/emoji_u1f600.svg diff --git a/example/assets/simple/blend_and_mask.svg b/packages/flutter_svg/example/assets/simple/blend_and_mask.svg similarity index 100% rename from example/assets/simple/blend_and_mask.svg rename to packages/flutter_svg/example/assets/simple/blend_and_mask.svg diff --git a/example/assets/simple/blend_mode_devil.svg b/packages/flutter_svg/example/assets/simple/blend_mode_devil.svg similarity index 100% rename from example/assets/simple/blend_mode_devil.svg rename to packages/flutter_svg/example/assets/simple/blend_mode_devil.svg diff --git a/example/assets/simple/clip_path.svg b/packages/flutter_svg/example/assets/simple/clip_path.svg similarity index 100% rename from example/assets/simple/clip_path.svg rename to packages/flutter_svg/example/assets/simple/clip_path.svg diff --git a/example/assets/simple/clip_path_2.svg b/packages/flutter_svg/example/assets/simple/clip_path_2.svg similarity index 100% rename from example/assets/simple/clip_path_2.svg rename to packages/flutter_svg/example/assets/simple/clip_path_2.svg diff --git a/example/assets/simple/clip_path_3.svg b/packages/flutter_svg/example/assets/simple/clip_path_3.svg similarity index 100% rename from example/assets/simple/clip_path_3.svg rename to packages/flutter_svg/example/assets/simple/clip_path_3.svg diff --git a/example/assets/simple/clip_path_transform.svg b/packages/flutter_svg/example/assets/simple/clip_path_transform.svg similarity index 100% rename from example/assets/simple/clip_path_transform.svg rename to packages/flutter_svg/example/assets/simple/clip_path_transform.svg diff --git a/example/assets/simple/dash_path.svg b/packages/flutter_svg/example/assets/simple/dash_path.svg similarity index 100% rename from example/assets/simple/dash_path.svg rename to packages/flutter_svg/example/assets/simple/dash_path.svg diff --git a/example/assets/simple/dash_zero.svg b/packages/flutter_svg/example/assets/simple/dash_zero.svg similarity index 100% rename from example/assets/simple/dash_zero.svg rename to packages/flutter_svg/example/assets/simple/dash_zero.svg diff --git a/example/assets/simple/ellipse.svg b/packages/flutter_svg/example/assets/simple/ellipse.svg similarity index 100% rename from example/assets/simple/ellipse.svg rename to packages/flutter_svg/example/assets/simple/ellipse.svg diff --git a/example/assets/simple/empty_defs.svg b/packages/flutter_svg/example/assets/simple/empty_defs.svg similarity index 100% rename from example/assets/simple/empty_defs.svg rename to packages/flutter_svg/example/assets/simple/empty_defs.svg diff --git a/example/assets/simple/empty_group.svg b/packages/flutter_svg/example/assets/simple/empty_group.svg similarity index 100% rename from example/assets/simple/empty_group.svg rename to packages/flutter_svg/example/assets/simple/empty_group.svg diff --git a/example/assets/simple/equation.svg b/packages/flutter_svg/example/assets/simple/equation.svg similarity index 100% rename from example/assets/simple/equation.svg rename to packages/flutter_svg/example/assets/simple/equation.svg diff --git a/example/assets/simple/fill-rule-inherit.svg b/packages/flutter_svg/example/assets/simple/fill-rule-inherit.svg similarity index 100% rename from example/assets/simple/fill-rule-inherit.svg rename to packages/flutter_svg/example/assets/simple/fill-rule-inherit.svg diff --git a/example/assets/simple/fill_inheritence_test.svg b/packages/flutter_svg/example/assets/simple/fill_inheritence_test.svg similarity index 100% rename from example/assets/simple/fill_inheritence_test.svg rename to packages/flutter_svg/example/assets/simple/fill_inheritence_test.svg diff --git a/example/assets/simple/group_composite_opacity.svg b/packages/flutter_svg/example/assets/simple/group_composite_opacity.svg similarity index 100% rename from example/assets/simple/group_composite_opacity.svg rename to packages/flutter_svg/example/assets/simple/group_composite_opacity.svg diff --git a/example/assets/simple/group_fill_opacity.svg b/packages/flutter_svg/example/assets/simple/group_fill_opacity.svg similarity index 100% rename from example/assets/simple/group_fill_opacity.svg rename to packages/flutter_svg/example/assets/simple/group_fill_opacity.svg diff --git a/example/assets/simple/group_in_defs.svg b/packages/flutter_svg/example/assets/simple/group_in_defs.svg similarity index 100% rename from example/assets/simple/group_in_defs.svg rename to packages/flutter_svg/example/assets/simple/group_in_defs.svg diff --git a/example/assets/simple/group_mask.svg b/packages/flutter_svg/example/assets/simple/group_mask.svg similarity index 100% rename from example/assets/simple/group_mask.svg rename to packages/flutter_svg/example/assets/simple/group_mask.svg diff --git a/example/assets/simple/group_opacity.svg b/packages/flutter_svg/example/assets/simple/group_opacity.svg similarity index 100% rename from example/assets/simple/group_opacity.svg rename to packages/flutter_svg/example/assets/simple/group_opacity.svg diff --git a/example/assets/simple/group_opacity_transform.svg b/packages/flutter_svg/example/assets/simple/group_opacity_transform.svg similarity index 100% rename from example/assets/simple/group_opacity_transform.svg rename to packages/flutter_svg/example/assets/simple/group_opacity_transform.svg diff --git a/example/assets/simple/hidden.svg b/packages/flutter_svg/example/assets/simple/hidden.svg similarity index 100% rename from example/assets/simple/hidden.svg rename to packages/flutter_svg/example/assets/simple/hidden.svg diff --git a/example/assets/simple/href-fill.svg b/packages/flutter_svg/example/assets/simple/href-fill.svg similarity index 100% rename from example/assets/simple/href-fill.svg rename to packages/flutter_svg/example/assets/simple/href-fill.svg diff --git a/example/assets/simple/image.svg b/packages/flutter_svg/example/assets/simple/image.svg similarity index 100% rename from example/assets/simple/image.svg rename to packages/flutter_svg/example/assets/simple/image.svg diff --git a/example/assets/simple/image_def.svg b/packages/flutter_svg/example/assets/simple/image_def.svg similarity index 100% rename from example/assets/simple/image_def.svg rename to packages/flutter_svg/example/assets/simple/image_def.svg diff --git a/example/assets/simple/image_transform_before_translate.svg b/packages/flutter_svg/example/assets/simple/image_transform_before_translate.svg similarity index 100% rename from example/assets/simple/image_transform_before_translate.svg rename to packages/flutter_svg/example/assets/simple/image_transform_before_translate.svg diff --git a/example/assets/simple/implicit_fill_with_opacity.svg b/packages/flutter_svg/example/assets/simple/implicit_fill_with_opacity.svg similarity index 100% rename from example/assets/simple/implicit_fill_with_opacity.svg rename to packages/flutter_svg/example/assets/simple/implicit_fill_with_opacity.svg diff --git a/example/assets/simple/invalid_dash_array.svg b/packages/flutter_svg/example/assets/simple/invalid_dash_array.svg similarity index 100% rename from example/assets/simple/invalid_dash_array.svg rename to packages/flutter_svg/example/assets/simple/invalid_dash_array.svg diff --git a/example/assets/simple/linear_gradient.svg b/packages/flutter_svg/example/assets/simple/linear_gradient.svg similarity index 100% rename from example/assets/simple/linear_gradient.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient.svg diff --git a/example/assets/simple/linear_gradient_2.svg b/packages/flutter_svg/example/assets/simple/linear_gradient_2.svg similarity index 100% rename from example/assets/simple/linear_gradient_2.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient_2.svg diff --git a/example/assets/simple/linear_gradient_absolute_user_space_translate.svg b/packages/flutter_svg/example/assets/simple/linear_gradient_absolute_user_space_translate.svg similarity index 100% rename from example/assets/simple/linear_gradient_absolute_user_space_translate.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient_absolute_user_space_translate.svg diff --git a/example/assets/simple/linear_gradient_percentage_bounding_translate.svg b/packages/flutter_svg/example/assets/simple/linear_gradient_percentage_bounding_translate.svg similarity index 100% rename from example/assets/simple/linear_gradient_percentage_bounding_translate.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient_percentage_bounding_translate.svg diff --git a/example/assets/simple/linear_gradient_percentage_user_space_translate.svg b/packages/flutter_svg/example/assets/simple/linear_gradient_percentage_user_space_translate.svg similarity index 100% rename from example/assets/simple/linear_gradient_percentage_user_space_translate.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient_percentage_user_space_translate.svg diff --git a/example/assets/simple/linear_gradient_xlink.svg b/packages/flutter_svg/example/assets/simple/linear_gradient_xlink.svg similarity index 100% rename from example/assets/simple/linear_gradient_xlink.svg rename to packages/flutter_svg/example/assets/simple/linear_gradient_xlink.svg diff --git a/example/assets/simple/male.svg b/packages/flutter_svg/example/assets/simple/male.svg similarity index 100% rename from example/assets/simple/male.svg rename to packages/flutter_svg/example/assets/simple/male.svg diff --git a/example/assets/simple/mask.svg b/packages/flutter_svg/example/assets/simple/mask.svg similarity index 100% rename from example/assets/simple/mask.svg rename to packages/flutter_svg/example/assets/simple/mask.svg diff --git a/example/assets/simple/mask_with_gradient.svg b/packages/flutter_svg/example/assets/simple/mask_with_gradient.svg similarity index 100% rename from example/assets/simple/mask_with_gradient.svg rename to packages/flutter_svg/example/assets/simple/mask_with_gradient.svg diff --git a/example/assets/simple/mask_with_use.svg b/packages/flutter_svg/example/assets/simple/mask_with_use.svg similarity index 100% rename from example/assets/simple/mask_with_use.svg rename to packages/flutter_svg/example/assets/simple/mask_with_use.svg diff --git a/example/assets/simple/mask_with_use2.svg b/packages/flutter_svg/example/assets/simple/mask_with_use2.svg similarity index 100% rename from example/assets/simple/mask_with_use2.svg rename to packages/flutter_svg/example/assets/simple/mask_with_use2.svg diff --git a/example/assets/simple/nested_group.svg b/packages/flutter_svg/example/assets/simple/nested_group.svg similarity index 100% rename from example/assets/simple/nested_group.svg rename to packages/flutter_svg/example/assets/simple/nested_group.svg diff --git a/example/assets/simple/opacity_on_path.svg b/packages/flutter_svg/example/assets/simple/opacity_on_path.svg similarity index 100% rename from example/assets/simple/opacity_on_path.svg rename to packages/flutter_svg/example/assets/simple/opacity_on_path.svg diff --git a/example/assets/simple/radial_gradient.svg b/packages/flutter_svg/example/assets/simple/radial_gradient.svg similarity index 100% rename from example/assets/simple/radial_gradient.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient.svg diff --git a/example/assets/simple/radial_gradient_absolute_user_space_translate.svg b/packages/flutter_svg/example/assets/simple/radial_gradient_absolute_user_space_translate.svg similarity index 100% rename from example/assets/simple/radial_gradient_absolute_user_space_translate.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient_absolute_user_space_translate.svg diff --git a/example/assets/simple/radial_gradient_focal.svg b/packages/flutter_svg/example/assets/simple/radial_gradient_focal.svg similarity index 100% rename from example/assets/simple/radial_gradient_focal.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient_focal.svg diff --git a/example/assets/simple/radial_gradient_percentage_bounding_translate.svg b/packages/flutter_svg/example/assets/simple/radial_gradient_percentage_bounding_translate.svg similarity index 100% rename from example/assets/simple/radial_gradient_percentage_bounding_translate.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient_percentage_bounding_translate.svg diff --git a/example/assets/simple/radial_gradient_percentage_user_space_translate.svg b/packages/flutter_svg/example/assets/simple/radial_gradient_percentage_user_space_translate.svg similarity index 100% rename from example/assets/simple/radial_gradient_percentage_user_space_translate.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient_percentage_user_space_translate.svg diff --git a/example/assets/simple/radial_gradient_xlink.svg b/packages/flutter_svg/example/assets/simple/radial_gradient_xlink.svg similarity index 100% rename from example/assets/simple/radial_gradient_xlink.svg rename to packages/flutter_svg/example/assets/simple/radial_gradient_xlink.svg diff --git a/example/assets/simple/radial_ref_linear_gradient.svg b/packages/flutter_svg/example/assets/simple/radial_ref_linear_gradient.svg similarity index 100% rename from example/assets/simple/radial_ref_linear_gradient.svg rename to packages/flutter_svg/example/assets/simple/radial_ref_linear_gradient.svg diff --git a/example/assets/simple/rect_rrect.svg b/packages/flutter_svg/example/assets/simple/rect_rrect.svg similarity index 100% rename from example/assets/simple/rect_rrect.svg rename to packages/flutter_svg/example/assets/simple/rect_rrect.svg diff --git a/example/assets/simple/rect_rrect_no_ry.svg b/packages/flutter_svg/example/assets/simple/rect_rrect_no_ry.svg similarity index 100% rename from example/assets/simple/rect_rrect_no_ry.svg rename to packages/flutter_svg/example/assets/simple/rect_rrect_no_ry.svg diff --git a/example/assets/simple/stroke_inherit_circles.svg b/packages/flutter_svg/example/assets/simple/stroke_inherit_circles.svg similarity index 100% rename from example/assets/simple/stroke_inherit_circles.svg rename to packages/flutter_svg/example/assets/simple/stroke_inherit_circles.svg diff --git a/example/assets/simple/style_attr.svg b/packages/flutter_svg/example/assets/simple/style_attr.svg similarity index 100% rename from example/assets/simple/style_attr.svg rename to packages/flutter_svg/example/assets/simple/style_attr.svg diff --git a/example/assets/simple/text.svg b/packages/flutter_svg/example/assets/simple/text.svg similarity index 100% rename from example/assets/simple/text.svg rename to packages/flutter_svg/example/assets/simple/text.svg diff --git a/example/assets/simple/text_2.svg b/packages/flutter_svg/example/assets/simple/text_2.svg similarity index 100% rename from example/assets/simple/text_2.svg rename to packages/flutter_svg/example/assets/simple/text_2.svg diff --git a/example/assets/simple/text_3.svg b/packages/flutter_svg/example/assets/simple/text_3.svg similarity index 100% rename from example/assets/simple/text_3.svg rename to packages/flutter_svg/example/assets/simple/text_3.svg diff --git a/example/assets/simple/text_4.svg b/packages/flutter_svg/example/assets/simple/text_4.svg similarity index 100% rename from example/assets/simple/text_4.svg rename to packages/flutter_svg/example/assets/simple/text_4.svg diff --git a/example/assets/simple/text_5.svg b/packages/flutter_svg/example/assets/simple/text_5.svg similarity index 100% rename from example/assets/simple/text_5.svg rename to packages/flutter_svg/example/assets/simple/text_5.svg diff --git a/example/assets/simple/text_6.svg b/packages/flutter_svg/example/assets/simple/text_6.svg similarity index 100% rename from example/assets/simple/text_6.svg rename to packages/flutter_svg/example/assets/simple/text_6.svg diff --git a/example/assets/simple/use_circles.svg b/packages/flutter_svg/example/assets/simple/use_circles.svg similarity index 100% rename from example/assets/simple/use_circles.svg rename to packages/flutter_svg/example/assets/simple/use_circles.svg diff --git a/example/assets/simple/use_circles_def.svg b/packages/flutter_svg/example/assets/simple/use_circles_def.svg similarity index 100% rename from example/assets/simple/use_circles_def.svg rename to packages/flutter_svg/example/assets/simple/use_circles_def.svg diff --git a/example/assets/simple/use_emc2.svg b/packages/flutter_svg/example/assets/simple/use_emc2.svg similarity index 100% rename from example/assets/simple/use_emc2.svg rename to packages/flutter_svg/example/assets/simple/use_emc2.svg diff --git a/example/assets/simple/use_fill.svg b/packages/flutter_svg/example/assets/simple/use_fill.svg similarity index 100% rename from example/assets/simple/use_fill.svg rename to packages/flutter_svg/example/assets/simple/use_fill.svg diff --git a/example/assets/simple/use_fill_test.svg b/packages/flutter_svg/example/assets/simple/use_fill_test.svg similarity index 100% rename from example/assets/simple/use_fill_test.svg rename to packages/flutter_svg/example/assets/simple/use_fill_test.svg diff --git a/example/assets/simple/use_opacity_grid.svg b/packages/flutter_svg/example/assets/simple/use_opacity_grid.svg similarity index 100% rename from example/assets/simple/use_opacity_grid.svg rename to packages/flutter_svg/example/assets/simple/use_opacity_grid.svg diff --git a/example/assets/simple/width_height_viewbox.svg b/packages/flutter_svg/example/assets/simple/width_height_viewbox.svg similarity index 100% rename from example/assets/simple/width_height_viewbox.svg rename to packages/flutter_svg/example/assets/simple/width_height_viewbox.svg diff --git a/example/assets/simple/zero_width_strokes.svg b/packages/flutter_svg/example/assets/simple/zero_width_strokes.svg similarity index 100% rename from example/assets/simple/zero_width_strokes.svg rename to packages/flutter_svg/example/assets/simple/zero_width_strokes.svg diff --git a/example/assets/svg_currentcolor.svg b/packages/flutter_svg/example/assets/svg_currentcolor.svg similarity index 100% rename from example/assets/svg_currentcolor.svg rename to packages/flutter_svg/example/assets/svg_currentcolor.svg diff --git a/example/assets/text_transform.svg b/packages/flutter_svg/example/assets/text_transform.svg similarity index 100% rename from example/assets/text_transform.svg rename to packages/flutter_svg/example/assets/text_transform.svg diff --git a/example/assets/w3samples/aa.svg b/packages/flutter_svg/example/assets/w3samples/aa.svg similarity index 100% rename from example/assets/w3samples/aa.svg rename to packages/flutter_svg/example/assets/w3samples/aa.svg diff --git a/example/assets/w3samples/alphachannel.svg b/packages/flutter_svg/example/assets/w3samples/alphachannel.svg similarity index 100% rename from example/assets/w3samples/alphachannel.svg rename to packages/flutter_svg/example/assets/w3samples/alphachannel.svg diff --git a/example/assets/wikimedia/Firefox_Logo_2017.svg b/packages/flutter_svg/example/assets/wikimedia/Firefox_Logo_2017.svg similarity index 100% rename from example/assets/wikimedia/Firefox_Logo_2017.svg rename to packages/flutter_svg/example/assets/wikimedia/Firefox_Logo_2017.svg diff --git a/example/assets/wikimedia/Flag_of_the_United_States.svg b/packages/flutter_svg/example/assets/wikimedia/Flag_of_the_United_States.svg similarity index 100% rename from example/assets/wikimedia/Flag_of_the_United_States.svg rename to packages/flutter_svg/example/assets/wikimedia/Flag_of_the_United_States.svg diff --git a/example/assets/wikimedia/Ghostscript_Tiger.svg b/packages/flutter_svg/example/assets/wikimedia/Ghostscript_Tiger.svg similarity index 100% rename from example/assets/wikimedia/Ghostscript_Tiger.svg rename to packages/flutter_svg/example/assets/wikimedia/Ghostscript_Tiger.svg diff --git a/example/assets/wikimedia/chess_knight.svg b/packages/flutter_svg/example/assets/wikimedia/chess_knight.svg similarity index 100% rename from example/assets/wikimedia/chess_knight.svg rename to packages/flutter_svg/example/assets/wikimedia/chess_knight.svg diff --git a/example/example.iml b/packages/flutter_svg/example/example.iml similarity index 100% rename from example/example.iml rename to packages/flutter_svg/example/example.iml diff --git a/example/example_android.iml b/packages/flutter_svg/example/example_android.iml similarity index 100% rename from example/example_android.iml rename to packages/flutter_svg/example/example_android.iml diff --git a/example/ios/.gitignore b/packages/flutter_svg/example/ios/.gitignore similarity index 100% rename from example/ios/.gitignore rename to packages/flutter_svg/example/ios/.gitignore diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/packages/flutter_svg/example/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from example/ios/Flutter/AppFrameworkInfo.plist rename to packages/flutter_svg/example/ios/Flutter/AppFrameworkInfo.plist diff --git a/example/ios/Flutter/Debug.xcconfig b/packages/flutter_svg/example/ios/Flutter/Debug.xcconfig similarity index 100% rename from example/ios/Flutter/Debug.xcconfig rename to packages/flutter_svg/example/ios/Flutter/Debug.xcconfig diff --git a/example/ios/Flutter/Release.xcconfig b/packages/flutter_svg/example/ios/Flutter/Release.xcconfig similarity index 100% rename from example/ios/Flutter/Release.xcconfig rename to packages/flutter_svg/example/ios/Flutter/Release.xcconfig diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/packages/flutter_svg/example/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from example/ios/Runner.xcodeproj/project.pbxproj rename to packages/flutter_svg/example/ios/Runner.xcodeproj/project.pbxproj diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to packages/flutter_svg/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/flutter_svg/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to packages/flutter_svg/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/flutter_svg/example/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcworkspace/contents.xcworkspacedata rename to packages/flutter_svg/example/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_svg/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/flutter_svg/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/flutter_svg/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to packages/flutter_svg/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/example/ios/Runner/AppDelegate.h b/packages/flutter_svg/example/ios/Runner/AppDelegate.h similarity index 100% rename from example/ios/Runner/AppDelegate.h rename to packages/flutter_svg/example/ios/Runner/AppDelegate.h diff --git a/example/ios/Runner/AppDelegate.m b/packages/flutter_svg/example/ios/Runner/AppDelegate.m similarity index 100% rename from example/ios/Runner/AppDelegate.m rename to packages/flutter_svg/example/ios/Runner/AppDelegate.m diff --git a/example/ios/Runner/AppDelegate.swift b/packages/flutter_svg/example/ios/Runner/AppDelegate.swift similarity index 100% rename from example/ios/Runner/AppDelegate.swift rename to packages/flutter_svg/example/ios/Runner/AppDelegate.swift diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to packages/flutter_svg/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/flutter_svg/example/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/LaunchScreen.storyboard rename to packages/flutter_svg/example/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/packages/flutter_svg/example/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/Main.storyboard rename to packages/flutter_svg/example/ios/Runner/Base.lproj/Main.storyboard diff --git a/example/ios/Runner/Info.plist b/packages/flutter_svg/example/ios/Runner/Info.plist similarity index 100% rename from example/ios/Runner/Info.plist rename to packages/flutter_svg/example/ios/Runner/Info.plist diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/packages/flutter_svg/example/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from example/ios/Runner/Runner-Bridging-Header.h rename to packages/flutter_svg/example/ios/Runner/Runner-Bridging-Header.h diff --git a/example/ios/Runner/main.m b/packages/flutter_svg/example/ios/Runner/main.m similarity index 100% rename from example/ios/Runner/main.m rename to packages/flutter_svg/example/ios/Runner/main.m diff --git a/example/lib/main.dart b/packages/flutter_svg/example/lib/main.dart similarity index 100% rename from example/lib/main.dart rename to packages/flutter_svg/example/lib/main.dart diff --git a/example/lib/simple.dart b/packages/flutter_svg/example/lib/simple.dart similarity index 100% rename from example/lib/simple.dart rename to packages/flutter_svg/example/lib/simple.dart diff --git a/example/linux/.gitignore b/packages/flutter_svg/example/linux/.gitignore similarity index 100% rename from example/linux/.gitignore rename to packages/flutter_svg/example/linux/.gitignore diff --git a/example/linux/CMakeLists.txt b/packages/flutter_svg/example/linux/CMakeLists.txt similarity index 100% rename from example/linux/CMakeLists.txt rename to packages/flutter_svg/example/linux/CMakeLists.txt diff --git a/example/linux/flutter/CMakeLists.txt b/packages/flutter_svg/example/linux/flutter/CMakeLists.txt similarity index 100% rename from example/linux/flutter/CMakeLists.txt rename to packages/flutter_svg/example/linux/flutter/CMakeLists.txt diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/packages/flutter_svg/example/linux/flutter/generated_plugin_registrant.cc similarity index 100% rename from example/linux/flutter/generated_plugin_registrant.cc rename to packages/flutter_svg/example/linux/flutter/generated_plugin_registrant.cc diff --git a/example/linux/flutter/generated_plugin_registrant.h b/packages/flutter_svg/example/linux/flutter/generated_plugin_registrant.h similarity index 100% rename from example/linux/flutter/generated_plugin_registrant.h rename to packages/flutter_svg/example/linux/flutter/generated_plugin_registrant.h diff --git a/example/linux/flutter/generated_plugins.cmake b/packages/flutter_svg/example/linux/flutter/generated_plugins.cmake similarity index 100% rename from example/linux/flutter/generated_plugins.cmake rename to packages/flutter_svg/example/linux/flutter/generated_plugins.cmake diff --git a/example/linux/main.cc b/packages/flutter_svg/example/linux/main.cc similarity index 100% rename from example/linux/main.cc rename to packages/flutter_svg/example/linux/main.cc diff --git a/example/linux/my_application.cc b/packages/flutter_svg/example/linux/my_application.cc similarity index 100% rename from example/linux/my_application.cc rename to packages/flutter_svg/example/linux/my_application.cc diff --git a/example/linux/my_application.h b/packages/flutter_svg/example/linux/my_application.h similarity index 100% rename from example/linux/my_application.h rename to packages/flutter_svg/example/linux/my_application.h diff --git a/example/macos/.gitignore b/packages/flutter_svg/example/macos/.gitignore similarity index 100% rename from example/macos/.gitignore rename to packages/flutter_svg/example/macos/.gitignore diff --git a/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/flutter_svg/example/macos/Flutter/Flutter-Debug.xcconfig similarity index 100% rename from example/macos/Flutter/Flutter-Debug.xcconfig rename to packages/flutter_svg/example/macos/Flutter/Flutter-Debug.xcconfig diff --git a/example/macos/Flutter/Flutter-Release.xcconfig b/packages/flutter_svg/example/macos/Flutter/Flutter-Release.xcconfig similarity index 100% rename from example/macos/Flutter/Flutter-Release.xcconfig rename to packages/flutter_svg/example/macos/Flutter/Flutter-Release.xcconfig diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/packages/flutter_svg/example/macos/Flutter/GeneratedPluginRegistrant.swift similarity index 100% rename from example/macos/Flutter/GeneratedPluginRegistrant.swift rename to packages/flutter_svg/example/macos/Flutter/GeneratedPluginRegistrant.swift diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/packages/flutter_svg/example/macos/Runner.xcodeproj/project.pbxproj similarity index 100% rename from example/macos/Runner.xcodeproj/project.pbxproj rename to packages/flutter_svg/example/macos/Runner.xcodeproj/project.pbxproj diff --git a/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_svg/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/flutter_svg/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/flutter_svg/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to packages/flutter_svg/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/flutter_svg/example/macos/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/macos/Runner.xcworkspace/contents.xcworkspacedata rename to packages/flutter_svg/example/macos/Runner.xcworkspace/contents.xcworkspacedata diff --git a/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/flutter_svg/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to packages/flutter_svg/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/macos/Runner/AppDelegate.swift b/packages/flutter_svg/example/macos/Runner/AppDelegate.swift similarity index 100% rename from example/macos/Runner/AppDelegate.swift rename to packages/flutter_svg/example/macos/Runner/AppDelegate.swift diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png similarity index 100% rename from example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png rename to packages/flutter_svg/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png diff --git a/example/macos/Runner/Base.lproj/MainMenu.xib b/packages/flutter_svg/example/macos/Runner/Base.lproj/MainMenu.xib similarity index 100% rename from example/macos/Runner/Base.lproj/MainMenu.xib rename to packages/flutter_svg/example/macos/Runner/Base.lproj/MainMenu.xib diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/flutter_svg/example/macos/Runner/Configs/AppInfo.xcconfig similarity index 100% rename from example/macos/Runner/Configs/AppInfo.xcconfig rename to packages/flutter_svg/example/macos/Runner/Configs/AppInfo.xcconfig diff --git a/example/macos/Runner/Configs/Debug.xcconfig b/packages/flutter_svg/example/macos/Runner/Configs/Debug.xcconfig similarity index 100% rename from example/macos/Runner/Configs/Debug.xcconfig rename to packages/flutter_svg/example/macos/Runner/Configs/Debug.xcconfig diff --git a/example/macos/Runner/Configs/Release.xcconfig b/packages/flutter_svg/example/macos/Runner/Configs/Release.xcconfig similarity index 100% rename from example/macos/Runner/Configs/Release.xcconfig rename to packages/flutter_svg/example/macos/Runner/Configs/Release.xcconfig diff --git a/example/macos/Runner/Configs/Warnings.xcconfig b/packages/flutter_svg/example/macos/Runner/Configs/Warnings.xcconfig similarity index 100% rename from example/macos/Runner/Configs/Warnings.xcconfig rename to packages/flutter_svg/example/macos/Runner/Configs/Warnings.xcconfig diff --git a/example/macos/Runner/DebugProfile.entitlements b/packages/flutter_svg/example/macos/Runner/DebugProfile.entitlements similarity index 100% rename from example/macos/Runner/DebugProfile.entitlements rename to packages/flutter_svg/example/macos/Runner/DebugProfile.entitlements diff --git a/example/macos/Runner/Info.plist b/packages/flutter_svg/example/macos/Runner/Info.plist similarity index 100% rename from example/macos/Runner/Info.plist rename to packages/flutter_svg/example/macos/Runner/Info.plist diff --git a/example/macos/Runner/MainFlutterWindow.swift b/packages/flutter_svg/example/macos/Runner/MainFlutterWindow.swift similarity index 100% rename from example/macos/Runner/MainFlutterWindow.swift rename to packages/flutter_svg/example/macos/Runner/MainFlutterWindow.swift diff --git a/example/macos/Runner/Release.entitlements b/packages/flutter_svg/example/macos/Runner/Release.entitlements similarity index 100% rename from example/macos/Runner/Release.entitlements rename to packages/flutter_svg/example/macos/Runner/Release.entitlements diff --git a/example/pubspec.yaml b/packages/flutter_svg/example/pubspec.yaml similarity index 100% rename from example/pubspec.yaml rename to packages/flutter_svg/example/pubspec.yaml diff --git a/example/test_driver/bench.dart b/packages/flutter_svg/example/test_driver/bench.dart similarity index 100% rename from example/test_driver/bench.dart rename to packages/flutter_svg/example/test_driver/bench.dart diff --git a/example/test_driver/bench_test.dart b/packages/flutter_svg/example/test_driver/bench_test.dart similarity index 100% rename from example/test_driver/bench_test.dart rename to packages/flutter_svg/example/test_driver/bench_test.dart diff --git a/example/test_driver/repaint.dart b/packages/flutter_svg/example/test_driver/repaint.dart similarity index 100% rename from example/test_driver/repaint.dart rename to packages/flutter_svg/example/test_driver/repaint.dart diff --git a/example/test_driver/repaint_test.dart b/packages/flutter_svg/example/test_driver/repaint_test.dart similarity index 100% rename from example/test_driver/repaint_test.dart rename to packages/flutter_svg/example/test_driver/repaint_test.dart diff --git a/example/web/favicon.png b/packages/flutter_svg/example/web/favicon.png similarity index 100% rename from example/web/favicon.png rename to packages/flutter_svg/example/web/favicon.png diff --git a/example/web/icons/Icon-192.png b/packages/flutter_svg/example/web/icons/Icon-192.png similarity index 100% rename from example/web/icons/Icon-192.png rename to packages/flutter_svg/example/web/icons/Icon-192.png diff --git a/example/web/icons/Icon-512.png b/packages/flutter_svg/example/web/icons/Icon-512.png similarity index 100% rename from example/web/icons/Icon-512.png rename to packages/flutter_svg/example/web/icons/Icon-512.png diff --git a/example/web/icons/Icon-maskable-192.png b/packages/flutter_svg/example/web/icons/Icon-maskable-192.png similarity index 100% rename from example/web/icons/Icon-maskable-192.png rename to packages/flutter_svg/example/web/icons/Icon-maskable-192.png diff --git a/example/web/icons/Icon-maskable-512.png b/packages/flutter_svg/example/web/icons/Icon-maskable-512.png similarity index 100% rename from example/web/icons/Icon-maskable-512.png rename to packages/flutter_svg/example/web/icons/Icon-maskable-512.png diff --git a/example/web/index.html b/packages/flutter_svg/example/web/index.html similarity index 100% rename from example/web/index.html rename to packages/flutter_svg/example/web/index.html diff --git a/example/web/manifest.json b/packages/flutter_svg/example/web/manifest.json similarity index 100% rename from example/web/manifest.json rename to packages/flutter_svg/example/web/manifest.json diff --git a/example/windows/.gitignore b/packages/flutter_svg/example/windows/.gitignore similarity index 100% rename from example/windows/.gitignore rename to packages/flutter_svg/example/windows/.gitignore diff --git a/example/windows/CMakeLists.txt b/packages/flutter_svg/example/windows/CMakeLists.txt similarity index 100% rename from example/windows/CMakeLists.txt rename to packages/flutter_svg/example/windows/CMakeLists.txt diff --git a/example/windows/flutter/CMakeLists.txt b/packages/flutter_svg/example/windows/flutter/CMakeLists.txt similarity index 100% rename from example/windows/flutter/CMakeLists.txt rename to packages/flutter_svg/example/windows/flutter/CMakeLists.txt diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/packages/flutter_svg/example/windows/flutter/generated_plugin_registrant.cc similarity index 100% rename from example/windows/flutter/generated_plugin_registrant.cc rename to packages/flutter_svg/example/windows/flutter/generated_plugin_registrant.cc diff --git a/example/windows/flutter/generated_plugin_registrant.h b/packages/flutter_svg/example/windows/flutter/generated_plugin_registrant.h similarity index 100% rename from example/windows/flutter/generated_plugin_registrant.h rename to packages/flutter_svg/example/windows/flutter/generated_plugin_registrant.h diff --git a/example/windows/flutter/generated_plugins.cmake b/packages/flutter_svg/example/windows/flutter/generated_plugins.cmake similarity index 100% rename from example/windows/flutter/generated_plugins.cmake rename to packages/flutter_svg/example/windows/flutter/generated_plugins.cmake diff --git a/example/windows/runner/CMakeLists.txt b/packages/flutter_svg/example/windows/runner/CMakeLists.txt similarity index 100% rename from example/windows/runner/CMakeLists.txt rename to packages/flutter_svg/example/windows/runner/CMakeLists.txt diff --git a/example/windows/runner/Runner.rc b/packages/flutter_svg/example/windows/runner/Runner.rc similarity index 100% rename from example/windows/runner/Runner.rc rename to packages/flutter_svg/example/windows/runner/Runner.rc diff --git a/example/windows/runner/flutter_window.cpp b/packages/flutter_svg/example/windows/runner/flutter_window.cpp similarity index 100% rename from example/windows/runner/flutter_window.cpp rename to packages/flutter_svg/example/windows/runner/flutter_window.cpp diff --git a/example/windows/runner/flutter_window.h b/packages/flutter_svg/example/windows/runner/flutter_window.h similarity index 100% rename from example/windows/runner/flutter_window.h rename to packages/flutter_svg/example/windows/runner/flutter_window.h diff --git a/example/windows/runner/main.cpp b/packages/flutter_svg/example/windows/runner/main.cpp similarity index 100% rename from example/windows/runner/main.cpp rename to packages/flutter_svg/example/windows/runner/main.cpp diff --git a/example/windows/runner/resource.h b/packages/flutter_svg/example/windows/runner/resource.h similarity index 100% rename from example/windows/runner/resource.h rename to packages/flutter_svg/example/windows/runner/resource.h diff --git a/example/windows/runner/resources/app_icon.ico b/packages/flutter_svg/example/windows/runner/resources/app_icon.ico similarity index 100% rename from example/windows/runner/resources/app_icon.ico rename to packages/flutter_svg/example/windows/runner/resources/app_icon.ico diff --git a/example/windows/runner/run_loop.cpp b/packages/flutter_svg/example/windows/runner/run_loop.cpp similarity index 100% rename from example/windows/runner/run_loop.cpp rename to packages/flutter_svg/example/windows/runner/run_loop.cpp diff --git a/example/windows/runner/run_loop.h b/packages/flutter_svg/example/windows/runner/run_loop.h similarity index 100% rename from example/windows/runner/run_loop.h rename to packages/flutter_svg/example/windows/runner/run_loop.h diff --git a/example/windows/runner/runner.exe.manifest b/packages/flutter_svg/example/windows/runner/runner.exe.manifest similarity index 100% rename from example/windows/runner/runner.exe.manifest rename to packages/flutter_svg/example/windows/runner/runner.exe.manifest diff --git a/example/windows/runner/utils.cpp b/packages/flutter_svg/example/windows/runner/utils.cpp similarity index 100% rename from example/windows/runner/utils.cpp rename to packages/flutter_svg/example/windows/runner/utils.cpp diff --git a/example/windows/runner/utils.h b/packages/flutter_svg/example/windows/runner/utils.h similarity index 100% rename from example/windows/runner/utils.h rename to packages/flutter_svg/example/windows/runner/utils.h diff --git a/example/windows/runner/win32_window.cpp b/packages/flutter_svg/example/windows/runner/win32_window.cpp similarity index 100% rename from example/windows/runner/win32_window.cpp rename to packages/flutter_svg/example/windows/runner/win32_window.cpp diff --git a/example/windows/runner/win32_window.h b/packages/flutter_svg/example/windows/runner/win32_window.h similarity index 100% rename from example/windows/runner/win32_window.h rename to packages/flutter_svg/example/windows/runner/win32_window.h diff --git a/flutter_svg.iml b/packages/flutter_svg/flutter_svg.iml similarity index 100% rename from flutter_svg.iml rename to packages/flutter_svg/flutter_svg.iml diff --git a/flutter_svg_android.iml b/packages/flutter_svg/flutter_svg_android.iml similarity index 100% rename from flutter_svg_android.iml rename to packages/flutter_svg/flutter_svg_android.iml diff --git a/lib/flutter_svg.dart b/packages/flutter_svg/lib/flutter_svg.dart similarity index 100% rename from lib/flutter_svg.dart rename to packages/flutter_svg/lib/flutter_svg.dart diff --git a/lib/src/cache.dart b/packages/flutter_svg/lib/src/cache.dart similarity index 100% rename from lib/src/cache.dart rename to packages/flutter_svg/lib/src/cache.dart diff --git a/lib/src/loaders.dart b/packages/flutter_svg/lib/src/loaders.dart similarity index 100% rename from lib/src/loaders.dart rename to packages/flutter_svg/lib/src/loaders.dart diff --git a/lib/src/utilities/_file_io.dart b/packages/flutter_svg/lib/src/utilities/_file_io.dart similarity index 100% rename from lib/src/utilities/_file_io.dart rename to packages/flutter_svg/lib/src/utilities/_file_io.dart diff --git a/lib/src/utilities/_file_none.dart b/packages/flutter_svg/lib/src/utilities/_file_none.dart similarity index 100% rename from lib/src/utilities/_file_none.dart rename to packages/flutter_svg/lib/src/utilities/_file_none.dart diff --git a/lib/src/utilities/_http_io.dart b/packages/flutter_svg/lib/src/utilities/_http_io.dart similarity index 100% rename from lib/src/utilities/_http_io.dart rename to packages/flutter_svg/lib/src/utilities/_http_io.dart diff --git a/lib/src/utilities/_http_web.dart b/packages/flutter_svg/lib/src/utilities/_http_web.dart similarity index 100% rename from lib/src/utilities/_http_web.dart rename to packages/flutter_svg/lib/src/utilities/_http_web.dart diff --git a/lib/src/utilities/compute.dart b/packages/flutter_svg/lib/src/utilities/compute.dart similarity index 100% rename from lib/src/utilities/compute.dart rename to packages/flutter_svg/lib/src/utilities/compute.dart diff --git a/lib/src/utilities/file.dart b/packages/flutter_svg/lib/src/utilities/file.dart similarity index 100% rename from lib/src/utilities/file.dart rename to packages/flutter_svg/lib/src/utilities/file.dart diff --git a/lib/src/utilities/http.dart b/packages/flutter_svg/lib/src/utilities/http.dart similarity index 100% rename from lib/src/utilities/http.dart rename to packages/flutter_svg/lib/src/utilities/http.dart diff --git a/lib/src/utilities/numbers.dart b/packages/flutter_svg/lib/src/utilities/numbers.dart similarity index 100% rename from lib/src/utilities/numbers.dart rename to packages/flutter_svg/lib/src/utilities/numbers.dart diff --git a/lib/svg.dart b/packages/flutter_svg/lib/svg.dart similarity index 100% rename from lib/svg.dart rename to packages/flutter_svg/lib/svg.dart diff --git a/pubspec.yaml b/packages/flutter_svg/pubspec.yaml similarity index 90% rename from pubspec.yaml rename to packages/flutter_svg/pubspec.yaml index 6801822a..fbf18e77 100644 --- a/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. -repository: https://github.com/dnfield/flutter_svg +repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues version: 2.0.5 diff --git a/test/cache_test.dart b/packages/flutter_svg/test/cache_test.dart similarity index 100% rename from test/cache_test.dart rename to packages/flutter_svg/test/cache_test.dart diff --git a/packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png b/packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b0e37514ac83ab1041e907949218f5592541ad GIT binary patch literal 2247 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzEX7WqAsj$Z!;#X#z`#-G z>EaktG3V`dN8UpW0t}8$6PkN=tzU7NY5qG_tHlZXe^&rC4OK8<*39o^%nWx97Fz?o zu!EnOiGd-7hl7D(f}sKfgTt`~ps3`iASgg8bJ-d8C#LniZR?(Un-Lf;qhK@yMnhmU z1V%#udk7q;p8={|KJ0y722@ZW&&I;Qa6&?Wfk7eJfq|i+hY?ta8jT8q0_5{8J_d$$ lrpCw14j(=D77?5c2iVOH^844-30wdPdb;|#taD0e0swHXiqrrA literal 0 HcmV?d00001 diff --git a/packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png b/packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png new file mode 100644 index 0000000000000000000000000000000000000000..29981f0358e7ef49b05257510617b9e30bfcc942 GIT binary patch literal 2421 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzEX7WqAsj$Z!;#X#z`&{F z>EaktG3V`_y}45zMO-ghiz$_Hnj~}zITXov9NFlts9L1`WXY2)4Z*@SDlKC6LizoF zBUU#}&Wk;J258(61tr(sF&_B*q43#_y$`44^*zp7`!)4DAA?1?_-=Nfm;UoJGBGfu zuy8OiOb}FHU~q720E$YE3W5S85*S414;RW@-)%nU#`CS${=O3g2F@rL4S~@R7!83T z6#{>jZmniuun8?Uo_;_5o~&{HwKGrO+5Wk8_RQ_O(hc{kH-cncfwKI@@z2vMWM+S7 znA6>Tmzm*#X4Q$n-cjfOH zEX?Z;GBvpGng6rQ{PU~CXJu#i*x7i1DjTYT2IFmI{0t0!uOFY;SbbRYuFUbPQLj(G zlRYqh=M7t+O+V^61Q-|;lpPot8hRKQ85oS1SQr>ij0%DRH_kHU?f}XB^F6*2UngHI{-(LU# literal 0 HcmV?d00001 diff --git a/test/golden_widget/text_color_filter.png b/packages/flutter_svg/test/failures/text_color_filter_masterImage.png similarity index 100% rename from test/golden_widget/text_color_filter.png rename to packages/flutter_svg/test/failures/text_color_filter_masterImage.png diff --git a/packages/flutter_svg/test/failures/text_color_filter_testImage.png b/packages/flutter_svg/test/failures/text_color_filter_testImage.png new file mode 100644 index 0000000000000000000000000000000000000000..20ea01b6daa35ee9087c6fea46d2b9302001805e GIT binary patch literal 2429 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq_%q)5S5QV$Rz;hJI55CE6~&XHPmS6w%~;ps7?sIO%Lq&dN0HcSklb z=NP8s=%{D)e2$Sg7kTiu-Or-;JV4`yCU8iPwq>Z0eV6`iwYkjYpJ%SVJ#+Y#EJMMo zb7A~IAKl|)WMW`QVc}q4m>{UYz~JE402GxR6$Ayy&InM@ZJRm!s&wDW%4daNK`Ct% zjE2By2#kinkP3l+2e(x*FzgB0J@d4@vHW-A>$lH5eP#RS-t(FKtIZke%Qk{!U4XL7 zXXby_w)ximoncPb=BvyM4^*pW?UWAZZ}{)mz;Gb(`f7HDIZCkFLFQZOSB8dQ6$gd~ z4dur1Y0rKGYnJ85^dlGw4lJK}{O*~nm(Sca`&{?l(TeJ!HD^QaR|bX$JJ2e&1NSX~ u^&JC4h4pBarhuzDf0hIeI;<62!vTNqBhs5H|K;2S#hIt8pUXO@geCwpCE_{& literal 0 HcmV?d00001 diff --git a/test/golden_widget/circle.em_ex.png b/packages/flutter_svg/test/golden_widget/circle.em_ex.png similarity index 100% rename from test/golden_widget/circle.em_ex.png rename to packages/flutter_svg/test/golden_widget/circle.em_ex.png diff --git a/test/golden_widget/circle.em_ex2.png b/packages/flutter_svg/test/golden_widget/circle.em_ex2.png similarity index 100% rename from test/golden_widget/circle.em_ex2.png rename to packages/flutter_svg/test/golden_widget/circle.em_ex2.png diff --git a/test/golden_widget/columns_and_rows.png b/packages/flutter_svg/test/golden_widget/columns_and_rows.png similarity index 100% rename from test/golden_widget/columns_and_rows.png rename to packages/flutter_svg/test/golden_widget/columns_and_rows.png diff --git a/test/golden_widget/ellipse.em_ex.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex.png similarity index 100% rename from test/golden_widget/ellipse.em_ex.png rename to packages/flutter_svg/test/golden_widget/ellipse.em_ex.png diff --git a/test/golden_widget/ellipse.em_ex2.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png similarity index 100% rename from test/golden_widget/ellipse.em_ex2.png rename to packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png diff --git a/test/golden_widget/flutter_logo.asset.png b/packages/flutter_svg/test/golden_widget/flutter_logo.asset.png similarity index 100% rename from test/golden_widget/flutter_logo.asset.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.asset.png diff --git a/test/golden_widget/flutter_logo.memory.png b/packages/flutter_svg/test/golden_widget/flutter_logo.memory.png similarity index 100% rename from test/golden_widget/flutter_logo.memory.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.memory.png diff --git a/test/golden_widget/flutter_logo.natural.png b/packages/flutter_svg/test/golden_widget/flutter_logo.natural.png similarity index 100% rename from test/golden_widget/flutter_logo.natural.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.natural.png diff --git a/test/golden_widget/flutter_logo.network.png b/packages/flutter_svg/test/golden_widget/flutter_logo.network.png similarity index 100% rename from test/golden_widget/flutter_logo.network.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.network.png diff --git a/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png similarity index 100% rename from test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.blendmode_color.png diff --git a/test/golden_widget/flutter_logo.string.color_filter.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png similarity index 100% rename from test/golden_widget/flutter_logo.string.color_filter.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png diff --git a/test/golden_widget/flutter_logo.string.ltr.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png similarity index 100% rename from test/golden_widget/flutter_logo.string.ltr.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png diff --git a/test/golden_widget/flutter_logo.string.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.png similarity index 100% rename from test/golden_widget/flutter_logo.string.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.string.png diff --git a/test/golden_widget/flutter_logo.string.rtl.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.rtl.png similarity index 100% rename from test/golden_widget/flutter_logo.string.rtl.png rename to packages/flutter_svg/test/golden_widget/flutter_logo.string.rtl.png diff --git a/test/golden_widget/line.em_ex.png b/packages/flutter_svg/test/golden_widget/line.em_ex.png similarity index 100% rename from test/golden_widget/line.em_ex.png rename to packages/flutter_svg/test/golden_widget/line.em_ex.png diff --git a/test/golden_widget/line.em_ex2.png b/packages/flutter_svg/test/golden_widget/line.em_ex2.png similarity index 100% rename from test/golden_widget/line.em_ex2.png rename to packages/flutter_svg/test/golden_widget/line.em_ex2.png diff --git a/test/golden_widget/rect.em_ex.png b/packages/flutter_svg/test/golden_widget/rect.em_ex.png similarity index 100% rename from test/golden_widget/rect.em_ex.png rename to packages/flutter_svg/test/golden_widget/rect.em_ex.png diff --git a/test/golden_widget/rect.em_ex2.png b/packages/flutter_svg/test/golden_widget/rect.em_ex2.png similarity index 100% rename from test/golden_widget/rect.em_ex2.png rename to packages/flutter_svg/test/golden_widget/rect.em_ex2.png diff --git a/test/golden_widget/stick_figure.withclipping.png b/packages/flutter_svg/test/golden_widget/stick_figure.withclipping.png similarity index 100% rename from test/golden_widget/stick_figure.withclipping.png rename to packages/flutter_svg/test/golden_widget/stick_figure.withclipping.png diff --git a/packages/flutter_svg/test/golden_widget/text_color_filter.png b/packages/flutter_svg/test/golden_widget/text_color_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f4360c7c53b47c2192a646c459fe7ba7d38845 GIT binary patch literal 2396 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq|3F)5S5QV$Rz;8*_yNMA|N9a|c$lh;|VJQL@M zE-(%9XDo-{_*o0AHOPn?q%k)XL-*Gzw$Bc zD7$@?nSr6V0f@cF0F61`JBs_&z!w`=J6}p z1NUzN-NeAKM~;bwf#C#)00V=9GSs~c3`V1ZzyLu3|9-HpcqZv`_Vhy)khrI-pUXO@ GgeCwFGScn< literal 0 HcmV?d00001 diff --git a/test/golden_widget/two_of_same.png b/packages/flutter_svg/test/golden_widget/two_of_same.png similarity index 100% rename from test/golden_widget/two_of_same.png rename to packages/flutter_svg/test/golden_widget/two_of_same.png diff --git a/test/loaders_test.dart b/packages/flutter_svg/test/loaders_test.dart similarity index 100% rename from test/loaders_test.dart rename to packages/flutter_svg/test/loaders_test.dart diff --git a/test/no_width_height_test.dart b/packages/flutter_svg/test/no_width_height_test.dart similarity index 100% rename from test/no_width_height_test.dart rename to packages/flutter_svg/test/no_width_height_test.dart diff --git a/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart similarity index 100% rename from test/widget_svg_test.dart rename to packages/flutter_svg/test/widget_svg_test.dart diff --git a/packages/flutter_svg_test/README.md b/packages/flutter_svg_test/README.md new file mode 100644 index 00000000..3a1e3e2d --- /dev/null +++ b/packages/flutter_svg_test/README.md @@ -0,0 +1,44 @@ +# flutter_svg_test + +### Testing + +This package provides a set of functions to find images generated by +[**flutter_svg** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) +in widget tests. + +The methods find elements with the `SvgPicture` type and compare either the `BytesLoader` or the +configuration of the `BytesLoader` with the giving test attribute. + +### Example + +#### Find by BytesLoader + +The following example shows how you can find svgs with the matching `SvgAssetLoader`. + + ```dart +testWidgets('Finds svg', (WidgetTester widgetTester) async { + + final SvgPicture asset = SvgPicture.asset('/test/path/my.svg'); + + await widgetTester.pumpWidget(asset); + + expect(find.svg(asset.bytesLoader), findsOneWidget); +}); +``` + +#### Find by svg path + +Sometimes it is more convenient instead of instantiate the whole `BytesLoader` to +compare only specific attributes. + +The following example shows how you can find svgs with the specified attribute. + + ```dart +testWidgets('asset svg with path', (WidgetTester widgetTester) async { + const String svgPath = 'test/flutter_logo.svg'; + + await widgetTester.pumpWidget(SvgPicture.asset(svgPath)); + + expect(find.svgAssetWithPath(svgPath), findsOneWidget); +}); + ``` diff --git a/packages/flutter_svg_test/lib/flutter_svg_test.dart b/packages/flutter_svg_test/lib/flutter_svg_test.dart new file mode 100644 index 00000000..a2200ef5 --- /dev/null +++ b/packages/flutter_svg_test/lib/flutter_svg_test.dart @@ -0,0 +1,170 @@ +import 'dart:typed_data'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// Extension on common finder to have native feeling +extension CommonFinderExt on CommonFinders { + /// Finds [SvgPicture] widgets containing `svg` equal to the `svg` argument. + /// + /// ## Sample code + /// ```dart + /// expect(find.svg(SvgPicture.asset('assets/asset_name.svg')), findsOneWidget); + /// ``` + /// + /// If the `skipOffstage` argument is true (the default), then this skips + /// nodes that are [Offstage] or that are from inactive [Route]s. + Finder svg(BytesLoader svg, {bool skipOffstage = true}) { + return _SvgFinder(svg, skipOffstage: skipOffstage); + } + + /// Finds widgets created by [SvgPicture.asset] with the [path] argument. + /// ## Sample code + /// ```dart + /// expect(svgAssetWithPath('assets/asset_name.svg'), findsOneWidget); + /// ``` + /// This will match [SvgPicture.asset] with the [path] 'assets/asset_name.svg'. + /// If the `skipOffstage` argument is true (the default), then this skips + /// nodes that are [Offstage] or that are from inactive [Route]s. + Finder svgAssetWithPath(String path, {bool skipOffstage = true}) { + return _SvgAssetWithPathFinder(svgPath: path, skipOffstage: skipOffstage); + } + + /// Finds widgets created by [SvgPicture.network] with the [url] argument. + /// ## Sample code + /// ```dart + /// expect(find.svgNetworkWithUrl('https://svg.dart'), findsOneWidget); + /// ``` + /// This will match [SvgPicture.network] with the [url] https://svg.dart'. + /// If the `skipOffstage` argument is true (the default), then this skips + /// nodes that are [Offstage] or that are from inactive [Route]s. + Finder svgNetworkWithUrl(String url, {bool skipOffstage = true}) { + return _SvgNetworkWithUrlFinder(url: url, skipOffstage: skipOffstage); + } + + /// Finds widgets created by [SvgPicture.memory] with the [bytes] argument. + /// ## Sample code + /// ```dart + /// const Uint8List svgBytes = [1, 2, 3, 4]; + /// expect(find.svgMemoryWithBytes(svgBytes), findsOneWidget); + /// ``` + /// This will match [SvgPicture.memory] with the [bytes] [1,2,3,4]. + /// If the `skipOffstage` argument is true (the default), then this skips + /// nodes that are [Offstage] or that are from inactive [Route]s. + Finder svgMemoryWithBytes(Uint8List bytes, {bool skipOffstage = true}) { + return _SvgMemoryWithBytesFinder(bytes: bytes, skipOffstage: skipOffstage); + } + + /// Finds widgets created by [SvgPicture.file] with the [path] argument. + /// ## Sample code + /// ```dart + /// expect(find.svgFileWithPath('test/flutter_logo.svg'), findsOneWidget); + /// ``` + /// This will match [SvgPicture.file] with the [path] 'test/flutter_logo.svg'. + /// If the `skipOffstage` argument is true (the default), then this skips + /// nodes that are [Offstage] or that are from inactive [Route]s. + Finder svgFileWithPath(String path, {bool skipOffstage = true}) { + return _SvgFileWithPathFinder(path: path, skipOffstage: skipOffstage); + } +} + +class _SvgFinder extends MatchFinder { + _SvgFinder(this._svg, {super.skipOffstage}); + + final BytesLoader _svg; + + @override + String get description => "svg: '$_svg'"; + + @override + bool matches(Element candidate) { + return _getBytesLoader( + candidate, + (BytesLoader loader) => loader == _svg, + ); + } +} + +class _SvgAssetWithPathFinder extends MatchFinder { + _SvgAssetWithPathFinder({required String svgPath, super.skipOffstage}) + : _svgPath = svgPath; + final String _svgPath; + + @override + String get description => "Path: '$_svgPath' and created by SvgPicture.asset"; + + @override + bool matches(Element candidate) { + return _getBytesLoader( + candidate, + (SvgAssetLoader loader) => loader.assetName == _svgPath, + ); + } +} + +class _SvgNetworkWithUrlFinder extends MatchFinder { + _SvgNetworkWithUrlFinder({required String url, super.skipOffstage}) + : _url = url; + final String _url; + + @override + String get description => "Url: '$_url' and created by SvgPicture.network"; + + @override + bool matches(Element candidate) { + return _getBytesLoader( + candidate, + (SvgNetworkLoader loader) => loader.url == _url, + ); + } +} + +class _SvgFileWithPathFinder extends MatchFinder { + _SvgFileWithPathFinder({required String path, super.skipOffstage}) + : _path = path; + final String _path; + + @override + String get description => "Path: '$_path' and created by SvgPicture.file"; + + @override + bool matches(Element candidate) { + return _getBytesLoader( + candidate, + (SvgFileLoader loader) => loader.file.path == _path, + ); + } +} + +class _SvgMemoryWithBytesFinder extends MatchFinder { + _SvgMemoryWithBytesFinder({required Uint8List bytes, super.skipOffstage}) + : _bytes = bytes; + final Uint8List _bytes; + + @override + String get description => "Bytes: '$_bytes' and created by SvgPicture.memory"; + + @override + bool matches(Element candidate) { + return _getBytesLoader( + candidate, + (SvgBytesLoader loader) => loader.bytes == _bytes, + ); + } +} + +bool _getBytesLoader( + Element candidate, + bool Function(T loader) matcher, +) { + bool result = false; + final Widget widget = candidate.widget; + if (widget is SvgPicture) { + final BytesLoader bytesLoader = widget.bytesLoader; + if (bytesLoader is T) { + result = matcher(bytesLoader as T); + } + } + return result; +} diff --git a/packages/flutter_svg_test/pubspec.yaml b/packages/flutter_svg_test/pubspec.yaml new file mode 100644 index 00000000..42877752 --- /dev/null +++ b/packages/flutter_svg_test/pubspec.yaml @@ -0,0 +1,18 @@ +name: flutter_svg_test +description: A testing library which makes it easy to test flutter svg . Built to be used with the flutter svg package. +repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test +issue_tracker: https://github.com/dnfield/flutter_svg/issues +version: 1.0.0 + +dependencies: + flutter: + sdk: flutter + flutter_svg: ^2.0.4 + flutter_test: + sdk: flutter + +environment: + sdk: '>=2.19.0-0 <4.0.0' + flutter: ">=3.7.0-0" + + diff --git a/packages/flutter_svg_test/test/flutter_logo.svg b/packages/flutter_svg_test/test/flutter_logo.svg new file mode 100644 index 00000000..ec3d9144 --- /dev/null +++ b/packages/flutter_svg_test/test/flutter_logo.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/flutter_svg_test/test/flutter_svg_test_test.dart b/packages/flutter_svg_test/test/flutter_svg_test_test.dart new file mode 100644 index 00000000..a3a88e05 --- /dev/null +++ b/packages/flutter_svg_test/test/flutter_svg_test_test.dart @@ -0,0 +1,183 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_svg_test/flutter_svg_test.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('finds', () { + group('with bytesLoader', () { + testWidgets('asset svg', (WidgetTester widgetTester) async { + final SvgPicture asset = SvgPicture.asset('test/flutter_logo.svg'); + await widgetTester.pumpWidget( + DefaultAssetBundle( + bundle: _FakeAssetBundle(), + child: asset, + ), + ); + + expect(find.svg(asset.bytesLoader), findsOneWidget); + }); + + testWidgets('network svg', (WidgetTester widgetTester) async { + await HttpOverrides.runZoned(() async { + final SvgPicture asset = SvgPicture.network('svg.dart'); + await widgetTester.pumpWidget(asset); + + expect(find.svg(asset.bytesLoader), findsOneWidget); + }, createHttpClient: (SecurityContext? c) => _setupFakeClient); + }); + + testWidgets('string svg', (WidgetTester widgetTester) async { + final SvgPicture asset = SvgPicture.string(_svgStr); + await widgetTester.pumpWidget(asset); + + expect(find.svg(asset.bytesLoader), findsOneWidget); + }); + + testWidgets('file svg', (WidgetTester widgetTester) async { + final File file = File('test/flutter_logo.svg'); + final SvgPicture asset = SvgPicture.file(file); + await widgetTester.pumpWidget(asset); + + expect(find.svg(asset.bytesLoader), findsOneWidget); + }); + + testWidgets('memory svg', (WidgetTester widgetTester) async { + final SvgPicture asset = SvgPicture.memory(_svgBytes); + await widgetTester.pumpWidget(asset); + + expect(find.svg(asset.bytesLoader), findsOneWidget); + }); + }); + + testWidgets('asset svg with path', (WidgetTester widgetTester) async { + const String svgPath = 'test/flutter_logo.svg'; + await widgetTester.pumpWidget( + DefaultAssetBundle( + bundle: _FakeAssetBundle(), + child: SvgPicture.asset(svgPath), + ), + ); + + expect(find.svgAssetWithPath(svgPath), findsOneWidget); + }); + + testWidgets('network svg with url', (WidgetTester widgetTester) async { + await HttpOverrides.runZoned(() async { + const String svgUri = 'svg.dart'; + await widgetTester.pumpWidget(SvgPicture.network(svgUri)); + + expect(find.svgNetworkWithUrl(svgUri), findsOneWidget); + }, createHttpClient: (SecurityContext? c) => _setupFakeClient); + }); + + testWidgets('file svg wit path', (WidgetTester widgetTester) async { + const String svgPath = 'test/flutter_logo.svg'; + + await widgetTester.pumpWidget(SvgPicture.file(File(svgPath))); + + expect(find.svgFileWithPath(svgPath), findsOneWidget); + }); + + testWidgets('memory svg with bytes', (WidgetTester widgetTester) async { + final Uint8List svgBytes = _svgBytes; + await widgetTester.pumpWidget(SvgPicture.memory(svgBytes)); + + expect(find.svgMemoryWithBytes(svgBytes), findsOneWidget); + }); + }); +} + +HttpClient get _setupFakeClient { + final _FakeHttpClientResponse fakeResponse = _FakeHttpClientResponse(); + final _FakeHttpClientRequest fakeRequest = + _FakeHttpClientRequest(fakeResponse); + return _FakeHttpClient(fakeRequest); +} + +class _FakeAssetBundle extends Fake implements AssetBundle { + @override + Future loadString(String key, {bool cache = true}) async { + return _svgStr; + } + + @override + Future load(String key) async { + return Uint8List.fromList(utf8.encode(_svgStr)).buffer.asByteData(); + } +} + +class _FakeHttpClient extends Fake implements HttpClient { + _FakeHttpClient(this.request); + + _FakeHttpClientRequest request; + + @override + Future getUrl(Uri url) async => request; +} + +class _FakeHttpHeaders extends Fake implements HttpHeaders { + final Map values = {}; + + @override + void add(String name, Object value, {bool preserveHeaderCase = false}) { + values[name] = value.toString(); + } + + @override + List? operator [](String key) { + return [values[key]!]; + } +} + +class _FakeHttpClientRequest extends Fake implements HttpClientRequest { + _FakeHttpClientRequest(this.response); + + _FakeHttpClientResponse response; + + @override + final HttpHeaders headers = _FakeHttpHeaders(); + + @override + Future close() async => response; +} + +class _FakeHttpClientResponse extends Fake implements HttpClientResponse { + @override + int statusCode = 200; + + @override + int contentLength = _svgStr.length; + + @override + HttpClientResponseCompressionState get compressionState => + HttpClientResponseCompressionState.notCompressed; + + @override + StreamSubscription> listen( + void Function(List event)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + }) { + return Stream.fromIterable([_svgBytes]).listen( + onData, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError, + ); + } +} + +final Uint8List _svgBytes = utf8.encode(_svgStr) as Uint8List; + +const String _svgStr = ''' + + + +'''; From d0fa1aa96df4ae7f1bc9aa0fe126e3ed97bc69b5 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 19 Apr 2023 15:20:10 -0700 Subject: [PATCH 116/142] Update README.md --- packages/flutter_svg/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/flutter_svg/README.md b/packages/flutter_svg/README.md index 9ac9beb9..64aa45bc 100644 --- a/packages/flutter_svg/README.md +++ b/packages/flutter_svg/README.md @@ -78,8 +78,6 @@ package, this package _does not render the data to an `Image` at any point_. This carries a performance penalty for some common use cases, but also allows for more flexibility around scaling. -See [main.dart](/../master/example/lib/main.dart) for a complete sample. - ## Precompiling and Optimizing SVGs The vector_graphics backend supports SVG compilation which produces a binary From f12e664aa68156a2a23a9d8c889422975a3e4237 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 20 Apr 2023 09:58:37 -0700 Subject: [PATCH 117/142] Update test golden images for the latest Skia roll (#908) --- .../text_color_filter_isolatedDiff.png | Bin 2247 -> 0 bytes .../failures/text_color_filter_maskedDiff.png | Bin 2421 -> 0 bytes .../text_color_filter_masterImage.png | Bin 2396 -> 0 bytes .../failures/text_color_filter_testImage.png | Bin 2429 -> 0 bytes .../test/golden_widget/circle.em_ex.png | Bin 10224 -> 14207 bytes .../test/golden_widget/circle.em_ex2.png | Bin 10224 -> 14207 bytes .../test/golden_widget/columns_and_rows.png | Bin 25790 -> 32678 bytes .../test/golden_widget/ellipse.em_ex.png | Bin 6534 -> 8367 bytes .../test/golden_widget/ellipse.em_ex2.png | Bin 6534 -> 8367 bytes .../test/golden_widget/flutter_logo.asset.png | Bin 10275 -> 10864 bytes .../golden_widget/flutter_logo.memory.png | Bin 10275 -> 10864 bytes .../golden_widget/flutter_logo.natural.png | Bin 25928 -> 26474 bytes .../golden_widget/flutter_logo.network.png | Bin 10275 -> 10864 bytes ...go.string.color_filter.blendmode_color.png | Bin 9344 -> 9676 bytes .../flutter_logo.string.color_filter.png | Bin 7599 -> 8160 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3389 -> 3722 bytes .../golden_widget/flutter_logo.string.png | Bin 10275 -> 10864 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3389 -> 3721 bytes .../test/golden_widget/rect.em_ex.png | Bin 4070 -> 4626 bytes .../test/golden_widget/rect.em_ex2.png | Bin 4070 -> 4626 bytes .../stick_figure.withclipping.png | Bin 20024 -> 20756 bytes 21 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png delete mode 100644 packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png delete mode 100644 packages/flutter_svg/test/failures/text_color_filter_masterImage.png delete mode 100644 packages/flutter_svg/test/failures/text_color_filter_testImage.png diff --git a/packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png b/packages/flutter_svg/test/failures/text_color_filter_isolatedDiff.png deleted file mode 100644 index a7b0e37514ac83ab1041e907949218f5592541ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2247 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzEX7WqAsj$Z!;#X#z`#-G z>EaktG3V`dN8UpW0t}8$6PkN=tzU7NY5qG_tHlZXe^&rC4OK8<*39o^%nWx97Fz?o zu!EnOiGd-7hl7D(f}sKfgTt`~ps3`iASgg8bJ-d8C#LniZR?(Un-Lf;qhK@yMnhmU z1V%#udk7q;p8={|KJ0y722@ZW&&I;Qa6&?Wfk7eJfq|i+hY?ta8jT8q0_5{8J_d$$ lrpCw14j(=D77?5c2iVOH^844-30wdPdb;|#taD0e0swHXiqrrA diff --git a/packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png b/packages/flutter_svg/test/failures/text_color_filter_maskedDiff.png deleted file mode 100644 index 29981f0358e7ef49b05257510617b9e30bfcc942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2421 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzEX7WqAsj$Z!;#X#z`&{F z>EaktG3V`_y}45zMO-ghiz$_Hnj~}zITXov9NFlts9L1`WXY2)4Z*@SDlKC6LizoF zBUU#}&Wk;J258(61tr(sF&_B*q43#_y$`44^*zp7`!)4DAA?1?_-=Nfm;UoJGBGfu zuy8OiOb}FHU~q720E$YE3W5S85*S414;RW@-)%nU#`CS${=O3g2F@rL4S~@R7!83T z6#{>jZmniuun8?Uo_;_5o~&{HwKGrO+5Wk8_RQ_O(hc{kH-cncfwKI@@z2vMWM+S7 znA6>Tmzm*#X4Q$n-cjfOH zEX?Z;GBvpGng6rQ{PU~CXJu#i*x7i1DjTYT2IFmI{0t0!uOFY;SbbRYuFUbPQLj(G zlRYqh=M7t+O+V^61Q-|;lpPot8hRKQ85oS1SQr>ij0%DRH_kHU?f}XB^F6*2UngHI{-(LU# diff --git a/packages/flutter_svg/test/failures/text_color_filter_masterImage.png b/packages/flutter_svg/test/failures/text_color_filter_masterImage.png deleted file mode 100644 index f7f4360c7c53b47c2192a646c459fe7ba7d38845..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2396 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq|3F)5S5QV$Rz;8*_yNMA|N9a|c$lh;|VJQL@M zE-(%9XDo-{_*o0AHOPn?q%k)XL-*Gzw$Bc zD7$@?nSr6V0f@cF0F61`JBs_&z!w`=J6}p z1NUzN-NeAKM~;bwf#C#)00V=9GSs~c3`V1ZzyLu3|9-HpcqZv`_Vhy)khrI-pUXO@ GgeCwFGScn< diff --git a/packages/flutter_svg/test/failures/text_color_filter_testImage.png b/packages/flutter_svg/test/failures/text_color_filter_testImage.png deleted file mode 100644 index 20ea01b6daa35ee9087c6fea46d2b9302001805e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2429 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq_%q)5S5QV$Rz;hJI55CE6~&XHPmS6w%~;ps7?sIO%Lq&dN0HcSklb z=NP8s=%{D)e2$Sg7kTiu-Or-;JV4`yCU8iPwq>Z0eV6`iwYkjYpJ%SVJ#+Y#EJMMo zb7A~IAKl|)WMW`QVc}q4m>{UYz~JE402GxR6$Ayy&InM@ZJRm!s&wDW%4daNK`Ct% zjE2By2#kinkP3l+2e(x*FzgB0J@d4@vHW-A>$lH5eP#RS-t(FKtIZke%Qk{!U4XL7 zXXby_w)ximoncPb=BvyM4^*pW?UWAZZ}{)mz;Gb(`f7HDIZCkFLFQZOSB8dQ6$gd~ z4dur1Y0rKGYnJ85^dlGw4lJK}{O*~nm(Sca`&{?l(TeJ!HD^QaR|bX$JJ2e&1NSX~ u^&JC4h4pBarhuzDf0hIeI;<62!vTNqBhs5H|K;2S#hIt8pUXO@geCwpCE_{& diff --git a/packages/flutter_svg/test/golden_widget/circle.em_ex.png b/packages/flutter_svg/test/golden_widget/circle.em_ex.png index 9c72bdcbea280fda4aa3b156426e9245db3ad49d..ac9af33da57ca012b93e930391076a29ae6dfd2f 100644 GIT binary patch literal 14207 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 literal 10224 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 MgYEh|7Tk#c1$ZGXHvj+t diff --git a/packages/flutter_svg/test/golden_widget/circle.em_ex2.png b/packages/flutter_svg/test/golden_widget/circle.em_ex2.png index 9c72bdcbea280fda4aa3b156426e9245db3ad49d..ac9af33da57ca012b93e930391076a29ae6dfd2f 100644 GIT binary patch literal 14207 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 literal 10224 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 MgYEh|7Tk#c1$ZGXHvj+t diff --git a/packages/flutter_svg/test/golden_widget/columns_and_rows.png b/packages/flutter_svg/test/golden_widget/columns_and_rows.png index 105dbecb54686478846c83fdfa7c9d51bbd730ef..acd19c0a4a3f21f38fdb52601ec44f9b4831a607 100644 GIT binary patch literal 32678 zcmcG$2{_c>`#(HVC?OTH4k6jgnr%ke$u9d+mSo?Fv8AFU!(_|)u@l+%wUTU6#+E&i zW$et5(eRv6pY8kmKELPsU)TScD`cGaIrq8Gx$kq|uk*U+sg9Nk)hVV^5D0`yO;u43 z0wHCGK#mzxkb!rSeZ$EO<~8#KS4|0yhp!!Ydpn_Fkq`pX4OQFcz1x#o=(an2)Lvkco8y9NapF8R-Rejm0i zyw>tG?WTFxU@zDA3Qv2KTCq$^3D>Ri)N)p{1n$`L+`3#!g6B`@v0o28em#`^`ilK> zi*T~o(=`~oYU)&L2H*MjUhH2(@YsRY?d1c%S`LW(AH|87*JT}LsK+QVX&cPX;@nMt zjcg-<-t)P+72sc$afO&wMM#a5u=qTc_*_nSYG#eJ!yl76R?jk@3x<=8i8y|Y*bi|1 zaKGvHBRMjN>I?HPq!7rXe4W^Ep_c)N6}W-*M0%rXXm4W99=bZCwiU`~bs%c-JiNw_ zsiBfHTSkV;Wx2BeW|qwWfjnW|!9(QVyn`LHHbwV)=nJP7E=2oQdFDT+QD=KBOt)^e-TRm&djU+n`32RqofE=4Q zBGr?~T|b?GTe+?Doi2c8Am+nZ?u^!cBcnTar!o2iKYEzgp)HEA?zqLcBr4;D$4;8q z1xd5tAUy_oYn@FAA=%C*slVd3By7pMv~m+?<-&y4sl~cZWAY95UYB#NvL)77nAg*e zPPi`C!jp}VG(4{c{+fW}WN1^s@Zdm%2A{#pVOu8jlF(8bRlkF5YI39zb1ZLHL4`My zC%SaKYdP~^jO|n=2}$Vf^8OQ{p+m1ocyHyj%9##p*uToq@yNU-UDXAvm!&qPM3dU* zOx0uH+wT*KgK<--TjC8bIjATg$DchHf*dcVr|LBCM`x@EJKP`JH|iZxQz6UoT6H35 z%q(UktjX|;Gc;#RH}rjm%9`fqF|qXjJ?86bl9!ehSQUf@Q^xjzcz#1p8>t?5QqdRu zB`5V=Y z%b}^4Fo8womag$HeLJQ}0eMdXG@>|h^DP>>j&p@+`Kj&KkcWuAy^<7;Mf;Q)6Dptt|+B95*5}6Cj5RLEd19 zhN2j+x%A0$2i7`6aNSooa`3tTrtu_WdJVQZQG+k#E%GF!Oj?W`az;1Aud4W*{+c%0 zUV0^kGH-H*#9`1zdiZNxVaWX#ZJ@<1VzcX|$d>_kz63>VZ%Ql;338mioJH+izP_`D zogJWKmF>852J+-06Zn>-@hqXmqhKx|Fz@8&bkIYDde3J z*tfLXI0d_rr-SiPRelH&*DJ zdv{VCHqw)Qoza5_x_QHbA44Y5<^&EDAP7_##UV8@;4V4blC;^L@@L-G-u9n-QD!F^-g?MFUL zL3<=_n_i__@%Dwe6J<9WC5?v)JK_QOmor(`jWS#rcfAa9Ab6~mGuCa!OMpnJbbGr6>A3;s2sSE8G#3r<=U?C4kYw8aUE2tqXpp%Z^d$Sk^4rsU6f_GdOSq%%QmUx z#~^ozL!61~Gd8^}7_t(W5_Cv2Xn560c$~SHF4wCv^(1IQ?EXyCvIq4$V*~}M+DUuT zi~gR}|6yfj`omPu^kYovC(io+5>W9uimUcppt`d#c#L8T4(v+YSA4&CkKw zyt@t-fFvc!FXQm)C`+F)+V-8tdE1i97Uo}N&p;@ch+fD!u#b?r>!}Y$dby;$Yh$^7 z0`kU+sL--a|J{hGdi)tOlt?98&zI$92;|2z(CxAL>XFIiwyTakMP0KLpbzBHo4CwG zPWA($b>1URAyiXX@bI&f8sFSIMvY{F`AMYIH05t;Z$Iwd3Q4Tn_rKj8{c0gl7y>zZ zE>ti+@o?NfeS8V&UF<1zwB zTx`?h^hh+yz>{tL>ksnZf*G!Vq0A6%V^m?1O7tNen1-;sAN3kOv1P+1Rr3D)1tU__ z?2mJh<3ybu`#>ABaV@2pY_0VeHDN5Z`$!AAWjk6cn`fC#vwBU-3w4|g z8K>3cyn3Kcoy2W%fw%{5hjXlAEL-+^Z{_$r1GaWTntmctW@!NEZICm_Cm+9XRBP(M5vV#!jVO^mLSK*4zc1MJ+G^e z-g4da(#80t>f5N|b2>!8CWrv5dPD5<-MTzdMwG85g}tnr=cl^;wXI#ZkM|TPiL*R% zAQjr{?(4DB!McvTkFF#=y2q<(mOp_ExvL`d<1GY|aO50T7rXC8%=RrZY6RTo$|2!? z^N@2#q^W-`J*vjX9Sa<~GFWNa4Mt=(`?7tmjO^Oi=kZiGHJU5eIx-qkyueVWh^jaS z8%*p63fJ614{ zO7V-wCBO|6#gU5SNA`z*@r)>FlY^I(Ainw45XG^;QNj=TluWC}#3D-)c?04;SNtxDUYA1|8D%$~ ztVg`t4`y)iI4tna@1QFUNTDJeaQfR7x&`{T?U5jNh{HuO6(=822^_kmWY&=uSp=XseU54U~*w zR_EK6@6kfoO^ItqhBrMOv{x?usd+z06#a=>y|?`g8GX!f7`E$rpE3SF37?P4%8ho*|g?^WOHCkzDA)049dWm!Zogb~S`fP1sSdtk(z_W#M%ie>8 z))5!=!jhvHHXgZ9ZI`xB>Q{16PTJOrga72hV_SiJ#r+6vH7O+T-IQ^vAlx}0jO`d5 z@g zS-7>{a;sZVlucNNl7wCUDEFwoC(l)Atu`H;U%Z}HTreigvJ^A5m`J}}{o~nz6Q3GF zIrqR}eSu1?^}e5B#(0{3jWS&nFtA_oyI~R8Tym{Y629mmcW+`-MyYMiZe#B5uu3hh z!)3MID2?&_S62N+)qS5CV5ot$^szp+JTTkeF?0h-Y|aw5M#!G2$wU32(hjpORfS3P zCWZJ#DsG3}x++3eP@jspOoIsin}SsJ$ViJbaZCKlgMI?JyHMB{19Uj3 zIpw}f-ih8Vy$60VA_-NSkySqGV^=CYXZ!W+7rh!Q13aCEYr}}X`FHA2L{fh@lPhRB zts)(6QNQ$wz7p-8FV@eeS*6;Z3b%PBtRd%x#+x{7a~H17D-7_|jxGd+ihs0=E!GB;8Sza&|7!L6`A<^2YMN1 zjK<=crk_HITkKaF2$Hjrn;*^aYfrmhML#LdiHlcfEKH3*C56Bkv{+AvaJh{gHq&dn z_F@KPDliVGYQ+9l2S^J`Uh=D#rWY-K*VTW>(EBQJjVhAE!QM}qhQ<~fD^uZENa?^r zwE4>t4dCP~V~Szc6f~8-;)tpCqNB2)_Pyrkdl&mvxpDK!JByDFe@Uf#Pu{gk2Q~Hb z3T|hplybY8)e@x6G+0}#XftEbACj~CYTs-B&gkf?$=*9;ay{=$l7>4uIQOCVOf&{g zI21ZN6bc9?6lY9f%W}0GI~g52N2f=`Rhi9ByWA76%549fR};m=IqZJzuQ^2-C(td; za|?vu(fI^nza(;p27nO|`2b+R;6-s79FP!5=$rqGzg_@CblEl=xILB&j|ahZKcoJF zz2NgtW=zf24tbXa;{^rdbK6n5dniI>uYciHw*n3x@wwC0Lu#a};lN9{IA0a}oSwN2=Bi z9yo6C-{FP1mC(WXTyv%F6up*;8js*&cy_+;Tvff?mqlH9$a|%;7?n-TaX$<>IR8$y zP`nCdk#@uE^YBXtd*B}1)K~&opjSeb(g%HG>Y$~r`y2_ghMxW=#z@W43>9FXJNypQ z(cH+Bozco)Bp3A7{7Lk&W9&j%mhelaxr`X{vP;DV8;_??*ar5Y2O@fyQXBkdF5d+> zLF2ufRp!&8x14Zxh4xyeaDJEis)lBZ#s*RR&-7Hh>CfjEPaKywS9~3ux>V(7s#)_z zgTLb$Ujv4Lswo180|CQe`WLuMk(Q9gM!WDwRnYZ!A=5djUBlz3`Rm+z;zRLRJJh= zuYv@4|E==DhQC1wDFJ|A`~o3(S+q3Uiyqsmi@Xv@3s1$G?JoEnei&Qp{xy6AGgz@U zuwsL+LgV<*(`AVdOrHVVX383 z&#QlbuTfeQKN+#@`06d2)G3P4I*P2|k3;~Y09te%Y;xnmug|LKV~8%jsy1g+YTZh7 zP>^*gk?*bfN`VAq2u+h&N;BX|Kmu7^qEOnwR!6Qh03-k;Lro&Me{xu@0gGNoP z{`L}$<%SU3_o%9n6uIwwYwZdZR&7oxxuj;zR-Z;0HLL>4bDmN5*YOKO6i0h89S>fk z-}VmDusff8!j76-iL#Id*ah>)p66(qwb;HA%KyYJ7-Gv!A}JsSmC5+4Xxevg0+k8! zEd8PEB6;+JL3UPZq9=C4J&P>@T=V7JBn#&;xzN?P591S`G=)v@v&}1A#~{LkG#K)4 zkI9b5UePa;jInH=^-ipELu^PsJoV5)RoG>BO2ZH2kVX6I$^3eXkgrUbi0AkR*D^`2 zFVgp*jdtS2uC7mANna^nsLOMB;lQ|)I`t=<;cIdPXFOrTba)QZygxxjapRUmE*vqs zzgD&GH*UnIR@6p1rDS`53_W5gROn0wzXW-53ZvpPNTbLK8sq#_dZe#@pE{eqROUt< z?;Al5a?`e@hx&O3Gn&3OB&x!gj_v~J6A`8}kLGb#^@UG2uItE5U21ONeng@)_&{)H zG9WEDup#T=!k6bK*n`0ODiDYP8TP>@A({c=li!HP6(2`YBSRr>=~mg8%4yHSCJTsM|)I?|!oKY}NiFyvWJ3NE_; zf;)m1cZqO^!)+qmVd{PacTne&s=_cGtC_*IwWwx-l znrvT6aZ9NFnjQ;*JiSgZW(J);B0K&dVE%Q*va+fd4&5(vgGuK!D`N~jiyt-(;8eph zEb8Pj=7Y%U>|i4NaVF_S;?3s!ADVYDU-P^ta%&84Dg;co_-j3goz-^A@8BMHuxaTqo-uY zTlQykl=^x{b!rVdAB&_anslqRrS(87xd@AK2qXvOJ=Nb$MFf}PD|>b=O;A&2(7yYq z#k!7)3AlAbqy*&sNnBe9=n?Gj7HJ6w$GoyYeTk_{y(72wpzb|)nJ0|G>h;RJCuUvW zLe4M@(j0>6&@-L+fq7Ga;FJJ1C4Y7;szYRQ9i)BiLIu#bKzSg$+!%UW{@qJWQ-KLr zcW`a^Zk0j>3(vV0*aull$fgp3f(%Cr5RnIN%Ju?+Ao=la>1_#?aV$!zPF#IHABnCv zxx01j2^6E^UI3*arJ@MjF6m%Fm+t`3;%wisBjDtW&mi(P5Jn6LGoRG)!Ks29B62DxUjAz z5h0o&_R@W&J(*vffg!1bk{wn6odJ_k1zoiNNJV7()boM?K6+>GUo8c=KvpE4mKt=S z2)c;+)F^4{h2uEQWp`IDp?m}Z@-r|=a6VtpB6%R(w3B?_WkScyQYl%^81n7W-w)n* zsrvHpJDlicvx6T!#6MsMTYzCeqes#-A?JorYI#nV^%Nm#yBQLC`5z5_;VcLjfU_9L z0QlvJ2u9^T(9|iQsd59$1GfcS`wVoU!ncJ1a>i~DxuF9;a~|l)y0GbInINJpOy4tS zY|j!RAEyg{2W(#Fp8QwJ1ZKRhL$ zs`J+q&jLCu<5C&>uAw{Yi6v*WOkK4tY<3{=t>cp>K?SBRb{fZDaT8Vmf3KlCb70DAgCL#nZ^*JhvW1CB?YjS+!!s>#LiB4AV zgu`;&{^qBZ&J*wpkd2eL>>bdM88j@<=Feu0mKnb*u=F67=(lO2zw~S$w2Q6pu_tnEk#^wx{_H}lu-t_l6~Ab1m4Ae@Z|m?)Yc zfP+(mj^}X2{Q;BAP zqm07Sj39cUc#mZeJb*ioN7nj{nO20DeVu@D6n4X5w>K93u`EYLYqaOXk|eYfu|{<~ zG$$*#m<=3>N~B?*WkI5%B2iC6aBaFMcmEPG*idNO5%B<-xgm`!*EcprUs@-rMb0}>&x-^?SyP}8k>>85#|bUXN-eD)D%!nbv7nT~uFy7&t#`edW|EXwYaO^X+rFrnUa3W5&Dm$TqV zJ+706sS+`_?;Tr?gyYP1~tW-`l46L65?qe!>L) zu0jZ2(URbDo(577j-LsR{uOD>d4u_McWjSU^fkZzcq>OGVue4I>yD+{hYIbuz#nmO z+esJ8>L)?py7^kvDWq>Sb>Sr-^yxO{pP^jN#f!U5QQ9qivf^F(lCwKE`I2nu>!l^@ z9@9g;YXJ*6)@_xBf@f4Cu*$7fNu}*pSSx+CF;PC8HUjRZif?bM#80fHR*0)# zCT40n@K-=8UScL;N*Cia)o>eAN}V8PwH4fgik(_d08z^14YUqwjWMxC`&R2k4X3nB z;XtnZNxAAYRyATaF-RkcAxDLSEVRJq-}q9#@o#*I4i%27LYR*Q_or8y^+uOOwfxZ0 zTE$f(xqpd3R7@cdff9b|36}{f*s~$a4O(=s#F(I+6fQO_l(vTIs~tV0*86~xu#BzI zQe(brD8wS@6Ar7DDFTUg5GB{IjtZcvFhjl{?@Et(_TEqfL8qNuNQ37T0}WrA7Yy1}w7Z3Q`6;V*P`Th z@cu9e@FyFuguYLv$wI0cb{ZOX4&}B4Y~C$FA3cRW9fiJwmXhmZU##yb6lGEghD%i2 z4PGb@n^8R4O2~Ve!Eb1a4W6*{R9v(Od}n=u%>P6voesPS_+asuW#Ezy7=avs@WAUh z5fuag)$RX_zebgj>+lb2;0(Xm7t&L3MD0G_UD9{8Nb$~Zad za1WuP>@&*L40)q6M_Lda2pNh+&Z#Oga6g{TOiA$eo*1OG=L?u^DpY@y-E}vI#;tSl zsh~+vnItFYoSy_QYk*!1&DH}%NORdkF*8jba+l$V9!*uJF zT>P%dYh^Ni4L+RFuP@^{Ho>-HmKGPvbz*Nr8O9!qbnGPO+R~-kGfq)#qTsFjCv^2T z>2)H2pk9(WWNMjqj!!cf`Df|>6V5FjG&LsF`R&?bxBcv@^M#WrGq}0g)vm(~m0{@T zfyGgQIm~;;jC*x*Pw&&B4oMg@DzVs^3bK4xwkT^u=>cAgd-0dda>BIp@gs@3=~51a z;;QdxOv9eVBx6vpwpNhfK?_dpr0Rds*p@K6oj$(rw#g@ILjy|=<~)w))f#PSJAR^H zxl_t>o*U)7)<=gk?oSWRiK6ZO=COlB>Wt%;7iVK~*r9WzL$SXXVMF1f<)b<6{}&i5 z_-`1Cx_jPNp_S0z6p-xL%EWav&p%g!=2|Rrxl?78>zk5lHBD!cy(ZuV<=lvGbIs!b z{&H&cOxo>h;&i2CcK-or)nI;2Pjc&lQ)dM8-W&0`HlR2QAd^AkKcTIkKvmQ(723g( z55e8b8^%Jv68tCGdhsHwddd92=boseB?a3tG|)f=CJ%eX39S_dJL{F^zmTmKEol+< zG$*TNt5Yh6Ro>Gkh4qVspB8D1gtaz*aX?B?&^v}YKQ}wysS*&2OyPtsDZyN$11B25 z=5Sd3?+l#cz26KRegD51IODHkk0df?-HO$kv+?Ovk&ZGr9T z*Qk?AcEDLs1SZRI=hjQ5BVN8A(214;OW$sYtw~325H(Al+S%bVN2)b9E4@{2er#&1 zT1v(y!p5<``G&b`T(CP*>Ii5m$M?&XV3%?G;%bOCNouD-VD)^(T;>mEB4s5S zqF-hNDRoa>L+!ZG9Nd+>bA@UtcXbNEQF2}&$j3^}tKB<->v?Cy^T0Qhdu6dS_c@>v zTjdo7670|HmiPf4mgLvE$%9yt3Un~#7HCVaykF5ln0V~J-%a=I``3=g?lH*ko#d{H zumnzM9qpcRbf7_E16hu#B@fOVVGiCWlV>k^6tt6<+Zi!X^ye7#VE^BGf->2#79W#kLBf45N%Uca;scq zE7o<+#%|80-awrFH{pl8?_Y!;Wy~+aPvScXIquF5ObpWdBEZF9=%<0j)O&S8;#8e; zVF23Vt7pq_h}m(eTv&R0mvKkU+6%X~kPcf3Qj>c>o~yJ~ZaT*q1fGvYVmY8iDzFj_ zP13Cq@}81&L41r3>pQj+ko@89TM50^CioATSXRE94W-bF(Au!T9Ll{q@i|V5&W_g{ z&>DkcCd4NL?=95+=V5-crbeAFcbS@K(%4eOszbyqB2K+I+&@Ls|aC9IS!=7=Y z*aBxiRcDt*o+Y-9ukEeoQXQrJYe4mC=-|eJtGE8bo+YU}d=9@DNL%HGbDS?bRa|0_ zwilt*vGajk4J3OAFKB*s&TmOg3Fa6P$VIbP0PIY5F54HK zjC?P_zHT9AF=->k&$>k8Ab-+5XF6yod{-!$N&S9ex?)F{N-sFF*rC-bFx11qK})9X z*e_&rjXV<(WaNmP+(3$lYEK?ZFDWATH|@z^Oy=_Rx1x~AoY1c8Fh^t{7x`X6v)DXm zELG>8l!i)2qSc3wVk`Wjw_V6a8W;T7m_)^|W=sglIdn#ZbgKM}r8$g2{@{cjsF}ge zj)wkpFSxicF8<$WOH-U-_bx&YIG~#NJVjWPNTm7J(&1E0KHMJK7*U#{ft|*=eKC#bDY=aIDX2|c6KQAezVjIK+ogiZc2D< zbneN$|K4sO)EG78+az^Fp6a`g2IQ%rAL0%qYG)S^3b3C_uy2n8k3S21Pq{~7$g~xk zL}qI}rT5mO1K&08{sDFAT(nRSkx->NEZfeNl;rnmnj3lm6e$mTcOCZaLEt0Kr9IV~ zq@H*B2zlnNrvNk~3Y@X?#B8&CUDMRLtr_?hEzKM!%N!?Lr^+={I`X|3`|S3bq+JP& zh#?kti0lLipAp)krT&k0b7Jgl7MUX{5o23p6x@Xh+Nb_!8_<`fe%az@LLxSl>+uNU z#?k5mp&kalC*7k^L2nc1(@^$Pvz&|0b0&&glYV=xBQFtkE+)slh39C&h+=iB$i^Vu zxq!Jl$S1HEz2Wol>w6Q&>ZF@_w(puw+O{0fIfx!rVDA)QS;)XgJY9RL&ZOU(f<=DL znhyhR)C?zd=06+gkXHOGJI@;6t{z?8xo629IL9eF$BFM$x! zq`FKG=wYY41?q%5YAabgPjAu6ZqY*LIPcGK!a7wp&@sg2K*_M921S|Q$?Ii} z*o+1=lRpVhvzX&lo#V9ZR4MCJA=-N`2lQ!xcw@ul>zNNPiI_igX&rPsfaVO}Xbu2Y-CGGOPk2qfaJF*=6IStP=Wi;&!hm~@2t3Xs zxTk7BdQt69s@q*_m!@M|NgWl$4C^*f;6>JJ2mMlLV(DMIOp2-m1TAH{G8eA2<{%@T5bx z$~UGnYWP84WZR>}+<9woh9%8s4X!6`I~+0NRK)%|h<+U~FKPn0Do7abiB@%Z)OE*H zZQlT7KNRA_q#wLF#73Ff^z4^(oTzKTgeZs?HkfHlLBsC~mncXVIZ&zrLkKFizd`(^ejr zMvbQNi~>Z)*E<$z3POl~oww!0AtN$8{Gxwx?XEoin`s7x8drslyNk56y&G!H}(o=BQv+*%ml3deXn|NRK11Bf-oz;wF z%fqQt#S_FoAXotLk5KQPY9J}v)P6B>-J>pW-U(y3AbI#5Hv&Q6D_?)Vf*)-+6iL{fVVg~wN&&xr`1MDEry;vYAnrqs_=u2@+N7f366RvJ^U93M7pJ^ ztpFl@KJCTYLIcyPU3H(03CByrfKOc=o<}jf=NzfzMQBef5~DX7s_HwkmwN;ew{E5g zX(03GFjOY`_#bKxZ)VGGn>Djimo_u1)=b@1unHC^O_1L8I-10@z%QNTO))e8CNObi zKBG4F**fBV(f&$GY_PA6qfq#jvd}8}9Bpd#X0Nq{v1O{DC6Iro3@}GmEjwKWm^2Ya z2_^qCN0WSkAycey!*2~~&jAjIC9O1lZiYXatd79Npe%+1hNXDfTKoQy+<4j0rjs!S&JXqw&tu+cX&{ zPqqko$y#PSh6gkF@>^RN$k6@+m-&9S@;s=_8fn7QccU{}_0Z*N>s?PlrO{hWbbCVe zL9RQtPmLzEoQ5i3bSSNVT{hLId0%g;_T&Agm?R(mlbszPK*wH$N~*xn&jKe{_Ue29 zfTHK}e+(;|a-xp#j^9}!d8djGNP@VDCTh5g}HU8?JT8tbo-t~yNW zXt`PRP9er9_1|^9yRbzfl<>s%RT<1tfVrc$^D~uZfE>O7hZ={*Q=r_`QA~*A> z1j(vufy=NG+$;&h;`9+gt40rVj)Q37uZ*6AXUl_iuOJQd)s+#disD}4$>+!Klt<1- z4jn#nPzCupU2DkbI!z4(>(AN3glJ-d04>+oNMN2l5U2}0{R{~Ls^KJhmQ zJ-hP@UID2#=VWI`cc)52EHXY8IsW1a1IG!5zwv0+eRXw{!noLOlfsxvn$_?8JGk=g zJi@foCg2gnnmLQo^KMULj(8F{=nMqLUZSn>c7 z{L85**yof@LQcL}{4bPhsnkkzi&k(hJFhjk_Xv(nKER7>sKbDYa~4nh?-a_o{QreQ zNl%e~B;G$D-p7H88hTr?PZ-J#6YP|v&F@@2{SZewmwoD=dW$d^-){qzkB~P+#yWWY z|AJ>%9~@h5Z?Hv~T%BU3! zXh+}dw`54@Mq78G1G^4J=bHwTYDb>^FU6l{@R3f<#)sM>SdBYK8*Y%SKJPU-qOcAR z4rW#9RMgUp)X=p@HV4(!yuR0|Cg@`{5@Co)`|{bbAfFej)FRS@-~G_>?C?D1%n|3) zm=2?|Q2?dYe~6DQ8ZyrMhR({}6*gmPu*DF160|HNstqhB56y~I+aq&dzN=Pgs(k=R zf-dWwi+x%OfQp-CWuRB0)2}@e;q?oB@_9L;LwZ?`r9Y$D8; z9IjhjYGxyhcu*$E#@6|Y_ZvcPAPi5!gCPf02}k~6s?Nq2c|>sNLFL_o*(6?LycG{W z@oTI<9u&rk1~{K<6n^LK@fMBLHmcfLcjIOqfQqc8ojr;*~=&g0OAs5 zKD7&$EG3J3cl6h-PWhR61dO4Vvh4_y{S|DCWpMAQfwsc?cm4=|^At}4Xni5?D@ddO zF}jhb+iA+|R;SwcD1+`XD-->0qnw{Z>!ahwBV_qEsQ`+Y;bw&Gaxn>VL?{dTIE($1 z0C?o++X_p$+8QcFUjBFyJt=;=(!A^vf$y%y!mdNPN*ae-mP*7g=<=t3fK1`sbP9qJlj z<`%;AM*gam<=#GNbq$tPf@;l`dQLO*hwBe2^Qcn=9YORC4>2-C;J?-OKWTXCk3epD z|wO&(eqnY3t$G32C66(SD6!{FNHFrW-nF-l-5{p@hSwPQv} zEcFLz?t_cBr+C^_V=?x96+V1KEnl*k5`**rJC)yAYR$&x#;NZ}9 z6L;8Z5F32Wpr0m!4}``Q_}$&PYxTuse-|h-ME|~UsUCUyj%ftn-b4@|YWlf}uV~gP z2DMG*rv7e;aZ|T8xkbm} zh9AdEp4E^-kY1hOwQxOk*IATmXGEvAdFG2}m*sV7`l3Vlw2Vo=)51*x6x!$D7qzhZ zxX@XBnz2g3(DF|86)NJB4k41HUtkQL=uw}Y5oW@#O6h%4<-BhDj9CUvLOzrMH<~6T z=i_H+V)$%)YxsnIh*wVFK=XKF%8HM5o!2Uq%W!!tV$>!`uOqAqhpO5`HBW8;Xn*(K zDr?tbNULzZ)_l-3{m~xV01PJ;Tjm%An>;}2top`%hGBarWh+?QeRfNa``CcQpIm@W zwTI0+MxRo#nO=HE@e1~!uAO)zkTI4%R64~x+749%j-JrY&z+W5*b;k%sZ1{A0%#ZD=`p!&eq{AXdfiQr8I=}GS9N{)$lGj>;nS((a4 zMki;{HN0ILm$~dqjPcs==p8anb;Iok->fUKJIV;W;$Z4Zd8_YD)kYyzDz?YAg#v^` zBMtm?jU5gOKi}2sGp7UpdbBw>17n%`9SxuO?XNT&#y?qDzENbMN+zVSn^vhU%KdTR+8mat{b#+ z!5vX(yK;=MhF=WnY|`cCY_8X3!l2kLl<$Vhq=9mD1e_PM%htDC(s!Y`4x$4ufNBA@ zbp!)O#T%o-rMwAt^WlibRC_immfAUf#}#R{S(k?@r`mEh$SGt8OgeO`=$|?wEXL0Nx^;Fi4{B`N4&XnQhcCE(_)>i{xEA}64)#ZTF9`pqeMgo03you2c03(= zB{emUVLAZen;ADNee@r*IE+dGZQz=LQb^Ee#6$nA5zA1INvB(y+%}(PWy^+I`11x1 zboE0v)zxyx>uem)g1Y}_9dRAsH-sd|n4jhZ{!!Pj8bP?zwJiPh+_o<*V~VCdE%=aw z!=IjN~v# z+(3LM@muvaQkV$AS2)fMvbpzhg{}98EM&VGmw5a}5qxOd%)TknS)WDh(?b}_5SpF0yWK}D+N!k$$qs^1Rp69wE7*@ zeR67v@NkzOzjksrASCx~OScM#2*VkgVa1~6#OXqV*aPp7tNq(eh0rOY5fCdNBJ>9_ zDz~XRtw&+BokiPIjgu|2w#jsrzJ8dY_(Np29cydS$Jg!Ctb)t$jyKwB4QDcDOdNEo`lOJ5dKSy>*3mNU{?7+ckNDy{j^ECBDm zr6r#iJi$UF^nroFK8sW*P~?#8b-62*BFvAiHsipRrF-=}rnzx|Sn;w-TU^%wPI%^s z34Z)PiX%o&mY$m@UjKG=)xFxe&f6!6+U_Y7awr=i`~Z=v<;~CE{R_c8Ffbk9hzp>W zSvv4QH+dmJ)AR^@UUF`>-w(pb?2>i7-S*BSM!Zjo)A!|w?h=Kd_^9Sg)p!3as!;zx z{%k?p2;28)|KU6{VQ1%LLK17yMH(jnBM@GBfT?1Go6i> zRO#lEuJPB9T5lGsTWiMc+!4t?-1GfOle^AZxHze{8~!a`a3$Bc>*mAV!7!T_c{>R6 zRZcCUmA1MyQqCAR?piXL*Sa+##x%<>5`vD+-`9t`(h%bwn)@d!gMW;LvapECxj`!3 zWV|*FXX9V5IW-B#<+!!bO*b2Zt7t~#X2zoC0o4P?JKkwQJ`DM8EhfV^qVf;m+lD3@ z(W{f@%|TLX#m-lSn^($Hsh_`;W}4l9r~@Ak{}ltjD~7g+vuoJxW0$S9dca zN}~r3Vk4vdS4bj3Z3bVX>mxCvPu`Jc9=30Ss#8X@a^0HGeUh632$0X$Vnh(EY^V?7 z>Y6o#(4G$2y%u(c{HQhrWJjc0cZO)Dr_$Y^{7wN5d*Rl+!p)U$OIwp}GMKHrc%1s} ze&YD=;t>hxL|k;^;BcgaD%c~|TYCd^X_2G7i;;AQ|C2)E(qdGxQ1 zr=p_qy39uh@K^3A{EP;v2&j9CP*|gC&m_@0)5z*JHPhmYd*4LY$b8ekmzQNpb)D+{ z@V8&}CbIKyl}Eku`AT|<=qq=mk!JdRV?1=yLF+jPMioX}cFnK!ju&*?GyfC8Gs#@@ z)NuaZRLPA#8BkC!^(xv*%mQK5ZL;*F;}mj83cY?HzeD_-j;mwOzE@L2R~PQ;);i_1 z?I#~jhrnUupuWfj)Mq`$ljQ%gtkTOIvxky(qxMdsYEM4x)2MwpHK`UG*)h>^89#Dv z&BwZ|Bi-=9c;%m;?QvUn$9k2yaIwNBx!1XQH;%SAeZ;bOLF<;aM}#*f0&IL@E~*iO z%bus|Y;CskNUQQ}(QH5)FSo|Q)_3Zm`&y?Z=zo>KST5ddYw0vRsY;} z|MWAQ@OnMm;Qs5`I`M($Yt6>(krs+s(fAqYQ3UILsv>x>iDWa`C?GXH>r!~bWMT$O zy|vOo%o4~LJfqzU#)DQJCK_^6#U|>1Ue%bAib4VRw6Ks+O83lv&DnzA^6?K9wuM`Y zzp7_|t$yV$!0Qf>%}uK5i$4C&-=2HPAuBf_gnJUO0H6qeu?A+!0o3x9R_=XelY-~J zKX-(0On0lI<9TV_9fMW#d)2$PlSD4$)51lq`b;AG{V1smdj%DDk#Abd^GDl6bGS~& zs6>RYzw^5)H@}%_-P9`wWvq3pc^kx?#D7AggER2;At@U)K+AuEowD|m)A;hOy6mtc zwmrxWH_j>&3LHqcx=nV~uXe|4IKE1%lzb!EpjU?7Q52J;w`_OG;e7OfYl0DJhrvA% zItA)Wll>-q{EE}~69ayHp}Yk z`_YGeQoEkhe!5v)j*Kpqj$+CE_mxF!Ry~f7=<;vo2r8zElXV}y8kLSNpBqGC0c~E15UPR3 zWe1##DcV#{TToTHxOM$!a&K%o>e9U9K)R>7(&{l%CF`sciWRjsSEcpQk5zRWC%Uzi z^vu^Koq}#;1?K?VfdR;aDuLd589H}rrs5vuq+{IHQ(1dfly|k%!5IGsGD;&vNkx{X zwfXq4X@)zi+@1LBxsP|>rQBo)m{r!5QZO>ofumIj^5+4=U2O#U>hxy+H;$`1TrP5_ z>HBv++U1moi&#a8GrL4VPgV@`n5$@C;78F3ey$J0&Qr+{!tk*$AOf&MwTj^Xr@8M8 zYiirt-HM8W%HAR%Eub{%Tcnc!iW-W5bdVC2CQW(?5K!5Gh!8pg5>!HOBGMsIQ9>6& z@6rjKkWd1FZ=s&=oa}wSd+&39UH-80JZr8s$DCulqr7v@WoUcU!%OsS(j29lnC(>5f?eh8fYfcf$dYoP1^cpK-jspG$Q>Gz?-}TdOn5{Cu zU^#65m1260st$`oycOxPM7@v;GstRAdv-o1qB<^nL&{yLPXL4s0ry?kNqQL$EGmvO5uyn{KBe&%kzyGw&^PGh2&%IY9bd$I?dP&uG zO{ZC#Jy{$?q3?=yk{;A1E*bKdeAl`<__f50z?Owmg`)f7ee8ui8i z-B6xhqVsheUH*OHH7Ro1OoF#RTbQ@}+$g-v%TkVFlW{vcuP!k6v~~ zDlCc5Iy40w9_U1ybjvB0RfQy-mmq}MXe;57c6y>ySF;96T}%S>5LctOP)Bn8KQAZ ze~3ZH(T~v$gUFF z(XD%G*xwvOe%K2B{p>0A`jP>0&6LTz!6G6PLmh*+!N|M0NUoIEx@e)ABF-0F0xid$ zlb?RP;X1ng$~trsj*g-onq&O&5ptK*a@243m8LHqewcqj9C~uP!eR z47RH=5aw;-l>Ogd@%jq8<=xFZh8-%(u^6@xs!)`UU(L+ z)up;3XlH^sCR)%{f^t`_gPfRKaSP}3C@(&uXdJMr4=#7SGKf&`-nl8c*~3YhRg~{B%1xkbLYd($K{N*UPu#Qh5-@&S+lSbKVx`>)kQo!+_CYdF2Z z4(h315IZ+F)L1O$_$Egf*|`O_N+s@v{u|tO;o-J2mk=fA#BGL9>OF^fkA!FP$o#K zrTP3+$k&duoOGensEge~htDvMzNfKX@!{LMI1PN^)~N+31pu~EWnd2R$v;5BX5fk& zS=(?*DDxF&ecMS%X$d?K^zN&HtjCA9!B2&f1)Jl0IN{?mHqI=+oA5+cu=mbzM2as1 zbNLHnB{cew`7h+@{ijqKWj?;~w{WeYgZP|a_!fVbB(}nq@^se=l%MG-g0UFe2fm0iZ>Ew@G~l?3kKWwY6cme1;_6S6P`uYa6a*Do zw#8k#QvBpI0QlwMe5TC~O&aa7oF{#~{q6cTlL2D`&NBEH-jgLva061tMH$hd97O%C z>B)XY4lr4kUD5C&;ht+9B!m?4<@DHdtQ{dY`}|m4-{89{?RsW?Zl^t=2g48dWSo>( z&XM`Fe<6n#HFxaT7k3T>F3OSWCH8@8w^trOSz0z+A`qwg*P}OHm-0(bPeEnMo_r|i zw!*rx$e3g_4lTPm_lK|w@%A8l{_PnZRS09sCn7&M`<|bruN>gKd{nolB-p*SF7CtV zm4e2hDxbcyOxq03+#lokAyop;>Ki-k$TBmN$wD@CX-aAT^0KOi9OO(#mAs355a|mC z?rpaV3WSBoH*_-k?a|?tL!!KKr0vb^dlMp$O*#923mhq37WaGDiL_K3Qu-r!;E%pW zva(Wz%(LZrb5*K3umkrHZ?g1M@)Z}V6qm-FdiTx@1PJU8S*yv?Gidm`eKhg(S$BfO z7uxA-TN+H@u4|hSo*YS2Vi{ERw=u8#wqjS9n_q7-RRY0`+GWJ#@;Cr{f}c~4Bug(q zje>^|RLsxTEY&$VCl!U9K&rZ^P;Xxj( zH-YCGmYke>e49!*Pa3|KT2JV$_tuXXdovi`3oU#LxcL*hRRCOEDPUqP6y)K!Vl_gUv zHJuuqyJnlrW%Kfq;eJe0UJ#Za;#G0$%+PPqs56xl*Tel0%L^ZZNseRCmFHU%0TRUX zOT9zhkRY|ZX;6I8+aN=>U%FwbaxUeumyEyv18Ci+tqdeAZ8? zI{In9N{4oK!4+u{aug2cd!{L=KEVEW^BF;dlQ@RL+m_dA#@(~OLzF@W+DDTBT?4l6 z9wHcU(8W2W14=~5x)XeH1CL;fqeO8Ud_xC_?`0@`z?@*vs0seqe+|csnrwyQb*qSm zxk=q;#f)ee1~dEuYd zHy%A(7rb|`PFMO{=*?qVPEDcKjy)Y`T`da(jn0y-U4Cj)eiE5)eZvLo&(9f9q$~-U z-DaAKMwpDyE#R1Jq~D!QYBFzuZXPd{smpSEch4xEc-Jlq%0;(OA*-uW8~sSihuxV> zBJFP<++P&mie(>JAJCl=<QW}VoR0K2Sk>|W-yy`sWr$}Je z9~z(Gd}n?~B?&0j0Vfo^4H~&dJ!zKDlNYVoz>UJ}J*#~N-kF`Xv?^7WOqUlfSJH`9 z#z5T0EXwt45QGesB%{iy`B_Vok;Oz;R_HA>BpTSfnhK#t;@&gJ&MJqZ*X#zZhbIp{ zZL$*}uFhk8X4EM>v+Z-7t8!{@=ZUJ-Os)msL>^#Zum6y=fG5xQ6JH2sW@aDg68~;xudm?ZCWLQAS_n68nf-JHN{y-bgxp< zkTGXFTeO|`7vPW)+y@e-e^l$mBO5ijEMF`E)4a(DEvpH>N4Kgs@`veF4Tr+V&&QH!|_|d zF&26%E3bdNQ%~i(F;ElA?+frbLHSBQa&!9AAA~n$!g7~wl^*?-({8yasq*LdMLD_7 z=K_fw57$YFQ{Ek!SLv+r0lJTtGFgkt@CHIzn22p)g&TyrIb}wcaYapDS?x#Kk{?ga z-&RvzV&Onc|oHrzK$fYmE42AUereIPyQmz`yH4ZoGOg%vDU zif$sw1yHD4HgaD)xsCZa|B}N&7UVVKg~Oora+Bp_?Vb}CsupW@H(<(1y|uoNFwHpd z0(1}9_xx|e>e;KKc3p#E$$rM<=nyk*PUnv=SAlAtT$lzve3gN;6E5qz{<42`o&Zx$ z>D9rhg-RVKtXDR$=*WKdt`8FC+8ZMqY@PiY?W23JFzVeQpe~md>>*vSwd%w4GN43r zH5f5fNXC$jU*2ljK3r_L@wpHbZDe_S-_Q*(jM$lMELa@)FM zc~2tGpV8?I{T@~&XDyPH*Bp18&K`78*%6eLsNjZsS$7w}5YIZDa6n5*#iA3Og*f*b zc>R3Z$=w^(PJK+IZOW+7;;VicS7R)&j9DcZxr@Ln2q4yE9L5t9IE`*bRj=J0#f_iE zVR9?{b+JHgE6mc^TLz#Ckbu)8H-u8|7X-azFZJ>9ql7SNJQAC^2!iyhky^QthQ zbjdpSr*rK&wP=Jx(Jq-Q-vZ*4y-Z%~f?6(r|7g?}zIkG3Y?h#lYITr$Z;&Fa&h&~g zIU_Jgy=LTYnrw07CoTLNtr^#((cziJeo(XXa~5agLwy2F>5hs;E{~65Xv(Q)=TVAO z>Q)b-pk$g%j$bF3X9LTCmFqGOdXEs6Q5@3muaCy#>)AegC%2XkTr4~VCd{oi&!d#b z74E4|Xxo^(YPgcsOSXo^`Oj3l#S9?o_jtSR&JiM+>{~$9YV%`3u;6WsBDJdwUJvKP zTrs!*EI=<=uA#!7@JPD%bu7z}r}z?^R{H+IJVrG`(Z;b#_E#nc5K#k8v1nax2KpDl z2O)KhbCb|Az*;%i&sx1VQ5O;BiUZu9YKHtnkBu~Gm3w>ZOhiREMETyauWLO7l+*oS zzxF#99hyR+f<7?Dl0k8MSY?SMBu*~?qI5oS{^1%aK-aEy#Z7Z!L5|LPBDOH&v}S*r z!K3MOn-+;@t*mO?-l>%WP6dd>fGSunq>S%1k*Vyr-+06hzY#F-#tIfpGBk!EvR=Es z^6-t`x$g1pIN^4(SB-hi;7boR7KzZRjWFpz#Ey4XxDuF3oG1+AmTS82zJ?! z_RN1>g3<5%%X;q8<*@#(m1+^ohsiqLT5QAU2Q6vCk{ThEpOs5(oe7`2^ydii;YZUi zoV`(ETCL07GCxuDWWSqHA-#HLtP=q1T^&uiG_--`gx?kOkggIZ5iU`m5jV*1_ZY97`4~OX(kmci+j@@7wH^q`vZvl>u+RrmbPMR`IIbS?ix2m~)rH>cb&{|ya z7mtQRTCBg&=fyuOUx*)&#l2C=2;Vy!w%_`cbSF3$2P#y9*F7*x9icFWvO!sq_T%?6 zs_-I~4zaW60E66lr%OVH)7?m~b%+F)i`E%eHaB%ukR7WUx_MsZcEd76<_jd}(v$D1 zPeg^K8%&7Evkhf!EKkT^>5H)#243s5<7*`uEPil3pf->?NyonY(BAif_|M8wD8MUZ z3-NA*DSfsjqm*Dh2Z0cnPm)L|-EKYG%HHl>&w*=#i&=Sv(nf4SZAS9Zm2F`;RjD2m zf0Pw#ceXt|LUrpn!$Svez|o|U^_mV>%v`N&Zwvhr;K51_A+%Z#rUd#%Z1N?h}n zYESmRnIEV2rp+)$oCn?Ks;j@T=q$)3S}Z5I!puxgq>j~mo>cAvbFxOGnp=jIM#;q(U8OuX1(hpv;HdAi1T zS#$7dLOs>KnzLS{tLr-sZ~r6Y>T|h z!7fUup7H$fTtj1~kU;5(Dzg%wt3|EuA7gfjkKc%*zFCCpARg zY%g~E$n<;yD)a6AmP~-ZS6T_Kf_`YIrQ=5G&nWvjCAQ96;Yf-c5C9v5OHq0*5~3Dw zB6gkizQM#Cy#(u_ulnfmqX-O$lY#V|H6znVrca*@bqlfT_Ij~f;7|mfSCaF~X$0j> zAKm1V%#iyN--SPv`yME5siK+M5uRRfaVqa3vlab70=cJq+CeKa=Z%jpwH*~U zBx@x!a60wnFy{-Cej03onl!booEn>9CnCW8Q>nMXKyXDCAD)WDWLcjb=nsd$22Eu4cZ z8LuNaujd(RZUt^BPQb?+d16~GCu-XByTHCy7AJ4*Ibv7G{ZU(K1=|>JBt?&vOn2pw z`&ZLmq@N2u0xT9rhn@Oy9Ba>?M-G3+a0v1O|9;bNIQHXA49Ay`4}YqkVgCK_f8PD0 zM}dF5GPhL^fBv5u*Wu+BwaOoT(a-k4H<{|O;k0U`&G1b{agDR+lt7KEa0f*byp6=( z&}?DPOL9+4EQb_oXaNn3KAkw~ggN+3`Ho{--{wKtSZuiX^nFJ7z;#eX%;9CLU28+n zF`EkBdPHV!<)fsrosC8>?=&DbbMQ^hfuv(Lz2HNmgaV1&g_40kn;KY&??S=O7n#g| zU7o(J`dom3OMXrnzIvQG|3EJ^!JK&;A7UO@Z*TuPU^ftMRf8Sp_**OIi^#8zvPY_A zjqrysZ*Kp*M!|ZD|F%hHj*!nbka6eMx_j0e{PT4q`WcU3fy4=mLL2^@f$rKWLTu^^ zuoil}g5MklAa%;7+U4eXZEklZFGO^1K<-P$2fTNQ;h?Kuc4d);4b z1p4Av@0Df5;S`g-fX;K?p7RQo>yw^EXIBsNDCD`^THs8+YcJ}$1^9EG5zhIwkBxW# zeDR;d@Z+hOQW3xz650tQd&y~UB87OZ?KnO~g5Xi$Rem$IoxeMqQrDw&k&M(*ay66< z0C!F;mW5yCcxX0$)#sn%lc?c*G)__zrj*j(ugjVMyA=6W=+O83h6b}5tON&XaMTH$ zfhAYG2tAMxTGY~A{Wj0%dz_(f@UQfLbj;ctDC1b5#0X5-jPB}EqDsxYhU=Dk$yvjo z=fVzA3WQDphyL=ckio7MLM!h5g3Dc=GVgzOskeY~Y!|jT2Qrn8Cpj8@G2D+axMA zzqvBGR+ur}wa*IgP)9J&U}wL$y$<#R4$`+?WhSbZSSIo!Nkc}b{)fxlj@3e-mj0j^ z9ZXGsrGo^{ShYzfO~!a(5JlKL*@`GlrdRQ)b0Zn!K!}@BFIphTch!Q(i<3KAP!P*LQ#A0OYjOW((7;inkij4)l^*?huX2z$&ALej5{an+huqa+4e3=EgENf zRa~vpDZYr^_Ka5`?9M$`1b;7(nMqNE$AllJv2-mwywLHe2ciaD5_mPIbkOet5Kdu- z1LoYb*`&OnHX`0g(nebSIZvgoQd+BKwnk0SV8 z$f?O%WpaICaHmxmj!)6ab1`PWTYErhpICtk?~Wbr(Lb*)+*fF00R1A7o#J(IfHv*_gF^W@?;yrlxuO?*%P{*-e~ znUkl~F_)?Pz8;D*rv6JsAVO$6YvWP2;n6oQI@C*GqJ+}rCwn5_;+iwTG*bnDLY^H6 z5M_S@N%Wt1aAlK{qC==oPo%z&T6z%R=P2Uuzd-TQm@30hi1(&v$K&vShoh{!a6^(2 zu=K8H92KpyzOHXxMY?c(e3)ICDz#9e%R(C2@w2xQC+431yCE3zA#H_tO>#6T-E*F$ z{WuP^>*^4f+;_wLX^rtQaqS+Q$`$}3UZd`O-I}q`8GO@Jqcq&`IgR{zw?M5rs{0L| zaBXPcf%rDQ(x>Dg2O@Y8W;c9$E=vWWyt<#w!i!AQP(&VVgW-k8Xu9#f51cfD9#=Hz zOp}|;(Z^uBA&b`@7JfqHuOt@SMA+Mqa~PTdk)q^T4Fm5;7-xnk@I@=DoxJNr)7t#mb!MWeD9!xY z%E0A?cwNUXFRXGE{06SH6!Boz`T88SdtYW;-l$X8)i|i(Jlqg!v>~qsa{AlL1)1iK zO=GEuz($V>gPKWG4@Rxp0iepYH79ALtR;k8__u@m>FbgbXa4}!Ndy&LNGqDABYbt~ zb@*;anylCsIRfa|!ZL#$VOkI2)I23a%vGfArvUtmAaC%_tv$n@W-A9l^ZFByWDUIW zob~Jd*dUJ`Gex-J_+8>QY+BEo#$H=BiKfy=s^#_YNJ()k*@F2{(IfXXE5Dkk|4H@?hczdZh*0bV50JHjZ>c;t#qW=XLj`An_|;d3J`U z0*wDxJoK}zSaP^zXn(^^%ZIuc_cSBv-!=Tbubr5VEuJCzC4%*7wMi^79J|KDXz8L+ zp_i88G>m!Q#`zaGuFL{deCi^cKb%HxGZ7{%KOsw<*OT3$@M36^i+*O*dN*R@Neq;d z)WS#cjR42pqLn-`JlOU=)ca3kdoW$hMnMUS_iJhllZ; zzRpux@d7LW1sMlrXqnOT0^dpm$I(toLMz{t;^YeDfnjn%H!RgnSG9=`K0|anV>%s6 zi?&%7AohM?VY|PYMU{@+53^zxWq$|UOQXD60G`aZP2SLqv%5-=cD$O_(Fo&AkHB7Q z;^U^d@leZwzB*3}lNC@WQc~+AZCNcmWX$g@of9LfBSn$(k8gqqvNoZ(?Q)=Caqlpjl_W_)2 z;WOZYpJaT37Fs;XU&Fu(N7D)hbPgCZ#RZ6X9fbdK7_5nC)13be=la;OWb4tl&SpNB z8RF#_s5Y&|0Xny9KDqeYhmP#--1fHes9ke#EYu~T)%r2mk=A_+Cx?%ZFP*dz3}tok zD0UecUy1-bhR_%b(1(_p*okKWE>#uls*!B9w@OF)-`4!Y4_kmzj^JLr^A!2-M}0MR zxV%-KTkHX^Isxbeh{p3BDo+xt?x1Rmc$Hdx@TI!@Ut(GEKgRbcm2Q`Zy%|!6H+|!wsWegmPp^U;i5RDsl23BZlr8&YzTVGjrwSt6l|Y8nPsa+< zV6SZ+I8bA#dq$KK{=3#eRZomoolBaIn$<$21yk}Fv}L-l-OO|>h^7sI*Jct-Fo3vS5Tp}QQ7JvAE(^)OC@0#N`xZPOnv()=zMB7dP;0gB&m z)sS}gRPfU%ZT|9u-skGx7;fTIC}_6MZI4Xv5I`=_3Mtag=i@%oy(?A9Q?Z-cBW2#Z z=^`RthF>FZFY#wJF zXs_M?_39OYS9sRE-^uNhr%R=1d+$iRoQBU?J==3ZVQoxW2;%lg+hxS?Y(_kXMeJgc^@CQg3uv;orB(LcX+58#cz^(i51$;b+7ijh7P%tLG1hjTyiUhX zmKFaYL!oy0#=O%ei4;UM6{k^U+j6)V9JP=)`lO-~hus-)Fg|6f*;+_yB5W@X4}qym zV=X1xFD@Z_HAIleB}VB1O^_(9%Ptf^3JCF{(2`v3jXK)440wQia>BfO3G;AGqo`8w z4Q4x{8LzM*U}K49Fu-?Tf)}2o9ml?3iC&)M!-B1z;b}rR8|y(Bkl-tbr!U_%s+Hp} z;fL%S=l|5H`9 z%89x2r=Oj-;_@S;pp4uU~Z?R?L_k7_&z*nrVnu64&W%t70I{TLhzR~u*36>3^ z5wTcweqF_h(+y!e{0* zn7JGJX6D$Vn(_;-R7YI{MfNHpvz=e!%BC+yfD8Y_V*(D8MH~2XS9M4Cgg6GHq~Bw4 ze|>Jq9*q)qK&y$ktlfF~mNadS|8BbH=|V;YZAC2Q_hniM6Hl78Of|8>#<_)K=;1G~ z{oAzS3_+r($LbSm>i`^5CPKH{-q{)hRTfLfWRKoj$)%?G%%4*zJE4f15xTfte@;NmNi%NPk@X>%i| zaj!&K*sUy~vA9%^^>1W=b*&dFTX59~R=f>b{}v0S(9S1%!;}oLG9|GA&Q1MVCeJz2 z&Gr?mn?s%HnZ}&pzXY)|8$>H}K(QaSg_3 zx47LmK%JU+=hl-_c1bvT=!0!6G+)~sh(P|Amxgn`#x4L`Ae0-qiEK1E$vpnRrUJ&Q_fsUXep{is{^WiK%Q4xAw@Oh5+5 z^fxcs?#nTRz-yuY?RO5J160AbWVXCrHvrtF;Q83g`#IB+lK(?PekBQ|{t>radV{O&C&NiXMnQM|r)mRO}VEbY?tA7sQ^I$dnC))Xlo&@dBhWAnj}BhEFxMxPKHv znt&8L?QvULiw3}zSpli5>88`%(ZjE}Wf|4rFSXmoIT#?U7SdxVxGZkD&xwpl8$HEq zLvoCA*NcwRVA5gla4r1GM^b$6*P%<&#pZ|YMYqStWvwJFAD!tpM&-w6zn{oRM16K_ z)6n*;RPoRse$gWbQZ~)f*IhbEDn&dw;rMRTEAF2IClWt&%w{aHIc}dAb^YemFIm$^ zh3B+(R8!mk%87e_T-YGy{nxcsC-(>PozSi01^#t={eXr#uzqLbcs=6k z=q#`l)7$IM({Bsht-m$?4dV}+xraxbYPwFthos4MP7+qEU|Xb}n%Zx$Ejfq)ZDtB! zjBEgCR*+ZEK*7PLFgFq)I$mBT0CYuW8U8i~ol+;AE?U3w`^zN7ydQkW{$LmHnF`=b zL<@(E$Fd8CBkK6OG1|EJN1@$Xd+wfQRve*OtH=*!67Oj~Jwco50d1U`8#X;x4jBaJ r%l~)W!2b)eaL76QfAaUS>VT=c^A5anYQyQUOBy$IZWLd?_w>I2o#NyR literal 25790 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 diff --git a/packages/flutter_svg/test/golden_widget/ellipse.em_ex.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex.png index 3244264aae23833ef7e318faa5d6951c95bbae3a..e3a3a585e8fb38fb84930d38fdee2a938602e45e 100644 GIT binary patch literal 8367 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 literal 6534 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 diff --git a/packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png index 3244264aae23833ef7e318faa5d6951c95bbae3a..e3a3a585e8fb38fb84930d38fdee2a938602e45e 100644 GIT binary patch literal 8367 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 literal 6534 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 diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.asset.png b/packages/flutter_svg/test/golden_widget/flutter_logo.asset.png index c73024a3e8466eac6de9e2e133e3787c6dd8fac6..d2fe2c73b96cc05babc542a9c04ef76f8d23345c 100644 GIT binary patch literal 10864 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 Q_M)n6tsL0}ERWOw2fap}6#xJL literal 10275 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 Q_M)n6tsL0}ERWOw2fap}6#xJL literal 10275 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 literal 25928 zcmeI5iC@fH{Qp0=$lkPx78zQ!5LZQM!L&%SPBW-xvR7!Lg^U^sEm!3mt}S&7F_UIo zy0SD)ku2A)ETL|;lrR#LRNwPC@6UYd-v8kD{pE2VSNHun=Y5{%b>8QFme0qPG|$&_ z$iR^U34$0h%Zs&uAO`RWqQ8blKV&JY{P7F=t=Gl{o->GoJBIJkfBdp>#;ipe=$BAq zMIu3%5VKg*7i~K7p|n>o^i-7IA^oU9dh7Ysqd<=WJqq+F(4#<)0zC@!DA1!oj{-dk z^eE7yK#v0drxg%Ay^wMEc0upt9O;UFUWt>BBxblBoBqpC5pi9yF)iGLRhM+j$NP9l z$J@}rv!9AX-37g$IR2kjq^EN|3iK$@qd<=W|34{kwoTB2`^zn#Tk^Bx)whaKofl*J zU#{OZs-wLo?q^FJ=Pr6Ky8rV{19^E)$hK$2wzgNKjdJaHcjd44_6D2JnZv5@mLy5h z!`jitGO|!DKkJpmwNr<8zd5L_^?Y1M(__hMWLKR0g-bpcm?(9F>#WdEn+_3!NXt;B zoH<9>7yWcelTS9J=yjEI3_ImJ^tL98JUOUJo~+bGKYj2PktGQyE#4k8d2fXGVgPQJ zZ(e8h;3@|_5@__&Ba3`+6S^N#k(d2L$0$%qLS&vK_0r~{CKP`F%;#U!FjI~IjPY1C zOdbW(M-5Xu8DNSs)G$XVm}pHk%tL^w^`Kz}0L*h5W;_KGov4O6PQmn3!xT|4fuq$h z1EA?m+tf|3&;Yd!)D5LGp^p>PZrxI$M=lIC+*m+aTW3{=g-SQYRrs4}A7)@c;{#Hr zn}cDo+F<(&_?S)09|R!WR5jUPcRWIh1!~>+QviNH-J6+Oc${Ul`uh7ZtLQyFK=(is zpE>F=+)1Gch7yFuMyg#l>d@2z&b zX&1P?r4B#B0p^cj0Ns!WG~{cphI>98Lgf_Qv=hvqDZACt^qGKB&ZA+B#{!IihS3HX z!!DTr0hlW^j1vW;p@!j`156YR^T7*X3TT*2fO$g02q>6KG|W(tx0aqUifsTh&0Vd` zlmh^>OC3;zIlz3@RKwJc1(=U!YGsa4Fab172EY{2nNZLRlyOkcZ(=+J6F@7o17I%C zQo|HcFdQ1D7c?D6=RFpTzKRZAP0Fp6+O6Af(4)IFoC%;*|CJ<7#0i#|4{on=&f!EZ zvc)A7DDgmM7fk^}8ExnV?ds8?J9q{j5E;E-@J+B&Q8_)V@eCa9)+}}Z^wTjKpP^<| zWP=2Q=ppL|N$$WAb%@zgC|7Be0f1sgqxb-d?P&Fg@tJ^fgGR{!6dxMp0EMDOqZ|Vi zZ5qW4Q1rV{rh+O88l^9w^rKO%DU>c%MgvMIjgkT=gJ~2lg`!ELI2?1PZ?q+u=r z%!e)*O&DS$8phBAOZ|B)4Kou|I%=X8UqFR*JPqRuFq^tyf&nI)9>OUAQ#+J~$pe_@ zUg{}Us|7FyG>kt5Gn9sz4KOdeV5q>hqG7b4=?QcMUWWh^&Qv#K0!!v+dTACJg1q!j zkC+80Xk|WvH+m+su`JeeX&-aIK(E~h3% z0Pq9o-du((>hG%#1Caxs%%a(}CZC6562S=d2omc}@XljAy<=1Ch91AC;fmsMs7%>M zHysTLE|1o&7FOI^9U5jDEcS+7Fy;U=vkM0H?gD)pCJJDNcER`p%tspL$sP>zqzlFg zCiA5(7y?3WI1OV6@=l{?jHnMpOCBw_02cGlbS5Nx0mis%2xbAy3mRq$z!as>%9sO; z1Dy$Ldt;bdGaAMpU@p^fDH;SY4zx0YiFlYkThhw(hNe^KrW0ZGYv^8^fLkHGM-%CT z6MAz+Ob1=6?UlOW__RvEl8JIBGNCnu2*M?}^x92?gW&+(!9KWMMOWzRC*T3mqZbT? z8)lVt4QoGqIuz}o#kPgLmGuldQm11H_`PVA2E)pfK?}(jV3Y%0DB6H>jMn4;pqO=` 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 diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.network.png b/packages/flutter_svg/test/golden_widget/flutter_logo.network.png index c73024a3e8466eac6de9e2e133e3787c6dd8fac6..d2fe2c73b96cc05babc542a9c04ef76f8d23345c 100644 GIT binary patch literal 10864 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 Q_M)n6tsL0}ERWOw2fap}6#xJL literal 10275 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 Ii~aWf510q&ApigX literal 9344 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 diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png index 3138a2bce82d2bc1ee3f5d9ee18a916f05b20d9a..532d4f1e46e5e981f636a3550a41ee353c5dcc67 100644 GIT binary patch literal 8160 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 bLHA#~6qjawu~(cTXIyEb64l34+AaSJI=J9p literal 7599 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 Ef3wSbq5uE@ diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png index 13f1aa453c9e6c1030dcc2927330ce88ca28175b..962179bceb31c8941d19bfe5f8afa2e8f298c991 100644 GIT binary patch literal 3722 zcmeHI2~$(a7VaBRBQ6j?6ylJOuu4jF5Mfx7h=H)o1dM_(Do~0KWyVpA$`&vxG68{r zvdE5r%R>zswh;#5y%8cJAS$42BMP!hMZknbc_-HVi)YuZx^=$(&gs+N={_Cj$ziWi z(^EqTt#Nf>aS>7>BZTw8F9#&+%=r`W!+2b_BNDf690fy_=jgfz4}*^n6e6^Cn=5O_ zp0J$BzI_S%Pk&c0`#baXFMBs%U(QM(Yr2`nJakz(AMo#(VixJgS1ZodU&>$|d=%g) z+}iPIpX2$I^>HbthuxpknXDJ&YXW0qx{Dr#wNl6J*Q#Kn=gsMTxtVq96RGKyJrD9; zTMkc$_vZ4V>!P~((+o>343haazA5m3t^o7?;o;to`}EL z(AUT?<|eC{jau)%5mb>`wP^ki$Za(g~qJXC&6t%Z|`S)Ap*5-ms#M6~{l&kB> zx2MvPS_>G*YK}#g=;vfEh!v>d08Uj<*<0!0wNw)}A@$WE^7PE;C|1b6hmQDK(kYjL zLj_K{P#s0=5TFy@Z&d_-1Tvzz^U*VRn6cC(p_wd%y(xdR0(~YkkbtI>KIO-09A0R1%u!bu1Q8l#&q;J8)2qqGOV7A*AQqz%+>J#=qiDg z05mz!xe-6{(FqEM^VGZ`6v?hGWhu}b7KBkrjl)NthOltG5`ge(ZU87V5h#J7Lt&WO4O5xy!QI~( z*_+bL7b-gAxWyN(igx#$`7vl!_*0bv9*~*wnj~Vr&HP1Y>O-x$oN^0RQAj?Nak(e} z(`Kc-r8Zm9$K;dM)4hzLEvp3j8f3K0^Qt0j@s%-b>!ecPabvoqQGF-uX*I}#N;#$b zu6`Fe-A`-CU$DKkpt$wvXqi@=x&WsIzU^{66l9PoK-w-#6vJ8?h<*VyzWT2iR$!a_ zebVSqXwt^&n|+Euj*ed=HmpFCpxCmRv6*Vf{fa!4WH8kr^?x|u{@{$bT1hG5Ms0x| zA5+pQ4%yxgU2kweD)kBC^-$mpB|z+Zt<>T&#jEnk$1T362Tjc8ZXH0jO2x#V@uT*1 z?vp%@S(I@z<TV8rZA^i_atT!p6XSN^u@{2$Nx3a#Zp4 z$u^NOGc~9*!@eXn4M&7|Aa4z*7OQomL2Z)g#zZ%*p+w(F z2+Cpr2XYdVqZ_2p`>1!PcEkwP1(!kBokygny#GGEP;xxTcd;;E*8cLaa!ONIcLs-M z+Iaq15ygGKbSH{#$SHjWJz5Io? zrD!r8L4HP7A^n3Ngo>R@CRV|bXRR&o4_k|(md>wX*i|h}BcCQ!JkxcuH>X8Z>Nh(l z468i5Td$(FE_ZGr<#XBirXsB_FK-X~g#nMHk2zmjR06KUc`)ki!n-DRXL~rz&$oYG z==5?nDIydRQpBbCSEA4M-?h9QNmmy*Dp&8yP%?=gUlvKc6`%am5;-g?F;V;VbBi)! zp?9QT3`&J-UQk82tXJV+r{8aBZCA6Mn3h1Oqe#*V*Q-H^uOJ#4-6_@(*^lHFC)vTOG68jSI(Z+6w(L z6Xu?ThtTX8I)^BF&5J!sA7zg#8lo6>tRD_#EVe}P%8u{P@{*===q0;I4h$VBe8zOb zbcfZhw#I#VCXOgJA7KH$H!mgc@y|IsdaaaXUwyXiy6-krgY z8thfPVNX?-=o;+Kt~~Ivh=B>#K_ffiZQ|@wV$oVR^CEI>E9t-=ffH|u2Pfh!oX-rz z3Y$c%z>d79?u2o3>LrVK4Z#51up_RPj$b~#eCJ_(L;N7{tt7ihGGF47c0W3Czd0l% zf_fdcvksarJ5Ktu?ECQlh@H20K9TcJxyPW@pfNMj@72c-b{(PCH&Y!lU$6*pp`hbT z_RJ;D{k4jepQKHJhXdX>+v)!{X5q1~4@qmB2I^KmQAq%-fm(k6;AbU}h&er;%MRMy za#SBVfPN#n&~!feaJ0HQ$E~2~`Zm5P@J#_w;9234ieOfI?;?(PP$`J3 L6Ne>s3^@NkGXavB literal 3389 zcmeH|`(Mj@9LGOfIZY3=ZzQK=tJO*&UF6!DS*?pQ^e9BA)I;t`7nLSqlUX&CqN0Nw zq;W(F9W+}~nx%^rl}jmEt-EyI-+ny*0^eV@@ALEeyf3fMh`5gQ2at@2guU=X*uRFuLiv?5+u=oXKg-RV1Wzm}h>y^u&u;AH-cjef-c==? z*D`vp>b6^2eCOS+3IoZdOU?ngHK7^_IZ=GctF?Qwbj_?16n-l5p4|trW!^doU;G=$ zg#nneWvaVac_f~9!{I@2Pp;-g$I}jC&y4U$icZ%JdU5>)N>y*gvZ~&L?~Ydu41bCa zrW2u#-_LIcesKqQVIKX<4%r&@VW{zgu+rl>!?uI=_xtaPj<1-iG_M=Ik2lC=fJu2e z1UNF&TzK&RC`Ltyxitd@c%j46-i3$A+lSAwq^Ut4D^kvdXx9_BSP(UN6-NFWHo3l5 z3&uy@ysRl>6`~m#z6D68{BXJEDBr@C@o22J`_TQhvRP=wR4NK`iA4p51R|6EObb0E zQ_&>PSoF$@KrH0~7{$R#0M-DQ0FD4qgJQk~OxXJdNAb_ z4s@xgQ9OvKJD|W_0v*&tWuiJ3DD**L1d3=-?9`>8HcuWRV=WrI01_Di$D3YY&OjEa zh>&NaA~35pNlZ_O;If>Dl*xl=i#LFmd;o3$_yCl+0)X@|Od+TUrT3v6J%};GoT!=e z1cJ7LpWdfII&&hKrwv(8LbF^O$hwctM3!u5t2LEhpH4fJL6pDnGDwHH==6-p16R6cmy6}kJz1}fpC6GXP%#uq)Uy2X&BNLi`1 zn<710wyOx-DgOTwEmCejx(w`v17P!q5|n z!>dhQ6cgUhX8*9M#lVb85DMB1jA4*Sf0;gLy9+I#sKsCrari{?#THt$gCc5CYMp*G2VBiF zg(;Y$v#dZ>eI^n@^U7hx^lk?x2I)~YMLXjXd)&mgF0OAta$sBnn@ca8lh_85_2ZHW zAXyzEs?2gVnZ92r%HK)@vz0FUm0Bn{+l~{WKQg+qSykQVpLkwm-*l4Sp5+7!7g{!z zj2tG>^FO=}RDz8o%vq>| z!$SqLlSoDC;_U41joah%t9LqQ*e}eEZJaAq=Rg<=e#DLmlKb~$4TXH}IeJ_iY~>Ka z7vj2 zPcMANF>t%VvDlPIPuKWGl2ggvF2&ICRKYb@v7qk9lV}D1u5@K% zXs0k!zOlsc^-_i&W{mpq8=%??yIm4h64#};p6x}y(iGE^VjmdSu|l=`>(qUB`mWt~ zlvuwJ`&9XvXyy!Sl2CEOJl0u#(Y@wJgQ8KlK-+*%ffAd6p>=NuF0adsp8qB@=8q;_ zV^jmD_=|juBkO5V_4m~_H#QFs`UZAf+~d+ynnnv|7^K+S)#Exd(A5{w?)2(=J^uc} zul>k~U-plKrZGC~hV=4n9*M|Xj0ic_w=N70uXQAI&usF?4!@UEK z&d}xDvGgV@jL4k}*W2N6FG{9}FlO^`GgQ3~1PWqoO< xCK6HMckSs2acBJRI|1K|-_LIcet8GfUmnXMJEu?!GMD3CxH)^V^I2OG{sTz&_wxV% diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.png index c73024a3e8466eac6de9e2e133e3787c6dd8fac6..d2fe2c73b96cc05babc542a9c04ef76f8d23345c 100644 GIT binary patch literal 10864 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 Q_M)n6tsL0}ERWOw2fap}6#xJL literal 10275 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 J&@teb{{dcRr>y`0 literal 3389 zcmeH|`(M*#6vxkZkW4UOpn{|^Hg0KZSYZjwIR|5SftT(j-o=~>ge@;|3-B9J4hZFD z$mC{IT!AQ3k|Ihv7^FB%kYPZ|O>kTqg3d9d^X+lx0C-dA&))!G!UUjgrq4hki%k3+e~7~y1Ux9aH-7+MOb_#fB04^Cbg>j*)>9#W zl_)xIs6(BaXSP748+qTWs-ok-U5D}?e(?Q7-V$z-SQITSZ`vp+uyNUDx<=CF)Y(49 zidMXBdcXQ-r-)isipV)2tNH7rWU1%1eWP;IGd|g#S?gp+q8zP;N?ohk@*UOB?|Q4B z$95c3zclp4>~p2zI;Nj#2ma>{kcZY-F1=7J=g>&6>jz)-4+{L^`Ev$ij6GV0u0}Be zkB>UYIcSo?ioh!~+mFQm-!PZ}+}$!9Aj1uH7Rzrqh8c2sb(!McyBWFrE!t=y?le>K z?t-0LclbXTOa6D{VPi`z?+Vzn;aS9CDC{Fu3Vk`2@Olw%i=71&* z2&Qe93AvMQ4d1$Qp#LNgA?^qg5X_)J4gw~ERR|0S?6ZL=T8dydf>;WCkH8JVy9gp( zI8dL0Qv?*iEW^S$NdJ(a)m%}UL5wvMBAif>3dCbeRCuGpGuaA8UAZ8o>j_u>2#VO@0}U<>*ns<-!b&UYk7i8I@A>c;hwupsd{3! zsZis;$EiVER^_7mP7m&87ek0_|1DkYKQ`BEOBZKG_YG#W<(U6zLTzJ_vr^@$G~*87 z+DF~{(p=FJYPG^VpA}!SSg+HyQav#DqmX|n%^C*@9Bk;Zal-NvagNRJAMkK-Z`d%w z<)ko4Y6a%#Y(Rv9&OjqbT-4RCSmGxA=4%{B#>(T;D8r+-vh|>tj}{T}zV$)63~#$I z@A<;P)az_?Rg{SiNeftFjlTbPFAUAyJJXspZ}Z??PB~F_okdAxC^>b2?W{$~3QE#T zNv^SZqbMn*B+ZE^QB(-_2RbuSuht1#FEP;UaQVm2OrTz!E3ZhMOeh}F_s1^f-4i%S z{FF!3g}8CQbj_s0=^4jQlqD2mDdZ!(34Hzx-TjtNsn@Moq}a}JN0l#nqF9U-9L`k< zTC4xfNG+Y|_^4AOrGW+5)>cq+k-Tjk( zhR{dhdA3e4j%Qhu?VGgSFr>a0Rrd4B*3c`gb+XfeoZ;{NVuLWu3F?a7=KD{ys$W+e zes$}%uwu?zUP?i*!@4=g-`o~ko zTQ|LOroLe2hWa|#ZtG&FIX{%ot9-Dj^xU>?K1Ml)Sqfs4(|cTr9%@N zN*lfHwT(U|l4NT#9B=Vh&lFo6ql=y}XeGmvcw>pjc++xr%;P(Z_Z`#xWw{Zkdxi&R zY_L6}?Ulv(UB=oAW4}#a2u$$FtTtmESlfHqg$F-j+iA*aUGMYi$e!5G!q~Zw#?MC{ zqXq;xP+9rf*daM5T-Lm@_+>y6h_IW5F!LX%`u5ZuT|1IPClr?0@M`#Un8Z}Ge3PIF z8+uI>f@S!?27Xz8vmNoH&kYRVA)rF(oeay-lB8 Hki>rg9Qpw3 diff --git a/packages/flutter_svg/test/golden_widget/rect.em_ex.png b/packages/flutter_svg/test/golden_widget/rect.em_ex.png index 03519b9cd0df80b88d6465830d6bf3ffb1be145c..78fa8e1206e717fe141cdfd8facdcdc8476769ab 100644 GIT binary patch literal 4626 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 DuIGS@ delta 1999 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 DuIGS@ delta 1999 zcmYjSdpMNa8eiWxqZuX|=bY$b7@9bT*+^{;k%`#m6xz>oFv>6|O==UGQOc$7F*;^u zNX1 zeC5ubXGoUm+n7D}o4}3x?ELZl3(xzRO70*&k2J0N$>$ zo;M|Z9@ab(g6dz_IN_4FgO;XQ-_n`NC3Ec;wm_5J)qSXTbFXMY~zdr`FOWPPJk{8<|Shsq5>u5i}rN_Dq*KF;hg|ky4m_k08ahUufa%!dor13 zkvwaHmwV$U5?A)`5mEkK8D5M$n1KEr55fhV+Kc zbS>SV0>X7u&JP`JIRI$lyVAf4m=OTZnloKrQYtAxpyzEAm_e`lAS!WH!ElvS_fgtN zvNFm!tnmGQJp!~|8nZ%woXCjylld0}0Q3iYzamcjRBH|JN?2)MKA7-qp?yVzmHcB8IxtO@*Bn$fic3%7k=k%g_1EPM;}GqEmqHhb z{8`QpIG9%+@(+<_JWjK~858dOymx7w)zQt_fej8vWF-%!xAywb2(u&d5=iDcj4iMX z`)S{d_tsL?P8B+aF%M3A@#UV0M(>Q_rszA`dO&)o?uuD*%zNntp^L-sr2DWfsFRB$ z%B)MLHTZ+@Cpx#x5RuHIaTw`e0~gcL8YdCmQiB|Q8QOUuv6gf{6elcJ?%M6k|D=xd z%_eL4Norlju{?1n@&bZc=tI}Hr56cZ)GRfNQO%O|snpcJ3DR!|&;NCKH`iGjrE`zy kjq^*xLV{&=sw@0^bx4moG-eb)Z2 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 ZwO^{cll(l*?-OA2J+@Ayf}MW<_)ngU(9-|_ literal 20024 zcmeI4dpuNWAHb*bM!l7$PxnMSDn?2dxrEULlM!knw7Ikug%XCuFg9BzDs85;384uy zxkSil45jR5b6HJp>pE|_jA2}cVO-wxoHMr1{=1*uKX&(=e;nueo!|33-{18y^Kt#K z4RP_pwF@yA%wo%fW@HRzfg1*+sH8L>dh&ulp#c4u<4-2;$7EHh^gzET`0uy0Q-Ut4 z(rG#dvjJmiw$Co;VPDytInZeM?dj}(C7=zxPy#3clmJQqC4dq@37`Z}0w@8L07?KQ zfD-se69{iCPP$t#wEfm=AJR(fcfQ~6U-ho$YP*Gd|D&SsS}iDbC(1^aP>$v%6wT8q z%i?sWh_tRM?I|}e)g~`m-QnhbQhQC>nQmc{;92#&&W=@s)cQzejej&TbaN;HlmJQq zC4dq@37`Z}0w@8Lz`u^b-gBO3l)C-|j8vYR}$>Z=ADo_I~dj%ztO^H&}-MXZHT~#=nz# zT#9B?E_^~fybswYogT(>9R(j=W3&#!+bXpk5R128dwsHT7kHY!0fAte-*Is@kw`pK z4W2$qL6A-6R16iQLnB<5?7lT%#O^)}DqQWOP@<)FGE}`}!tNuCk!1zz-%HA_kB*3l z$n|)vqM|aXQS!hhEi-o%ynEPLlBEep&2C=cN{phIrfdf zwyx(nzlZYnj0hO^5$EL`V43h6g$}C(g9fcU8qLHr_~PbR%aElZTg=SK(tz@Q(2^1kx{@mJ3^O zqqxpEcAiBlwmQi)#-lp%uDGU#eu_#a`NmvZl+n$DaWBbRS+pbBp zO0eIUpLpwNn?$(jp0}p5vQodK?exy;wP%-WXlS%WW#K+|@F{y*M3g;(b!|(5f-Ec? zAQy$xI^|LH^m<{fx8A99=kT~~f~Rc#)0t17Qm2XsrMdB1QJr3=0|EnArq*gkrAS*9 zI#z)9$Mz$;PH<9s=3-IqGj_4EFt5>jU~+QORxYs*k>K91aMV#x**!BZSvf6g!#*>O z$r?3BETxZl95ZP6^ZSAPFp4*>%3wb%aN81!K4e@)7YrZp6w66)RYUR+wZFRkM% z1)KSH3YDwMb}DfGvwGtV6R)VKN1Ntp#`>t&XkO7U->~CK^3DxgUo}JoUt8O>(xLO< zR*dznlIo5kemcu)#x!6yIfo}Id`Zs1%f4jTZp$xO_>sn(FPZv}z7S;h;K>ihcJm-a zrKfO+Yo?OxC8laDu$cB88P_fVei%JS?nZ^cl!Q-m<+514pZoj!3&*KpyH5LnVexJk zc$Mw7>B5Nsed-GA5z-GI0;Yn~6Txu%S99SCW4y5P(~vRl7H@F;#ncio5)*~}4*XoS zt&8et&zH%vT?6dx1CEj|-y?HcJrLzfb>Ohv{({Bgq$+0jhn7T1b)#}vTB%B4l|gn0 zuGMx`<0%Zk=Na`v$+@wR!fi~IPY-oQ8`Z!B#%4%fF4JBaok|ZX$*{r?H+qjI%i;^d zYMp{x`vHUSvIWRY^e5*wr`Dz$k;N^PJ)z_IZBH26aGfnr2nGf(ydSs^<+p*{TS}M} z=Va;NI&-%AsCSNhn?#gN>2=m=z6vx26E7km6LTvK)rjRz9zDiP%2Z9_sO+*w&r=gP z-OpD?$h+*e-j%^(83l{2Nj)^4hmWjSKc2&4)mvb}blW!~79aIAR&~8c)=SQ4=6gy! zQWbeM(_y=!F78x~(J5?E2a{5DVP*%3@l5V>_ zsVB`sxwSs=(u%=z%R9I-Amo-NpZSM}!{+!i!#KVum`ez~c)(UvREWhg8L1D4j~#FU zqT;P`eP&hT2Dn6@Uh=y)1&~7h`1b?`nUl=!5={ZQoTG@Gw{x9tEWP{IT&jM8jcfl< z)#&7<1ZHJ{G7xH5gY2asD@zznH}I}(rZ@c5U6w61hM+8ICIA^X5Bb_y5S3+Ek9ZEl z?*ZiH6)kwCkWA9=3-~w+ybxpb72*#cb**=;xoOc-8{zY$u4h2jm&_e_|3vks1>z4m zyW|UdA7osj&Gdd{qvpWomslu=C3DC0a4C$PYho(mXt{8+7A!aLmV1?-F5{U-{R6-s z7S&pX40O4W@EV3)`(C+$$tUv>rxw@2uFws+DMVW2w%FV(WQJ|+Y;PayPf*F(1Z1bL z$ai!Nas@WuGhoMA{mgejl2}C17cwhFmN};U9X}-Ax=0m z8LFRzK%gdGF7UsHAV_p9TP(_dx;;gWjFo=yV32S5Rp}`9gRl$dVGx^z zIRXc$0x^PPQcT>eXj)8)GpVPfCg9^VoIGZAhEj-9ZoEyJZRhTcf@)xWC{G-a!0EG2 z12)=TwMbDLh|2~dWCzh$!B%A<=fbrZ* zr@HbND!)B8krMZ!}!{k#kU?KMWr%Vy+`OC5Gf&KSNCiUwIC%c)XSa0u9q}_JKQ8dS^75 z)G!H)#fmR3E^hlgJpTSR7mSzI2O$SEVrrJKK0(aqspClaSWcF!as!;nsIhY8ul$OP zW1tM_Od2P44g1R01MR9SkR&xf4$8VWEvk*IvZ0(%Ne{|*S`Gc`Ull1EfIF!Yd2T6# zD(QNYpu6NfG4!)DF6Pv==8pDvkHB4)u@(}Xi?q6^M@WWEAB2*L=Q8fsaUd)Wu6YlUA=6OI{n6=DYq>2wy0@M}xUR5g_98V|6+OJZw_rEp6_hdQTD(++ks-5|8R zt2T^x6LfYh@IoSx&ev_guc`v;`_XBSE#BGmxdxn@uVqy=`2$UE+YwDU4%T&t-UnA2->BWX@!{F}Q1?(g+ztZK+A)3BEVlToJ@%Jqb*CWB0fEP!ez)XWyU)&TMF^E?*(Vh~<4IkRe%Z|xYG_Tfj-($IL`QAJSia2G$f`nQ0(PFGj~KJ>!#B?iAiwL;<{rdz zTi!N`40S-Q2rhvNX@RdEkfkakMhfh0Z+~R8R;+=r}Y>8zH#E$z+oY-XZRCt(Px@JFd5@epIpS2f$rkchu>VJ7jAs$ za+ZqFAp$xS5TJ&Lc?r)HIJd?7hpofXyefrI!Ssg6_D#U8S(vljr~v`auI02>4u#lf zv5=K~n_5>v{xu56osqn2KDITkGL~)t7E#CeMMCJe!8^y1IVZF83gC*=us|I?CNw;N ziZx{681lQv&cU(drVxx)*JOyN_z}uGQHfCA--LCu}ILc<3 From 72d9f462e6043c41604ad9f4410d0f02bb069c85 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 25 Apr 2023 11:32:10 -0700 Subject: [PATCH 118/142] Add a script that will be run by the Flutter customer test suite (#911) --- flutter_test_registry/flutter_test_repo_test.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100755 flutter_test_registry/flutter_test_repo_test.sh diff --git a/flutter_test_registry/flutter_test_repo_test.sh b/flutter_test_registry/flutter_test_repo_test.sh new file mode 100755 index 00000000..502fd062 --- /dev/null +++ b/flutter_test_registry/flutter_test_repo_test.sh @@ -0,0 +1,8 @@ +# Script invoked by the Flutter customer tests repository. + +set -e + +pushd packages/flutter_svg +flutter analyze --no-fatal-infos +flutter test +popd From 99e6eee17daba51666dab6b3343c891111c9f665 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 25 Apr 2023 12:49:12 -0700 Subject: [PATCH 119/142] Avoid use of pushd in the script run in the customer test CI environment (#912) --- flutter_test_registry/flutter_test_repo_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flutter_test_registry/flutter_test_repo_test.sh b/flutter_test_registry/flutter_test_repo_test.sh index 502fd062..9ee6733e 100755 --- a/flutter_test_registry/flutter_test_repo_test.sh +++ b/flutter_test_registry/flutter_test_repo_test.sh @@ -2,7 +2,7 @@ set -e -pushd packages/flutter_svg +cd packages/flutter_svg flutter analyze --no-fatal-infos flutter test -popd +cd ../.. From 5e798588f92793abc11019080cd903ba4311d162 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 1 May 2023 09:20:45 -0700 Subject: [PATCH 120/142] rework example --- packages/flutter_svg/example/lib/grid.dart | 162 ++++++++++++++++ packages/flutter_svg/example/lib/main.dart | 185 ++++--------------- packages/flutter_svg/example/lib/simple.dart | 31 ---- 3 files changed, 193 insertions(+), 185 deletions(-) create mode 100644 packages/flutter_svg/example/lib/grid.dart delete mode 100644 packages/flutter_svg/example/lib/simple.dart diff --git a/packages/flutter_svg/example/lib/grid.dart b/packages/flutter_svg/example/lib/grid.dart new file mode 100644 index 00000000..26e40be5 --- /dev/null +++ b/packages/flutter_svg/example/lib/grid.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +const List _assetNames = [ + // 'assets/notfound.svg', // uncomment to test an asset that doesn't exist. + 'assets/flutter_logo.svg', + 'assets/dart.svg', + 'assets/simple/clip_path_3.svg', + 'assets/simple/clip_path_2.svg', + 'assets/simple/clip_path.svg', + 'assets/simple/fill-rule-inherit.svg', + 'assets/simple/group_fill_opacity.svg', + 'assets/simple/group_opacity.svg', + 'assets/simple/text.svg', + 'assets/simple/text_2.svg', + 'assets/simple/text_5.svg', + 'assets/simple/linear_gradient.svg', + 'assets/simple/linear_gradient_2.svg', + 'assets/simple/male.svg', + 'assets/simple/radial_gradient.svg', + 'assets/simple/rect_rrect.svg', + 'assets/simple/rect_rrect_no_ry.svg', + 'assets/simple/style_attr.svg', + 'assets/w3samples/aa.svg', + 'assets/w3samples/alphachannel.svg', + 'assets/simple/ellipse.svg', + 'assets/simple/dash_path.svg', + 'assets/simple/nested_group.svg', + 'assets/simple/stroke_inherit_circles.svg', + 'assets/simple/use_circles.svg', + 'assets/simple/use_opacity_grid.svg', + 'assets/wikimedia/chess_knight.svg', + 'assets/wikimedia/Ghostscript_Tiger.svg', + 'assets/wikimedia/Firefox_Logo_2017.svg', +]; + +/// Assets treated as "icons" - using a color filter to render differently. +const List iconNames = [ + 'assets/deborah_ufw/new-action-expander.svg', + 'assets/deborah_ufw/new-camera.svg', + 'assets/deborah_ufw/new-gif-button.svg', + 'assets/deborah_ufw/new-gif.svg', + 'assets/deborah_ufw/new-image.svg', + 'assets/deborah_ufw/new-mention.svg', + 'assets/deborah_ufw/new-pause-button.svg', + 'assets/deborah_ufw/new-play-button.svg', + 'assets/deborah_ufw/new-send-circle.svg', + 'assets/deborah_ufw/numeric_25.svg', +]; + +/// Assets to test network access. +const List uriNames = [ + 'http://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg', + 'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/410.svg', + 'https://upload.wikimedia.org/wikipedia/commons/b/b4/Chess_ndd45.svg', +]; + +void main() { + runApp(_MyApp()); +} + +class _MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const _MyHomePage(title: 'Flutter SVG Demo'), + ); + } +} + +class _MyHomePage extends StatefulWidget { + const _MyHomePage({Key? key, required this.title}) : super(key: key); + final String title; + + @override + _MyHomePageState createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State<_MyHomePage> { + final List _painters = []; + late double _dimension; + + @override + void initState() { + super.initState(); + _dimension = 203.0; + for (String assetName in _assetNames) { + _painters.add( + SvgPicture.asset(assetName), + ); + } + + for (int i = 0; i < iconNames.length; i++) { + _painters.add( + Directionality( + textDirection: TextDirection.ltr, + child: SvgPicture.asset( + iconNames[i], + colorFilter: ColorFilter.mode( + Colors.blueGrey[(i + 1) * 100] ?? Colors.blueGrey, + BlendMode.srcIn, + ), + matchTextDirection: true, + ), + ), + ); + } + + for (String uriName in uriNames) { + _painters.add( + SvgPicture.network( + uriName, + placeholderBuilder: (BuildContext context) => Container( + padding: const EdgeInsets.all(30.0), + child: const CircularProgressIndicator(), + ), + ), + ); + } + // Shows an example of an SVG image that will fetch a raster image from a URL. + _painters.add(SvgPicture.string(''' + +''')); + } + + @override + Widget build(BuildContext context) { + if (_dimension > MediaQuery.of(context).size.width - 10.0) { + _dimension = MediaQuery.of(context).size.width - 10.0; + } + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Column(children: [ + Slider( + min: 5.0, + max: MediaQuery.of(context).size.width - 10.0, + value: _dimension, + onChanged: (double val) { + setState(() => _dimension = val); + }, + ), + Expanded( + child: GridView.extent( + // shrinkWrap: true, + maxCrossAxisExtent: _dimension, + padding: const EdgeInsets.all(4.0), + mainAxisSpacing: 4.0, + crossAxisSpacing: 4.0, + children: _painters.toList(), + ), + ), + ]), + ); + } +} diff --git a/packages/flutter_svg/example/lib/main.dart b/packages/flutter_svg/example/lib/main.dart index 26e40be5..42ee8b0c 100644 --- a/packages/flutter_svg/example/lib/main.dart +++ b/packages/flutter_svg/example/lib/main.dart @@ -1,162 +1,39 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -const List _assetNames = [ - // 'assets/notfound.svg', // uncomment to test an asset that doesn't exist. - 'assets/flutter_logo.svg', - 'assets/dart.svg', - 'assets/simple/clip_path_3.svg', - 'assets/simple/clip_path_2.svg', - 'assets/simple/clip_path.svg', - 'assets/simple/fill-rule-inherit.svg', - 'assets/simple/group_fill_opacity.svg', - 'assets/simple/group_opacity.svg', - 'assets/simple/text.svg', - 'assets/simple/text_2.svg', - 'assets/simple/text_5.svg', - 'assets/simple/linear_gradient.svg', - 'assets/simple/linear_gradient_2.svg', - 'assets/simple/male.svg', - 'assets/simple/radial_gradient.svg', - 'assets/simple/rect_rrect.svg', - 'assets/simple/rect_rrect_no_ry.svg', - 'assets/simple/style_attr.svg', - 'assets/w3samples/aa.svg', - 'assets/w3samples/alphachannel.svg', - 'assets/simple/ellipse.svg', - 'assets/simple/dash_path.svg', - 'assets/simple/nested_group.svg', - 'assets/simple/stroke_inherit_circles.svg', - 'assets/simple/use_circles.svg', - 'assets/simple/use_opacity_grid.svg', - 'assets/wikimedia/chess_knight.svg', - 'assets/wikimedia/Ghostscript_Tiger.svg', - 'assets/wikimedia/Firefox_Logo_2017.svg', -]; - -/// Assets treated as "icons" - using a color filter to render differently. -const List iconNames = [ - 'assets/deborah_ufw/new-action-expander.svg', - 'assets/deborah_ufw/new-camera.svg', - 'assets/deborah_ufw/new-gif-button.svg', - 'assets/deborah_ufw/new-gif.svg', - 'assets/deborah_ufw/new-image.svg', - 'assets/deborah_ufw/new-mention.svg', - 'assets/deborah_ufw/new-pause-button.svg', - 'assets/deborah_ufw/new-play-button.svg', - 'assets/deborah_ufw/new-send-circle.svg', - 'assets/deborah_ufw/numeric_25.svg', -]; - -/// Assets to test network access. -const List uriNames = [ - 'http://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg', - 'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/410.svg', - 'https://upload.wikimedia.org/wikipedia/commons/b/b4/Chess_ndd45.svg', -]; +const String svgString = ''' + + + + + + + + + + + + + + + + + + + + +'''; void main() { - runApp(_MyApp()); -} - -class _MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - home: const _MyHomePage(title: 'Flutter SVG Demo'), - ); - } -} - -class _MyHomePage extends StatefulWidget { - const _MyHomePage({Key? key, required this.title}) : super(key: key); - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State<_MyHomePage> { - final List _painters = []; - late double _dimension; - - @override - void initState() { - super.initState(); - _dimension = 203.0; - for (String assetName in _assetNames) { - _painters.add( - SvgPicture.asset(assetName), - ); - } - - for (int i = 0; i < iconNames.length; i++) { - _painters.add( - Directionality( - textDirection: TextDirection.ltr, - child: SvgPicture.asset( - iconNames[i], - colorFilter: ColorFilter.mode( - Colors.blueGrey[(i + 1) * 100] ?? Colors.blueGrey, - BlendMode.srcIn, - ), - matchTextDirection: true, - ), - ), - ); - } - - for (String uriName in uriNames) { - _painters.add( - SvgPicture.network( - uriName, - placeholderBuilder: (BuildContext context) => Container( - padding: const EdgeInsets.all(30.0), - child: const CircularProgressIndicator(), - ), + runApp(MaterialApp( + home: Scaffold( + body: Center( + child: SvgPicture.string( + svgString, + width: 500, + height: 500, ), - ); - } - // Shows an example of an SVG image that will fetch a raster image from a URL. - _painters.add(SvgPicture.string(''' - -''')); - } - - @override - Widget build(BuildContext context) { - if (_dimension > MediaQuery.of(context).size.width - 10.0) { - _dimension = MediaQuery.of(context).size.width - 10.0; - } - return Scaffold( - appBar: AppBar( - title: Text(widget.title), ), - body: Column(children: [ - Slider( - min: 5.0, - max: MediaQuery.of(context).size.width - 10.0, - value: _dimension, - onChanged: (double val) { - setState(() => _dimension = val); - }, - ), - Expanded( - child: GridView.extent( - // shrinkWrap: true, - maxCrossAxisExtent: _dimension, - padding: const EdgeInsets.all(4.0), - mainAxisSpacing: 4.0, - crossAxisSpacing: 4.0, - children: _painters.toList(), - ), - ), - ]), - ); - } + ), + )); } diff --git a/packages/flutter_svg/example/lib/simple.dart b/packages/flutter_svg/example/lib/simple.dart deleted file mode 100644 index c93b44e3..00000000 --- a/packages/flutter_svg/example/lib/simple.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; - -const String svgString = ''' - - - - - - - - - - - -'''; - -void main() { - runApp(MaterialApp( - home: Scaffold( - body: Center( - child: SvgPicture.string( - svgString, - width: 500, - height: 500, - ), - ), - ), - )); -} From 4c88f8b773f3eaa350876455d134e6cbc183abc4 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 11 May 2023 16:06:03 -0700 Subject: [PATCH 121/142] Update widget_svg_test.dart --- .../flutter_svg/test/widget_svg_test.dart | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/packages/flutter_svg/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart index 35023413..99c270aa 100644 --- a/packages/flutter_svg/test/widget_svg_test.dart +++ b/packages/flutter_svg/test/widget_svg_test.dart @@ -457,29 +457,6 @@ void main() { await _checkWidgetAndGolden(key, 'flutter_logo.string.color_filter.png'); }); - testWidgets('SvgPicture colorFilter - flutter logo - BlendMode.color', - (WidgetTester tester) async { - final GlobalKey key = GlobalKey(); - await tester.pumpWidget( - RepaintBoundary( - key: key, - child: SvgPicture.string( - svgStr, - width: 100.0, - height: 100.0, - colorFilter: const ColorFilter.mode( - Color(0xFF990000), - BlendMode.color, - ), - ), - ), - ); - - await tester.pumpAndSettle(); - await _checkWidgetAndGolden( - key, 'flutter_logo.string.color_filter.blendmode_color.png'); - }); - testWidgets('SvgPicture colorFilter with text', (WidgetTester tester) async { const String svgData = ''' From d4c98e25da72eeec13e4192adfa90563b01fa17c Mon Sep 17 00:00:00 2001 From: Mr John <38257989+MrJohnDev@users.noreply.github.com> Date: Thu, 18 May 2023 08:33:28 +0700 Subject: [PATCH 122/142] [deps] update vector_graphics to 1.1.5+1 (#923) --- packages/flutter_svg/pubspec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index fbf18e77..0f61a414 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.5 +version: 2.0.6 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.4 - vector_graphics_codec: ^1.1.4 - vector_graphics_compiler: ^1.1.4 + vector_graphics: ^1.1.5+1 + vector_graphics_codec: ^1.1.5+1 + vector_graphics_compiler: ^1.1.5+1 dev_dependencies: flutter_test: From 3a13376f3b663e2bd59096ca3fa5041ab65def54 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 18 May 2023 11:19:24 -0700 Subject: [PATCH 123/142] Fix analysis for CI, update changelog, roll v_g further (#924) * Fix analysis for CI, update changelog, roll v_g further * Update goldens --- packages/flutter_svg/CHANGELOG.md | 5 ++++ packages/flutter_svg/pubspec.yaml | 6 ++--- .../test/golden_widget/circle.em_ex.png | Bin 14207 -> 10224 bytes .../test/golden_widget/circle.em_ex2.png | Bin 14207 -> 10224 bytes .../test/golden_widget/columns_and_rows.png | Bin 32678 -> 25790 bytes .../test/golden_widget/ellipse.em_ex.png | Bin 8367 -> 6534 bytes .../test/golden_widget/ellipse.em_ex2.png | Bin 8367 -> 6534 bytes .../test/golden_widget/flutter_logo.asset.png | Bin 10864 -> 10275 bytes .../golden_widget/flutter_logo.memory.png | Bin 10864 -> 10275 bytes .../golden_widget/flutter_logo.natural.png | Bin 26474 -> 25928 bytes .../golden_widget/flutter_logo.network.png | Bin 10864 -> 10275 bytes .../flutter_logo.string.color_filter.png | Bin 8160 -> 7599 bytes .../golden_widget/flutter_logo.string.ltr.png | Bin 3722 -> 3389 bytes .../golden_widget/flutter_logo.string.png | Bin 10864 -> 10275 bytes .../golden_widget/flutter_logo.string.rtl.png | Bin 3721 -> 3389 bytes .../test/golden_widget/rect.em_ex.png | Bin 4626 -> 4070 bytes .../test/golden_widget/rect.em_ex2.png | Bin 4626 -> 4070 bytes .../stick_figure.withclipping.png | Bin 20756 -> 20024 bytes .../test/no_width_height_test.dart | 12 ++++----- .../flutter_svg/test/widget_svg_test.dart | 25 +++++++++--------- 20 files changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index d0f7a722..91f21a0d 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 2.0.6 + +- Fix test-only issues with latest Flutter stable (3.10). +- Roll vector_graphics to higher minimum version. + ## 2.0.5 - Allow malformed UTF-8 in loaders. diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index 0f61a414..814e8167 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -7,9 +7,9 @@ version: 2.0.6 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.5+1 - vector_graphics_codec: ^1.1.5+1 - vector_graphics_compiler: ^1.1.5+1 + vector_graphics: ^1.1.6 + vector_graphics_codec: ^1.1.6 + vector_graphics_compiler: ^1.1.6 dev_dependencies: flutter_test: diff --git a/packages/flutter_svg/test/golden_widget/circle.em_ex.png b/packages/flutter_svg/test/golden_widget/circle.em_ex.png index ac9af33da57ca012b93e930391076a29ae6dfd2f..9c72bdcbea280fda4aa3b156426e9245db3ad49d 100644 GIT binary patch literal 10224 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 MgYEh|7Tk#c1$ZGXHvj+t literal 14207 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 diff --git a/packages/flutter_svg/test/golden_widget/circle.em_ex2.png b/packages/flutter_svg/test/golden_widget/circle.em_ex2.png index ac9af33da57ca012b93e930391076a29ae6dfd2f..9c72bdcbea280fda4aa3b156426e9245db3ad49d 100644 GIT binary patch literal 10224 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 MgYEh|7Tk#c1$ZGXHvj+t literal 14207 zcmaibc{r5q`}Z}&APPMc6`3Am%T8!ynKq0pMTKlrSqf3Zs3|e6>PgbrcV$bKMAnpP zlOanHY4cQL2-WwQp`MX=&s)Fu_j}*tc#q@lk81Aw+RpvF&hv9$-0ot(M0%w(LTCxq zVT&6=Vnl@So>CI1MwPRduU;h9BaQo2Wab;7^QHzy*Yeh`MFt&SN=~ z@0ckg9=--&kLG{vP+_Cf_>KVi%TA}2dOLY&@8MI@sYN%F(NZy~4!z?m@B(-F6+6Wh z7O$c1I(LV7c65- z9pZ9Nx7;=V*Ff;MU;4PQ!s8*b9XRrz?qn|Cv_YT1wI_d7Ov60T9oNXOZRpG1TkXG@>6dwa zw*zm6E>DgzHd89*)lv;Q+zdMAL~fbg-2)#`LB68=*oEVEvh6!#%{An<3I0Qp<5sP@ zuIxXkAqrp%-RZGaJ+^73f!-6_QT0-3se~KNX7Pc+bHQohdMa{%aodW#odkx|ZdZD2 z{RrOTFs|1O23=@2vrSTE?hIL-$Jc?s`*hYbkHG-zTZeXM2e-ci;)BQ5J z4SOWBp5HD+v6HZ3rZ`d)~8l(K1vkWqMuwGW2 z(f|vdp1C%e|83-m4q20Hs6oEL&^$2qnxy8yy-PnfS7K!_*Z>26XcG_1EU1T-Cf8Vp zxsScsJNWd{s9o$I#p#j4Upb>_11c|OQP|C9*)`U-tu6P))00)6TPj4gkLWNX*hd2+ z=c=57gC{5`!GLh~;_e21{m|9Y68>juVo0uJ8)qxkrDtciUZ2Qs!U!d-h9T|^LGIB! zrSxr26+TJmDxdvQ#`Hffl5t;(qDxsu#^W(xvv`B<^nD>;-&)E!C9rQ5^AkvMA4Gp5 zZDK-QvzcVjiCD6RYfn|Y_>8ICmwu93SC#&rZ-#wMRSY6J-?J~__Ri7Bd6JeE*?_zE z@+Z^~9mqaMDoq`VX=W&+^Y*yC75%ls>M6m)$>Txxw-~Ew`DyGJqS-A&Z-HFpBV=?; zS}M08=G<3c$X<3nkm1=NlRUelM3639DVAVJINN$R9q zt+O@*naXwiBeDZAPG;ganKITixOPQoi7t~Q>$}AgE>E}#)20ORftu-cvSOSr9pYkN zYxVfx))u3?tBJ=PCagHGnk~86CaJc1eNC7kqIXb~voLWQ_qYl^lHwb>#henpkwj;l zMtVA)ce%+RZo5mzE|9a+AB3~_ zZ~#0F)?dR4VWKb zq8Z+6(ygwS%*_jyDrOX}C_hk~mm6Q4-j}R0WGTa8`Q#Mm>`d$-RGvWz3WT#}W!{mV z(Y)z0QQf~nv4qwv-j~b{EE0qPe^fjvH6e^Ou8v*a$+O!h^w8$-ms70nKI5H)*-^Rp zhc+*3g_}Q*R8sT$EoCVCzjeCh`6l*Q?2*KcttFhjwyCP!X=Ndbx`=<+)h`z~?{n3oguj(q zvS$>heB=`FL0vE|X!IGjTuf2YCcbTd*^DOm9e%7`<8`u>6Lls1=UUd^i&@tp$vLi) z>1VTNRCs;Q$w)bx#vD86Fk{V8r!Ft*>UY41jP-^ZS}B<^rj?>kzJPAmR=m*~gJ&fw?ulLL-jXQYT(%k?)|-2-t=yHV^sb9=sNkWINI z;1HBoWV_Li=XREZzI)0AQ|x*L$z8*FytCN5y&B)zKQN=2K2;H_1X`V9(o**ZezhL| zR`P5QydOJzC3vkXxT+dh_~mwr-G$I-oTt{{6h8OE;`R$SgiKnApiEm0RlM7wBiiEI zz5`5d^3tMqsT+|@2gf;A_8DMDL0^@N;T4^yBWj=&uU07}wT=74`iW41t1Q>e#!X3Z z37d5p|6+S?kAl140jxLGv!+Z$$?Y@*?pJHo)6CpPg^x+!Txu{DwY^B}cS_f1MobXV zT~pk_g6?4R4oP&Tj;!H5(Gu*4E8L1(QDd1OtU=y@J#Qd$H%!Fj^#Mnhfbv`)5&SbS zKt>r3J^HoGZ4>fHleig9@dEa}BP?au7>26iIpP6Q<34jl4Z}mZVu;;R@{B)HxfvyI z!>y>c%x}w&!qj29W5)I^2mY`32b<9iyw{?SaR(6$cmjJaPYmC~75Upj> zp=&ve7AFMc!e}zp9HI>pt5)YKbcWf0LK^ugCNXZvkS)#BE&!p&-lXw7Qsp7#O)|SF zB%5$sNlnh+1B}FnT?GXu*_S}vZD(p_Lbof?f0EP^U<$9%nJs4!CxH*kz}GlJw&&C} z??Mm2CI#4+@Z$z6$<++`f}e^>yKX>CdXkgNy9TC8QJ3r5*IiZWxdE;EWO()EdXrWN zHQrAVt1XrxGF?i0r?P1{zB#G1n6FwHi8$@r%;TBd6~K^pMXZVf1D=w*@B!o(wTL6- zYBX)b&h^m1h1-*o=`&y{ z)vGFdZTMmM;1{sQYLh`BKD2~2*~Ykws)OWw=O)EHmk|Pv{^;2DvDp`Smit#mGW{mx zDHiL+Y9Ks*pxP`iUW^9z8*>d)hH{31ov#&>NYl?|9n44bliywg%^s_c2)2)H&dIn{ zFN;s8x;P&m2ca`C^8Kn2F=Re2JCyTdz}?zb=GEPchD7qZ2xoyi(8$U7w@f9+_K+%G z*;m1rGVYU?nWf+j8h6``PS5Q$1wPsJJ$x%3fhGg1Iq#j@{PFhuWjf5m6UxZw z!)ms=@UMY2topWCnca{zcDv0PC%e@n+8zC3esE`63^=KR%eM`P3>$k=lM(kFxE>T9 zMUCd)A35s-)^8N^$!6Ix?-V(tZ1$s_KkEg;S+#!yu1rWa=aNBh&lj`U;E*rl z%195L_U!T#@uIwB$pD@CoB(%FJx=o%C&AypW2r=`P$3Dsex&q4{GkjUa-@g68#h&L z^BR?Ls2^>juI{yzfRHBVGZ!Y=wzIT>_R=(RG^~3xS>*);h+YeiQvTE5F{d}~T^=i} zJ0Ida>qw-7~~u_T~2627mW!kgM-G{p_tlw(uOOAvBkO zAcqgKkFChb_y#IEDCrbH! z)bA14l;#O{p?lyqn?XydYU6jAkoc3q!#mylnrgu^NazD8ztoa~H>1_~;A##|}DKiHS$8~f)QVFD~Oz3THK2jBKD z?vYgNDu_dNZAVQ~3p=9jgBDds7h2=IIzl1&Ko&p5hVq6XTzKYR&1LEN-~Bm6%7!!% z*>!jKza6Y=>9sBd{bFtd2GM%Vo6?k;50YdYfVb4x`{2=OMb;$-JSs3c)RgXBJsw{Z zXVCM68rz8J9PgxtJ@0A9C;CaS((#1%;=I4CY=PQp%cH)28<4888>SJq8BbztxO>61 zq1+=|>qozi9BjJIkf#mXh2m>6(!pxc0RKOe>FM>dxQgy}CrVnW+I%LD1<{?=-DI$> zDVS_Cd_Yy)b7;(o676h@ozz;^$*}dErFeCOx-ri97eX@}MR7~oI!$7U8sfBNo~B5y z%V+hA-l}uA?w}ynWmCebrGv3}H^E;JLn(188Eg;OZqm1JQM+L3(|^^md(nDg<4yHG+zDYJMqU;Vn|uVU0!*I zvnFwR@~z=LA7z60??)RCX%e#qv#=e9mU)^ZwQ>ftoehCH{?r=gEB{p}WBmrV$R9Nt zKsSEUWOh-zTdXNC&qyWPU62DZ&R)#GyEX7Rdi+poqB4JwfHYtKpfh3{b8+<24oyG>PdgUUOsDG)TqtRRY)s3a)3-Z9 zE+p=B^VBko92ffA0zWlG6DvtqQ$UM{{?;T8w=1w`+d0_NUtjOfW*}O-ga;)g&$4<@ z0=>GC658tdB1 z&77joCvatE8fHD?KPK>K%Gc19p{#nod|n}`$?8wpd@Byr|e`or3TYn`)V^wjx-`>ti3f&`lirPE8sJ%o*4H!O_cBZfMA8ebk z2;Aotd+|uMU+5&SoOXX%l4br+xV8Q|ZjD&i%9{LhdwzL8Wl?)u7hNd5h)3^&v?LdA z^q0Lh=x&<2S#XaOKlN!Ep_Pqm-J4Ekc7Gq(NXwZH#?ue1Uf8F8bFI4Vprv@i-8sdi zto=U)mIxj4>f^8u9h2GpE^Bj5M#N)raWrQ0rkchvx50TmQ@|X>rw_f8?Vt9r^B{HhWj6HTa)2 zc^Gw#ug8|_sXHQ?iq|I&tKtO2LEWS6B|a+^;w%9{;luEyg7lj%=+(#A@6RF*>Gtx%b5oaw3Kj$Fl2|$$LDc1-$&0!1$d5<0(N+G!(P{lWgGYF5{mm;DLSf^Akqug3dkaVg9 zp)rZjKVKD`T)uELykfc#)hghq;Ry{aBd6%{G|NJr4!bK=N z;E?#Lnvao`@ysS)^U*h6Z^UG9sBOs2@vCPL-D`r_yH!`|QrYa3O`II!1bo(DZl93v z-KCo@b3z5OnXZ+K1`hf6Eorbq=xvtS9~FImJ*<9HI^}!k2vt^j-)h7%Xf#k7O@hid zSV+~-Pw{}YKd>aDT1%4O{ub^kW7kvbX+v+MP_@NNb3M;1_mq-8I)i)hcw!N{*V>5! z@#5*8MFV@U5Q@UP-ruIJYIxo!|>zs_uZ5P1swX`m9=PKY&W4OkL~C9weQcxh*Fv|8(e7`0S_L=i)1XK_y>*u!tR~|Kicf0%t4(;xGy=Wl7Ref{BpNRD`QeJg{g2SO# z5CsNku7tv^ncT6>~3PYJQIy*s+!mi%@T293<;>(~Fd_p((C zD&+U3tRAA>6KR2uq?RJumx^n&R7H6RVYTN^?`me^bVLvA$Otueu9V*WC5^xfzf1?} z)6EnsUU$hjO!INb(==4uvu>4)0~GeO$Q65+BUY7V7*n4x`N&xz>DRiWh{dQ)JH2b@ zq)eJtff%Ytk0e&Fm6k#jTRo^que4YuU#SX?wW64|D|{_6JOZItQlUDY=iW8Yn0*Mw zFOsToG^CCXggMgF+q~c~<@_orvA?yHNNDy2ix7PvWxuw=p|LxUgwDgg=S~joqC_jN zz@xAXvt^U+5u&(zFw49nOZxjk51{B&8%9yj@1JE&zMoVOdKc_W_!;#`oF};oGNmz_ z(6z5hS7{R8>mjr%5PP*5M{YTSiMh7q^vUMEGHDhvh-2sF{=jBBEzaCP9KBjk5dVJ7 zqo*B5l?_!DN3_K%^)2=I@7L4Mm@yE`hRk^_y?dZjHsTM&x_`U=^s?z1o--aY(ShC7 z*Zq#m0&Aw6U2&&Ur)r8=2u)p%U;6N`<9jR-MQs^DeD@3CV;5MZ2Ajx!d!HeNSjPJf z5p>6j10vzdj`lx-<@>iy-+@uTm;VFXX<>pk5usm!FnBv?^GqiU>y}mANYArageb$F-Vgr5bbf{lqj>VLdz_c|18J2_k_eq|15aMiT2V@YI!rT9F@4*jb7|B#2-aF{C2&dbnx zK~g%f0^2VQJIYMk*FQXW{MYl}5**3~jzlc1>yxbe@nSA8y4sri10vgw0bSS5dJ-gl z;1DGY4Eu)OLzt|2FX*v52TFzMTXi{WX9U>G5=^IF@1j`URzS2*R$}7cKcB~c?82k! z9eJl^K`oc-VZ$!hlw)rewIBVzbaeP2=5Bsgl+p5|mn9X?di=LO-zjH>eGdW$VT7r( zFM%f+d62Dos1Pjp^^aPec}Qs!n*G=*kgu_CnZZ4@*H>fStE9G;u~?aL@7=dC3^>WRJ-!`)pF&De5Hu|(#69XsOcRz!d^}!xkkQ16d=)zh1?j|e6y(T5Ar(Q}7 z_3D`A>y#cli>r8&*UchX$Cn|r`@wfz&q8Y@`37({73a+qDxSZWzF;ngstuzrbF#iP zvBGwPoqgv*FbIR#;xw8~y>G??7QNdcs2ed;sFpbK=5#74Uu6$4qN+@kKCral(sw^f z$Xx6N%zr(BpcMFxP;|^4(&p5;4p7LU0mp$L43{Z&YrlH z`!K)!Z;DpIqnU~*DeH^R|3sYCp6U-QD}5+`WmiKaezFpar3y)L)C46Qimpw0G7Fvs zV(s!IljKe}LFV3bklHXc@^!TMcPsZ(JidhD*?KFC@#t;4(3ZCOyDw$(2>8L=x}{;9 z`!Wu$osy_=2Y9s0+T|i=hRyJZ&8j+tlvFV+fD`>G4(^4@41b;4CU4j#@Mj)t^7>~n z`-1u1n0u%o{R|#$C&jprxhDRg%adAX>`Fy-a8EFiuDh zi}d_o9P46`zW7PVbKF`!Lvn@vxIKfXAG1m0%{oCC6d;>X}_iNzjtWZxrF6 z@~Ni#+dR+I<=~E}8X}|2koRyoNw`$EEGZ9sloN6A+os`)G8Xh6Y`7j0DX_I-Q>@a= z0Z7Rno9n?P-Sa0!t@0jgYVwpg(u7><+N}XUiqBIS}8eEB&Cg-@;Y#ZO@x!9LPEz8lr3)Z~)57)YfAC zH7RBLRYRv!l_BnY;;xjG2-r^u@U~HYQ;k^v&>1Cy!G)Z9JMQ)p8Kk^f?anW0iQq!- z>OZg)J4Z2em2%N#r6k`s)m5*LDIylXs(Y7+1_^Puxeq0+VeiQsa$X3%UdwbPlP^{7 z=d7Q2x?HairuulogF+~BcikK{`gr3VQI2Fll#t*3Ke3_t;1Tx;-V7X zo!C|b2$!iX&LY-_@%iNyq@kQX1vyA8?OrG9@xK5gi&i*b0(4=^E%}J8!aF0I|L8wU zf?&5NrwkD7EK@*UXWWRV@3P6@*-Cz&L1^N~OO^C1;JuO$&d1O7r*89!o}E-IPz+?l{C6!W&)hkL*~e}b)8OU` zzLL^qzf9oJTi(R)YyYw&!Hr1=ZvK)9?CA~u^vI5(=av#i&lWkb!@3Vr?_2bPT%DRb zYyDlIZ2Kzk2Ide?P~Y1;!=AVFL2DDLO0NPNF%B@d?Gu+qi=QM;3A7-;uvl>%r{hgO z$o{eTCtRf!ZUo%N`ssRTBCin{ zXr6utM*C#LX(peAE{s0^Su){95aBV9rmWm2r|k7blXy`_3K>bgak8aFnduWp{*BQw zD{XiN`Ax37Gd!!y1?F{?{~;%dM>G4pO9T*bSocExC|HA>-G^1++8&k#T0(k(e|48n zAW?zCPhf*ru)!GXsy4BN2+3YXEJZS53yz8%BkXZ%iCXUxb$5!>M$m#|wVx%U9<@W2 z+`?&N)d5ww=cnkJrdmKkQ_<}Jelh0$RrX+AHx5NPa6_S89;PbhnR|6Dk;;A~EFt+H z#AckGhbskC%jkq6C^c#^4?@R;qSX?>{DPvk98{%6jK|opdC#%(ulht`pm}RA6u!*W zEpSacx`fG-uq0BZZung^s#`ULcdO?`mWeK5)y<_lg-U^%`4O<|-K+Yr>o0+TGz>qH zvQBz&I+l1<^f)LbK~HU;+cuZxRBx8^nj0E>@{(cHbb>Je{R~d8T$Bmnj(X}d9!yZhb z8oL#fYBchUPT; zvV@w=&eq)}kqoGg$3@))8Ix_|^4X@)P(bGkc+X6-h0su#DUHMgnxUjA3Ww@EhjQ|$ z$W%>PJy(x7@;JtVdkNcDVti|7zKEl&Qz;e(&B3P_gag=i|L25Bwtt8!eyr8Sg%W

}+Q@iwM(mxSY_d`w|H&t(A`cpys^;##dht)>SiNw$%XBp%1~%d4oNa)Ce|++byOL z6eiPN6RZJE6Djm}(46T8!7A_uhY}b#NGaaFY(YkDX)ijD{O)!1ws|TgJ;omH^J$V% z2%nU3_`^ep=V%`uF-S7LcmAkr+AaRCE2Q7;nD*4W6gD-J#cL~P=J&y-PDSkDoi?n1 z)6x#?l%W<=vr3C?=cC5B=6UTt$92J zXunbHWA=$^6==JhDBq#g_`OWjKstI5^v3Sh6CF_|NZ+;{mAlKn!u#NjEIi?jO zeFrp2kBx|V>JkDBJDld!HC(%^yrD*!tyjY1g3?0gJL(F)=Cnz2t2392F~vcL-1LkW z0oK<{#SO)qB%88Zs-TOYy!4j$T$s405+T6Mp!=I9(-kbT_tl9sTLs)em%e8?!1$of zT}WO18d^c?{&Uf3WOM;rBtB+N2v`DLPtIBTJA+<}dRpbF2_`OsQuT%~jl8v^v;5*4MJQw<&TSVwQ1@}4GB-<8XNq0a(0JDl25mS~R6kX|X^2_G!!q}6Q zGV3zLwtztB1TT6z!d$3=X7D$(RKL2}CF@w%4ojV+jK=^-X)88d+Rr0M_yR%}_d09w zcHj1cWlTFb#bI5I2m@1Q?1VChcbgE(>Trs+UhtwU?_=2l+#ML~nb{SY+)@IZcVPFo z)IZ}7ffgipF0WVvokR_;F1Rh)>D1Xou~AB>bi4dZQHvh;8z>fM%kk*Ut~b!w+DyV^eth24&rwr$yL8LGeTATZ;9oc%X;ZaeaT_a zzGB_Jqs~q440{h9WI%H!od+-lH1J77m{zrQOj8qg*kD+pb&x?`0uV)tJev8G)o*n> zjBAhKFBAv?;;>k&Bi#Xdj8U)6%0%ZNRD`LD(;}=c92QT>oIP}$xs$yOLv9p0-cRE# z?T|DYccR$+MwWgc*@Fxzr7;E@1Y`7l_n|M&xvx!BFA4A3>-FqsvK7`awfrz2wANMo zzknmvgwV$+pM5gb1sN$Vh49+$y;o*OkFFXeJ%g11m?n>6-ZGGh5!=r_NGO1^$$%qn z#SsAcxN;9d^Qaroad?%<`y6N^W2}wKw zyp-FhfR~b!%Hu$T&NI2(O*mDf0XH0RTCZY~vHJoPO^bUKR;^yEq{WQM?0N!ZFFvF1 zxxXZg8(gC==Mzh}M1>W+cSC8CYt=X;W88}Uj5R$jUD@o(L9l;|T5B^yu&!WiUN#2b zA~O%C3DSRe9oeM$T)#ZG#LiN1S_=TKhFRRv*8XQ81fzeVfBDAPj)-LhXc85Q3<9== zyiemL!9g{jz0_gu&ito~hzJ1>`;U&~4P{0qTU9fbvlboMYd(@e54-;s^h6sp;bF>t z;fPOeyr!s-RL5A>!YjI1j%8Q(<9@%cL<3uK2|s{-6r#r))ax*tG~e2hj7z60!(sHzkVbH$TbrZh8V5#_C zt-)emU7+SIOpR1@h+&=!5OF@K72*L$;@7T_*m4XV4p>WF0E3pvFt@O6UAh2%jq^-q z$GHl;0c?ul!`_n5x(q`_z{>xbYccOL_5MpsInLS`U5%c0C80Z@84qW$jO2gA`ZhpL z%Kqg&ifcSK;VyXEWN=GIYvd*dCI!$W@mBdrl6WGjEQU1p_RwNRmI#_na?8B|N329R8#KNtJioYwq|tLxas~cZq%Yfc8+QUi zGGJ_3+3u7BRR9QfG`!^^=qF{vxh+Fau={FKh7F&Nt^%BFb+EM5Z_F@P*WE;+=LT+f zgbtTHbahx?i(ifnFd>}1>JCso9VUbAf6=y(^Zq3%E;Y*|MPK9tc;Sjf03DYDzN3hL zxeR(rdYpFA_Tx;ig_KkZg%+}m1mn;OKF&PIehQvz-H)p&06XK&LqU}@^FK)GbYA0s zBc*-In3a{g(YsPsFL|N$%Zz3FyVA1Tu{f@$D7lrsM}U^~lKZe5G_ zgcW6Y)`M+P%1@}#fIEu>YtD@_)`CGyGD=Cz9T-Mbtl~{;34h6u;b_`txClwG9&D#5 z>oN>%v)M{oqT*v|Qc(}w*m40n5!z2jPs1+CR)n*+@62w0q*TmnT(5;M9Q#S-12j1e zYx=`$K)&Awa6BX<7pX3e0^vWwtM}Zb&Ka0}Yma3{WOg&)3k9Q?<@=oyEc5Sbit19V z^v#Zj=SphYaR=QZgV=o?VfSBH%A!L$M5mkuF#Z*1E|r>>1U&&Kqx1Dz%s9vQSGz>s z@g2CvQ}~Bl%7aH_hf;HAJln65%sWDrJ&?QT zJk8s2PIDXCVvr{`!t;4!DUaTjusD|emE-`C=+CE`*vAkn?N7(P&f~SD09K4`7n409|UR z#Qyp8XTtNH$uX81YA#*zk)^ZynLD9rK;ZmaYjhfSQ>JNun&96Qm0X?@8~e^d;Y&^b z>>)>+oU&Qx%8fNF50JGNt4ec6F9V*nnKZSVOcg+|6g4X{p@ zfI_daDE13|(Vm{7_nr=`**s3$ZRLsyc8m#ERMteiB#IZ@2@6$~M&_IT=PRGS&K=Z5 z$1c|r-VM@^zo^tfJx$TR5Cca;C5+6P7+y}H22)2W=4-!QeivkQcAcCTPw}cDmfIPX8iXn{eTR zQ!;)_K=-j^6WvMok5cO&@5`a6YHO^Hcz#ceY$tQ&+6SM$PXj9#yUS_)`KO7DwER`V zMxzG)(MtdGr~x#552d-k&`~%F%JK?ATZdcc(v1(EhIC-g$sYDSM1oQbYQJ`uJYu_Lw;4Mm=>Mgf{QB`Of_a}a zdD#_;(pZ9Tw`rT0@w&;BpJz?~x^Q7OR9b#%=Gq9iHHCJWYYW%^bIfAk$Xbfsk<%XM zllLAu6tG_RpS;V~lI8y_vnFoOkzZznci|}iEl&J(Hqqek|GV>IUbd7DZKT kjN3izuw_fY)sy%N_il;fkEZ^G_8g*ab=gw2iFW#b0g%*9@Bjb+ diff --git a/packages/flutter_svg/test/golden_widget/columns_and_rows.png b/packages/flutter_svg/test/golden_widget/columns_and_rows.png index acd19c0a4a3f21f38fdb52601ec44f9b4831a607..105dbecb54686478846c83fdfa7c9d51bbd730ef 100644 GIT binary patch literal 25790 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 literal 32678 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 diff --git a/packages/flutter_svg/test/golden_widget/ellipse.em_ex.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex.png index e3a3a585e8fb38fb84930d38fdee2a938602e45e..3244264aae23833ef7e318faa5d6951c95bbae3a 100644 GIT binary patch literal 6534 zcmeHLc|6qJzyA{13Z<-tkR{8Y%|1ifvb4&G(TE~SMaIsApW)cWN*TEl?`zb>`B&T`TIQU?3*E2rD4t{>@4q*r)q-=at_l#H4RIeF< zzq4@jK+#bpR|8L$kGpk;wqb>IjrinkbtRQOS)?V|MQ_bYs5X6)%oDt2$FfZ_%;`;` zMbSf^ptmv)Q=Yq!#tFb6c zU3(cZwuo+xV{UOecS@p1d)Ij0a0YL~Ac)i1z^Eyyeut!rZ*os=NiFAeH-*0`|9*u- z96=7GgX0U!(*D!weq+UTCrel3l=|Z%dhQ|22!@Xyyefwi&Dg+`)AVuNA4YE!C8ju& zRrQ(K5yWC~qwf5N;genQ1e=bNbghYX(u|9M>R!g0shU@kOqfkDq;hiY!=!`cN_@bq z+Kj&WTzPM&dKS*80SbQ?t4N+XTt0Zi8c@I3l27*$Dda*B{5n0@FEM)6W$Ck|F@17K zYGZ>*N#CBX zNbf}I-l^N{0MQP(V=J@18Ui>0Z9a1k!vL64}#(9h{( zKb~HS-E$P~*2~N!P+e_XCUeF-wxSTk#ecT>&g{vS@txF_`FI^@<}A;{fsvj%=klm@ ztHvNnEQ0tw2HKF=3cn6S$n?4{ISbsdmIfP>+Qf!*Ln8ULv1?bPn;?MS=}&0&1_3!Z zHnLj17$w&oONmI_jzJJ3(n3rA{pi*0ol~!-)kKybQBu;nZuf*h>PZ^)Xh}cQ%8?1j zgT~M!W@4Lry$;SLl(6Fver(kGogNc(ui<2I zP)+0o2o%@nv5pG|{C6~LQ$UF6#fgU7bYk%?iv_ME4tBt;c+vT<*G}JV=>dlz?)~Hx zs2*Q=a2fLua94I0-DQ&{Ehc*ta;u>`(%u;d80TA2_@Apa8@wKy9(_vKGZRNdkVdN% zNcM_*$EGG_AV!>A_-I*YYqvNwfV+oG|3{@;1_#=?0B#jq7TLU`bTkXUrf%~m(1W#} z;tak(y(hD5wKgm#1FoOtLp@G}M4NiGB4#UVU!A3%ybooKhzpqIsP#_Vc&5$@m5t;3 zz@t=T<;!^i1d%ddrXkyg1%*4oa`6U3nG&bTO7#SbUtdDXYXe<}=FkT-ehP)BS9(}X z2tlp?*uOSVv(Ho)23GMVndabeU4@665Yw-)m*z!Xfx_0aHzHjovDtHtp5M=8_;Or8c8O>&KC>siPRd|(2tvFrRCtu`? z026{&V}!v55I(7Ms!s7&pWK^RG`qP4kB_aVfZuH}y`HZ5epN#3IK zZN=98p?l$h>TmMrWWb;?bkOqUbgcG1Fh1}oFyVn(fd0xMORA3~FbYQg(5~_e60U8T z@Iw=f_qp~k#+yI@9LonDR{SX2qQy25(huqf8!othDuA20N)u6wdOHtKT0zLRE}`QR zL>9BawiC3g=VL?9xxS~sZC9y-mZt4neJlZhPg}mpXH0Zap~21!(Q(q#U7g<`A_sv` z)o*bHcOaGtHsuZNe~;;YRuq=v`z}j)kg_o-gr7F>^qfLA2|%O$3mrG|Mc7vyGExK* zM9QO$WZ{DSMsP{78;T3i-kG(8KIGELvyH|_v+;7nw(7tv4FmIWyEzIN8uLi>0b3LA`dpK^Fud$uT!v5X^MMT1ciO?vm(~m zzSGAVs3+UP5>f)wo>LU-&5?;{sv;0&M?3o98op0wQ5+_j6Q>+Ef@yq!Swh>zOah0p zDgI^gLNZ#7+)MyqR5G;WpffFomS^0y4sQ zrU&W8d7V%eX1ZhF2Hr|(!W$9|0UpOcVhM+$U^A_*nO?pH!Ei9MH@t@--M-*G#hm(7 zClLFc3{R_?Vz3E?+9e-kiX zMVw7#!}|v-KNm`Z$myEjx5DgT@5YKU>4aw7%b1;K%ns&xlyj~%^&2$R@0>TLmSkqb(B+!iY=YtysH6nT62xVT= zgUfee(^m81GzD>rfW;J}0=p9ABJ{n%ANd5P);JU&5Ezj)`n`Sg#~I&EEK1O;w@i83 z>fZ4HWgF5VUI5IIR6(eqljkI{LLUnAaFKw)XK&R66fwF$fS)QLJ0!t*q#7zvRS?4c z^(GCf9Xcv(i+v&hM#P}s#1L77-^>|2h@btffW+;i403l}yqFN8+yB1(r%3;z@_(I< zv4rr=CU+_!!X8pY-T(B=3_*RX zLfqyZ!Mi@sZpY{vUUe375#KfYF=DRRrW(ZD^3Ry_Si)e7-TR3^LFEiv#O|{XaJbZ@ z=4}f6Iqsk#N=@o73vGS_Le!>;3sF|J{Fd(^W?PvEYg5d?KHJ!dv_9xzHI6(X>GY@H zVMcjTa+jQb?!yYy{u5w!Dtp`?y785qFBhMETwr8~Lwvlk&So=|Pyr+r0Ys0E<_?%a zOS~JK%O`N0XlG?)q?iFg{)Pg=cVl3A*(wQ*1~=U?ez5DRLnVdAJJzCEz7 zu;XuwFKFOz<%6|CSmDur%aqBhkU?2h7i)!)4y_yDfw}xZoA=TLC!<8fEY+}t#Fy$_ zgL&?@hp)Q%+;hTi<)=z0ORB#dJQ~`(BZOA+zD+Fo2|DH7z%e zh#a_D1uhDy-o0zPs(r;x`!g+2=l=kXa3Z=pFRt`g>5bOr&6rNmR)9Qj{#h{J`uNwv zU)sFV)8|&i;E7h|B0Cj}&S@MZekgp*v}3DJkw_XhxIR5W8=a?YF3xfNPWOHT*=+^= z6OuD-pbfi$mlYmmrcGOY&jKqtRqh5S8-INezk0>TxtuRwfj8P#?$f*(UuvlP;E^v! z5j)l7o&~X+;L?OSLJ!_0v+O^mF|a+C(tD+ELF^E$#Kw-CdV{XCG^o5a3-3A4Oi>T$ z&MNop+VZS-mmh<^)-@=|pDmnv7@Bp7UHs+5N9s6e(lPeGTL87(ZmNF(Z1$Z@K__r? z`88qp^%{(}92BHpMd93jqvIMutVpYDkzHGqb$`I(J`$=dZ;$<>D5+In6bK+9ut@pdTR0vnV?*u z9u)7tlu+P+o`*NBx1}wr{4qpCqhYLFRc{97pKRYmvFNfK+~)9kpAO$(nEHh~r-nZz zitp$gu60G#9@)qTI8^LV3)R0YxtQb$Hb_6(*n@gM%2W6i&s17A`TE_GVEIc%f1OlJ zBI_9>6+_CWzXf`4Zy1ZX7Bf8W3G2@vc@gH@Bo$N2VZkvqCjZ^014Z$AXLC=Xb8&11 zi+*F|mKInmGcw%wq9oOY0^f`X+ag4c2_CnYp?Pop5|| z4;EW#5N9IKlz*P~R%ZQNx^I!u8*IuDw=qc{H-yQ)v35MLZApneWv+DOttlk&M@L{A zK@pWQSNw5764Du|{yJupGnP5}6{d&%`95u3J3_*D_%HhHh6uTu>SAXsrhbuYo+!VL z&cd-Zd7ts6|0RW+0yRd^Ffgi0>iox?U}>!xLcwWD7<>%Dzc$x0uRC^x3Ok&}Gv7V9 zwatx6{rdeMRCQe}gQjSVujL?5d-T05x~d7)-l4oM7<}tv&PMwMbD2w9ZbF*iX@di$8ApYEu>o= zhItqp23$)0@;sJ%lSX~;NB$Oup%m&Sw8K)IJ1dQZedp~N>R#>}(cM*@kY<@pU48+> zI8XWBg{CuuhPe#T`JFsWN3Q_~R1S1m8|%;%m0&@z$~-%oF=;&9whX=N&BZc(ag;5t zlOCC14!)XT^E&K3novsa5AS5_sCjLJxPC6})iNf}fEX$C@0=Pjo|4FE;ATe<Dj5Od(P9W^6>R}*+OMT|+)0r%WUzTh>5&)n@A=ZwD%<7I~0VZ9wr z>iM4bo*9%NU=ZYo(Z-SF$1Udp6E+C_!EAZYPH1zi3H#+b(>I3jdXETrN8cF-1xzTs zbNFIk<7hU#IUq{yGmiUHhFcfQ?k9ytK9EB_NP#!B>(AE3yN$V{S6>qpx#l%QXw!_h zh9hnuQ4vjG+&jqhvCEBnkRFuWj%2)w$*Xe6jU4bx+FZ_P5{p&$INU7YX5`?CgB*L( z;{AUZO+wOUy{@(nlHECDyHAkGw7R99DnnS*Dz=t9@)X}+=KNh1UgCR>B?zU%yTf&tOtjHVM~=OOtqjfj!Ve>u zMFm?YLbJr8{cI_*2GnD2*EkwR1YqgKD+3vZuD-HIIXoEk29HlUO7>6$S$g1*U8&aH z?|QaRTGFOb-Zqpde&}lv8R$Afsg~8G1r=wT(Le>ZaVEcqMViO9my1P7fEETyP zj&v4i6Nb|gjMtiEspWivqU4I4h_}{&8-S&@hF{1p=mbJ`jB zQbsb2U%yYyC236%<{uOGoQ8pQq9Y_YY~Tj$kr1=7z&h%JcifWa(c~u$gVUL-SW1)} z%&boDoUPXENWPaH_s#9AkEGSvHw+iS5Nyrr(3If$;3zX(RhM~F-87}vB#`Q71gS;m zB}7aIuT7qk5&=zGuAghnxlsg`Y)38WCH*I literal 8367 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 diff --git a/packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png b/packages/flutter_svg/test/golden_widget/ellipse.em_ex2.png index e3a3a585e8fb38fb84930d38fdee2a938602e45e..3244264aae23833ef7e318faa5d6951c95bbae3a 100644 GIT binary patch literal 6534 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 literal 8367 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 diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.asset.png b/packages/flutter_svg/test/golden_widget/flutter_logo.asset.png index d2fe2c73b96cc05babc542a9c04ef76f8d23345c..c73024a3e8466eac6de9e2e133e3787c6dd8fac6 100644 GIT binary patch literal 10275 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 Q_M)n6tsL0}ERWOw2fap}6#xJL diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.memory.png b/packages/flutter_svg/test/golden_widget/flutter_logo.memory.png index d2fe2c73b96cc05babc542a9c04ef76f8d23345c..c73024a3e8466eac6de9e2e133e3787c6dd8fac6 100644 GIT binary patch literal 10275 zcmcIq`$J6Y*WWXZ+9>TwhYm6`-Q7berD>ZJU8E8zB@K1lFFB>CsU{7ks2L-!(P{nC1#XI(yPt>;JjHlpn)z>X<05jsQIEY{>{v9x(Gu1${b zM=>Oh!$lnhZaOqN&a6=5#A=Q)z!9BAo*;S+ zNb&|j>XW1sLF$p@BZ4HsmU$B-o9wLzvMHAED~|~-Y$ok)cNQX85^2{5AOL8>*h_+y zgeX0L(AZ=MRIU-@q*i=2xQLN{Rk{d~XA6lCsCaX5q%)CJbqQF5my#~5hQL@+QlCJp zwJ~YH1$+!~A{o+v_wx}_%-Rq~UXLb~g%EnJNYV=QZazUW5WLqZy)K~Fo6_3>df$+a zVfz8?3{vVYL_C0u3~mBwXOd`9dm)l%PLA`m*vR%JB!WDUpFEyO7~2eTvy@_W1=a;5 zYuI8SCs5>HK+dDcB|vIXB&ZFXMUjp`8dBskAg56zOtd^IG{wd^atkNzE(VBIOu{bT z6d-IO?doVlZk%8yCMtyG;I3G6gBHuwfzHSbBon5dgwRZq$!NqF;m8vn+|C;4gxoZoDuj628we?{U!+@FC^ucKnPUGeBf6ZXqk|bhY*;$k*2gE1nN?f z)c`sz$<9D0=oFKkRe)cGOaU?$Nw#MCp}*-mw%~ghrR1A_K~Rgw3N^aTqru z(PBpsS|z2G4z_%#@k{_Sfs!|+(epTDU{F{z+bPyCT!>sG>lqRTRqWzoGF)MHKsr$5 zQXq$U9fZi*zo=fw?%H8qs0?d)R4?eANhMkZ9GgHT8iyeKNkTMb(-|MA>8%cEp`2z` zsF~t)hDkcc9ozCc_D#QnZq*nC@Cm^X+{lObZT@n`G5Xe6$@^2tDC~_8% zqbPC*oq>{-9CsQ9SwEfRzeCCFJW283N=Dj8h?C&!Evo zR0sl$abYzX0^}0L#5To%)5e=?rg5FD68yt0=VlF}8G=6^htAD&Xi+A+AbkrGc$ulqxqm zqhMG*8Hv`Q0>glW4Fj-YxYYdZmIDg47sgLu?d1${Ns^4Pj5PxfmX0URK z>7HXL7Bbh2-^oLzfBvhy%tHPp=iRmbZ`my6=329;8=pFaK~GY9-w*aFhEmU5qtiXf zunuz&rv--}8*khkvKi{V(m3e!%9Xx@$qpoIfIh6qMa?nuP|S-g=9N$fC5p@`bOu$% z--tDvnXJSm!ZNbZ46}bnF-vmpz!6GpFK~lNK^{qlrPtC$&7}Xs(#wTzW<)|LX%z-~ zpPbIun5+tYF58gCJ3~ZUvb{o0F4j!eVpGMQQYKtO7f}_TQkLf+q{{xVvLq&3o7|Cx z*&m~rDp^y9+quvt58lJ=PtaaQ%%tJA2eiqJaHL)5Yl~bz|1-lPT0D%%>(C#V>L(v= zukq7{u=Z->m9<`@&iIUY^U@I4F=O&ND(n|D$H0!VohLNit0$@+k$#WNN_gnM%;68)#1Xxm8p zHPnT%cIZj15x6txj3kV+mOTRZBm-T`69q06P`NL=JQ};TA6+bHC8q*D5r+Q~X*&-O z1?|NmZG5E7pfg??@SyY!^J~)?3)no>|H&Ib8^-@9 zZ$>OT9+bLaemiIz@WTElzY3Nu#)0xSJlp2c=%>WesUy+F(vavQb`F{&;pv3K;i*_@ z*+{f|4j|DJ#8Tn^+ObGI~3WgFUH@duq%|Pq-`V5>qUSBBx?3 zQ|AKyV%c_C{eDGd`@M|FA4Tpt>lQ|x8|Y4Sd7t9G=Vnp%zuTKt4mv??)(cQ+)=xbw zpKHkLj8h0X-xbMPoX;r=;Th-?qidp}Z-DFrJ}neOmx|!T7?2+(aE`_5 zjkuYRP`Vap8Tk8BBALeI`BbPS+6i$ty?}#?%8fq=(Nx|aZhuLu4mV4d~P1Rz#L56KstP+8N`om!0ZXp#otMkH(gGH%_VKIy%=nU654JhC=eqC+VhM}Xv_aa;8?p*#R-`F=R<>sn;eJyE z^mWQ2KZ#+nVAd`wl@L@R?p( z3b8v+IxCOWWNXssqqZ6np0(Wv6S2z#NI#01ta?d!kvJI;8$hvYHN-RdYlvv-gI^9) znpG-Yg?Ljz9N3Ikcp2~tjk&@QIECdCVq(c-vGj{rGt-97aF}-KPjFzee77$1T6nX{ z=937m`l2@3b#*%Pnl*G~Ahh)4?-ErGcnl`+v(f_W9~mpPCsO_4{lSiK;PL_{;W`Y7GDf|Fu$|H zentuB+(6&Ttv^@h>%3~O_S3q;8Hq|$>NBm3xN;b4g%O*9+NZ8P)@Uh z7mxx2E^qoGUWFP45qP~{fnItBvBJ008T`MRvnGxK&uA6KII@7v4Lc_#hHL?pd8}mJ zq`e{lWed(ss<6MJVFo&$%>l6`&Hk9`1WvO`CkyV1bopEp705TO=Qu*Ubx@&mHXT+8 zG62sNu#nZgU15D7O1R6;=5XVl5qZLg;NognVZS0w3zX=nf)ZSyJ&mx&2hZT-u;O|q zQ;#cL4|iR-k4#%jjO+!UwOCc7Nf|gmXuAsX>|_L6lNK9)UZLjMX#xmM!7-C01%H$^ zEH0Wlq&Uui>vb;y<`D8X+(UL(s7>Cy5E$LYfsQ4DyaP$(5R;A1tx)?jfRIXrATGgJ z0g2NHKCq>puE-qa0}~i|1gT#y?{+dDXIl#k> ziUGH?%p4FR=Yh|pIcA(M0iF*}E~;=pF5`h)!X+NBG!bcxf}Qm7=E|)*SBHn&5|_#D zP$hz_SyiWb_WY+q!r1nJ-@1N-m!f{ze##CV^n3M`jxBHKRY6(<|1phR=+QOS*H+EU z_)ylX!P*&`53WRYUsk7}NL%2ca``*vz}L z%}Ho2S7ydarh9nU#7YZYE-dWNKlEgBM)=pzNM{kU1TIzVSS+MzCU@%Ewf)KQlAIj( zoR5j_KQs>24Q^V35@lLF2|cs?$-}138$;h7KHng4j`7!GW$((ZMIHAzE&ow|@8i!+ zUn3ku$lq`c&4leEa4Ji)(fU`I$DHj&pzQqIV@6-IbDXA`v+gK==V$C2^oeRZu(L#k zScm*?cIZM9XylKROVu=|&a9ACImxODa=X|A`vfm8IC?l;=nwi8`jZs4<02g!LEk&I398k(`PSUalPvwd_gX|< zKRJm>SBFQFWDbv*^%B4FtPYE`49$$}9ctB{z3xG|6F6mXofnSMJ3I4<&%R*t*5O+$`VRQT?<9ubptF5Q>)IQnhfSy!sh6PCa`|1z<3o|#N7>&ou|8DZYb ztN*{Givnj)oAdIcHRD!u+cPZ88wGkiVLEW1#5ng}PGKD>`TmtVu=zIx|9sPK4!1p_ z-llY@r6Eq_kZdHEuarE>v;J@5tdbc8)i=)0p;VWpd!*#|Hd}e;ho+cwz#H7=KbYL` zcr|x|@4JIHto0b36QOFWGHYCA_G($LBD?);CPBgvJhQacuFR2a~fb=!;^vil)_wjM(aJNb%P4`fS}v2b3ZSHMi0$K*6val@~N4*|2Y=<`chy*&>V@%;+R)INv#H&Z?H<#Ux4VOB&Vj|FeWH}YVB)FjiX!mJwLAJ?t!F+6Q>Hjv%a!Ju1lkO z9@~EJxm%DM7V@_4?$M%&3H8e_l-hUigb+8tbMP!JPPZjjFmK?V-{8^gmgg~{RT2D2 ze;)1=I7{k_1553<$agOlA;gE1S>rkTbXnX#l}*M&^4fa`pwzh*c)ttr@ZI-fr=xss ze`IRy*Q-np4o@v`8j>zb(9Ae8`0eE2^8+U&AA@iBf4QE!^=Gvt|LN(4-8mvfvLs;% z%q#fh@|wxKmez95IBSlw#`eyw?yc)91%v65{^%c%6W$d6?u{&*ZZ$jdGD-`9Gsb5r z`ld?Wbo}|rNI7efu4J8`SAX)ld0rU@D-Gr)X`J@kQ(uRf&Ck{SG?cH$c&!Wb#9uGK zh788HA5la6x!jt&+huR!WC!#^ucY*M{<2}E+ROBq^w02)*C|BTJTc%7zAsnAtL@5& zh=^?WU;nGF$KJ=h|8d)VRz$ocx5KJ{!xQ?#OxI;{JgvEcMFY)GmEX$u_6)2QoE`go z?)>c~53201G-sVkUt2dAbQsHohuqA+^a5^Y-IHa_8T_otnligW*0aBS>(2Wv*Rn#4 z2f|+LJnp_VWxB4#9;=7fpKOh9^bsM%XE5FIoF56}SdtROeB0na%Ypj)CnTrBx$Q0f z{VR$hCR=7)41Cdb>&-IRlXX^I-(=TOT0Qa20^^LgZvk78&1w%0%XddU{806zy{`X) zXLd$n&Aa%HiTBs`|5xLfQ@bKaU)TIs*R2boh4s7tVA8L{xs$OXOa!}|q~zQDs8E4r zm~uxDE7`XzIZc_YJG(Tmd+UnpulD9nXupPYl;850;S$_Rqmfat>SNnfCRvzmxgC*-)Iw^ZoO>MA6eC_-$ z%kJz>m2bHi2OkIDhW-_S8eh9QQBToS>4iN z(0%US$5TCK4a-`3wp+Pa@UB#Chn4geR#LQvIWOUXWNGQp%EnO3$d=xl)e-#lZT>LP zdR01#g50~acNZQ{U)5Jz`*EF>(@po4Ws=oQ`gVUsloP$@-7~$`&A&JI{Ic!0(A2c| zOFb-c+%@xEAUFIWKc%EAtds)!>>a3M+U1)7>ap+m&@HyvqN6blE_3P45Nknyc zu@FJj%8B0sz^=FliuKg4ZKBinWz7Y-t7dI4DvWGv`ByN5wcI>5Ax3#K+t}j$@dx33 zwT^rAYdu-Bne>bBCA7!6QLpuy!Yk~lz3~jz9;^DI)NwoSB&WaoJz(}eYMa&Nj4e%l ze=Y##t$RCE=-SO~p6g2e8VmckZmn77Yy0@`*}nb%^||}Lx{&kJJ?GP^SK-q<_T+pl zUgZ&foYqsAe&BsRl+n`S zAF0n@q0-~Z@UFc>>#W{{&o)1?9N7T}DG#{2JY8}`np@zzeCI-24apnq)WHW;zqV`~ z)w&4(_~L9=qaTa?1Ry9LjO_{-TDNt&v1fN2N}CNEjw;(-wDwO{E$s&s&i);qKW4CM zGm{yz_ix%no}(P{qm0wu3AS0iiQ<~~K5-eeVe^D-P;zlQvGh~3e~ns)&&BGEwj0;w zPFT&YRyphPq)NSVgYc}fsH^qm+nR^*6YcETdJHf4@qy~u$LJbE?neI&R)Og*EiHnV z{<|Iu`-9v4Irz_A+3oEP&u;ws#y9FQyviZ@V5cmY$(bRO^%&%AEAV}?BiDNh zuQA-n{AOcP%G){THx5-_E?ELEY{F^q%@;2^BJFK%3GV&3BYcx*e*X z3g7SFT|;kUtlr3+jEGJ3Mb@L??zQQQ9AmW_^Z0OpLV}p{CbN3;=bRs?wq6<0SA4-r zW1PJFvKZ5WyD{#xMT=v6NHX-J!?w32>f^V}Fi+*@!wVQJcs^RJt;aYB1t74zSTo}DEMtoVTOW^Jwfkx-z=SIN zhQhs%+jI5i*|)u$R(eFZ39tib^k8mLB!X<1q?E9JdxwR6pZFyRkPPNxe#^mz_u-dg-_KOxXDWXQy6^IL&|awCKveM=^vmY<|D%D}BFcOUW#c zF3k$H6<(vG2cdee{nXS^GSu5Hm)|^hez37Q#>5UK-Z%J$$I*p~WgZ?8D<~9mRp@2j zUrK*JQns&FZatoI(&&m*76u-~TyY zGZ8M}$=7tp4wR39--{FteV@@M*;RMteB!!~18ew?oX`q*GkG0{a^NVk8-ATqV8j!{ zEOVyAuTShyW-LZL^+@B%@vHFrmup%aI|CjYUN!I#J(1WBtzg3sT@H}r4RGjmL$1B8IpI|5>cte~>u?EQ1=hLLJA`bj8M?{j{ zpf{M(8v?vml-_XAkVfg%1-%%F7T)a;>>w$%4_M)Wia-kwNVp}5wiUFZj-;(_7{5z; z!?yzloK5uFkYo~gqrRVnI1wPI{zanM2N2+e1JHgTet#86qDh7&s(y@Qg<%@$tVtRS zQ(&DyzYYmj1TW4=9GeIy@g9xOCB>Zpl?j=C)hmN88uYmyc!#f=JGQE6i^GTmk>h9YF`T1)6g zt1N}4A|%yKp~zOD$u_cm&-*>OkIz5w^@}sF_c_nAyw2;q&g=Dl3!EIS7tB?diy+7X zTN}1Bg2>Pi1n)|m4I@{MpALY3xTDV2ETo`Lu@`<2j3I#oeX`MPGLh6!f+HtBTXe%C%YL$A3=!&5&=h@YdhO&eP1Pi1R;}(A{`* zvzXesnxzd%v@>M6i*n>Ov(DOQv3BRFF3g?F^3`N>ZyvPYn!D(svAN`1-DDs2XkD%8 z0o~xb+VRxU(X#q(6;lI-LGXlwS7}FK>MlDl?f>=fYUdqU1o8WMi!|L^EvvhGjA=LK z=O>({K9P3&_W3r+hf8DI-^+wQm_tU+sWFIloQ8vV0+%izotC2xr6Ra=llF-8Dp@Ns z4OwKxA;(J6m%{VCeDwJuD=y+h5U+D;k7y^7k)Tc3a~pWRN1jShV`yFm`MXuJ>jb28 z>P)0ZP09+Yf~-+it||;JLkDFx5Qs>rGOE9VfWtHOF#Of)xk$q)OuynfAbq4HI=TZR zlbJx;V&sPi&~+5km4K34q~s+a4KUJ`3#7c1Y)J3JAr+;366^Z)CDpPzj$DL%MMBHG z9wg>8pG=c*t9P89#dK|th~6L;e|zgb?)H9txUL)x;i)o+ww#JYaN#k93cu19gSSpq zvdRKdZX|-E%@?n;X_xU;VYM@d~74R`%4wKRcsW+frj@qCJ?rLKI z-pL5gqZcDx=i=}c&H|L-rXlcVVahzN0fIe52~21NTm>nvHjG9}agBiYi4=Dw;HpS* zQ^51%;7pY)kH$oD<0LdyG42nTF<%wTFinu!iAj;85ZuRFOp0jBMFP~NQs9n>5#||7 zo`xi!!vH>k1&h@&01d!eOvlIrKz2z-b5K$`+6`pCEfx?*2xGDhM%DqTXfGWFTtz8E z9ZLR4%{jE^-P7(iJqFQ=!_>QR#{xn2o~qwsT=-|^Ak|JQ?C^Wf@Q`+ypvw6~WPGGU zG;S7S~uf;3yi#-9I8By(9L_#LGlJUV$b)^A#;`Fv5EBt`5a7@CM=#F zWsDV8MEVJA(1XoIhWJ?c9AHIRU~`EWfPEwkzk&j!2%Gl`eIUJMbLuL3e1|1^8ptYFC<3520VdA!>r8> zM{vXqsAGsPoryqHQ7i?JqG3|$`+-#&18-PU-ieqyhTvH-Hm!&PL}n*8@5lm(>?)}R zYG8pqmKcaVz+RT}Ubf*PIsyzqClSH9;xQAv!36IFY_u3~4W+z00arnay9#g@NO2MH z;RR+GjR=#Yf&magstKDsV1Y*T9EC@^|JmKSfsnlv5KEMtO0vQ&d$t(<@ z2f^WQO5@Q3us5at_KL=fl@3B-JEzXz+j5XeH70kjfV5YR$}FElP6yTmU=0J-D2z20 zN~aYCT?pJGL~{C4?77oo9Db2h|8o^4w^bf{{yWIOmFjoH6M9yGbL}#kNeC_omL`}= zrZETjs3ruGDE$D&$<@cx)NJRu=TI;sZbc_|6I$34hyG$7{zfi5NUfRqL|y#`2C z>F8G=e}TyY0v$7K=nR4zk@^qFT!Cy>#80QqUdMGG+$dmq@3hSPd zm`{CwruXj8U>zi|(he#}f1lvM^}HnW66zuanpB#Xm8;*;nQn!r}y0G{;xTQ`rz^$no&S0!#{WoM~SrOA(L|$no@9Qh*v7)8m!k>g>Q|JkmJ5m zA0WrWuSk7>98aJ9i**j!1j;%af{;rfCWlLn z!#_{BYzw;8cetV~dEndjlC~)=@w!ckxNv#Q+Tl~*uDvZc@77`PJr$|$Cwfo3SDI@G z;nGL_7XIXupj%wT;#N@p_cxnc0qr8Hpgkg>O7;wewi+sOj3iemp(%>jg%gMur0B2% zt1vWUk#O+AmeT|^ElQH^f#-~z;Ie>IM&tw zQGRn1*9mm|r`&-;L)-iR_|Fo_=b+fw{L;o%nL|D&4I8GN>p6#vw)_9_Ysk@tpo6B1 zH($E`Txel2Vcj0#R3-c25^@y|01$&KTepRN>ovEGJ{sf?%`|jwU34aTA^;Ph%YxsOFq^oMLN&s2IeiTP2*_X5 zf0@9{ClIUUl$)$(0HK*br_M6bp0PkdnW>pd{8U_Jy%BYi2aOYl&^TEn|;NwS(CF|HPo`dGg6mW~^|9^`Jpko(W3>oFztStmkSoUL7P5YuE8& zt!KR2K8KueiKumU#>#wo+D(Mg7&e0shX#*z^vv=ZeByd;g%&@0Y9?&7MX>%7O;VyS@Iu%J(szFZ8JJ!A^8fr?4$e1zvh9q7Kb;IQx?z6Q^Opn z5bCUUxtV!_hS`wGt5TWq2u>Q_e4^k#1L`QW1{$UDKLgC51XZ$af@ciq(Lrk#>++@< ziygsbRl3)y{}{jmdsWsIjTsGkM6&Delt#rFmx4SYSXZz`oXtqktnU! z+)tSKRVnOC-P_ETFNw)N_Q&Owdk3$jG1Ak%;leM!lRvV!JwsP$d93^3b+^f!*hXJF ztlLhvGrpcYaA&olof;#3v=(-Y{j4r!#+M_`9Ea=9!(X*X{WaT;{b9R4V{5z2IU19; zlyXE)ygB|ius*@`0Q*kSl!JA{%q6Fe6IBqV2gpiG0hK-5PG3a9!ZR9eo zV}C=(Hllog`~jwDFw@sR=aa#dY}Az1#$p`6rMwy-QmDsvY)93?F%waNy*W3HLT7xr z^-Z!AR+2pjk%vusYdM|GY0ApS#^?<0GT^&GMfnu?2+dKj<5TJ;s#sph#t%FNgfOLGt&>0eX9%$5{KKnFruA9cfI#C zbpQ+JiS?g3*x;&US8L$#7K;o}Jr5RBJ?WXED%qRR##sD@>3*Pqj-7=u8jLMg!T6NW zF>5%}&4tFOpal(0uRXXItwg3)K;y2-G{;=Ni-uu^I)iIKraAFDH}EC7_U>p{1HqX( zXw}wTmPf-MA_S)!mD^?DWElR~a5*}bRRvD>B4S(Uj^*8dMIpO|AB!7%W1?h|^b=FQe zvdo4iJ*(Io4L)CZNf5o5PfCa0>|bMd>ChNIT1}2xAx9*8JbxyYgfLuYa?n#IcYRb8 z27lO$p1H1F#+8o4EBctBR#b`J@uO$MBs_yg_J-d0_q08n?>}VPz6%OVrz`!0S)?j! zi|bn_gY3qf9ewiq{s~N#AUomu1fZMpgUam2P7_UK#JFOwEVxS=N|AW8rXD9>pWdCd z_GxJRDn|~o>PN$D?`VnlMWX3%z*j4?JYBina~b<7t4fy4J!{02sS^Dzh`!G!(TF5p z?iGP>4L@35K%$XJK3oO(C5TpmUrR~e+$($`k^OX$7)SX0X}*(;m?9wBYQeJ`N2s+3 z>|K=Klwf*@Hy)n-of%nW?R5s`5;?8i9X{X5K>Tvn87uf{mOf4L`b+uH%f(FWD z2wBFE%?aFGufpaaD;mqsu4YD5S;r3>qL1|_Pa!gf4xFKN^{{4;6-|?8^(y4}LPoDG z52hgF!T85nu5#j+)+>Z$F)q+`ROta?ugds&BLgOZ8}+qLW(o9-)^p4jgJnJ864Ea2 zV!rTVAf{XXFtr$2MWL$AMeXj1IZ4{VT`Uk@oD~UJLk`KZI?NjAVo=2vO;eS>!F9u< za2g7n3g=33mF(Huil`tQJr`}{1U$TqacW@a;C??e4Y+tXL%~saY?T&x;{-?eMb?~~ z_x?g%odrkF%~i5FZ=Fz2R>ML0FUiMmzK|)nMQ|NqMW#08WW%aqUL_D4g4-j0rs$&> za8Cd&PP%E%1(Z?ut_8x)=94aG1TnHWT3Ln(9ZAL~whXU=1M|DJBzyEktFtLoCyQg8 zRU9nz|KLz!-loRjHp0!~5VUWz{5NWqCyz{}nEM`kw7^>cz^Ob*=BFl*G8zFVq9mmmHVv-E~PqJLfy@ zKP3(e{Zh{uTi_C!*LM{`Pm6nUx9d%`tjwBzIbuTFW?oo6R6`xVR4yr+9yfa1Iu=nL zS2kg;TWq1qwE>^!r3L+7z9)Y-M@YQ7&HR03eCU{G*pcohFUqet+nqYm?Z4aN#PB6L z;Um|A#w>g|nE1uH^}*nuj=d}Vgl8Uq`;+AUGcIkcsKmG+Y;)XEh3RuIBI1gZwugP~ zI%6-)I#3>x(XtL-TtA=KpuL~vU0pZwJ*6`z5@*rN)c zAGt7+-=xYbGX-d_(0M!iK=D-8wB&ipyL~PZg2X7nK9`Qjo(_o(m>IjJpwVS_UjMj1 zouCQV#ph_O-0HeF-#guZ_Gq8*-!uLAS^VJVTX}13O#5D({9L?5QC1wY#mFr6uAOP; z*3!YNU&;8J{B(5t0CfE2M$Vp=uLf|Q&SMtJg9F{-0eA(v%ht1j_-s|T(+6=}zh1vK@ydWk+?5WO^@zOL1dxE}O2B94gr3HM*nS|@u0 zc%ujeCZ9x>8xH^UuD4dIKXPH@ltaHvV(M6e9%EtIMNo2Vx==t)FC@V1Q69$}zw?(~ z$b?2gVcSE-3hMYM=d-|mw#Eo2Gs1$}yGVTa`-MmkJ}e6zd@@I@ z-x?4)VL=UEEEGlz)Cw(WEUpsVL)-FJON|emc=8Em?&Yn#mm3COiYC=u&-Ra*wA6}j zloId%$fFZ_-+YR5Lf?x|_T}F_jr&`Z1;XSl zN@<7UNDQSt$BmZG+F$@4Iod*$Vf%@qvF7SW3D+A?$M}gt@ePp)!`U~etAjXDRvg?} z&L^XnG!^=6n|eS0h3*q$(*cA1FTQRO>n{|p7waEu>VGsz&9F2Y?1Fv5E_k}B5H8o^ z;ci!+AD!CVs#qo&94Nnk`0JBh>h7&V;byPThrJZdd{0cc*q!a@7+PM}t;XW&!tE=Z zD1!C}ACH1!s6DH~Ung7+gj+6PaRy3qvB6`88HG4S!;0`vi0nY3m zIC^Hr9pkflYbOW%^V`Zoy}LZk3^!Q!r{4SK`{u_1#(qc-d+_`;+eY*!cz*IrTTAo3 zV;wKAy|pe{u_c(%`1#3T?|1LudQm9^NgG(<409+K!yNYa_xtbwQpq5g@x#r4dKm43 zklhe&2z%9bERyfSjvfqAXN*KOzbH){OMo!+0LC(Ybi(z%$WQYu$JdKQ)(S(uU7nYT zI66e=fGTV6wL8Xt=}pv@msyl_s|Y*x23DRj`=cwvYz^Z|xz|lyI)QHo7u9f-xw(XD z85le{GOU;I^RY)jK+#x}1y%k8=kq&>N&95dG{qMb^5Lp`Bip7#s&KOKP+{AZC}HyG znk4GCv88@%H_0pC8ci7&AO1XUY(DXXPo^oLH{z7WDBoaDi8XaR{_b1<^55mD^2_V2 zl`l4a{5T~{wl3B0*@rg2G$<=h29#TFuirfRE@X_Awg*#VmkNcO9w_LQTxtHQ9~HToe?cbWe9rDw zc02?we7Jw{qxbh!i!6hW9bLnieW|8kf7Azyz@|fXyDfZ2i(#hWE(txjUGP2VDLHF7 zEK_*sL(smJjFEV^7p;T(4Byd)Nu_<&qJL@oDEQ(H@Mge)*Ob@Xymac3^>pu5$Kb zcO04e>g8bxEN@o^T=%QeKmU0>fA|xX^Lc#F`+LVGUu%2W*Y+ zyzSA3Ie-II1D$fDxKtuZE%{p5db0BK*N%C!2b(U44qNy2_kP)2vdzxtu0m#tZ}f5D z4#pcAD1o^scHlX@Z@FhM@of`lv}M?(a8tFYsZ=QfGWch1OM#zBp|g^e$gcU?_RA|) z6oDdW%E(;eyP}fA2PE%EQatuM{E=0ctsDKUriD)WS_$=f2px4RF$yWu9 zu;tOKP}SGAzuJCG*Kg}+R-f;xzT@3*Zvxb-L=7ra%kF%1OXR2TC&Ip&zj^E5c5lt_ znZ#v6&w+9NZ7(0YIOpb#c|O`L@oTQ1_t8$VFY(Fh`y&M^gs(CfvQiB*WO_Jb+9Ran zHI(VYAADTK$Jb`-F8d&Vpi3nurTFriS7(Y-b+cXsx;NYAIOy4fkk$E)rIt>YmF;N=_s z>p|YP0@B&?!72Y;?&TqqP8^3ij-pY=;eiF+HAP8p8}~o3Yg#6lkH+QIdBVl?WN*lG5)Oyk-}>mJI6epsOT9EzI5YkJ!RzAS>qGZxxgnR z0Lb%M8$>!3yiV;a`E->BO3Ec)D?c3wl_VLz@pmsbn~b}(Cb`~xaC7;}!tDGwR4yj) zL}yH~(Y@H?<3))N9bql=;T>#r!G@=yoQGyBsHUBX`&>p-$4qXNB??y-X7-^{eS?iH zuZ^?vAIbO_7rq|qFI8u8@56=|)w`3YxP)rmI{5N=t%&AV=;pZmpufY3dW$P-Tne&V zIA!5sjspU+hpv_4Yg~i%04MuF?A`vgNn3)f;S^u@j{!9z&T#2`=Q?ez1+#rtyV`1z zoRw~5CcBKRNhi$?rVc(5mDYnyEw1#hO=3(mUuIp4O$nXALQ%VKsG|YYIjV znNrV)y!aQ^d$tc6>dPD<(;~KJiQC$=nX|9$EJ;4TooZ*E=Q7eN+(%Kah=Ec>VxNmn zfpf%&Wtb%Cj*p7*Jo;6l5P@JXsfGU9`00rU?UuD2+W{zk6fJK~nZg z^ZVDWAcLVK53zZ~`!1Ys8=Vw&{%LL-*B9?hO&l{JMz6cBKEkb?ZF4)wbX#{}R?F?P z&PFD0>!xvvRy<@2XcrbQQy#1mc{yA#PR`lPQT#USYPvUK>}0*jfqSDR?RdRq^7TP~ zo7WZ3wuQqCr9l=XuAzJNOO~dwj|um=Y^k}v-}q{wo6YMp*3QSKVz%b*aeE_t`VO|W zEO^NrXvC`o%eU>{jh%HBvB`g82%WtN$KG4EXO5O+2x|akKb?QJ-l`K zN40SlXSzG*OPR51d3KOJkNIfrJ6uqKfM^=R$t*r$`tkYH#_m%Ax}D=~v9sgLXr1$f znXxX;+ukw-4m|X1%EW!S5MA`d8qNlfd==b+jw-l?+ADmR?kXL(7-?m5Vy$>gc!|JN z{=$zgsus}}=rS&DFL-E_?-pdZO}j|cbxz0<-47--+6!H zP3fx}&W^9Ix?8qq1ked{p=iuKdWE>dkTJWPs$eC`&`K+bbym3W_j*nMtkE;@;(FFj zRaRG|@X`GmpUxk<8o$Kd&F1t!@9Fwc>UpAC_Nbh)6Wm)l<({H{-Xo5AtD6~DBg~G| z7G^&RaT$$j+9)G_w1ZFXF$JERm*}7GNuK77X2sd3rES->yfS-9;l`E@Wk#-m2ru|( z$QkpMtcBGgk5vo$!#u&H{X6#UH`tMu;X#1 zR^g5Q-HHja?Gcc~4eRmnp-AH%US>(*)RzIy_wn+RgTtSawku6&k1ru~iSs+#BRb`k z8w`LiB%V55aocyW-+%k-e)r|&@D&4-#}vXhE!hrm(?TOt@D@rs_&P9RYqnCvDG6Nw$uRbgqn>Z9#9{5wcJz~3njDEXN!BRRo@QRex*SBf=wV?4< zctQpk9>Dw|OS#yp%OJ9OOj&Tuu`_&>G3jJJbo?=@k57_$;W-fk%!Zh9>~uZL%_3l|@s6uaW%NM2djS zw}Owxv?(k$ozMI=LRl|jtOsBwiT0QeMR3&PL0D{f6}=FI$Cw2l z0|6j~hK;tPBnDft7bWS~=mbitU?leT7+E~rTo}^Q_wd2bg4o8K_e%3FY||<&ZEl_V zjLj=dNK7IQmtLe4+HDa3roJsiH*4rOcxU;fmRA9{nMjJ%1~E!%V7Tanl}c@ZyHjo} z77&js;JOPI1rr*4h_?cplM$HwAY0TQNL{873ur8SAJ=dY^IQ!gGn9&Y&bkJmRv40I z3?MDVp2KT-_)ZWNzp4tF+Of#R!Y43Jswg~9Zho^8f)s!HnUl(yM7OleSVqf;tH%wy z-oDo(BN_u?6Wxr$zJHioYC*=(K$$T7xPPSCWr3ymc3A5O6ZwDsOJ6-r-Me$|KDU)$ Q_M)n6tsL0}ERWOw2fap}6#xJL diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.natural.png b/packages/flutter_svg/test/golden_widget/flutter_logo.natural.png index 9e355df1dd1d5681beb2b78e411ed7629ef8b629..510026df7d61288b94d857d0cf82fa4b06a09fb1 100644 GIT binary patch literal 25928 zcmeI5iC@fH{Qp0=$lkPx78zQ!5LZQM!L&%SPBW-xvR7!Lg^U^sEm!3mt}S&7F_UIo zy0SD)ku2A)ETL|;lrR#LRNwPC@6UYd-v8kD{pE2VSNHun=Y5{%b>8QFme0qPG|$&_ z$iR^U34$0h%Zs&uAO`RWqQ8blKV&JY{P7F=t=Gl{o->GoJBIJkfBdp>#;ipe=$BAq zMIu3%5VKg*7i~K7p|n>o^i-7IA^oU9dh7Ysqd<=WJqq+F(4#<)0zC@!DA1!oj{-dk z^eE7yK#v0drxg%Ay^wMEc0upt9O;UFUWt>BBxblBoBqpC5pi9yF)iGLRhM+j$NP9l z$J@}rv!9AX-37g$IR2kjq^EN|3iK$@qd<=W|34{kwoTB2`^zn#Tk^Bx)whaKofl*J zU#{OZs-wLo?q^FJ=Pr6Ky8rV{19^E)$hK$2wzgNKjdJaHcjd44_6D2JnZv5@mLy5h z!`jitGO|!DKkJpmwNr<8zd5L_^?Y1M(__hMWLKR0g-bpcm?(9F>#WdEn+_3!NXt;B zoH<9>7yWcelTS9J=yjEI3_ImJ^tL98JUOUJo~+bGKYj2PktGQyE#4k8d2fXGVgPQJ zZ(e8h;3@|_5@__&Ba3`+6S^N#k(d2L$0$%qLS&vK_0r~{CKP`F%;#U!FjI~IjPY1C zOdbW(M-5Xu8DNSs)G$XVm}pHk%tL^w^`Kz}0L*h5W;_KGov4O6PQmn3!xT|4fuq$h z1EA?m+tf|3&;Yd!)D5LGp^p>PZrxI$M=lIC+*m+aTW3{=g-SQYRrs4}A7)@c;{#Hr zn}cDo+F<(&_?S)09|R!WR5jUPcRWIh1!~>+QviNH-J6+Oc${Ul`uh7ZtLQyFK=(is zpE>F=+)1Gch7yFuMyg#l>d@2z&b zX&1P?r4B#B0p^cj0Ns!WG~{cphI>98Lgf_Qv=hvqDZACt^qGKB&ZA+B#{!IihS3HX z!!DTr0hlW^j1vW;p@!j`156YR^T7*X3TT*2fO$g02q>6KG|W(tx0aqUifsTh&0Vd` zlmh^>OC3;zIlz3@RKwJc1(=U!YGsa4Fab172EY{2nNZLRlyOkcZ(=+J6F@7o17I%C zQo|HcFdQ1D7c?D6=RFpTzKRZAP0Fp6+O6Af(4)IFoC%;*|CJ<7#0i#|4{on=&f!EZ zvc)A7DDgmM7fk^}8ExnV?ds8?J9q{j5E;E-@J+B&Q8_)V@eCa9)+}}Z^wTjKpP^<| zWP=2Q=ppL|N$$WAb%@zgC|7Be0f1sgqxb-d?P&Fg@tJ^fgGR{!6dxMp0EMDOqZ|Vi zZ5qW4Q1rV{rh+O88l^9w^rKO%DU>c%MgvMIjgkT=gJ~2lg`!ELI2?1PZ?q+u=r z%!e)*O&DS$8phBAOZ|B)4Kou|I%=X8UqFR*JPqRuFq^tyf&nI)9>OUAQ#+J~$pe_@ zUg{}Us|7FyG>kt5Gn9sz4KOdeV5q>hqG7b4=?QcMUWWh^&Qv#K0!!v+dTACJg1q!j zkC+80Xk|WvH+m+su`JeeX&-aIK(E~h3% z0Pq9o-du((>hG%#1Caxs%%a(}CZC6562S=d2omc}@XljAy<=1Ch91AC;fmsMs7%>M zHysTLE|1o&7FOI^9U5jDEcS+7Fy;U=vkM0H?gD)pCJJDNcER`p%tspL$sP>zqzlFg zCiA5(7y?3WI1OV6@=l{?jHnMpOCBw_02cGlbS5Nx0mis%2xbAy3mRq$z!as>%9sO; z1Dy$Ldt;bdGaAMpU@p^fDH;SY4zx0YiFlYkThhw(hNe^KrW0ZGYv^8^fLkHGM-%CT z6MAz+Ob1=6?UlOW__RvEl8JIBGNCnu2*M?}^x92?gW&+(!9KWMMOWzRC*T3mqZbT? z8)lVt4QoGqIuz}o#kPgLmGuldQm11H_`PVA2E)pfK?}(jV3Y%0DB6H>jMn4;pqO=` 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 literal 26474 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 diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.network.png b/packages/flutter_svg/test/golden_widget/flutter_logo.network.png index d2fe2c73b96cc05babc542a9c04ef76f8d23345c..c73024a3e8466eac6de9e2e133e3787c6dd8fac6 100644 GIT binary patch literal 10275 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 Q_M)n6tsL0}ERWOw2fap}6#xJL diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.color_filter.png index 532d4f1e46e5e981f636a3550a41ee353c5dcc67..3138a2bce82d2bc1ee3f5d9ee18a916f05b20d9a 100644 GIT binary patch literal 7599 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 Ef3wSbq5uE@ literal 8160 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 bLHA#~6qjawu~(cTXIyEb64l34+AaSJI=J9p diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.ltr.png index 962179bceb31c8941d19bfe5f8afa2e8f298c991..13f1aa453c9e6c1030dcc2927330ce88ca28175b 100644 GIT binary patch literal 3389 zcmeH|`(Mj@9LGOfIZY3=ZzQK=tJO*&UF6!DS*?pQ^e9BA)I;t`7nLSqlUX&CqN0Nw zq;W(F9W+}~nx%^rl}jmEt-EyI-+ny*0^eV@@ALEeyf3fMh`5gQ2at@2guU=X*uRFuLiv?5+u=oXKg-RV1Wzm}h>y^u&u;AH-cjef-c==? z*D`vp>b6^2eCOS+3IoZdOU?ngHK7^_IZ=GctF?Qwbj_?16n-l5p4|trW!^doU;G=$ zg#nneWvaVac_f~9!{I@2Pp;-g$I}jC&y4U$icZ%JdU5>)N>y*gvZ~&L?~Ydu41bCa zrW2u#-_LIcesKqQVIKX<4%r&@VW{zgu+rl>!?uI=_xtaPj<1-iG_M=Ik2lC=fJu2e z1UNF&TzK&RC`Ltyxitd@c%j46-i3$A+lSAwq^Ut4D^kvdXx9_BSP(UN6-NFWHo3l5 z3&uy@ysRl>6`~m#z6D68{BXJEDBr@C@o22J`_TQhvRP=wR4NK`iA4p51R|6EObb0E zQ_&>PSoF$@KrH0~7{$R#0M-DQ0FD4qgJQk~OxXJdNAb_ z4s@xgQ9OvKJD|W_0v*&tWuiJ3DD**L1d3=-?9`>8HcuWRV=WrI01_Di$D3YY&OjEa zh>&NaA~35pNlZ_O;If>Dl*xl=i#LFmd;o3$_yCl+0)X@|Od+TUrT3v6J%};GoT!=e z1cJ7LpWdfII&&hKrwv(8LbF^O$hwctM3!u5t2LEhpH4fJL6pDnGDwHH==6-p16R6cmy6}kJz1}fpC6GXP%#uq)Uy2X&BNLi`1 zn<710wyOx-DgOTwEmCejx(w`v17P!q5|n z!>dhQ6cgUhX8*9M#lVb85DMB1jA4*Sf0;gLy9+I#sKsCrari{?#THt$gCc5CYMp*G2VBiF zg(;Y$v#dZ>eI^n@^U7hx^lk?x2I)~YMLXjXd)&mgF0OAta$sBnn@ca8lh_85_2ZHW zAXyzEs?2gVnZ92r%HK)@vz0FUm0Bn{+l~{WKQg+qSykQVpLkwm-*l4Sp5+7!7g{!z zj2tG>^FO=}RDz8o%vq>| z!$SqLlSoDC;_U41joah%t9LqQ*e}eEZJaAq=Rg<=e#DLmlKb~$4TXH}IeJ_iY~>Ka z7vj2 zPcMANF>t%VvDlPIPuKWGl2ggvF2&ICRKYb@v7qk9lV}D1u5@K% zXs0k!zOlsc^-_i&W{mpq8=%??yIm4h64#};p6x}y(iGE^VjmdSu|l=`>(qUB`mWt~ zlvuwJ`&9XvXyy!Sl2CEOJl0u#(Y@wJgQ8KlK-+*%ffAd6p>=NuF0adsp8qB@=8q;_ zV^jmD_=|juBkO5V_4m~_H#QFs`UZAf+~d+ynnnv|7^K+S)#Exd(A5{w?)2(=J^uc} zul>k~U-plKrZGC~hV=4n9*M|Xj0ic_w=N70uXQAI&usF?4!@UEK z&d}xDvGgV@jL4k}*W2N6FG{9}FlO^`GgQ3~1PWqoO< xCK6HMckSs2acBJRI|1K|-_LIcet8GfUmnXMJEu?!GMD3CxH)^V^I2OG{sTz&_wxV% literal 3722 zcmeHI2~$(a7VaBRBQ6j?6ylJOuu4jF5Mfx7h=H)o1dM_(Do~0KWyVpA$`&vxG68{r zvdE5r%R>zswh;#5y%8cJAS$42BMP!hMZknbc_-HVi)YuZx^=$(&gs+N={_Cj$ziWi z(^EqTt#Nf>aS>7>BZTw8F9#&+%=r`W!+2b_BNDf690fy_=jgfz4}*^n6e6^Cn=5O_ zp0J$BzI_S%Pk&c0`#baXFMBs%U(QM(Yr2`nJakz(AMo#(VixJgS1ZodU&>$|d=%g) z+}iPIpX2$I^>HbthuxpknXDJ&YXW0qx{Dr#wNl6J*Q#Kn=gsMTxtVq96RGKyJrD9; zTMkc$_vZ4V>!P~((+o>343haazA5m3t^o7?;o;to`}EL z(AUT?<|eC{jau)%5mb>`wP^ki$Za(g~qJXC&6t%Z|`S)Ap*5-ms#M6~{l&kB> zx2MvPS_>G*YK}#g=;vfEh!v>d08Uj<*<0!0wNw)}A@$WE^7PE;C|1b6hmQDK(kYjL zLj_K{P#s0=5TFy@Z&d_-1Tvzz^U*VRn6cC(p_wd%y(xdR0(~YkkbtI>KIO-09A0R1%u!bu1Q8l#&q;J8)2qqGOV7A*AQqz%+>J#=qiDg z05mz!xe-6{(FqEM^VGZ`6v?hGWhu}b7KBkrjl)NthOltG5`ge(ZU87V5h#J7Lt&WO4O5xy!QI~( z*_+bL7b-gAxWyN(igx#$`7vl!_*0bv9*~*wnj~Vr&HP1Y>O-x$oN^0RQAj?Nak(e} z(`Kc-r8Zm9$K;dM)4hzLEvp3j8f3K0^Qt0j@s%-b>!ecPabvoqQGF-uX*I}#N;#$b zu6`Fe-A`-CU$DKkpt$wvXqi@=x&WsIzU^{66l9PoK-w-#6vJ8?h<*VyzWT2iR$!a_ zebVSqXwt^&n|+Euj*ed=HmpFCpxCmRv6*Vf{fa!4WH8kr^?x|u{@{$bT1hG5Ms0x| zA5+pQ4%yxgU2kweD)kBC^-$mpB|z+Zt<>T&#jEnk$1T362Tjc8ZXH0jO2x#V@uT*1 z?vp%@S(I@z<TV8rZA^i_atT!p6XSN^u@{2$Nx3a#Zp4 z$u^NOGc~9*!@eXn4M&7|Aa4z*7OQomL2Z)g#zZ%*p+w(F z2+Cpr2XYdVqZ_2p`>1!PcEkwP1(!kBokygny#GGEP;xxTcd;;E*8cLaa!ONIcLs-M z+Iaq15ygGKbSH{#$SHjWJz5Io? zrD!r8L4HP7A^n3Ngo>R@CRV|bXRR&o4_k|(md>wX*i|h}BcCQ!JkxcuH>X8Z>Nh(l z468i5Td$(FE_ZGr<#XBirXsB_FK-X~g#nMHk2zmjR06KUc`)ki!n-DRXL~rz&$oYG z==5?nDIydRQpBbCSEA4M-?h9QNmmy*Dp&8yP%?=gUlvKc6`%am5;-g?F;V;VbBi)! zp?9QT3`&J-UQk82tXJV+r{8aBZCA6Mn3h1Oqe#*V*Q-H^uOJ#4-6_@(*^lHFC)vTOG68jSI(Z+6w(L z6Xu?ThtTX8I)^BF&5J!sA7zg#8lo6>tRD_#EVe}P%8u{P@{*===q0;I4h$VBe8zOb zbcfZhw#I#VCXOgJA7KH$H!mgc@y|IsdaaaXUwyXiy6-krgY z8thfPVNX?-=o;+Kt~~Ivh=B>#K_ffiZQ|@wV$oVR^CEI>E9t-=ffH|u2Pfh!oX-rz z3Y$c%z>d79?u2o3>LrVK4Z#51up_RPj$b~#eCJ_(L;N7{tt7ihGGF47c0W3Czd0l% zf_fdcvksarJ5Ktu?ECQlh@H20K9TcJxyPW@pfNMj@72c-b{(PCH&Y!lU$6*pp`hbT z_RJ;D{k4jepQKHJhXdX>+v)!{X5q1~4@qmB2I^KmQAq%-fm(k6;AbU}h&er;%MRMy za#SBVfPN#n&~!feaJ0HQ$E~2~`Zm5P@J#_w;9234ieOfI?;?(PP$`J3 L6Ne>s3^@NkGXavB diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.png index d2fe2c73b96cc05babc542a9c04ef76f8d23345c..c73024a3e8466eac6de9e2e133e3787c6dd8fac6 100644 GIT binary patch literal 10275 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 Q_M)n6tsL0}ERWOw2fap}6#xJL diff --git a/packages/flutter_svg/test/golden_widget/flutter_logo.string.rtl.png b/packages/flutter_svg/test/golden_widget/flutter_logo.string.rtl.png index 9355a72d7429bdf5cb3fcd42ea55bbb14ac3b3a7..626ffb7fd58574041908d1c5555b7de5dc284f68 100644 GIT binary patch literal 3389 zcmeH|`(M*#6vxkZkW4UOpn{|^Hg0KZSYZjwIR|5SftT(j-o=~>ge@;|3-B9J4hZFD z$mC{IT!AQ3k|Ihv7^FB%kYPZ|O>kTqg3d9d^X+lx0C-dA&))!G!UUjgrq4hki%k3+e~7~y1Ux9aH-7+MOb_#fB04^Cbg>j*)>9#W zl_)xIs6(BaXSP748+qTWs-ok-U5D}?e(?Q7-V$z-SQITSZ`vp+uyNUDx<=CF)Y(49 zidMXBdcXQ-r-)isipV)2tNH7rWU1%1eWP;IGd|g#S?gp+q8zP;N?ohk@*UOB?|Q4B z$95c3zclp4>~p2zI;Nj#2ma>{kcZY-F1=7J=g>&6>jz)-4+{L^`Ev$ij6GV0u0}Be zkB>UYIcSo?ioh!~+mFQm-!PZ}+}$!9Aj1uH7Rzrqh8c2sb(!McyBWFrE!t=y?le>K z?t-0LclbXTOa6D{VPi`z?+Vzn;aS9CDC{Fu3Vk`2@Olw%i=71&* z2&Qe93AvMQ4d1$Qp#LNgA?^qg5X_)J4gw~ERR|0S?6ZL=T8dydf>;WCkH8JVy9gp( zI8dL0Qv?*iEW^S$NdJ(a)m%}UL5wvMBAif>3dCbeRCuGpGuaA8UAZ8o>j_u>2#VO@0}U<>*ns<-!b&UYk7i8I@A>c;hwupsd{3! zsZis;$EiVER^_7mP7m&87ek0_|1DkYKQ`BEOBZKG_YG#W<(U6zLTzJ_vr^@$G~*87 z+DF~{(p=FJYPG^VpA}!SSg+HyQav#DqmX|n%^C*@9Bk;Zal-NvagNRJAMkK-Z`d%w z<)ko4Y6a%#Y(Rv9&OjqbT-4RCSmGxA=4%{B#>(T;D8r+-vh|>tj}{T}zV$)63~#$I z@A<;P)az_?Rg{SiNeftFjlTbPFAUAyJJXspZ}Z??PB~F_okdAxC^>b2?W{$~3QE#T zNv^SZqbMn*B+ZE^QB(-_2RbuSuht1#FEP;UaQVm2OrTz!E3ZhMOeh}F_s1^f-4i%S z{FF!3g}8CQbj_s0=^4jQlqD2mDdZ!(34Hzx-TjtNsn@Moq}a}JN0l#nqF9U-9L`k< zTC4xfNG+Y|_^4AOrGW+5)>cq+k-Tjk( zhR{dhdA3e4j%Qhu?VGgSFr>a0Rrd4B*3c`gb+XfeoZ;{NVuLWu3F?a7=KD{ys$W+e zes$}%uwu?zUP?i*!@4=g-`o~ko zTQ|LOroLe2hWa|#ZtG&FIX{%ot9-Dj^xU>?K1Ml)Sqfs4(|cTr9%@N zN*lfHwT(U|l4NT#9B=Vh&lFo6ql=y}XeGmvcw>pjc++xr%;P(Z_Z`#xWw{Zkdxi&R zY_L6}?Ulv(UB=oAW4}#a2u$$FtTtmESlfHqg$F-j+iA*aUGMYi$e!5G!q~Zw#?MC{ zqXq;xP+9rf*daM5T-Lm@_+>y6h_IW5F!LX%`u5ZuT|1IPClr?0@M`#Un8Z}Ge3PIF z8+uI>f@S!?27Xz8vmNoH&kYRVA)rF(oeay-lB8 Hki>rg9Qpw3 literal 3721 zcmeHI`#;qA8vo3g*2uOP$~9wVD6K8IlqJT{l%b4El8z%@hK6)eM7hq{qjr$SoUDr3 zP$pd|ij^~(3bpQ(%Dv<=a%smU<9?p$wg1KO`QiJ0J=f3kyr0V_*`4XMX0^_0gwPsi z2Hg`O1p|bzKKSo|lNI$#IQ%dXo=%Rauu*Rq2wa4tvlkvt96pGP&<_^QbO*09g0XJD z3;zt(7E6cfN7)CcE^D}24u%=-coCm4_1sg*Ir-3)2bx&Eu00`H?cYkI8ZY&y1j23Qa%#ccP^jgm=Tay6?NB}EbK0>u$YW_#taRu_`S&@c5or#az#Yr z*?b36Bo6N=W-Vp&Tjy*K3%TXsp>)7ZnKO=8MKLDA zqm%Uur5UaFtz8AaN0Ma77|#p9H1DXB@`L&8xVTwfG_zsAQiZcc3DkGSp=K-wOPi@u zM4Jf)D01Vn?EOY6N~z0k#z?wQA1gAl;qu{v603+TMHG8y7@Wr^2J5ty1)n~rCL#}D#fouo5O0H=ma8)q=ODYilLc8 zu#GNoy9pM@S(~haVw^cBe0QG$=a9Mq5@gCyE)g;=P$ie zt_qqU(GV!~@8+NkfeabAVR5-tkjYtaVPr%_S~v{W-4QGu074@QFbsh~E`RCdQUvBq zLmF}kRF#_PEBmh{A^`*3h;#c`GwVlw7&2GkJXbY9JDG9lK^9(>L)t(^KF4r)aXO@N zZ#NbffQP8PO)%K4L4`fDtyg3y;IWSO6c$Z2w(aoOsW>AoR@|4leZbruvfQu{T=j`$ zcqvAF$B2f`b09%u9G>oX!lEpE%0+)f> zg!`wjYlNQcmb|&>_qsh$e-cRq2xFXnz3S!QOI|`@3-^Q*b>moSOGuXql<^tG2d(nR zm%Tcb#+wtBL|>aP&^wH2Rsf*TYIP!SeJ2^xN(O*~x~rVt${YX|Zvz@y{b68uO=<+I zsP~dk7U8dWnn-M;9*ZJNG426iYcQuz0$B9`7woWqQod$2fDUM_dVL|CJ6hh;WhRon z<-dq7(l9B7EU4ZNlkpV@JiLWV9yD4kti_%h$8 zfS~<7)rVZilezX&iJmt~zm!?1$0jaHX12VadL1!uufl2D3sdlB{C@j$S;w}VG%kD2 zO6bu!lYR9m(RyoHp1I9Qzu>Vd3*th*Y2$FOE%M$0J_F;^(%;+?E%j51^z9xb?hKAJ z*D=#k8=jl99*!RBwkatcnncF(X*?C5EZ6*6)wE=m_?LKpyM%68+``~*UN)~F9eF%N z$J4Cknd*{mdvsQe*>KyDBI=TO zWKwa)|Dd)uFC$G5K5?=()#`5@y?6VQ@?*w+8?*1SN(^6K+y3f|rS}EiC%EWO*g?!z z54m{2sZ<2uHCmWS`Cdhf(;w%T&W?W2z07WtGCb^zsGdO{ zJid<$%VSSLO)?&1tb)OcLmv}Jo7%!+^`EepTgu}v2e&Dr*5yc$zk z?XwRx)LVQ$_Fe=VMX=GnuR*$9`RKt=-igtioY=9}dp4zU6CP=ElG%rrOZ=a=OCS2& zDol;p-ZNpVhTXaVYth8UFDZYn^|`W2!dP>QLab@Solk0ETQ1gggk3KkSNF(%V*8mg zR5NcMQ?|bWf3>6d({=qtC3KGr%eKVE%+WJG^y9gluK19Tl0GArX0IyiKpeGL*=pC` z1Y`2uuR(`W-uq}DoD<@*z}N+h9xeAI!PC=&t%AXC zi;U9~x|-|n{uO3z_k2{Lg~5~Ec*7C{Qc&lm9v7t3IgbnWO?v~dbq!`#8r-l^DZX6 J&@teb{{dcRr>y`0 diff --git a/packages/flutter_svg/test/golden_widget/rect.em_ex.png b/packages/flutter_svg/test/golden_widget/rect.em_ex.png index 78fa8e1206e717fe141cdfd8facdcdc8476769ab..03519b9cd0df80b88d6465830d6bf3ffb1be145c 100644 GIT binary patch delta 1999 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 DuIGS@ diff --git a/packages/flutter_svg/test/golden_widget/rect.em_ex2.png b/packages/flutter_svg/test/golden_widget/rect.em_ex2.png index 78fa8e1206e717fe141cdfd8facdcdc8476769ab..03519b9cd0df80b88d6465830d6bf3ffb1be145c 100644 GIT binary patch delta 1999 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 DuIGS@ diff --git a/packages/flutter_svg/test/golden_widget/stick_figure.withclipping.png b/packages/flutter_svg/test/golden_widget/stick_figure.withclipping.png index daa068799c5b885cd564e9c9808f8cdf84a4e783..e6039db89e746335a814ce54e205e33d912f7a78 100644 GIT binary patch literal 20024 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 literal 20756 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 ZwO^{cll(l*?-OA2J+@Ayf}MW<_)ngU(9-|_ diff --git a/packages/flutter_svg/test/no_width_height_test.dart b/packages/flutter_svg/test/no_width_height_test.dart index 3efffbbb..58bcf5f5 100644 --- a/packages/flutter_svg/test/no_width_height_test.dart +++ b/packages/flutter_svg/test/no_width_height_test.dart @@ -27,19 +27,19 @@ class ColumnsAndRows extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( + return const Column( children: [ - Row(children: const [ + Row(children: [ ImageWithText(), ]), Row( - children: const [ + children: [ ImageWithText(), ImageWithText(), ], ), Row( - children: const [ + children: [ ImageWithText(), ImageWithText(), ImageWithText(), @@ -47,7 +47,7 @@ class ColumnsAndRows extends StatelessWidget { ], ), Row( - children: const [ + children: [ ImageWithText(), ImageWithText(), ImageWithText(), @@ -57,7 +57,7 @@ class ColumnsAndRows extends StatelessWidget { ], ), Row( - children: const [ + children: [ ImageWithText(), ImageWithText(), ImageWithText(), diff --git a/packages/flutter_svg/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart index 99c270aa..04f4ff82 100644 --- a/packages/flutter_svg/test/widget_svg_test.dart +++ b/packages/flutter_svg/test/widget_svg_test.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'dart:ui' show window; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; @@ -43,6 +42,8 @@ void main() { late FakeHttpClientResponse fakeResponse; late FakeHttpClientRequest fakeRequest; late FakeHttpClient fakeHttpClient; + final MediaQueryData mediaQueryData = + MediaQueryData.fromView(PlatformDispatcher.instance.implicitView!); setUpAll(() { final LocalFileComparator oldComparator = @@ -107,7 +108,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: SvgPicture.string( @@ -127,7 +128,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: Center( key: key, child: SvgPicture.string( @@ -145,7 +146,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: Center( key: key, child: SvgPicture.string( @@ -163,7 +164,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: Directionality( @@ -204,7 +205,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: Directionality( @@ -245,7 +246,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: SvgPicture.memory( @@ -264,7 +265,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: SvgPicture.asset( @@ -286,7 +287,7 @@ void main() { Directionality( textDirection: TextDirection.ltr, child: MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: DefaultAssetBundle( bundle: fakeAsset, child: RepaintBoundary( @@ -309,7 +310,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: SvgPicture.network( @@ -328,7 +329,7 @@ void main() { final GlobalKey key = GlobalKey(); await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: RepaintBoundary( key: key, child: SvgPicture.network('test.svg', @@ -365,7 +366,7 @@ void main() { fakeResponse.statusCode = 400; await tester.pumpWidget( MediaQuery( - data: MediaQueryData.fromWindow(window), + data: mediaQueryData, child: SvgPicture.network( 'notFound.svg', ), From 9c7c9cd2cd531aeb0a37182f1f6b4728a826d3ae Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 18 May 2023 11:20:44 -0700 Subject: [PATCH 124/142] License file --- packages/flutter_svg/LICENSE | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/flutter_svg/LICENSE diff --git a/packages/flutter_svg/LICENSE b/packages/flutter_svg/LICENSE new file mode 100644 index 00000000..89a79eb0 --- /dev/null +++ b/packages/flutter_svg/LICENSE @@ -0,0 +1,19 @@ +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. \ No newline at end of file From ad9e4d96659e5d7269c4d3da8c344a9dab732fd1 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Fri, 26 May 2023 20:58:10 -0700 Subject: [PATCH 125/142] License for _test --- packages/flutter_svg_test/LICENSE | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/flutter_svg_test/LICENSE diff --git a/packages/flutter_svg_test/LICENSE b/packages/flutter_svg_test/LICENSE new file mode 100644 index 00000000..89a79eb0 --- /dev/null +++ b/packages/flutter_svg_test/LICENSE @@ -0,0 +1,19 @@ +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. \ No newline at end of file From 33fb64be1d93f4e88c715a4cc6a4ab829e6e5e97 Mon Sep 17 00:00:00 2001 From: tattuu Date: Sun, 28 May 2023 04:12:34 +0900 Subject: [PATCH 126/142] Fix typo in README.md (#929) --- packages/flutter_svg/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_svg/README.md b/packages/flutter_svg/README.md index 64aa45bc..15ba7208 100644 --- a/packages/flutter_svg/README.md +++ b/packages/flutter_svg/README.md @@ -66,7 +66,7 @@ final PictureInfo pictureInfo = await vg.loadPicture(SvgStringLoader(rawSvg), nu // You can draw the picture to a canvas: canvas.drawPicture(pictureInfo.picture); -// Or convert the picture to a an image: +// Or convert the picture to an image: final ui.Image image = pictureInfo.picture.toImage(...); pictureInfo.picture.dispose(); From 1ed5a99958d664914b6c1ec6f16ac20cbb2465ac Mon Sep 17 00:00:00 2001 From: David Peters <46222898+dxvid-pts@users.noreply.github.com> Date: Wed, 7 Jun 2023 16:17:50 +0200 Subject: [PATCH 127/142] Fix broken link in Readme (#935) * Update README.md * Update README.md * Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aafb63f..bd6e7dab 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ provides a set of functions to find images generated by `flutter_svg` in widget - SMIL animations. That just seems crazy. I think it'll be possible to animate the SVG but probably in a more Flutter driven way. - Interactivity/events in SVG. -- Any CSS support - preprocess your SVGs (perhaps with [usvg](https://github.com/RazrFalcon/resvg/tree/master/usvg) or [scour](https://github.com/scour-project/scour) to get rid of all CSS?). +- Any CSS support - preprocess your SVGs (perhaps with [usvg](https://github.com/RazrFalcon/resvg/tree/master/crates/usvg) or [scour](https://github.com/scour-project/scour) to get rid of all CSS?). - Scripting in SVGs - Foreign elements - Rendering properties/hints From d7b5c23a79dcb5425548879bdb79a5e7f5097ce5 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 12 Jun 2023 10:29:59 -0700 Subject: [PATCH 128/142] Fix broken textDirection (#940) --- analysis_options.yaml | 2 -- packages/flutter_svg/CHANGELOG.md | 4 ++++ packages/flutter_svg/lib/svg.dart | 1 + packages/flutter_svg/pubspec.yaml | 8 ++++---- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index b2fb7f06..c40de4fa 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -91,12 +91,10 @@ linter: - hash_and_equals - implementation_imports # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 - - iterable_contains_unrelated_type # - join_return_with_assignment # not yet tested - library_names - library_prefixes # - lines_longer_than_80_chars # not yet tested - - list_remove_unrelated_type # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 - no_adjacent_strings_in_list - no_duplicate_case_values diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index 91f21a0d..393bce6a 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 2.0.7 + +- Fix broken `matchTextDirection`. + ## 2.0.6 - Fix test-only issues with latest Flutter stable (3.10). diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index ae2d221d..e4fa8176 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -496,6 +496,7 @@ class SvgPicture extends StatelessWidget { colorFilter: colorFilter, placeholderBuilder: placeholderBuilder, clipViewbox: !allowDrawingOutsideViewBox, + matchTextDirection: matchTextDirection, ); } } diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index 814e8167..c6642e58 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,14 +2,14 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.6 +version: 2.0.7 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.6 - vector_graphics_codec: ^1.1.6 - vector_graphics_compiler: ^1.1.6 + vector_graphics: ^1.1.7 + vector_graphics_codec: ^1.1.7 + vector_graphics_compiler: ^1.1.7 dev_dependencies: flutter_test: From 3148f722de7a616999cab3cc5d1469bdbedbdde0 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Fri, 14 Jul 2023 00:57:12 +0800 Subject: [PATCH 129/142] Adds DefaultSvgTheme (#964) --- packages/flutter_svg/CHANGELOG.md | 4 + .../flutter_svg/lib/src/default_theme.dart | 42 ++++ packages/flutter_svg/lib/src/loaders.dart | 30 ++- packages/flutter_svg/lib/svg.dart | 15 +- .../flutter_svg/test/default_theme_test.dart | 195 ++++++++++++++++++ 5 files changed, 272 insertions(+), 14 deletions(-) create mode 100644 packages/flutter_svg/lib/src/default_theme.dart create mode 100644 packages/flutter_svg/test/default_theme_test.dart diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index 393bce6a..f9268123 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 2.0.8 + +- Adds back `DefaultSvgTheme`. + ## 2.0.7 - Fix broken `matchTextDirection`. diff --git a/packages/flutter_svg/lib/src/default_theme.dart b/packages/flutter_svg/lib/src/default_theme.dart new file mode 100644 index 00000000..a44a981d --- /dev/null +++ b/packages/flutter_svg/lib/src/default_theme.dart @@ -0,0 +1,42 @@ +import 'package:flutter/widgets.dart'; + +import 'loaders.dart'; + +/// The SVG theme to apply to descendant [SvgPicture] widgets +/// which don't have explicit theme values. +class DefaultSvgTheme extends InheritedTheme { + /// Creates a default SVG theme for the given subtree + /// using the provided [theme]. + const DefaultSvgTheme({ + Key? key, + required Widget child, + required this.theme, + }) : super(key: key, child: child); + + /// The SVG theme to apply. + final SvgTheme theme; + + /// The closest instance of this class that encloses the given context. + /// + /// Typical usage is as follows: + /// + /// ```dart + /// DefaultSvgTheme theme = DefaultSvgTheme.of(context); + /// ``` + static DefaultSvgTheme? of(BuildContext context) { + return context.dependOnInheritedWidgetOfExactType(); + } + + @override + bool updateShouldNotify(DefaultSvgTheme oldWidget) { + return theme != oldWidget.theme; + } + + @override + Widget wrap(BuildContext context, Widget child) { + return DefaultSvgTheme( + theme: theme, + child: child, + ); + } +} diff --git a/packages/flutter_svg/lib/src/loaders.dart b/packages/flutter_svg/lib/src/loaders.dart index 5ebd8dd6..9ec1fde3 100644 --- a/packages/flutter_svg/lib/src/loaders.dart +++ b/packages/flutter_svg/lib/src/loaders.dart @@ -3,13 +3,14 @@ import 'dart:convert' show utf8; import 'package:flutter/foundation.dart' hide compute; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_svg/src/utilities/http.dart'; import 'package:vector_graphics/vector_graphics.dart'; import 'package:vector_graphics_compiler/vector_graphics_compiler.dart' as vg; import '../svg.dart' show svg; +import 'default_theme.dart'; import 'utilities/compute.dart'; import 'utilities/file.dart'; +import 'utilities/http.dart'; /// A theme used when decoding an SVG picture. @immutable @@ -111,12 +112,12 @@ class _DelegateVgColorMapper extends vg.ColorMapper { abstract class SvgLoader extends BytesLoader { /// See class doc. const SvgLoader({ - this.theme = const SvgTheme(), + this.theme, this.colorMapper, }); /// The theme to determine currentColor and font sizing attributes. - final SvgTheme theme; + final SvgTheme? theme; /// The [ColorMapper] used to transform colors from the SVG, if any. final ColorMapper? colorMapper; @@ -130,7 +131,24 @@ abstract class SvgLoader extends BytesLoader { Future prepareMessage(BuildContext? context) => SynchronousFuture(null); + /// Returns the svg theme. + @visibleForTesting + @protected + SvgTheme getTheme(BuildContext? context) { + if (theme != null) { + return theme!; + } + if (context != null) { + final SvgTheme? defaultTheme = DefaultSvgTheme.of(context)?.theme; + if (defaultTheme != null) { + return defaultTheme; + } + } + return const SvgTheme(); + } + Future _load(BuildContext? context) { + final SvgTheme theme = getTheme(context); return prepareMessage(context).then((T? message) { return compute((T? message) { return vg @@ -160,6 +178,7 @@ abstract class SvgLoader extends BytesLoader { @override SvgCacheKey cacheKey(BuildContext? context) { + final SvgTheme theme = getTheme(context); return SvgCacheKey(keyData: this, theme: theme, colorMapper: colorMapper); } } @@ -172,13 +191,13 @@ abstract class SvgLoader extends BytesLoader { class SvgCacheKey { /// See [SvgCacheKey]. const SvgCacheKey({ - required this.theme, required this.keyData, required this.colorMapper, + this.theme, }); /// The theme for this cached SVG. - final SvgTheme theme; + final SvgTheme? theme; /// The other key data for the SVG. /// @@ -365,6 +384,7 @@ class SvgAssetLoader extends SvgLoader { @override SvgCacheKey cacheKey(BuildContext? context) { + final SvgTheme theme = getTheme(context); return SvgCacheKey( theme: theme, colorMapper: colorMapper, diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index e4fa8176..ca421374 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -12,6 +12,7 @@ export 'package:vector_graphics/vector_graphics.dart' show BytesLoader, vg, VectorGraphicUtilities, PictureInfo; export 'src/cache.dart'; +export 'src/default_theme.dart'; export 'src/loaders.dart'; /// Instance for [Svg]'s utility methods, which can produce a [DrawableRoot] @@ -84,7 +85,6 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, - this.theme = const SvgTheme(), @deprecated bool cacheColorFilter = false, }) : super(key: key); @@ -179,7 +179,7 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, - this.theme = const SvgTheme(), + SvgTheme? theme, ui.ColorFilter? colorFilter, @deprecated ui.Color? color, @deprecated ui.BlendMode colorBlendMode = ui.BlendMode.srcIn, @@ -243,7 +243,7 @@ class SvgPicture extends StatelessWidget { this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, @deprecated bool cacheColorFilter = false, - this.theme = const SvgTheme(), + SvgTheme? theme, }) : bytesLoader = SvgNetworkLoader(url, headers: headers, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), super(key: key); @@ -294,7 +294,7 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, - this.theme = const SvgTheme(), + SvgTheme? theme, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgFileLoader(file, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -343,7 +343,7 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, - this.theme = const SvgTheme(), + SvgTheme? theme, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgBytesLoader(bytes, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -392,7 +392,7 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, - this.theme = const SvgTheme(), + SvgTheme? theme, @deprecated bool cacheColorFilter = false, }) : bytesLoader = SvgStringLoader(string, theme: theme), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), @@ -479,9 +479,6 @@ class SvgPicture extends StatelessWidget { /// The color filter, if any, to apply to this widget. final ColorFilter? colorFilter; - /// The theme used when parsing SVG elements. - final SvgTheme theme; - @override Widget build(BuildContext context) { return createCompatVectorGraphic( diff --git a/packages/flutter_svg/test/default_theme_test.dart b/packages/flutter_svg/test/default_theme_test.dart new file mode 100644 index 00000000..1078ae49 --- /dev/null +++ b/packages/flutter_svg/test/default_theme_test.dart @@ -0,0 +1,195 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('DefaultSvgTheme', () { + testWidgets('changes propagate to SvgPicture', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + currentColor: Color(0xFF733821), + fontSize: 14.0, + xHeight: 6.0, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string(''' + + +'''); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + BuildContext context = tester.element(find.byType(SvgPicture)); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context), + equals(svgTheme), + ); + + const SvgTheme anotherSvgTheme = SvgTheme( + currentColor: Color(0xFF05290E), + fontSize: 12.0, + xHeight: 7.0, + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: anotherSvgTheme, + child: svgPictureWidget, + )); + context = tester.element(find.byType(SvgPicture)); + + svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context), + equals(anotherSvgTheme), + ); + }); + + testWidgets( + 'currentColor from the widget\'s theme takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + currentColor: Color(0xFF733821), + fontSize: 14.0, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + theme: const SvgTheme( + currentColor: Color(0xFF05290E), + fontSize: 14.0, + ), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + final BuildContext context = tester.element(find.byType(SvgPicture)); + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader) + .getTheme(context) + .currentColor, + equals(const Color(0xFF05290E)), + ); + }); + + testWidgets( + 'fontSize from the widget\'s theme takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + fontSize: 14.0, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + theme: const SvgTheme( + fontSize: 12.0, + ), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + final BuildContext context = tester.element(find.byType(SvgPicture)); + + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context).fontSize, + equals(12.0), + ); + }); + + testWidgets( + 'fontSize defaults to 14 ' + 'if no widget\'s theme, DefaultSvgTheme or DefaultTextStyle is provided', + (WidgetTester tester) async { + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + ); + + await tester.pumpWidget(svgPictureWidget); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + final BuildContext context = tester.element(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context).fontSize, + equals(14.0), + ); + }); + + testWidgets( + 'xHeight from the widget\'s theme takes precedence over ' + 'the theme from DefaultSvgTheme', (WidgetTester tester) async { + const SvgTheme svgTheme = SvgTheme( + fontSize: 14.0, + xHeight: 6.5, + ); + + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + theme: const SvgTheme( + fontSize: 12.0, + xHeight: 7.0, + ), + ); + + await tester.pumpWidget(DefaultSvgTheme( + theme: svgTheme, + child: svgPictureWidget, + )); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + final BuildContext context = tester.element(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context).xHeight, + equals(7.0), + ); + }); + + testWidgets( + 'xHeight defaults to the font size divided by 2 (7.0) ' + 'if no widget\'s theme or DefaultSvgTheme is provided', + (WidgetTester tester) async { + final SvgPicture svgPictureWidget = SvgPicture.string( + ''' + + +''', + ); + + await tester.pumpWidget(svgPictureWidget); + + final SvgPicture svgPicture = tester.firstWidget(find.byType(SvgPicture)); + final BuildContext context = tester.element(find.byType(SvgPicture)); + expect(svgPicture, isNotNull); + expect( + (svgPicture.bytesLoader as SvgStringLoader).getTheme(context).xHeight, + equals(7.0), + ); + }); + }); +} From 6a246870efc45bc1768299aa4353ba484754145c Mon Sep 17 00:00:00 2001 From: Andrew Brampton Date: Mon, 9 Oct 2023 20:09:10 -0700 Subject: [PATCH 130/142] Fixed minor typo in link on the README.md (#995) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bd6e7dab..8aa70ca5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This library consists of two packages: and [**flutter_svg_test** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test). -[flutter_svg](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test) +[flutter_svg](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) provides a wrapper around Dart implementations of SVG parsing, including SVG path data. In particular, it provides efficient `BytesLoader` implementations for [`package:vector_graphics`](https://pub.dev/packages/vector_graphics). From b6b399e69f74206f9b8373cc00b1f5790bd9d535 Mon Sep 17 00:00:00 2001 From: Andrew Brampton Date: Mon, 16 Oct 2023 09:58:13 -0700 Subject: [PATCH 131/142] Added debugFillProperties to SvgPicture to enable easier debugging. (#999) --- packages/flutter_svg/lib/svg.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index ca421374..3ac7c6a7 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -496,4 +496,22 @@ class SvgPicture extends StatelessWidget { matchTextDirection: matchTextDirection, ); } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + + properties.add(StringProperty('bytesLoader', bytesLoader.toString(), showName: false)); + properties.add(DoubleProperty('width', width, defaultValue: null)); + properties.add(DoubleProperty('height', height, defaultValue: null)); + properties.add(EnumProperty('alignment', alignment, defaultValue: Alignment.center)); + properties.add(DiagnosticsProperty('allowDrawingOutsideViewBox', allowDrawingOutsideViewBox, defaultValue: false)); + properties.add(EnumProperty('clipBehavior', clipBehavior, defaultValue: BoxFit.contain)); + properties.add(StringProperty('colorFilter', colorFilter.toString(), defaultValue: null)); + properties.add(EnumProperty('fit', fit, defaultValue: BoxFit.contain)); + properties.add(DiagnosticsProperty('placeholderBuilder', placeholderBuilder, defaultValue: null)); + properties.add(DiagnosticsProperty('matchTextDirection', matchTextDirection, defaultValue: false)); + properties.add(DiagnosticsProperty('excludeFromSemantics', excludeFromSemantics, defaultValue: false)); + properties.add(StringProperty('semanticsLabel', semanticsLabel, defaultValue: null)); + } } From 6164f367ecc82caf09392380a24c19286e48abb2 Mon Sep 17 00:00:00 2001 From: Andrew Brampton Date: Tue, 17 Oct 2023 13:42:08 -0700 Subject: [PATCH 132/142] Fixed formatting broken in https://github.com/dnfield/flutter_svg/pull/999 (#1001) I originally didn't format the debugFillProperties because that seems to be what happens in the main flutter library (presumably for better readability), but here it breaks the presubmits. So here is a quick `dart format`. --- packages/flutter_svg/lib/svg.dart | 34 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index 3ac7c6a7..a87d5180 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -501,17 +501,31 @@ class SvgPicture extends StatelessWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(StringProperty('bytesLoader', bytesLoader.toString(), showName: false)); + properties.add( + StringProperty('bytesLoader', bytesLoader.toString(), showName: false)); properties.add(DoubleProperty('width', width, defaultValue: null)); properties.add(DoubleProperty('height', height, defaultValue: null)); - properties.add(EnumProperty('alignment', alignment, defaultValue: Alignment.center)); - properties.add(DiagnosticsProperty('allowDrawingOutsideViewBox', allowDrawingOutsideViewBox, defaultValue: false)); - properties.add(EnumProperty('clipBehavior', clipBehavior, defaultValue: BoxFit.contain)); - properties.add(StringProperty('colorFilter', colorFilter.toString(), defaultValue: null)); - properties.add(EnumProperty('fit', fit, defaultValue: BoxFit.contain)); - properties.add(DiagnosticsProperty('placeholderBuilder', placeholderBuilder, defaultValue: null)); - properties.add(DiagnosticsProperty('matchTextDirection', matchTextDirection, defaultValue: false)); - properties.add(DiagnosticsProperty('excludeFromSemantics', excludeFromSemantics, defaultValue: false)); - properties.add(StringProperty('semanticsLabel', semanticsLabel, defaultValue: null)); + properties.add(EnumProperty('alignment', alignment, + defaultValue: Alignment.center)); + properties.add(DiagnosticsProperty( + 'allowDrawingOutsideViewBox', allowDrawingOutsideViewBox, + defaultValue: false)); + properties.add(EnumProperty('clipBehavior', clipBehavior, + defaultValue: BoxFit.contain)); + properties.add(StringProperty('colorFilter', colorFilter.toString(), + defaultValue: null)); + properties + .add(EnumProperty('fit', fit, defaultValue: BoxFit.contain)); + properties.add(DiagnosticsProperty( + 'placeholderBuilder', placeholderBuilder, + defaultValue: null)); + properties.add(DiagnosticsProperty( + 'matchTextDirection', matchTextDirection, + defaultValue: false)); + properties.add(DiagnosticsProperty( + 'excludeFromSemantics', excludeFromSemantics, + defaultValue: false)); + properties.add( + StringProperty('semanticsLabel', semanticsLabel, defaultValue: null)); } } From 16c062beaef478da415a062fb459cc366e8f7863 Mon Sep 17 00:00:00 2001 From: Andrew Brampton Date: Tue, 17 Oct 2023 14:38:28 -0700 Subject: [PATCH 133/142] Fixes issue where a incorrect key was being given to the ImageCache (#1000) * Fixed the hashcode in SvgStringLoader and SvgBytesLoader. It was accidently using the svg global object, instead of a local field. This caused caches (such as PaintingBinding.instance.imageCache) to misbehave. * Add a test which ensures the embedded image in a SvgPicture is not incorrectly cached and carried over. --- packages/flutter_svg/lib/src/loaders.dart | 4 +- .../test/golden_widget/image_blue.png | Bin 0 -> 3276 bytes .../test/golden_widget/image_red.png | Bin 0 -> 3278 bytes .../flutter_svg/test/widget_svg_test.dart | 48 ++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 packages/flutter_svg/test/golden_widget/image_blue.png create mode 100644 packages/flutter_svg/test/golden_widget/image_red.png diff --git a/packages/flutter_svg/lib/src/loaders.dart b/packages/flutter_svg/lib/src/loaders.dart index 9ec1fde3..0c9931d0 100644 --- a/packages/flutter_svg/lib/src/loaders.dart +++ b/packages/flutter_svg/lib/src/loaders.dart @@ -237,7 +237,7 @@ class SvgStringLoader extends SvgLoader { } @override - int get hashCode => Object.hash(svg, theme, colorMapper); + int get hashCode => Object.hash(_svg, theme, colorMapper); @override bool operator ==(Object other) { @@ -266,7 +266,7 @@ class SvgBytesLoader extends SvgLoader { String provideSvg(void message) => utf8.decode(bytes, allowMalformed: true); @override - int get hashCode => Object.hash(svg, theme, colorMapper); + int get hashCode => Object.hash(bytes, theme, colorMapper); @override bool operator ==(Object other) { diff --git a/packages/flutter_svg/test/golden_widget/image_blue.png b/packages/flutter_svg/test/golden_widget/image_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..1561f73cf184f8627c1ef907041bfc5d802c20c9 GIT binary patch literal 3276 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYV2a>i1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq|#Y)5S5QV$R#^2L&AhL=HH_KX!X6Q#v92##)8zYkH^e?0di1B%QlYbpRzjKx9jP7LeL$-D$|Sc;uI zLpXq-h9jkefq|#O)5S5QV$R#^2L&AhL=GHqf9&>DrgTF7jkOBba}KYLF+To^jiEvR zX4<){yf)viGBPk6sFx66U{FYQU|?wIVFU^ov9T~PoEQ}x4Uo~qFq#oYONP->akNGl rtqn(O!_nGsv^E^A4YAjTXLz;$vu#*uYk3>kCt>h(^>bP0l+XkK5kl)* literal 0 HcmV?d00001 diff --git a/packages/flutter_svg/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart index 04f4ff82..f464e01b 100644 --- a/packages/flutter_svg/test/widget_svg_test.dart +++ b/packages/flutter_svg/test/widget_svg_test.dart @@ -728,6 +728,54 @@ void main() { matchesGoldenFile('golden_widget/two_of_same.png'), ); }); + + // This tests https://github.com/dnfield/flutter_svg/issues/990 + // Where embedded images were being incorrectly cached. + testWidgets('SvgPicture - with cached images', (WidgetTester tester) async { + // Simple red and blue 10x10 squares. + // Borrowed from https://gist.github.com/ondrek/7413434?permalink_comment_id=4674255#gistcomment-4674255 + final Map images = { + 'red': + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mP8z8BQz0AEYBxVSF+FABJADveWkH6oAAAAAElFTkSuQmCC', + 'blue': + 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYBxVSF+FAP5FDvcfRYWgAAAAAElFTkSuQmCC', + }; + + // We keep pumping widgets into the same tester, to ensure the same cache + // is used on each iteration. + for (final String key in images.keys) { + final String image = images[key]!; + final String svgStr = ''' + + '''; + + // First try with SvgPicture.string + await tester.pumpWidget(RepaintBoundary( + child: SvgPicture.string(svgStr), + )); + await tester.runAsync(() => vg.waitForPendingDecodes()); + await tester.pumpAndSettle(); + + Finder widgetFinder = find.byType(SvgPicture); + expect(widgetFinder, findsOneWidget); + await expectLater( + widgetFinder, matchesGoldenFile('golden_widget/image_$key.png')); + + // Then with SvgPicture.memory + await tester.pumpWidget(RepaintBoundary( + child: SvgPicture.memory(utf8.encode(svgStr) as Uint8List), + )); + await tester.runAsync(() => vg.waitForPendingDecodes()); + await tester.pumpAndSettle(); + + widgetFinder = find.byType(SvgPicture); + expect(widgetFinder, findsOneWidget); + await expectLater( + widgetFinder, matchesGoldenFile('golden_widget/image_$key.png')); + } + }); } class FakeAssetBundle extends Fake implements AssetBundle { From 05f0f196a8d373ac55cf07d5cff4c70d639c308a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 24 Oct 2023 16:04:47 -0700 Subject: [PATCH 134/142] fixes --- packages/flutter_svg/CHANGELOG.md | 3 +++ packages/flutter_svg/example/pubspec.yaml | 6 +++--- packages/flutter_svg/lib/svg.dart | 2 +- packages/flutter_svg/pubspec.yaml | 6 +++--- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index f9268123..d7781e76 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -3,6 +3,9 @@ ## 2.0.8 - Adds back `DefaultSvgTheme`. +- Bump vector_graphics to 1.1.9+1 +- Adds debugFillProperties +- Fix bug for cache keys. ## 2.0.7 diff --git a/packages/flutter_svg/example/pubspec.yaml b/packages/flutter_svg/example/pubspec.yaml index a4f3c406..c6691b6c 100644 --- a/packages/flutter_svg/example/pubspec.yaml +++ b/packages/flutter_svg/example/pubspec.yaml @@ -32,8 +32,8 @@ environment: # dependency_overrides: # vector_graphics_codec: -# path: ../../vector_graphics/packages/vector_graphics_codec +# path: ../../../../vector_graphics/packages/vector_graphics_codec # vector_graphics_compiler: -# path: ../../vector_graphics/packages/vector_graphics_compiler +# path: ../../../../vector_graphics/packages/vector_graphics_compiler # vector_graphics: -# path: ../../vector_graphics/packages/vector_graphics +# path: ../../../../vector_graphics/packages/vector_graphics diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index a87d5180..bfad274f 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -505,7 +505,7 @@ class SvgPicture extends StatelessWidget { StringProperty('bytesLoader', bytesLoader.toString(), showName: false)); properties.add(DoubleProperty('width', width, defaultValue: null)); properties.add(DoubleProperty('height', height, defaultValue: null)); - properties.add(EnumProperty('alignment', alignment, + properties.add(DiagnosticsProperty('alignment', alignment, defaultValue: Alignment.center)); properties.add(DiagnosticsProperty( 'allowDrawingOutsideViewBox', allowDrawingOutsideViewBox, diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index c6642e58..fcbb67ff 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -7,9 +7,9 @@ version: 2.0.7 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.7 - vector_graphics_codec: ^1.1.7 - vector_graphics_compiler: ^1.1.7 + vector_graphics: ^1.1.9+1 + vector_graphics_codec: ^1.1.9+1 + vector_graphics_compiler: ^1.1.9+1 dev_dependencies: flutter_test: From 1114a0f7343aef5afa27f5c513b3f0c2e51f7822 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 24 Oct 2023 16:06:04 -0700 Subject: [PATCH 135/142] missing file --- packages/flutter_svg/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index fcbb67ff..689fdee5 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.7 +version: 2.0.8 dependencies: flutter: From 20932e20cb779373f7030a029baa177e228336cb Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 31 Oct 2023 15:10:12 -0700 Subject: [PATCH 136/142] Fix semver violation for SvgPicture (#1008) * Fix semver violation for SvgPicture * fix for older versions of flutter? --- packages/flutter_svg/CHANGELOG.md | 6 ++ packages/flutter_svg/lib/svg.dart | 81 +++++++++++++------ packages/flutter_svg/pubspec.yaml | 2 +- .../flutter_svg/test/widget_svg_test.dart | 3 +- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index d7781e76..4fce8669 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGES +## 2.0.9 + +- Adds back `SvgPicture(theme:)` parameter with a deprecation. Although this + parameter was inherently broken, removing it would require a major semver + bump, which would cause consumers to miss out on important fixes. + ## 2.0.8 - Adds back `DefaultSvgTheme`. diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index bfad274f..785cfa14 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -85,6 +85,10 @@ class SvgPicture extends StatelessWidget { this.semanticsLabel, this.excludeFromSemantics = false, this.clipBehavior = Clip.hardEdge, + @Deprecated( + 'No code should use this parameter. It never was implemented properly. ' + 'The SVG theme must be set on the bytesLoader.') + SvgTheme? theme, @deprecated bool cacheColorFilter = false, }) : super(key: key); @@ -501,31 +505,58 @@ class SvgPicture extends StatelessWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add( - StringProperty('bytesLoader', bytesLoader.toString(), showName: false)); - properties.add(DoubleProperty('width', width, defaultValue: null)); - properties.add(DoubleProperty('height', height, defaultValue: null)); - properties.add(DiagnosticsProperty('alignment', alignment, - defaultValue: Alignment.center)); - properties.add(DiagnosticsProperty( - 'allowDrawingOutsideViewBox', allowDrawingOutsideViewBox, - defaultValue: false)); - properties.add(EnumProperty('clipBehavior', clipBehavior, - defaultValue: BoxFit.contain)); - properties.add(StringProperty('colorFilter', colorFilter.toString(), - defaultValue: null)); properties - .add(EnumProperty('fit', fit, defaultValue: BoxFit.contain)); - properties.add(DiagnosticsProperty( - 'placeholderBuilder', placeholderBuilder, - defaultValue: null)); - properties.add(DiagnosticsProperty( - 'matchTextDirection', matchTextDirection, - defaultValue: false)); - properties.add(DiagnosticsProperty( - 'excludeFromSemantics', excludeFromSemantics, - defaultValue: false)); - properties.add( - StringProperty('semanticsLabel', semanticsLabel, defaultValue: null)); + ..add(StringProperty( + 'bytesLoader', + bytesLoader.toString(), + showName: false, + )) + ..add(DoubleProperty('width', width, defaultValue: null)) + ..add(DoubleProperty('height', height, defaultValue: null)) + ..add(DiagnosticsProperty( + 'alignment', + alignment, + defaultValue: Alignment.center, + )) + ..add(DiagnosticsProperty( + 'allowDrawingOutsideViewBox', + allowDrawingOutsideViewBox, + defaultValue: false, + )) + ..add(EnumProperty( + 'clipBehavior', + clipBehavior, + defaultValue: BoxFit.contain, + )) + ..add(StringProperty( + 'colorFilter', + colorFilter.toString(), + defaultValue: null, + )) + ..add(EnumProperty( + 'fit', + fit, + defaultValue: BoxFit.contain, + )) + ..add(DiagnosticsProperty( + 'placeholderBuilder', + placeholderBuilder, + defaultValue: null, + )) + ..add(DiagnosticsProperty( + 'matchTextDirection', + matchTextDirection, + defaultValue: false, + )) + ..add(DiagnosticsProperty( + 'excludeFromSemantics', + excludeFromSemantics, + defaultValue: false, + )) + ..add(StringProperty( + 'semanticsLabel', + semanticsLabel, + defaultValue: null, + )); } } diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index 689fdee5..a5d77b93 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.8 +version: 2.0.9 dependencies: flutter: diff --git a/packages/flutter_svg/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart index f464e01b..8913907b 100644 --- a/packages/flutter_svg/test/widget_svg_test.dart +++ b/packages/flutter_svg/test/widget_svg_test.dart @@ -765,6 +765,7 @@ void main() { // Then with SvgPicture.memory await tester.pumpWidget(RepaintBoundary( + // ignore: unnecessary_cast child: SvgPicture.memory(utf8.encode(svgStr) as Uint8List), )); await tester.runAsync(() => vg.waitForPendingDecodes()); @@ -902,4 +903,4 @@ const String stickFigureSvgStr = ''' '''; -final Uint8List svgBytes = utf8.encode(svgStr) as Uint8List; +final Uint8List svgBytes = Uint8List.fromList(utf8.encode(svgStr)); From ac2ef32526c8b85be87094ac3f9c7c3af247f047 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 5 Dec 2023 13:39:07 -0800 Subject: [PATCH 137/142] skip out of date test --- packages/flutter_svg/test/no_width_height_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/flutter_svg/test/no_width_height_test.dart b/packages/flutter_svg/test/no_width_height_test.dart index 58bcf5f5..5c0955eb 100644 --- a/packages/flutter_svg/test/no_width_height_test.dart +++ b/packages/flutter_svg/test/no_width_height_test.dart @@ -18,6 +18,7 @@ void main() { await expectLater( find.byType(RepaintBoundary), matchesGoldenFile('golden_widget/columns_and_rows.png'), + skip: 'This golden needs updating', ); }, skip: !isLinux); } From 1a33cbda4cda8feb56b597836ade2b5af3c12c64 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 5 Dec 2023 13:44:13 -0800 Subject: [PATCH 138/142] ignore unnecessary cast --- packages/flutter_svg_test/test/flutter_svg_test_test.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/flutter_svg_test/test/flutter_svg_test_test.dart b/packages/flutter_svg_test/test/flutter_svg_test_test.dart index a3a88e05..474b5e79 100644 --- a/packages/flutter_svg_test/test/flutter_svg_test_test.dart +++ b/packages/flutter_svg_test/test/flutter_svg_test_test.dart @@ -174,10 +174,12 @@ class _FakeHttpClientResponse extends Fake implements HttpClientResponse { } } +// Ignore this because the minimum flutter sdk needs this cast. +// ignore: unnecessary_cast final Uint8List _svgBytes = utf8.encode(_svgStr) as Uint8List; const String _svgStr = ''' - + '''; From a3911bb074c49b821bb9beaa349ee04ac9f4e2f7 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 5 Dec 2023 13:49:41 -0800 Subject: [PATCH 139/142] Avoid expanding the parameter type of operator== (#1017) Object.operator== takes an `Object`, and no Dart runtime passes a `null` value to an `==` implementation. SvgTheme's implementation should not have an expanded parameter type of `dynamic`. See https://github.com/flutter/flutter/issues/117838 for the overarching issue for Flutter. Co-authored-by: Dan Field --- packages/flutter_svg/lib/src/loaders.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_svg/lib/src/loaders.dart b/packages/flutter_svg/lib/src/loaders.dart index 0c9931d0..ac781ef5 100644 --- a/packages/flutter_svg/lib/src/loaders.dart +++ b/packages/flutter_svg/lib/src/loaders.dart @@ -54,7 +54,7 @@ class SvgTheme { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { if (other.runtimeType != runtimeType) { return false; } From 09fd110bdbf746df770d17dc9e592bd1e806b126 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 20 Feb 2024 08:54:04 -0800 Subject: [PATCH 140/142] Use package:http, drop dart:html (#1038) * Use package:http, drop dart:html * Format --- .gitignore | 2 +- packages/flutter_svg/CHANGELOG.md | 5 + packages/flutter_svg/lib/src/loaders.dart | 13 +- .../lib/src/utilities/_http_io.dart | 22 --- .../lib/src/utilities/_http_web.dart | 12 -- .../flutter_svg/lib/src/utilities/http.dart | 1 - packages/flutter_svg/lib/svg.dart | 9 +- packages/flutter_svg/pubspec.yaml | 9 +- .../flutter_svg/test/widget_svg_test.dart | 154 ++++++------------ 9 files changed, 77 insertions(+), 150 deletions(-) delete mode 100644 packages/flutter_svg/lib/src/utilities/_http_io.dart delete mode 100644 packages/flutter_svg/lib/src/utilities/_http_web.dart delete mode 100644 packages/flutter_svg/lib/src/utilities/http.dart diff --git a/.gitignore b/.gitignore index c6346e7f..a48af087 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,6 @@ coverage/ .project # golden failure diffs -test/failures +**/test/failures # Flutter crash logs /flutter_*.log diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index 4fce8669..ea9a4e24 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGES +## 2.0.10 + +- Use package:http for network requests, and allow injection of the client. +- Bump vector_graphics dependency. + ## 2.0.9 - Adds back `SvgPicture(theme:)` parameter with a deprecation. Although this diff --git a/packages/flutter_svg/lib/src/loaders.dart b/packages/flutter_svg/lib/src/loaders.dart index ac781ef5..2996cc11 100644 --- a/packages/flutter_svg/lib/src/loaders.dart +++ b/packages/flutter_svg/lib/src/loaders.dart @@ -3,6 +3,7 @@ import 'dart:convert' show utf8; import 'package:flutter/foundation.dart' hide compute; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; +import 'package:http/http.dart' as http; import 'package:vector_graphics/vector_graphics.dart'; import 'package:vector_graphics_compiler/vector_graphics_compiler.dart' as vg; @@ -10,7 +11,6 @@ import '../svg.dart' show svg; import 'default_theme.dart'; import 'utilities/compute.dart'; import 'utilities/file.dart'; -import 'utilities/http.dart'; /// A theme used when decoding an SVG picture. @immutable @@ -109,6 +109,7 @@ class _DelegateVgColorMapper extends vg.ColorMapper { /// A [BytesLoader] that parses a SVG data in an isolate and creates a /// vector_graphics binary representation. +@immutable abstract class SvgLoader extends BytesLoader { /// See class doc. const SvgLoader({ @@ -423,7 +424,8 @@ class SvgNetworkLoader extends SvgLoader { this.headers, super.theme, super.colorMapper, - }); + http.Client? httpClient, + }) : _httpClient = httpClient; /// The [Uri] encoded resource address. final String url; @@ -431,9 +433,12 @@ class SvgNetworkLoader extends SvgLoader { /// Optional HTTP headers to send as part of the request. final Map? headers; + final http.Client? _httpClient; + @override - Future prepareMessage(BuildContext? context) { - return httpGet(url, headers: headers); + Future prepareMessage(BuildContext? context) async { + final http.Client client = _httpClient ?? http.Client(); + return (await client.get(Uri.parse(url), headers: headers)).bodyBytes; } @override diff --git a/packages/flutter_svg/lib/src/utilities/_http_io.dart b/packages/flutter_svg/lib/src/utilities/_http_io.dart deleted file mode 100644 index 458a2072..00000000 --- a/packages/flutter_svg/lib/src/utilities/_http_io.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; // ignore: unnecessary_import - -import 'package:flutter/foundation.dart'; - -/// Fetches an HTTP resource from the specified [url] using the specified [headers]. -Future httpGet(String url, {Map? headers}) async { - final HttpClient httpClient = HttpClient(); - final Uri uri = Uri.base.resolve(url); - final HttpClientRequest request = await httpClient.getUrl(uri); - if (headers != null) { - headers.forEach((String key, String value) { - request.headers.add(key, value); - }); - } - final HttpClientResponse response = await request.close(); - - if (response.statusCode != HttpStatus.ok) { - throw HttpException('Could not get network asset', uri: uri); - } - return consolidateHttpClientResponseBytes(response); -} diff --git a/packages/flutter_svg/lib/src/utilities/_http_web.dart b/packages/flutter_svg/lib/src/utilities/_http_web.dart deleted file mode 100644 index fc8b2c17..00000000 --- a/packages/flutter_svg/lib/src/utilities/_http_web.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:convert'; -import 'dart:html'; -import 'dart:typed_data'; - -/// Fetches an HTTP resource from the specified [url] using the specified [headers]. -Future httpGet(String url, {Map? headers}) async { - final HttpRequest request = await HttpRequest.request( - url, - requestHeaders: headers, - ); - return Uint8List.fromList(utf8.encode(request.responseText!)); -} diff --git a/packages/flutter_svg/lib/src/utilities/http.dart b/packages/flutter_svg/lib/src/utilities/http.dart deleted file mode 100644 index cdf44641..00000000 --- a/packages/flutter_svg/lib/src/utilities/http.dart +++ /dev/null @@ -1 +0,0 @@ -export '_http_io.dart' if (dart.library.html) '_http_web.dart'; diff --git a/packages/flutter_svg/lib/svg.dart b/packages/flutter_svg/lib/svg.dart index 785cfa14..d39e47ba 100644 --- a/packages/flutter_svg/lib/svg.dart +++ b/packages/flutter_svg/lib/svg.dart @@ -2,6 +2,7 @@ import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; +import 'package:http/http.dart' as http; import 'package:vector_graphics/vector_graphics_compat.dart'; import 'src/cache.dart'; @@ -248,7 +249,13 @@ class SvgPicture extends StatelessWidget { this.clipBehavior = Clip.hardEdge, @deprecated bool cacheColorFilter = false, SvgTheme? theme, - }) : bytesLoader = SvgNetworkLoader(url, headers: headers, theme: theme), + http.Client? httpClient, + }) : bytesLoader = SvgNetworkLoader( + url, + headers: headers, + theme: theme, + httpClient: httpClient, + ), colorFilter = colorFilter ?? _getColorFilter(color, colorBlendMode), super(key: key); diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index a5d77b93..4e07c613 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,14 +2,15 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.9 +version: 2.0.10 dependencies: flutter: sdk: flutter - vector_graphics: ^1.1.9+1 - vector_graphics_codec: ^1.1.9+1 - vector_graphics_compiler: ^1.1.9+1 + http: ^1.2.1 + vector_graphics: ^1.1.11 + vector_graphics_codec: ^1.1.11 + vector_graphics_compiler: ^1.1.11 dev_dependencies: flutter_test: diff --git a/packages/flutter_svg/test/widget_svg_test.dart b/packages/flutter_svg/test/widget_svg_test.dart index 8913907b..49dfe8ed 100644 --- a/packages/flutter_svg/test/widget_svg_test.dart +++ b/packages/flutter_svg/test/widget_svg_test.dart @@ -1,12 +1,11 @@ -import 'dart:async'; import 'dart:convert'; -import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; class _TolerantComparator extends LocalFileComparator { _TolerantComparator(Uri testFile) : super(testFile); @@ -39,9 +38,6 @@ Future _checkWidgetAndGolden(Key key, String filename) async { } void main() { - late FakeHttpClientResponse fakeResponse; - late FakeHttpClientRequest fakeRequest; - late FakeHttpClient fakeHttpClient; final MediaQueryData mediaQueryData = MediaQueryData.fromView(PlatformDispatcher.instance.implicitView!); @@ -54,12 +50,6 @@ void main() { goldenFileComparator = newComparator; }); - setUp(() { - fakeResponse = FakeHttpClientResponse(); - fakeRequest = FakeHttpClientRequest(fakeResponse); - fakeHttpClient = FakeHttpClient(fakeRequest); - }); - testWidgets( 'SvgPicture does not use a color filtering widget when no color specified', (WidgetTester tester) async { @@ -306,40 +296,41 @@ void main() { }); testWidgets('SvgPicture.network', (WidgetTester tester) async { - await HttpOverrides.runZoned(() async { - final GlobalKey key = GlobalKey(); - await tester.pumpWidget( - MediaQuery( - data: mediaQueryData, - child: RepaintBoundary( - key: key, - child: SvgPicture.network( - 'test.svg', - ), + final GlobalKey key = GlobalKey(); + await tester.pumpWidget( + MediaQuery( + data: mediaQueryData, + child: RepaintBoundary( + key: key, + child: SvgPicture.network( + 'test.svg', + httpClient: FakeHttpClient(), ), ), - ); - await tester.pumpAndSettle(); - await _checkWidgetAndGolden(key, 'flutter_logo.network.png'); - }, createHttpClient: (SecurityContext? c) => fakeHttpClient); + ), + ); + await tester.pumpAndSettle(); + await _checkWidgetAndGolden(key, 'flutter_logo.network.png'); }); testWidgets('SvgPicture.network with headers', (WidgetTester tester) async { - await HttpOverrides.runZoned(() async { - final GlobalKey key = GlobalKey(); - await tester.pumpWidget( - MediaQuery( - data: mediaQueryData, - child: RepaintBoundary( - key: key, - child: SvgPicture.network('test.svg', - headers: const {'a': 'b'}), + final GlobalKey key = GlobalKey(); + final FakeHttpClient client = FakeHttpClient(); + await tester.pumpWidget( + MediaQuery( + data: mediaQueryData, + child: RepaintBoundary( + key: key, + child: SvgPicture.network( + 'test.svg', + headers: const {'a': 'b'}, + httpClient: client, ), ), - ); - await tester.pumpAndSettle(); - expect(fakeRequest.headers['a']!.single, 'b'); - }, createHttpClient: (SecurityContext? c) => fakeHttpClient); + ), + ); + await tester.pumpAndSettle(); + expect(client.headers['a'], 'b'); }); testWidgets('SvgPicture can be created without a MediaQuery', @@ -361,19 +352,18 @@ void main() { }); testWidgets('SvgPicture.network HTTP exception', (WidgetTester tester) async { - await HttpOverrides.runZoned(() async { - expect(() async { - fakeResponse.statusCode = 400; - await tester.pumpWidget( - MediaQuery( - data: mediaQueryData, - child: SvgPicture.network( - 'notFound.svg', - ), + expect(() async { + final http.Client client = FakeHttpClient(400); + await tester.pumpWidget( + MediaQuery( + data: mediaQueryData, + child: SvgPicture.network( + 'notFound.svg', + httpClient: client, ), - ); - }, isNotNull); - }, createHttpClient: (SecurityContext? c) => fakeHttpClient); + ), + ); + }, isNotNull); }); testWidgets('SvgPicture semantics', (WidgetTester tester) async { @@ -791,65 +781,19 @@ class FakeAssetBundle extends Fake implements AssetBundle { } } -class FakeHttpClient extends Fake implements HttpClient { - FakeHttpClient(this.request); +class FakeHttpClient extends Fake implements http.Client { + FakeHttpClient([this.statusCode = 200]); - FakeHttpClientRequest request; + final int statusCode; - @override - Future getUrl(Uri url) async => request; -} - -class FakeHttpHeaders extends Fake implements HttpHeaders { - final Map values = {}; - - @override - void add(String name, Object value, {bool preserveHeaderCase = false}) { - values[name] = value.toString(); - } + final Map headers = {}; @override - List? operator [](String key) { - return [values[key]!]; - } -} - -class FakeHttpClientRequest extends Fake implements HttpClientRequest { - FakeHttpClientRequest(this.response); - - FakeHttpClientResponse response; - - @override - final HttpHeaders headers = FakeHttpHeaders(); - - @override - Future close() async => response; -} - -class FakeHttpClientResponse extends Fake implements HttpClientResponse { - @override - int statusCode = 200; - - @override - int contentLength = svgStr.length; - - @override - HttpClientResponseCompressionState get compressionState => - HttpClientResponseCompressionState.notCompressed; - - @override - StreamSubscription> listen( - void Function(List event)? onData, { - Function? onError, - void Function()? onDone, - bool? cancelOnError, - }) { - return Stream.fromIterable([svgBytes]).listen( - onData, - onDone: onDone, - onError: onError, - cancelOnError: cancelOnError, - ); + Future get(Uri url, {Map? headers}) async { + if (headers != null) { + this.headers.addAll(headers); + } + return http.Response(svgStr, statusCode); } } From 2f7c8ca1a1c1aaedc37e77cf1560cbb0e00baa9a Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 20 Feb 2024 10:26:07 -0800 Subject: [PATCH 141/142] Relax http (#1041) * Relax http * update test package too * format; --- packages/flutter_svg/CHANGELOG.md | 4 + packages/flutter_svg/pubspec.yaml | 4 +- packages/flutter_svg_test/pubspec.yaml | 9 +- .../test/flutter_svg_test_test.dart | 90 +++---------------- 4 files changed, 26 insertions(+), 81 deletions(-) diff --git a/packages/flutter_svg/CHANGELOG.md b/packages/flutter_svg/CHANGELOG.md index ea9a4e24..d17a8ff4 100644 --- a/packages/flutter_svg/CHANGELOG.md +++ b/packages/flutter_svg/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGES +## 2.0.10+1 + +- Relax http dependency. + ## 2.0.10 - Use package:http for network requests, and allow injection of the client. diff --git a/packages/flutter_svg/pubspec.yaml b/packages/flutter_svg/pubspec.yaml index 4e07c613..a30078b6 100644 --- a/packages/flutter_svg/pubspec.yaml +++ b/packages/flutter_svg/pubspec.yaml @@ -2,12 +2,12 @@ name: flutter_svg description: An SVG rendering and widget library for Flutter, which allows painting and displaying Scalable Vector Graphics 1.1 files. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 2.0.10 +version: 2.0.10+1 dependencies: flutter: sdk: flutter - http: ^1.2.1 + http: ^1.0.0 vector_graphics: ^1.1.11 vector_graphics_codec: ^1.1.11 vector_graphics_compiler: ^1.1.11 diff --git a/packages/flutter_svg_test/pubspec.yaml b/packages/flutter_svg_test/pubspec.yaml index 42877752..54a1a426 100644 --- a/packages/flutter_svg_test/pubspec.yaml +++ b/packages/flutter_svg_test/pubspec.yaml @@ -2,17 +2,20 @@ name: flutter_svg_test description: A testing library which makes it easy to test flutter svg . Built to be used with the flutter svg package. repository: https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test issue_tracker: https://github.com/dnfield/flutter_svg/issues -version: 1.0.0 +version: 1.0.1 dependencies: flutter: sdk: flutter - flutter_svg: ^2.0.4 + flutter_svg: ^2.0.10 flutter_test: sdk: flutter +dev_dependencies: + http: ^1.0.0 + environment: sdk: '>=2.19.0-0 <4.0.0' flutter: ">=3.7.0-0" - + diff --git a/packages/flutter_svg_test/test/flutter_svg_test_test.dart b/packages/flutter_svg_test/test/flutter_svg_test_test.dart index 474b5e79..d00ce7a4 100644 --- a/packages/flutter_svg_test/test/flutter_svg_test_test.dart +++ b/packages/flutter_svg_test/test/flutter_svg_test_test.dart @@ -1,4 +1,3 @@ -import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; @@ -7,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg_test/flutter_svg_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; void main() { group('finds', () { @@ -24,12 +24,14 @@ void main() { }); testWidgets('network svg', (WidgetTester widgetTester) async { - await HttpOverrides.runZoned(() async { - final SvgPicture asset = SvgPicture.network('svg.dart'); - await widgetTester.pumpWidget(asset); + final http.Client fakeClient = _FakeHttpClient(); + final SvgPicture asset = SvgPicture.network( + 'svg.dart', + httpClient: fakeClient, + ); + await widgetTester.pumpWidget(asset); - expect(find.svg(asset.bytesLoader), findsOneWidget); - }, createHttpClient: (SecurityContext? c) => _setupFakeClient); + expect(find.svg(asset.bytesLoader), findsOneWidget); }); testWidgets('string svg', (WidgetTester widgetTester) async { @@ -68,12 +70,10 @@ void main() { }); testWidgets('network svg with url', (WidgetTester widgetTester) async { - await HttpOverrides.runZoned(() async { - const String svgUri = 'svg.dart'; - await widgetTester.pumpWidget(SvgPicture.network(svgUri)); + const String svgUri = 'svg.dart'; + await widgetTester.pumpWidget(SvgPicture.network(svgUri)); - expect(find.svgNetworkWithUrl(svgUri), findsOneWidget); - }, createHttpClient: (SecurityContext? c) => _setupFakeClient); + expect(find.svgNetworkWithUrl(svgUri), findsOneWidget); }); testWidgets('file svg wit path', (WidgetTester widgetTester) async { @@ -93,13 +93,6 @@ void main() { }); } -HttpClient get _setupFakeClient { - final _FakeHttpClientResponse fakeResponse = _FakeHttpClientResponse(); - final _FakeHttpClientRequest fakeRequest = - _FakeHttpClientRequest(fakeResponse); - return _FakeHttpClient(fakeRequest); -} - class _FakeAssetBundle extends Fake implements AssetBundle { @override Future loadString(String key, {bool cache = true}) async { @@ -112,65 +105,10 @@ class _FakeAssetBundle extends Fake implements AssetBundle { } } -class _FakeHttpClient extends Fake implements HttpClient { - _FakeHttpClient(this.request); - - _FakeHttpClientRequest request; - - @override - Future getUrl(Uri url) async => request; -} - -class _FakeHttpHeaders extends Fake implements HttpHeaders { - final Map values = {}; - - @override - void add(String name, Object value, {bool preserveHeaderCase = false}) { - values[name] = value.toString(); - } - - @override - List? operator [](String key) { - return [values[key]!]; - } -} - -class _FakeHttpClientRequest extends Fake implements HttpClientRequest { - _FakeHttpClientRequest(this.response); - - _FakeHttpClientResponse response; - - @override - final HttpHeaders headers = _FakeHttpHeaders(); - - @override - Future close() async => response; -} - -class _FakeHttpClientResponse extends Fake implements HttpClientResponse { - @override - int statusCode = 200; - - @override - int contentLength = _svgStr.length; - - @override - HttpClientResponseCompressionState get compressionState => - HttpClientResponseCompressionState.notCompressed; - +class _FakeHttpClient extends Fake implements http.Client { @override - StreamSubscription> listen( - void Function(List event)? onData, { - Function? onError, - void Function()? onDone, - bool? cancelOnError, - }) { - return Stream.fromIterable([_svgBytes]).listen( - onData, - onDone: onDone, - onError: onError, - cancelOnError: cancelOnError, - ); + Future get(Uri url, {Map? headers}) async { + return http.Response(_svgStr, 200); } } From 2c33e0aacf0da91cc37bd1bc2f507029e7b7334e Mon Sep 17 00:00:00 2001 From: Aniket Jain Date: Sun, 24 Mar 2024 02:24:26 +0530 Subject: [PATCH 142/142] update readme.md --- README.md | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8aa70ca5..44f2cbd4 100644 --- a/README.md +++ b/README.md @@ -10,27 +10,15 @@ Draw SVG files using Flutter. ## Overview -This library consists of two packages: -[**flutter_svg** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) -and -[**flutter_svg_test** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test). - -[flutter_svg](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) -provides a wrapper around Dart implementations of SVG parsing, -including SVG path data. In particular, it provides efficient `BytesLoader` -implementations for [`package:vector_graphics`](https://pub.dev/packages/vector_graphics). -The package is easier to use but not as performant as using the -`vector_graphics` and `vector_graphics_compiler` packages directly. Those -packages allow you to do ahead-of-time compilation and optimization of SVGs, -and offer some more performant rasterization strategies at runtime. - -[**flutter_svg_test** ](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test) -provides a set of functions to find images generated by `flutter_svg` in widget tests. +This library consists of two packages: [**flutter_svg**](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) and [**flutter_svg_test**](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test). + +[flutter_svg](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg) provides a wrapper around Dart implementations of SVG parsing, including SVG path data. In particular, it provides efficient `BytesLoader` implementations for [`package:vector_graphics`](https://pub.dev/packages/vector_graphics). The package is easier to use but not as performant as using the `vector_graphics` and `vector_graphics_compiler` packages directly. Those packages allow you to do ahead-of-time compilation and optimization of SVGs, and offer some more performant rasterization strategies at runtime. + +[**flutter_svg_test**](https://github.com/dnfield/flutter_svg/tree/master/packages/flutter_svg_test) provides a set of functions to find images generated by `flutter_svg` in widget tests. ## Out of scope/non-goals -- SMIL animations. That just seems crazy. I think it'll be possible to animate - the SVG but probably in a more Flutter driven way. +- SMIL animations. That just seems crazy. I think it'll be possible to animate the SVG but probably in a more Flutter-driven way. - Interactivity/events in SVG. - Any CSS support - preprocess your SVGs (perhaps with [usvg](https://github.com/RazrFalcon/resvg/tree/master/crates/usvg) or [scour](https://github.com/scour-project/scour) to get rid of all CSS?). - Scripting in SVGs