Harmonize parseSVGLengthList usage and naming. Probably requires api change in ios as well.

This commit is contained in:
Mikael Sand
2017-07-22 20:33:05 +03:00
parent 5372355b11
commit 6b022ac861
4 changed files with 106 additions and 76 deletions
@@ -18,6 +18,7 @@ import java.util.ArrayList;
import javax.annotation.Nullable; import javax.annotation.Nullable;
// https://www.w3.org/TR/SVG/text.html#TSpanElement
class GlyphContext { class GlyphContext {
static final float DEFAULT_FONT_SIZE = 12f; static final float DEFAULT_FONT_SIZE = 12f;
@@ -31,23 +32,23 @@ class GlyphContext {
// Unique input attribute lists (only added if node sets a value) // Unique input attribute lists (only added if node sets a value)
private final ArrayList<String[]> mXsContext = new ArrayList<>(); private final ArrayList<String[]> mXsContext = new ArrayList<>();
private final ArrayList<String[]> mYsContext = new ArrayList<>(); private final ArrayList<String[]> mYsContext = new ArrayList<>();
private final ArrayList<String[]> mdXsContext = new ArrayList<>();
private final ArrayList<String[]> mdYsContext = new ArrayList<>();
private final ArrayList<float[]> mRsContext = new ArrayList<>(); private final ArrayList<float[]> mRsContext = new ArrayList<>();
private final ArrayList<float[]> mdXsContext = new ArrayList<>();
private final ArrayList<float[]> mdYsContext = new ArrayList<>();
// Unique index into attribute list (one per unique list) // Unique index into attribute list (one per unique list)
private final ArrayList<Integer> mXIndices = new ArrayList<>(); private final ArrayList<Integer> mXIndices = new ArrayList<>();
private final ArrayList<Integer> mYIndices = new ArrayList<>(); private final ArrayList<Integer> mYIndices = new ArrayList<>();
private final ArrayList<Integer> mRIndices = new ArrayList<>();
private final ArrayList<Integer> mdXIndices = new ArrayList<>(); private final ArrayList<Integer> mdXIndices = new ArrayList<>();
private final ArrayList<Integer> mdYIndices = new ArrayList<>(); private final ArrayList<Integer> mdYIndices = new ArrayList<>();
private final ArrayList<Integer> mRIndices = new ArrayList<>();
// Index of unique context used (one per node push/pop) // Index of unique context used (one per node push/pop)
private final ArrayList<Integer> mXsIndices = new ArrayList<>(); private final ArrayList<Integer> mXsIndices = new ArrayList<>();
private final ArrayList<Integer> mYsIndices = new ArrayList<>(); private final ArrayList<Integer> mYsIndices = new ArrayList<>();
private final ArrayList<Integer> mRsIndices = new ArrayList<>();
private final ArrayList<Integer> mdXsIndices = new ArrayList<>(); private final ArrayList<Integer> mdXsIndices = new ArrayList<>();
private final ArrayList<Integer> mdYsIndices = new ArrayList<>(); private final ArrayList<Integer> mdYsIndices = new ArrayList<>();
private final ArrayList<Integer> mRsIndices = new ArrayList<>();
// Current stack (one per node push/pop) // Current stack (one per node push/pop)
private final ArrayList<ReadableMap> mFontContext = new ArrayList<>(); private final ArrayList<ReadableMap> mFontContext = new ArrayList<>();
@@ -57,31 +58,53 @@ class GlyphContext {
private double fontSize = DEFAULT_FONT_SIZE; private double fontSize = DEFAULT_FONT_SIZE;
// Current accumulated values // Current accumulated values
// https://www.w3.org/TR/SVG/types.html#DataTypeCoordinate
// <coordinate> syntax is the same as that for <length>
private float mx; private float mx;
private float my; private float my;
// https://www.w3.org/TR/SVG/types.html#Length
private float mdx; private float mdx;
private float mdy; private float mdy;
// Current attribute list // Current <list-of-coordinates> SVGLengthList
// https://www.w3.org/TR/SVG/types.html#InterfaceSVGLengthList
// https://www.w3.org/TR/SVG/types.html#DataTypeCoordinates
// https://www.w3.org/TR/SVG/text.html#TSpanElementXAttribute
private String[] mXs = new String[]{}; private String[] mXs = new String[]{};
// https://www.w3.org/TR/SVG/text.html#TSpanElementYAttribute
private String[] mYs = new String[]{}; private String[] mYs = new String[]{};
// Current <list-of-lengths> SVGLengthList
// https://www.w3.org/TR/SVG/types.html#DataTypeLengths
// https://www.w3.org/TR/SVG/text.html#TSpanElementDXAttribute
private String[] mdXs = new String[]{};
// https://www.w3.org/TR/SVG/text.html#TSpanElementDYAttribute
private String[] mdYs = new String[]{};
// Current <list-of-numbers> SVGLengthList
// https://www.w3.org/TR/SVG/types.html#DataTypeNumbers
// https://www.w3.org/TR/SVG/text.html#TSpanElementRotateAttribute
private float[] mRs = new float[]{0}; private float[] mRs = new float[]{0};
private float[] mdXs = new float[]{};
private float[] mdYs = new float[]{};
// Current attribute list index // Current attribute list index
private int mXsIndex; private int mXsIndex;
private int mYsIndex; private int mYsIndex;
private int mRsIndex;
private int mdXsIndex; private int mdXsIndex;
private int mdYsIndex; private int mdYsIndex;
private int mRsIndex;
// Current value index in current attribute list // Current value index in current attribute list
private int mXIndex = -1; private int mXIndex = -1;
private int mYIndex = -1; private int mYIndex = -1;
private int mRIndex = -1;
private int mdXIndex = -1; private int mdXIndex = -1;
private int mdYIndex = -1; private int mdYIndex = -1;
private int mRIndex = -1;
// Stack length and last index // Stack length and last index
private int mContextLength; private int mContextLength;
@@ -99,15 +122,15 @@ class GlyphContext {
mXsContext.add(mXs); mXsContext.add(mXs);
mYsContext.add(mYs); mYsContext.add(mYs);
mRsContext.add(mRs);
mdXsContext.add(mdXs); mdXsContext.add(mdXs);
mdYsContext.add(mdYs); mdYsContext.add(mdYs);
mRsContext.add(mRs);
mXIndices.add(mXIndex); mXIndices.add(mXIndex);
mYIndices.add(mYIndex); mYIndices.add(mYIndex);
mRIndices.add(mRIndex);
mdXIndices.add(mdXIndex); mdXIndices.add(mdXIndex);
mdYIndices.add(mdYIndex); mdYIndices.add(mdYIndex);
mRIndices.add(mRIndex);
pushIndices(); pushIndices();
} }
@@ -126,8 +149,8 @@ class GlyphContext {
boolean reset, boolean reset,
TextShadowNode node, TextShadowNode node,
@Nullable ReadableMap font, @Nullable ReadableMap font,
@Nullable String x, @Nullable ReadableArray x,
@Nullable String y, @Nullable ReadableArray y,
@Nullable ReadableArray rotate, @Nullable ReadableArray rotate,
@Nullable ReadableArray deltaX, @Nullable ReadableArray deltaX,
@Nullable ReadableArray deltaY @Nullable ReadableArray deltaY
@@ -143,35 +166,27 @@ class GlyphContext {
fontSize = getFontSize(); fontSize = getFontSize();
if (x != null) { if (x != null && x.size() != 0) {
mXsIndex++; mXsIndex++;
mXIndex = -1; mXIndex = -1;
mXIndices.add(mXIndex); mXIndices.add(mXIndex);
mXs = x.trim().split("\\s+"); mXs = getStringArrayFromReadableArray(x);
mXsContext.add(mXs); mXsContext.add(mXs);
} }
if (y != null) { if (y != null && y.size() != 0) {
mYsIndex++; mYsIndex++;
mYIndex = -1; mYIndex = -1;
mYIndices.add(mYIndex); mYIndices.add(mYIndex);
mYs = y.trim().split("\\s+"); mYs = getStringArrayFromReadableArray(y);
mYsContext.add(mYs); mYsContext.add(mYs);
} }
if (rotate != null && rotate.size() != 0) {
mRsIndex++;
mRIndex = -1;
mRIndices.add(mRIndex);
mRs = getFloatArrayFromReadableArray(rotate, 360);
mRsContext.add(mRs);
}
if (deltaX != null && deltaX.size() != 0) { if (deltaX != null && deltaX.size() != 0) {
mdXsIndex++; mdXsIndex++;
mdXIndex = -1; mdXIndex = -1;
mdXIndices.add(mdXIndex); mdXIndices.add(mdXIndex);
mdXs = getFloatArrayFromReadableArray(deltaX, mWidth / mScale); mdXs = getStringArrayFromReadableArray(deltaX);
mdXsContext.add(mdXs); mdXsContext.add(mdXs);
} }
@@ -179,33 +194,41 @@ class GlyphContext {
mdYsIndex++; mdYsIndex++;
mdYIndex = -1; mdYIndex = -1;
mdYIndices.add(mdYIndex); mdYIndices.add(mdYIndex);
mdYs = getFloatArrayFromReadableArray(deltaY, mHeight / mScale); mdYs = getStringArrayFromReadableArray(deltaY);
mdYsContext.add(mdYs); mdYsContext.add(mdYs);
} }
if (rotate != null && rotate.size() != 0) {
mRsIndex++;
mRIndex = -1;
mRIndices.add(mRIndex);
mRs = getFloatArrayFromReadableArray(rotate);
mRsContext.add(mRs);
}
pushIndices(); pushIndices();
} }
private void pushIndices() { private void pushIndices() {
mXsIndices.add(mXsIndex); mXsIndices.add(mXsIndex);
mYsIndices.add(mYsIndex); mYsIndices.add(mYsIndex);
mRsIndices.add(mRsIndex);
mdXsIndices.add(mdXsIndex); mdXsIndices.add(mdXsIndex);
mdYsIndices.add(mdYsIndex); mdYsIndices.add(mdYsIndex);
mRsIndices.add(mRsIndex);
} }
private void reset() { private void reset() {
mXsIndex = mYsIndex = mRsIndex = mdXsIndex = mdYsIndex = 0; mXsIndex = mYsIndex = mdXsIndex = mdYsIndex = mRsIndex = 0;
mXIndex = mYIndex = mRIndex = mdXIndex = mdYIndex = -1; mXIndex = mYIndex = mdXIndex = mdYIndex = mRIndex = -1;
mx = my = mdx = mdy = 0; mx = my = mdx = mdy = 0;
} }
void popContext() { void popContext() {
mXsIndices.remove(mContextLength); mXsIndices.remove(mContextLength);
mYsIndices.remove(mContextLength); mYsIndices.remove(mContextLength);
mRsIndices.remove(mContextLength);
mdXsIndices.remove(mContextLength); mdXsIndices.remove(mContextLength);
mdYsIndices.remove(mContextLength); mdYsIndices.remove(mContextLength);
mRsIndices.remove(mContextLength);
mContextLength--; mContextLength--;
top--; top--;
@@ -215,15 +238,15 @@ class GlyphContext {
int x = mXsIndex; int x = mXsIndex;
int y = mYsIndex; int y = mYsIndex;
int r = mRsIndex;
int dx = mdXsIndex; int dx = mdXsIndex;
int dy = mdYsIndex; int dy = mdYsIndex;
int r = mRsIndex;
mXsIndex = mXsIndices.get(mContextLength); mXsIndex = mXsIndices.get(mContextLength);
mYsIndex = mYsIndices.get(mContextLength); mYsIndex = mYsIndices.get(mContextLength);
mRsIndex = mRsIndices.get(mContextLength);
mdXsIndex = mdXsIndices.get(mContextLength); mdXsIndex = mdXsIndices.get(mContextLength);
mdYsIndex = mdYsIndices.get(mContextLength); mdYsIndex = mdYsIndices.get(mContextLength);
mRsIndex = mRsIndices.get(mContextLength);
if (x != mXsIndex) { if (x != mXsIndex) {
mXsContext.remove(x); mXsContext.remove(x);
@@ -235,11 +258,6 @@ class GlyphContext {
mYs = mYsContext.get(mYsIndex); mYs = mYsContext.get(mYsIndex);
mYIndex = mYIndices.get(mYsIndex); mYIndex = mYIndices.get(mYsIndex);
} }
if (r != mRsIndex) {
mRsContext.remove(r);
mRs = mRsContext.get(mRsIndex);
mRIndex = mRIndices.get(mRsIndex);
}
if (dx != mdXsIndex) { if (dx != mdXsIndex) {
mdXsContext.remove(dx); mdXsContext.remove(dx);
mdXs = mdXsContext.get(mdXsIndex); mdXs = mdXsContext.get(mdXsIndex);
@@ -250,6 +268,11 @@ class GlyphContext {
mdYs = mdYsContext.get(mdYsIndex); mdYs = mdYsContext.get(mdYsIndex);
mdYIndex = mdYIndices.get(mdYsIndex); mdYIndex = mdYIndices.get(mdYsIndex);
} }
if (r != mRsIndex) {
mRsContext.remove(r);
mRs = mRsContext.get(mRsIndex);
mRIndex = mRIndices.get(mRsIndex);
}
} }
private static void incrementIndices(ArrayList<Integer> indices, int topIndex) { private static void incrementIndices(ArrayList<Integer> indices, int topIndex) {
@@ -289,21 +312,14 @@ class GlyphContext {
return my; return my;
} }
float nextRotation() {
incrementIndices(mRIndices, mRsIndex);
mRIndex = Math.min(mRIndex + 1, mRs.length - 1);
return mRs[mRIndex];
}
float nextDeltaX() { float nextDeltaX() {
incrementIndices(mdXIndices, mdXsIndex); incrementIndices(mdXIndices, mdXsIndex);
int nextIndex = mdXIndex + 1; int nextIndex = mdXIndex + 1;
if (nextIndex < mdXs.length) { if (nextIndex < mdXs.length) {
mdXIndex = nextIndex; mdXIndex = nextIndex;
float val = mdXs[nextIndex]; String string = mdXs[nextIndex];
float val = PropHelper.fromRelativeToFloat(string, mWidth, 0, 1, fontSize);
mdx += val * mScale; mdx += val * mScale;
} }
@@ -316,13 +332,22 @@ class GlyphContext {
int nextIndex = mdYIndex + 1; int nextIndex = mdYIndex + 1;
if (nextIndex < mdYs.length) { if (nextIndex < mdYs.length) {
mdYIndex = nextIndex; mdYIndex = nextIndex;
float val = mdYs[nextIndex]; String string = mdYs[nextIndex];
float val = PropHelper.fromRelativeToFloat(string, mHeight, 0, 1, fontSize);
mdy += val * mScale; mdy += val * mScale;
} }
return mdy; return mdy;
} }
float nextRotation() {
incrementIndices(mRIndices, mRsIndex);
mRIndex = Math.min(mRIndex + 1, mRs.length - 1);
return mRs[mRIndex];
}
float getWidth() { float getWidth() {
return mWidth; return mWidth;
} }
@@ -400,20 +425,21 @@ class GlyphContext {
return map; return map;
} }
private float[] getFloatArrayFromReadableArray(ReadableArray readableArray, float dim) { private String[] getStringArrayFromReadableArray(ReadableArray readableArray) {
int size = readableArray.size();
String[] strings = new String[size];
for (int i = 0; i < size; i++) {
strings[i] = readableArray.getString(i);
}
return strings;
}
private float[] getFloatArrayFromReadableArray(ReadableArray readableArray) {
int size = readableArray.size(); int size = readableArray.size();
float[] floats = new float[size]; float[] floats = new float[size];
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
switch (readableArray.getType(i)) { String string = readableArray.getString(i);
case String: floats[i] = Float.valueOf(string);
String string = readableArray.getString(i);
floats[i] = PropHelper.fromRelativeToFloat(string, dim, 0, 1, fontSize);
break;
case Number:
floats[i] = (float) readableArray.getDouble(i);
break;
}
} }
return floats; return floats;
} }
@@ -180,9 +180,10 @@ class TSpanShadowNode extends TextShadowNode {
x = gc.nextX(width + kerning); x = gc.nextX(width + kerning);
y = gc.nextY(); y = gc.nextY();
r = gc.nextRotation();
dx = gc.nextDeltaX(); dx = gc.nextDeltaX();
dy = gc.nextDeltaY(); dy = gc.nextDeltaY();
r = gc.nextRotation();
matrix = new Matrix(); matrix = new Matrix();
float xSum = offset + x + dx - width; float xSum = offset + x + dx - width;
@@ -39,11 +39,11 @@ class TextShadowNode extends GroupShadowNode {
private int mTextAnchor = TEXT_ANCHOR_AUTO; private int mTextAnchor = TEXT_ANCHOR_AUTO;
private int mTextDecoration = TEXT_DECORATION_NONE; private int mTextDecoration = TEXT_DECORATION_NONE;
private @Nullable ReadableArray mRotate; private @Nullable ReadableArray mPositionX;
private @Nullable ReadableArray mDeltaX; private @Nullable ReadableArray mPositionY;
private @Nullable ReadableArray mDeltaX;
private @Nullable ReadableArray mDeltaY; private @Nullable ReadableArray mDeltaY;
private @Nullable String mPositionX; private @Nullable ReadableArray mRotate;
private @Nullable String mPositionY;
@ReactProp(name = "textAnchor") @ReactProp(name = "textAnchor")
public void setTextAnchor(int textAnchor) { public void setTextAnchor(int textAnchor) {
@@ -76,13 +76,13 @@ class TextShadowNode extends GroupShadowNode {
} }
@ReactProp(name = "positionX") @ReactProp(name = "positionX")
public void setPositionX(@Nullable String positionX) { public void setPositionX(@Nullable ReadableArray positionX) {
mPositionX = positionX; mPositionX = positionX;
markUpdated(); markUpdated();
} }
@ReactProp(name = "positionY") @ReactProp(name = "positionY")
public void setPositionY(@Nullable String positionY) { public void setPositionY(@Nullable ReadableArray positionY) {
mPositionY = positionY; mPositionY = positionY;
markUpdated(); markUpdated();
} }
+13 -10
View File
@@ -75,18 +75,20 @@ export function extractFont(props) {
return _.defaults(ownedFont, font); return _.defaults(ownedFont, font);
} }
function parseDelta(delta) { function parseSVGLengthList(delta) {
if (typeof delta === 'string') { if (typeof delta === 'string') {
return delta.trim().replace(commaReg, ' ').split(spaceReg); return delta.trim().replace(commaReg, ' ').split(spaceReg);
} else if (typeof delta === 'number') { } else if (typeof delta === 'number') {
return [delta]; return [delta.toString()];
} else if (delta && typeof delta.map === 'function') {
return delta.map(d => `${d}`);
} else { } else {
return []; return [];
} }
} }
export default function(props, container) { export default function(props, container) {
const { let {
x, x,
y, y,
dx, dx,
@@ -99,14 +101,15 @@ export default function(props, container) {
textDecoration textDecoration
} = props; } = props;
let positionX = parseSVGLengthList(x);
let positionY = parseSVGLengthList(y);
const deltaX = parseSVGLengthList(dx);
const deltaY = parseSVGLengthList(dy);
rotate = parseSVGLengthList(rotate);
const deltaX = parseDelta(dx);
const deltaY = parseDelta(dy);
const rotates = parseDelta(rotate);
let { children } = props; let { children } = props;
let content = null; let content = null;
if (typeof children === 'string' || typeof children === 'number') { if (typeof children === 'string' || typeof children === 'number') {
const childrenString = children.toString(); const childrenString = children.toString();
if (container) { if (container) {
@@ -131,13 +134,13 @@ export default function(props, container) {
font: extractFont(props), font: extractFont(props),
children, children,
content, content,
positionX,
positionY,
rotate,
deltaX, deltaX,
deltaY, deltaY,
rotate: rotates,
method, method,
spacing, spacing,
startOffset: (startOffset || 0).toString(), startOffset: (startOffset || 0).toString(),
positionX: _.isNil(x) ? null : x.toString(),
positionY: _.isNil(y) ? null : y.toString()
}; };
} }