Flutter Engine
FlutterView.mm
Go to the documentation of this file.
1 // Copyright 2013 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 "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
6 
7 #include "flutter/common/settings.h"
8 #include "flutter/common/task_runners.h"
9 #include "flutter/flow/layers/layer_tree.h"
10 #include "flutter/fml/platform/darwin/cf_utils.h"
11 #include "flutter/fml/synchronization/waitable_event.h"
12 #include "flutter/fml/trace_event.h"
13 #include "flutter/shell/common/platform_view.h"
14 #include "flutter/shell/common/rasterizer.h"
15 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
16 #import "flutter/shell/platform/darwin/ios/ios_surface_gl.h"
17 #import "flutter/shell/platform/darwin/ios/ios_surface_software.h"
18 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
19 
20 @implementation FlutterView {
21  id<FlutterViewEngineDelegate> _delegate;
22 }
23 
24 - (instancetype)init {
25  @throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
26  reason:nil
27  userInfo:nil]);
28 }
29 
30 - (instancetype)initWithFrame:(CGRect)frame {
31  @throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
32  reason:nil
33  userInfo:nil]);
34 }
35 
36 - (instancetype)initWithCoder:(NSCoder*)aDecoder {
37  @throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
38  reason:nil
39  userInfo:nil]);
40 }
41 
42 - (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate opaque:(BOOL)opaque {
43  if (delegate == nil) {
44  NSLog(@"FlutterView delegate was nil.");
45  [self release];
46  return nil;
47  }
48 
49  self = [super initWithFrame:CGRectNull];
50 
51  if (self) {
52  _delegate = delegate;
53  self.layer.opaque = opaque;
54  }
55 
56  return self;
57 }
58 
59 - (void)layoutSubviews {
60  if ([self.layer isKindOfClass:NSClassFromString(@"CAEAGLLayer")] ||
61  [self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
62  CGFloat screenScale = [UIScreen mainScreen].scale;
63  self.layer.allowsGroupOpacity = YES;
64  self.layer.contentsScale = screenScale;
65  self.layer.rasterizationScale = screenScale;
66  }
67 
68  [super layoutSubviews];
69 }
70 
72 
75 }
76 
77 + (void)setForceSoftwareRendering:(BOOL)forceSoftwareRendering {
79 }
80 
81 + (Class)layerClass {
84 }
85 
86 - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
87  TRACE_EVENT0("flutter", "SnapshotFlutterView");
88 
89  if (layer != self.layer || context == nullptr) {
90  return;
91  }
92 
93  auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
94  asBase64Encoded:NO];
95 
96  if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
97  return;
98  }
99 
100  NSData* data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
101  length:screenshot.data->size()];
102 
103  fml::CFRef<CGDataProviderRef> image_data_provider(
104  CGDataProviderCreateWithCFData(reinterpret_cast<CFDataRef>(data)));
105 
106  fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
107 
108  fml::CFRef<CGImageRef> image(CGImageCreate(
109  screenshot.frame_size.width(), // size_t width
110  screenshot.frame_size.height(), // size_t height
111  8, // size_t bitsPerComponent
112  32, // size_t bitsPerPixel,
113  4 * screenshot.frame_size.width(), // size_t bytesPerRow
114  colorspace, // CGColorSpaceRef space
115  static_cast<CGBitmapInfo>(kCGImageAlphaPremultipliedLast |
116  kCGBitmapByteOrder32Big), // CGBitmapInfo bitmapInfo
117  image_data_provider, // CGDataProviderRef provider
118  nullptr, // const CGFloat* decode
119  false, // bool shouldInterpolate
120  kCGRenderingIntentDefault // CGColorRenderingIntent intent
121  ));
122 
123  const CGRect frame_rect =
124  CGRectMake(0.0, 0.0, screenshot.frame_size.width(), screenshot.frame_size.height());
125 
126  CGContextSaveGState(context);
127  CGContextTranslateCTM(context, 0.0, CGBitmapContextGetHeight(context));
128  CGContextScaleCTM(context, 1.0, -1.0);
129  CGContextDrawImage(context, frame_rect, image);
130  CGContextRestoreGState(context);
131 }
132 
133 - (BOOL)isAccessibilityElement {
134  // iOS does not provide an API to query whether the voice control
135  // is turned on or off. It is likely at least one of the assitive
136  // technologies is turned on if this method is called. If we do
137  // not catch it in notification center, we will catch it here.
138  //
139  // TODO(chunhtai): Remove this workaround once iOS provides an
140  // API to query whether voice control is enabled.
141  // https://github.com/flutter/flutter/issues/76808.
142  [_delegate flutterViewAccessibilityDidCall];
143  return NO;
144 }
145 
146 @end
BOOL forceSoftwareRendering
Definition: FlutterView.h:47
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api)
static BOOL _forceSoftwareRendering
Definition: FlutterView.mm:71
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
int BOOL
Definition: windows_types.h:37