1// Copyright 2020 Google LLC. 2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3 4#include "tools/skottie_ios_app/SkiaContext.h" 5 6#include "include/core/SkBitmap.h" 7#include "include/core/SkCanvas.h" 8#include "include/core/SkSize.h" 9#include "include/utils/mac/SkCGUtils.h" 10#include "src/base/SkTime.h" 11 12#import <UIKit/UIKit.h> 13 14// A UIView that uses a CPU-backed SkSurface to draw. 15@interface SkiaUIView : UIView 16 @property (strong) SkiaViewController* controller; 17 18 // Override of the UIView interface. 19 - (void)drawRect:(CGRect)rect; 20@end 21 22@implementation SkiaUIView { 23 SkBitmap fBackBuffer; 24} 25 26- (void)drawRect:(CGRect)rect { 27 SkiaViewController* viewController = [self controller]; 28 static constexpr double kFrameRate = 1.0 / 30.0; 29 double next = [viewController isPaused] ? 0 : kFrameRate + SkTime::GetNSecs() * 1e-9; 30 [super drawRect:rect]; 31 CGSize size = [self bounds].size; 32 SkISize iSize = {(int)size.width, (int)size.height}; 33 if (fBackBuffer.drawsNothing() || iSize != fBackBuffer.dimensions()) { 34 fBackBuffer.allocN32Pixels(iSize.fWidth, iSize.fHeight); 35 } 36 fBackBuffer.eraseColor(SK_ColorTRANSPARENT); 37 { 38 SkCanvas canvas(fBackBuffer); 39 [viewController draw:rect toCanvas:&canvas atSize:size]; 40 } 41 SkCGDrawBitmap(UIGraphicsGetCurrentContext(), fBackBuffer, 0, 0); 42 if (next) { 43 [NSTimer scheduledTimerWithTimeInterval:std::max(0.0, next - SkTime::GetNSecs() * 1e-9) 44 target:self 45 selector:@selector(setNeedsDisplay) 46 userInfo:nil 47 repeats:NO]; 48 } 49} 50@end 51 52@interface SkiaUIContext : SkiaContext 53 - (UIView*) makeViewWithController:(SkiaViewController*)vc withFrame:(CGRect)frame; 54 - (SkiaViewController*) getViewController:(UIView*)view; 55@end 56 57@implementation SkiaUIContext 58- (UIView*) makeViewWithController:(SkiaViewController*)vc withFrame:(CGRect)frame { 59 SkiaUIView* skiaView = [[SkiaUIView alloc] initWithFrame:frame]; 60 [skiaView setController:vc]; 61 return skiaView; 62} 63- (SkiaViewController*) getViewController:(UIView*)view { 64 return [view isKindOfClass:[SkiaUIView class]] ? [(SkiaUIView*)view controller] : nil; 65} 66@end 67 68SkiaContext* MakeSkiaUIContext() { return [[SkiaUIContext alloc] init]; } 69