GLImage.m 3.51 KB
Newer Older
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
1

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
2 3 4 5
#import <React/RCTBridge.h>
#import <React/RCTImageLoader.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
6 7 8
#import "GLImage.h"
#import "GLImageData.h"
#import "GLTexture.h"
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
9

10
@implementation GLImage
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
11 12 13
{
  RCTBridge *_bridge; // React's bridge allow to access the imageLoader
  UIImage *_image; // The currently loaded image (nil if no image fully loaded yet)
14 15
  GLImageData *_data; // Cache of the data related to this image (computed by getImageData)
  GLTexture *_texture; // Cache of the texture
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
16 17 18 19 20 21 22 23 24 25 26
  void (^_onload)(void); // called everytime an image loads
  RCTImageLoaderCancellationBlock _loading; // the current loading cancellation function
}

- (instancetype)initWithBridge:(RCTBridge *)bridge withOnLoad:(void (^)(void))onload
{
  if ((self = [super init])) {
    _bridge = bridge;
    _onload = onload;
    _image = nil;
    _loading = nil;
27
    _texture = [[GLTexture alloc] init];
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
28 29 30 31 32 33 34 35 36 37 38
  }
  return self;
}

- (void)dealloc
{
  [self clearImage];
  if (_loading) _loading();
  _onload = nil;
  _loading = nil;
  _bridge = nil;
39
  _texture = nil;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
40 41 42 43 44 45 46 47 48 49
}

RCT_NOT_IMPLEMENTED(-init)

- (void) clearImage
{
  _image = nil;
  _data = nil;
}

50
- (GLTexture *) getTexture
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
51
{
52 53
  if (_image) {
    if (!_data) {
54
        _data = [GLImageData genPixelsWithImage:_image];
55 56 57 58
    }
    [_texture setPixels:_data];
  }
  else {
59
      [_texture setPixels:nil];
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
60
  }
61
  return _texture;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
62 63
}

64
- (void)setSource:(RCTImageSource *)source
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
65
{
66 67
  if (![source isEqual:_source]) {
    _source = source;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
68 69 70 71 72 73
    [self reloadImage];
  }
}

- (void)reloadImage
{
74
  RCTImageSource *source = _source;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
75 76
  if (_loading) _loading();
  _loading = nil;
77
  if (!source) {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
78
    [self clearImage];
79 80
  }
  else {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
81
    // Load the image (without resizing it)
82 83
    __weak GLImage *weakSelf = self;
    _loading = [_bridge.imageLoader loadImageWithURLRequest:source.request
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
84 85
                                       size:CGSizeZero
                                      scale:0
Steven Scaffidi's avatar
Steven Scaffidi committed
86
                                      clipped:YES
87
                                 resizeMode:RCTResizeModeStretch
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
88
                              progressBlock:nil
89
                              partialLoadBlock:nil
90 91 92 93 94 95 96 97 98 99 100 101 102
                            completionBlock:^(NSError *error, UIImage *loadedImage) {
                              GLImage *strongSelf = weakSelf;
                              void (^setImageBlock)(UIImage *) = ^(UIImage *image) {
                                if (![source isEqual:strongSelf.source]) {
                                  // Bail out if source has changed since we started loading
                                  return;
                                }
                                strongSelf.image = [UIImage imageWithCGImage:image.CGImage];
                                dispatch_async(dispatch_get_main_queue(), ^{
                                  if (_onload) _onload();
                                });
                              };

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
103 104 105 106 107
                              _loading = nil;
                              [self clearImage];
                              if (error) {
                                NSLog(@"Image failed to load: %@", error);
                              } else {
108 109 110
                                if ([NSThread isMainThread]) {
                                  setImageBlock(loadedImage);
                                } else {
111
                                  RCTExecuteOnMainQueue(^{
112
                                    setImageBlock(loadedImage);
113
                                  });
114
                                }
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
115 116 117 118 119 120 121
                              }
                            }];
  }
}


@end