Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
aef96b80
Commit
aef96b80
authored
Feb 02, 2016
by
krisgiesing
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1505 from krisgiesing/image_scaling
Add scale awareness to images
parents
b89d81a9
5161d120
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
118 additions
and
52 deletions
+118
-52
interactive_flex.dart
examples/rendering/interactive_flex.dart
+2
-2
box_painter.dart
packages/flutter/lib/src/painting/box_painter.dart
+2
-2
image.dart
packages/flutter/lib/src/rendering/image.dart
+17
-2
asset_bundle.dart
packages/flutter/lib/src/services/asset_bundle.dart
+8
-7
image_cache.dart
packages/flutter/lib/src/services/image_cache.dart
+16
-9
image_resource.dart
packages/flutter/lib/src/services/image_resource.dart
+11
-5
asset_vendor.dart
packages/flutter/lib/src/widgets/asset_vendor.dart
+43
-21
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+19
-4
No files found.
examples/rendering/interactive_flex.dart
View file @
aef96b80
...
...
@@ -82,8 +82,8 @@ void main() {
// Resizeable image
image
=
new
RenderImageGrow
(
null
,
new
Size
(
100.0
,
null
));
imageCache
.
load
(
"http://flutter.io/favicon.ico"
).
first
.
then
((
ui
.
Image
dartLogo
)
{
image
.
image
=
dartLogo
;
imageCache
.
load
(
"http://flutter.io/favicon.ico"
).
first
.
then
((
ImageInfo
dartLogo
)
{
image
.
image
=
dartLogo
.
image
;
});
row
.
add
(
new
RenderPadding
(
padding:
const
EdgeDims
.
all
(
10.0
),
child:
image
));
...
...
packages/flutter/lib/src/painting/box_painter.dart
View file @
aef96b80
...
...
@@ -668,10 +668,10 @@ class BackgroundImage {
_imageResource
.
removeListener
(
_handleImageChanged
);
}
void
_handleImageChanged
(
ui
.
Image
resolvedImage
)
{
void
_handleImageChanged
(
ImageInfo
resolvedImage
)
{
if
(
resolvedImage
==
null
)
return
;
_image
=
resolvedImage
;
_image
=
resolvedImage
.
image
;
final
List
<
VoidCallback
>
localListeners
=
new
List
<
VoidCallback
>.
from
(
_listeners
);
for
(
VoidCallback
listener
in
localListeners
)
...
...
packages/flutter/lib/src/rendering/image.dart
View file @
aef96b80
...
...
@@ -22,6 +22,7 @@ class RenderImage extends RenderBox {
ui
.
Image
image
,
double
width
,
double
height
,
double
scale:
1.0
,
Color
color
,
ImageFit
fit
,
FractionalOffset
alignment
,
...
...
@@ -30,6 +31,7 @@ class RenderImage extends RenderBox {
})
:
_image
=
image
,
_width
=
width
,
_height
=
height
,
_scale
=
scale
,
_color
=
color
,
_fit
=
fit
,
_alignment
=
alignment
,
...
...
@@ -76,6 +78,19 @@ class RenderImage extends RenderBox {
markNeedsLayout
();
}
/// Specifies the image's scale.
///
/// Used when determining the best display size for the image.
double
get
scale
=>
_scale
;
double
_scale
;
void
set
scale
(
double
value
)
{
assert
(
value
!=
null
);
if
(
value
==
_scale
)
return
;
_scale
=
value
;
markNeedsLayout
();
}
ColorFilter
_colorFilter
;
// Should we make the transfer mode configurable?
...
...
@@ -161,8 +176,8 @@ class RenderImage extends RenderBox {
if
(
constraints
.
isTight
||
_image
==
null
)
return
constraints
.
smallest
;
double
width
=
_image
.
width
.
toDouble
();
double
height
=
_image
.
height
.
toDouble
();
double
width
=
_image
.
width
.
toDouble
()
/
_scale
;
double
height
=
_image
.
height
.
toDouble
()
/
_scale
;
assert
(
width
>
0.0
);
assert
(
height
>
0.0
);
double
aspectRatio
=
width
/
height
;
...
...
packages/flutter/lib/src/services/asset_bundle.dart
View file @
aef96b80
...
...
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
as
ui
;
import
'dart:ui_internals'
as
internals
;
import
'dart:typed_data'
;
...
...
@@ -43,16 +42,18 @@ class NetworkAssetBundle extends AssetBundle {
}
abstract
class
CachingAssetBundle
extends
AssetBundle
{
Map
<
String
,
ImageResource
>
_imageCache
=
new
Map
<
String
,
ImageResource
>();
Map
<
String
,
Future
<
String
>>
_stringCache
=
new
Map
<
String
,
Future
<
String
>>();
final
Map
<
String
,
ImageResource
>
imageResourceCache
=
<
String
,
ImageResource
>{};
final
Map
<
String
,
Future
<
String
>>
_stringCache
=
<
String
,
Future
<
String
>>{};
Future
<
ui
.
Image
>
_
fetchImage
(
String
key
)
async
{
return
await
decodeImageFromDataPipe
(
await
load
(
key
));
Future
<
ImageInfo
>
fetchImage
(
String
key
)
async
{
return
new
ImageInfo
(
image:
await
decodeImageFromDataPipe
(
await
load
(
key
)
));
}
ImageResource
loadImage
(
String
key
)
{
return
_imag
eCache
.
putIfAbsent
(
key
,
()
{
return
new
ImageResource
(
_
fetchImage
(
key
));
return
imageResourc
eCache
.
putIfAbsent
(
key
,
()
{
return
new
ImageResource
(
fetchImage
(
key
));
});
}
...
...
packages/flutter/lib/src/services/image_cache.dart
View file @
aef96b80
...
...
@@ -3,7 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
as
ui
;
import
'dart:ui'
show
hashValues
;
import
'package:mojo/mojo/url_response.mojom.dart'
;
import
'package:quiver/collection.dart'
;
...
...
@@ -15,25 +15,32 @@ import 'image_resource.dart';
/// Implements a way to retrieve an image, for example by fetching it from the network.
/// Also used as a key in the image cache.
abstract
class
ImageProvider
{
Future
<
ui
.
Image
>
loadImage
();
Future
<
ImageInfo
>
loadImage
();
}
class
_UrlFetcher
implements
ImageProvider
{
final
String
_url
;
final
double
_scale
;
_UrlFetcher
(
this
.
_url
);
_UrlFetcher
(
this
.
_url
,
this
.
_scale
);
Future
<
ui
.
Image
>
loadImage
()
async
{
Future
<
ImageInfo
>
loadImage
()
async
{
UrlResponse
response
=
await
fetchUrl
(
_url
);
if
(
response
.
statusCode
>=
400
)
{
print
(
"Failed (
${response.statusCode}
) to load image
$_url
"
);
return
null
;
}
return
await
decodeImageFromDataPipe
(
response
.
body
);
return
new
ImageInfo
(
image:
await
decodeImageFromDataPipe
(
response
.
body
),
scale:
_scale
);
}
bool
operator
==(
other
)
=>
other
is
_UrlFetcher
&&
_url
==
other
.
_url
;
int
get
hashCode
=>
_url
.
hashCode
;
bool
operator
==(
other
)
{
return
other
is
_UrlFetcher
&&
_url
==
other
.
_url
&&
_scale
==
other
.
_scale
;
}
int
get
hashCode
=>
hashValues
(
_url
,
_scale
);
}
const
int
_kDefaultSize
=
1000
;
...
...
@@ -53,8 +60,8 @@ class _ImageCache {
});
}
ImageResource
load
(
String
url
)
{
return
loadProvider
(
new
_UrlFetcher
(
url
));
ImageResource
load
(
String
url
,
{
double
scale:
1.0
}
)
{
return
loadProvider
(
new
_UrlFetcher
(
url
,
scale
));
}
}
...
...
packages/flutter/lib/src/services/image_resource.dart
View file @
aef96b80
...
...
@@ -7,8 +7,14 @@ import 'dart:ui' as ui;
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.
typedef
void
ImageListener
(
ui
.
Image
image
);
typedef
void
ImageListener
(
ImageInfo
image
);
/// A handle to an image resource
///
...
...
@@ -21,15 +27,15 @@ class ImageResource {
}
bool
_resolved
=
false
;
Future
<
ui
.
Image
>
_futureImage
;
ui
.
Image
_image
;
Future
<
ImageInfo
>
_futureImage
;
ImageInfo
_image
;
final
List
<
ImageListener
>
_listeners
=
new
List
<
ImageListener
>();
/// The first concrete [ui.Image] object represented by this handle.
///
/// Instead of receivingly only the first image, most clients will want to
/// [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]
/// object is available. Note: If a concrete image is available currently,
...
...
@@ -50,7 +56,7 @@ class ImageResource {
_listeners
.
remove
(
listener
);
}
void
_handleImageLoaded
(
ui
.
Image
image
)
{
void
_handleImageLoaded
(
ImageInfo
image
)
{
_image
=
image
;
_resolved
=
true
;
_notifyListeners
();
...
...
packages/flutter/lib/src/widgets/asset_vendor.dart
View file @
aef96b80
...
...
@@ -29,12 +29,36 @@ class _ResolvingAssetBundle extends CachingAssetBundle {
final
AssetBundle
bundle
;
final
_AssetResolver
resolver
;
Map
<
String
,
String
>
_
keyCache
=
<
String
,
String
>{};
final
Map
<
String
,
String
>
keyCache
=
<
String
,
String
>{};
Future
<
core
.
MojoDataPipeConsumer
>
load
(
String
key
)
async
{
if
(!
_keyCache
.
containsKey
(
key
))
_keyCache
[
key
]
=
await
resolver
.
resolve
(
key
);
return
await
bundle
.
load
(
_keyCache
[
key
]);
if
(!
keyCache
.
containsKey
(
key
))
keyCache
[
key
]
=
await
resolver
.
resolve
(
key
);
return
await
bundle
.
load
(
keyCache
[
key
]);
}
}
// Asset bundle that understands how specific asset keys represent image scale.
class
_ResolutionAwareAssetBundle
extends
_ResolvingAssetBundle
{
_ResolutionAwareAssetBundle
({
AssetBundle
bundle
,
_ResolutionAwareAssetResolver
resolver
})
:
super
(
bundle:
bundle
,
resolver:
resolver
);
_ResolutionAwareAssetResolver
get
resolver
=>
super
.
resolver
;
Future
<
ImageInfo
>
fetchImage
(
String
key
)
async
{
core
.
MojoDataPipeConsumer
pipe
=
await
load
(
key
);
// At this point the key should be in our key cache, and the image
// resource should be in our image cache
double
scale
=
resolver
.
getScale
(
keyCache
[
key
]);
return
new
ImageInfo
(
image:
await
decodeImageFromDataPipe
(
pipe
),
scale:
scale
);
}
}
...
...
@@ -58,7 +82,7 @@ abstract class _VariantAssetResolver extends _AssetResolver {
Future
<
String
>
resolve
(
String
name
)
async
{
_initializer
??=
_loadManifest
();
await
_initializer
;
// If there's no asset manifest, just return the main asset
always
// If there's no asset manifest, just return the main asset
if
(
_assetManifest
==
null
)
return
name
;
// Allow references directly to variants: if the supplied name is not a
...
...
@@ -81,18 +105,15 @@ class _ResolutionAwareAssetResolver extends _VariantAssetResolver {
final
double
devicePixelRatio
;
static
final
RegExp
extractRatioRegExp
=
new
RegExp
(
r"/?(\d+(\.\d*)?)x/"
);
// We assume the main asset is designed for a device pixel ratio of 1.0
static
const
double
_naturalResolution
=
1.0
;
static
final
RegExp
_extractRatioRegExp
=
new
RegExp
(
r"/?(\d+(\.\d*)?)x/"
);
SplayTreeMap
<
double
,
String
>
_buildMapping
(
List
<
String
>
candidates
)
{
SplayTreeMap
<
double
,
String
>
result
=
new
SplayTreeMap
<
double
,
String
>();
for
(
String
candidate
in
candidates
)
{
Match
match
=
extractRatioRegExp
.
firstMatch
(
candidate
);
if
(
match
!=
null
&&
match
.
groupCount
>
0
)
{
double
resolution
=
double
.
parse
(
match
.
group
(
1
));
result
[
resolution
]
=
candidate
;
}
}
return
result
;
double
getScale
(
String
key
)
{
Match
match
=
_extractRatioRegExp
.
firstMatch
(
key
);
if
(
match
!=
null
&&
match
.
groupCount
>
0
)
return
double
.
parse
(
match
.
group
(
1
));
return
1.0
;
}
// Return the value for the key in a [SplayTreeMap] nearest the provided key.
...
...
@@ -112,9 +133,10 @@ class _ResolutionAwareAssetResolver extends _VariantAssetResolver {
}
String
chooseVariant
(
String
main
,
List
<
String
>
candidates
)
{
SplayTreeMap
<
double
,
String
>
mapping
=
_buildMapping
(
candidates
);
// We assume the main asset is designed for a device pixel ratio of 1.0
mapping
[
1.0
]
=
main
;
SplayTreeMap
<
double
,
String
>
mapping
=
new
SplayTreeMap
<
double
,
String
>();
for
(
String
candidate
in
candidates
)
mapping
[
getScale
(
candidate
)]
=
candidate
;
mapping
[
_naturalResolution
]
=
main
;
return
_findNearest
(
mapping
,
devicePixelRatio
);
}
}
...
...
@@ -172,7 +194,7 @@ class _AssetVendorState extends State<AssetVendor> {
void
initState
()
{
super
.
initState
();
_bundle
=
new
_Resol
ving
AssetBundle
(
_bundle
=
new
_Resol
utionAware
AssetBundle
(
bundle:
config
.
bundle
,
resolver:
new
_ResolutionAwareAssetResolver
(
bundle:
config
.
bundle
,
...
...
@@ -184,7 +206,7 @@ class _AssetVendorState extends State<AssetVendor> {
void
didUpdateConfig
(
AssetVendor
oldConfig
)
{
if
(
config
.
bundle
!=
oldConfig
.
bundle
||
config
.
devicePixelRatio
!=
oldConfig
.
devicePixelRatio
)
{
_bundle
=
new
_Resol
ving
AssetBundle
(
_bundle
=
new
_Resol
utionAware
AssetBundle
(
bundle:
config
.
bundle
,
resolver:
new
_ResolutionAwareAssetResolver
(
bundle:
config
.
bundle
,
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
aef96b80
...
...
@@ -1520,6 +1520,7 @@ class RawImage extends LeafRenderObjectWidget {
this
.
image
,
this
.
width
,
this
.
height
,
this
.
scale
:
1.0
,
this
.
color
,
this
.
fit
,
this
.
alignment
,
...
...
@@ -1542,6 +1543,11 @@ class RawImage extends LeafRenderObjectWidget {
/// aspect ratio.
final
double
height
;
/// Specifies the image's scale.
///
/// Used when determining the best display size for the image.
final
double
scale
;
/// If non-null, apply this color filter to the image before painting.
final
Color
color
;
...
...
@@ -1571,6 +1577,7 @@ class RawImage extends LeafRenderObjectWidget {
image:
image
,
width:
width
,
height:
height
,
scale:
scale
,
color:
color
,
fit:
fit
,
alignment:
alignment
,
...
...
@@ -1581,6 +1588,7 @@ class RawImage extends LeafRenderObjectWidget {
renderObject
.
image
=
image
;
renderObject
.
width
=
width
;
renderObject
.
height
=
height
;
renderObject
.
scale
=
scale
;
renderObject
.
color
=
color
;
renderObject
.
alignment
=
alignment
;
renderObject
.
fit
=
fit
;
...
...
@@ -1662,9 +1670,9 @@ class _ImageListenerState extends State<RawImageResource> {
config
.
image
.
addListener
(
_handleImageChanged
);
}
ui
.
Image
_resolvedImage
;
ImageInfo
_resolvedImage
;
void
_handleImageChanged
(
ui
.
Image
resolvedImage
)
{
void
_handleImageChanged
(
ImageInfo
resolvedImage
)
{
setState
(()
{
_resolvedImage
=
resolvedImage
;
});
...
...
@@ -1684,9 +1692,10 @@ class _ImageListenerState extends State<RawImageResource> {
Widget
build
(
BuildContext
context
)
{
return
new
RawImage
(
image:
_resolvedImage
,
image:
_resolvedImage
?.
image
,
width:
config
.
width
,
height:
config
.
height
,
scale:
_resolvedImage
==
null
?
1.0
:
_resolvedImage
.
scale
,
color:
config
.
color
,
fit:
config
.
fit
,
alignment:
config
.
alignment
,
...
...
@@ -1703,6 +1712,7 @@ class NetworkImage extends StatelessComponent {
this
.
src
,
this
.
width
,
this
.
height
,
this
.
scale
:
1.0
,
this
.
color
,
this
.
fit
,
this
.
alignment
,
...
...
@@ -1725,6 +1735,11 @@ class NetworkImage extends StatelessComponent {
/// aspect ratio.
final
double
height
;
/// Specifies the image's scale.
///
/// Used when determining the best display size for the image.
final
double
scale
;
/// If non-null, apply this color filter to the image before painting.
final
Color
color
;
...
...
@@ -1752,7 +1767,7 @@ class NetworkImage extends StatelessComponent {
Widget
build
(
BuildContext
context
)
{
return
new
RawImageResource
(
image:
imageCache
.
load
(
src
),
image:
imageCache
.
load
(
src
,
scale:
scale
),
width:
width
,
height:
height
,
color:
color
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment