Skip to content

Commit

Permalink
Implement intrinsic size
Browse files Browse the repository at this point in the history
  • Loading branch information
janicduplessis committed Mar 9, 2022
1 parent 82f0f3a commit 3bcd041
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 4 deletions.
6 changes: 3 additions & 3 deletions Example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ PODS:
- React-jsi (= 0.68.0-rc.1)
- React-logger (= 0.68.0-rc.1)
- React-perflogger (= 0.68.0-rc.1)
- RNSVG (12.2.0):
- RNSVG (12.3.0):
- React-Core
- SocketRocket (0.6.0)
- Yoga (1.14.0)
Expand Down Expand Up @@ -501,7 +501,7 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: bcdeff523be9f87a135b7c6fde8736db94904716
FBReactNativeSpec: 0c3f104f594b34d7b3a923cd12e03b0d4e12eaf5
FBReactNativeSpec: 7f11cf3f2edc35b35269c4ac7d907beba346188a
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c
Expand Down Expand Up @@ -540,7 +540,7 @@ SPEC CHECKSUMS:
React-RCTVibration: 5cab6419b68d5750482b0fc34dbb27af550469cc
React-runtimeexecutor: 10cda3a396b14a764a5f86088e7e3810b9c66cec
ReactCommon: 73a01eb83f22c84a6b09dfb60f3463888ebd4975
RNSVG: 4ecc2e8f38b6ebe7889909570c26f3abe8059767
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: d29dba374c1a582b40cfb736647b5e1b5ed35dba
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
64 changes: 64 additions & 0 deletions Example/src/examples/Svg.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,68 @@ class SvgNativeMethods extends Component {
}
}

class SvgAutoHeight extends Component {
static title = 'SVG with auto height';
render() {
return (
<Svg
width="50"
height="auto"
viewBox="0 0 100 100"
style={{backgroundColor: 'gray'}}>
<Circle
cx="50"
cy="50"
r="45"
stroke="blue"
strokeWidth="2.5"
fill="green"
/>
<Rect
x="15"
y="15"
width="70"
height="70"
stroke="red"
strokeWidth="2"
fill="yellow"
/>
</Svg>
);
}
}

class SvgAutoWidth extends Component {
static title = 'SVG with auto width';
render() {
return (
<Svg
width="auto"
height="75"
viewBox="0 0 100 100"
style={{backgroundColor: 'gray'}}>
<Circle
cx="50"
cy="50"
r="45"
stroke="blue"
strokeWidth="2.5"
fill="green"
/>
<Rect
x="15"
y="15"
width="70"
height="70"
stroke="red"
strokeWidth="2"
fill="yellow"
/>
</Svg>
);
}
}

const icon = (
<Svg height="30" width="30" viewBox="0 0 20 20">
<Circle cx="10" cy="10" r="8" stroke="blue" strokeWidth="1" fill="green" />
Expand All @@ -189,6 +251,8 @@ const samples = [
SvgOpacity,
SvgViewbox,
SvgLayout,
SvgAutoHeight,
SvgAutoWidth,
SvgNativeMethods,
];

Expand Down
2 changes: 1 addition & 1 deletion android/src/main/java/com/horcrux/svg/SVGLength.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private SVGLength(String length) {
length = length.trim();
int stringLength = length.length();
int percentIndex = stringLength - 1;
if (stringLength == 0 || length.equals("normal")) {
if (stringLength == 0 || length.equals("normal") || length.equals("auto")) {
unit = UnitType.UNKNOWN;
value = 0;
} else if (length.codePointAt(percentIndex) == '%') {
Expand Down
60 changes: 60 additions & 0 deletions android/src/main/java/com/horcrux/svg/SvgShadowNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2015-present, Horcrux.
* All rights reserved.
*
* This source code is licensed under the MIT-style license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.horcrux.svg;

import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.text.ReactBaseTextShadowNode;
import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaMeasureMode;
import com.facebook.yoga.YogaMeasureOutput;
import com.facebook.yoga.YogaNode;

public class SvgShadowNode extends ReactBaseTextShadowNode implements YogaMeasureFunction {
private float mVbWidth = 0;
private float mVbHeight = 0;

public SvgShadowNode() {
setMeasureFunction(this);
}

@ReactProp(name = "vbWidth")
public void setVbWidth(float vbWidth) {
mVbWidth = vbWidth;
}

@ReactProp(name = "vbHeight")
public void setVbHeight(float vbHeight) {
mVbHeight = vbHeight;
}

@Override
public long measure(
YogaNode node,
float baseWidth,
YogaMeasureMode widthMode,
float baseHeight,
YogaMeasureMode heightMode) {

float width = baseWidth;
float height = baseHeight;
float maxWidth = widthMode == YogaMeasureMode.AT_MOST ? width : Float.MAX_VALUE;
float maxHeight = heightMode == YogaMeasureMode.AT_MOST ? height : Float.MAX_VALUE;

if (mVbWidth != 0 && mVbHeight != 0) {
if (widthMode != YogaMeasureMode.EXACTLY) {
width = Math.min(mVbWidth / mVbHeight * height, maxWidth);
}
if (heightMode != YogaMeasureMode.EXACTLY) {
height = Math.min(mVbHeight / mVbWidth * width, maxHeight);
}
}

return YogaMeasureOutput.make(width, height);
}
}
5 changes: 5 additions & 0 deletions android/src/main/java/com/horcrux/svg/SvgViewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public SvgView createViewInstance(ThemedReactContext reactContext) {
return new SvgView(reactContext);
}

@Override
public SvgShadowNode createShadowNodeInstance() {
return new SvgShadowNode();
}

@Override
public void updateExtraData(ReactViewGroup root, Object extraData) {
super.updateExtraData(root, extraData);
Expand Down
24 changes: 24 additions & 0 deletions apple/ViewManagers/RNSVGSvgShadowView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) 2015-present, Horcrux.
* All rights reserved.
*
* 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 <React/RCTShadowView.h>

@class RCTBridge;

NS_ASSUME_NONNULL_BEGIN

@interface RNSVGSvgShadowView : RCTShadowView

@property (nonatomic, assign) CGFloat vbWidth;
@property (nonatomic, assign) CGFloat vbHeight;

@end

NS_ASSUME_NONNULL_END
57 changes: 57 additions & 0 deletions apple/ViewManagers/RNSVGSvgShadowView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2015-present, Horcrux.
* All rights reserved.
*
* This source code is licensed under the MIT-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "RNSVGSvgShadowView.h"

@implementation RNSVGSvgShadowView

- (instancetype)init
{
if (self = [super init]) {
YGNodeSetMeasureFunc(self.yogaNode, RNSVGSvgShadowViewMeasure);
}

return self;
}

static YGSize RNSVGSvgShadowViewMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode)
{
RNSVGSvgShadowView *shadowView = (__bridge RNSVGSvgShadowView *)YGNodeGetContext(node);

CGSize size = {width, height};
CGSize maximumSize = {
widthMode == YGMeasureModeAtMost ? size.width : CGFLOAT_MAX,
heightMode == YGMeasureModeAtMost ? size.height : CGFLOAT_MAX,
};
if (shadowView.vbWidth != 0 && shadowView.vbHeight != 0) {
if (widthMode != YGMeasureModeExactly) {
size.width = MIN(shadowView.vbWidth / shadowView.vbHeight * size.height, maximumSize.width);
}
if (heightMode != YGMeasureModeExactly) {
size.height = MIN(shadowView.vbHeight / shadowView.vbWidth * size.width, maximumSize.height);
}
}

return (YGSize){
RCTYogaFloatFromCoreGraphicsFloat(size.width),
RCTYogaFloatFromCoreGraphicsFloat(size.height),
};
}

- (BOOL)isYogaLeafNode
{
return YES;
}

- (void)layoutSubviewsWithContext:(RCTLayoutContext)layoutContext
{
// Do nothing.
}

@end

8 changes: 8 additions & 0 deletions apple/ViewManagers/RNSVGSvgViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import <React/RCTUIManagerUtils.h>
#import "RNSVGSvgViewManager.h"
#import "RNSVGSvgView.h"
#import "RNSVGSvgShadowView.h"

@implementation RNSVGSvgViewManager

Expand All @@ -21,6 +22,11 @@ - (RNSVGView *)view
return [RNSVGSvgView new];
}

- (RCTShadowView *)shadowView
{
return [RNSVGSvgShadowView new];
}

RCT_EXPORT_VIEW_PROPERTY(bbWidth, RNSVGLength*)
RCT_EXPORT_VIEW_PROPERTY(bbHeight, RNSVGLength*)
RCT_EXPORT_VIEW_PROPERTY(minX, CGFloat)
Expand All @@ -38,6 +44,8 @@ - (RNSVGView *)view
view.tintColor = [RCTConvert UIColor:json];
}

RCT_EXPORT_SHADOW_PROPERTY(vbWidth, CGFloat)
RCT_EXPORT_SHADOW_PROPERTY(vbHeight, CGFloat)

- (void)toDataURL:(nonnull NSNumber *)reactTag options:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback attempt:(int)attempt {
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,RNSVGView *> *viewRegistry) {
Expand Down

0 comments on commit 3bcd041

Please sign in to comment.