diff options
author | Romain Guy <romainguy@google.com> | 2010-07-20 13:09:13 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-07-20 16:37:27 -0700 |
commit | a1db574036c9bc2d397b69f8200594027e1fff16 (patch) | |
tree | ece6071cd30838075c334e6b2eda391af45c0f12 | |
parent | c0ac193b9415680f0a69e20a3f5f22d16f8053be (diff) | |
download | frameworks_base-a1db574036c9bc2d397b69f8200594027e1fff16.zip frameworks_base-a1db574036c9bc2d397b69f8200594027e1fff16.tar.gz frameworks_base-a1db574036c9bc2d397b69f8200594027e1fff16.tar.bz2 |
Add preliminary support for text rendering.
Change-Id: I547eb631dbda24d13960d54b4144fb8908fd8a49
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 37 | ||||
-rw-r--r-- | core/jni/android/graphics/Typeface.cpp | 8 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 28 | ||||
-rw-r--r-- | core/jni/android_view_HardwareRenderer.cpp | 6 | ||||
-rw-r--r-- | graphics/java/android/graphics/Paint.java | 5 | ||||
-rw-r--r-- | graphics/java/android/graphics/TemporaryBuffer.java | 16 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 56 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 9 |
8 files changed, 120 insertions, 45 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b811b7b..1424638 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -32,6 +32,11 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.SweepGradient; +import android.graphics.TemporaryBuffer; +import android.text.GraphicsOperations; +import android.text.SpannableString; +import android.text.SpannedString; +import android.text.TextUtils; import javax.microedition.khronos.opengles.GL; @@ -574,22 +579,46 @@ class GLES20Canvas extends Canvas { @Override public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { - // TODO: Implement + if ((index | count | (index + count) | (text.length - index - count)) < 0) { + throw new IndexOutOfBoundsException(); + } + nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); } + + private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y, + int bidiFlags, int paint); @Override public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { - // TODO: Implement + if (text instanceof String || text instanceof SpannedString || + text instanceof SpannableString) { + nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, + paint.mNativePaint); + } else if (text instanceof GraphicsOperations) { + ((GraphicsOperations) text).drawText(this, start, end, x, y, + paint); + } else { + char[] buf = TemporaryBuffer.obtain(end - start); + TextUtils.getChars(text, start, end, buf, 0); + nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint); + TemporaryBuffer.recycle(buf); + } } @Override public void drawText(String text, int start, int end, float x, float y, Paint paint) { - // TODO: Implement + if ((start | end | (end - start) | (text.length() - end)) < 0) { + throw new IndexOutOfBoundsException(); + } + nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); } + private native void nDrawText(int renderer, String text, int start, int end, float x, float y, + int bidiFlags, int paint); + @Override public void drawText(String text, float x, float y, Paint paint) { - drawText(text, 0, text.length(), x, y, paint); + nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint); } @Override diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp index 7c7bfeb..1fe72e6 100644 --- a/core/jni/android/graphics/Typeface.cpp +++ b/core/jni/android/graphics/Typeface.cpp @@ -130,7 +130,13 @@ static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject, return NULL; } - return SkTypeface::CreateFromStream(new AssetStream(asset, true)); + SkStream* stream = new AssetStream(asset, true); + SkTypeface* face = SkTypeface::CreateFromStream(stream); + // SkTypeFace::CreateFromStream calls ref() on the stream, so we + // need to unref it here or it won't be freed later on + stream->unref(); + + return face; } static SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) { diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index d177e1a..fa4d23c 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "OpenGLRenderer" + #include "jni.h" #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> @@ -24,6 +26,7 @@ #include <SkMatrix.h> #include <SkPaint.h> #include <SkRegion.h> +#include <SkScalerContext.h> #include <SkXfermode.h> #include <OpenGLRenderer.h> @@ -207,7 +210,6 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject canvas, renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint); - // TODO: make sure that 0 is correct for the flags env->ReleaseByteArrayElements(chunks, storage, 0); } @@ -246,6 +248,26 @@ static void android_view_GLES20Canvas_setupLinearShader(JNIEnv* env, jobject can } // ---------------------------------------------------------------------------- +// Text +// ---------------------------------------------------------------------------- + +static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jcharArray text, int index, int count, + jfloat x, jfloat y, int flags, SkPaint* paint) { + jchar* textArray = env->GetCharArrayElements(text, NULL); + // TODO: draw from textArray + index + env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); +} + +static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jstring text, int start, int end, + jfloat x, jfloat y, int flags, SkPaint* paint) { + const jchar* textArray = env->GetStringChars(text, NULL); + // TODO: draw from textArray + start + env->ReleaseStringChars(text, textArray); +} + +// ---------------------------------------------------------------------------- // JNI Glue // ---------------------------------------------------------------------------- @@ -288,6 +310,10 @@ static JNINativeMethod gMethods[] = { { "nSetupBitmapShader", "(IIIIII)V", (void*) android_view_GLES20Canvas_setupBitmapShader }, { "nSetupLinearShader", "(IIIIIIII)V", (void*) android_view_GLES20Canvas_setupLinearShader }, + { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray }, + { "nDrawText", "(ILjava/lang/String;IIFFII)V", + (void*) android_view_GLES20Canvas_drawText }, + { "nGetClipBounds", "(ILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds }, }; diff --git a/core/jni/android_view_HardwareRenderer.cpp b/core/jni/android_view_HardwareRenderer.cpp index abd788b..6d20c9d 100644 --- a/core/jni/android_view_HardwareRenderer.cpp +++ b/core/jni/android_view_HardwareRenderer.cpp @@ -34,13 +34,11 @@ static void android_view_HardwareRenderer_abandonGlCaches(JNIEnv* env, jobject) const char* const kClassPathName = "android/view/HardwareRenderer"; static JNINativeMethod gMethods[] = { - { "nativeAbandonGlCaches", "()V", - (void*)android_view_HardwareRenderer_abandonGlCaches }, + { "nativeAbandonGlCaches", "()V", (void*)android_view_HardwareRenderer_abandonGlCaches }, }; int register_android_view_HardwareRenderer(JNIEnv* env) { - return AndroidRuntime::registerNativeMethods(env, - kClassPathName, gMethods, NELEM(gMethods)); + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } }; diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 9b4d3a8..3d63aa6 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -43,7 +43,10 @@ public class Paint { private boolean mHasCompatScaling; private float mCompatScaling; private float mInvCompatScaling; - /* package */ int mBidiFlags = BIDI_DEFAULT_LTR; + /** + * @hide + */ + public int mBidiFlags = BIDI_DEFAULT_LTR; private static final Style[] sStyleArray = { Style.FILL, Style.STROKE, Style.FILL_AND_STROKE diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java index 1d7fe01..c5b8143 100644 --- a/graphics/java/android/graphics/TemporaryBuffer.java +++ b/graphics/java/android/graphics/TemporaryBuffer.java @@ -18,9 +18,11 @@ package android.graphics; import com.android.internal.util.ArrayUtils; -/* package */ class TemporaryBuffer -{ - /* package */ static char[] obtain(int len) { +/** + * @hide + */ +public class TemporaryBuffer { + public static char[] obtain(int len) { char[] buf; synchronized (TemporaryBuffer.class) { @@ -28,15 +30,15 @@ import com.android.internal.util.ArrayUtils; sTemp = null; } - if (buf == null || buf.length < len) + if (buf == null || buf.length < len) { buf = new char[ArrayUtils.idealCharArraySize(len)]; + } return buf; } - /* package */ static void recycle(char[] temp) { - if (temp.length > 1000) - return; + public static void recycle(char[] temp) { + if (temp.length > 1000) return; synchronized (TemporaryBuffer.class) { sTemp = temp; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index e39385a..1fa76d2 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -138,8 +138,8 @@ OpenGLRenderer::OpenGLRenderer(): mCurrentProgram = mDrawTextureProgram; mShader = kShaderNone; - mShaderTileX = SkShader::kClamp_TileMode; - mShaderTileY = SkShader::kClamp_TileMode; + mShaderTileX = GL_CLAMP_TO_EDGE; + mShaderTileY = GL_CLAMP_TO_EDGE; mShaderMatrix = NULL; mShaderBitmap = NULL; @@ -535,8 +535,8 @@ void OpenGLRenderer::resetShader() { mShader = OpenGLRenderer::kShaderNone; mShaderKey = NULL; mShaderBlend = false; - mShaderTileX = SkShader::kClamp_TileMode; - mShaderTileY = SkShader::kClamp_TileMode; + mShaderTileX = GL_CLAMP_TO_EDGE; + mShaderTileY = GL_CLAMP_TO_EDGE; } void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tileX, @@ -544,8 +544,8 @@ void OpenGLRenderer::setupBitmapShader(SkBitmap* bitmap, SkShader::TileMode tile mShader = OpenGLRenderer::kShaderBitmap; mShaderBlend = hasAlpha; mShaderBitmap = bitmap; - mShaderTileX = tileX; - mShaderTileY = tileY; + mShaderTileX = gTileModes[tileX]; + mShaderTileY = gTileModes[tileY]; mShaderMatrix = matrix; } @@ -556,8 +556,8 @@ void OpenGLRenderer::setupLinearGradientShader(SkShader* shader, float* bounds, mShader = OpenGLRenderer::kShaderLinearGradient; mShaderKey = shader; mShaderBlend = hasAlpha; - mShaderTileX = tileMode; - mShaderTileY = tileMode; + mShaderTileX = gTileModes[tileMode]; + mShaderTileY = gTileModes[tileMode]; mShaderMatrix = matrix; mShaderBounds = bounds; mShaderColors = colors; @@ -623,8 +623,18 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right float alpha, SkXfermode::Mode mode) { Texture* texture = mGradientCache.get(mShaderKey); if (!texture) { + SkShader::TileMode tileMode = SkShader::kClamp_TileMode; + switch (mShaderTileX) { + case GL_REPEAT: + tileMode = SkShader::kRepeat_TileMode; + break; + case GL_MIRRORED_REPEAT: + tileMode = SkShader::kMirror_TileMode; + break; + } + texture = mGradientCache.addLinearGradient(mShaderKey, mShaderBounds, mShaderColors, - mShaderPositions, mShaderCount, mShaderTileX); + mShaderPositions, mShaderCount, tileMode); } mModelView.loadTranslate(left, top, 0.0f); @@ -634,14 +644,7 @@ void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right mDrawLinearGradientProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); chooseBlending(mShaderBlend || alpha < 1.0f, mode); - - if (texture->id != mLastTexture) { - glBindTexture(GL_TEXTURE_2D, texture->id); - mLastTexture = texture->id; - } - // TODO: Don't set the texture parameters every time - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gTileModes[mShaderTileX]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileModes[mShaderTileX]); + bindTexture(texture->id, mShaderTileX, mShaderTileY); Rect start(mShaderBounds[0], mShaderBounds[1], mShaderBounds[2], mShaderBounds[3]); if (mShaderMatrix) { @@ -736,14 +739,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b mDrawTextureProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); chooseBlending(blend || alpha < 1.0f, mode); - - if (texture != mLastTexture) { - glBindTexture(GL_TEXTURE_2D, texture); - mLastTexture = texture; - } - // TODO: Don't set the texture parameters every time - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gTileModes[mShaderTileX]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gTileModes[mShaderTileY]); + bindTexture(texture, mShaderTileX, mShaderTileY); // Always premultiplied //glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha); @@ -826,5 +822,15 @@ void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermod } } +void OpenGLRenderer::bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT) { + if (texture != mLastTexture) { + glBindTexture(GL_TEXTURE_2D, texture); + mLastTexture = texture; + } + // TODO: Don't set the texture parameters every time + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index dd7999d..9dc2a43 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -287,6 +287,11 @@ private: inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode); /** + * Binds the specified texture with the specified wrap modes. + */ + inline void bindTexture(GLuint texture, GLenum wrapS, GLenum wrapT); + + /** * Enable or disable blending as necessary. This function sets the appropriate * blend function based on the specified xfermode. */ @@ -341,8 +346,8 @@ private: ShaderType mShader; SkShader* mShaderKey; bool mShaderBlend; - SkShader::TileMode mShaderTileX; - SkShader::TileMode mShaderTileY; + GLenum mShaderTileX; + GLenum mShaderTileY; SkMatrix* mShaderMatrix; // Bitmaps SkBitmap* mShaderBitmap; |