Path.cpp revision 7979388d4f7d5d9dbfcf7e1cc4709f8088c034ae
1/* libs/android_runtime/android/graphics/Path.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18// This file was generated from the C++ include file: SkPath.h 19// Any changes made to this file will be discarded by the build. 20// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, 21// or one of the auxilary file specifications in device/tools/gluemaker. 22 23#include "jni.h" 24#include "GraphicsJNI.h" 25#include <android_runtime/AndroidRuntime.h> 26 27#include "SkPath.h" 28#include "SkPathOps.h" 29 30#include <Caches.h> 31#include <vector> 32#include <map> 33 34namespace android { 35 36class SkPathGlue { 37public: 38 39 static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { 40 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 41#ifdef USE_OPENGL_RENDERER 42 if (android::uirenderer::Caches::hasInstance()) { 43 android::uirenderer::Caches::getInstance().resourceCache.destructor(obj); 44 return; 45 } 46#endif 47 delete obj; 48 } 49 50 static jlong init1(JNIEnv* env, jobject clazz) { 51 return reinterpret_cast<jlong>(new SkPath()); 52 } 53 54 static jlong init2(JNIEnv* env, jobject clazz, jlong valHandle) { 55 SkPath* val = reinterpret_cast<SkPath*>(valHandle); 56 return reinterpret_cast<jlong>(new SkPath(*val)); 57 } 58 59 static void reset(JNIEnv* env, jobject clazz, jlong objHandle) { 60 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 61 obj->reset(); 62 } 63 64 static void rewind(JNIEnv* env, jobject clazz, jlong objHandle) { 65 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 66 obj->rewind(); 67 } 68 69 static void assign(JNIEnv* env, jobject clazz, jlong dstHandle, jlong srcHandle) { 70 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 71 const SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 72 *dst = *src; 73 } 74 75 static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) { 76 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 77 return obj->isConvex(); 78 } 79 80 static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) { 81 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 82 return obj->getFillType(); 83 } 84 85 static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) { 86 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 87 SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle); 88 path->setFillType(ft); 89 } 90 91 static jboolean isEmpty(JNIEnv* env, jobject clazz, jlong objHandle) { 92 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 93 return obj->isEmpty(); 94 } 95 96 static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) { 97 SkRect rect; 98 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 99 jboolean result = obj->isRect(&rect); 100 GraphicsJNI::rect_to_jrectf(rect, env, jrect); 101 return result; 102 } 103 104 static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) { 105 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 106 const SkRect& bounds = obj->getBounds(); 107 GraphicsJNI::rect_to_jrectf(bounds, env, jbounds); 108 } 109 110 static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) { 111 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 112 obj->incReserve(extraPtCount); 113 } 114 115 static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) { 116 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 117 obj->moveTo(x, y); 118 } 119 120 static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 121 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 122 obj->rMoveTo(dx, dy); 123 } 124 125 static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) { 126 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 127 obj->lineTo(x, y); 128 } 129 130 static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 131 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 132 obj->rLineTo(dx, dy); 133 } 134 135 static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) { 136 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 137 obj->quadTo(x1, y1, x2, y2); 138 } 139 140 static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) { 141 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 142 obj->rQuadTo(dx1, dy1, dx2, dy2); 143 } 144 145 static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 146 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 147 obj->cubicTo(x1, y1, x2, y2, x3, y3); 148 } 149 150 static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 151 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 152 obj->rCubicTo(x1, y1, x2, y2, x3, y3); 153 } 154 155 static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) { 156 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 157 SkRect oval_; 158 GraphicsJNI::jrectf_to_rect(env, oval, &oval_); 159 obj->arcTo(oval_, startAngle, sweepAngle, forceMoveTo); 160 } 161 162 static void close(JNIEnv* env, jobject clazz, jlong objHandle) { 163 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 164 obj->close(); 165 } 166 167 static void addRect(JNIEnv* env, jobject clazz, jlong objHandle, 168 jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { 169 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 170 SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 171 obj->addRect(left, top, right, bottom, dir); 172 } 173 174 static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, 175 jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { 176 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 177 SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 178 SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 179 obj->addOval(oval, dir); 180 } 181 182 static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) { 183 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 184 SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 185 obj->addCircle(x, y, radius, dir); 186 } 187 188 static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle) { 189 SkRect oval_; 190 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 191 GraphicsJNI::jrectf_to_rect(env, oval, &oval_); 192 obj->addArc(oval_, startAngle, sweepAngle); 193 } 194 195 static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect, 196 jfloat rx, jfloat ry, jint dirHandle) { 197 SkRect rect; 198 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 199 SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 200 GraphicsJNI::jrectf_to_rect(env, jrect, &rect); 201 obj->addRoundRect(rect, rx, ry, dir); 202 } 203 204 static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jobject jrect, 205 jfloatArray array, jint dirHandle) { 206 SkRect rect; 207 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 208 SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 209 GraphicsJNI::jrectf_to_rect(env, jrect, &rect); 210 AutoJavaFloatArray afa(env, array, 8); 211#ifdef SK_SCALAR_IS_FLOAT 212 const float* src = afa.ptr(); 213#else 214 #error Need to convert float array to SkScalar array before calling the following function. 215#endif 216 obj->addRoundRect(rect, src, dir); 217 } 218 219 static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) { 220 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 221 SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 222 obj->addPath(*src, dx, dy); 223 } 224 225 static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) { 226 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 227 SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 228 obj->addPath(*src); 229 } 230 231 static void addPath__PathMatrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong matrixHandle) { 232 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 233 SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 234 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 235 obj->addPath(*src, *matrix); 236 } 237 238 static void offset__FFPath(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy, jlong dstHandle) { 239 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 240 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 241 obj->offset(dx, dy, dst); 242 } 243 244 static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 245 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 246 obj->offset(dx, dy); 247 } 248 249 static void setLastPoint(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 250 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 251 obj->setLastPt(dx, dy); 252 } 253 254 static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) { 255 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 256 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 257 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 258 obj->transform(*matrix, dst); 259 } 260 261 static void transform__Matrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle) { 262 SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 263 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 264 obj->transform(*matrix); 265 } 266 267 static jboolean op(JNIEnv* env, jobject clazz, jlong p1Handle, jlong p2Handle, jint opHandle, jlong rHandle) { 268 SkPath* p1 = reinterpret_cast<SkPath*>(p1Handle); 269 SkPath* p2 = reinterpret_cast<SkPath*>(p2Handle); 270 SkPathOp op = static_cast<SkPathOp>(opHandle); 271 SkPath* r = reinterpret_cast<SkPath*>(rHandle); 272 return Op(*p1, *p2, op, r); 273 } 274 275 typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points); 276 277 static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 278 const SkPoint& point) { 279 float length = 0; 280 if (!lengths.empty()) { 281 length = lengths.back(); 282 } 283 segmentPoints.push_back(point); 284 lengths.push_back(length); 285 } 286 287 static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 288 const SkPoint& toPoint) { 289 if (segmentPoints.empty()) { 290 segmentPoints.push_back(SkPoint::Make(0, 0)); 291 lengths.push_back(0); 292 } else if (segmentPoints.back() == toPoint) { 293 return; // Empty line 294 } 295 float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint); 296 segmentPoints.push_back(toPoint); 297 lengths.push_back(length); 298 } 299 300 static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) { 301 float oneMinusT = 1 - t; 302 float oneMinusTSquared = oneMinusT * oneMinusT; 303 float oneMinusTCubed = oneMinusTSquared * oneMinusT; 304 float tSquared = t * t; 305 float tCubed = tSquared * t; 306 return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1) 307 + (3 * oneMinusT * tSquared * p2) + (tCubed * p3); 308 } 309 310 static SkPoint cubicBezierCalculation(float t, const SkPoint* points) { 311 float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(), 312 points[2].x(), points[3].x()); 313 float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(), 314 points[2].y(), points[3].y()); 315 return SkPoint::Make(x, y); 316 } 317 318 static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) { 319 float oneMinusT = 1 - t; 320 return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2)); 321 } 322 323 static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) { 324 float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x()); 325 float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y()); 326 return SkPoint::Make(x, y); 327 } 328 329 // Subdivide a section of the Bezier curve, set the mid-point and the mid-t value. 330 // Returns true if further subdivision is necessary as defined by errorSquared. 331 static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction, 332 float t0, const SkPoint &p0, float t1, const SkPoint &p1, 333 float& midT, SkPoint &midPoint, float errorSquared) { 334 midT = (t1 + t0) / 2; 335 float midX = (p1.x() + p0.x()) / 2; 336 float midY = (p1.y() + p0.y()) / 2; 337 338 midPoint = (*bezierFunction)(midT, points); 339 float xError = midPoint.x() - midX; 340 float yError = midPoint.y() - midY; 341 float midErrorSquared = (xError * xError) + (yError * yError); 342 return midErrorSquared > errorSquared; 343 } 344 345 // Divides Bezier curves until linear interpolation is very close to accurate, using 346 // errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly 347 // short-circuit subdivision. If you imagine an S shape, the top and bottom points being the 348 // starting and end points, linear interpolation would mark the center where the curve places 349 // the point. It is clearly not the case that we can linearly interpolate at that point. 350 // doubleCheckDivision forces a second examination between subdivisions to ensure that linear 351 // interpolation works. 352 static void addBezier(const SkPoint* points, 353 bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints, 354 std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) { 355 typedef std::map<float, SkPoint> PointMap; 356 PointMap tToPoint; 357 358 tToPoint[0] = (*bezierFunction)(0, points); 359 tToPoint[1] = (*bezierFunction)(1, points); 360 361 PointMap::iterator iter = tToPoint.begin(); 362 PointMap::iterator next = iter; 363 ++next; 364 while (next != tToPoint.end()) { 365 bool needsSubdivision = true; 366 SkPoint midPoint; 367 do { 368 float midT; 369 needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 370 iter->second, next->first, next->second, midT, midPoint, errorSquared); 371 if (!needsSubdivision && doubleCheckDivision) { 372 SkPoint quarterPoint; 373 float quarterT; 374 needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 375 iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared); 376 if (needsSubdivision) { 377 // Found an inflection point. No need to double-check. 378 doubleCheckDivision = false; 379 } 380 } 381 if (needsSubdivision) { 382 next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint)); 383 } 384 } while (needsSubdivision); 385 iter = next; 386 next++; 387 } 388 389 // Now that each division can use linear interpolation with less than the allowed error 390 for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) { 391 addLine(segmentPoints, lengths, iter->second); 392 } 393 } 394 395 static void createVerbSegments(SkPath::Verb verb, const SkPoint* points, 396 std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) { 397 switch (verb) { 398 case SkPath::kMove_Verb: 399 addMove(segmentPoints, lengths, points[0]); 400 break; 401 case SkPath::kClose_Verb: 402 addLine(segmentPoints, lengths, points[0]); 403 break; 404 case SkPath::kLine_Verb: 405 addLine(segmentPoints, lengths, points[1]); 406 break; 407 case SkPath::kQuad_Verb: 408 addBezier(points, quadraticBezierCalculation, segmentPoints, lengths, 409 errorSquared, false); 410 break; 411 case SkPath::kCubic_Verb: 412 addBezier(points, cubicBezierCalculation, segmentPoints, lengths, 413 errorSquared, true); 414 break; 415 default: 416 // Leave element as NULL, Conic sections are not supported. 417 break; 418 } 419 } 420 421 // Returns a float[] with each point along the path represented by 3 floats 422 // * fractional length along the path that the point resides 423 // * x coordinate 424 // * y coordinate 425 // Note that more than one point may have the same length along the path in 426 // the case of a move. 427 // NULL can be returned if the Path is empty. 428 static jfloatArray approximate(JNIEnv* env, jclass, jlong pathHandle, float acceptableError) 429 { 430 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 431 SkASSERT(path); 432 SkPath::Iter pathIter(*path, false); 433 SkPath::Verb verb; 434 SkPoint points[4]; 435 std::vector<SkPoint> segmentPoints; 436 std::vector<float> lengths; 437 float errorSquared = acceptableError * acceptableError; 438 439 while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) { 440 createVerbSegments(verb, points, segmentPoints, lengths, errorSquared); 441 } 442 443 if (segmentPoints.empty()) { 444 return NULL; 445 } 446 447 size_t numPoints = segmentPoints.size(); 448 size_t approximationArraySize = numPoints * 3; 449 450 float* approximation = new float[approximationArraySize]; 451 float totalLength = lengths.back(); 452 453 int approximationIndex = 0; 454 for (size_t i = 0; i < numPoints; i++) { 455 const SkPoint& point = segmentPoints[i]; 456 approximation[approximationIndex++] = lengths[i] / totalLength; 457 approximation[approximationIndex++] = point.x(); 458 approximation[approximationIndex++] = point.y(); 459 } 460 461 jfloatArray result = env->NewFloatArray(approximationArraySize); 462 env->SetFloatArrayRegion(result, 0, approximationArraySize, approximation); 463 delete[] approximation; 464 return result; 465 } 466}; 467 468static JNINativeMethod methods[] = { 469 {"finalizer", "(J)V", (void*) SkPathGlue::finalizer}, 470 {"init1","()J", (void*) SkPathGlue::init1}, 471 {"init2","(J)J", (void*) SkPathGlue::init2}, 472 {"native_reset","(J)V", (void*) SkPathGlue::reset}, 473 {"native_rewind","(J)V", (void*) SkPathGlue::rewind}, 474 {"native_set","(JJ)V", (void*) SkPathGlue::assign}, 475 {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex}, 476 {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType}, 477 {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType}, 478 {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty}, 479 {"native_isRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect}, 480 {"native_computeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds}, 481 {"native_incReserve","(JI)V", (void*) SkPathGlue::incReserve}, 482 {"native_moveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF}, 483 {"native_rMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo}, 484 {"native_lineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF}, 485 {"native_rLineTo","(JFF)V", (void*) SkPathGlue::rLineTo}, 486 {"native_quadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF}, 487 {"native_rQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo}, 488 {"native_cubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF}, 489 {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo}, 490 {"native_arcTo","(JLandroid/graphics/RectF;FFZ)V", (void*) SkPathGlue::arcTo}, 491 {"native_close","(J)V", (void*) SkPathGlue::close}, 492 {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect}, 493 {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval}, 494 {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle}, 495 {"native_addArc","(JLandroid/graphics/RectF;FF)V", (void*) SkPathGlue::addArc}, 496 {"native_addRoundRect","(JLandroid/graphics/RectF;FFI)V", (void*) SkPathGlue::addRoundRectXY}, 497 {"native_addRoundRect","(JLandroid/graphics/RectF;[FI)V", (void*) SkPathGlue::addRoundRect8}, 498 {"native_addPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF}, 499 {"native_addPath","(JJ)V", (void*) SkPathGlue::addPath__Path}, 500 {"native_addPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix}, 501 {"native_offset","(JFFJ)V", (void*) SkPathGlue::offset__FFPath}, 502 {"native_offset","(JFF)V", (void*) SkPathGlue::offset__FF}, 503 {"native_setLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint}, 504 {"native_transform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath}, 505 {"native_transform","(JJ)V", (void*) SkPathGlue::transform__Matrix}, 506 {"native_op","(JJIJ)Z", (void*) SkPathGlue::op}, 507 {"native_approximate", "(JF)[F", (void*) SkPathGlue::approximate}, 508}; 509 510int register_android_graphics_Path(JNIEnv* env) { 511 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Path", methods, 512 sizeof(methods) / sizeof(methods[0])); 513 return result; 514} 515 516} 517