19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h>
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkShader.h"
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkGradientShader.h"
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkPorterDuff.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkComposeShader.h"
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkTemplates.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkXfermode.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy#include <SkiaShader.h>
12a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy#include <Caches.h>
1306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
1406f96e2652e4855b6520ad9dd70583677605b79aRomain Guyusing namespace android::uirenderer;
1506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
167fac2e18339f765320d759e8d4c090f92431959eRomain Guystatic struct {
177fac2e18339f765320d759e8d4c090f92431959eRomain Guy    jclass clazz;
1806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    jfieldID shader;
1906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy} gShaderClassInfo;
207fac2e18339f765320d759e8d4c090f92431959eRomain Guy
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == ptr) {
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        doThrowIAE(env);
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void Color_RGBToHSV(JNIEnv* env, jobject, int red, int green, int blue, jfloatArray hsvArray)
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar hsv[3];
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkRGBToHSV(red, green, blue, hsv);
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float* values = autoHSV.ptr();
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < 3; i++) {
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        values[i] = SkScalarToFloat(hsv[i]);
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
384cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArray)
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float*      values = autoHSV.ptr();;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar    hsv[3];
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i = 0; i < 3; i++) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        hsv[i] = SkFloatToScalar(values[i]);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
484cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return SkHSVToColor(alpha, hsv);
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////////////
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5406f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic void Shader_destructor(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader)
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
566062c5912dc79704b489fc8c289b78a400ed05eeDerek Sollenberger    SkSafeUnref(shader);
575c13d89c1332fcc499379b9064b891187b75ca32Chet Haase    // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
58a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy#ifdef USE_OPENGL_RENDERER
59a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy    if (android::uirenderer::Caches::hasInstance()) {
605c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
61ad93c2bb63dfc813b2eefa1043aa63afbddce655Chet Haase    } else {
62ad93c2bb63dfc813b2eefa1043aa63afbddce655Chet Haase        delete skiaShader;
63a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy    }
64a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy#endif
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6706f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader,
6806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const SkMatrix* matrix)
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
70a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed    if (shader) {
71a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed        if (NULL == matrix) {
72a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed            shader->resetLocalMatrix();
73a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed        }
74a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed        else {
75a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed            shader->setLocalMatrix(*matrix);
76a04e555dc91b11ad833cb5db4a24e38082d1dc45Mike Reed        }
77163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
7806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        skiaShader->setMatrix(const_cast<SkMatrix*>(matrix));
79163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////////////
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8506f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkShader* BitmapShader_constructor(JNIEnv* env, jobject o, const SkBitmap* bitmap,
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                          int tileModeX, int tileModeY)
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* s = SkShader::CreateBitmapShader(*bitmap,
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        (SkShader::TileMode)tileModeX,
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        (SkShader::TileMode)tileModeY);
9106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, s);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return s;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9606f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkiaShader* BitmapShader_postConstructor(JNIEnv* env, jobject o, SkShader* shader,
9706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkBitmap* bitmap, int tileModeX, int tileModeY) {
98163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
9906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
10006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
10106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
10206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return skiaShader;
103163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#else
104163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    return NULL;
105163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
1067fac2e18339f765320d759e8d4c090f92431959eRomain Guy}
1074cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
10806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy///////////////////////////////////////////////////////////////////////////////////////////////
1097fac2e18339f765320d759e8d4c090f92431959eRomain Guy
1107fac2e18339f765320d759e8d4c090f92431959eRomain Guystatic SkShader* LinearGradient_create1(JNIEnv* env, jobject o,
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        float x0, float y0, float x1, float y1,
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        jintArray colorArray, jfloatArray posArray, int tileMode)
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkPoint pts[2];
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    size_t count = env->GetArrayLength(colorArray);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
1227b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy    SkScalar* pos = NULL;
1237fac2e18339f765320d759e8d4c090f92431959eRomain Guy
12406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (posArray) {
12506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        AutoJavaFloatArray autoPos(env, posArray, count);
12606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        const float* posValues = autoPos.ptr();
12706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        pos = (SkScalar*)storage.get();
12806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        for (size_t i = 0; i < count; i++) {
12906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            pos[i] = SkFloatToScalar(posValues[i]);
13006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        }
13106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
1324cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
13306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkShader* shader = SkGradientShader::CreateLinear(pts,
13406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy                                reinterpret_cast<const SkColor*>(colorValues),
13506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy                                pos, count,
13606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy                                static_cast<SkShader::TileMode>(tileMode));
13706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
13806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
13906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    ThrowIAE_IfNull(env, shader);
14006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return shader;
14106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
14206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
14306f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
14406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        float x0, float y0, float x1, float y1, jintArray colorArray,
14506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        jfloatArray posArray, int tileMode) {
146163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
14706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    size_t count = env->GetArrayLength(colorArray);
14806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
14906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
1507fac2e18339f765320d759e8d4c090f92431959eRomain Guy    jfloat* storedBounds = new jfloat[4];
1517fac2e18339f765320d759e8d4c090f92431959eRomain Guy    storedBounds[0] = x0; storedBounds[1] = y0;
1527fac2e18339f765320d759e8d4c090f92431959eRomain Guy    storedBounds[2] = x1; storedBounds[3] = y1;
15342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
15442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    bool missFirst = false;
15542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    bool missLast = false;
15642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    size_t stopCount = count;
1577fac2e18339f765320d759e8d4c090f92431959eRomain Guy
15842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    jfloat* storedPositions = NULL;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (posArray) {
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoJavaFloatArray autoPos(env, posArray, count);
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const float* posValues = autoPos.ptr();
16242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
16342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        missFirst = posValues[0] != 0.0f;
16442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        missLast = posValues[count - 1] != 1.0f;
16542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
16642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        stopCount += missFirst + missLast;
16742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        storedPositions = new jfloat[stopCount];
16842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
16942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        if (missFirst) {
17042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            storedPositions[0] = 0.0f;
17142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        }
17242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
17342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        for (size_t i = missFirst; i < count + missFirst; i++) {
17442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            storedPositions[i] = posValues[i - missFirst];
17542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        }
17642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
17742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        if (missLast) {
17842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            storedPositions[stopCount - 1] = 1.0f;
1797fac2e18339f765320d759e8d4c090f92431959eRomain Guy        }
1807fac2e18339f765320d759e8d4c090f92431959eRomain Guy    } else {
18142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        storedPositions = new jfloat[count];
1827fac2e18339f765320d759e8d4c090f92431959eRomain Guy        storedPositions[0] = 0.0f;
1837b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        const jfloat step = 1.0f / (count - 1);
1847b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        for (size_t i = 1; i < count - 1; i++) {
1857b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy            storedPositions[i] = step * i;
1867b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        }
1877b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        storedPositions[count - 1] = 1.0f;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
19042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    uint32_t* storedColors = new uint32_t[stopCount];
19142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
19242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    if (missFirst) {
19342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        storedColors[0] = static_cast<uint32_t>(colorValues[0]);
19442e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
19542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
19642e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    for (size_t i = missFirst; i < count + missFirst; i++) {
19742e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
19842e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
19942e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
20042e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    if (missLast) {
20142e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy        storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
20242e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy    }
20342e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy
20406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
20542e1e0d482d774cf18a55773e434f02edb9e4462Romain Guy            storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
20606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
20706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
20806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
20906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return skiaShader;
210163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#else
211163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    return NULL;
212163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
21306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
21406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
21506f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkiaShader* LinearGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
21606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        float x0, float y0, float x1, float y1, int color0, int color1, int tileMode) {
217163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
21806f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    float* storedBounds = new float[4];
21906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    storedBounds[0] = x0; storedBounds[1] = y0;
22006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    storedBounds[2] = x1; storedBounds[3] = y1;
22106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    float* storedPositions = new float[2];
22306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    storedPositions[0] = 0.0f;
22406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    storedPositions[1] = 1.0f;
22506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
22606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    uint32_t* storedColors = new uint32_t[2];
22761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    storedColors[0] = static_cast<uint32_t>(color0);
22861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy    storedColors[1] = static_cast<uint32_t>(color1);
22906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
23006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
23106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
23206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
23306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
23406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return skiaShader;
235163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#else
236163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    return NULL;
237163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2407fac2e18339f765320d759e8d4c090f92431959eRomain Guystatic SkShader* LinearGradient_create2(JNIEnv* env, jobject o,
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        float x0, float y0, float x1, float y1,
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        int color0, int color1, int tileMode)
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkPoint pts[2];
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pts[0].set(SkFloatToScalar(x0), SkFloatToScalar(y0));
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    pts[1].set(SkFloatToScalar(x1), SkFloatToScalar(y1));
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkColor colors[2];
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[0] = color0;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[1] = color1;
2514cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, (SkShader::TileMode)tileMode);
25306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, s);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return s;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////////////
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
260ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guystatic SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius,
261ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        jintArray colorArray, jfloatArray posArray, int tileMode) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkPoint center;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    center.set(SkFloatToScalar(x), SkFloatToScalar(y));
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t      count = env->GetArrayLength(colorArray);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar*                   pos = NULL;
2704cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (posArray) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoJavaFloatArray autoPos(env, posArray, count);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const float* posValues = autoPos.ptr();
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pos = (SkScalar*)storage.get();
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i = 0; i < count; i++)
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos[i] = SkFloatToScalar(posValues[i]);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* shader = SkGradientShader::CreateRadial(center,
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                SkFloatToScalar(radius),
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                reinterpret_cast<const SkColor*>(colorValues),
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                pos, count,
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                static_cast<SkShader::TileMode>(tileMode));
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 JNI_ABORT);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, shader);
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return shader;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
291ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guystatic SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius,
292ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        int color0, int color1, int tileMode) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkPoint center;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    center.set(SkFloatToScalar(x), SkFloatToScalar(y));
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkColor colors[2];
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[0] = color0;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[1] = color1;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL,
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                          2, (SkShader::TileMode)tileMode);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, s);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return s;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
306ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guystatic SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
307ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) {
308ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#ifdef USE_OPENGL_RENDERER
309ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    size_t count = env->GetArrayLength(colorArray);
310ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
311ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
312ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    jfloat* storedPositions = new jfloat[count];
313ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    uint32_t* storedColors = new uint32_t[count];
314ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    for (size_t i = 0; i < count; i++) {
315ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        storedColors[i] = static_cast<uint32_t>(colorValues[i]);
316ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    }
317ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
318ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    if (posArray) {
319ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        AutoJavaFloatArray autoPos(env, posArray, count);
320ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        const float* posValues = autoPos.ptr();
321ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        for (size_t i = 0; i < count; i++) {
322ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy            storedPositions[i] = posValues[i];
323ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        }
324ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    } else {
325ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        storedPositions[0] = 0.0f;
3267b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        const jfloat step = 1.0f / (count - 1);
3277b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        for (size_t i = 1; i < count - 1; i++) {
3287b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy            storedPositions[i] = step * i;
3297b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        }
3307b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        storedPositions[count - 1] = 1.0f;
331ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    }
332ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
333ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
334ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy            storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
335ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
336ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
337ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
338ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    return skiaShader;
339ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#else
340ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    return NULL;
341ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#endif
342ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
343ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
344ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guystatic SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
345ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        float x, float y, float radius, int color0, int color1, int tileMode) {
346ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#ifdef USE_OPENGL_RENDERER
347ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    float* storedPositions = new float[2];
348ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    storedPositions[0] = 0.0f;
349ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    storedPositions[1] = 1.0f;
350ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
351ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    uint32_t* storedColors = new uint32_t[2];
352ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    storedColors[0] = static_cast<uint32_t>(color0);
353ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    storedColors[1] = static_cast<uint32_t>(color1);
354ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
355ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
356ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy            storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
357ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
358ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
359ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    return skiaShader;
360ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#else
361ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    return NULL;
362ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy#endif
363ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy}
364ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
368ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        jintArray jcolors, jfloatArray jpositions) {
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t      count = env->GetArrayLength(jcolors);
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const jint* colors = env->GetIntArrayElements(jcolors, NULL);
3714cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkAutoSTMalloc<8, SkScalar> storage(jpositions ? count : 0);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar*                   pos = NULL;
3744cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL != jpositions) {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoJavaFloatArray autoPos(env, jpositions, count);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const float* posValues = autoPos.ptr();
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pos = (SkScalar*)storage.get();
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (size_t i = 0; i < count; i++) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos[i] = SkFloatToScalar(posValues[i]);
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* shader = SkGradientShader::CreateSweep(SkFloatToScalar(x),
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     SkFloatToScalar(y),
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     reinterpret_cast<const SkColor*>(colors),
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     pos, count);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 JNI_ABORT);
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, shader);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return shader;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
395ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy        int color0, int color1) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkColor colors[2];
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[0] = color0;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    colors[1] = color1;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkShader* s = SkGradientShader::CreateSweep(SkFloatToScalar(x), SkFloatToScalar(y),
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                         colors, NULL, 2);
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ThrowIAE_IfNull(env, s);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return s;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
405ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guystatic SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
406ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        float x, float y, jintArray colorArray, jfloatArray posArray) {
407ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#ifdef USE_OPENGL_RENDERER
408ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    size_t count = env->GetArrayLength(colorArray);
409ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
410ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
411ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    jfloat* storedPositions = new jfloat[count];
412ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    uint32_t* storedColors = new uint32_t[count];
413ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    for (size_t i = 0; i < count; i++) {
414ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        storedColors[i] = static_cast<uint32_t>(colorValues[i]);
415ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    }
416ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
417ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    if (posArray) {
418ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        AutoJavaFloatArray autoPos(env, posArray, count);
419ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        const float* posValues = autoPos.ptr();
420ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        for (size_t i = 0; i < count; i++) {
421ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy            storedPositions[i] = posValues[i];
422ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        }
423ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    } else {
424ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        storedPositions[0] = 0.0f;
4257b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        const jfloat step = 1.0f / (count - 1);
4267b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        for (size_t i = 1; i < count - 1; i++) {
4277b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy            storedPositions[i] = step * i;
4287b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        }
4297b5b6abf852c039983eded25ebe43a70fef5a4abRomain Guy        storedPositions[count - 1] = 1.0f;
430ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    }
431ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
432ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
433ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy            shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
434ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
435ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
436ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    return skiaShader;
437ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#else
438ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    return NULL;
439ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#endif
440ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
441ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
442ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guystatic SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
443ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy        float x, float y, int color0, int color1) {
444ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#ifdef USE_OPENGL_RENDERER
445ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    float* storedPositions = new float[2];
446ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    storedPositions[0] = 0.0f;
447ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    storedPositions[1] = 1.0f;
448ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
449ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    uint32_t* storedColors = new uint32_t[2];
450ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    storedColors[0] = static_cast<uint32_t>(color0);
451ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    storedColors[1] = static_cast<uint32_t>(color1);
452ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
453ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
454ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy            shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
455ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
456ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    return skiaShader;
457ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#else
458ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    return NULL;
459ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy#endif
460ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy}
461ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////////////
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
46406f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkShader* ComposeShader_create1(JNIEnv* env, jobject o,
46506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader* shaderA, SkShader* shaderB, SkXfermode* mode)
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return new SkComposeShader(shaderA, shaderB, mode);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
47006f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkShader* ComposeShader_create2(JNIEnv* env, jobject o,
47106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkShader* shaderA, SkShader* shaderB, SkPorterDuff::Mode porterDuffMode)
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
47306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode));
47406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkXfermode* mode = (SkXfermode*) au.get();
47506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return new SkComposeShader(shaderA, shaderB, mode);
47606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
47706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy
47806f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkiaShader* ComposeShader_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
47906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader* shaderA, SkiaShader* shaderB, SkPorterDuff::Mode porterDuffMode) {
480163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
48148daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy    SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
48248daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy    return new SkiaComposeShader(shaderA, shaderB, mode, shader);
483163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#else
484163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    return NULL;
485163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
48606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy}
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48806f96e2652e4855b6520ad9dd70583677605b79aRomain Guystatic SkiaShader* ComposeShader_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
48906f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        SkiaShader* shaderA, SkiaShader* shaderB, SkXfermode* mode) {
490163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#ifdef USE_OPENGL_RENDERER
49106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    SkXfermode::Mode skiaMode;
49206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    if (!SkXfermode::IsMode(mode, &skiaMode)) {
49348daa54d31fc59ec969dcff65eb3cbb0ce879a8dRomain Guy        // TODO: Support other modes
49406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy        skiaMode = SkXfermode::kSrcOver_Mode;
49506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    }
49606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    return new SkiaComposeShader(shaderA, shaderB, skiaMode, shader);
497163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#else
498163935113919a184122b8b3bd672ef08c8df65dcRomain Guy    return NULL;
499163935113919a184122b8b3bd672ef08c8df65dcRomain Guy#endif
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////////////
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gColorMethods[] = {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeRGBToHSV",     "(III[F)V", (void*)Color_RGBToHSV   },
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeHSVToColor",   "(I[F)I",   (void*)Color_HSVToColor }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gShaderMethods[] = {
51006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativeDestructor",        "(II)V",    (void*)Shader_destructor        },
51106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativeSetLocalMatrix",    "(III)V",   (void*)Shader_setLocalMatrix    }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gBitmapShaderMethods[] = {
51506f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativeCreate",     "(III)I",  (void*)BitmapShader_constructor },
51606f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativePostCreate", "(IIII)I", (void*)BitmapShader_postConstructor }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gLinearGradientMethods[] = {
52006f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativeCreate1",     "(FFFF[I[FI)I",  (void*)LinearGradient_create1     },
52106f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativeCreate2",     "(FFFFIII)I",    (void*)LinearGradient_create2     },
52206f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativePostCreate1", "(IFFFF[I[FI)I", (void*)LinearGradient_postCreate1 },
52306f96e2652e4855b6520ad9dd70583677605b79aRomain Guy    { "nativePostCreate2", "(IFFFFIII)I",   (void*)LinearGradient_postCreate2 }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gRadialGradientMethods[] = {
527ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate1",     "(FFF[I[FI)I",  (void*)RadialGradient_create1     },
528ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate2",     "(FFFIII)I",    (void*)RadialGradient_create2     },
529ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 },
530ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativePostCreate2", "(IFFFIII)I",   (void*)RadialGradient_postCreate2 }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gSweepGradientMethods[] = {
534ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate1",     "(FF[I[F)I",  (void*)SweepGradient_create1     },
535ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate2",     "(FFII)I",    (void*)SweepGradient_create2     },
536ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
537ee916f14cbd1fe1422c063ce2ef7b185e2bc5c6fRomain Guy    { "nativePostCreate2", "(IFFII)I",   (void*)SweepGradient_postCreate2 }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gComposeShaderMethods[] = {
541ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate1",      "(III)I",   (void*)ComposeShader_create1     },
542ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativeCreate2",      "(III)I",   (void*)ComposeShader_create2     },
543ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativePostCreate1",  "(IIII)I",  (void*)ComposeShader_postCreate1 },
544ddb80bebb0776e6d852aab6e8bba5d5591847a55Romain Guy    { "nativePostCreate2",  "(IIII)I",  (void*)ComposeShader_postCreate2 }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define REG(env, name, array)                                                                       \
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    result = android::AndroidRuntime::registerNativeMethods(env, name, array, SK_ARRAY_COUNT(array));  \
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (result < 0) return result
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Shader(JNIEnv* env)
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result;
5564cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/Color", gColorMethods);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/Shader", gShaderMethods);
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/BitmapShader", gBitmapShaderMethods);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/LinearGradient", gLinearGradientMethods);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/RadialGradient", gRadialGradientMethods);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/SweepGradient", gSweepGradientMethods);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    REG(env, "android/graphics/ComposeShader", gComposeShaderMethods);
5644cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
567