19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* libs/android_runtime/android/graphics/Path.cpp 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 524609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** Licensed under the Apache License, Version 2.0 (the "License"); 624609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** you may not use this file except in compliance with the License. 724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 924609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** http://www.apache.org/licenses/LICENSE-2.0 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 1124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** Unless required by applicable law or agreed to in writing, software 1224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** distributed under the License is distributed on an "AS IS" BASIS, 1324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// This file was generated from the C++ include file: SkPath.h 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Any changes made to this file will be discarded by the build. 2024609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// or one of the auxilary file specifications in device/tools/gluemaker. 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h" 25ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkPath.h" 28eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include "SkPathOps.h" 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger#include <Caches.h> 31c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount#include <vector> 32c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount#include <map> 33a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass SkPathGlue { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic: 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { 4036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 41ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger // Purge entries from the HWUI path cache if this path's data is unique 42ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger if (obj->unique() && android::uirenderer::Caches::hasInstance()) { 43ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj); 44a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy } 45ee248599d49a15fc207c5aeb0b90ec263cc1d600Derek Sollenberger delete obj; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jlong init1(JNIEnv* env, jobject clazz) { 4936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat return reinterpret_cast<jlong>(new SkPath()); 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat 5236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jlong init2(JNIEnv* env, jobject clazz, jlong valHandle) { 5336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* val = reinterpret_cast<SkPath*>(valHandle); 5436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat return reinterpret_cast<jlong>(new SkPath(*val)); 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat 5736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void reset(JNIEnv* env, jobject clazz, jlong objHandle) { 5836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->reset(); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void rewind(JNIEnv* env, jobject clazz, jlong objHandle) { 6336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->rewind(); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void assign(JNIEnv* env, jobject clazz, jlong dstHandle, jlong srcHandle) { 6836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 6936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat const SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *dst = *src; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat 735be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) { 745be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 755be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik return obj->isConvex(); 765be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik } 775be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik 7836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) { 7936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return obj->getFillType(); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 825be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik 8336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) { 8436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 8536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path->setFillType(ft); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat 8936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jboolean isEmpty(JNIEnv* env, jobject clazz, jlong objHandle) { 9036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return obj->isEmpty(); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 942e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) { 952e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III SkRect rect; 9636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 972e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III jboolean result = obj->isRect(&rect); 982e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III GraphicsJNI::rect_to_jrectf(rect, env, jrect); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 1022e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) { 10336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1042e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III const SkRect& bounds = obj->getBounds(); 1052e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III GraphicsJNI::rect_to_jrectf(bounds, env, jbounds); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 10836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) { 10936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->incReserve(extraPtCount); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 11336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) { 11436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1152e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->moveTo(x, y); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 11836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 11936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1202e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->rMoveTo(dx, dy); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 12336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) { 12436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1252e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->lineTo(x, y); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 12836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 12936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1302e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->rLineTo(dx, dy); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 13336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) { 13436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1352e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->quadTo(x1, y1, x2, y2); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 13836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) { 13936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1402e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->rQuadTo(dx1, dy1, dx2, dy2); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 14336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 14436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1452e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->cubicTo(x1, y1, x2, y2, x3, y3); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 14836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) { 14936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1502e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->rCubicTo(x1, y1, x2, y2, x3, y3); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 15324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, 15424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, 15524609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese jboolean forceMoveTo) { 15636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 15724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 15824609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese obj->arcTo(oval, startAngle, sweepAngle, forceMoveTo); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16024609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 16136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void close(JNIEnv* env, jobject clazz, jlong objHandle) { 16236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->close(); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1657979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik 1667979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik static void addRect(JNIEnv* env, jobject clazz, jlong objHandle, 1677979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { 16836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 16936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 1702e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->addRect(left, top, right, bottom, dir); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1727979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik 1737979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, 1747979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) { 17536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 17636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 1777979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 1787979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik obj->addOval(oval, dir); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1807979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik 18136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) { 18236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 18336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 1842e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->addCircle(x, y, radius, dir); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1867979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik 18724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, 18824609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle) { 18924609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 19036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 19124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese obj->addArc(oval, startAngle, sweepAngle); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1937979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik 19424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, 19524609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese jfloat right, jfloat bottom, jfloat rx, jfloat ry, jint dirHandle) { 19624609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 19736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 19836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 1992e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->addRoundRect(rect, rx, ry, dir); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 20224609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jfloat left, jfloat top, 20324609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) { 20424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 20536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 20636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoJavaFloatArray afa(env, array, 8); 2082e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III#ifdef SK_SCALAR_IS_FLOAT 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const float* src = afa.ptr(); 2102e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III#else 2112e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III #error Need to convert float array to SkScalar array before calling the following function. 2122e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III#endif 2132e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->addRoundRect(rect, src, dir); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21524609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 21636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) { 21736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 21836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 2192e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->addPath(*src, dx, dy); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 22236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) { 22336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 22436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->addPath(*src); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22724609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 22836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void addPath__PathMatrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong matrixHandle) { 22936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 23036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 23136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->addPath(*src, *matrix); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 23536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 23636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 2372e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->offset(dx, dy); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void setLastPoint(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) { 24136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 2422e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III obj->setLastPt(dx, dy); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 24536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) { 24636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 24736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 24836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->transform(*matrix, dst); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese 25236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static void transform__Matrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle) { 25336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* obj = reinterpret_cast<SkPath*>(objHandle); 25436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project obj->transform(*matrix); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2578018c8db8221aa604b3c083e09d173cc27e53d83Romain Guy 25836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jboolean op(JNIEnv* env, jobject clazz, jlong p1Handle, jlong p2Handle, jint opHandle, jlong rHandle) { 25936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* p1 = reinterpret_cast<SkPath*>(p1Handle); 26036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* p2 = reinterpret_cast<SkPath*>(p2Handle); 26136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPathOp op = static_cast<SkPathOp>(opHandle); 26236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* r = reinterpret_cast<SkPath*>(rHandle); 26336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat return Op(*p1, *p2, op, r); 2648018c8db8221aa604b3c083e09d173cc27e53d83Romain Guy } 265c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 266c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount typedef SkPoint (*bezierCalculation)(float t, const SkPoint* points); 267c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 268c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static void addMove(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 269c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount const SkPoint& point) { 270c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float length = 0; 271c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (!lengths.empty()) { 272c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount length = lengths.back(); 273c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 274c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount segmentPoints.push_back(point); 275c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount lengths.push_back(length); 276c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 277c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 278c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static void addLine(std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, 279c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount const SkPoint& toPoint) { 280c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (segmentPoints.empty()) { 281c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount segmentPoints.push_back(SkPoint::Make(0, 0)); 282c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount lengths.push_back(0); 283c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } else if (segmentPoints.back() == toPoint) { 284c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return; // Empty line 285c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 286c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float length = lengths.back() + SkPoint::Distance(segmentPoints.back(), toPoint); 287c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount segmentPoints.push_back(toPoint); 288c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount lengths.push_back(length); 289c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 290c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 291c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static float cubicCoordinateCalculation(float t, float p0, float p1, float p2, float p3) { 292c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float oneMinusT = 1 - t; 293c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float oneMinusTSquared = oneMinusT * oneMinusT; 294c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float oneMinusTCubed = oneMinusTSquared * oneMinusT; 295c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float tSquared = t * t; 296c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float tCubed = tSquared * t; 297c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return (oneMinusTCubed * p0) + (3 * oneMinusTSquared * t * p1) 298c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount + (3 * oneMinusT * tSquared * p2) + (tCubed * p3); 299c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 300c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 301c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static SkPoint cubicBezierCalculation(float t, const SkPoint* points) { 302c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float x = cubicCoordinateCalculation(t, points[0].x(), points[1].x(), 303c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount points[2].x(), points[3].x()); 304c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float y = cubicCoordinateCalculation(t, points[0].y(), points[1].y(), 305c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount points[2].y(), points[3].y()); 306c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return SkPoint::Make(x, y); 307c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 308c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 309c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static float quadraticCoordinateCalculation(float t, float p0, float p1, float p2) { 310c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float oneMinusT = 1 - t; 311c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return oneMinusT * ((oneMinusT * p0) + (t * p1)) + t * ((oneMinusT * p1) + (t * p2)); 312c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 313c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 314c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static SkPoint quadraticBezierCalculation(float t, const SkPoint* points) { 315c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float x = quadraticCoordinateCalculation(t, points[0].x(), points[1].x(), points[2].x()); 316c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float y = quadraticCoordinateCalculation(t, points[0].y(), points[1].y(), points[2].y()); 317c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return SkPoint::Make(x, y); 318c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 319c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 320c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Subdivide a section of the Bezier curve, set the mid-point and the mid-t value. 321c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Returns true if further subdivision is necessary as defined by errorSquared. 322c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static bool subdividePoints(const SkPoint* points, bezierCalculation bezierFunction, 323c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float t0, const SkPoint &p0, float t1, const SkPoint &p1, 324c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float& midT, SkPoint &midPoint, float errorSquared) { 325c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount midT = (t1 + t0) / 2; 326c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float midX = (p1.x() + p0.x()) / 2; 327c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float midY = (p1.y() + p0.y()) / 2; 328c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 329c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount midPoint = (*bezierFunction)(midT, points); 330c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float xError = midPoint.x() - midX; 331c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float yError = midPoint.y() - midY; 332c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float midErrorSquared = (xError * xError) + (yError * yError); 333c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return midErrorSquared > errorSquared; 334c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 335c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 336c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Divides Bezier curves until linear interpolation is very close to accurate, using 337c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // errorSquared as a metric. Cubic Bezier curves can have an inflection point that improperly 338c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // short-circuit subdivision. If you imagine an S shape, the top and bottom points being the 339c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // starting and end points, linear interpolation would mark the center where the curve places 340c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // the point. It is clearly not the case that we can linearly interpolate at that point. 341c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // doubleCheckDivision forces a second examination between subdivisions to ensure that linear 342c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // interpolation works. 343c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static void addBezier(const SkPoint* points, 344c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount bezierCalculation bezierFunction, std::vector<SkPoint>& segmentPoints, 345c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount std::vector<float>& lengths, float errorSquared, bool doubleCheckDivision) { 346c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount typedef std::map<float, SkPoint> PointMap; 347c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount PointMap tToPoint; 348c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 349c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount tToPoint[0] = (*bezierFunction)(0, points); 350c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount tToPoint[1] = (*bezierFunction)(1, points); 351c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 352c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount PointMap::iterator iter = tToPoint.begin(); 353c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount PointMap::iterator next = iter; 354c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount ++next; 355c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount while (next != tToPoint.end()) { 356c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount bool needsSubdivision = true; 357c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkPoint midPoint; 358c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount do { 359c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float midT; 360c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 361c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount iter->second, next->first, next->second, midT, midPoint, errorSquared); 362c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (!needsSubdivision && doubleCheckDivision) { 363c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkPoint quarterPoint; 364c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float quarterT; 365c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount needsSubdivision = subdividePoints(points, bezierFunction, iter->first, 366c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount iter->second, midT, midPoint, quarterT, quarterPoint, errorSquared); 367c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (needsSubdivision) { 368c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Found an inflection point. No need to double-check. 369c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount doubleCheckDivision = false; 370c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 371c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 372c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (needsSubdivision) { 373c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount next = tToPoint.insert(iter, PointMap::value_type(midT, midPoint)); 374c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 375c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } while (needsSubdivision); 376c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount iter = next; 377c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount next++; 378c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 379c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 380c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Now that each division can use linear interpolation with less than the allowed error 381c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount for (iter = tToPoint.begin(); iter != tToPoint.end(); ++iter) { 382c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount addLine(segmentPoints, lengths, iter->second); 383c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 384c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 385c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 386c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount static void createVerbSegments(SkPath::Verb verb, const SkPoint* points, 387c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount std::vector<SkPoint>& segmentPoints, std::vector<float>& lengths, float errorSquared) { 388c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount switch (verb) { 389c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount case SkPath::kMove_Verb: 390c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount addMove(segmentPoints, lengths, points[0]); 391c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount break; 392c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount case SkPath::kClose_Verb: 3937fe03a267e6edb65142444765ce29ad5ff126052George Mount addLine(segmentPoints, lengths, points[0]); 3947fe03a267e6edb65142444765ce29ad5ff126052George Mount break; 395c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount case SkPath::kLine_Verb: 396c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount addLine(segmentPoints, lengths, points[1]); 397c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount break; 398c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount case SkPath::kQuad_Verb: 399c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount addBezier(points, quadraticBezierCalculation, segmentPoints, lengths, 400c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount errorSquared, false); 401c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount break; 402c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount case SkPath::kCubic_Verb: 403c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount addBezier(points, cubicBezierCalculation, segmentPoints, lengths, 404c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount errorSquared, true); 405c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount break; 406c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount default: 407c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Leave element as NULL, Conic sections are not supported. 408c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount break; 409c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 410c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 411c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 412c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Returns a float[] with each point along the path represented by 3 floats 413c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // * fractional length along the path that the point resides 414c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // * x coordinate 415c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // * y coordinate 416c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // Note that more than one point may have the same length along the path in 417c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // the case of a move. 418c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount // NULL can be returned if the Path is empty. 41936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat static jfloatArray approximate(JNIEnv* env, jclass, jlong pathHandle, float acceptableError) 420c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount { 42136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 422c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkASSERT(path); 423c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkPath::Iter pathIter(*path, false); 424c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkPath::Verb verb; 425c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount SkPoint points[4]; 426c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount std::vector<SkPoint> segmentPoints; 427c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount std::vector<float> lengths; 428c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float errorSquared = acceptableError * acceptableError; 429c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 43068cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount while ((verb = pathIter.next(points, false)) != SkPath::kDone_Verb) { 431c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount createVerbSegments(verb, points, segmentPoints, lengths, errorSquared); 432c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 433c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 434c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount if (segmentPoints.empty()) { 43568cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount int numVerbs = path->countVerbs(); 43668cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount if (numVerbs == 1) { 43768cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount addMove(segmentPoints, lengths, path->getPoint(0)); 43868cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount } else { 43968cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount // Invalid or empty path. Fall back to point(0,0) 44068cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount addMove(segmentPoints, lengths, SkPoint()); 44168cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount } 44268cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount } 44368cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount 44468cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount float totalLength = lengths.back(); 44568cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount if (totalLength == 0) { 44668cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount // Lone Move instructions should still be able to animate at the same value. 44768cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount segmentPoints.push_back(segmentPoints.back()); 44868cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount lengths.push_back(1); 44968cfdad20d83400e0cc0ddb4c86deaeda3337d4dGeorge Mount totalLength = 1; 450c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 451c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 452c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount size_t numPoints = segmentPoints.size(); 453c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount size_t approximationArraySize = numPoints * 3; 454c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 455c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount float* approximation = new float[approximationArraySize]; 456c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 457c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount int approximationIndex = 0; 4587fe03a267e6edb65142444765ce29ad5ff126052George Mount for (size_t i = 0; i < numPoints; i++) { 459c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount const SkPoint& point = segmentPoints[i]; 460c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount approximation[approximationIndex++] = lengths[i] / totalLength; 461c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount approximation[approximationIndex++] = point.x(); 462c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount approximation[approximationIndex++] = point.y(); 463c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 464c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount 465c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount jfloatArray result = env->NewFloatArray(approximationArraySize); 466c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount env->SetFloatArrayRegion(result, 0, approximationArraySize, approximation); 467c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount delete[] approximation; 468c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount return result; 469c96c7b2e54965e30c8fb82295f1ca9f891ebd5e7George Mount } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod methods[] = { 47336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"finalizer", "(J)V", (void*) SkPathGlue::finalizer}, 47436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"init1","()J", (void*) SkPathGlue::init1}, 47536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"init2","(J)J", (void*) SkPathGlue::init2}, 47636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_reset","(J)V", (void*) SkPathGlue::reset}, 47736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_rewind","(J)V", (void*) SkPathGlue::rewind}, 47836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_set","(JJ)V", (void*) SkPathGlue::assign}, 4795be83edd15e11420287cc0af93a95d5a6dfae68fChris Craik {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex}, 48036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType}, 48136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType}, 48236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty}, 48336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_isRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect}, 48436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_computeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds}, 48536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_incReserve","(JI)V", (void*) SkPathGlue::incReserve}, 48636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_moveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF}, 48736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_rMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo}, 48836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_lineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF}, 48936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_rLineTo","(JFF)V", (void*) SkPathGlue::rLineTo}, 49036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_quadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF}, 49136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_rQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo}, 49236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_cubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF}, 49336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo}, 49424609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese {"native_arcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo}, 49536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_close","(J)V", (void*) SkPathGlue::close}, 4967979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect}, 4977979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval}, 49836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle}, 49924609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese {"native_addArc","(JFFFFFF)V", (void*) SkPathGlue::addArc}, 50024609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese {"native_addRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY}, 50124609581330bc350f797179e3c1a59789c645ec2Antonio Calabrese {"native_addRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8}, 50236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_addPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF}, 50336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_addPath","(JJ)V", (void*) SkPathGlue::addPath__Path}, 50436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_addPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix}, 50536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_offset","(JFF)V", (void*) SkPathGlue::offset__FF}, 50636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_setLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint}, 50736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_transform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath}, 50836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_transform","(JJ)V", (void*) SkPathGlue::transform__Matrix}, 50936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_op","(JJIJ)Z", (void*) SkPathGlue::op}, 51036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat {"native_approximate", "(JF)[F", (void*) SkPathGlue::approximate}, 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Path(JNIEnv* env) { 514ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, "android/graphics/Path", methods, NELEM(methods)); 5151ad545d207db840d0e403569ce214431eead4217Derek Sollenberger 5161ad545d207db840d0e403569ce214431eead4217Derek Sollenberger static_assert(0 == SkPath::kCW_Direction, "direction_mismatch"); 5171ad545d207db840d0e403569ce214431eead4217Derek Sollenberger static_assert(1 == SkPath::kCCW_Direction, "direction_mismatch"); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 521