1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// @docImport 'dart:ui';
6///
7/// @docImport 'package:flutter/widgets.dart';
8/// @docImport 'package:flutter_driver/driver_extension.dart';
9library;
10
11import 'dart:ui' as ui;
12import 'package:flutter/foundation.dart';
13import 'package:flutter/services.dart' show ServicesBinding;
14
15import 'image_cache.dart';
16import 'shader_warm_up.dart';
17
18/// Binding for the painting library.
19///
20/// Hooks into the cache eviction logic to clear the image cache.
21///
22/// Requires the [ServicesBinding] to be mixed in earlier.
23mixin PaintingBinding on BindingBase, ServicesBinding {
24 @override
25 void initInstances() {
26 super.initInstances();
27 _instance = this;
28 _imageCache = createImageCache();
29 shaderWarmUp?.execute();
30 }
31
32 /// The current [PaintingBinding], if one has been created.
33 ///
34 /// Provides access to the features exposed by this mixin. The binding must
35 /// be initialized before using this getter; this is typically done by calling
36 /// [runApp] or [WidgetsFlutterBinding.ensureInitialized].
37 static PaintingBinding get instance => BindingBase.checkInstance(_instance);
38 static PaintingBinding? _instance;
39
40 /// [ShaderWarmUp] instance to be executed during [initInstances].
41 ///
42 /// Defaults to `null`, meaning no shader warm-up is done. Some platforms may
43 /// not support shader warm-up before at least one frame has been displayed.
44 ///
45 /// If the application has scenes that require the compilation of complex
46 /// shaders, it may cause jank in the middle of an animation or interaction.
47 /// In that case, setting [shaderWarmUp] to a custom [ShaderWarmUp] before
48 /// creating the binding (usually before [runApp] for normal Flutter apps, and
49 /// before [enableFlutterDriverExtension] for Flutter driver tests) may help
50 /// if that object paints the difficult scene in its
51 /// [ShaderWarmUp.warmUpOnCanvas] method, as this allows Flutter to
52 /// pre-compile and cache the required shaders during startup.
53 ///
54 /// Currently the warm-up happens synchronously on the raster thread which
55 /// means the rendering of the first frame on the raster thread will be
56 /// postponed until the warm-up is finished.
57 ///
58 /// The warm up is only costly (100ms-200ms, depending on the shaders to
59 /// compile) during the first run after the installation or a data wipe. The
60 /// warm up does not block the platform thread so there should be no
61 /// "Application Not Responding" warning.
62 ///
63 /// If this is null, no shader warm-up is executed.
64 ///
65 /// See also:
66 ///
67 /// * [ShaderWarmUp], the interface for implementing custom warm-up scenes.
68 /// * <https://docs.flutter.dev/perf/shader>
69 static ShaderWarmUp? shaderWarmUp;
70
71 /// The singleton that implements the Flutter framework's image cache.
72 ///
73 /// The cache is used internally by [ImageProvider] and should generally not
74 /// be accessed directly.
75 ///
76 /// The image cache is created during startup by the [createImageCache]
77 /// method.
78 ImageCache get imageCache => _imageCache;
79 late ImageCache _imageCache;
80
81 /// Creates the [ImageCache] singleton (accessible via [imageCache]).
82 ///
83 /// This method can be overridden to provide a custom image cache.
84 @protected
85 ImageCache createImageCache() => ImageCache();
86
87 /// Calls through to [dart:ui.instantiateImageCodecFromBuffer] from [ImageCache].
88 ///
89 /// The [buffer] parameter should be an [ui.ImmutableBuffer] instance which can
90 /// be acquired from [ui.ImmutableBuffer.fromUint8List] or [ui.ImmutableBuffer.fromAsset].
91 ///
92 /// The [cacheWidth] and [cacheHeight] parameters, when specified, indicate
93 /// the size to decode the image to.
94 ///
95 /// Both [cacheWidth] and [cacheHeight] must be positive values greater than
96 /// or equal to 1, or null. It is valid to specify only one of `cacheWidth`
97 /// and [cacheHeight] with the other remaining null, in which case the omitted
98 /// dimension will be scaled to maintain the aspect ratio of the original
99 /// dimensions. When both are null or omitted, the image will be decoded at
100 /// its native resolution.
101 ///
102 /// The [allowUpscaling] parameter determines whether the `cacheWidth` or
103 /// [cacheHeight] parameters are clamped to the intrinsic width and height of
104 /// the original image. By default, the dimensions are clamped to avoid
105 /// unnecessary memory usage for images. Callers that wish to display an image
106 /// above its native resolution should prefer scaling the canvas the image is
107 /// drawn into.
108 @Deprecated(
109 'Use instantiateImageCodecWithSize instead. '
110 'This feature was deprecated after v3.7.0-1.4.pre.',
111 )
112 Future<ui.Codec> instantiateImageCodecFromBuffer(
113 ui.ImmutableBuffer buffer, {
114 int? cacheWidth,
115 int? cacheHeight,
116 bool allowUpscaling = false,
117 }) {
118 assert(cacheWidth == null || cacheWidth > 0);
119 assert(cacheHeight == null || cacheHeight > 0);
120 return ui.instantiateImageCodecFromBuffer(
121 buffer,
122 targetWidth: cacheWidth,
123 targetHeight: cacheHeight,
124 allowUpscaling: allowUpscaling,
125 );
126 }
127
128 /// Calls through to [dart:ui.instantiateImageCodecWithSize] from [ImageCache].
129 ///
130 /// The [buffer] parameter should be an [ui.ImmutableBuffer] instance which can
131 /// be acquired from [ui.ImmutableBuffer.fromUint8List] or
132 /// [ui.ImmutableBuffer.fromAsset].
133 ///
134 /// The [getTargetSize] parameter, when specified, will be invoked and passed
135 /// the image's intrinsic size to determine the size to decode the image to.
136 /// The width and the height of the size it returns must be positive values
137 /// greater than or equal to 1, or null. It is valid to return a [TargetImageSize]
138 /// that specifies only one of `width` and `height` with the other remaining
139 /// null, in which case the omitted dimension will be scaled to maintain the
140 /// aspect ratio of the original dimensions. When both are null or omitted,
141 /// the image will be decoded at its native resolution (as will be the case if
142 /// the [getTargetSize] parameter is omitted).
143 Future<ui.Codec> instantiateImageCodecWithSize(
144 ui.ImmutableBuffer buffer, {
145 ui.TargetImageSizeCallback? getTargetSize,
146 }) {
147 return ui.instantiateImageCodecWithSize(buffer, getTargetSize: getTargetSize);
148 }
149
150 @override
151 void evict(String asset) {
152 super.evict(asset);
153 imageCache.clear();
154 imageCache.clearLiveImages();
155 }
156
157 @override
158 void handleMemoryPressure() {
159 super.handleMemoryPressure();
160 imageCache.clear();
161 }
162
163 /// Listenable that notifies when the available fonts on the system have
164 /// changed.
165 ///
166 /// System fonts can change when the system installs or removes new font. To
167 /// correctly reflect the change, it is important to relayout text related
168 /// widgets when this happens.
169 ///
170 /// Objects that show text and/or measure text (e.g. via [TextPainter] or
171 /// [Paragraph]) should listen to this and redraw/remeasure.
172 Listenable get systemFonts => _systemFonts;
173 final _SystemFontsNotifier _systemFonts = _SystemFontsNotifier();
174
175 @override
176 Future<void> handleSystemMessage(Object systemMessage) async {
177 await super.handleSystemMessage(systemMessage);
178 final Map<String, dynamic> message = systemMessage as Map<String, dynamic>;
179 final String type = message['type'] as String;
180 switch (type) {
181 case 'fontsChange':
182 _systemFonts.notifyListeners();
183 }
184 return;
185 }
186}
187
188class _SystemFontsNotifier extends Listenable {
189 final Set<VoidCallback> _systemFontsCallbacks = <VoidCallback>{};
190
191 void notifyListeners() {
192 for (final VoidCallback callback in _systemFontsCallbacks) {
193 callback();
194 }
195 }
196
197 @override
198 void addListener(VoidCallback listener) {
199 _systemFontsCallbacks.add(listener);
200 }
201
202 @override
203 void removeListener(VoidCallback listener) {
204 _systemFontsCallbacks.remove(listener);
205 }
206}
207
208/// The singleton that implements the Flutter framework's image cache.
209///
210/// The cache is used internally by [ImageProvider] and should generally not be
211/// accessed directly.
212///
213/// The image cache is created during startup by the [PaintingBinding]'s
214/// [PaintingBinding.createImageCache] method.
215ImageCache get imageCache => PaintingBinding.instance.imageCache;
216

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com