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