15@property(nonatomic, weak) id<FlutterViewEngineDelegate> delegate;
16@property(nonatomic, weak) UIWindowScene* previousScene;
23 BOOL _isWideGamutEnabled;
28 NSAssert(NO,
@"FlutterView must initWithDelegate");
33 NSAssert(NO,
@"FlutterView must initWithDelegate");
38 NSAssert(NO,
@"FlutterView must initWithDelegate");
43 return self.window.windowScene.screen;
52- (void)setIntrinsicContentSize:(CGSize)size {
53 if (!
self.autoResizable) {
58 CGFloat scale =
window ?
self.window.windowScene.screen.scale :
self.traitCollection.displayScale;
59 CGSize scaledSize = CGSizeMake(
size.width / scale,
size.height / scale);
61 CGSize roundedScaleSize = CGSizeMake(roundf(scaledSize.width), roundf(scaledSize.height));
62 CGSize roundedIntrinsicSize =
66 if (CGSizeEqualToSize(roundedIntrinsicSize, roundedScaleSize)) {
71 self.translatesAutoresizingMaskIntoConstraints =
false;
74 [
self removeAutoResizeLayoutConstraints];
78 attribute:NSLayoutAttributeWidth
79 relatedBy:NSLayoutRelationEqual
81 attribute:NSLayoutAttributeNotAnAttribute
83 constant:scaledSize.width];
87 attribute:NSLayoutAttributeHeight
88 relatedBy:NSLayoutRelationEqual
90 attribute:NSLayoutAttributeNotAnAttribute
92 constant:scaledSize.height];
94 [NSLayoutConstraint activateConstraints:@[ widthConstraint, heightConstraint ]];
95 [
self setNeedsLayout];
98- (void)resetIntrinsicContentSize {
99 _intrinsicSize = CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
100 [
self removeAutoResizeLayoutConstraints];
103- (void)removeAutoResizeLayoutConstraints {
104 for (NSLayoutConstraint* constraint in
self.constraints) {
106 constraint.active = NO;
111- (MTLPixelFormat)pixelFormat {
112 if ([
self.layer isKindOfClass:[CAMetalLayer class]]) {
115#pragma clang diagnostic push
116#pragma clang diagnostic ignored "-Wunguarded-availability-new"
117 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
118 return layer.pixelFormat;
120 return MTLPixelFormatBGRA8Unorm;
122- (
BOOL)isWideGamutSupported {
134 return self.screen.traitCollection.displayGamut != UIDisplayGamutSRGB;
137- (instancetype)initWithDelegate:(
id<FlutterViewEngineDelegate>)delegate
139 enableWideGamut:(
BOOL)isWideGamutEnabled {
140 if (delegate == nil) {
141 NSLog(
@"FlutterView delegate was nil.");
145 self = [
super initWithFrame:CGRectNull];
148 _delegate = delegate;
149 _isWideGamutEnabled = isWideGamutEnabled;
150 self.layer.opaque = opaque;
152 _intrinsicSize = CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
158static void PrintWideGamutWarningOnce() {
159 static BOOL did_print = NO;
163 FML_DLOG(WARNING) <<
"Rendering wide gamut colors is turned on but isn't "
164 "supported, downgrading the color gamut to sRGB.";
168- (void)layoutSubviews {
169 if ([
self.layer isKindOfClass:[CAMetalLayer class]]) {
172#pragma clang diagnostic push
173#pragma clang diagnostic ignored "-Wunguarded-availability-new"
174 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
175#pragma clang diagnostic pop
176 CGFloat screenScale =
self.screen.scale;
177 layer.allowsGroupOpacity = YES;
178 layer.contentsScale = screenScale;
179 layer.rasterizationScale = screenScale;
181 if (_isWideGamutEnabled &&
self.isWideGamutSupported) {
183 layer.colorspace = srgb;
184 layer.pixelFormat = MTLPixelFormatBGRA10_XR;
185 }
else if (_isWideGamutEnabled && !
self.isWideGamutSupported) {
186 PrintWideGamutWarningOnce();
190 [
super layoutSubviews];
197- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
204 auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
207 if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.IsEmpty()) {
211 NSData*
data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
212 length:screenshot.data->size()];
215 CGDataProviderCreateWithCFData(
reinterpret_cast<CFDataRef
>(data)));
220 size_t bits_per_component = 8u;
221 size_t bits_per_pixel = 32u;
222 size_t bytes_per_row_multiplier = 4u;
223 CGBitmapInfo bitmap_info =
224 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
225 static_cast<uint32_t
>(kCGBitmapByteOrder32Big));
227 switch (screenshot.pixel_format) {
235 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedFirst) |
236 static_cast<uint32_t
>(kCGBitmapByteOrder32Little));
239 bits_per_component = 16u;
240 bits_per_pixel = 64u;
241 bytes_per_row_multiplier = 8u;
243 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
244 static_cast<uint32_t
>(kCGBitmapFloatComponents) |
245 static_cast<uint32_t
>(kCGBitmapByteOrder16Little));
250 screenshot.frame_size.width,
251 screenshot.frame_size.height,
254 bytes_per_row_multiplier * screenshot.frame_size.width,
260 kCGRenderingIntentDefault
263 const CGRect frame_rect =
264 CGRectMake(0.0, 0.0, screenshot.frame_size.width, screenshot.frame_size.height);
269 height = CGFloat(screenshot.frame_size.height);
272 CGContextScaleCTM(
context, 1.0, -1.0);
274 CGContextRestoreGState(
context);
277- (
BOOL)isAccessibilityElement {
286 [
self.delegate flutterViewAccessibilityDidCall];
300- (NSArray<
id<UIFocusItem>>*)focusItemsInRect:(CGRect)rect {
301 NSObject* rootAccessibilityElement =
302 [
self.accessibilityElements count] > 0 ?
self.accessibilityElements[0] : nil;
304 ? @[ [rootAccessibilityElement accessibilityElementAtIndex:0] ]
308- (NSArray<
id<UIFocusEnvironment>>*)preferredFocusEnvironments {
316- (void)willMoveToWindow:(UIWindow*)newWindow {
319 UIWindowScene* newScene = newWindow.windowScene;
320 UIWindowScene* currentScene =
self.window.windowScene;
322 if (newScene == currentScene) {
329 if (previousSceneLifeCycleDelegate) {
330 [previousSceneLifeCycleDelegate removeFlutterManagedEngine:(FlutterEngine*)self.delegate];
331 self.previousScene = nil;
338 if (newSceneLifeCycleDelegate) {
339 [newSceneLifeCycleDelegate addFlutterManagedEngine:(FlutterEngine*)self.delegate];
344 self.previousScene = currentScene;
FlutterVulkanImage * image
#define FML_DLOG(severity)
#define FML_DCHECK(condition)
instancetype initWithFrame
instancetype initWithCoder
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
IOSRenderingAPI GetRenderingAPIForProcess()
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api)
std::shared_ptr< ContextGLES > context
static constexpr bool kSurfaceDataAccessible
#define TRACE_EVENT0(category_group, name)