blob: 6b5a3517710de3b09c86d8264b154d580b44751d [file] [log] [blame]
Hal Canary41194432019-09-09 17:03:38 -04001// Copyright 2019 Google LLC.
Brian Osmanb47704b2019-09-16 16:17:21 -04002// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Hal Canary41194432019-09-09 17:03:38 -04003
Hal Canary118df7c2019-12-18 16:26:19 -05004#include "tools/skottie_ios_app/SkiaContext.h"
5#include "tools/skottie_ios_app/SkottieViewController.h"
6
Hal Canary27483062019-12-06 15:01:08 -05007#include "include/core/SkTypes.h"
Hal Canary41194432019-09-09 17:03:38 -04008
Hal Canary41194432019-09-09 17:03:38 -04009#import <UIKit/UIKit.h>
10
Hal Canary118df7c2019-12-18 16:26:19 -050011#include <cstdlib>
Hal Canary27483062019-12-06 15:01:08 -050012
Hal Canary118df7c2019-12-18 16:26:19 -050013@interface AppViewController : UIViewController
14 @property (strong) SkiaContext* skiaContext;
15 @property (strong) UIStackView* stackView;
16@end
17
18@implementation AppViewController
19
20- (void)loadView {
21 [self setView:[[UIView alloc] init]];
22}
23
24- (void)viewDidLoad {
25 [super viewDidLoad];
26 if (![self skiaContext]) {
27 #if (SK_SUPPORT_GPU && defined(SK_METAL) && !defined(SK_BUILD_FOR_GOOGLE3))
28 [self setSkiaContext:MakeSkiaMetalContext()];
29 #elif (SK_SUPPORT_GPU && defined(SK_GL) && !defined(SK_BUILD_FOR_GOOGLE3))
30 [self setSkiaContext:MakeSkiaGLContext()];
31 #else
32 [self setSkiaContext:MakeSkiaUIContext()];
33 #endif
34 if (![self skiaContext]) {
35 NSLog(@"abort: failed to make skia context.");
36 std::abort();
37 }
38 }
39 CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
40
Hal Canary41194432019-09-09 17:03:38 -040041 UIStackView* stack = [[UIStackView alloc] init];
42 [stack setAxis:UILayoutConstraintAxisVertical];
43 [stack setDistribution:UIStackViewDistributionEqualSpacing];
44
45 NSBundle* mainBundle = [NSBundle mainBundle];
46 NSArray<NSString*>* paths = [mainBundle pathsForResourcesOfType:@"json"
Hal Canary988b1e42019-09-26 14:29:51 -040047 inDirectory:@"data"];
Hal Canary41194432019-09-09 17:03:38 -040048 constexpr CGFloat kSpacing = 2;
49 CGFloat totalHeight = kSpacing;
50 for (NSUInteger i = 0; i < [paths count]; ++i) {
51 NSString* path = [paths objectAtIndex:i];
52 NSData* content = [NSData dataWithContentsOfFile:path];
53 if (!content) {
54 NSLog(@"'%@' not found", path);
55 continue;
56 }
Hal Canary118df7c2019-12-18 16:26:19 -050057 SkottieViewController* controller = [[SkottieViewController alloc] init];
58 if (![controller loadAnimation:content]) {
Hal Canary41194432019-09-09 17:03:38 -040059 continue;
60 }
Hal Canary118df7c2019-12-18 16:26:19 -050061 CGSize animSize = [controller size];
62 CGFloat height = animSize.width ? (screenWidth * animSize.height / animSize.width) : 0;
63 CGRect frame = {{0, 0}, {screenWidth, height}};
64 UIView* skiaView = [[self skiaContext] makeViewWithController:controller withFrame:frame];
65 [[[skiaView heightAnchor] constraintEqualToConstant:height] setActive:true];
66 [[[skiaView widthAnchor] constraintEqualToConstant:screenWidth] setActive:true];
67 [skiaView setNeedsDisplay];
68 [stack addArrangedSubview:skiaView];
Hal Canary41194432019-09-09 17:03:38 -040069 totalHeight += height + kSpacing;
70 }
Hal Canary118df7c2019-12-18 16:26:19 -050071 [stack setFrame:{{0, 0}, {screenWidth, totalHeight}}];
72 [stack setNeedsDisplay];
Hal Canary41194432019-09-09 17:03:38 -040073
74 CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
75 CGSize mainScreenSize = [[UIScreen mainScreen] bounds].size;
76 CGRect scrollViewBounds = {{0, statusBarHeight},
77 {mainScreenSize.width, mainScreenSize.height - statusBarHeight}};
78 UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:scrollViewBounds];
Hal Canary118df7c2019-12-18 16:26:19 -050079 [scrollView setContentSize:[stack frame].size];
80 [scrollView addSubview:stack];
Hal Canary41194432019-09-09 17:03:38 -040081 [scrollView setBackgroundColor:[UIColor blackColor]];
Hal Canary118df7c2019-12-18 16:26:19 -050082 [scrollView setNeedsDisplay];
83
84 [self setStackView:stack];
Hal Canary41194432019-09-09 17:03:38 -040085
86 UIView* mainView = [self view];
87 [mainView setBounds:{{0, 0}, mainScreenSize}];
88 [mainView setBackgroundColor:[UIColor whiteColor]];
89 [mainView addSubview:scrollView];
Hal Canary118df7c2019-12-18 16:26:19 -050090 [mainView setNeedsDisplay];
Hal Canary41194432019-09-09 17:03:38 -040091
92 UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
93 [tapGestureRecognizer addTarget:self action:@selector(handleTap:)];
94 [mainView addGestureRecognizer:tapGestureRecognizer];
95}
96
97- (void)handleTap:(UIGestureRecognizer*)sender {
Hal Canary719a8112019-12-17 10:01:42 -050098 if ([sender state] != UIGestureRecognizerStateEnded) {
Hal Canary41194432019-09-09 17:03:38 -040099 return;
100 }
101 NSArray<UIView*>* subviews = [[self stackView] subviews];
102 for (NSUInteger i = 0; i < [subviews count]; ++i) {
Hal Canary118df7c2019-12-18 16:26:19 -0500103 UIView* uIView = [subviews objectAtIndex:i];
104 if (SkiaViewController* controller = [[self skiaContext] getViewController:uIView]) {
105 [controller togglePaused];
106 [uIView setNeedsDisplay];
Hal Canary41194432019-09-09 17:03:38 -0400107 }
Hal Canary41194432019-09-09 17:03:38 -0400108 }
109}
110@end
111
112@interface AppDelegate : UIResponder <UIApplicationDelegate>
Hal Canary118df7c2019-12-18 16:26:19 -0500113 @property (strong, nonatomic) UIWindow* window;
Hal Canary41194432019-09-09 17:03:38 -0400114@end
115
116@implementation AppDelegate
117
118- (BOOL)application:(UIApplication*)app didFinishLaunchingWithOptions:(NSDictionary*)ops {
119 [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
120 [[self window] setRootViewController:[[AppViewController alloc] init]];
121 [[self window] makeKeyAndVisible];
122 return YES;
123}
124@end
125
126int main(int argc, char* argv[]) {
127 @autoreleasepool {
128 return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
129 }
130}