7 #include "flutter/fml/platform/darwin/cf_utils.h"
14 @property(nonatomic, weak) id<FlutterViewEngineDelegate> delegate;
18 BOOL _isWideGamutEnabled;
21 - (instancetype)init {
22 NSAssert(NO,
@"FlutterView must initWithDelegate");
27 NSAssert(NO,
@"FlutterView must initWithDelegate");
32 NSAssert(NO,
@"FlutterView must initWithDelegate");
37 if (@available(iOS 13.0, *)) {
38 return self.window.windowScene.screen;
40 return UIScreen.mainScreen;
43 - (MTLPixelFormat)pixelFormat {
44 if ([
self.layer isKindOfClass:[CAMetalLayer
class]]) {
47 #pragma clang diagnostic push
48 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
49 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
50 return layer.pixelFormat;
52 return MTLPixelFormatBGRA8Unorm;
54 - (BOOL)isWideGamutSupported {
55 FML_DCHECK(
self.screen);
66 return self.screen.traitCollection.displayGamut != UIDisplayGamutSRGB;
71 enableWideGamut:(BOOL)isWideGamutEnabled {
72 if (delegate == nil) {
73 NSLog(
@"FlutterView delegate was nil.");
77 self = [
super initWithFrame:CGRectNull];
81 _isWideGamutEnabled = isWideGamutEnabled;
82 self.layer.opaque = opaque;
88 static void PrintWideGamutWarningOnce() {
89 static BOOL did_print = NO;
93 FML_DLOG(WARNING) <<
"Rendering wide gamut colors is turned on but isn't "
94 "supported, downgrading the color gamut to sRGB.";
98 - (void)layoutSubviews {
99 if ([
self.layer isKindOfClass:[CAMetalLayer
class]]) {
102 #pragma clang diagnostic push
103 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
104 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
105 #pragma clang diagnostic pop
106 CGFloat screenScale =
self.screen.scale;
107 layer.allowsGroupOpacity = YES;
108 layer.contentsScale = screenScale;
109 layer.rasterizationScale = screenScale;
110 layer.framebufferOnly = flutter::Settings::kSurfaceDataAccessible ? NO : YES;
111 if (_isWideGamutEnabled &&
self.isWideGamutSupported) {
112 fml::CFRef<CGColorSpaceRef> srgb(CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB));
113 layer.colorspace = srgb;
114 layer.pixelFormat = MTLPixelFormatBGRA10_XR;
115 }
else if (_isWideGamutEnabled && !
self.isWideGamutSupported) {
116 PrintWideGamutWarningOnce();
120 [
super layoutSubviews];
123 + (Class)layerClass {
128 - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
129 TRACE_EVENT0(
"flutter",
"SnapshotFlutterView");
131 if (layer !=
self.layer || context ==
nullptr) {
135 auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
138 if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
142 NSData* data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
143 length:screenshot.data->size()];
145 fml::CFRef<CGDataProviderRef> image_data_provider(
146 CGDataProviderCreateWithCFData(
reinterpret_cast<CFDataRef
>(data)));
148 fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
151 size_t bits_per_component = 8u;
152 size_t bits_per_pixel = 32u;
153 size_t bytes_per_row_multiplier = 4u;
154 CGBitmapInfo bitmap_info =
155 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
156 static_cast<uint32_t
>(kCGBitmapByteOrder32Big));
158 switch (screenshot.pixel_format) {
159 case flutter::Rasterizer::ScreenshotFormat::kUnknown:
160 case flutter::Rasterizer::ScreenshotFormat::kR8G8B8A8UNormInt:
163 case flutter::Rasterizer::ScreenshotFormat::kB8G8R8A8UNormInt:
166 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedFirst) |
167 static_cast<uint32_t
>(kCGBitmapByteOrder32Little));
169 case flutter::Rasterizer::ScreenshotFormat::kR16G16B16A16Float:
170 bits_per_component = 16u;
171 bits_per_pixel = 64u;
172 bytes_per_row_multiplier = 8u;
174 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
175 static_cast<uint32_t
>(kCGBitmapFloatComponents) |
176 static_cast<uint32_t
>(kCGBitmapByteOrder16Little));
180 fml::CFRef<CGImageRef> image(CGImageCreate(
181 screenshot.frame_size.width(),
182 screenshot.frame_size.height(),
185 bytes_per_row_multiplier * screenshot.frame_size.width(),
191 kCGRenderingIntentDefault
194 const CGRect frame_rect =
195 CGRectMake(0.0, 0.0, screenshot.frame_size.width(), screenshot.frame_size.height());
196 CGContextSaveGState(context);
198 CGFloat height = CGBitmapContextGetHeight(context);
200 height = CGFloat(screenshot.frame_size.height());
202 CGContextTranslateCTM(context, 0.0, height);
203 CGContextScaleCTM(context, 1.0, -1.0);
204 CGContextDrawImage(context, frame_rect, image);
205 CGContextRestoreGState(context);
208 - (BOOL)isAccessibilityElement {
217 [
self.delegate flutterViewAccessibilityDidCall];
231 - (NSArray<id<UIFocusItem>>*)focusItemsInRect:(CGRect)rect {
232 NSObject* rootAccessibilityElement =
233 [
self.accessibilityElements count] > 0 ?
self.accessibilityElements[0] : nil;
235 ? @[ [rootAccessibilityElement accessibilityElementAtIndex:0] ]
239 - (NSArray<id<UIFocusEnvironment>>*)preferredFocusEnvironments {
instancetype initWithFrame
instancetype initWithCoder
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api)