// Copyright 2019 Google LLC. // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. #include "tools/skottie_ios_app/SkiaContext.h" #include "tools/skottie_ios_app/SkottieViewController.h" #include "include/core/SkTypes.h" #import #include @interface AppViewController : UIViewController @property (strong) SkiaContext* skiaContext; @property (strong) UIStackView* stackView; @end @implementation AppViewController - (void)loadView { [self setView:[[UIView alloc] init]]; } - (void)viewDidLoad { [super viewDidLoad]; if (![self skiaContext]) { #if (defined(SK_GANESH) && defined(SK_METAL) && !defined(SK_BUILD_FOR_GOOGLE3)) [self setSkiaContext:MakeSkiaMetalContext()]; #elif (defined(SK_GANESH) && defined(SK_GL) && !defined(SK_BUILD_FOR_GOOGLE3)) [self setSkiaContext:MakeSkiaGLContext()]; #else [self setSkiaContext:MakeSkiaUIContext()]; #endif if (![self skiaContext]) { NSLog(@"abort: failed to make skia context."); std::abort(); } } CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width; UIStackView* stack = [[UIStackView alloc] init]; [stack setAxis:UILayoutConstraintAxisVertical]; [stack setDistribution:UIStackViewDistributionEqualSpacing]; NSBundle* mainBundle = [NSBundle mainBundle]; NSArray* paths = [mainBundle pathsForResourcesOfType:@"json" inDirectory:@"data"]; constexpr CGFloat kSpacing = 2; CGFloat totalHeight = kSpacing; for (NSUInteger i = 0; i < [paths count]; ++i) { NSString* path = [paths objectAtIndex:i]; NSData* content = [NSData dataWithContentsOfFile:path]; if (!content) { NSLog(@"'%@' not found", path); continue; } SkottieViewController* controller = [[SkottieViewController alloc] init]; if (![controller loadAnimation:content]) { continue; } CGSize animSize = [controller size]; CGFloat height = animSize.width ? (screenWidth * animSize.height / animSize.width) : 0; CGRect frame = {{0, 0}, {screenWidth, height}}; UIView* skiaView = [[self skiaContext] makeViewWithController:controller withFrame:frame]; [[[skiaView heightAnchor] constraintEqualToConstant:height] setActive:true]; [[[skiaView widthAnchor] constraintEqualToConstant:screenWidth] setActive:true]; [skiaView setNeedsDisplay]; [stack addArrangedSubview:skiaView]; totalHeight += height + kSpacing; } [stack setFrame:{{0, 0}, {screenWidth, totalHeight}}]; [stack setNeedsDisplay]; CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; CGSize mainScreenSize = [[UIScreen mainScreen] bounds].size; CGRect scrollViewBounds = {{0, statusBarHeight}, {mainScreenSize.width, mainScreenSize.height - statusBarHeight}}; UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:scrollViewBounds]; [scrollView setContentSize:[stack frame].size]; [scrollView addSubview:stack]; [scrollView setBackgroundColor:[UIColor blackColor]]; [scrollView setNeedsDisplay]; [self setStackView:stack]; UIView* mainView = [self view]; [mainView setBounds:{{0, 0}, mainScreenSize}]; [mainView setBackgroundColor:[UIColor whiteColor]]; [mainView addSubview:scrollView]; [mainView setNeedsDisplay]; UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init]; [tapGestureRecognizer addTarget:self action:@selector(handleTap:)]; [mainView addGestureRecognizer:tapGestureRecognizer]; } - (void)handleTap:(UIGestureRecognizer*)sender { if ([sender state] != UIGestureRecognizerStateEnded) { return; } NSArray* subviews = [[self stackView] subviews]; for (NSUInteger i = 0; i < [subviews count]; ++i) { UIView* uIView = [subviews objectAtIndex:i]; if (SkiaViewController* controller = [[self skiaContext] getViewController:uIView]) { [controller togglePaused]; [uIView setNeedsDisplay]; } } } @end @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow* window; @end @implementation AppDelegate - (BOOL)application:(UIApplication*)app didFinishLaunchingWithOptions:(NSDictionary*)ops { [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]]; [[self window] setRootViewController:[[AppViewController alloc] init]]; [[self window] makeKeyAndVisible]; return YES; } @end int main(int argc, char* argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }