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 | import 'package:flutter/foundation.dart'; |
6 | |
7 | import 'box.dart'; |
8 | import 'layer.dart'; |
9 | import 'object.dart'; |
10 | |
11 | /// A rectangle upon which a backend texture is mapped. |
12 | /// |
13 | /// Backend textures are images that can be applied (mapped) to an area of the |
14 | /// Flutter view. They are created, managed, and updated using a |
15 | /// platform-specific texture registry. This is typically done by a plugin |
16 | /// that integrates with host platform video player, camera, or OpenGL APIs, |
17 | /// or similar image sources. |
18 | /// |
19 | /// A texture box refers to its backend texture using an integer ID. Texture |
20 | /// IDs are obtained from the texture registry and are scoped to the Flutter |
21 | /// view. Texture IDs may be reused after deregistration, at the discretion |
22 | /// of the registry. The use of texture IDs currently unknown to the registry |
23 | /// will silently result in a blank rectangle. |
24 | /// |
25 | /// Texture boxes are repainted autonomously as dictated by the backend (e.g. on |
26 | /// arrival of a video frame). Such repainting generally does not involve |
27 | /// executing Dart code. |
28 | /// |
29 | /// The size of the rectangle is determined by the parent, and the texture is |
30 | /// automatically scaled to fit. |
31 | /// |
32 | /// See also: |
33 | /// |
34 | /// * [TextureRegistry](/javadoc/io/flutter/view/TextureRegistry.html) |
35 | /// for how to create and manage backend textures on Android. |
36 | /// * [TextureRegistry Protocol](/ios-embedder/protocol_flutter_texture_registry-p.html) |
37 | /// for how to create and manage backend textures on iOS. |
38 | class TextureBox extends RenderBox { |
39 | /// Creates a box backed by the texture identified by [textureId], and use |
40 | /// [filterQuality] to set texture's [FilterQuality]. |
41 | TextureBox({ |
42 | required int textureId, |
43 | bool freeze = false, |
44 | FilterQuality filterQuality = FilterQuality.low, |
45 | }) : _textureId = textureId, |
46 | _freeze = freeze, |
47 | _filterQuality = filterQuality; |
48 | |
49 | /// The identity of the backend texture. |
50 | int get textureId => _textureId; |
51 | int _textureId; |
52 | set textureId(int value) { |
53 | if (value != _textureId) { |
54 | _textureId = value; |
55 | markNeedsPaint(); |
56 | } |
57 | } |
58 | |
59 | /// When true the texture will not be updated with new frames. |
60 | bool get freeze => _freeze; |
61 | bool _freeze; |
62 | set freeze(bool value) { |
63 | if (value != _freeze) { |
64 | _freeze = value; |
65 | markNeedsPaint(); |
66 | } |
67 | } |
68 | |
69 | /// {@macro flutter.widgets.Texture.filterQuality} |
70 | FilterQuality get filterQuality => _filterQuality; |
71 | FilterQuality _filterQuality; |
72 | set filterQuality(FilterQuality value) { |
73 | if (value != _filterQuality) { |
74 | _filterQuality = value; |
75 | markNeedsPaint(); |
76 | } |
77 | } |
78 | |
79 | @override |
80 | bool get sizedByParent => true; |
81 | |
82 | @override |
83 | bool get alwaysNeedsCompositing => true; |
84 | |
85 | @override |
86 | bool get isRepaintBoundary => true; |
87 | |
88 | @override |
89 | @protected |
90 | Size computeDryLayout(covariant BoxConstraints constraints) { |
91 | return constraints.biggest; |
92 | } |
93 | |
94 | @override |
95 | bool hitTestSelf(Offset position) => true; |
96 | |
97 | @override |
98 | void paint(PaintingContext context, Offset offset) { |
99 | context.addLayer(TextureLayer( |
100 | rect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height), |
101 | textureId: _textureId, |
102 | freeze: freeze, |
103 | filterQuality: _filterQuality, |
104 | )); |
105 | } |
106 | } |
107 | |