@@ -11,10 +11,15 @@ typedef ImageSourceMatcher = bool Function(
1111 dom.Element element,
1212);
1313
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+ };
1823
1924ImageSourceMatcher networkSourceMatcher ({
2025 List <String > schemas: const ["https" , "http" ],
@@ -33,8 +38,8 @@ ImageSourceMatcher networkSourceMatcher({
3338 }
3439 };
3540
36- ImageSourceMatcher assetUriMatcher () => (attributes, element) =>
37- _src (attributes) != null && _src (attributes).startsWith ("asset:" );
41+ ImageSourceMatcher assetUriMatcher () =>
42+ (attributes, element) => _src (attributes) != null && _src (attributes).startsWith ("asset:" );
3843
3944typedef ImageRender = Widget Function (
4045 RenderContext context,
@@ -43,8 +48,7 @@ typedef ImageRender = Widget Function(
4348);
4449
4550ImageRender base64ImageRender () => (context, attributes, element) {
46- final decodedImage =
47- base64.decode (_src (attributes).split ("base64," )[1 ].trim ());
51+ final decodedImage = base64.decode (_src (attributes).split ("base64," )[1 ].trim ());
4852 precacheImage (
4953 MemoryImage (decodedImage),
5054 context.buildContext,
@@ -56,8 +60,7 @@ ImageRender base64ImageRender() => (context, attributes, element) {
5660 decodedImage,
5761 frameBuilder: (ctx, child, frame, _) {
5862 if (frame == null ) {
59- return Text (_alt (attributes) ?? "" ,
60- style: context.style.generateTextStyle ());
63+ return Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
6164 }
6265 return child;
6366 },
@@ -79,8 +82,7 @@ ImageRender assetImageRender({
7982 height: height ?? _height (attributes),
8083 frameBuilder: (ctx, child, frame, _) {
8184 if (frame == null ) {
82- return Text (_alt (attributes) ?? "" ,
83- style: context.style.generateTextStyle ());
85+ return Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
8486 }
8587 return child;
8688 },
@@ -109,8 +111,7 @@ ImageRender networkImageRender({
109111 },
110112 );
111113 Completer <Size > completer = Completer ();
112- Image image =
113- Image .network (src, frameBuilder: (ctx, child, frame, _) {
114+ Image image = Image .network (src, frameBuilder: (ctx, child, frame, _) {
114115 if (frame == null ) {
115116 if (! completer.isCompleted) {
116117 completer.completeError ("error" );
@@ -124,8 +125,7 @@ ImageRender networkImageRender({
124125 image.image.resolve (ImageConfiguration ()).addListener (
125126 ImageStreamListener ((ImageInfo image, bool synchronousCall) {
126127 var myImage = image.image;
127- Size size =
128- Size (myImage.width.toDouble (), myImage.height.toDouble ());
128+ Size size = Size (myImage.width.toDouble (), myImage.height.toDouble ());
129129 if (! completer.isCompleted) {
130130 completer.complete (size);
131131 }
@@ -147,28 +147,46 @@ ImageRender networkImageRender({
147147 frameBuilder: (ctx, child, frame, _) {
148148 if (frame == null ) {
149149 return altWidget? .call (_alt (attributes)) ??
150- Text (_alt (attributes) ?? "" ,
151- style: context.style.generateTextStyle ());
150+ Text (_alt (attributes) ?? "" , style: context.style.generateTextStyle ());
152151 }
153152 return child;
154153 },
155154 );
156155 } else if (snapshot.hasError) {
157- return altWidget? .call (_alt (attributes)) ?? Text ( _alt (attributes) ?? "" ,
158- style: context.style.generateTextStyle ());
156+ return altWidget? .call (_alt (attributes)) ??
157+ Text ( _alt (attributes) ?? "" , style: context.style.generateTextStyle ());
159158 } else {
160159 return loadingWidget? .call () ?? const CircularProgressIndicator ();
161160 }
162161 },
163162 );
164163 };
165164
165+ ImageRender svgDataImageRender () => (context, attributes, element) {
166+ final dataUri = _dataUriFormat.firstMatch (_src (attributes));
167+ final data = dataUri.namedGroup ('data' );
168+ if (dataUri.namedGroup ('encoding' ) == ';base64' ) {
169+ final decodedImage = base64.decode (data.trim ());
170+ return SvgPicture .memory (
171+ decodedImage,
172+ width: _width (attributes),
173+ height: _height (attributes),
174+ );
175+ }
176+ return SvgPicture .string (Uri .decodeFull (data));
177+ };
178+
166179ImageRender svgNetworkImageRender () => (context, attributes, element) {
167- return SvgPicture .network (attributes["src" ]);
180+ return SvgPicture .network (
181+ attributes["src" ],
182+ width: _width (attributes),
183+ height: _height (attributes),
184+ );
168185 };
169186
170187final Map <ImageSourceMatcher , ImageRender > defaultImageRenders = {
171- base64DataUriMatcher (): base64ImageRender (),
188+ dataUriMatcher (mime: 'image/svg+xml' , encoding: null ): svgDataImageRender (),
189+ dataUriMatcher (): base64ImageRender (),
172190 assetUriMatcher (): assetImageRender (),
173191 networkSourceMatcher (extension : "svg" ): svgNetworkImageRender (),
174192 networkSourceMatcher (): networkImageRender (),
0 commit comments