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];
198- (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
201 if (layer !=
self.layer || context ==
nullptr) {
205 auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
208 if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.IsEmpty()) {
212 NSData*
data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
213 length:screenshot.data->size()];
216 CGDataProviderCreateWithCFData(
reinterpret_cast<CFDataRef
>(
data)));
221 size_t bits_per_component = 8u;
222 size_t bits_per_pixel = 32u;
223 size_t bytes_per_row_multiplier = 4u;
224 CGBitmapInfo bitmap_info =
225 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
226 static_cast<uint32_t
>(kCGBitmapByteOrder32Big));
228 switch (screenshot.pixel_format) {
236 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedFirst) |
237 static_cast<uint32_t
>(kCGBitmapByteOrder32Little));
240 bits_per_component = 16u;
241 bits_per_pixel = 64u;
242 bytes_per_row_multiplier = 8u;
244 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
245 static_cast<uint32_t
>(kCGBitmapFloatComponents) |
246 static_cast<uint32_t
>(kCGBitmapByteOrder16Little));
251 screenshot.frame_size.width,
252 screenshot.frame_size.height,
255 bytes_per_row_multiplier * screenshot.frame_size.width,
261 kCGRenderingIntentDefault
264 const CGRect frame_rect =
265 CGRectMake(0.0, 0.0, screenshot.frame_size.width, screenshot.frame_size.height);
266 CGContextSaveGState(context);
268 CGFloat
height = CGBitmapContextGetHeight(context);
270 height = CGFloat(screenshot.frame_size.height);
272 CGContextTranslateCTM(context, 0.0,
height);
273 CGContextScaleCTM(context, 1.0, -1.0);
274 CGContextDrawImage(context, frame_rect,
image);
275 CGContextRestoreGState(context);
278- (
BOOL)isAccessibilityElement {
287 [
self.delegate flutterViewAccessibilityDidCall];
301- (NSArray<
id<UIFocusItem>>*)focusItemsInRect:(CGRect)rect {
302 NSObject* rootAccessibilityElement =
303 [
self.accessibilityElements count] > 0 ?
self.accessibilityElements[0] : nil;
305 ? @[ [rootAccessibilityElement accessibilityElementAtIndex:0] ]
309- (NSArray<
id<UIFocusEnvironment>>*)preferredFocusEnvironments {
317- (void)willMoveToWindow:(UIWindow*)newWindow {
320 UIWindowScene* newScene = newWindow.windowScene;
321 UIWindowScene* currentScene =
self.window.windowScene;
323 if (newScene == currentScene) {
330 if (previousSceneLifeCycleDelegate) {
331 [previousSceneLifeCycleDelegate removeFlutterManagedEngine:(FlutterEngine*)self.delegate];
332 self.previousScene = nil;
339 if (newSceneLifeCycleDelegate) {
340 [newSceneLifeCycleDelegate addFlutterManagedEngine:(FlutterEngine*)self.delegate];
345 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
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api)
static constexpr bool kSurfaceDataAccessible
std::shared_ptr< const fml::Mapping > data
#define TRACE_EVENT0(category_group, name)