Merge "Add conic support for Path#approximate" into oc-dev
am: ebd44d0076
Change-Id: I68f5924aef7526de1c801f529dd5a304a1a1d287
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 292454b..d3d6882 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -26,6 +26,7 @@
#include "SkPath.h"
#include "SkPathOps.h"
+#include "SkGeometry.h" // WARNING: Internal Skia Header
#include <Caches.h>
#include <vector>
@@ -355,8 +356,9 @@
}
}
- static void createVerbSegments(SkPath::Verb verb, const SkPoint* points,
- std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) {
+ static void createVerbSegments(const SkPath::Iter& pathIter, SkPath::Verb verb,
+ const SkPoint* points, std::vector<SkPoint>& segmentPoints,
+ std::vector<float>& lengths, float errorSquared, float errorConic) {
switch (verb) {
case SkPath::kMove_Verb:
addMove(segmentPoints, lengths, points[0]);
@@ -375,8 +377,27 @@
addBezier(points, cubicBezierCalculation, segmentPoints, lengths,
errorSquared, true);
break;
+ case SkPath::kConic_Verb: {
+ SkAutoConicToQuads converter;
+ const SkPoint* quads = converter.computeQuads(
+ points, pathIter.conicWeight(), errorConic);
+ for (int i = 0; i < converter.countQuads(); i++) {
+ // Note: offset each subsequent quad by 2, since end points are shared
+ const SkPoint* quad = quads + i * 2;
+ addBezier(quad, quadraticBezierCalculation, segmentPoints, lengths,
+ errorConic, false);
+ }
+ break;
+ }
default:
- // Leave element as NULL, Conic sections are not supported.
+ static_assert(SkPath::kMove_Verb == 0
+ && SkPath::kLine_Verb == 1
+ && SkPath::kQuad_Verb == 2
+ && SkPath::kConic_Verb == 3
+ && SkPath::kCubic_Verb == 4
+ && SkPath::kClose_Verb == 5
+ && SkPath::kDone_Verb == 6,
+ "Path enum changed, new types may have been added.");
break;
}
}
@@ -398,9 +419,11 @@
std::vector<SkPoint> segmentPoints;
std::vector<float> lengths;
float errorSquared = acceptableError * acceptableError;
+ float errorConic = acceptableError / 2; // somewhat arbitrary
while ((verb = pathIter.next(points, false)) != SkPath::kDone_Verb) {
- createVerbSegments(verb, points, segmentPoints, lengths, errorSquared);
+ createVerbSegments(pathIter, verb, points, segmentPoints, lengths,
+ errorSquared, errorConic);
}
if (segmentPoints.empty()) {
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 3631373..098cdc6 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -16,8 +16,10 @@
package android.graphics;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Size;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -805,7 +807,12 @@
* the error is less than half a pixel.
* @return An array of components for points approximating the Path.
*/
- public float[] approximate(float acceptableError) {
+ @NonNull
+ @Size(min = 6, multiple = 3)
+ public float[] approximate(@FloatRange(from = 0) float acceptableError) {
+ if (acceptableError < 0) {
+ throw new IllegalArgumentException("AcceptableError must be greater than or equal to 0");
+ }
return nApproximate(mNativePath, acceptableError);
}
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 9246237..64b2c45 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -1005,6 +1005,14 @@
break;
}
default:
+ static_assert(SkPath::kMove_Verb == 0
+ && SkPath::kLine_Verb == 1
+ && SkPath::kQuad_Verb == 2
+ && SkPath::kConic_Verb == 3
+ && SkPath::kCubic_Verb == 4
+ && SkPath::kClose_Verb == 5
+ && SkPath::kDone_Verb == 6,
+ "Path enum changed, new types may have been added");
break;
}
}