This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// A little helper to make sure we have the right memory allocation ready for use.
// We assume that we will only this in one place so no reference counting is necessary.
// Needs to be freed when deallocated.
// This is fragile since this relies on these values not getting reused. Consider
// wrapping these in an Obj-C class or some ARC hackery to get refcounting.
typedef struct {
size_t count;
CGFloat *array;
} ARTCGFloatArray;

16
node_modules/react-native/Libraries/ART/ARTContainer.h generated vendored Normal file
View File

@ -0,0 +1,16 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
@protocol ARTContainer <NSObject>
// This is used as a hook for child to mark it's parent as dirty.
// This bubbles up to the root which gets marked as dirty.
- (void)invalidate;
@end

17
node_modules/react-native/Libraries/ART/ARTGroup.h generated vendored Normal file
View File

@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import "ARTContainer.h"
#import "ARTNode.h"
@interface ARTGroup : ARTNode <ARTContainer>
@property (nonatomic, assign) CGRect clipping;
@end

24
node_modules/react-native/Libraries/ART/ARTGroup.m generated vendored Normal file
View File

@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTGroup.h>
@implementation ARTGroup
- (void)renderLayerTo:(CGContextRef)context
{
if (!CGRectIsEmpty(self.clipping)) {
CGContextClipToRect(context, self.clipping);
}
for (ARTNode *node in self.subviews) {
[node renderTo:context];
}
}
@end

30
node_modules/react-native/Libraries/ART/ARTNode.h generated vendored Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/UIView+React.h>
/**
* ART nodes are implemented as empty UIViews but this is just an implementation detail to fit
* into the existing view management. They should also be shadow views and painted on a background
* thread.
*/
@interface ARTNode : UIView
@property (nonatomic, assign) CGFloat opacity;
- (void)invalidate;
- (void)renderTo:(CGContextRef)context;
/**
* renderTo will take opacity into account and draw renderLayerTo off-screen if there is opacity
* specified, then composite that onto the context. renderLayerTo always draws at opacity=1.
* @abstract
*/
- (void)renderLayerTo:(CGContextRef)context;
@end

80
node_modules/react-native/Libraries/ART/ARTNode.m generated vendored Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTNode.h>
#import <React/ARTContainer.h>
@implementation ARTNode
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
{
[super insertReactSubview:subview atIndex:atIndex];
[self insertSubview:subview atIndex:atIndex];
[self invalidate];
}
- (void)removeReactSubview:(UIView *)subview
{
[super removeReactSubview:subview];
[self invalidate];
}
- (void)didUpdateReactSubviews
{
// Do nothing, as subviews are inserted by insertReactSubview:
}
- (void)setOpacity:(CGFloat)opacity
{
[self invalidate];
_opacity = opacity;
}
- (void)setTransform:(CGAffineTransform)transform
{
[self invalidate];
super.transform = transform;
}
- (void)invalidate
{
id<ARTContainer> container = (id<ARTContainer>)self.superview;
[container invalidate];
}
- (void)renderTo:(CGContextRef)context
{
if (self.opacity <= 0) {
// Nothing to paint
return;
}
if (self.opacity >= 1) {
// Just paint at full opacity
CGContextSaveGState(context);
CGContextConcatCTM(context, self.transform);
CGContextSetAlpha(context, 1);
[self renderLayerTo:context];
CGContextRestoreGState(context);
return;
}
// This needs to be painted on a layer before being composited.
CGContextSaveGState(context);
CGContextConcatCTM(context, self.transform);
CGContextSetAlpha(context, self.opacity);
CGContextBeginTransparencyLayer(context, NULL);
[self renderLayerTo:context];
CGContextEndTransparencyLayer(context);
CGContextRestoreGState(context);
}
- (void)renderLayerTo:(CGContextRef)context
{
// abstract
}
@end

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import "ARTBrush.h"
#import "ARTCGFloatArray.h"
#import "ARTNode.h"
@interface ARTRenderable : ARTNode
@property (nonatomic, strong) ARTBrush *fill;
@property (nonatomic, assign) CGColorRef stroke;
@property (nonatomic, assign) CGFloat strokeWidth;
@property (nonatomic, assign) CGLineCap strokeCap;
@property (nonatomic, assign) CGLineJoin strokeJoin;
@property (nonatomic, assign) ARTCGFloatArray strokeDash;
@end

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTRenderable.h>
@implementation ARTRenderable
- (void)setFill:(ARTBrush *)fill
{
[self invalidate];
_fill = fill;
}
- (void)setStroke:(CGColorRef)stroke
{
if (stroke == _stroke) {
return;
}
[self invalidate];
CGColorRelease(_stroke);
_stroke = CGColorRetain(stroke);
}
- (void)setStrokeWidth:(CGFloat)strokeWidth
{
[self invalidate];
_strokeWidth = strokeWidth;
}
- (void)setStrokeCap:(CGLineCap)strokeCap
{
[self invalidate];
_strokeCap = strokeCap;
}
- (void)setStrokeJoin:(CGLineJoin)strokeJoin
{
[self invalidate];
_strokeJoin = strokeJoin;
}
- (void)setStrokeDash:(ARTCGFloatArray)strokeDash
{
if (strokeDash.array == _strokeDash.array) {
return;
}
if (_strokeDash.array) {
free(_strokeDash.array);
}
[self invalidate];
_strokeDash = strokeDash;
}
- (void)dealloc
{
CGColorRelease(_stroke);
if (_strokeDash.array) {
free(_strokeDash.array);
}
}
- (void)renderTo:(CGContextRef)context
{
if (self.opacity <= 0 || self.opacity >= 1 || (self.fill && self.stroke)) {
// If we have both fill and stroke, we will need to paint this using normal compositing
[super renderTo: context];
return;
}
// This is a terminal with only one painting. Therefore we don't need to paint this
// off-screen. We can just composite it straight onto the buffer.
CGContextSaveGState(context);
CGContextConcatCTM(context, self.transform);
CGContextSetAlpha(context, self.opacity);
[self renderLayerTo:context];
CGContextRestoreGState(context);
}
- (void)renderLayerTo:(CGContextRef)context
{
// abstract
}
@end

16
node_modules/react-native/Libraries/ART/ARTShape.h generated vendored Normal file
View File

@ -0,0 +1,16 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import "ARTRenderable.h"
@interface ARTShape : ARTRenderable
@property (nonatomic, assign) CGPathRef d;
@end

66
node_modules/react-native/Libraries/ART/ARTShape.m generated vendored Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTShape.h>
@implementation ARTShape
- (void)setD:(CGPathRef)d
{
if (d == _d) {
return;
}
[self invalidate];
CGPathRelease(_d);
_d = CGPathRetain(d);
}
- (void)dealloc
{
CGPathRelease(_d);
}
- (void)renderLayerTo:(CGContextRef)context
{
if ((!self.fill && !self.stroke) || !self.d) {
return;
}
CGPathDrawingMode mode = kCGPathStroke;
if (self.fill) {
if ([self.fill applyFillColor:context]) {
mode = kCGPathFill;
} else {
CGContextSaveGState(context);
CGContextAddPath(context, self.d);
CGContextClip(context);
[self.fill paint:context];
CGContextRestoreGState(context);
if (!self.stroke) {
return;
}
}
}
if (self.stroke) {
CGContextSetStrokeColorWithColor(context, self.stroke);
CGContextSetLineWidth(context, self.strokeWidth);
CGContextSetLineCap(context, self.strokeCap);
CGContextSetLineJoin(context, self.strokeJoin);
ARTCGFloatArray dash = self.strokeDash;
if (dash.count) {
CGContextSetLineDash(context, 0, dash.array, dash.count);
}
if (mode == kCGPathFill) {
mode = kCGPathFillStroke;
}
}
CGContextAddPath(context, self.d);
CGContextDrawPath(context, mode);
}
@end

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import "ARTContainer.h"
@interface ARTSurfaceView : UIView <ARTContainer>
@end

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTSurfaceView.h>
#import <React/RCTLog.h>
#import <React/ARTNode.h>
@implementation ARTSurfaceView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.opaque = NO;
}
return self;
}
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
{
[super insertReactSubview:subview atIndex:atIndex];
[self insertSubview:subview atIndex:atIndex];
[self invalidate];
}
- (void)removeReactSubview:(UIView *)subview
{
[super removeReactSubview:subview];
[self invalidate];
}
- (void)didUpdateReactSubviews
{
// Do nothing, as subviews are inserted by insertReactSubview:
}
- (void)invalidate
{
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
for (ARTNode *node in self.subviews) {
[node renderTo:context];
}
}
@end

18
node_modules/react-native/Libraries/ART/ARTText.h generated vendored Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import "ARTRenderable.h"
#import "ARTTextFrame.h"
@interface ARTText : ARTRenderable
@property (nonatomic, assign) CTTextAlignment alignment;
@property (nonatomic, assign) ARTTextFrame textFrame;
@end

125
node_modules/react-native/Libraries/ART/ARTText.m generated vendored Normal file
View File

@ -0,0 +1,125 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTText.h>
#import <CoreText/CoreText.h>
@implementation ARTText
- (void)setAlignment:(CTTextAlignment)alignment
{
[self invalidate];
_alignment = alignment;
}
static void ARTFreeTextFrame(ARTTextFrame frame)
{
if (frame.count) {
// We must release each line before freeing up this struct
for (int i = 0; i < frame.count; i++) {
CFRelease(frame.lines[i]);
}
free(frame.lines);
free(frame.widths);
}
}
- (void)setTextFrame:(ARTTextFrame)frame
{
if (frame.lines != _textFrame.lines) {
ARTFreeTextFrame(_textFrame);
}
[self invalidate];
_textFrame = frame;
}
- (void)dealloc
{
ARTFreeTextFrame(_textFrame);
}
- (void)renderLayerTo:(CGContextRef)context
{
ARTTextFrame frame = self.textFrame;
if ((!self.fill && !self.stroke) || !frame.count) {
return;
}
// to-do: draw along a path
CGTextDrawingMode mode = kCGTextStroke;
if (self.fill) {
if ([self.fill applyFillColor:context]) {
mode = kCGTextFill;
} else {
for (int i = 0; i < frame.count; i++) {
CGContextSaveGState(context);
// Inverse the coordinate space since CoreText assumes a bottom-up coordinate space
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetTextDrawingMode(context, kCGTextClip);
[self renderLineTo:context atIndex:i];
// Inverse the coordinate space back to the original before filling
CGContextScaleCTM(context, 1.0, -1.0);
[self.fill paint:context];
// Restore the state so that the next line can be clipped separately
CGContextRestoreGState(context);
}
if (!self.stroke) {
return;
}
}
}
if (self.stroke) {
CGContextSetStrokeColorWithColor(context, self.stroke);
CGContextSetLineWidth(context, self.strokeWidth);
CGContextSetLineCap(context, self.strokeCap);
CGContextSetLineJoin(context, self.strokeJoin);
ARTCGFloatArray dash = self.strokeDash;
if (dash.count) {
CGContextSetLineDash(context, 0, dash.array, dash.count);
}
if (mode == kCGTextFill) {
mode = kCGTextFillStroke;
}
}
CGContextSetTextDrawingMode(context, mode);
// Inverse the coordinate space since CoreText assumes a bottom-up coordinate space
CGContextScaleCTM(context, 1.0, -1.0);
for (int i = 0; i < frame.count; i++) {
[self renderLineTo:context atIndex:i];
}
}
- (void)renderLineTo:(CGContextRef)context atIndex:(int)index
{
ARTTextFrame frame = self.textFrame;
CGFloat shift;
switch (self.alignment) {
case kCTTextAlignmentRight:
shift = frame.widths[index];
break;
case kCTTextAlignmentCenter:
shift = (frame.widths[index] / 2);
break;
default:
shift = 0;
break;
}
// We should consider snapping this shift to device pixels to improve rendering quality
// when a line has subpixel width.
CGContextSetTextPosition(context, -shift, -frame.baseLine - frame.lineHeight * index);
CTLineRef line = frame.lines[index];
CTLineDraw(line, context);
}
@end

23
node_modules/react-native/Libraries/ART/ARTTextFrame.h generated vendored Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <CoreText/CoreText.h>
// A little helper to make sure we have a set of lines including width ready for use.
// We assume that we will only this in one place so no reference counting is necessary.
// Needs to be freed when deallocated.
// This is fragile since this relies on these values not getting reused. Consider
// wrapping these in an Obj-C class or some ARC hackery to get refcounting.
typedef struct {
size_t count;
CGFloat baseLine; // Distance from the origin to the base line of the first line
CGFloat lineHeight; // Distance between lines
CTLineRef *lines;
CGFloat *widths; // Width of each line
} ARTTextFrame;

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
@interface ARTBrush : NSObject
/* @abstract */
- (instancetype)initWithArray:(NSArray *)data NS_DESIGNATED_INITIALIZER;
/**
* For certain brushes we can fast path a combined fill and stroke.
* For those brushes we override applyFillColor which sets the fill
* color to be used by those batch paints. Those return YES.
* We can't batch gradient painting in CoreGraphics, so those will
* return NO and paint gets called instead.
* @abstract
*/
- (BOOL)applyFillColor:(CGContextRef)context;
/**
* paint fills the context with a brush. The context is assumed to
* be clipped.
* @abstract
*/
- (void)paint:(CGContextRef)context;
@end

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTBrush.h>
#import <React/RCTDefines.h>
@implementation ARTBrush
- (instancetype)initWithArray:(NSArray *)data
{
return [super init];
}
RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (BOOL)applyFillColor:(CGContextRef)context
{
return NO;
}
- (void)paint:(CGContextRef)context
{
// abstract
}
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTBrush.h"
@interface ARTLinearGradient : ARTBrush
@end

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTLinearGradient.h>
#import <React/RCTLog.h>
#import "RCTConvert+ART.h"
@implementation ARTLinearGradient
{
CGGradientRef _gradient;
CGPoint _startPoint;
CGPoint _endPoint;
}
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{
if ((self = [super initWithArray:array])) {
if (array.count < 5) {
RCTLogError(@"-[%@ %@] expects 5 elements, received %@",
self.class, NSStringFromSelector(_cmd), array);
return nil;
}
_startPoint = [RCTConvert CGPoint:array offset:1];
_endPoint = [RCTConvert CGPoint:array offset:3];
_gradient = CGGradientRetain([RCTConvert CGGradient:array offset:5]);
}
return self;
}
- (void)dealloc
{
CGGradientRelease(_gradient);
}
- (void)paint:(CGContextRef)context
{
CGGradientDrawingOptions extendOptions =
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawLinearGradient(context, _gradient, _startPoint, _endPoint, extendOptions);
}
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTBrush.h"
@interface ARTPattern : ARTBrush
@end

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTPattern.h>
#import <React/RCTLog.h>
#import "RCTConvert+ART.h"
@implementation ARTPattern
{
CGImageRef _image;
CGRect _rect;
}
- (instancetype)initWithArray:(NSArray<id /* imagesource + numbers */> *)array
{
if ((self = [super initWithArray:array])) {
if (array.count < 6) {
RCTLogError(@"-[%@ %@] expects 6 elements, received %@",
self.class, NSStringFromSelector(_cmd), array);
return nil;
}
_image = CGImageRetain([RCTConvert CGImage:array[1]]);
_rect = [RCTConvert CGRect:array offset:2];
}
return self;
}
- (void)dealloc
{
CGImageRelease(_image);
}
// Note: This could use applyFillColor with a pattern. This could be more efficient but
// to do that, we need to calculate our own user space CTM.
- (void)paint:(CGContextRef)context
{
CGContextDrawTiledImage(context, _rect, _image);
}
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTBrush.h"
@interface ARTRadialGradient : ARTBrush
@end

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTRadialGradient.h>
#import <React/RCTLog.h>
#import "RCTConvert+ART.h"
@implementation ARTRadialGradient
{
CGGradientRef _gradient;
CGPoint _focusPoint;
CGPoint _centerPoint;
CGFloat _radius;
CGFloat _radiusRatio;
}
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{
if ((self = [super initWithArray:array])) {
if (array.count < 7) {
RCTLogError(@"-[%@ %@] expects 7 elements, received %@",
self.class, NSStringFromSelector(_cmd), array);
return nil;
}
_radius = [RCTConvert CGFloat:array[3]];
_radiusRatio = [RCTConvert CGFloat:array[4]] / _radius;
_focusPoint.x = [RCTConvert CGFloat:array[1]];
_focusPoint.y = [RCTConvert CGFloat:array[2]] / _radiusRatio;
_centerPoint.x = [RCTConvert CGFloat:array[5]];
_centerPoint.y = [RCTConvert CGFloat:array[6]] / _radiusRatio;
_gradient = CGGradientRetain([RCTConvert CGGradient:array offset:7]);
}
return self;
}
- (void)dealloc
{
CGGradientRelease(_gradient);
}
- (void)paint:(CGContextRef)context
{
CGAffineTransform transform = CGAffineTransformMakeScale(1, _radiusRatio);
CGContextConcatCTM(context, transform);
CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawRadialGradient(context, _gradient, _focusPoint, 0, _centerPoint, _radius, extendOptions);
}
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTBrush.h"
@interface ARTSolidColor : ARTBrush
@end

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTSolidColor.h>
#import <React/RCTLog.h>
#import "RCTConvert+ART.h"
@implementation ARTSolidColor
{
CGColorRef _color;
}
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{
if ((self = [super initWithArray:array])) {
_color = CGColorRetain([RCTConvert CGColor:array offset:1]);
}
return self;
}
- (void)dealloc
{
CGColorRelease(_color);
}
- (BOOL)applyFillColor:(CGContextRef)context
{
CGContextSetFillColorWithColor(context, _color);
return YES;
}
@end

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <QuartzCore/QuartzCore.h>
#import <React/RCTConvert.h>
#import "ARTBrush.h"
#import "ARTCGFloatArray.h"
#import "ARTTextFrame.h"
@interface RCTConvert (ART)
+ (CGPathRef)CGPath:(id)json CF_RETURNS_NOT_RETAINED;
+ (CTTextAlignment)CTTextAlignment:(id)json;
+ (ARTTextFrame)ARTTextFrame:(id)json;
+ (ARTCGFloatArray)ARTCGFloatArray:(id)json;
+ (ARTBrush *)ARTBrush:(id)json;
+ (CGPoint)CGPoint:(id)json offset:(NSUInteger)offset;
+ (CGRect)CGRect:(id)json offset:(NSUInteger)offset;
+ (CGColorRef)CGColor:(id)json offset:(NSUInteger)offset CF_RETURNS_NOT_RETAINED;
+ (CGGradientRef)CGGradient:(id)json offset:(NSUInteger)offset CF_RETURNS_NOT_RETAINED;
@end

View File

@ -0,0 +1,222 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTConvert+ART.h"
#import <React/RCTFont.h>
#import <React/RCTLog.h>
#import <React/ARTLinearGradient.h>
#import <React/ARTPattern.h>
#import <React/ARTRadialGradient.h>
#import <React/ARTSolidColor.h>
@implementation RCTConvert (ART)
+ (CGPathRef)CGPath:(id)json
{
NSArray *arr = [self NSNumberArray:json];
NSUInteger count = [arr count];
#define NEXT_VALUE [self double:arr[i++]]
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, 0);
@try {
NSUInteger i = 0;
while (i < count) {
NSUInteger type = [arr[i++] unsignedIntegerValue];
switch (type) {
case 0:
CGPathMoveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE);
break;
case 1:
CGPathCloseSubpath(path);
break;
case 2:
CGPathAddLineToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE);
break;
case 3:
CGPathAddCurveToPoint(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE);
break;
case 4:
CGPathAddArc(path, NULL, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE, NEXT_VALUE == 0);
break;
default:
RCTLogError(@"Invalid CGPath type %llu at element %llu of %@", (unsigned long long)type, (unsigned long long)i, arr);
CGPathRelease(path);
return NULL;
}
}
}
@catch (NSException *exception) {
RCTLogError(@"Invalid CGPath format: %@", arr);
CGPathRelease(path);
return NULL;
}
return (CGPathRef)CFAutorelease(path);
}
RCT_ENUM_CONVERTER(CTTextAlignment, (@{
@"auto": @(kCTTextAlignmentNatural),
@"left": @(kCTTextAlignmentLeft),
@"center": @(kCTTextAlignmentCenter),
@"right": @(kCTTextAlignmentRight),
@"justify": @(kCTTextAlignmentJustified),
}), kCTTextAlignmentNatural, integerValue)
// This takes a tuple of text lines and a font to generate a CTLine for each text line.
// This prepares everything for rendering a frame of text in ARTText.
+ (ARTTextFrame)ARTTextFrame:(id)json
{
NSDictionary *dict = [self NSDictionary:json];
ARTTextFrame frame;
frame.count = 0;
NSArray *lines = [self NSArray:dict[@"lines"]];
NSUInteger lineCount = [lines count];
if (lineCount == 0) {
return frame;
}
CTFontRef font = (__bridge CTFontRef)[self UIFont:dict[@"font"]];
if (!font) {
return frame;
}
// Create a dictionary for this font
CFDictionaryRef attributes = (__bridge CFDictionaryRef)@{
(NSString *)kCTFontAttributeName:(__bridge id)font,
(NSString *)kCTForegroundColorFromContextAttributeName: @YES
};
// Set up text frame with font metrics
CGFloat size = CTFontGetSize(font);
frame.count = lineCount;
frame.baseLine = size; // estimate base line
frame.lineHeight = size * 1.1; // Base on ART canvas line height estimate
frame.lines = malloc(sizeof(CTLineRef) * lineCount);
frame.widths = malloc(sizeof(CGFloat) * lineCount);
[lines enumerateObjectsUsingBlock:^(NSString *text, NSUInteger i, BOOL *stop) {
CFStringRef string = (__bridge CFStringRef)text;
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
CTLineRef line = CTLineCreateWithAttributedString(attrString);
CFRelease(attrString);
frame.lines[i] = line;
frame.widths[i] = CTLineGetTypographicBounds(line, NULL, NULL, NULL);
}];
return frame;
}
+ (ARTCGFloatArray)ARTCGFloatArray:(id)json
{
NSArray *arr = [self NSNumberArray:json];
NSUInteger count = arr.count;
ARTCGFloatArray array;
array.count = count;
array.array = NULL;
if (count) {
// Ideally, these arrays should already use the same memory layout.
// In that case we shouldn't need this new malloc.
array.array = malloc(sizeof(CGFloat) * count);
for (NSUInteger i = 0; i < count; i++) {
array.array[i] = [arr[i] doubleValue];
}
}
return array;
}
+ (ARTBrush *)ARTBrush:(id)json
{
NSArray *arr = [self NSArray:json];
NSUInteger type = [self NSUInteger:arr.firstObject];
switch (type) {
case 0: // solid color
// These are probably expensive allocations since it's often the same value.
// We should memoize colors but look ups may be just as expensive.
return [[ARTSolidColor alloc] initWithArray:arr];
case 1: // linear gradient
return [[ARTLinearGradient alloc] initWithArray:arr];
case 2: // radial gradient
return [[ARTRadialGradient alloc] initWithArray:arr];
case 3: // pattern
return [[ARTPattern alloc] initWithArray:arr];
default:
RCTLogError(@"Unknown brush type: %llu", (unsigned long long)type);
return nil;
}
}
+ (CGPoint)CGPoint:(id)json offset:(NSUInteger)offset
{
NSArray *arr = [self NSArray:json];
if (arr.count < offset + 2) {
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(2 + offset), arr);
return CGPointZero;
}
return (CGPoint){
[self CGFloat:arr[offset]],
[self CGFloat:arr[offset + 1]],
};
}
+ (CGRect)CGRect:(id)json offset:(NSUInteger)offset
{
NSArray *arr = [self NSArray:json];
if (arr.count < offset + 4) {
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr);
return CGRectZero;
}
return (CGRect){
{[self CGFloat:arr[offset]], [self CGFloat:arr[offset + 1]]},
{[self CGFloat:arr[offset + 2]], [self CGFloat:arr[offset + 3]]},
};
}
+ (CGColorRef)CGColor:(id)json offset:(NSUInteger)offset
{
NSArray *arr = [self NSArray:json];
if (arr.count < offset + 4) {
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)(4 + offset), arr);
return NULL;
}
return [self CGColor:[arr subarrayWithRange:(NSRange){offset, 4}]];
}
+ (CGGradientRef)CGGradient:(id)json offset:(NSUInteger)offset
{
NSArray *arr = [self NSArray:json];
if (arr.count < offset) {
RCTLogError(@"Too few elements in array (expected at least %llu): %@", (unsigned long long)offset, arr);
return NULL;
}
arr = [arr subarrayWithRange:(NSRange){offset, arr.count - offset}];
ARTCGFloatArray colorsAndOffsets = [self ARTCGFloatArray:arr];
size_t stops = colorsAndOffsets.count / 5;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(
rgb,
colorsAndOffsets.array,
colorsAndOffsets.array + stops * 4,
stops
);
CGColorSpaceRelease(rgb);
free(colorsAndOffsets.array);
return (CGGradientRef)CFAutorelease(gradient);
}
@end

View File

@ -0,0 +1,33 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
source[:commit] = `git rev-parse HEAD`.strip
else
source[:tag] = "v#{version}"
end
Pod::Spec.new do |s|
s.name = "React-ART"
s.version = version
s.summary = "A library for drawing vector graphics."
s.homepage = "https://reactnative.dev/"
s.license = package["license"]
s.author = "Facebook, Inc. and its affiliates"
s.platforms = { :ios => "10.0", :tvos => "10.0" }
s.source = source
s.source_files = "**/*.{m}"
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
s.header_dir = "ART"
s.dependency "React-Core/ARTHeaders", version
end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTNodeManager.h"
@interface ARTGroupManager : ARTNodeManager
@end

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTGroupManager.h>
#import <React/ARTGroup.h>
#import "RCTConvert+ART.h"
@implementation ARTGroupManager
RCT_EXPORT_MODULE()
- (ARTNode *)node
{
return [ARTGroup new];
}
RCT_EXPORT_VIEW_PROPERTY(clipping, CGRect)
@end

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTViewManager.h>
@class ARTNode;
@interface ARTNodeManager : RCTViewManager
- (ARTNode *)node;
@end

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTNodeManager.h>
#import <React/ARTNode.h>
@implementation ARTNodeManager
RCT_EXPORT_MODULE()
- (ARTNode *)node
{
return [ARTNode new];
}
- (UIView *)view
{
return [self node];
}
- (RCTShadowView *)shadowView
{
return nil;
}
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(transform, CGAffineTransform)
@end

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTNodeManager.h"
#import "ARTRenderable.h"
@interface ARTRenderableManager : ARTNodeManager
- (ARTRenderable *)node;
@end

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTRenderableManager.h>
#import "RCTConvert+ART.h"
@implementation ARTRenderableManager
RCT_EXPORT_MODULE()
- (ARTRenderable *)node
{
return [ARTRenderable new];
}
RCT_EXPORT_VIEW_PROPERTY(strokeWidth, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(strokeCap, CGLineCap)
RCT_EXPORT_VIEW_PROPERTY(strokeJoin, CGLineJoin)
RCT_EXPORT_VIEW_PROPERTY(fill, ARTBrush)
RCT_EXPORT_VIEW_PROPERTY(stroke, CGColor)
RCT_EXPORT_VIEW_PROPERTY(strokeDash, ARTCGFloatArray)
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTRenderableManager.h"
@interface ARTShapeManager : ARTRenderableManager
@end

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTShapeManager.h>
#import <React/ARTShape.h>
#import "RCTConvert+ART.h"
@implementation ARTShapeManager
RCT_EXPORT_MODULE()
- (ARTRenderable *)node
{
return [ARTShape new];
}
RCT_EXPORT_VIEW_PROPERTY(d, CGPath)
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTViewManager.h>
@interface ARTSurfaceViewManager : RCTViewManager
@end

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTSurfaceViewManager.h>
#import <React/ARTSurfaceView.h>
@implementation ARTSurfaceViewManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
return [ARTSurfaceView new];
}
@end

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "ARTRenderableManager.h"
@interface ARTTextManager : ARTRenderableManager
@end

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/ARTTextManager.h>
#import <React/ARTText.h>
#import "RCTConvert+ART.h"
@implementation ARTTextManager
RCT_EXPORT_MODULE()
- (ARTRenderable *)node
{
return [ARTText new];
}
RCT_EXPORT_VIEW_PROPERTY(alignment, CTTextAlignment)
RCT_REMAP_VIEW_PROPERTY(frame, textFrame, ARTTextFrame)
@end