mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-06 16:32:24 +00:00
Refactor percentage props
This commit is contained in:
@@ -45,14 +45,15 @@ public class CircleShadowNode extends RenderableShadowNode {
|
||||
@Override
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
Path path = new Path();
|
||||
float cx = PropHelper.fromPercentageToFloat(mCx, mCanvasWidth, 0, mScale);
|
||||
float cy = PropHelper.fromPercentageToFloat(mCy, mCanvasHeight, 0, mScale);
|
||||
|
||||
float cx = relativeOnWidth(mCx);
|
||||
float cy = relativeOnHeight(mCy);
|
||||
|
||||
float r;
|
||||
if (PropHelper.isPercentage(mR)) {
|
||||
r = PropHelper.fromPercentageToFloat(mR, 1, 0, 1);
|
||||
float powX = (float)Math.pow((mCanvasWidth * r), 2);
|
||||
float powY = (float)Math.pow((mCanvasHeight * r), 2);
|
||||
float powX = (float)Math.pow((getCanvasWidth() * r), 2);
|
||||
float powY = (float)Math.pow((getCanvasHeight() * r), 2);
|
||||
r = (float)Math.sqrt(powX + powY) / (float)Math.sqrt(2);
|
||||
} else {
|
||||
r = Float.parseFloat(mR) * mScale;
|
||||
|
||||
@@ -53,10 +53,10 @@ public class EllipseShadowNode extends RenderableShadowNode {
|
||||
@Override
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
Path path = new Path();
|
||||
float cx = PropHelper.fromPercentageToFloat(mCx, mCanvasWidth, 0, mScale);
|
||||
float cy = PropHelper.fromPercentageToFloat(mCy, mCanvasHeight, 0, mScale);
|
||||
float rx = PropHelper.fromPercentageToFloat(mRx, mCanvasWidth, 0, mScale);
|
||||
float ry = PropHelper.fromPercentageToFloat(mRy, mCanvasHeight, 0, mScale);
|
||||
float cx = relativeOnWidth(mCx);
|
||||
float cy = relativeOnHeight(mCy);
|
||||
float rx = relativeOnWidth(mRx);
|
||||
float ry = relativeOnHeight(mRy);
|
||||
RectF oval = new RectF(cx - rx, cy - ry, cx + rx, cy + ry);
|
||||
path.addOval(oval, Path.Direction.CW);
|
||||
|
||||
|
||||
@@ -27,10 +27,8 @@ public class GroupShadowNode extends RenderableShadowNode {
|
||||
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
int count = saveAndSetupCanvas(canvas);
|
||||
clip(canvas, paint);
|
||||
drawGroup(canvas, paint, opacity);
|
||||
restoreCanvas(canvas, count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,10 +37,10 @@ public class GroupShadowNode extends RenderableShadowNode {
|
||||
final VirtualNode self = this;
|
||||
traverseChildren(new NodeRunnable() {
|
||||
public boolean run(VirtualNode node) {
|
||||
node.setupDimensions(canvas);
|
||||
|
||||
node.mergeProperties(self, mAttributeList, true);
|
||||
int count = node.saveAndSetupCanvas(canvas);
|
||||
node.draw(canvas, paint, opacity * mOpacity);
|
||||
node.restoreCanvas(canvas, count);
|
||||
node.markUpdateSeen();
|
||||
|
||||
if (node.isResponsible()) {
|
||||
@@ -63,7 +61,6 @@ public class GroupShadowNode extends RenderableShadowNode {
|
||||
|
||||
traverseChildren(new NodeRunnable() {
|
||||
public boolean run(VirtualNode node) {
|
||||
node.setupDimensions(canvas);
|
||||
path.addPath(node.getPath(canvas, paint));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,11 +107,8 @@ public class ImageShadowNode extends RenderableShadowNode {
|
||||
|
||||
@Override
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
mPath = getPath(canvas, paint);
|
||||
|
||||
if (!mLoading.get()) {
|
||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
|
||||
if (Fresco.getImagePipeline().isInBitmapMemoryCache(request)) {
|
||||
tryRender(request, canvas, paint, opacity * mOpacity);
|
||||
} else {
|
||||
@@ -153,18 +150,15 @@ public class ImageShadowNode extends RenderableShadowNode {
|
||||
|
||||
@Nonnull
|
||||
private Rect getRect() {
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale);
|
||||
float x = relativeOnWidth(mX);
|
||||
float y = relativeOnHeight(mY);
|
||||
float w = relativeOnWidth(mW);
|
||||
float h = relativeOnHeight(mH);
|
||||
|
||||
return new Rect((int) x, (int) y, (int) (x + w), (int) (y + h));
|
||||
}
|
||||
|
||||
private void doRender(Canvas canvas, Paint paint, Bitmap bitmap, float opacity) {
|
||||
final int count = saveAndSetupCanvas(canvas);
|
||||
canvas.concat(mMatrix);
|
||||
|
||||
Paint alphaPaint = new Paint();
|
||||
alphaPaint.setAlpha((int) (opacity * 255));
|
||||
|
||||
@@ -185,17 +179,9 @@ public class ImageShadowNode extends RenderableShadowNode {
|
||||
renderRect = new RectF(0, 0, (int)rectWidth, (int)(rectWidth / mImageRatio));
|
||||
}
|
||||
|
||||
ViewBoxShadowNode viewBox = new ViewBoxShadowNode();
|
||||
viewBox.setMinX("0");
|
||||
viewBox.setMinY("0");
|
||||
viewBox.setVbWidth(renderRect.width() / mScale + "");
|
||||
viewBox.setVbHeight(renderRect.height() / mScale + "");
|
||||
viewBox.setWidth(rectWidth / mScale + "");
|
||||
viewBox.setHeight(rectHeight / mScale + "");
|
||||
viewBox.setAlign(mAlign);
|
||||
viewBox.setMeetOrSlice(mMeetOrSlice);
|
||||
viewBox.setupDimensions(new Rect(0, 0, (int) rectWidth, (int) rectHeight));
|
||||
Matrix transform = viewBox.getTransform();
|
||||
RectF vbRect = new RectF(0, 0, renderRect.width() / mScale, renderRect.height() / mScale);
|
||||
RectF eRect = new RectF(getCanvasLeft(), getCanvasTop(), rectWidth / mScale + getCanvasLeft(), rectHeight / mScale + getCanvasTop());
|
||||
Matrix transform = ViewBoxShadowNode.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false);
|
||||
|
||||
transform.mapRect(renderRect);
|
||||
Matrix translation = new Matrix();
|
||||
@@ -205,30 +191,28 @@ public class ImageShadowNode extends RenderableShadowNode {
|
||||
Path clip = new Path();
|
||||
|
||||
Path clipPath = getClipPath(canvas, paint);
|
||||
|
||||
Path path = getPath(canvas, paint);
|
||||
if (clipPath != null) {
|
||||
// clip by the common area of clipPath and mPath
|
||||
clip.setFillType(Path.FillType.INVERSE_EVEN_ODD);
|
||||
|
||||
Path inverseWindingPath = new Path();
|
||||
inverseWindingPath.setFillType(Path.FillType.INVERSE_WINDING);
|
||||
inverseWindingPath.addPath(mPath);
|
||||
inverseWindingPath.addPath(path);
|
||||
inverseWindingPath.addPath(clipPath);
|
||||
|
||||
Path evenOddPath = new Path();
|
||||
evenOddPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
evenOddPath.addPath(mPath);
|
||||
evenOddPath.addPath(path);
|
||||
evenOddPath.addPath(clipPath);
|
||||
|
||||
canvas.clipPath(evenOddPath, Region.Op.DIFFERENCE);
|
||||
canvas.clipPath(inverseWindingPath, Region.Op.DIFFERENCE);
|
||||
} else {
|
||||
canvas.clipPath(mPath, Region.Op.REPLACE);
|
||||
canvas.clipPath(path, Region.Op.REPLACE);
|
||||
}
|
||||
|
||||
canvas.drawBitmap(bitmap, null, renderRect, alphaPaint);
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
}
|
||||
|
||||
private void tryRender(ImageRequest request, Canvas canvas, Paint paint, float opacity) {
|
||||
|
||||
@@ -51,10 +51,10 @@ public class LineShadowNode extends RenderableShadowNode {
|
||||
@Override
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
Path path = new Path();
|
||||
float x1 = PropHelper.fromPercentageToFloat(mX1, mCanvasWidth, 0, mScale);
|
||||
float y1 = PropHelper.fromPercentageToFloat(mY1, mCanvasHeight, 0, mScale);
|
||||
float x2 = PropHelper.fromPercentageToFloat(mX2, mCanvasWidth, 0, mScale);
|
||||
float y2 = PropHelper.fromPercentageToFloat(mY2, mCanvasHeight, 0, mScale);
|
||||
float x1 = relativeOnWidth(mX1);
|
||||
float y1 = relativeOnHeight(mY1);
|
||||
float x2 = relativeOnWidth(mX2);
|
||||
float y2 = relativeOnHeight(mY2);
|
||||
|
||||
path.moveTo(x1, y1);
|
||||
path.lineTo(x2, y2);
|
||||
|
||||
@@ -69,12 +69,12 @@ public class RectShadowNode extends RenderableShadowNode {
|
||||
@Override
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
Path path = new Path();
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale);
|
||||
float rx = PropHelper.fromPercentageToFloat(mRx, mCanvasWidth, 0, mScale);
|
||||
float ry = PropHelper.fromPercentageToFloat(mRy, mCanvasHeight, 0, mScale);
|
||||
float x = relativeOnWidth(mX);
|
||||
float y = relativeOnHeight(mY);
|
||||
float w = relativeOnWidth(mW);
|
||||
float h = relativeOnHeight(mH);
|
||||
float rx = relativeOnWidth(mRx);
|
||||
float ry = relativeOnHeight(mRy);
|
||||
|
||||
if (rx != 0 || ry != 0) {
|
||||
if (rx == 0) {
|
||||
|
||||
@@ -201,18 +201,12 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
if (mPath == null) {
|
||||
mPath = getPath(canvas, paint);
|
||||
mPath.setFillType(mFillRule);
|
||||
}
|
||||
|
||||
opacity *= mOpacity;
|
||||
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
int count = saveAndSetupCanvas(canvas);
|
||||
if (mPath == null) {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Paths should have a valid path (d) prop");
|
||||
mPath = getPath(canvas, paint);
|
||||
mPath.setFillType(mFillRule);
|
||||
}
|
||||
|
||||
clip(canvas, paint);
|
||||
@@ -222,9 +216,6 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
||||
if (setupStrokePaint(paint, opacity * mStrokeOpacity, null)) {
|
||||
canvas.drawPath(mPath, paint);
|
||||
}
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,39 +294,39 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(
|
||||
mCanvasWidth,
|
||||
mCanvasHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
if (matrix != null) {
|
||||
canvas.concat(matrix);
|
||||
}
|
||||
|
||||
canvas.concat(mMatrix);
|
||||
|
||||
Paint paint = new Paint();
|
||||
clip(canvas, paint);
|
||||
setHitTestFill(paint);
|
||||
canvas.drawPath(mPath, paint);
|
||||
|
||||
if (setHitTestStroke(paint)) {
|
||||
canvas.drawPath(mPath, paint);
|
||||
}
|
||||
|
||||
canvas.setBitmap(bitmap);
|
||||
try {
|
||||
if (bitmap.getPixel(point.x, point.y) != 0) {
|
||||
return getReactTag();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
return -1;
|
||||
} finally {
|
||||
bitmap.recycle();
|
||||
}
|
||||
// Bitmap bitmap = Bitmap.createBitmap(
|
||||
// mCanvasWidth,
|
||||
// mCanvasHeight,
|
||||
// Bitmap.Config.ARGB_8888);
|
||||
//
|
||||
// Canvas canvas = new Canvas(bitmap);
|
||||
//
|
||||
// if (matrix != null) {
|
||||
// canvas.concat(matrix);
|
||||
// }
|
||||
//
|
||||
// canvas.concat(mMatrix);
|
||||
//
|
||||
// Paint paint = new Paint();
|
||||
// clip(canvas, paint);
|
||||
// setHitTestFill(paint);
|
||||
// canvas.drawPath(mPath, paint);
|
||||
//
|
||||
// if (setHitTestStroke(paint)) {
|
||||
// canvas.drawPath(mPath, paint);
|
||||
// }
|
||||
//
|
||||
// canvas.setBitmap(bitmap);
|
||||
// try {
|
||||
// if (bitmap.getPixel(point.x, point.y) != 0) {
|
||||
// return getReactTag();
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
//
|
||||
// return -1;
|
||||
// } finally {
|
||||
// bitmap.recycle();
|
||||
// }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -377,15 +368,14 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
||||
String fieldName = mergeList.getString(i);
|
||||
Field field = getClass().getField(fieldName);
|
||||
Object value = field.get(target);
|
||||
mOriginProperties.add(field.get(this));
|
||||
|
||||
if (inherited) {
|
||||
if (!hasOwnProperty(fieldName)) {
|
||||
mAttributeList.pushString(fieldName);
|
||||
mOriginProperties.add(field.get(this));
|
||||
field.set(this, value);
|
||||
}
|
||||
} else {
|
||||
mOriginProperties.add(field.get(this));
|
||||
field.set(this, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -13,6 +13,8 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Base64;
|
||||
@@ -42,6 +44,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
private final Map<String, VirtualNode> mDefinedClipPaths = new HashMap<>();
|
||||
private final Map<String, VirtualNode> mDefinedTemplates = new HashMap<>();
|
||||
private final Map<String, PropHelper.RNSVGBrush> mDefinedBrushes = new HashMap<>();
|
||||
private Canvas mCanvas;
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
@@ -71,12 +74,18 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
(int) getLayoutHeight(),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawChildren(canvas);
|
||||
mCanvas = new Canvas(bitmap);
|
||||
drawChildren(mCanvas);
|
||||
mCanvas = null;
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public Rect getCanvasBounds() {
|
||||
return mCanvas.getClipBounds();
|
||||
}
|
||||
|
||||
private void drawChildren(Canvas canvas) {
|
||||
canvas.getClipBounds();
|
||||
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
Paint paint = new Paint();
|
||||
|
||||
@@ -86,9 +95,11 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
|
||||
VirtualNode child = (VirtualNode) getChildAt(i);
|
||||
child.setupDimensions(canvas);
|
||||
child.saveDefinition();
|
||||
|
||||
int count = child.saveAndSetupCanvas(canvas);
|
||||
child.draw(canvas, paint, 1f);
|
||||
child.restoreCanvas(canvas, count);
|
||||
child.markUpdateSeen();
|
||||
|
||||
if (child.isResponsible() && !mResponsible) {
|
||||
|
||||
@@ -75,8 +75,6 @@ public class TSpanShadowNode extends TextShadowNode {
|
||||
}
|
||||
|
||||
setupTextPath();
|
||||
setupDimensions(canvas);
|
||||
|
||||
Path path = new Path();
|
||||
|
||||
pushGlyphContext();
|
||||
|
||||
@@ -51,8 +51,7 @@ public class TextPathShadowNode extends TextShadowNode {
|
||||
}
|
||||
|
||||
PathShadowNode path = (PathShadowNode)template;
|
||||
|
||||
return new BezierTransformer(path.getBezierCurves(), PropHelper.fromPercentageToFloat(mStartOffset, mCanvasWidth, 0, mScale));
|
||||
return new BezierTransformer(path.getBezierCurves(), relativeOnWidth(mStartOffset));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -90,42 +90,30 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
setupGlyphContext();
|
||||
clip(canvas, paint);
|
||||
|
||||
int count = canvas.save();
|
||||
setupGlyphContext(canvas);
|
||||
|
||||
Path path = getGroupPath(canvas, paint);
|
||||
Matrix matrix = getAlignMatrix(path);
|
||||
canvas.concat(matrix);
|
||||
drawGroup(canvas, paint, opacity);
|
||||
releaseCachedPath();
|
||||
|
||||
mPath = path;
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
setupGlyphContext(canvas);
|
||||
setupGlyphContext();
|
||||
Path groupPath = getGroupPath(canvas, paint);
|
||||
Matrix matrix = getAlignMatrix(groupPath);
|
||||
groupPath.transform(mMatrix);
|
||||
groupPath.transform(matrix);
|
||||
|
||||
releaseCachedPath();
|
||||
return groupPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGroup(Canvas canvas, Paint paint, float opacity) {
|
||||
pushGlyphContext();
|
||||
int count = canvas.save();
|
||||
canvas.concat(mMatrix);
|
||||
super.drawGroup(canvas, paint, opacity);
|
||||
restoreCanvas(canvas, count);
|
||||
popGlyphContext();
|
||||
}
|
||||
|
||||
@@ -170,9 +158,8 @@ public class TextShadowNode extends GroupShadowNode {
|
||||
return mTextRoot;
|
||||
}
|
||||
|
||||
protected void setupGlyphContext(Canvas canvas) {
|
||||
setupDimensions(canvas);
|
||||
mGlyphContext = new GlyphContext(mScale, mCanvasWidth, mCanvasHeight);
|
||||
protected void setupGlyphContext() {
|
||||
mGlyphContext = new GlyphContext(mScale, getCanvasWidth(), getCanvasHeight());
|
||||
}
|
||||
|
||||
protected void releaseCachedPath() {
|
||||
|
||||
@@ -57,15 +57,12 @@ public class UseShadowNode extends RenderableShadowNode {
|
||||
VirtualNode template = getSvgShadowNode().getDefinedTemplate(mHref);
|
||||
|
||||
if (template != null) {
|
||||
int count = saveAndSetupCanvas(canvas);
|
||||
|
||||
clip(canvas, paint);
|
||||
template.mergeProperties(this, mAttributeList, true);
|
||||
int count = template.saveAndSetupCanvas(canvas);
|
||||
clip(canvas, paint);
|
||||
template.draw(canvas, paint, opacity * mOpacity);
|
||||
template.restoreCanvas(canvas, count);
|
||||
template.resetProperties();
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
} else {
|
||||
FLog.w(ReactConstants.TAG, "`Use` element expected a pre-defined svg template as `href` prop, " +
|
||||
"template named: " + mHref + " is not defined.");
|
||||
|
||||
@@ -12,6 +12,7 @@ package com.horcrux.svg;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
@@ -85,26 +86,42 @@ public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
setupDimensions(canvas);
|
||||
mMatrix = getTransform();
|
||||
super.draw(canvas, paint, opacity);
|
||||
protected int saveAndSetupCanvas(Canvas canvas) {
|
||||
mMatrix = getTransformFromProps();
|
||||
return super.saveAndSetupCanvas(canvas);
|
||||
}
|
||||
|
||||
public Matrix getTransform() {
|
||||
private Matrix getTransformFromProps() {
|
||||
|
||||
float vbX = relativeOnWidth(mMinX);
|
||||
float vbY = relativeOnHeight(mMinY);
|
||||
float vbWidth = relativeOnWidth(mVbWidth);
|
||||
float vbHeight = relativeOnHeight(mVbHeight);
|
||||
|
||||
|
||||
float eX = getCanvasLeft();
|
||||
float eY = getCanvasTop();
|
||||
float eWidth = mBoxWidth != null ? relativeOnWidth(mBoxWidth) : getCanvasWidth();
|
||||
float eHeight = mBoxHeight != null ? relativeOnHeight(mBoxHeight) : getCanvasHeight();
|
||||
|
||||
return getTransform(new RectF(vbX, vbY, vbWidth + vbX, vbHeight + vbY), new RectF(eX, eY, eWidth + eX, eHeight + eY), mAlign, mMeetOrSlice, mFromSymbol);
|
||||
}
|
||||
|
||||
static public Matrix getTransform(RectF vbRect, RectF eRect, String align, int meetOrSlice, boolean fromSymbol) {
|
||||
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||
|
||||
// Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively.
|
||||
float vbX = PropHelper.fromPercentageToFloat(mMinX, mCanvasWidth, 0, mScale);
|
||||
float vbY = PropHelper.fromPercentageToFloat(mMinY, mCanvasHeight, 0, mScale);
|
||||
float vbWidth = PropHelper.fromPercentageToFloat(mVbWidth, mCanvasWidth, 0, mScale);
|
||||
float vbHeight = PropHelper.fromPercentageToFloat(mVbHeight, mCanvasHeight, 0, mScale);
|
||||
float vbX = vbRect.left;
|
||||
float vbY = vbRect.top;
|
||||
float vbWidth = vbRect.width();
|
||||
float vbHeight = vbRect.height();
|
||||
|
||||
// Let e-x, e-y, e-width, e-height be the position and size of the element respectively.
|
||||
float eX = mCanvasX;
|
||||
float eY = mCanvasY;
|
||||
float eWidth = mBoxWidth != null ? PropHelper.fromPercentageToFloat(mBoxWidth, mCanvasWidth, 0, mScale) : mCanvasWidth;
|
||||
float eHeight = mBoxHeight != null ? PropHelper.fromPercentageToFloat(mBoxHeight, mCanvasHeight, 0, mScale) : mCanvasHeight;
|
||||
float eX = eRect.left;
|
||||
float eY = eRect.top;
|
||||
float eWidth = eRect.width();
|
||||
float eHeight = eRect.height();
|
||||
|
||||
|
||||
// Initialize scale-x to e-width/vb-width.
|
||||
float scaleX = eWidth / vbWidth;
|
||||
@@ -118,7 +135,7 @@ public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
float translateY = vbY - eY;
|
||||
|
||||
// If align is 'none'
|
||||
if (mMeetOrSlice == MOS_NONE) {
|
||||
if (meetOrSlice == MOS_NONE) {
|
||||
// Let scale be set the smaller value of scale-x and scale-y.
|
||||
// Assign scale-x and scale-y to scale.
|
||||
float scale = scaleX = scaleY = Math.min(scaleX, scaleY);
|
||||
@@ -137,29 +154,29 @@ public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
// If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller.
|
||||
// Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the larger.
|
||||
|
||||
if (!mAlign.equals("none") && mMeetOrSlice == MOS_MEET) {
|
||||
if (!align.equals("none") && meetOrSlice == MOS_MEET) {
|
||||
scaleX = scaleY = Math.min(scaleX, scaleY);
|
||||
} else if (!mAlign.equals("none") && mMeetOrSlice == MOS_SLICE) {
|
||||
} else if (!align.equals("none") && meetOrSlice == MOS_SLICE) {
|
||||
scaleX = scaleY = Math.max(scaleX, scaleY);
|
||||
}
|
||||
|
||||
// If align contains 'xMid', minus (e-width / scale-x - vb-width) / 2 from transform-x.
|
||||
if (mAlign.contains("xMid")) {
|
||||
if (align.contains("xMid")) {
|
||||
translateX -= (eWidth / scaleX - vbWidth) / 2;
|
||||
}
|
||||
|
||||
// If align contains 'xMax', minus (e-width / scale-x - vb-width) from transform-x.
|
||||
if (mAlign.contains("xMax")) {
|
||||
if (align.contains("xMax")) {
|
||||
translateX -= eWidth / scaleX - vbWidth;
|
||||
}
|
||||
|
||||
// If align contains 'yMid', minus (e-height / scale-y - vb-height) / 2 from transform-y.
|
||||
if (mAlign.contains("YMid")) {
|
||||
if (align.contains("YMid")) {
|
||||
translateY -= (eHeight / scaleY - vbHeight) / 2;
|
||||
}
|
||||
|
||||
// If align contains 'yMax', minus (e-height / scale-y - vb-height) from transform-y.
|
||||
if (mAlign.contains("YMax")) {
|
||||
if (align.contains("YMax")) {
|
||||
translateY -= eHeight / scaleY - vbHeight;
|
||||
}
|
||||
|
||||
@@ -168,7 +185,7 @@ public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
// The transform applied to content contained by the element is given by
|
||||
// translate(translate-x, translate-y) scale(scale-x, scale-y).
|
||||
Matrix transform = new Matrix();
|
||||
transform.postTranslate(-translateX * (mFromSymbol ? scaleX : 1), -translateY * (mFromSymbol ? scaleY : 1));
|
||||
transform.postTranslate(-translateX * (fromSymbol ? scaleX : 1), -translateY * (fromSymbol ? scaleY : 1));
|
||||
transform.postScale(scaleX, scaleY);
|
||||
return transform;
|
||||
}
|
||||
|
||||
@@ -37,23 +37,14 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
protected float mOpacity = 1f;
|
||||
protected Matrix mMatrix = new Matrix();
|
||||
|
||||
private int mClipRule;
|
||||
protected @Nullable String mClipPath;
|
||||
|
||||
private static final int PATH_TYPE_CLOSE = 1;
|
||||
private static final int PATH_TYPE_CURVETO = 3;
|
||||
private static final int PATH_TYPE_LINETO = 2;
|
||||
private static final int PATH_TYPE_MOVETO = 0;
|
||||
|
||||
private static final int CLIP_RULE_EVENODD = 0;
|
||||
private static final int CLIP_RULE_NONZERO = 1;
|
||||
|
||||
protected final float mScale;
|
||||
private int mClipRule;
|
||||
protected boolean mResponsible;
|
||||
protected int mCanvasX;
|
||||
protected int mCanvasY;
|
||||
protected int mCanvasWidth;
|
||||
protected int mCanvasHeight;
|
||||
protected String mName;
|
||||
|
||||
private SvgViewShadowNode mSvgShadowNode;
|
||||
@@ -78,8 +69,8 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
*
|
||||
* @param canvas the canvas to set up
|
||||
*/
|
||||
protected final int saveAndSetupCanvas(Canvas canvas) {
|
||||
final int count = canvas.save();
|
||||
protected int saveAndSetupCanvas(Canvas canvas) {
|
||||
int count = canvas.save();
|
||||
canvas.concat(mMatrix);
|
||||
return count;
|
||||
}
|
||||
@@ -124,7 +115,16 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
if (matrixArray != null) {
|
||||
int matrixSize = PropHelper.toFloatArray(matrixArray, sMatrixData);
|
||||
if (matrixSize == 6) {
|
||||
setupMatrix();
|
||||
sRawMatrix[0] = sMatrixData[0];
|
||||
sRawMatrix[1] = sMatrixData[2];
|
||||
sRawMatrix[2] = sMatrixData[4] * mScale;
|
||||
sRawMatrix[3] = sMatrixData[1];
|
||||
sRawMatrix[4] = sMatrixData[3];
|
||||
sRawMatrix[5] = sMatrixData[5] * mScale;
|
||||
sRawMatrix[6] = 0;
|
||||
sRawMatrix[7] = 0;
|
||||
sRawMatrix[8] = 1;
|
||||
mMatrix.setValues(sRawMatrix);
|
||||
} else if (matrixSize != -1) {
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: Transform matrices must be of size 6");
|
||||
}
|
||||
@@ -141,19 +141,6 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
protected void setupMatrix() {
|
||||
sRawMatrix[0] = sMatrixData[0];
|
||||
sRawMatrix[1] = sMatrixData[2];
|
||||
sRawMatrix[2] = sMatrixData[4] * mScale;
|
||||
sRawMatrix[3] = sMatrixData[1];
|
||||
sRawMatrix[4] = sMatrixData[3];
|
||||
sRawMatrix[5] = sMatrixData[5] * mScale;
|
||||
sRawMatrix[6] = 0;
|
||||
sRawMatrix[7] = 0;
|
||||
sRawMatrix[8] = 1;
|
||||
mMatrix.setValues(sRawMatrix);
|
||||
}
|
||||
|
||||
protected @Nullable Path getClipPath(Canvas canvas, Paint paint) {
|
||||
if (mClipPath != null) {
|
||||
VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath);
|
||||
@@ -169,7 +156,6 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
default:
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: clipRule: " + mClipRule + " unrecognized");
|
||||
}
|
||||
|
||||
return clipPath;
|
||||
} else {
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: Undefined clipPath: " + mClipPath);
|
||||
@@ -206,26 +192,39 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
|
||||
ReactShadowNode parent = getParent();
|
||||
|
||||
while (!(parent instanceof SvgViewShadowNode)) {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
} else {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof SvgViewShadowNode) {
|
||||
mSvgShadowNode = (SvgViewShadowNode)parent;
|
||||
} else if (parent instanceof VirtualNode) {
|
||||
mSvgShadowNode = ((VirtualNode) parent).getSvgShadowNode();
|
||||
} else {
|
||||
FLog.e(ReactConstants.TAG, "RNSVG: " + getClass().getName() + " should be descendant of a SvgViewShadow.");
|
||||
}
|
||||
mSvgShadowNode = (SvgViewShadowNode) parent;
|
||||
|
||||
return mSvgShadowNode;
|
||||
}
|
||||
|
||||
protected void setupDimensions(Canvas canvas) {
|
||||
setupDimensions(canvas.getClipBounds());
|
||||
protected float relativeOnWidth(String position) {
|
||||
return PropHelper.fromPercentageToFloat(position, getCanvasWidth(), 0, mScale);
|
||||
}
|
||||
|
||||
protected void setupDimensions(Rect rect) {
|
||||
mCanvasX = rect.left;
|
||||
mCanvasY = rect.top;
|
||||
mCanvasWidth = rect.width();
|
||||
mCanvasHeight = rect.height();
|
||||
protected float relativeOnHeight(String position) {
|
||||
return PropHelper.fromPercentageToFloat(position, getCanvasHeight(), 0, mScale);
|
||||
}
|
||||
|
||||
protected float getCanvasWidth() {
|
||||
return getSvgShadowNode().getCanvasBounds().width();
|
||||
}
|
||||
|
||||
protected float getCanvasHeight() {
|
||||
return getSvgShadowNode().getCanvasBounds().height();
|
||||
}
|
||||
|
||||
protected float getCanvasLeft() {
|
||||
return getSvgShadowNode().getCanvasBounds().left;
|
||||
}
|
||||
|
||||
protected float getCanvasTop() {
|
||||
return getSvgShadowNode().getCanvasBounds().top;
|
||||
}
|
||||
|
||||
protected void saveDefinition() {
|
||||
|
||||
Reference in New Issue
Block a user