summaryrefslogtreecommitdiff
path: root/libs/hwui/jni/PathIterator.cpp
blob: e9de6555935d977a0000f07a2d606455de3caa05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* libs/android_runtime/android/graphics/PathMeasure.cpp
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include <log/log.h>

#include "GraphicsJNI.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "graphics_jni_helpers.h"

namespace android {

class SkPathIteratorGlue {
public:
    static void finalizer(SkPath::RawIter* obj) { delete obj; }

    static jlong getFinalizer(JNIEnv* env, jclass clazz) {
        return static_cast<jlong>(reinterpret_cast<uintptr_t>(&finalizer));
    }

    static jlong create(JNIEnv* env, jobject clazz, jlong pathHandle) {
        const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
        return reinterpret_cast<jlong>(new SkPath::RawIter(*path));
    }

    // A variant of 'next' (below) that is compatible with the host JVM.
    static jint nextHost(JNIEnv* env, jclass clazz, jlong iteratorHandle, jfloatArray pointsArray) {
        jfloat* points = env->GetFloatArrayElements(pointsArray, 0);
#ifdef __ANDROID__
        jint result = next(iteratorHandle, reinterpret_cast<jlong>(points));
#else
        jint result = next(env, clazz, iteratorHandle, reinterpret_cast<jlong>(points));
#endif
        env->ReleaseFloatArrayElements(pointsArray, points, 0);
        return result;
    }

    // ---------------- @CriticalNative -------------------------

    static jint peek(CRITICAL_JNI_PARAMS_COMMA jlong iteratorHandle) {
        SkPath::RawIter* iterator = reinterpret_cast<SkPath::RawIter*>(iteratorHandle);
        return iterator->peek();
    }

    static jint next(CRITICAL_JNI_PARAMS_COMMA jlong iteratorHandle, jlong pointsArray) {
        static_assert(SkPath::kMove_Verb == 0, "SkPath::Verb unexpected index");
        static_assert(SkPath::kLine_Verb == 1, "SkPath::Verb unexpected index");
        static_assert(SkPath::kQuad_Verb == 2, "SkPath::Verb unexpected index");
        static_assert(SkPath::kConic_Verb == 3, "SkPath::Verb unexpected index");
        static_assert(SkPath::kCubic_Verb == 4, "SkPath::Verb unexpected index");
        static_assert(SkPath::kClose_Verb == 5, "SkPath::Verb unexpected index");
        static_assert(SkPath::kDone_Verb == 6, "SkPath::Verb unexpected index");

        SkPath::RawIter* iterator = reinterpret_cast<SkPath::RawIter*>(iteratorHandle);
        float* points = reinterpret_cast<float*>(pointsArray);
        SkPath::Verb verb =
                static_cast<SkPath::Verb>(iterator->next(reinterpret_cast<SkPoint*>(points)));
        if (verb == SkPath::kConic_Verb) {
            float weight = iterator->conicWeight();
            points[6] = weight;
        }
        return static_cast<int>(verb);
    }
};

static const JNINativeMethod methods[] = {
        {"nCreate", "(J)J", (void*)SkPathIteratorGlue::create},
        {"nGetFinalizer", "()J", (void*)SkPathIteratorGlue::getFinalizer},

        // ------- @CriticalNative below here ------------------

        {"nPeek", "(J)I", (void*)SkPathIteratorGlue::peek},
        {"nNext", "(JJ)I", (void*)SkPathIteratorGlue::next},
        {"nNextHost", "(J[F)I", (void*)SkPathIteratorGlue::nextHost},
};

int register_android_graphics_PathIterator(JNIEnv* env) {
    return RegisterMethodsOrDie(env, "android/graphics/PathIterator", methods, NELEM(methods));
}

}  // namespace android