Commit f52a1e0a authored by Kris Giesing's avatar Kris Giesing

Associate scale with image more strongly in image resources

parent b81f3f8b
...@@ -668,10 +668,10 @@ class BackgroundImage { ...@@ -668,10 +668,10 @@ class BackgroundImage {
_imageResource.removeListener(_handleImageChanged); _imageResource.removeListener(_handleImageChanged);
} }
void _handleImageChanged(ui.Image resolvedImage) { void _handleImageChanged(ImageInfo resolvedImage) {
if (resolvedImage == null) if (resolvedImage == null)
return; return;
_image = resolvedImage; _image = resolvedImage.image;
final List<VoidCallback> localListeners = final List<VoidCallback> localListeners =
new List<VoidCallback>.from(_listeners); new List<VoidCallback>.from(_listeners);
for (VoidCallback listener in localListeners) for (VoidCallback listener in localListeners)
......
...@@ -22,7 +22,7 @@ class RenderImage extends RenderBox { ...@@ -22,7 +22,7 @@ class RenderImage extends RenderBox {
ui.Image image, ui.Image image,
double width, double width,
double height, double height,
double scale, double scale: 1.0,
Color color, Color color,
ImageFit fit, ImageFit fit,
FractionalOffset alignment, FractionalOffset alignment,
...@@ -84,6 +84,7 @@ class RenderImage extends RenderBox { ...@@ -84,6 +84,7 @@ class RenderImage extends RenderBox {
double get scale => _scale; double get scale => _scale;
double _scale; double _scale;
void set scale (double value) { void set scale (double value) {
assert(value != null);
if (value == _scale) if (value == _scale)
return; return;
_scale = value; _scale = value;
...@@ -175,9 +176,8 @@ class RenderImage extends RenderBox { ...@@ -175,9 +176,8 @@ class RenderImage extends RenderBox {
if (constraints.isTight || _image == null) if (constraints.isTight || _image == null)
return constraints.smallest; return constraints.smallest;
double scale = _scale ?? 1.0; double width = _image.width.toDouble() / _scale;
double width = _image.width.toDouble() / scale; double height = _image.height.toDouble() / _scale;
double height = _image.height.toDouble() / scale;
assert(width > 0.0); assert(width > 0.0);
assert(height > 0.0); assert(height > 0.0);
double aspectRatio = width / height; double aspectRatio = width / height;
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui;
import 'dart:ui_internals' as internals; import 'dart:ui_internals' as internals;
import 'dart:typed_data'; import 'dart:typed_data';
...@@ -48,8 +47,8 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -48,8 +47,8 @@ abstract class CachingAssetBundle extends AssetBundle {
final Map<String, Future<String>> _stringCache = final Map<String, Future<String>> _stringCache =
new Map<String, Future<String>>(); new Map<String, Future<String>>();
Future<ui.Image> fetchImage(String key) async { Future<ImageInfo> fetchImage(String key) async {
return await decodeImageFromDataPipe(await load(key)); return new ImageInfo(image: await decodeImageFromDataPipe(await load(key)));
} }
ImageResource loadImage(String key) { ImageResource loadImage(String key) {
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui;
import 'package:mojo/mojo/url_response.mojom.dart'; import 'package:mojo/mojo/url_response.mojom.dart';
import 'package:quiver/collection.dart'; import 'package:quiver/collection.dart';
...@@ -15,7 +14,7 @@ import 'image_resource.dart'; ...@@ -15,7 +14,7 @@ import 'image_resource.dart';
/// Implements a way to retrieve an image, for example by fetching it from the network. /// Implements a way to retrieve an image, for example by fetching it from the network.
/// Also used as a key in the image cache. /// Also used as a key in the image cache.
abstract class ImageProvider { abstract class ImageProvider {
Future<ui.Image> loadImage(); Future<ImageInfo> loadImage();
} }
class _UrlFetcher implements ImageProvider { class _UrlFetcher implements ImageProvider {
...@@ -23,13 +22,13 @@ class _UrlFetcher implements ImageProvider { ...@@ -23,13 +22,13 @@ class _UrlFetcher implements ImageProvider {
_UrlFetcher(this._url); _UrlFetcher(this._url);
Future<ui.Image> loadImage() async { Future<ImageInfo> loadImage() async {
UrlResponse response = await fetchUrl(_url); UrlResponse response = await fetchUrl(_url);
if (response.statusCode >= 400) { if (response.statusCode >= 400) {
print("Failed (${response.statusCode}) to load image $_url"); print("Failed (${response.statusCode}) to load image $_url");
return null; return null;
} }
return await decodeImageFromDataPipe(response.body); return new ImageInfo(image: await decodeImageFromDataPipe(response.body));
} }
bool operator ==(other) => other is _UrlFetcher && _url == other._url; bool operator ==(other) => other is _UrlFetcher && _url == other._url;
......
...@@ -7,8 +7,14 @@ import 'dart:ui' as ui; ...@@ -7,8 +7,14 @@ import 'dart:ui' as ui;
import 'print.dart'; import 'print.dart';
class ImageInfo {
ImageInfo({ this.image, this.scale: 1.0 });
final ui.Image image;
final double scale;
}
/// A callback for when the image is available. /// A callback for when the image is available.
typedef void ImageListener(ui.Image image); typedef void ImageListener(ImageInfo image);
/// A handle to an image resource /// A handle to an image resource
/// ///
...@@ -16,21 +22,20 @@ typedef void ImageListener(ui.Image image); ...@@ -16,21 +22,20 @@ typedef void ImageListener(ui.Image image);
/// image object might change over time, either because the image is animating /// image object might change over time, either because the image is animating
/// or because the underlying image resource was mutated. /// or because the underlying image resource was mutated.
class ImageResource { class ImageResource {
ImageResource(this._futureImage, { this.scale : 1.0 }) { ImageResource(this._futureImage) {
_futureImage.then(_handleImageLoaded, onError: (exception, stack) => _handleImageError('Failed to load image:', exception, stack)); _futureImage.then(_handleImageLoaded, onError: (exception, stack) => _handleImageError('Failed to load image:', exception, stack));
} }
bool _resolved = false; bool _resolved = false;
Future<ui.Image> _futureImage; Future<ImageInfo> _futureImage;
ui.Image _image; ImageInfo _image;
double scale;
final List<ImageListener> _listeners = new List<ImageListener>(); final List<ImageListener> _listeners = new List<ImageListener>();
/// The first concrete [ui.Image] object represented by this handle. /// The first concrete [ui.Image] object represented by this handle.
/// ///
/// Instead of receivingly only the first image, most clients will want to /// Instead of receivingly only the first image, most clients will want to
/// [addListener] to be notified whenever a a concrete image is available. /// [addListener] to be notified whenever a a concrete image is available.
Future<ui.Image> get first => _futureImage; Future<ImageInfo> get first => _futureImage;
/// Adds a listener callback that is called whenever a concrete [ui.Image] /// Adds a listener callback that is called whenever a concrete [ui.Image]
/// object is available. Note: If a concrete image is available currently, /// object is available. Note: If a concrete image is available currently,
...@@ -51,7 +56,7 @@ class ImageResource { ...@@ -51,7 +56,7 @@ class ImageResource {
_listeners.remove(listener); _listeners.remove(listener);
} }
void _handleImageLoaded(ui.Image image) { void _handleImageLoaded(ImageInfo image) {
_image = image; _image = image;
_resolved = true; _resolved = true;
_notifyListeners(); _notifyListeners();
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:collection'; import 'dart:collection';
import 'dart:convert'; import 'dart:convert';
import 'dart:ui' as ui;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:mojo/core.dart' as core; import 'package:mojo/core.dart' as core;
...@@ -51,13 +50,15 @@ class _ResolutionAwareAssetBundle extends _ResolvingAssetBundle { ...@@ -51,13 +50,15 @@ class _ResolutionAwareAssetBundle extends _ResolvingAssetBundle {
_ResolutionAwareAssetResolver get resolver => super.resolver; _ResolutionAwareAssetResolver get resolver => super.resolver;
Future<ui.Image> fetchImage(String key) async { Future<ImageInfo> fetchImage(String key) async {
core.MojoDataPipeConsumer pipe = await load(key); core.MojoDataPipeConsumer pipe = await load(key);
// At this point the key should be in our key cache, and the image // At this point the key should be in our key cache, and the image
// resource should be in our image cache // resource should be in our image cache
double scale = resolver.getScale(keyCache[key]); double scale = resolver.getScale(keyCache[key]);
imageResourceCache[key].scale = scale; return new ImageInfo(
return await decodeImageFromDataPipe(pipe); image: await decodeImageFromDataPipe(pipe),
scale: scale
);
} }
} }
......
...@@ -1508,7 +1508,7 @@ class RawImage extends LeafRenderObjectWidget { ...@@ -1508,7 +1508,7 @@ class RawImage extends LeafRenderObjectWidget {
this.image, this.image,
this.width, this.width,
this.height, this.height,
this.scale, this.scale: 1.0,
this.color, this.color,
this.fit, this.fit,
this.alignment, this.alignment,
...@@ -1658,16 +1658,11 @@ class _ImageListenerState extends State<RawImageResource> { ...@@ -1658,16 +1658,11 @@ class _ImageListenerState extends State<RawImageResource> {
config.image.addListener(_handleImageChanged); config.image.addListener(_handleImageChanged);
} }
// Note, we remember the resolved image and the scale together. If the ImageInfo _resolvedImage;
// source image resource is updated, we shouldn't grab its scale until
// it provides the associated resolved image.
ui.Image _resolvedImage;
double _scale;
void _handleImageChanged(ui.Image resolvedImage) { void _handleImageChanged(ImageInfo resolvedImage) {
setState(() { setState(() {
_resolvedImage = resolvedImage; _resolvedImage = resolvedImage;
_scale = config.image.scale;
}); });
} }
...@@ -1685,10 +1680,10 @@ class _ImageListenerState extends State<RawImageResource> { ...@@ -1685,10 +1680,10 @@ class _ImageListenerState extends State<RawImageResource> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new RawImage( return new RawImage(
image: _resolvedImage, image: _resolvedImage?.image,
width: config.width, width: config.width,
height: config.height, height: config.height,
scale: _scale, scale: _resolvedImage == null ? 1.0 : _resolvedImage.scale,
color: config.color, color: config.color,
fit: config.fit, fit: config.fit,
alignment: config.alignment, alignment: config.alignment,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment