summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2010-07-20 13:09:13 -0700
committerRomain Guy <romainguy@google.com>2010-07-20 16:37:27 -0700
commita1db574036c9bc2d397b69f8200594027e1fff16 (patch)
treeece6071cd30838075c334e6b2eda391af45c0f12
parentc0ac193b9415680f0a69e20a3f5f22d16f8053be (diff)
downloadframeworks_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.java37
-rw-r--r--core/jni/android/graphics/Typeface.cpp8
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp28
-rw-r--r--core/jni/android_view_HardwareRenderer.cpp6
-rw-r--r--graphics/java/android/graphics/Paint.java5
-rw-r--r--graphics/java/android/graphics/TemporaryBuffer.java16
-rw-r--r--libs/hwui/OpenGLRenderer.cpp56
-rw-r--r--libs/hwui/OpenGLRenderer.h9
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;