@@ -11,10 +11,15 @@ typedef ImageSourceMatcher = bool Function(
11
11
dom.Element ? element,
12
12
);
13
13
14
- ImageSourceMatcher base64DataUriMatcher () => (attributes, element) =>
15
- _src (attributes) != null &&
16
- _src (attributes)! .startsWith ("data:image" ) &&
17
- _src (attributes)! .contains ("base64," );
14
+ final _dataUriFormat = RegExp ("^(?<scheme>data):(?<mime>image\/ [\\ w\+\-\. ]+)(?<encoding>;base64)?\, (?<data>.*)" );
15
+
16
+ ImageSourceMatcher dataUriMatcher ({String ? encoding = 'base64' , String ? mime}) => (attributes, element) {
17
+ if (_src (attributes) == null ) return false ;
18
+ final dataUri = _dataUriFormat.firstMatch (_src (attributes)! );
19
+ return dataUri != null &&
20
+ (mime == null || dataUri.namedGroup ('mime' ) == mime) &&
21
+ (encoding == null || dataUri.namedGroup ('encoding' ) == ';$encoding ' );
22
+ };
18
23
19
24
ImageSourceMatcher networkSourceMatcher ({
20
25
List <String > schemas: const ["https" , "http" ],
@@ -56,8 +61,7 @@ ImageRender base64ImageRender() => (context, attributes, element) {
56
61
decodedImage,
57
62
frameBuilder: (ctx, child, frame, _) {
58
63
if (frame == null ) {
59
- return Text (_alt (attributes) ?? "" ,
60
- style: context.style.generateTextStyle ());
64
+ return Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
61
65
}
62
66
return child;
63
67
},
@@ -79,8 +83,7 @@ ImageRender assetImageRender({
79
83
height: height ?? _height (attributes),
80
84
frameBuilder: (ctx, child, frame, _) {
81
85
if (frame == null ) {
82
- return Text (_alt (attributes) ?? "" ,
83
- style: context.style.generateTextStyle ());
86
+ return Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
84
87
}
85
88
return child;
86
89
},
@@ -109,8 +112,7 @@ ImageRender networkImageRender({
109
112
},
110
113
);
111
114
Completer <Size > completer = Completer ();
112
- Image image =
113
- Image .network (src, frameBuilder: (ctx, child, frame, _) {
115
+ Image image = Image .network (src, frameBuilder: (ctx, child, frame, _) {
114
116
if (frame == null ) {
115
117
if (! completer.isCompleted) {
116
118
completer.completeError ("error" );
@@ -124,8 +126,7 @@ ImageRender networkImageRender({
124
126
image.image.resolve (ImageConfiguration ()).addListener (
125
127
ImageStreamListener ((ImageInfo image, bool synchronousCall) {
126
128
var myImage = image.image;
127
- Size size =
128
- Size (myImage.width.toDouble (), myImage.height.toDouble ());
129
+ Size size = Size (myImage.width.toDouble (), myImage.height.toDouble ());
129
130
if (! completer.isCompleted) {
130
131
completer.complete (size);
131
132
}
@@ -147,28 +148,47 @@ ImageRender networkImageRender({
147
148
frameBuilder: (ctx, child, frame, _) {
148
149
if (frame == null ) {
149
150
return altWidget? .call (_alt (attributes)) ??
150
- Text (_alt (attributes) ?? "" ,
151
- style: context.style.generateTextStyle ());
151
+ Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
152
152
}
153
153
return child;
154
154
},
155
155
);
156
156
} else if (snapshot.hasError) {
157
- return altWidget? .call (_alt (attributes)) ?? Text ( _alt (attributes) ?? "" ,
158
- style: context.style.generateTextStyle ());
157
+ return altWidget? .call (_alt (attributes)) ??
158
+ Text ( _alt (attributes) ?? "" , style: context.style.generateTextStyle ());
159
159
} else {
160
160
return loadingWidget? .call () ?? const CircularProgressIndicator ();
161
161
}
162
162
},
163
163
);
164
164
};
165
165
166
+ ImageRender svgDataImageRender () => (context, attributes, element) {
167
+ final dataUri = _dataUriFormat.firstMatch (_src (attributes)! );
168
+ final data = dataUri? .namedGroup ('data' );
169
+ if (data == null ) return null ;
170
+ if (dataUri? .namedGroup ('encoding' ) == ';base64' ) {
171
+ final decodedImage = base64.decode (data.trim ());
172
+ return SvgPicture .memory (
173
+ decodedImage,
174
+ width: _width (attributes),
175
+ height: _height (attributes),
176
+ );
177
+ }
178
+ return SvgPicture .string (Uri .decodeFull (data));
179
+ };
180
+
166
181
ImageRender svgNetworkImageRender () => (context, attributes, element) {
167
- return SvgPicture .network (_src (attributes)! );
182
+ return SvgPicture .network (
183
+ attributes["src" ]! ,
184
+ width: _width (attributes),
185
+ height: _height (attributes),
186
+ );
168
187
};
169
188
170
189
final Map <ImageSourceMatcher , ImageRender > defaultImageRenders = {
171
- base64DataUriMatcher (): base64ImageRender (),
190
+ dataUriMatcher (mime: 'image/svg+xml' , encoding: null ): svgDataImageRender (),
191
+ dataUriMatcher (): base64ImageRender (),
172
192
assetUriMatcher (): assetImageRender (),
173
193
networkSourceMatcher (extension : "svg" ): svgNetworkImageRender (),
174
194
networkSourceMatcher (): networkImageRender (),
0 commit comments