[android] Fix clipping path on Android < Kitkat (API 19)

This commit is contained in:
Mikael Sand
2018-09-01 16:41:03 +03:00
parent 11a57526fc
commit 7bb1e748b7
3 changed files with 48 additions and 28 deletions
@@ -13,8 +13,11 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.support.annotation.RequiresApi;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.ReactShadowNode;
@@ -131,29 +134,52 @@ class GroupShadowNode extends RenderableShadowNode {
return path;
}
protected Path getPath(final Canvas canvas, final Paint paint, final Path.Op op) {
protected Path getPath(final Canvas canvas, final Paint paint, final Region.Op op) {
final Path path = new Path();
traverseChildren(new NodeRunnable() {
public void run(ReactShadowNode node) {
if (node instanceof VirtualNode) {
VirtualNode n = (VirtualNode)node;
Matrix transform = n.mMatrix;
Path p2;
if (n instanceof GroupShadowNode) {
p2 = ((GroupShadowNode)n).getPath(canvas, paint, op);
} else {
p2 = n.getPath(canvas, paint);
}
p2.transform(transform);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path.op(p2, op);
} else {
path.addPath(p2);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final Path.Op pop = Path.Op.valueOf(op.name());
traverseChildren(new NodeRunnable() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void run(ReactShadowNode node) {
if (node instanceof VirtualNode) {
VirtualNode n = (VirtualNode)node;
Matrix transform = n.mMatrix;
Path p2;
if (n instanceof GroupShadowNode) {
p2 = ((GroupShadowNode)n).getPath(canvas, paint, op);
} else {
p2 = n.getPath(canvas, paint);
}
p2.transform(transform);
path.op(p2, pop);
}
}
}
});
});
} else {
Rect clipBounds = canvas.getClipBounds();
final Region bounds = new Region(clipBounds);
final Region r = new Region();
traverseChildren(new NodeRunnable() {
public void run(ReactShadowNode node) {
if (node instanceof VirtualNode) {
VirtualNode n = (VirtualNode)node;
Matrix transform = n.mMatrix;
Path p2;
if (n instanceof GroupShadowNode) {
p2 = ((GroupShadowNode)n).getPath(canvas, paint, op);
} else {
p2 = n.getPath(canvas, paint);
}
p2.transform(transform);
Region r2 = new Region();
r2.setPath(p2, bounds);
r.op(r2, op);
}
}
});
path.addPath(r.getBoundaryPath());
}
return path;
}
@@ -12,6 +12,7 @@ package com.horcrux.svg;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Region;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
@@ -141,7 +142,7 @@ class TextShadowNode extends GroupShadowNode {
}
@Override
protected Path getPath(Canvas canvas, Paint paint, Path.Op op) {
protected Path getPath(Canvas canvas, Paint paint, Region.Op op) {
return getPath(canvas, paint);
}
@@ -27,8 +27,6 @@ import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import java.util.List;
import javax.annotation.Nullable;
import static com.horcrux.svg.FontData.DEFAULT_FONT_SIZE;
@@ -244,12 +242,7 @@ abstract class VirtualNode extends LayoutShadowNode {
ClipPathShadowNode mClipNode = (ClipPathShadowNode) getSvgShadowNode().getDefinedClipPath(mClipPath);
if (mClipNode != null) {
Path clipPath;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
clipPath = mClipNode.getPath(canvas, paint, Path.Op.UNION);
} else {
clipPath = mClipNode.getPath(canvas, paint);
}
Path clipPath = mClipNode.getPath(canvas, paint, Region.Op.UNION);
switch (mClipRule) {
case CLIP_RULE_EVENODD:
clipPath.setFillType(Path.FillType.EVEN_ODD);