Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10d32a33 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I16dc1411 into eclair-mr2

* changes:
  add boundary patch
parents 26d4e539 c04851fd
Loading
Loading
Loading
Loading
+40 −2
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
#include "SkShader.h"
#include "SkTemplates.h"

#include "SkBoundaryPatch.h"
#include "SkMeshUtils.h"

#define TIME_DRAWx

static uint32_t get_thread_msec() {
@@ -862,8 +865,6 @@ public:
    }
};

///////////////////////////////////////////////////////////////////////////////

static JNINativeMethod gCanvasMethods[] = {
    {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
    {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster},
@@ -965,6 +966,42 @@ static JNINativeMethod gCanvasMethods[] = {
    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
};

///////////////////////////////////////////////////////////////////////////////

static void BoundaryPatch_computeCubic(JNIEnv* env, jobject, jfloatArray jpts,
                                   int texW, int texH, int rows, int cols,
                                   jfloatArray jverts, jshortArray jidx) {
    AutoJavaFloatArray ptsArray(env, jpts, 24, kRO_JNIAccess);

    int vertCount = rows * cols;
    AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4, kRW_JNIAccess);
    SkPoint* verts = (SkPoint*)vertsArray.ptr();
    SkPoint* texs = verts + vertCount;

    int idxCount = (rows - 1) * (cols - 1) * 6;
    AutoJavaShortArray idxArray(env, jidx, idxCount, kRW_JNIAccess);
    uint16_t* idx = (uint16_t*)idxArray.ptr();  // cast from int16_t*

    SkCubicBoundary cubic;
    memcpy(cubic.fPts, ptsArray.ptr(), 12 * sizeof(SkPoint));

    SkBoundaryPatch patch;
    patch.setBoundary(&cubic);
    // generate our verts
    patch.evalPatch(verts, rows, cols);

    SkMeshIndices mesh;
    // generate our texs and idx
    mesh.init(texs, idx, texW, texH, rows, cols);
}

static JNINativeMethod gBoundaryPatchMethods[] = {
    {"nativeComputeCubicPatch", "([FIIII[F[S)V",
    (void*)BoundaryPatch_computeCubic },
};

///////////////////////////////////////////////////////////////////////////////

#include <android_runtime/AndroidRuntime.h>

#define REG(env, name, array) \
@@ -976,6 +1013,7 @@ int register_android_graphics_Canvas(JNIEnv* env) {
    int result;

    REG(env, "android/graphics/Canvas", gCanvasMethods);
    REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods);
    
    return result;
}
+6 −4
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ bool GraphicsJNI::hasException(JNIEnv *env) {
///////////////////////////////////////////////////////////////////////////////

AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
                                       int minLength)
                                       int minLength, JNIAccess access)
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
    SkASSERT(env);
    if (array) {
@@ -66,11 +66,12 @@ AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
        }
        fPtr = env->GetFloatArrayElements(array, NULL);
    }
    fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
}

AutoJavaFloatArray::~AutoJavaFloatArray() {
    if (fPtr) {
        fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0);
        fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode);
    }
}

@@ -94,7 +95,7 @@ AutoJavaIntArray::~AutoJavaIntArray() {
}

AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
                                       int minLength)
                                       int minLength, JNIAccess access)
: fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
    SkASSERT(env);
    if (array) {
@@ -104,11 +105,12 @@ AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
        }
        fPtr = env->GetShortArrayElements(array, NULL);
    }
    fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
}

AutoJavaShortArray::~AutoJavaShortArray() {
    if (fPtr) {
        fEnv->ReleaseShortArrayElements(fArray, fPtr, 0);
        fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode);
    }
}

+11 −2
Original line number Diff line number Diff line
@@ -80,9 +80,15 @@ private:
    bool fReportSizeToVM;
};

enum JNIAccess {
    kRO_JNIAccess,
    kRW_JNIAccess
};

class AutoJavaFloatArray {
public:
    AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0);
    AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
                       int minLength = 0, JNIAccess = kRW_JNIAccess);
    ~AutoJavaFloatArray();
    
    float* ptr() const { return fPtr; }
@@ -93,6 +99,7 @@ private:
    jfloatArray fArray;
    float*      fPtr;
    int         fLen;
    int         fReleaseMode;
};

class AutoJavaIntArray {
@@ -112,7 +119,8 @@ private:

class AutoJavaShortArray {
public:
    AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0);
    AutoJavaShortArray(JNIEnv* env, jshortArray array,
                       int minLength = 0, JNIAccess = kRW_JNIAccess);
    ~AutoJavaShortArray();
    
    jshort* ptr() const { return fPtr; }
@@ -123,6 +131,7 @@ private:
    jshortArray fArray;
    jshort*      fPtr;
    int         fLen;
    int         fReleaseMode;
};

class AutoJavaByteArray {
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2009 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.
 */

package android.graphics.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.Xfermode;

/**
 * @hide
 */
public class BoundaryPatch {
    private Paint   mPaint;
    private Bitmap  mTexture;
    private int     mRows;
    private int     mCols;
    private float[] mCubicPoints;
    private boolean mDirty;
    // these are the computed output of the native code
    private float[] mVerts;
    private short[] mIndices;

    public BoundaryPatch() {
        mRows = mCols = 2;  // default minimum
        mCubicPoints = new float[24];
        mPaint = new Paint();
        mPaint.setDither(true);
        mPaint.setFilterBitmap(true);
        mDirty = true;
    }

    /**
     * Set the boundary to be 4 cubics. This takes a single array of floats,
     * and picks up the 12 pairs starting at offset, and treats them as
     * the x,y coordinates of the cubic control points. The points wrap around
     * a patch, as follows. For documentation purposes, pts[i] will mean the
     * x,y pair of floats, as if pts[] were an array of "points".
     *
     * Top: pts[0..3]
     * Right: pts[3..6]
     * Bottom: pts[6..9]
     * Right: pts[9..11], pts[0]
     *
     * The coordinates are copied from the input array, so subsequent changes
     * to pts[] will not be reflected in the boundary.
     *
     * @param pts The src array of x,y pairs for the boundary cubics
     * @param offset The index into pts of the first pair
     * @param rows The number of points across to approximate the boundary.
     *             Must be >= 2, though very large values may slow down drawing
     * @param cols The number of points down to approximate the boundary.
     *             Must be >= 2, though very large values may slow down drawing
     */
    public void setCubicBoundary(float[] pts, int offset, int rows, int cols) {
        if (rows < 2 || cols < 2) {
            throw new RuntimeException("rows and cols must be >= 2");
        }
        System.arraycopy(pts, offset, mCubicPoints, 0, 24);
        if (mRows != rows || mCols != cols) {
            mRows = rows;
            mCols = cols;
        }
        mDirty = true;
    }

    /**
     * Reference a bitmap texture to be mapped onto the patch.
     */
    public void setTexture(Bitmap texture) {
        if (mTexture != texture) {
            if (mTexture == null ||
                    mTexture.getWidth() != texture.getWidth() ||
                    mTexture.getHeight() != texture.getHeight()) {
                // need to recompute texture coordinates
                mDirty = true;
            }
            mTexture = texture;
            mPaint.setShader(new BitmapShader(texture,
                                              Shader.TileMode.CLAMP,
                                              Shader.TileMode.CLAMP));
        }
    }

    /**
     * Return the paint flags for the patch
     */
    public int getPaintFlags() {
        return mPaint.getFlags();
    }

    /**
     * Set the paint flags for the patch
     */
    public void setPaintFlags(int flags) {
        mPaint.setFlags(flags);
    }

    /**
     * Set the xfermode for the patch
     */
    public void setXfermode(Xfermode mode) {
        mPaint.setXfermode(mode);
    }

    /**
     * Set the alpha for the patch
     */
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    /**
     * Draw the patch onto the canvas.
     *
     * setCubicBoundary() and setTexture() must be called before drawing.
     */
    public void draw(Canvas canvas) {
        if (mDirty) {
            buildCache();
            mDirty = false;
        }

        // cut the count in half, since mVerts.length is really the length of
        // the verts[] and tex[] arrays combined
        // (tex[] are stored after verts[])
        int vertCount = mVerts.length >> 1;
        canvas.drawVertices(Canvas.VertexMode.TRIANGLES, vertCount,
                            mVerts, 0, mVerts, vertCount, null, 0,
                            mIndices, 0, mIndices.length,
                            mPaint);
    }

    private void buildCache() {
        // we need mRows * mCols points, for verts and another set for textures
        // so *2 for going from points -> floats, and *2 for verts and textures
        int vertCount = mRows * mCols * 4;
        if (mVerts == null || mVerts.length != vertCount) {
            mVerts = new float[vertCount];
        }

        int indexCount = (mRows - 1) * (mCols - 1) * 6;
        if (mIndices == null || mIndices.length != indexCount) {
            mIndices = new short[indexCount];
        }

        nativeComputeCubicPatch(mCubicPoints,
                                mTexture.getWidth(), mTexture.getHeight(),
                                mRows, mCols, mVerts, mIndices);
    }

    private static native
    void nativeComputeCubicPatch(float[] cubicPoints,
                                 int texW, int texH, int rows, int cols,
                                 float[] verts, short[] indices);
}