@@ -1492,9 +1492,6 @@ class SvgParser {
14921492 String ? id,
14931493 ) {
14941494 final String ? rawStroke = attributeMap['stroke' ];
1495- if (rawStroke == 'none' ) {
1496- return SvgStrokeAttributes .none;
1497- }
14981495
14991496 final String ? rawStrokeOpacity = attributeMap['stroke-opacity' ];
15001497 double ? opacity;
@@ -1546,7 +1543,9 @@ class SvgParser {
15461543 return SvgStrokeAttributes ._(
15471544 _definitions,
15481545 shaderId: shaderId,
1549- color: color,
1546+ color: rawStroke == 'none'
1547+ ? const ColorOrNone .none ()
1548+ : ColorOrNone .color (color),
15501549 cap: _parseCap (rawStrokeCap, null ),
15511550 join: _parseJoin (rawLineJoin, null ),
15521551 miterLimit: parseDouble (rawMiterLimit),
@@ -1566,10 +1565,6 @@ class SvgParser {
15661565 ) {
15671566 final String rawFill = attributeMap['fill' ] ?? '' ;
15681567
1569- if (rawFill == 'none' ) {
1570- return SvgFillAttributes .none;
1571- }
1572-
15731568 final String ? rawFillOpacity = attributeMap['fill-opacity' ];
15741569 double ? opacity;
15751570 if (rawFillOpacity != null ) {
@@ -1589,7 +1584,7 @@ class SvgParser {
15891584 }
15901585 return SvgFillAttributes ._(
15911586 _definitions,
1592- color: const Color (0xFFFFFFFF ),
1587+ color: const ColorOrNone . color ( Color (0xFFFFFFFF ) ),
15931588 shaderId: rawFill,
15941589 hasPattern: hasPattern,
15951590 opacity: opacity,
@@ -1605,7 +1600,9 @@ class SvgParser {
16051600
16061601 return SvgFillAttributes ._(
16071602 _definitions,
1608- color: fillColor,
1603+ color: rawFill == 'none'
1604+ ? const ColorOrNone .none ()
1605+ : ColorOrNone .color (fillColor),
16091606 opacity: opacity,
16101607 );
16111608 }
@@ -1640,7 +1637,9 @@ class SvgParser {
16401637 dx: DoubleOrPercentage .fromString (rawDx),
16411638 dy: DoubleOrPercentage .fromString (rawDy),
16421639 href: attributeMap['href' ],
1643- color: color,
1640+ color: attributeMap['color' ]? .toLowerCase () == 'none'
1641+ ? const ColorOrNone .none ()
1642+ : ColorOrNone .color (color),
16441643 stroke: _parseStrokeAttributes (
16451644 attributeMap,
16461645 opacity,
@@ -1822,7 +1821,7 @@ class SvgAttributes {
18221821 this .id,
18231822 this .href,
18241823 this .transform = AffineMatrix .identity,
1825- this .color,
1824+ this .color = const ColorOrNone . color () ,
18261825 this .stroke,
18271826 this .fill,
18281827 this .fillRule = PathFillType .nonZero,
@@ -1935,7 +1934,7 @@ class SvgAttributes {
19351934 /// [stroke] .
19361935 ///
19371936 /// https://www.w3.org/TR/SVG11/color.html#ColorProperty
1938- final Color ? color;
1937+ final ColorOrNone color;
19391938
19401939 /// The stroking properties of this element.
19411940 final SvgStrokeAttributes ? stroke;
@@ -2052,7 +2051,7 @@ class SvgAttributes {
20522051 id: newRaw['id' ],
20532052 href: newRaw['href' ],
20542053 transform: transformOverride ?? transform,
2055- color: color ?? parent.color,
2054+ color: color. _applyParent ( parent.color) ,
20562055 stroke: stroke? .applyParent (parent.stroke) ?? parent.stroke,
20572056 fill: fill? .applyParent (parent.fill) ?? parent.fill,
20582057 fillRule: fillRule,
@@ -2123,7 +2122,7 @@ class DoubleOrPercentage {
21232122class SvgStrokeAttributes {
21242123 const SvgStrokeAttributes ._(
21252124 this ._definitions, {
2126- this .color,
2125+ this .color = const ColorOrNone . color () ,
21272126 this .shaderId,
21282127 this .join,
21292128 this .cap,
@@ -2135,15 +2134,11 @@ class SvgStrokeAttributes {
21352134 this .opacity,
21362135 });
21372136
2138- /// Specifies that strokes should not be drawn, even if they otherwise would
2139- /// be.
2140- static const SvgStrokeAttributes none = SvgStrokeAttributes ._(null );
2141-
21422137 final _Resolver ? _definitions;
21432138
21442139 /// The color to use for stroking. Does _not_ include the [opacity] value. Only
21452140 /// opacity is used if the [shaderId] is not null.
2146- final Color ? color;
2141+ final ColorOrNone color;
21472142
21482143 /// The literal reference to a shader defined elsewhere.
21492144 final String ? shaderId;
@@ -2195,7 +2190,7 @@ class SvgStrokeAttributes {
21952190 SvgStrokeAttributes applyParent (SvgStrokeAttributes ? parent) {
21962191 return SvgStrokeAttributes ._(
21972192 _definitions,
2198- color: color ?? parent? .color,
2193+ color: color. _applyParent ( parent? .color) ,
21992194 shaderId: shaderId ?? parent? .shaderId,
22002195 join: join ?? parent? .join,
22012196 cap: cap ?? parent? .cap,
@@ -2214,7 +2209,9 @@ class SvgStrokeAttributes {
22142209 /// Returns null if this is [none] .
22152210 Stroke ? toStroke (Rect shaderBounds, AffineMatrix transform) {
22162211 // A zero width stroke is a hairline in Flutter, but a nop in SVG.
2217- if (color == null && hasPattern == null && shaderId == null || width == 0 ) {
2212+ if (color.isNone ||
2213+ (color.color == null && hasPattern == null && shaderId == null ||
2214+ width == 0 )) {
22182215 return null ;
22192216 }
22202217
@@ -2242,7 +2239,7 @@ class SvgStrokeAttributes {
22422239 }
22432240
22442241 return Stroke (
2245- color: color! .withOpacity (opacity ?? 1.0 ),
2242+ color: color.color ! .withOpacity (opacity ?? 1.0 ),
22462243 shader: shader,
22472244 join: join,
22482245 cap: cap,
@@ -2257,20 +2254,17 @@ class SvgFillAttributes {
22572254 /// Create a new [SvgFillAttributes] ;
22582255 const SvgFillAttributes ._(
22592256 this ._definitions, {
2260- this .color,
2257+ this .color = const ColorOrNone . color () ,
22612258 this .shaderId,
22622259 this .hasPattern,
22632260 this .opacity,
22642261 });
22652262
2266- /// Specifies that fills should not be drawn, even if they otherwise would be.
2267- static const SvgFillAttributes none = SvgFillAttributes ._(null );
2268-
22692263 final _Resolver ? _definitions;
22702264
22712265 /// The color to use for filling. Does _not_ include the [opacity] value. Only
22722266 /// opacity is used if the [shaderId] is not null.
2273- final Color ? color;
2267+ final ColorOrNone color;
22742268
22752269 /// The opacity to apply to a default color, if [color] is null.
22762270 final double ? opacity;
@@ -2298,7 +2292,7 @@ class SvgFillAttributes {
22982292 SvgFillAttributes applyParent (SvgFillAttributes ? parent) {
22992293 return SvgFillAttributes ._(
23002294 _definitions,
2301- color: color ?? parent? .color,
2295+ color: color. _applyParent ( parent? .color) ,
23022296 shaderId: shaderId ?? parent? .shaderId,
23032297 hasPattern: hasPattern ?? parent? .hasPattern,
23042298 opacity: opacity ?? parent? .opacity,
@@ -2314,7 +2308,10 @@ class SvgFillAttributes {
23142308 AffineMatrix transform, {
23152309 Color ? defaultColor,
23162310 }) {
2317- final Color ? resolvedColor = color? .withOpacity (opacity ?? 1.0 ) ??
2311+ if (color.isNone) {
2312+ return null ;
2313+ }
2314+ final Color ? resolvedColor = color.color? .withOpacity (opacity ?? 1.0 ) ??
23182315 defaultColor? .withOpacity (opacity ?? 1.0 );
23192316 if (resolvedColor == null ) {
23202317 return null ;
@@ -2338,4 +2335,55 @@ class SvgFillAttributes {
23382335
23392336 return Fill (color: resolvedColor, shader: shader);
23402337 }
2338+
2339+ @override
2340+ String toString () {
2341+ return 'SvgFillAttributes('
2342+ 'definitions: $_definitions , '
2343+ 'color: $color , '
2344+ 'shaderId: $shaderId , '
2345+ 'hasPattern: $hasPattern , '
2346+ 'oapctiy: $opacity )' ;
2347+ }
2348+ }
2349+
2350+ /// Represents a color for filling or stroking.
2351+ ///
2352+ /// If the [color] is not null, [isNone] is false.
2353+ ///
2354+ /// If the [color] is null and [isNone] is false, color should be inherited from
2355+ /// the parent or defaulted as per the SVG specification.
2356+ ///
2357+ /// If the [color] is null and [isNone] is true, inheritence should be cleared
2358+ /// and no painting should happen.
2359+ class ColorOrNone {
2360+ /// See [ColorOrNone] .
2361+ const ColorOrNone .none ()
2362+ : isNone = true ,
2363+ color = null ;
2364+
2365+ /// See [ColorOrNone] .
2366+ const ColorOrNone .color ([this .color]) : isNone = false ;
2367+
2368+ /// Whether to paint anything.
2369+ final bool isNone;
2370+
2371+ /// The color to use when painting. If null and [isNone] is false, inherit
2372+ /// from parent.
2373+ final Color ? color;
2374+
2375+ ColorOrNone _applyParent (ColorOrNone ? parent) {
2376+ if (parent == null || isNone) {
2377+ return this ;
2378+ }
2379+
2380+ if (parent.isNone && color == null ) {
2381+ return const ColorOrNone .none ();
2382+ }
2383+
2384+ return ColorOrNone .color (color ?? parent.color);
2385+ }
2386+
2387+ @override
2388+ String toString () => isNone ? '"none"' : (color? .toString () ?? 'null' );
23412389}
0 commit comments