Implement support for em in dx and dy attributes and font props for G element

This commit is contained in:
Mikael Sand
2017-06-20 03:15:01 +03:00
parent b094bc80f0
commit 155fa4b6ae
6 changed files with 117 additions and 64 deletions

View File

@@ -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;
}
}
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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}

View File

@@ -74,7 +74,12 @@ const RenderableAttributes = {
...FillAndStrokeAttributes
};
const GroupAttributes = RenderableAttributes;
const GroupAttributes = {
font: {
diff: fontDiffer
},
...RenderableAttributes
};
const UseAttributes = {
href: true,

View File

@@ -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];
}