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 
73 + (BOOL)forceSoftwareRendering {
75 }
76 
77 + (void)setForceSoftwareRendering:(BOOL)forceSoftwareRendering {
79 }
80 
81 + (Class)layerClass {
84 }
85 
86 - (std::unique_ptr<flutter::IOSSurface>)createSurface:
87  (std::shared_ptr<flutter::IOSContext>)ios_context {
89  std::move(ios_context), // context
90  fml::scoped_nsobject<CALayer>{[self.layer retain]}, // layer
91  [_delegate platformViewsController] // platform views controller
92  );
93 }
94 
95 - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
96  TRACE_EVENT0("flutter", "SnapshotFlutterView");
97 
98  if (layer != self.layer || context == nullptr) {
99  return;
100  }
101 
102  auto screenshot = [_delegate takeScreenshot:flutter::Rasterizer::ScreenshotType::UncompressedImage
103  asBase64Encoded:NO];
104 
105  if (!screenshot.data || screenshot.data->isEmpty() || screenshot.frame_size.isEmpty()) {
106  return;
107  }
108 
109  NSData* data = [NSData dataWithBytes:const_cast<void*>(screenshot.data->data())
110  length:screenshot.data->size()];
111 
112  fml::CFRef<CGDataProviderRef> image_data_provider(
113  CGDataProviderCreateWithCFData(reinterpret_cast<CFDataRef>(data)));
114 
115  fml::CFRef<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB());
116 
117  fml::CFRef<CGImageRef> image(CGImageCreate(
118  screenshot.frame_size.width(), // size_t width
119  screenshot.frame_size.height(), // size_t height
120  8, // size_t bitsPerComponent
121  32, // size_t bitsPerPixel,
122  4 * screenshot.frame_size.width(), // size_t bytesPerRow
123  colorspace, // CGColorSpaceRef space
124  static_cast<CGBitmapInfo>(kCGImageAlphaPremultipliedLast |
125  kCGBitmapByteOrder32Big), // CGBitmapInfo bitmapInfo
126  image_data_provider, // CGDataProviderRef provider
127  nullptr, // const CGFloat* decode
128  false, // bool shouldInterpolate
129  kCGRenderingIntentDefault // CGColorRenderingIntent intent
130  ));
131 
132  const CGRect frame_rect =
133  CGRectMake(0.0, 0.0, screenshot.frame_size.width(), screenshot.frame_size.height());
134 
135  CGContextSaveGState(context);
136  CGContextTranslateCTM(context, 0.0, CGBitmapContextGetHeight(context));
137  CGContextScaleCTM(context, 1.0, -1.0);
138  CGContextDrawImage(context, frame_rect, image);
139  CGContextRestoreGState(context);
140 }
141 
142 @end
BOOL forceSoftwareRendering
Definition: FlutterView.h:38
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
Definition: ref_ptr.h:252
Class GetCoreAnimationLayerClassForRenderingAPI(IOSRenderingAPI rendering_api)
static BOOL _forceSoftwareRendering
Definition: FlutterView.mm:71
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
static std::unique_ptr< IOSSurface > Create(std::shared_ptr< IOSContext > context, fml::scoped_nsobject< CALayer > layer, FlutterPlatformViewsController *platform_views_controller)
Definition: ios_surface.mm:18