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