<commit_before>/* Copyright (c) 2014-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ASImageNode.h"

#import <AsyncDisplayKit/_ASCoreAnimationExtras.h>
#import <AsyncDisplayKit/_ASDisplayLayer.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>

#import "ASImageNode+CGExtras.h"

@interface _ASImageNodeDrawParameters : NSObject

@property (nonatomic, assign, readonly) BOOL cropEnabled;
@property (nonatomic, assign) BOOL opaque;
@property (nonatomic, retain) UIImage *image;
@property (nonatomic, assign) CGRect bounds;
@property (nonatomic, assign) CGFloat contentsScale;
@property (nonatomic, retain) UIColor *backgroundColor;
@property (nonatomic, assign) UIViewContentMode contentMode;
@property (nonatomic, assign) CGRect cropRect;
@property (nonatomic, copy) asimagenode_modification_block_t imageModificationBlock;

@end

// TODO: eliminate explicit parameters with a set of keys copied from the node
@implementation _ASImageNodeDrawParameters

- (id)initWithCrop:(BOOL)cropEnabled opaque:(BOOL)opaque image:(UIImage *)image bounds:(CGRect)bounds contentsScale:(CGFloat)contentsScale backgroundColor:(UIColor *)backgroundColor contentMode:(UIViewContentMode)contentMode cropRect:(CGRect)cropRect imageModificationBlock:(asimagenode_modification_block_t)imageModificationBlock
{
  self = [self init];
  if (!self) return nil;

  _cropEnabled = cropEnabled;
  _opaque = opaque;
  _image = image;
  _bounds = bounds;
  _contentsScale = contentsScale;
  _backgroundColor = backgroundColor;
  _contentMode = contentMode;
  _cropRect = cropRect;
  _imageModificationBlock = [imageModificationBlock copy];

  return self;
}

- (NSString *)description
{
  return [NSString stringWithFormat:@"<%@ : %p image:%@ cropEnabled:%@ opaque:%@ bounds:%@ contentsScale:%.2f backgroundColor:%@ contentMode:%@ cropRect:%@>", [self class], self, self.image, @(self.cropEnabled), @(self.opaque), NSStringFromCGRect(self.bounds), self.contentsScale, self.backgroundColor, ASDisplayNodeNSStringFromUIContentMode(self.contentMode), NSStringFromCGRect(self.cropRect)];
}

@end


@implementation ASImageNode
{
@private
  UIImage *_image;

  void (^_displayCompletionBlock)(BOOL canceled);
  ASDN::RecursiveMutex _imageLock;

  // Cropping.
  BOOL _cropEnabled; // Defaults to YES.
  CGRect _cropRect; // Defaults to CGRectMake(0.5, 0.5, 0, 0)
  CGRect _cropDisplayBounds;
}

@synthesize image = _image;

- (id)init
{
  if (!(self = [super init]))
    return nil;

  // TODO can this be removed?
  self.contentsScale = ASDisplayNodeScreenScale();
  self.contentMode = UIViewContentModeScaleAspectFill;
  self.opaque = NO;

  _cropEnabled = YES;
  _cropRect = CGRectMake(0.5, 0.5, 0, 0);
  _cropDisplayBounds = CGRectNull;
  _placeholderColor = ASDisplayNodeDefaultPlaceholderColor();

  return self;
}

- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
  ASDN::MutexLocker l(_imageLock);
  if (_image)
    return _image.size;
  else
    return CGSizeZero;
}

- (void)setImage:(UIImage *)image
{
  ASDN::MutexLocker l(_imageLock);
  if (_image != image) {
    _image = image;
    ASDisplayNodePerformBlockOnMainThread(^{
      [self invalidateCalculatedSize];
      [self setNeedsDisplay];
    });
  }
}

- (UIImage *)image
{
  ASDN::MutexLocker l(_imageLock);
  return _image;
}
<commit_msg>Fix ASImageNode -measure: / -setImage: deadlock.<commit_after>/* Copyright (c) 2014-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ASImageNode.h"

#import <AsyncDisplayKit/_ASCoreAnimationExtras.h>
#import <AsyncDisplayKit/_ASDisplayLayer.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>

#import "ASImageNode+CGExtras.h"

@interface _ASImageNodeDrawParameters : NSObject

@property (nonatomic, assign, readonly) BOOL cropEnabled;
@property (nonatomic, assign) BOOL opaque;
@property (nonatomic, retain) UIImage *image;
@property (nonatomic, assign) CGRect bounds;
@property (nonatomic, assign) CGFloat contentsScale;
@property (nonatomic, retain) UIColor *backgroundColor;
@property (nonatomic, assign) UIViewContentMode contentMode;
@property (nonatomic, assign) CGRect cropRect;
@property (nonatomic, copy) asimagenode_modification_block_t imageModificationBlock;

@end

// TODO: eliminate explicit parameters with a set of keys copied from the node
@implementation _ASImageNodeDrawParameters

- (id)initWithCrop:(BOOL)cropEnabled opaque:(BOOL)opaque image:(UIImage *)image bounds:(CGRect)bounds contentsScale:(CGFloat)contentsScale backgroundColor:(UIColor *)backgroundColor contentMode:(UIViewContentMode)contentMode cropRect:(CGRect)cropRect imageModificationBlock:(asimagenode_modification_block_t)imageModificationBlock
{
  self = [self init];
  if (!self) return nil;

  _cropEnabled = cropEnabled;
  _opaque = opaque;
  _image = image;
  _bounds = bounds;
  _contentsScale = contentsScale;
  _backgroundColor = backgroundColor;
  _contentMode = contentMode;
  _cropRect = cropRect;
  _imageModificationBlock = [imageModificationBlock copy];

  return self;
}

- (NSString *)description
{
  return [NSString stringWithFormat:@"<%@ : %p image:%@ cropEnabled:%@ opaque:%@ bounds:%@ contentsScale:%.2f backgroundColor:%@ contentMode:%@ cropRect:%@>", [self class], self, self.image, @(self.cropEnabled), @(self.opaque), NSStringFromCGRect(self.bounds), self.contentsScale, self.backgroundColor, ASDisplayNodeNSStringFromUIContentMode(self.contentMode), NSStringFromCGRect(self.cropRect)];
}

@end


@implementation ASImageNode
{
@private
  UIImage *_image;

  void (^_displayCompletionBlock)(BOOL canceled);
  ASDN::RecursiveMutex _imageLock;

  // Cropping.
  BOOL _cropEnabled; // Defaults to YES.
  CGRect _cropRect; // Defaults to CGRectMake(0.5, 0.5, 0, 0)
  CGRect _cropDisplayBounds;
}

@synthesize image = _image;

- (id)init
{
  if (!(self = [super init]))
    return nil;

  // TODO can this be removed?
  self.contentsScale = ASDisplayNodeScreenScale();
  self.contentMode = UIViewContentModeScaleAspectFill;
  self.opaque = NO;

  _cropEnabled = YES;
  _cropRect = CGRectMake(0.5, 0.5, 0, 0);
  _cropDisplayBounds = CGRectNull;
  _placeholderColor = ASDisplayNodeDefaultPlaceholderColor();

  return self;
}

- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize
{
  ASDN::MutexLocker l(_imageLock);
  if (_image)
    return _image.size;
  else
    return CGSizeZero;
}

- (void)setImage:(UIImage *)image
{
  ASDN::MutexLocker l(_imageLock);
  if (_image != image) {
    _image = image;

    ASDN::MutexUnlocker u(_imageLock);
    ASDisplayNodePerformBlockOnMainThread(^{
      [self invalidateCalculatedSize];
      [self setNeedsDisplay];
    });
  }
}

- (UIImage *)image
{
  ASDN::MutexLocker l(_imageLock);
  return _image;
}

{'fraction_non_alphanumeric': 0.11009050384979062, 'fraction_numerical': 0.0045927326759421854, 'mean_word_length': 5.749316317228806, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6789747', 'n_tokens_mistral': 2449, 'n_tokens_neox': 2311, 'n_words': 574}