/* * Copyright 2021 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkCanvas.h" #include "include/core/SkColor.h" #include "include/core/SkPaint.h" #include "include/core/SkRRect.h" #include "include/core/SkShader.h" #include "modules/jetski/src/Utils.h" #include namespace { jint Canvas_GetWidth(JNIEnv* env, jobject, jlong native_instance) { const auto* canvas = reinterpret_cast(native_instance); return canvas ? canvas->imageInfo().width() : 0; } jint Canvas_GetHeight(JNIEnv* env, jobject, jlong native_instance) { const auto* canvas = reinterpret_cast(native_instance); return canvas ? canvas->imageInfo().height() : 0; } jint Canvas_Save(JNIEnv* env, jobject, jlong native_instance) { if (auto* canvas = reinterpret_cast(native_instance)) { return canvas->save(); } return 0; } void Canvas_Restore(JNIEnv* env, jobject, jlong native_instance) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->restore(); } } void Canvas_RestoreToCount(JNIEnv* env, jobject, jlong native_instance, jint count) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->restoreToCount(count); } } jint Canvas_SaveLayer(JNIEnv* env, jobject, jlong native_instance, jlong native_paint) { auto* paint = reinterpret_cast(native_paint); if (auto* canvas = reinterpret_cast(native_instance)) { return canvas->saveLayer(nullptr, paint); } return 0; } jlong Canvas_LocalToDevice(JNIEnv* env, jobject, jlong native_instance) { if (auto* canvas = reinterpret_cast(native_instance)) { SkM44* m = new SkM44(canvas->getLocalToDevice()); return reinterpret_cast(m); } return 0; } void Canvas_Concat(JNIEnv* env, jobject, jlong native_instance, jlong native_matrix) { auto* canvas = reinterpret_cast(native_instance); auto* matrix = reinterpret_cast(native_matrix); if (canvas && matrix) { canvas->concat(*matrix); } } void Canvas_Concat16f(JNIEnv* env, jobject, jlong native_instance, jfloatArray jmatrix) { SkASSERT(env->GetArrayLength(jmatrix) == 16); if (auto* canvas = reinterpret_cast(native_instance)) { auto* m = env->GetFloatArrayElements(jmatrix, nullptr); canvas->concat(SkM44::RowMajor(m)); env->ReleaseFloatArrayElements(jmatrix, m, 0); } } void Canvas_Translate(JNIEnv* env, jobject, jlong native_instance, jfloat tx, jfloat ty, jfloat tz) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->concat(SkM44::Translate(tx, ty, tz)); } } void Canvas_Scale(JNIEnv* env, jobject, jlong native_instance, jfloat sx, jfloat sy, jfloat sz) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->concat(SkM44::Scale(sx, sy, sz)); } } void Canvas_ClipPath(JNIEnv* env, jobject, jlong native_instance, jlong native_path, jint native_clipOp, jboolean doAA) { if (auto* canvas = reinterpret_cast(native_instance)) { if (auto* path = reinterpret_cast(native_path)) { canvas->clipPath(*path, static_cast(native_clipOp), doAA); } } } void Canvas_ClipRect(JNIEnv* env, jobject, jlong native_instance, jfloat l, jfloat t, jfloat r, jfloat b, jint native_clipOp, jboolean doAA) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->clipRect(SkRect::MakeLTRB(l, t, r, b), static_cast(native_clipOp), doAA); } } void 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) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->clipRRect(SkRRect::MakeRectXY(SkRect::MakeLTRB(l, t, r, b), xRad, yRad), static_cast(native_clipOp), doAA); } } void Canvas_ClipShader(JNIEnv* env, jobject, jlong native_instance, jlong native_shader, jint native_clipOp) { if (auto* canvas = reinterpret_cast(native_instance)) { if (auto* shader = reinterpret_cast(native_shader)) { canvas->clipShader(sk_ref_sp(shader), static_cast(native_clipOp)); } } } void Canvas_DrawColor(JNIEnv* env, jobject, jlong native_instance, float r, float g, float b, float a) { if (auto* canvas = reinterpret_cast(native_instance)) { canvas->drawColor(SkColor4f{r, g, b, a}); } } void Canvas_DrawRect(JNIEnv* env, jobject, jlong native_instance, jfloat left, jfloat top, jfloat right, jfloat bottom, jlong native_paint) { auto* canvas = reinterpret_cast(native_instance); auto* paint = reinterpret_cast(native_paint); if (canvas && paint) { canvas->drawRect(SkRect::MakeLTRB(left, top, right, bottom), *paint); } } void Canvas_DrawImage(JNIEnv* env, jobject, jlong native_instance, jlong native_image, jfloat x, jfloat y, jint sampling_desc, jfloat sampling_b, jfloat sampling_c) { auto* canvas = reinterpret_cast(native_instance); auto* image = reinterpret_cast(native_image); if (canvas && image) { canvas->drawImage(image, x, y, jetski::utils::SamplingOptions(sampling_desc, sampling_b, sampling_c)); } } void Canvas_DrawPath(JNIEnv* env, jobject, jlong native_instance, jlong native_path, jlong native_paint) { auto* canvas = reinterpret_cast(native_instance); auto* path = reinterpret_cast(native_path); auto* paint = reinterpret_cast(native_paint); if (canvas && paint && path) { canvas->drawPath(*path, *paint); } } // jPos: a composite array in the form of [x1, y1, x2, y2, ... ,xn, yn] // callers of this function check should throw IllegalArgumentException in Java void Canvas_DrawGlyphs(JNIEnv* env, jobject, jlong native_instance, jcharArray jglyphs, jfloatArray jPos, jfloat xOrigin, jfloat yOrigin, jlong native_font, jlong native_paint) { auto* canvas = reinterpret_cast(native_instance); auto* font = reinterpret_cast(native_font); auto* paint = reinterpret_cast(native_paint); if (canvas && font && paint) { int count = env->GetArrayLength(jglyphs); auto* compositePositions = env->GetFloatArrayElements(jPos, nullptr); auto* positions = reinterpret_cast(compositePositions); auto* glyphs = env->GetCharArrayElements(jglyphs, nullptr); canvas->drawGlyphs(count, glyphs, positions, {xOrigin, yOrigin}, *font, *paint); env->ReleaseCharArrayElements(jglyphs, glyphs, 0); env->ReleaseFloatArrayElements(jPos, compositePositions, 0); } } } // namespace int register_jetski_Canvas(JNIEnv* env) { static const JNINativeMethod methods[] = { {"nGetWidth" , "(J)I" , reinterpret_cast(Canvas_GetWidth) }, {"nGetHeight" , "(J)I" , reinterpret_cast(Canvas_GetHeight) }, {"nSave" , "(J)I" , reinterpret_cast(Canvas_Save) }, {"nSaveLayer" , "(JJ)I" , reinterpret_cast(Canvas_SaveLayer) }, {"nRestore" , "(J)V" , reinterpret_cast(Canvas_Restore) }, {"nRestoreToCount" , "(JI)V" , reinterpret_cast(Canvas_RestoreToCount)}, {"nGetLocalToDevice", "(J)J" , reinterpret_cast(Canvas_LocalToDevice) }, {"nConcat" , "(JJ)V" , reinterpret_cast(Canvas_Concat) }, {"nConcat16f" , "(J[F)V" , reinterpret_cast(Canvas_Concat16f) }, {"nTranslate" , "(JFFF)V" , reinterpret_cast(Canvas_Translate) }, {"nScale" , "(JFFF)V" , reinterpret_cast(Canvas_Scale) }, {"nClipPath" , "(JJIZ)V" , reinterpret_cast(Canvas_ClipPath) }, {"nClipRect" , "(JFFFFIZ)V" , reinterpret_cast(Canvas_ClipRect) }, {"nClipRRect" , "(JFFFFFFIZ)V" , reinterpret_cast(Canvas_ClipRRect) }, {"nClipShader" , "(JJI)V" , reinterpret_cast(Canvas_ClipShader) }, {"nDrawColor" , "(JFFFF)V" , reinterpret_cast(Canvas_DrawColor) }, {"nDrawRect" , "(JFFFFJ)V" , reinterpret_cast(Canvas_DrawRect) }, {"nDrawImage" , "(JJFFIFF)V" , reinterpret_cast(Canvas_DrawImage) }, {"nDrawPath" , "(JJJ)V" , reinterpret_cast(Canvas_DrawPath) }, {"nDrawGlyphs" , "(J[C[FFFJJ)V", reinterpret_cast(Canvas_DrawGlyphs) }, }; const auto clazz = env->FindClass("org/skia/jetski/Canvas"); return clazz ? env->RegisterNatives(clazz, methods, std::size(methods)) : JNI_ERR; }