• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 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#include "tools/skottie_ios_app/SkottieViewController.h"
6
7#include "include/core/SkTypes.h"
8
9#import <UIKit/UIKit.h>
10
11#include <cstdlib>
12
13@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 (defined(SK_GANESH) && defined(SK_METAL) && !defined(SK_BUILD_FOR_GOOGLE3))
28        [self setSkiaContext:MakeSkiaMetalContext()];
29        #elif (defined(SK_GANESH) && 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
41    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"
47                                            inDirectory:@"data"];
48    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        }
57        SkottieViewController* controller = [[SkottieViewController alloc] init];
58        if (![controller loadAnimation:content]) {
59            continue;
60        }
61        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];
69        totalHeight += height + kSpacing;
70    }
71    [stack setFrame:{{0, 0}, {screenWidth, totalHeight}}];
72    [stack setNeedsDisplay];
73
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];
79    [scrollView setContentSize:[stack frame].size];
80    [scrollView addSubview:stack];
81    [scrollView setBackgroundColor:[UIColor blackColor]];
82    [scrollView setNeedsDisplay];
83
84    [self setStackView:stack];
85
86    UIView* mainView = [self view];
87    [mainView setBounds:{{0, 0}, mainScreenSize}];
88    [mainView setBackgroundColor:[UIColor whiteColor]];
89    [mainView addSubview:scrollView];
90    [mainView setNeedsDisplay];
91
92    UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
93    [tapGestureRecognizer addTarget:self action:@selector(handleTap:)];
94    [mainView addGestureRecognizer:tapGestureRecognizer];
95}
96
97- (void)handleTap:(UIGestureRecognizer*)sender {
98    if ([sender state] != UIGestureRecognizerStateEnded) {
99        return;
100    }
101    NSArray<UIView*>* subviews = [[self stackView] subviews];
102    for (NSUInteger i = 0; i < [subviews count]; ++i) {
103        UIView* uIView = [subviews objectAtIndex:i];
104        if (SkiaViewController* controller = [[self skiaContext] getViewController:uIView]) {
105            [controller togglePaused];
106            [uIView setNeedsDisplay];
107        }
108    }
109}
110@end
111
112@interface AppDelegate : UIResponder <UIApplicationDelegate>
113    @property (strong, nonatomic) UIWindow* window;
114@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}
131