7 #include "flutter/fml/platform/darwin/cf_utils.h"
12 @property(nonatomic, weak) id<FlutterViewEngineDelegate> delegate;
16 BOOL _isWideGamutEnabled;
19 - (instancetype)init {
20 NSAssert(NO,
@"FlutterView must initWithDelegate");
25 NSAssert(NO,
@"FlutterView must initWithDelegate");
30 NSAssert(NO,
@"FlutterView must initWithDelegate");
35 if (@available(iOS 13.0, *)) {
36 return self.window.windowScene.screen;
38 return UIScreen.mainScreen;
41 - (MTLPixelFormat)pixelFormat {
42 if ([
self.layer isKindOfClass:NSClassFromString(
@"CAMetalLayer")]) {
45 #pragma clang diagnostic push
46 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
47 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
48 return layer.pixelFormat;
50 return MTLPixelFormatBGRA8Unorm;
52 - (BOOL)isWideGamutSupported {
53 if (!
self.delegate.isUsingImpeller) {
57 FML_DCHECK(
self.screen);
62 return self.screen.traitCollection.displayGamut != UIDisplayGamutSRGB;
67 enableWideGamut:(BOOL)isWideGamutEnabled {
68 if (delegate == nil) {
69 NSLog(
@"FlutterView delegate was nil.");
73 self = [
super initWithFrame:CGRectNull];
77 _isWideGamutEnabled = isWideGamutEnabled;
78 self.layer.opaque = opaque;
84 static void PrintWideGamutWarningOnce() {
85 static BOOL did_print = NO;
89 FML_DLOG(WARNING) <<
"Rendering wide gamut colors is turned on but isn't "
90 "supported, downgrading the color gamut to sRGB.";
94 - (void)layoutSubviews {
95 if ([
self.layer isKindOfClass:NSClassFromString(
@"CAMetalLayer")]) {
98 #pragma clang diagnostic push
99 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
100 CAMetalLayer* layer = (CAMetalLayer*)
self.layer;
101 #pragma clang diagnostic pop
102 CGFloat screenScale =
self.screen.scale;
103 layer.allowsGroupOpacity = YES;
104 layer.contentsScale = screenScale;
105 layer.rasterizationScale = screenScale;
106 layer.framebufferOnly = flutter::Settings::kSurfaceDataAccessible ? NO : YES;
107 BOOL isWideGamutSupported =
self.isWideGamutSupported;
108 if (_isWideGamutEnabled && isWideGamutSupported) {
109 CGColorSpaceRef srgb = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
110 layer.colorspace = srgb;
112 layer.pixelFormat = MTLPixelFormatBGRA10_XR;
113 }
else if (_isWideGamutEnabled && !isWideGamutSupported) {
114 PrintWideGamutWarningOnce();
118 [
super layoutSubviews];
123 + (BOOL)forceSoftwareRendering {
127 + (void)setForceSoftwareRendering:(BOOL)forceSoftwareRendering {
131 + (Class)layerClass {
136 - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
137 TRACE_EVENT0(
"flutter",
"SnapshotFlutterView");
139 if (layer !=
self.layer || context ==
nullptr) {
143 auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
146 if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
150 NSData* data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
151 length:screenshot.data->size()];
153 fml::CFRef<CGDataProviderRef> image_data_provider(
154 CGDataProviderCreateWithCFData(
reinterpret_cast<CFDataRef
>(data)));
156 fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
159 size_t bits_per_component = 8u;
160 size_t bits_per_pixel = 32u;
161 size_t bytes_per_row_multiplier = 4u;
162 CGBitmapInfo bitmap_info =
163 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
164 static_cast<uint32_t
>(kCGBitmapByteOrder32Big));
166 switch (screenshot.pixel_format) {
167 case flutter::Rasterizer::ScreenshotFormat::kUnknown:
168 case flutter::Rasterizer::ScreenshotFormat::kR8G8B8A8UNormInt:
171 case flutter::Rasterizer::ScreenshotFormat::kB8G8R8A8UNormInt:
174 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedFirst) |
175 static_cast<uint32_t
>(kCGBitmapByteOrder32Little));
177 case flutter::Rasterizer::ScreenshotFormat::kR16G16B16A16Float:
178 bits_per_component = 16u;
179 bits_per_pixel = 64u;
180 bytes_per_row_multiplier = 8u;
182 static_cast<CGBitmapInfo
>(
static_cast<uint32_t
>(kCGImageAlphaPremultipliedLast) |
183 static_cast<uint32_t
>(kCGBitmapFloatComponents) |
184 static_cast<uint32_t
>(kCGBitmapByteOrder16Little));
188 fml::CFRef<CGImageRef> image(CGImageCreate(
189 screenshot.frame_size.width(),
190 screenshot.frame_size.height(),
193 bytes_per_row_multiplier * screenshot.frame_size.width(),
199 kCGRenderingIntentDefault
202 const CGRect frame_rect =
203 CGRectMake(0.0, 0.0, screenshot.frame_size.width(), screenshot.frame_size.height());
204 CGContextSaveGState(context);
206 CGFloat height = CGBitmapContextGetHeight(context);
208 height = CGFloat(screenshot.frame_size.height());
210 CGContextTranslateCTM(context, 0.0, height);
211 CGContextScaleCTM(context, 1.0, -1.0);
212 CGContextDrawImage(context, frame_rect, image);
213 CGContextRestoreGState(context);
216 - (BOOL)isAccessibilityElement {
225 [
self.delegate flutterViewAccessibilityDidCall];