Shader.java revision 8a6ad4a89d1b9ed61d3ec6f5bc12d479bc8d9f3b
168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi/*
268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Copyright (C) 2006 The Android Open Source Project
368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi *
468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * you may not use this file except in compliance with the License.
668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * You may obtain a copy of the License at
768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi *
868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi *
1068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * See the License for the specific language governing permissions and
1468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * limitations under the License.
1568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */
1668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
17de015407a89018f9422254624e1b75703f38defdGlenn Kastenpackage android.graphics;
1868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
1968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Triviimport android.annotation.NonNull;
204ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Triviimport android.annotation.Nullable;
214ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi
2268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi/**
2368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * Shader is the based class for objects that return horizontal spans of colors
2468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * during drawing. A subclass of Shader is installed in a Paint calling
254ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi * paint.setShader(shader). After that any object (other than a bitmap) that is
2668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi * drawn with that paint will get its color(s) from the shader.
2768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */
2868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivipublic class Shader {
294ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    /**
304ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     * @deprecated Use subclass constructors directly instead.
314ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     */
324ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    @Deprecated
334ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    public Shader() {}
344ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi
354ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    /**
3668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     * Current native shader instance. Created and updated lazily when {@link #getNativeInstance()}
3737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi     * is called - otherwise may be out of date with java setters/properties.
3837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi     */
3949935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    private long mNativeInstance;
4068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
41b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten    /**
4268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     * Current matrix - always set to null if local matrix is identity.
4368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     */
4468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    private Matrix mLocalMatrix;
45b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten
46b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten    public enum TileMode {
4768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        /**
48b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         * replicate the edge color if the shader draws outside of its
49b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         * original bounds
50b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         */
51b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        CLAMP   (0),
52b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        /**
53b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         * repeat the shader's image horizontally and vertically
54b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         */
55b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        REPEAT  (1),
56b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        /**
57b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         * repeat the shader's image horizontally and vertically, alternating
58b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         * mirror images so that adjacent images always seam
59b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten         */
60b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        MIRROR  (2);
61b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten
62b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        TileMode(int nativeInt) {
63b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten            this.nativeInt = nativeInt;
64b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        }
65b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten        final int nativeInt;
6668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    }
6768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
6868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    /**
6968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     * Return true if the shader has a non-identity local matrix.
702f6d462d89356cdaa77299ca27b60c5cca198d98Gloria Wang     * @param localM Set to the local matrix of the shader, if the shader's matrix is non-null.
71b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten     * @return true if the shader has a non-identity local matrix
72b2549c73290f1955f3a7731bf98446a45f295dfaGlenn Kasten     */
7368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    public boolean getLocalMatrix(@NonNull Matrix localM) {
7437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        if (mLocalMatrix != null) {
7537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi            localM.set(mLocalMatrix);
7649935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten            return true; // presence of mLocalMatrix means it's not identity
7768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        }
7837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        return false;
7937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    }
8037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi
814ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    /**
824ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     * Set the shader's local matrix. Passing null will reset the shader's
834ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     * matrix to identity.
844ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     *
854ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     * @param localM The shader's new local matrix, or null to specify identity
864ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi     */
874ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi    public void setLocalMatrix(@Nullable Matrix localM) {
884ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi        if (localM == null || localM.isIdentity()) {
894ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi            if (mLocalMatrix != null) {
904ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                mLocalMatrix = null;
914ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                discardNativeInstance();
924ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi            }
934ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi        } else {
944ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi            if (mLocalMatrix == null) {
954ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                mLocalMatrix = new Matrix(localM);
964ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                discardNativeInstance();
974ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi            } else if (!mLocalMatrix.equals(localM)) {
984ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                mLocalMatrix.set(localM);
994ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi                discardNativeInstance();
1004ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi            }
10137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        }
10237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    }
10381e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten
10449935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    long createNativeInstance(long nativeMatrix) {
10549935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten        return 0;
10649935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    }
10749935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten
10881e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten    private void discardNativeInstance() {
10981e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten        if (mNativeInstance != 0) {
11081e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten            nativeSafeUnref(mNativeInstance);
11181e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten            mNativeInstance = 0;
11281e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten        }
11337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    }
11468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
11581e917a2605e14901b8f5e6cac7eafb5667aad0dGlenn Kasten    @Override
11668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    protected void finalize() throws Throwable {
11768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        try {
11868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi            if (mNativeInstance != 0) {
11949935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten                nativeSafeUnref(mNativeInstance);
12049935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten            }
12149935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten            mNativeInstance = -1;
12249935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten        } finally {
12349935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten            super.finalize();
12449935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten        }
12549935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    }
12649935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten
12749935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    /**
12868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     * @hide
12949935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten     */
13049935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    protected Shader copy() {
13168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        final Shader copy = new Shader();
13268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        copyLocalMatrix(copy);
13349935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten        return copy;
13449935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten    }
13549935c51fddcd0caa0030e2aac0c3a7ba3339e3dGlenn Kasten
13668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    /**
13768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     * @hide
13868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     */
13968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    protected void copyLocalMatrix(Shader dest) {
14068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        dest.mLocalMatrix.set(mLocalMatrix);
14168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    }
1427ef5526a7bd12eccfa777cc8bc167794634f405aJean-Michel Trivi
14368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    /**
144ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten     * @hide
14568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi     */
1465933f3d5e532aaac31ce0e6551c59f0197c0ae3cGlenn Kasten    public long getNativeInstance() {
14768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        if (mNativeInstance == -1) {
148e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi            throw new IllegalStateException("attempting to use a finalized Shader");
14968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        }
15068d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
15168d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        if (mNativeInstance == 0) {
15268d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi            mNativeInstance = createNativeInstance(mLocalMatrix == null
15368d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi                    ? 0 : mLocalMatrix.native_instance);
15468d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        }
15568d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi        return mNativeInstance;
15637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi    }
15768d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi
15868d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi    private static native void nativeSafeUnref(long nativeInstance);
15968d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi}
160e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi