1 /*
2 * Copyright 2021 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkColor.h"
10 #include "include/core/SkPaint.h"
11 #include "include/core/SkRRect.h"
12 #include "include/core/SkShader.h"
13 #include "modules/jetski/src/Utils.h"
14
15 #include <jni.h>
16
17 namespace {
18
Canvas_GetWidth(JNIEnv * env,jobject,jlong native_instance)19 jint Canvas_GetWidth(JNIEnv* env, jobject, jlong native_instance) {
20 const auto* canvas = reinterpret_cast<const SkCanvas*>(native_instance);
21 return canvas ? canvas->imageInfo().width() : 0;
22 }
23
Canvas_GetHeight(JNIEnv * env,jobject,jlong native_instance)24 jint Canvas_GetHeight(JNIEnv* env, jobject, jlong native_instance) {
25 const auto* canvas = reinterpret_cast<const SkCanvas*>(native_instance);
26 return canvas ? canvas->imageInfo().height() : 0;
27 }
28
Canvas_Save(JNIEnv * env,jobject,jlong native_instance)29 jint Canvas_Save(JNIEnv* env, jobject, jlong native_instance) {
30 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
31 return canvas->save();
32 }
33 return 0;
34 }
35
Canvas_Restore(JNIEnv * env,jobject,jlong native_instance)36 void Canvas_Restore(JNIEnv* env, jobject, jlong native_instance) {
37 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
38 canvas->restore();
39 }
40 }
41
Canvas_RestoreToCount(JNIEnv * env,jobject,jlong native_instance,jint count)42 void Canvas_RestoreToCount(JNIEnv* env, jobject, jlong native_instance, jint count) {
43 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
44 canvas->restoreToCount(count);
45 }
46 }
47
Canvas_SaveLayer(JNIEnv * env,jobject,jlong native_instance,jlong native_paint)48 jint Canvas_SaveLayer(JNIEnv* env, jobject, jlong native_instance, jlong native_paint) {
49 auto* paint = reinterpret_cast<SkPaint* >(native_paint);
50 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
51 return canvas->saveLayer(nullptr, paint);
52 }
53 return 0;
54 }
55
Canvas_LocalToDevice(JNIEnv * env,jobject,jlong native_instance)56 jlong Canvas_LocalToDevice(JNIEnv* env, jobject, jlong native_instance) {
57 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
58 SkM44* m = new SkM44(canvas->getLocalToDevice());
59 return reinterpret_cast<jlong>(m);
60 }
61 return 0;
62 }
63
Canvas_Concat(JNIEnv * env,jobject,jlong native_instance,jlong native_matrix)64 void Canvas_Concat(JNIEnv* env, jobject, jlong native_instance, jlong native_matrix) {
65 auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
66 auto* matrix = reinterpret_cast<SkM44* >(native_matrix);
67
68 if (canvas && matrix) {
69 canvas->concat(*matrix);
70 }
71 }
72
Canvas_Concat16f(JNIEnv * env,jobject,jlong native_instance,jfloatArray jmatrix)73 void Canvas_Concat16f(JNIEnv* env, jobject, jlong native_instance, jfloatArray jmatrix) {
74 SkASSERT(env->GetArrayLength(jmatrix) == 16);
75
76 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
77 auto* m = env->GetFloatArrayElements(jmatrix, nullptr);
78 canvas->concat(SkM44::RowMajor(m));
79 env->ReleaseFloatArrayElements(jmatrix, m, 0);
80 }
81 }
82
Canvas_Translate(JNIEnv * env,jobject,jlong native_instance,jfloat tx,jfloat ty,jfloat tz)83 void Canvas_Translate(JNIEnv* env, jobject, jlong native_instance,
84 jfloat tx, jfloat ty, jfloat tz) {
85 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
86 canvas->concat(SkM44::Translate(tx, ty, tz));
87 }
88 }
89
Canvas_Scale(JNIEnv * env,jobject,jlong native_instance,jfloat sx,jfloat sy,jfloat sz)90 void Canvas_Scale(JNIEnv* env, jobject, jlong native_instance, jfloat sx, jfloat sy, jfloat sz) {
91 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
92 canvas->concat(SkM44::Scale(sx, sy, sz));
93 }
94 }
95
Canvas_ClipPath(JNIEnv * env,jobject,jlong native_instance,jlong native_path,jint native_clipOp,jboolean doAA)96 void Canvas_ClipPath(JNIEnv* env, jobject, jlong native_instance, jlong native_path,
97 jint native_clipOp, jboolean doAA) {
98 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
99 if (auto* path = reinterpret_cast<SkPath*>(native_path)) {
100 canvas->clipPath(*path, static_cast<SkClipOp>(native_clipOp), doAA);
101 }
102 }
103 }
104
Canvas_ClipRect(JNIEnv * env,jobject,jlong native_instance,jfloat l,jfloat t,jfloat r,jfloat b,jint native_clipOp,jboolean doAA)105 void Canvas_ClipRect(JNIEnv* env, jobject, jlong native_instance, jfloat l, jfloat t, jfloat r, jfloat b,
106 jint native_clipOp, jboolean doAA) {
107 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
108 canvas->clipRect(SkRect::MakeLTRB(l, t, r, b), static_cast<SkClipOp>(native_clipOp), doAA);
109 }
110 }
111
Canvas_ClipRRect(JNIEnv * env,jobject,jlong native_instance,jfloat l,jfloat t,jfloat r,jfloat b,jfloat xRad,jfloat yRad,jint native_clipOp,jboolean doAA)112 void Canvas_ClipRRect(JNIEnv* env, jobject, jlong native_instance, jfloat l, jfloat t, jfloat r, jfloat b,
113 jfloat xRad, jfloat yRad,
114 jint native_clipOp, jboolean doAA) {
115 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
116 canvas->clipRRect(SkRRect::MakeRectXY(SkRect::MakeLTRB(l, t, r, b), xRad, yRad),
117 static_cast<SkClipOp>(native_clipOp), doAA);
118 }
119 }
120
Canvas_ClipShader(JNIEnv * env,jobject,jlong native_instance,jlong native_shader,jint native_clipOp)121 void Canvas_ClipShader(JNIEnv* env, jobject, jlong native_instance, jlong native_shader, jint native_clipOp) {
122 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
123 if (auto* shader = reinterpret_cast<SkShader*>(native_shader)) {
124 canvas->clipShader(sk_ref_sp(shader), static_cast<SkClipOp>(native_clipOp));
125 }
126 }
127 }
128
Canvas_DrawColor(JNIEnv * env,jobject,jlong native_instance,float r,float g,float b,float a)129 void Canvas_DrawColor(JNIEnv* env, jobject, jlong native_instance,
130 float r, float g, float b, float a) {
131 if (auto* canvas = reinterpret_cast<SkCanvas*>(native_instance)) {
132 canvas->drawColor(SkColor4f{r, g, b, a});
133 }
134 }
135
Canvas_DrawRect(JNIEnv * env,jobject,jlong native_instance,jfloat left,jfloat top,jfloat right,jfloat bottom,jlong native_paint)136 void Canvas_DrawRect(JNIEnv* env, jobject, jlong native_instance,
137 jfloat left, jfloat top, jfloat right, jfloat bottom,
138 jlong native_paint) {
139 auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
140 auto* paint = reinterpret_cast<SkPaint* >(native_paint);
141 if (canvas && paint) {
142 canvas->drawRect(SkRect::MakeLTRB(left, top, right, bottom), *paint);
143 }
144 }
145
Canvas_DrawImage(JNIEnv * env,jobject,jlong native_instance,jlong native_image,jfloat x,jfloat y,jint sampling_desc,jfloat sampling_b,jfloat sampling_c)146 void Canvas_DrawImage(JNIEnv* env, jobject, jlong native_instance, jlong native_image,
147 jfloat x, jfloat y,
148 jint sampling_desc, jfloat sampling_b, jfloat sampling_c) {
149 auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
150 auto* image = reinterpret_cast<SkImage *>(native_image);
151
152 if (canvas && image) {
153 canvas->drawImage(image, x, y,
154 jetski::utils::SamplingOptions(sampling_desc, sampling_b, sampling_c));
155 }
156 }
157
Canvas_DrawPath(JNIEnv * env,jobject,jlong native_instance,jlong native_path,jlong native_paint)158 void Canvas_DrawPath(JNIEnv* env, jobject, jlong native_instance, jlong native_path,
159 jlong native_paint) {
160 auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
161 auto* path = reinterpret_cast<SkPath* >(native_path);
162 auto* paint = reinterpret_cast<SkPaint* >(native_paint);
163 if (canvas && paint && path) {
164 canvas->drawPath(*path, *paint);
165 }
166 }
167
168 // jPos: a composite array in the form of [x1, y1, x2, y2, ... ,xn, yn]
169 // callers of this function check should throw IllegalArgumentException in Java
Canvas_DrawGlyphs(JNIEnv * env,jobject,jlong native_instance,jcharArray jglyphs,jfloatArray jPos,jfloat xOrigin,jfloat yOrigin,jlong native_font,jlong native_paint)170 void Canvas_DrawGlyphs(JNIEnv* env, jobject, jlong native_instance, jcharArray jglyphs,
171 jfloatArray jPos, jfloat xOrigin, jfloat yOrigin,
172 jlong native_font, jlong native_paint) {
173 auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
174 auto* font = reinterpret_cast<SkFont*>(native_font);
175 auto* paint = reinterpret_cast<SkPaint* >(native_paint);
176 if (canvas && font && paint) {
177 int count = env->GetArrayLength(jglyphs);
178 auto* compositePositions = env->GetFloatArrayElements(jPos, nullptr);
179 auto* positions = reinterpret_cast<SkPoint*>(compositePositions);
180 auto* glyphs = env->GetCharArrayElements(jglyphs, nullptr);
181 canvas->drawGlyphs(count, glyphs, positions, {xOrigin, yOrigin}, *font, *paint);
182
183 env->ReleaseCharArrayElements(jglyphs, glyphs, 0);
184 env->ReleaseFloatArrayElements(jPos, compositePositions, 0);
185 }
186 }
187
188 } // namespace
189
register_jetski_Canvas(JNIEnv * env)190 int register_jetski_Canvas(JNIEnv* env) {
191 static const JNINativeMethod methods[] = {
192 {"nGetWidth" , "(J)I" , reinterpret_cast<void*>(Canvas_GetWidth) },
193 {"nGetHeight" , "(J)I" , reinterpret_cast<void*>(Canvas_GetHeight) },
194 {"nSave" , "(J)I" , reinterpret_cast<void*>(Canvas_Save) },
195 {"nSaveLayer" , "(JJ)I" , reinterpret_cast<void*>(Canvas_SaveLayer) },
196 {"nRestore" , "(J)V" , reinterpret_cast<void*>(Canvas_Restore) },
197 {"nRestoreToCount" , "(JI)V" , reinterpret_cast<void*>(Canvas_RestoreToCount)},
198 {"nGetLocalToDevice", "(J)J" , reinterpret_cast<void*>(Canvas_LocalToDevice) },
199 {"nConcat" , "(JJ)V" , reinterpret_cast<void*>(Canvas_Concat) },
200 {"nConcat16f" , "(J[F)V" , reinterpret_cast<void*>(Canvas_Concat16f) },
201 {"nTranslate" , "(JFFF)V" , reinterpret_cast<void*>(Canvas_Translate) },
202 {"nScale" , "(JFFF)V" , reinterpret_cast<void*>(Canvas_Scale) },
203 {"nClipPath" , "(JJIZ)V" , reinterpret_cast<void*>(Canvas_ClipPath) },
204 {"nClipRect" , "(JFFFFIZ)V" , reinterpret_cast<void*>(Canvas_ClipRect) },
205 {"nClipRRect" , "(JFFFFFFIZ)V" , reinterpret_cast<void*>(Canvas_ClipRRect) },
206 {"nClipShader" , "(JJI)V" , reinterpret_cast<void*>(Canvas_ClipShader) },
207 {"nDrawColor" , "(JFFFF)V" , reinterpret_cast<void*>(Canvas_DrawColor) },
208 {"nDrawRect" , "(JFFFFJ)V" , reinterpret_cast<void*>(Canvas_DrawRect) },
209 {"nDrawImage" , "(JJFFIFF)V" , reinterpret_cast<void*>(Canvas_DrawImage) },
210 {"nDrawPath" , "(JJJ)V" , reinterpret_cast<void*>(Canvas_DrawPath) },
211 {"nDrawGlyphs" , "(J[C[FFFJJ)V", reinterpret_cast<void*>(Canvas_DrawGlyphs) },
212
213 };
214
215 const auto clazz = env->FindClass("org/skia/jetski/Canvas");
216 return clazz
217 ? env->RegisterNatives(clazz, methods, std::size(methods))
218 : JNI_ERR;
219 }
220