Path.cpp revision 7023df08f14ec5dee76ac54c03e870f84e297636
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 "pathops/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, SkPath* obj) { 40#ifdef USE_OPENGL_RENDERER 41 if (android::uirenderer::Caches::hasInstance()) { 42 android::uirenderer::Caches::getInstance().resourceCache.destructor(obj); 43 return; 44 } 45#endif 46 delete obj; 47 } 48 49 static SkPath* init1(JNIEnv* env, jobject clazz) { 50 return new SkPath(); 51 } 52 53 static SkPath* init2(JNIEnv* env, jobject clazz, SkPath* val) { 54 return new SkPath(*val); 55 } 56 57 static void reset(JNIEnv* env, jobject clazz, SkPath* obj) { 58 obj->reset(); 59 } 60 61 static void rewind(JNIEnv* env, jobject clazz, SkPath* obj) { 62 obj->rewind(); 63 } 64 65 static void assign(JNIEnv* env, jobject clazz, SkPath* dst, const SkPath* src) { 66 *dst = *src; 67 } 68 69 static jint getFillType(JNIEnv* env, jobject clazz, SkPath* obj) { 70 return obj->getFillType(); 71 } 72 73 static void setFillType(JNIEnv* env, jobject clazz, SkPath* path, SkPath::FillType ft) { 74 path->setFillType(ft); 75 } 76 77 static jboolean isEmpty(JNIEnv* env, jobject clazz, SkPath* obj) { 78 return obj->isEmpty(); 79 } 80 81 static jboolean isRect(JNIEnv* env, jobject clazz, SkPath* obj, jobject rect) { 82 SkRect rect_; 83 jboolean result = obj->isRect(&rect_); 84 GraphicsJNI::rect_to_jrectf(rect_, env, rect); 85 return result; 86 } 87 88 static void computeBounds(JNIEnv* env, jobject clazz, SkPath* obj, jobject bounds) { 89 const SkRect& bounds_ = obj->getBounds(); 90 GraphicsJNI::rect_to_jrectf(bounds_, env, bounds); 91 } 92 93 static void incReserve(JNIEnv* env, jobject clazz, SkPath* obj, jint extraPtCount) { 94 obj->incReserve(extraPtCount); 95 } 96 97 static void moveTo__FF(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x, jfloat y) { 98 SkScalar x_ = SkFloatToScalar(x); 99 SkScalar y_ = SkFloatToScalar(y); 100 obj->moveTo(x_, y_); 101 } 102 103 static void rMoveTo(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx, jfloat dy) { 104 SkScalar dx_ = SkFloatToScalar(dx); 105 SkScalar dy_ = SkFloatToScalar(dy); 106 obj->rMoveTo(dx_, dy_); 107 } 108 109 static void lineTo__FF(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x, jfloat y) { 110 SkScalar x_ = SkFloatToScalar(x); 111 SkScalar y_ = SkFloatToScalar(y); 112 obj->lineTo(x_, y_); 113 } 114 115 static void rLineTo(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx, jfloat dy) { 116 SkScalar dx_ = SkFloatToScalar(dx); 117 SkScalar dy_ = SkFloatToScalar(dy); 118 obj->rLineTo(dx_, dy_); 119 } 120 121 static void quadTo__FFFF(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x1, jfloat y1, jfloat x2, jfloat y2) { 122 SkScalar x1_ = SkFloatToScalar(x1); 123 SkScalar y1_ = SkFloatToScalar(y1); 124 SkScalar x2_ = SkFloatToScalar(x2); 125 SkScalar y2_ = SkFloatToScalar(y2); 126 obj->quadTo(x1_, y1_, x2_, y2_); 127 } 128 129 static void rQuadTo(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) { 130 SkScalar dx1_ = SkFloatToScalar(dx1); 131 SkScalar dy1_ = SkFloatToScalar(dy1); 132 SkScalar dx2_ = SkFloatToScalar(dx2); 133 SkScalar dy2_ = SkFloatToScalar(dy2); 134 obj->rQuadTo(dx1_, dy1_, dx2_, dy2_); 135 } 136 137 static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 138 SkScalar x1_ = SkFloatToScalar(x1); 139 SkScalar y1_ = SkFloatToScalar(y1); 140 SkScalar x2_ = SkFloatToScalar(x2); 141 SkScalar y2_ = SkFloatToScalar(y2); 142 SkScalar x3_ = SkFloatToScalar(x3); 143 SkScalar y3_ = SkFloatToScalar(y3); 144 obj->cubicTo(x1_, y1_, x2_, y2_, x3_, y3_); 145 } 146 147 static void rCubicTo(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 148 SkScalar x1_ = SkFloatToScalar(x1); 149 SkScalar y1_ = SkFloatToScalar(y1); 150 SkScalar x2_ = SkFloatToScalar(x2); 151 SkScalar y2_ = SkFloatToScalar(y2); 152 SkScalar x3_ = SkFloatToScalar(x3); 153 SkScalar y3_ = SkFloatToScalar(y3); 154 obj->rCubicTo(x1_, y1_, x2_, y2_, x3_, y3_); 155 } 156 157 static void arcTo(JNIEnv* env, jobject clazz, SkPath* obj, jobject oval, jfloat startAngle, jfloat sweepAngle, jboolean forceMoveTo) { 158 SkRect oval_; 159 GraphicsJNI::jrectf_to_rect(env, oval, &oval_); 160 SkScalar startAngle_ = SkFloatToScalar(startAngle); 161 SkScalar sweepAngle_ = SkFloatToScalar(sweepAngle); 162 obj->arcTo(oval_, startAngle_, sweepAngle_, forceMoveTo); 163 } 164 165 static void close(JNIEnv* env, jobject clazz, SkPath* obj) { 166 obj->close(); 167 } 168 169 static void addRect__RectFI(JNIEnv* env, jobject clazz, SkPath* obj, jobject rect, SkPath::Direction dir) { 170 SkRect rect_; 171 GraphicsJNI::jrectf_to_rect(env, rect, &rect_); 172 obj->addRect(rect_, dir); 173 } 174 175 static void addRect__FFFFI(JNIEnv* env, jobject clazz, SkPath* obj, jfloat left, jfloat top, jfloat right, jfloat bottom, SkPath::Direction dir) { 176 SkScalar left_ = SkFloatToScalar(left); 177 SkScalar top_ = SkFloatToScalar(top); 178 SkScalar right_ = SkFloatToScalar(right); 179 SkScalar bottom_ = SkFloatToScalar(bottom); 180 obj->addRect(left_, top_, right_, bottom_, dir); 181 } 182 183 static void addOval(JNIEnv* env, jobject clazz, SkPath* obj, jobject oval, SkPath::Direction dir) { 184 SkRect oval_; 185 GraphicsJNI::jrectf_to_rect(env, oval, &oval_); 186 obj->addOval(oval_, dir); 187 } 188 189 static void addCircle(JNIEnv* env, jobject clazz, SkPath* obj, jfloat x, jfloat y, jfloat radius, SkPath::Direction dir) { 190 SkScalar x_ = SkFloatToScalar(x); 191 SkScalar y_ = SkFloatToScalar(y); 192 SkScalar radius_ = SkFloatToScalar(radius); 193 obj->addCircle(x_, y_, radius_, dir); 194 } 195 196 static void addArc(JNIEnv* env, jobject clazz, SkPath* obj, jobject oval, jfloat startAngle, jfloat sweepAngle) { 197 SkRect oval_; 198 GraphicsJNI::jrectf_to_rect(env, oval, &oval_); 199 SkScalar startAngle_ = SkFloatToScalar(startAngle); 200 SkScalar sweepAngle_ = SkFloatToScalar(sweepAngle); 201 obj->addArc(oval_, startAngle_, sweepAngle_); 202 } 203 204 static void addRoundRectXY(JNIEnv* env, jobject clazz, SkPath* obj, jobject rect, 205 jfloat rx, jfloat ry, SkPath::Direction dir) { 206 SkRect rect_; 207 GraphicsJNI::jrectf_to_rect(env, rect, &rect_); 208 SkScalar rx_ = SkFloatToScalar(rx); 209 SkScalar ry_ = SkFloatToScalar(ry); 210 obj->addRoundRect(rect_, rx_, ry_, dir); 211 } 212 213 static void addRoundRect8(JNIEnv* env, jobject, SkPath* obj, jobject rect, 214 jfloatArray array, SkPath::Direction dir) { 215 SkRect rect_; 216 GraphicsJNI::jrectf_to_rect(env, rect, &rect_); 217 AutoJavaFloatArray afa(env, array, 8); 218 const float* src = afa.ptr(); 219 SkScalar dst[8]; 220 221 for (int i = 0; i < 8; i++) { 222 dst[i] = SkFloatToScalar(src[i]); 223 } 224 obj->addRoundRect(rect_, dst, dir); 225 } 226 227 static void addPath__PathFF(JNIEnv* env, jobject clazz, SkPath* obj, SkPath* src, jfloat dx, jfloat dy) { 228 SkScalar dx_ = SkFloatToScalar(dx); 229 SkScalar dy_ = SkFloatToScalar(dy); 230 obj->addPath(*src, dx_, dy_); 231 } 232 233 static void addPath__Path(JNIEnv* env, jobject clazz, SkPath* obj, SkPath* src) { 234 obj->addPath(*src); 235 } 236 237 static void addPath__PathMatrix(JNIEnv* env, jobject clazz, SkPath* obj, SkPath* src, SkMatrix* matrix) { 238 obj->addPath(*src, *matrix); 239 } 240 241 static void offset__FFPath(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx, jfloat dy, SkPath* dst) { 242 SkScalar dx_ = SkFloatToScalar(dx); 243 SkScalar dy_ = SkFloatToScalar(dy); 244 obj->offset(dx_, dy_, dst); 245 } 246 247 static void offset__FF(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx, jfloat dy) { 248 SkScalar dx_ = SkFloatToScalar(dx); 249 SkScalar dy_ = SkFloatToScalar(dy); 250 obj->offset(dx_, dy_); 251 } 252 253 static void setLastPoint(JNIEnv* env, jobject clazz, SkPath* obj, jfloat dx, jfloat dy) { 254 SkScalar dx_ = SkFloatToScalar(dx); 255 SkScalar dy_ = SkFloatToScalar(dy); 256 obj->setLastPt(dx_, dy_); 257 } 258 259 static void transform__MatrixPath(JNIEnv* env, jobject clazz, SkPath* obj, SkMatrix* matrix, SkPath* dst) { 260 obj->transform(*matrix, dst); 261 } 262 263 static void transform__Matrix(JNIEnv* env, jobject clazz, SkPath* obj, SkMatrix* matrix) { 264 obj->transform(*matrix); 265 } 266 267 static jboolean op(JNIEnv* env, jobject clazz, SkPath* p1, SkPath* p2, SkPathOp op, SkPath* r) { 268 return Op(*p1, *p2, op, r); 269 } 270 271 typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points); 272 273 static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 274 const SkPoint& point) { 275 float length = 0; 276 if (!lengths.empty()) { 277 length = lengths.back(); 278 } 279 segmentPoints.push_back(point); 280 lengths.push_back(length); 281 } 282 283 static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 284 const SkPoint& toPoint) { 285 if (segmentPoints.empty()) { 286 segmentPoints.push_back(SkPoint::Make(0, 0)); 287 lengths.push_back(0); 288 } else if (segmentPoints.back() == toPoint) { 289 return; // Empty line 290 } 291 float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint); 292 segmentPoints.push_back(toPoint); 293 lengths.push_back(length); 294 } 295 296 static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) { 297 float oneMinusT = 1 - t; 298 float oneMinusTSquared = oneMinusT * oneMinusT; 299 float oneMinusTCubed = oneMinusTSquared * oneMinusT; 300 float tSquared = t * t; 301 float tCubed = tSquared * t; 302 return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1) 303 + (3 * oneMinusT * tSquared * p2) + (tCubed * p3); 304 } 305 306 static SkPoint cubicBezierCalculation(float t, const SkPoint* points) { 307 float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(), 308 points[2].x(), points[3].x()); 309 float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(), 310 points[2].y(), points[3].y()); 311 return SkPoint::Make(x, y); 312 } 313 314 static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) { 315 float oneMinusT = 1 - t; 316 return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2)); 317 } 318 319 static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) { 320 float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x()); 321 float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y()); 322 return SkPoint::Make(x, y); 323 } 324 325 // Subdivide a section of the Bezier curve, set the mid-point and the mid-t value. 326 // Returns true if further subdivision is necessary as defined by errorSquared. 327 static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction, 328 float t0, const SkPoint &p0, float t1, const SkPoint &p1, 329 float& midT, SkPoint &midPoint, float errorSquared) { 330 midT = (t1 + t0) / 2; 331 float midX = (p1.x() + p0.x()) / 2; 332 float midY = (p1.y() + p0.y()) / 2; 333 334 midPoint = (*bezierFunction)(midT, points); 335 float xError = midPoint.x() - midX; 336 float yError = midPoint.y() - midY; 337 float midErrorSquared = (xError * xError) + (yError * yError); 338 return midErrorSquared > errorSquared; 339 } 340 341 // Divides Bezier curves until linear interpolation is very close to accurate, using 342 // errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly 343 // short-circuit subdivision. If you imagine an S shape, the top and bottom points being the 344 // starting and end points, linear interpolation would mark the center where the curve places 345 // the point. It is clearly not the case that we can linearly interpolate at that point. 346 // doubleCheckDivision forces a second examination between subdivisions to ensure that linear 347 // interpolation works. 348 static void addBezier(const SkPoint* points, 349 bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints, 350 std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) { 351 typedef std::map<float, SkPoint> PointMap; 352 PointMap tToPoint; 353 354 tToPoint[0] = (*bezierFunction)(0, points); 355 tToPoint[1] = (*bezierFunction)(1, points); 356 357 PointMap::iterator iter = tToPoint.begin(); 358 PointMap::iterator next = iter; 359 ++next; 360 while (next != tToPoint.end()) { 361 bool needsSubdivision = true; 362 SkPoint midPoint; 363 do { 364 float midT; 365 needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 366 iter->second, next->first, next->second, midT, midPoint, errorSquared); 367 if (!needsSubdivision && doubleCheckDivision) { 368 SkPoint quarterPoint; 369 float quarterT; 370 needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 371 iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared); 372 if (needsSubdivision) { 373 // Found an inflection point. No need to double-check. 374 doubleCheckDivision = false; 375 } 376 } 377 if (needsSubdivision) { 378 next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint)); 379 } 380 } while (needsSubdivision); 381 iter = next; 382 next++; 383 } 384 385 // Now that each division can use linear interpolation with less than the allowed error 386 for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) { 387 addLine(segmentPoints, lengths, iter->second); 388 } 389 } 390 391 static void createVerbSegments(SkPath::Verb verb, const SkPoint* points, 392 std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) { 393 switch (verb) { 394 case SkPath::kMove_Verb: 395 addMove(segmentPoints, lengths, points[0]); 396 break; 397 case SkPath::kClose_Verb: 398 addLine(segmentPoints, lengths, points[0]); 399 break; 400 case SkPath::kLine_Verb: 401 addLine(segmentPoints, lengths, points[1]); 402 break; 403 case SkPath::kQuad_Verb: 404 addBezier(points, quadraticBezierCalculation, segmentPoints, lengths, 405 errorSquared, false); 406 break; 407 case SkPath::kCubic_Verb: 408 addBezier(points, cubicBezierCalculation, segmentPoints, lengths, 409 errorSquared, true); 410 break; 411 default: 412 // Leave element as NULL, Conic sections are not supported. 413 break; 414 } 415 } 416 417 // Returns a float[] with each point along the path represented by 3 floats 418 // * fractional length along the path that the point resides 419 // * x coordinate 420 // * y coordinate 421 // Note that more than one point may have the same length along the path in 422 // the case of a move. 423 // NULL can be returned if the Path is empty. 424 static jfloatArray approximate(JNIEnv* env, jclass, SkPath* path, float acceptableError) 425 { 426 SkASSERT(path); 427 SkPath::Iter pathIter(*path, false); 428 SkPath::Verb verb; 429 SkPoint points[4]; 430 std::vector<SkPoint> segmentPoints; 431 std::vector<float> lengths; 432 float errorSquared = acceptableError * acceptableError; 433 434 while ((verb = pathIter.next(points)) != SkPath::kDone_Verb) { 435 createVerbSegments(verb, points, segmentPoints, lengths, errorSquared); 436 } 437 438 if (segmentPoints.empty()) { 439 return NULL; 440 } 441 442 size_t numPoints = segmentPoints.size(); 443 size_t approximationArraySize = numPoints * 3; 444 445 float* approximation = new float[approximationArraySize]; 446 float totalLength = lengths.back(); 447 448 int approximationIndex = 0; 449 for (size_t i = 0; i < numPoints; i++) { 450 const SkPoint& point = segmentPoints[i]; 451 approximation[approximationIndex++] = lengths[i] / totalLength; 452 approximation[approximationIndex++] = point.x(); 453 approximation[approximationIndex++] = point.y(); 454 } 455 456 jfloatArray result = env->NewFloatArray(approximationArraySize); 457 env->SetFloatArrayRegion(result, 0, approximationArraySize, approximation); 458 delete[] approximation; 459 return result; 460 } 461 462 static SkPathMeasure* trim(JNIEnv* env, jobject clazz, SkPath* inPath, SkPath* outPath, 463 SkPathMeasure* pathMeasure, jfloat trimStart, jfloat trimEnd, jfloat trimOffset) { 464 if (trimStart == 0 && trimEnd == 1) { 465 if (outPath != NULL) { 466 *outPath = *inPath; 467 } 468 return pathMeasure; 469 } 470 471 bool modifyPath = (outPath == NULL); 472 if (modifyPath) { 473 outPath = new SkPath(); 474 } else { 475 outPath->reset(); 476 } 477 if (pathMeasure == NULL) { 478 pathMeasure = new SkPathMeasure(*inPath, false); 479 } 480 float length = pathMeasure->getLength(); 481 float start = (trimStart + trimOffset) * length; 482 float end = (trimEnd + trimOffset) * length; 483 484 if (end > length && start <= length) { 485 pathMeasure->getSegment(start, length, outPath, true); 486 pathMeasure->getSegment(0, end - length, outPath, true); 487 } else { 488 if (start > length) { 489 start -= length; 490 end -= length; 491 } 492 pathMeasure->getSegment(start, end, outPath, true); 493 } 494 if (modifyPath) { 495 delete pathMeasure; 496 pathMeasure = NULL; 497 *inPath = *outPath; 498 delete outPath; 499 } 500 return pathMeasure; 501 } 502 503 static void destroyMeasure(JNIEnv* env, jobject clazz, SkPathMeasure* measure) { 504 delete measure; 505 } 506}; 507 508static JNINativeMethod methods[] = { 509 {"finalizer", "(I)V", (void*) SkPathGlue::finalizer}, 510 {"init1","()I", (void*) SkPathGlue::init1}, 511 {"init2","(I)I", (void*) SkPathGlue::init2}, 512 {"native_reset","(I)V", (void*) SkPathGlue::reset}, 513 {"native_rewind","(I)V", (void*) SkPathGlue::rewind}, 514 {"native_set","(II)V", (void*) SkPathGlue::assign}, 515 {"native_getFillType","(I)I", (void*) SkPathGlue::getFillType}, 516 {"native_setFillType","(II)V", (void*) SkPathGlue::setFillType}, 517 {"native_isEmpty","(I)Z", (void*) SkPathGlue::isEmpty}, 518 {"native_isRect","(ILandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect}, 519 {"native_computeBounds","(ILandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds}, 520 {"native_incReserve","(II)V", (void*) SkPathGlue::incReserve}, 521 {"native_moveTo","(IFF)V", (void*) SkPathGlue::moveTo__FF}, 522 {"native_rMoveTo","(IFF)V", (void*) SkPathGlue::rMoveTo}, 523 {"native_lineTo","(IFF)V", (void*) SkPathGlue::lineTo__FF}, 524 {"native_rLineTo","(IFF)V", (void*) SkPathGlue::rLineTo}, 525 {"native_quadTo","(IFFFF)V", (void*) SkPathGlue::quadTo__FFFF}, 526 {"native_rQuadTo","(IFFFF)V", (void*) SkPathGlue::rQuadTo}, 527 {"native_cubicTo","(IFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF}, 528 {"native_rCubicTo","(IFFFFFF)V", (void*) SkPathGlue::rCubicTo}, 529 {"native_arcTo","(ILandroid/graphics/RectF;FFZ)V", (void*) SkPathGlue::arcTo}, 530 {"native_close","(I)V", (void*) SkPathGlue::close}, 531 {"native_addRect","(ILandroid/graphics/RectF;I)V", (void*) SkPathGlue::addRect__RectFI}, 532 {"native_addRect","(IFFFFI)V", (void*) SkPathGlue::addRect__FFFFI}, 533 {"native_addOval","(ILandroid/graphics/RectF;I)V", (void*) SkPathGlue::addOval}, 534 {"native_addCircle","(IFFFI)V", (void*) SkPathGlue::addCircle}, 535 {"native_addArc","(ILandroid/graphics/RectF;FF)V", (void*) SkPathGlue::addArc}, 536 {"native_addRoundRect","(ILandroid/graphics/RectF;FFI)V", (void*) SkPathGlue::addRoundRectXY}, 537 {"native_addRoundRect","(ILandroid/graphics/RectF;[FI)V", (void*) SkPathGlue::addRoundRect8}, 538 {"native_addPath","(IIFF)V", (void*) SkPathGlue::addPath__PathFF}, 539 {"native_addPath","(II)V", (void*) SkPathGlue::addPath__Path}, 540 {"native_addPath","(III)V", (void*) SkPathGlue::addPath__PathMatrix}, 541 {"native_offset","(IFFI)V", (void*) SkPathGlue::offset__FFPath}, 542 {"native_offset","(IFF)V", (void*) SkPathGlue::offset__FF}, 543 {"native_setLastPoint","(IFF)V", (void*) SkPathGlue::setLastPoint}, 544 {"native_transform","(III)V", (void*) SkPathGlue::transform__MatrixPath}, 545 {"native_transform","(II)V", (void*) SkPathGlue::transform__Matrix}, 546 {"native_op","(IIII)Z", (void*) SkPathGlue::op}, 547 {"native_approximate", "(IF)[F", (void*) SkPathGlue::approximate}, 548 {"native_destroyMeasure","(I)V", (void*) SkPathGlue::destroyMeasure}, 549 {"native_trim","(IIIFFF)I", (void*) SkPathGlue::trim}, 550}; 551 552int register_android_graphics_Path(JNIEnv* env) { 553 int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/Path", methods, 554 sizeof(methods) / sizeof(methods[0])); 555 return result; 556} 557 558} 559