mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-28 21:03:51 +00:00
Merge pull request #1494 from amgleitman/amgleitman/macos
Add macOS support
This commit is contained in:
+1
-1
@@ -4,5 +4,5 @@ Example/android/
|
||||
Example/ios/
|
||||
screenshots/
|
||||
android/
|
||||
ios/
|
||||
apple/
|
||||
src/lib/extract/transform.js
|
||||
|
||||
+13
-11
@@ -3,15 +3,17 @@ require 'json'
|
||||
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'RNSVG'
|
||||
s.version = package['version']
|
||||
s.summary = package['description']
|
||||
s.license = package['license']
|
||||
s.homepage = package['homepage']
|
||||
s.authors = 'Horcrux Chen'
|
||||
s.platforms = { :ios => "9.0", :tvos => "9.2" }
|
||||
s.source = { :git => 'https://github.com/react-native-community/react-native-svg.git', :tag => "v#{s.version}" }
|
||||
s.source_files = 'ios/**/*.{h,m}'
|
||||
s.requires_arc = true
|
||||
s.dependency 'React'
|
||||
s.name = 'RNSVG'
|
||||
s.version = package['version']
|
||||
s.summary = package['description']
|
||||
s.license = package['license']
|
||||
s.homepage = package['homepage']
|
||||
s.authors = 'Horcrux Chen'
|
||||
s.platforms = { :osx => "10.14", :ios => "9.0", :tvos => "9.2" }
|
||||
s.source = { :git => 'https://github.com/react-native-community/react-native-svg.git', :tag => "v#{s.version}" }
|
||||
s.source_files = 'apple/**/*.{h,m}'
|
||||
s.ios.exclude_files = '**/*.macos.{h,m}'
|
||||
s.osx.exclude_files = '**/*.ios.{h,m}'
|
||||
s.requires_arc = true
|
||||
s.dependency 'React'
|
||||
end
|
||||
|
||||
@@ -159,6 +159,11 @@ void PatternFunction(void* info, CGContextRef context)
|
||||
CGFloat h = [self getVal:[_points objectAtIndex:3] relative:height];
|
||||
|
||||
CGAffineTransform viewbox = [self.pattern.svgView getViewBoxTransform];
|
||||
#if TARGET_OS_OSX
|
||||
// This is needed because macOS and iOS have different conventions for where the origin is.
|
||||
// For macOS, it's in the bottom-left corner. For iOS, it's in the top-left corner.
|
||||
viewbox = CGAffineTransformScale(viewbox, 1, -1);
|
||||
#endif
|
||||
CGRect newBounds = CGRectMake(x, y, w, h);
|
||||
CGSize size = newBounds.size;
|
||||
self.useObjectBoundingBoxForContentUnits = _useContentObjectBoundingBox;
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
- (BOOL)isSimpleClipPath
|
||||
{
|
||||
NSArray<UIView*> *children = self.subviews;
|
||||
NSArray<RNSVGView*> *children = self.subviews;
|
||||
if (children.count == 1) {
|
||||
UIView* child = children[0];
|
||||
RNSVGView* child = children[0];
|
||||
if ([child class] != [RNSVGGroup class]) {
|
||||
return true;
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#import "RNSVGNode.h"
|
||||
|
||||
/**
|
||||
* RNSVG defination are implemented as abstract UIViews for all elements inside Defs.
|
||||
* RNSVG defination are implemented as abstract views for all elements inside Defs.
|
||||
*/
|
||||
|
||||
@interface RNSVGDefs : RNSVGNode
|
||||
@@ -27,7 +27,7 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
@implementation RNSVGForeignObject
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
__block CGRect bounds = CGRectNull;
|
||||
|
||||
[self traverseSubviews:^(UIView *node) {
|
||||
[self traverseSubviews:^(RNSVGView *node) {
|
||||
if ([node isKindOfClass:[RNSVGMask class]] || [node isKindOfClass:[RNSVGClipPath class]]) {
|
||||
// no-op
|
||||
} else if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||
@@ -7,7 +7,9 @@
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGContainer.h"
|
||||
#import "RNSVGCGFCRule.h"
|
||||
#import "RNSVGSvgView.h"
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
__block CGRect bounds = CGRectNull;
|
||||
|
||||
[self traverseSubviews:^(UIView *node) {
|
||||
[self traverseSubviews:^(RNSVGView *node) {
|
||||
if ([node isKindOfClass:[RNSVGMask class]] || [node isKindOfClass:[RNSVGClipPath class]]) {
|
||||
// no-op
|
||||
} else if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||
@@ -160,7 +160,7 @@
|
||||
return cached;
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||
@@ -192,7 +192,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
for (UIView *node in [self.subviews reverseObjectEnumerator]) {
|
||||
for (RNSVGView *node in [self.subviews reverseObjectEnumerator]) {
|
||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||
if ([node isKindOfClass:[RNSVGMask class]]) {
|
||||
continue;
|
||||
@@ -201,21 +201,21 @@
|
||||
if (event) {
|
||||
svgNode.active = NO;
|
||||
}
|
||||
UIView *hitChild = [svgNode hitTest:transformed withEvent:event];
|
||||
RNSVGPlatformView *hitChild = [svgNode hitTest:transformed withEvent:event];
|
||||
if (hitChild) {
|
||||
svgNode.active = YES;
|
||||
return (svgNode.responsible || (svgNode != hitChild)) ? hitChild : self;
|
||||
}
|
||||
} else if ([node isKindOfClass:[RNSVGSvgView class]]) {
|
||||
RNSVGSvgView* svgView = (RNSVGSvgView*)node;
|
||||
UIView *hitChild = [svgView hitTest:transformed withEvent:event];
|
||||
RNSVGPlatformView *hitChild = [svgView hitTest:transformed withEvent:event];
|
||||
if (hitChild) {
|
||||
return hitChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UIView *hitSelf = [super hitTest:transformed withEvent:event];
|
||||
RNSVGPlatformView *hitSelf = [super hitTest:transformed withEvent:event];
|
||||
if (hitSelf) {
|
||||
return hitSelf;
|
||||
}
|
||||
@@ -85,7 +85,7 @@
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
@implementation RNSVGMarker
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
@implementation RNSVGMask
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -103,7 +103,7 @@
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
@@ -6,14 +6,15 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGPainter.h"
|
||||
#import "RNSVGContainer.h"
|
||||
#import "RNSVGVBMOS.h"
|
||||
|
||||
@class RNSVGNode;
|
||||
|
||||
@interface RNSVGSvgView : UIView <RNSVGContainer>
|
||||
@interface RNSVGSvgView : RNSVGView <RNSVGContainer>
|
||||
|
||||
@property (nonatomic, strong) RNSVGLength *bbWidth;
|
||||
@property (nonatomic, strong) RNSVGLength *bbHeight;
|
||||
@@ -30,8 +31,6 @@
|
||||
@property (nonatomic, assign) CGAffineTransform invInitialCTM;
|
||||
@property (nonatomic, assign) CGAffineTransform viewBoxTransform;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* define <ClipPath></ClipPath> content as clipPath template.
|
||||
*/
|
||||
@@ -25,22 +25,24 @@
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
#if !TARGET_OS_OSX // Not available on macOS
|
||||
// This is necessary to ensure that [self setNeedsDisplay] actually triggers
|
||||
// a redraw when our parent transitions between hidden and visible.
|
||||
self.contentMode = UIViewContentModeRedraw;
|
||||
#endif
|
||||
rendered = false;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
||||
- (void)insertReactSubview:(RNSVGView *)subview atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:atIndex];
|
||||
[self insertSubview:subview atIndex:atIndex];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
- (void)removeReactSubview:(RNSVGView *)subview
|
||||
{
|
||||
[super removeReactSubview:subview];
|
||||
[self invalidate];
|
||||
@@ -66,7 +68,7 @@
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
UIView* parent = self.superview;
|
||||
RNSVGPlatformView* parent = self.superview;
|
||||
if ([parent isKindOfClass:[RNSVGNode class]]) {
|
||||
if (!rendered) {
|
||||
return;
|
||||
@@ -190,7 +192,7 @@
|
||||
_invviewBoxTransform = CGAffineTransformIdentity;
|
||||
}
|
||||
|
||||
for (UIView *node in self.subviews) {
|
||||
for (RNSVGView *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||
RNSVGNode *svg = (RNSVGNode *)node;
|
||||
[svg renderTo:context
|
||||
@@ -203,7 +205,7 @@
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
UIView* parent = self.superview;
|
||||
RNSVGPlatformView* parent = self.superview;
|
||||
if ([parent isKindOfClass:[RNSVGNode class]]) {
|
||||
return;
|
||||
}
|
||||
@@ -214,7 +216,7 @@
|
||||
_boundingBox = rect;
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
for (UIView *node in self.subviews) {
|
||||
for (RNSVGPlatformView *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||
RNSVGNode *svg = (RNSVGNode *)node;
|
||||
if (svg.responsible && !self.responsible) {
|
||||
@@ -228,7 +230,7 @@
|
||||
[self drawToContext:context withRect:rect];
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
CGPoint transformed = point;
|
||||
if (self.align) {
|
||||
@@ -243,7 +245,7 @@
|
||||
node.active = NO;
|
||||
}
|
||||
|
||||
UIView *hitChild = [node hitTest:transformed withEvent:event];
|
||||
RNSVGPlatformView *hitChild = [node hitTest:transformed withEvent:event];
|
||||
|
||||
if (hitChild) {
|
||||
node.active = YES;
|
||||
@@ -279,7 +281,7 @@
|
||||
return base64;
|
||||
}
|
||||
|
||||
- (void)reactSetInheritedBackgroundColor:(UIColor *)inheritedBackgroundColor
|
||||
- (void)reactSetInheritedBackgroundColor:(RNSVGColor *)inheritedBackgroundColor
|
||||
{
|
||||
self.backgroundColor = inheritedBackgroundColor;
|
||||
}
|
||||
@@ -113,7 +113,7 @@
|
||||
self.frame = bounds;
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
|
||||
RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href];
|
||||
@@ -122,7 +122,7 @@
|
||||
} else if (self.active) {
|
||||
return self;
|
||||
}
|
||||
UIView const* hitChild = [template hitTest:transformed withEvent:event];
|
||||
RNSVGPlatformView const* hitChild = [template hitTest:transformed withEvent:event];
|
||||
if (hitChild) {
|
||||
self.active = YES;
|
||||
return self;
|
||||
@@ -13,11 +13,11 @@
|
||||
@class RNSVGGroup;
|
||||
|
||||
/**
|
||||
* RNSVG nodes are implemented as base UIViews. They should be implementation for all basic
|
||||
* RNSVG nodes are implemented as base NSViews/UIViews. They should be implementation for all basic
|
||||
*interfaces for all non-definition nodes.
|
||||
*/
|
||||
|
||||
@interface RNSVGNode : UIView
|
||||
@interface RNSVGNode : RNSVGView
|
||||
|
||||
/*
|
||||
N[1/Sqrt[2], 36]
|
||||
@@ -132,7 +132,7 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
||||
|
||||
- (void)endTransparencyLayer:(CGContextRef)context;
|
||||
|
||||
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block;
|
||||
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGView *node))block;
|
||||
|
||||
- (void)clearChildCache;
|
||||
|
||||
@@ -46,14 +46,14 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
||||
- (void)insertReactSubview:(RNSVGView *)subview atIndex:(NSInteger)atIndex
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:atIndex];
|
||||
[self insertSubview:subview atIndex:atIndex];
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
- (void)removeReactSubview:(RNSVGView *)subview
|
||||
{
|
||||
[super removeReactSubview:subview];
|
||||
[self invalidate];
|
||||
@@ -98,7 +98,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
{
|
||||
RNSVGNode* node = self;
|
||||
while (node != nil) {
|
||||
UIView* parent = [node superview];
|
||||
RNSVGPlatformView* parent = [node superview];
|
||||
|
||||
if (![parent isKindOfClass:[RNSVGNode class]]) {
|
||||
return;
|
||||
@@ -124,7 +124,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
break;
|
||||
}
|
||||
|
||||
UIView* parent = [node superview];
|
||||
RNSVGPlatformView* parent = [node superview];
|
||||
|
||||
if (![node isKindOfClass:[RNSVGNode class]]) {
|
||||
node = nil;
|
||||
@@ -160,7 +160,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
return [glyphContext getFontSize];
|
||||
}
|
||||
|
||||
- (void)reactSetInheritedBackgroundColor:(UIColor *)inheritedBackgroundColor
|
||||
- (void)reactSetInheritedBackgroundColor:(RNSVGColor *)inheritedBackgroundColor
|
||||
{
|
||||
self.backgroundColor = inheritedBackgroundColor;
|
||||
}
|
||||
@@ -170,7 +170,11 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
_pointerEvents = pointerEvents;
|
||||
self.userInteractionEnabled = (pointerEvents != RCTPointerEventsNone);
|
||||
if (pointerEvents == RCTPointerEventsBoxNone) {
|
||||
#if TARGET_OS_OSX
|
||||
self.accessibilityModal = NO;
|
||||
#else
|
||||
self.accessibilityViewIsModal = NO;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +394,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
}
|
||||
|
||||
// hitTest delagate
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
|
||||
// abstract
|
||||
@@ -403,7 +407,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
return _svgView;
|
||||
}
|
||||
|
||||
__kindof UIView *parent = self.superview;
|
||||
__kindof RNSVGPlatformView *parent = self.superview;
|
||||
|
||||
if ([parent class] == [RNSVGSvgView class]) {
|
||||
_svgView = parent;
|
||||
@@ -587,9 +591,9 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)traverseSubviews:(BOOL (^)(__kindof UIView *node))block
|
||||
- (void)traverseSubviews:(BOOL (^)(__kindof RNSVGView *node))block
|
||||
{
|
||||
for (UIView *node in self.subviews) {
|
||||
for (RNSVGView *node in self.subviews) {
|
||||
if (!block(node)) {
|
||||
break;
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGBrush.h"
|
||||
#import "RNSVGCGFCRule.h"
|
||||
#import "RNSVGNode.h"
|
||||
@@ -513,7 +513,7 @@ UInt32 saturate(CGFloat value) {
|
||||
}
|
||||
|
||||
// hitTest delegate
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
- (RNSVGPlatformView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
if (!_hitArea) {
|
||||
return nil;
|
||||
@@ -0,0 +1,42 @@
|
||||
// Most (if not all) of this file could probably go away once react-native-macos's version of RCTUIKit.h makes its way upstream.
|
||||
// https://github.com/microsoft/react-native-macos/issues/242
|
||||
|
||||
#if !TARGET_OS_OSX
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define RNSVGColor UIColor
|
||||
#define RNSVGPlatformView UIView
|
||||
#define RNSVGTextView UILabel
|
||||
#define RNSVGView UIView
|
||||
|
||||
#else // TARGET_OS_OSX [
|
||||
|
||||
#import <React/RCTUIKit.h>
|
||||
|
||||
#define RNSVGColor NSColor
|
||||
#define RNSVGPlatformView NSView
|
||||
#define RNSVGTextView NSTextView
|
||||
|
||||
@interface RNSVGView : RCTUIView
|
||||
|
||||
@property CGPoint center;
|
||||
@property (nonatomic, strong) RNSVGColor *tintColor;
|
||||
|
||||
@end
|
||||
|
||||
// TODO: These could probably be a part of react-native-macos
|
||||
// See https://github.com/microsoft/react-native-macos/issues/658 and https://github.com/microsoft/react-native-macos/issues/659
|
||||
@interface NSImage (RNSVGMacOSExtensions)
|
||||
@property (readonly) CGImageRef CGImage;
|
||||
@end
|
||||
|
||||
@interface NSValue (RNSVGMacOSExtensions)
|
||||
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;
|
||||
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
|
||||
|
||||
@property (readonly) CGAffineTransform CGAffineTransformValue;
|
||||
@property (readonly) CGPoint CGPointValue;
|
||||
@end
|
||||
|
||||
#endif // ] TARGET_OS_OSX
|
||||
@@ -0,0 +1,86 @@
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
@implementation RNSVGView
|
||||
{
|
||||
NSColor *_tintColor;
|
||||
}
|
||||
|
||||
- (CGPoint)center
|
||||
{
|
||||
NSRect frameRect = self.frame;
|
||||
CGFloat xCenter = frameRect.origin.x + frameRect.size.width / 2;
|
||||
CGFloat yCenter = frameRect.origin.y + frameRect.size.height / 2;
|
||||
return CGPointMake(xCenter, yCenter);
|
||||
}
|
||||
|
||||
- (void)setCenter:(CGPoint)point
|
||||
{
|
||||
NSRect frameRect = self.frame;
|
||||
CGFloat xOrigin = frameRect.origin.x - frameRect.size.width / 2;
|
||||
CGFloat yOrigin = frameRect.origin.y - frameRect.size.height / 2;
|
||||
self.frame = CGRectMake(xOrigin, yOrigin, frameRect.size.width, frameRect.size.height);
|
||||
}
|
||||
|
||||
- (NSColor *)tintColor
|
||||
{
|
||||
if (_tintColor != nil) {
|
||||
return _tintColor;
|
||||
}
|
||||
|
||||
// To mimic iOS's tintColor, we crawl up the view hierarchy until either:
|
||||
// (a) we find a valid color
|
||||
// (b) we reach a view that isn't an RNSVGView
|
||||
NSView *parentView = [self superview];
|
||||
if ([parentView isKindOfClass:[RNSVGView class]]) {
|
||||
return [(RNSVGView *)parentView tintColor];
|
||||
} else {
|
||||
return [NSColor controlAccentColor];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTintColor:(NSColor *)tintColor
|
||||
{
|
||||
_tintColor = tintColor;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSImage (RNSVGMacOSExtensions)
|
||||
|
||||
- (CGImageRef) CGImage
|
||||
{
|
||||
return [self CGImageForProposedRect:NULL context:NULL hints:NULL];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSValue (RNSVGMacOSExtensions)
|
||||
|
||||
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform
|
||||
{
|
||||
return [NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)];
|
||||
}
|
||||
|
||||
+ (NSValue *)valueWithCGPoint:(CGPoint)point
|
||||
{
|
||||
return [NSValue valueWithBytes:&point objCType:@encode(CGPoint)];
|
||||
}
|
||||
|
||||
- (CGAffineTransform)CGAffineTransformValue
|
||||
{
|
||||
CGAffineTransform value;
|
||||
[self getValue:&value];
|
||||
return value;
|
||||
}
|
||||
|
||||
- (CGPoint)CGPointValue
|
||||
{
|
||||
CGPoint value;
|
||||
[self getValue:&value];
|
||||
return value;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,5 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGTextProperties.h"
|
||||
#import "RNSVGPropHelper.h"
|
||||
@@ -5,9 +5,12 @@
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreText/CoreText.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGText.h"
|
||||
|
||||
@interface RNSVGTSpan : RNSVGText
|
||||
@@ -6,36 +6,17 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
#import "RNSVGTSpan.h"
|
||||
#import "RNSVGUIKit.h"
|
||||
#import "RNSVGText.h"
|
||||
#import "RNSVGTextPath.h"
|
||||
#import "RNSVGTextProperties.h"
|
||||
#import "RNSVGTopAlignedLabel.h"
|
||||
#import "RNSVGPathMeasure.h"
|
||||
#import "RNSVGFontData.h"
|
||||
|
||||
static NSCharacterSet *RNSVGTSpan_separators = nil;
|
||||
static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
|
||||
|
||||
@interface TopAlignedLabel : UILabel
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation TopAlignedLabel
|
||||
|
||||
- (void)drawTextInRect:(CGRect) rect
|
||||
{
|
||||
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
|
||||
rect.size.height = [attributedText boundingRectWithSize:rect.size
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
context:nil].size.height;
|
||||
if (self.numberOfLines != 0) {
|
||||
rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
|
||||
}
|
||||
[super drawTextInRect:rect];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RNSVGTSpan
|
||||
{
|
||||
CGFloat startOffset;
|
||||
@@ -116,7 +97,7 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
|
||||
NSUInteger count = [emoji count];
|
||||
CGFloat fontSize = [gc getFontSize];
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
UILabel *label = [emoji objectAtIndex:i];
|
||||
RNSVGPlatformView *label = [emoji objectAtIndex:i];
|
||||
NSValue *transformValue = [emojiTransform objectAtIndex:i];
|
||||
CGAffineTransform transform = [transformValue CGAffineTransformValue];
|
||||
CGContextConcatCTM(context, transform);
|
||||
@@ -163,7 +144,7 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
|
||||
return attrs;
|
||||
}
|
||||
|
||||
TopAlignedLabel *label;
|
||||
RNSVGTopAlignedLabel *label;
|
||||
- (void)drawWrappedText:(CGContextRef)context gc:(RNSVGGlyphContext *)gc rect:(CGRect)rect color:(CGColorRef)color {
|
||||
[self pushGlyphContext];
|
||||
if (fontRef != nil) {
|
||||
@@ -198,17 +179,18 @@ TopAlignedLabel *label;
|
||||
|
||||
UIFont *font = (__bridge UIFont *)(fontRef);
|
||||
if (!label) {
|
||||
label = [[TopAlignedLabel alloc] init];
|
||||
label = [[RNSVGTopAlignedLabel alloc] init];
|
||||
}
|
||||
label.attributedText = (__bridge NSAttributedString * _Nullable)(attrString);
|
||||
label.baselineAdjustment = UIBaselineAdjustmentNone;
|
||||
label.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
label.backgroundColor = UIColor.clearColor;
|
||||
label.backgroundColor = RNSVGColor.clearColor;
|
||||
label.textAlignment = align;
|
||||
label.numberOfLines = 0;
|
||||
#if !TARGET_OS_OSX // On macOS, views are transparent by default
|
||||
label.opaque = NO;
|
||||
#endif
|
||||
label.font = font;
|
||||
label.textColor = [UIColor colorWithCGColor:color];
|
||||
label.textColor = [RNSVGColor colorWithCGColor:color];
|
||||
|
||||
CGFloat fontSize = [gc getFontSize];
|
||||
CGFloat height = CGRectGetHeight(rect);
|
||||
@@ -279,7 +261,7 @@ TopAlignedLabel *label;
|
||||
|
||||
NSString *str = self.content;
|
||||
if (!str) {
|
||||
for (UIView *node in self.subviews) {
|
||||
for (RNSVGView *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText *text = (RNSVGText*)node;
|
||||
advance += [text getSubtreeTextChunksTotalAdvance];
|
||||
@@ -1008,14 +990,18 @@ TopAlignedLabel *label;
|
||||
CGFloat width = box.size.width;
|
||||
|
||||
if (width == 0) { // Render unicode emoji
|
||||
UILabel *label = [[UILabel alloc] init];
|
||||
RNSVGTextView *label = [[RNSVGTextView alloc] init];
|
||||
CFIndex startIndex = indices[g];
|
||||
long len = MAX(1, endIndex - startIndex);
|
||||
NSRange range = NSMakeRange(startIndex, len);
|
||||
NSString* currChars = [str substringWithRange:range];
|
||||
#if TARGET_OS_OSX
|
||||
label.string = currChars;
|
||||
#else
|
||||
label.text = currChars;
|
||||
label.opaque = NO;
|
||||
label.backgroundColor = UIColor.clearColor;
|
||||
#endif
|
||||
label.backgroundColor = RNSVGColor.clearColor;
|
||||
UIFont * customFont = [UIFont systemFontOfSize:fontSize];
|
||||
|
||||
CGSize measuredSize = [currChars sizeWithAttributes:
|
||||
@@ -196,7 +196,7 @@
|
||||
return _alignmentBaseline;
|
||||
}
|
||||
|
||||
UIView* parent = self.superview;
|
||||
RNSVGPlatformView* parent = self.superview;
|
||||
while (parent != nil) {
|
||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText* node = (RNSVGText*)parent;
|
||||
@@ -221,7 +221,7 @@
|
||||
return _baselineShift;
|
||||
}
|
||||
|
||||
UIView* parent = [self superview];
|
||||
RNSVGPlatformView* parent = [self superview];
|
||||
while (parent != nil) {
|
||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText* node = (RNSVGText*)parent;
|
||||
@@ -271,7 +271,7 @@
|
||||
RNSVGGlyphContext* gc = [self.textRoot getGlyphContext];
|
||||
NSArray* font = [gc getFontContext];
|
||||
RNSVGText* node = self;
|
||||
UIView* parent = [self superview];
|
||||
RNSVGPlatformView* parent = [self superview];
|
||||
for (NSInteger i = [font count] - 1; i >= 0; i--) {
|
||||
RNSVGFontData* fontData = [font objectAtIndex:i];
|
||||
if (![parent isKindOfClass:[RNSVGText class]] ||
|
||||
@@ -291,7 +291,7 @@
|
||||
return cachedAdvance;
|
||||
}
|
||||
CGFloat advance = 0;
|
||||
for (UIView *node in self.subviews) {
|
||||
for (RNSVGView *node in self.subviews) {
|
||||
if ([node isKindOfClass:[RNSVGText class]]) {
|
||||
RNSVGText *text = (RNSVGText*)node;
|
||||
advance += [text getSubtreeTextChunksTotalAdvance];
|
||||
@@ -0,0 +1,13 @@
|
||||
#if TARGET_OS_OSX
|
||||
#import <React/RCTTextView.h>
|
||||
@interface RNSVGTopAlignedLabel : NSTextView
|
||||
|
||||
@property NSAttributedString *attributedText;
|
||||
@property NSLineBreakMode lineBreakMode;
|
||||
@property NSInteger numberOfLines;
|
||||
@property NSString *text;
|
||||
@property NSTextAlignment textAlignment;
|
||||
#else
|
||||
@interface RNSVGTopAlignedLabel : UILabel
|
||||
#endif
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
#import "RNSVGTopAlignedLabel.h"
|
||||
|
||||
@implementation RNSVGTopAlignedLabel
|
||||
|
||||
- (void)drawTextInRect:(CGRect) rect
|
||||
{
|
||||
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
|
||||
rect.size.height = [attributedText boundingRectWithSize:rect.size
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
context:nil].size.height;
|
||||
if (self.numberOfLines != 0) {
|
||||
rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
|
||||
}
|
||||
[super drawTextInRect:rect];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,55 @@
|
||||
#import "RNSVGTopAlignedLabel.h"
|
||||
|
||||
@implementation RNSVGTopAlignedLabel
|
||||
|
||||
- (NSAttributedString *)attributedText
|
||||
{
|
||||
return self.attributedString;
|
||||
}
|
||||
|
||||
- (NSLineBreakMode)lineBreakMode
|
||||
{
|
||||
return self.textContainer.lineBreakMode;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfLines
|
||||
{
|
||||
return self.textContainer.maximumNumberOfLines;
|
||||
}
|
||||
|
||||
- (NSString *)text
|
||||
{
|
||||
return self.string;
|
||||
}
|
||||
|
||||
- (NSTextAlignment)textAlignment
|
||||
{
|
||||
return self.alignment;
|
||||
}
|
||||
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedString
|
||||
{
|
||||
[self.textStorage setAttributedString:attributedString];
|
||||
}
|
||||
|
||||
- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode
|
||||
{
|
||||
self.textContainer.lineBreakMode = lineBreakMode;
|
||||
}
|
||||
|
||||
- (void)setNumberOfLines:(NSInteger)numberOfLines
|
||||
{
|
||||
self.textContainer.maximumNumberOfLines = numberOfLines;
|
||||
}
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
self.string = text;
|
||||
}
|
||||
|
||||
- (void)setTextAlignment:(NSTextAlignment)textAlignment
|
||||
{
|
||||
self.alignment = textAlignment;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -4,9 +4,10 @@
|
||||
https://github.com/erica/iOS-Drawing/tree/master/C08/Quartz%20Book%20Pack/Bezier
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#define RNSVGNULLPOINT CGRectNull.origin
|
||||
|
||||
@interface RNSVGBezierElement : NSObject
|
||||
@@ -1,4 +1,4 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#ifndef RNSVGLength_h
|
||||
#define RNSVGLength_h
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
typedef enum RNSVGMarkerType {
|
||||
kStartMarker,
|
||||
kMidMarker,
|
||||
@@ -6,7 +6,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
@interface RNSVGPathMeasure : NSObject
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
@interface RNSVGPathParser : NSObject
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RNSVGVBMOS.h"
|
||||
|
||||
@interface RNSVGViewBox : NSObject
|
||||
@@ -18,7 +18,7 @@ RCT_EXPORT_MODULE()
|
||||
return [RNSVGDefs new];
|
||||
}
|
||||
|
||||
- (UIView *)view
|
||||
- (RNSVGView *)view
|
||||
{
|
||||
return [self node];
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user