From 1af47603cfbb12cec88df44654073be6f38276b2 Mon Sep 17 00:00:00 2001 From: Michael Ortiz Date: Wed, 27 Apr 2016 22:07:30 -0700 Subject: [PATCH] Fix ReactNativeART arc drawing on Android Summary: **Motivation**: Arc drawing has been broken on Android for some time. dgladkov submitted a PR, which ended up having a bug and was never merged. This PR should fix that bug as well as provide screenshots to prove it works. **Reproducing the Bug:** dgladkov made a simple test app which helps to illustrate the bug. The repo can be found [here](https://github.com/dgladkov/RNArtArcDrawingBug). The demo app illustrates that on iOS, wedges are drawn correctly, but Android only draws full circles. [Direct Link to iOS Before](https://github.com/dgladkov/RNArtArcDrawingBug/blob/master/images/ios.png). [Direct Link to Android Before](https://github.com/dgladkov/RNArtArcDrawingBug/blob/master/images/android.png). **Proof The Bug is Fixed:** [Here is a direct link to Android After pic.](http://i.imgur.com/9dTU2Xn.png) You can see the wedges match the iOS Before screenshot. **What went wrong:** dgladkov's solution relied on Java's modulus, which in fact, implements modulus in a non-standard way. Modulus should a Closes https://github.com/facebook/react-native/pull/7049 Differential Revision: D3234404 Pulled By: spicyj fb-gh-sync-id: 4974b818dc49d9d16f2483c49b462c459a8bb479 fbshipit-source-id: 4974b818dc49d9d16f2483c49b462c459a8bb479 --- .../react/views/art/ARTShapeShadowNode.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java index ce8b5e136..21d8849ad 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/art/ARTShapeShadowNode.java @@ -191,6 +191,20 @@ public class ARTShapeShadowNode extends ARTVirtualNode { return false; } + /** + * Returns the floor modulus of the float arguments. Java modulus will return a negative remainder + * when the divisor is negative. Modulus should always be positive. This mimics the behavior of + * Math.floorMod, introduced in Java 8. + */ + private float modulus(float x, float y) { + float remainder = x % y; + float modulus = remainder; + if (remainder < 0) { + modulus += y; + } + return modulus; + } + /** * Creates a {@link Path} from an array of instructions constructed by JS * (see ARTSerializablePath.js). Each instruction starts with a type (see PATH_TYPE_*) followed @@ -232,11 +246,18 @@ public class ARTShapeShadowNode extends ARTVirtualNode { float r = data[i++] * mScale; float start = (float) Math.toDegrees(data[i++]); float end = (float) Math.toDegrees(data[i++]); - boolean clockwise = data[i++] == 0f; - if (!clockwise) { - end = 360 - end; + boolean clockwise = data[i++] == 1f; + float sweep = end - start; + if (Math.abs(sweep) > 360) { + sweep = 360; + } else { + sweep = modulus(sweep, 360); } - float sweep = start - end; + if (!clockwise && sweep < 360) { + start = end; + sweep = 360 - sweep; + } + RectF oval = new RectF(x - r, y - r, x + r, y + r); path.addArc(oval, start, sweep); break;