mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
Implement support for em in dx and dy attributes and font props for G element
This commit is contained in:
@@ -53,6 +53,24 @@ public class GlyphContext {
|
||||
mYContext = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void pushContext(@Nullable ReadableMap font) {
|
||||
PointF location = mCurrentLocation;
|
||||
|
||||
mDeltaContext.add(mCurrentDelta);
|
||||
|
||||
mCurrentDelta = clonePointF(mCurrentDelta);
|
||||
|
||||
mLocationContext.add(location);
|
||||
mFontContext.add(font);
|
||||
mDeltaXContext.add(new ArrayList<Float>());
|
||||
mDeltaYContext.add(new ArrayList<Float>());
|
||||
mXContext.add(location.x);
|
||||
mYContext.add(location.y);
|
||||
|
||||
mCurrentLocation = clonePointF(location);
|
||||
mContextLength++;
|
||||
}
|
||||
|
||||
public void pushContext(@Nullable ReadableMap font, @Nullable ReadableArray deltaX, @Nullable ReadableArray deltaY, @Nullable String positionX, @Nullable String positionY) {
|
||||
PointF location = mCurrentLocation;
|
||||
|
||||
@@ -194,10 +212,21 @@ public class GlyphContext {
|
||||
|
||||
private ArrayList<Float> getFloatArrayListFromReadableArray(ReadableArray readableArray) {
|
||||
ArrayList<Float> arrayList = new ArrayList<>();
|
||||
ReadableMap font = getGlyphFont();
|
||||
float fontSize = (float)font.getDouble("fontSize");
|
||||
|
||||
if (readableArray != null) {
|
||||
for (int i = 0; i < readableArray.size(); i++) {
|
||||
arrayList.add((float)readableArray.getDouble(i));
|
||||
switch (readableArray.getType(i)) {
|
||||
case String:
|
||||
String val = readableArray.getString(i);
|
||||
arrayList.add(Float.valueOf(val.substring(0, val.length() - 2)) * fontSize);
|
||||
break;
|
||||
|
||||
case Number:
|
||||
arrayList.add((float)readableArray.getDouble(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,11 @@ import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -24,8 +27,70 @@ import javax.annotation.Nullable;
|
||||
* Shadow node for virtual Group view
|
||||
*/
|
||||
public class GroupShadowNode extends RenderableShadowNode {
|
||||
protected @Nullable ReadableMap mFont;
|
||||
|
||||
private GlyphContext mGlyphContext;
|
||||
private GroupShadowNode mTextRoot;
|
||||
|
||||
@ReactProp(name = "font")
|
||||
public void setFont(@Nullable ReadableMap font) {
|
||||
mFont = font;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
protected GroupShadowNode getTextRoot() {
|
||||
if (mTextRoot == null) {
|
||||
mTextRoot = this;
|
||||
|
||||
while (mTextRoot != null) {
|
||||
if (mTextRoot.getClass() == GroupShadowNode.class) {
|
||||
break;
|
||||
}
|
||||
|
||||
ReactShadowNode parent = mTextRoot.getParent();
|
||||
|
||||
if (!(parent instanceof GroupShadowNode)) {
|
||||
//todo: throw exception here
|
||||
mTextRoot = null;
|
||||
} else {
|
||||
mTextRoot = (GroupShadowNode)parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mTextRoot;
|
||||
}
|
||||
|
||||
protected void setupGlyphContext() {
|
||||
mGlyphContext = new GlyphContext(mScale, getCanvasWidth(), getCanvasHeight());
|
||||
}
|
||||
|
||||
protected GlyphContext getGlyphContext() {
|
||||
return mGlyphContext;
|
||||
}
|
||||
|
||||
protected void pushGlyphContext() {
|
||||
getTextRoot().getGlyphContext().pushContext(mFont);
|
||||
}
|
||||
|
||||
protected void popGlyphContext() {
|
||||
getTextRoot().getGlyphContext().popContext();
|
||||
}
|
||||
|
||||
protected ReadableMap getFontFromContext() {
|
||||
return getTextRoot().getGlyphContext().getGlyphFont();
|
||||
}
|
||||
|
||||
protected PointF getGlyphPointFromContext(float offset, float glyphWidth) {
|
||||
return getTextRoot().getGlyphContext().getNextGlyphPoint(offset, glyphWidth);
|
||||
}
|
||||
|
||||
protected PointF getGlyphDeltaFromContext() {
|
||||
return getTextRoot().getGlyphContext().getNextGlyphDelta();
|
||||
}
|
||||
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
setupGlyphContext();
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
clip(canvas, paint);
|
||||
drawGroup(canvas, paint, opacity);
|
||||
@@ -33,6 +98,7 @@ public class GroupShadowNode extends RenderableShadowNode {
|
||||
}
|
||||
|
||||
protected void drawGroup(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
pushGlyphContext();
|
||||
final SvgViewShadowNode svg = getSvgShadowNode();
|
||||
final GroupShadowNode self = this;
|
||||
traverseChildren(new NodeRunnable() {
|
||||
@@ -57,6 +123,7 @@ public class GroupShadowNode extends RenderableShadowNode {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
popGlyphContext();
|
||||
}
|
||||
|
||||
protected void drawPath(Canvas canvas, Paint paint, float opacity) {
|
||||
|
||||
@@ -43,10 +43,6 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
private @Nullable ReadableArray mDeltaY;
|
||||
private @Nullable String mPositionX;
|
||||
private @Nullable String mPositionY;
|
||||
private @Nullable ReadableMap mFont;
|
||||
|
||||
private GlyphContext mGlyphContext;
|
||||
private TextShadowNode mTextRoot;
|
||||
|
||||
@ReactProp(name = "textAnchor", defaultInt = TEXT_ANCHOR_AUTO)
|
||||
public void setTextAnchor(int textAnchor) {
|
||||
@@ -108,12 +104,6 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
return groupPath;
|
||||
}
|
||||
|
||||
protected void drawGroup(Canvas canvas, Paint paint, float opacity) {
|
||||
pushGlyphContext();
|
||||
super.drawGroup(canvas, paint, opacity);
|
||||
popGlyphContext();
|
||||
}
|
||||
|
||||
private int getTextAnchor() {
|
||||
return mTextAnchor;
|
||||
}
|
||||
@@ -135,33 +125,6 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
return anchor;
|
||||
}
|
||||
|
||||
private TextShadowNode getTextRoot() {
|
||||
if (mTextRoot == null) {
|
||||
mTextRoot = this;
|
||||
|
||||
while (mTextRoot != null) {
|
||||
if (mTextRoot.getClass() == TextShadowNode.class) {
|
||||
break;
|
||||
}
|
||||
|
||||
ReactShadowNode parent = mTextRoot.getParent();
|
||||
|
||||
if (!(parent instanceof TextShadowNode)) {
|
||||
//todo: throw exception here
|
||||
mTextRoot = null;
|
||||
} else {
|
||||
mTextRoot = (TextShadowNode)parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mTextRoot;
|
||||
}
|
||||
|
||||
private void setupGlyphContext() {
|
||||
mGlyphContext = new GlyphContext(mScale, getCanvasWidth(), getCanvasHeight());
|
||||
}
|
||||
|
||||
protected void releaseCachedPath() {
|
||||
traverseChildren(new NodeRunnable() {
|
||||
public boolean run(VirtualNode node) {
|
||||
@@ -180,30 +143,11 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
return groupPath;
|
||||
}
|
||||
|
||||
protected GlyphContext getGlyphContext() {
|
||||
return mGlyphContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pushGlyphContext() {
|
||||
getTextRoot().getGlyphContext().pushContext(mFont, mDeltaX, mDeltaY, mPositionX, mPositionY);
|
||||
}
|
||||
|
||||
protected void popGlyphContext() {
|
||||
getTextRoot().getGlyphContext().popContext();
|
||||
}
|
||||
|
||||
protected ReadableMap getFontFromContext() {
|
||||
return getTextRoot().getGlyphContext().getGlyphFont();
|
||||
}
|
||||
|
||||
protected PointF getGlyphPointFromContext(float offset, float glyphWidth) {
|
||||
return getTextRoot().getGlyphContext().getNextGlyphPoint(offset, glyphWidth);
|
||||
}
|
||||
|
||||
protected PointF getGlyphDeltaFromContext() {
|
||||
return getTextRoot().getGlyphContext().getNextGlyphDelta();
|
||||
}
|
||||
|
||||
private Matrix getAlignMatrix(Path path) {
|
||||
RectF box = new RectF();
|
||||
path.computeBounds(box, true);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import React from 'react';
|
||||
import createReactNativeComponentClass from 'react-native/Libraries/Renderer/src/renderers/native/createReactNativeComponentClass';
|
||||
import Shape from './Shape';
|
||||
import {pathProps} from '../lib/props';
|
||||
import {pathProps, fontProps} from '../lib/props';
|
||||
import {GroupAttributes} from '../lib/attributes';
|
||||
import extractProps from '../lib/extract/extractProps';
|
||||
import {extractFont} from '../lib/extract/extractText';
|
||||
|
||||
export default class extends Shape{
|
||||
static displayName = 'G';
|
||||
|
||||
static propTypes = pathProps;
|
||||
static propTypes = {
|
||||
...pathProps,
|
||||
...fontProps,
|
||||
};
|
||||
|
||||
setNativeProps = (...args) => {
|
||||
this.root.setNativeProps(...args);
|
||||
@@ -19,6 +23,7 @@ export default class extends Shape{
|
||||
|
||||
return <RNSVGGroup
|
||||
{...extractProps(props, this)}
|
||||
font={extractFont(props)}
|
||||
ref={ele => {this.root = ele;}}
|
||||
>
|
||||
{props.children}
|
||||
|
||||
@@ -74,7 +74,12 @@ const RenderableAttributes = {
|
||||
...FillAndStrokeAttributes
|
||||
};
|
||||
|
||||
const GroupAttributes = RenderableAttributes;
|
||||
const GroupAttributes = {
|
||||
font: {
|
||||
diff: fontDiffer
|
||||
},
|
||||
...RenderableAttributes
|
||||
};
|
||||
|
||||
const UseAttributes = {
|
||||
href: true,
|
||||
|
||||
@@ -47,7 +47,7 @@ function parseFontString(font) {
|
||||
return cachedFontObjectsFromString[font];
|
||||
}
|
||||
|
||||
function extractFont(props) {
|
||||
export function extractFont(props) {
|
||||
let font = props.font;
|
||||
let fontSize = +props.fontSize;
|
||||
|
||||
@@ -68,8 +68,11 @@ function extractFont(props) {
|
||||
|
||||
function parseDelta(delta) {
|
||||
if (typeof delta === 'string') {
|
||||
if (isNaN(+delta)) {
|
||||
return delta.trim().replace(commaReg, ' ').split(spaceReg).map(d => +d || 0);
|
||||
const trim = delta.trim();
|
||||
if (trim.slice(-2) === 'em') {
|
||||
return [trim];
|
||||
} else if (isNaN(+delta)) {
|
||||
return trim.replace(commaReg, ' ').split(spaceReg).map(d => +d || 0);
|
||||
} else {
|
||||
return [+delta];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user