Fix tons of bugs and add new text rendering support.
Change-Id: I326c66b10784006f6df2f12d38e120cef94cd0d7
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 96bd884..78836fa 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -610,9 +610,13 @@
if ((index | count | (index + count) | (text.length - index - count)) < 0) {
throw new IndexOutOfBoundsException();
}
+
boolean hasModifier = setupModifiers(paint);
- nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
- if (hasModifier) nResetModifiers(mRenderer);
+ try {
+ nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
+ }
}
private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
@@ -621,20 +625,23 @@
@Override
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
boolean hasModifier = setupModifiers(paint);
- 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);
+ try {
+ 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);
+ }
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
}
- if (hasModifier) nResetModifiers(mRenderer);
}
@Override
@@ -642,9 +649,13 @@
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
+
boolean hasModifier = setupModifiers(paint);
- nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
- if (hasModifier) nResetModifiers(mRenderer);
+ try {
+ nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
+ }
}
private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
@@ -653,8 +664,12 @@
@Override
public void drawText(String text, float x, float y, Paint paint) {
boolean hasModifier = setupModifiers(paint);
- nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint);
- if (hasModifier) nResetModifiers(mRenderer);
+ try {
+ nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
+ paint.mNativePaint);
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
+ }
}
@Override
@@ -671,15 +686,59 @@
@Override
public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
float x, float y, int dir, Paint paint) {
- throw new UnsupportedOperationException();
+ if ((index | count | text.length - index - count) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
+ throw new IllegalArgumentException("Unknown direction: " + dir);
+ }
+
+ boolean hasModifier = setupModifiers(paint);
+ try {
+ nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
+ paint.mNativePaint);
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
+ }
}
+ private native void nDrawTextRun(int renderer, char[] text, int index, int count,
+ int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
+
@Override
public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
float x, float y, int dir, Paint paint) {
- throw new UnsupportedOperationException();
+ if ((start | end | end - start | text.length() - end) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ boolean hasModifier = setupModifiers(paint);
+ try {
+ int flags = dir == 0 ? 0 : 1;
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
+ contextEnd, x, y, flags, paint.mNativePaint);
+ } else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawTextRun(this, start, end,
+ contextStart, contextEnd, x, y, flags, paint);
+ } else {
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
+ x, y, flags, paint.mNativePaint);
+ TemporaryBuffer.recycle(buf);
+ }
+ } finally {
+ if (hasModifier) nResetModifiers(mRenderer);
+ }
}
+ private native void nDrawTextRun(int renderer, String text, int start, int end,
+ int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
+
@Override
public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 60d495f..cd6b820 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -34,12 +34,23 @@
*
* @hide
*/
-abstract class HardwareRenderer {
+public abstract class HardwareRenderer {
private boolean mEnabled;
private boolean mRequested = true;
private static final String LOG_TAG = "HardwareRenderer";
/**
+ * Indicates whether hardware acceleration is available under any form for
+ * the view hierarchy.
+ *
+ * @return True if the view hierarchy can potentially be hardware accelerated,
+ * false otherwise
+ */
+ public static boolean isAvailable() {
+ return GLES20Canvas.isAvailable();
+ }
+
+ /**
* Destroys the hardware rendering context.
*/
abstract void destroy();
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 2b98e89..36413d7 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -149,7 +149,9 @@
storedBounds[2] = x1; storedBounds[3] = y1;
jfloat* storedPositions = new jfloat[count];
uint32_t* storedColors = new uint32_t[count];
- memcpy(storedColors, colorValues, count);
+ for (size_t i = 0; i < count; i++) {
+ storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+ }
if (posArray) {
AutoJavaFloatArray autoPos(env, posArray, count);
@@ -185,8 +187,8 @@
storedPositions[1] = 1.0f;
uint32_t* storedColors = new uint32_t[2];
- storedColors[0] = color0;
- storedColors[1] = color1;
+ storedColors[0] = static_cast<uint32_t>(color0);
+ storedColors[1] = static_cast<uint32_t>(color1);
SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index 716d960..147e1fa 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -221,6 +221,18 @@
}
}
+bool TextLayout::prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
+ jsize contextCount, jchar* shaped) {
+ UErrorCode status = U_ZERO_ERROR;
+ count = shapeRtlText(context, start, count, contextCount, shaped, status);
+ if (U_SUCCESS(status)) {
+ return true;
+ } else {
+ LOG(LOG_WARN, "LAYOUT", "drawTextRun error %d\n", status);
+ }
+ return false;
+}
+
void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars,
jint start, jint count, jint contextCount,
int dirFlags, jfloat x, jfloat y, SkCanvas* canvas) {
@@ -231,12 +243,8 @@
uint8_t rtl = dirFlags & 0x1;
if (rtl) {
SkAutoSTMalloc<80, jchar> buffer(contextCount);
- UErrorCode status = U_ZERO_ERROR;
- count = shapeRtlText(chars, start, count, contextCount, buffer.get(), status);
- if (U_SUCCESS(status)) {
+ if (prepareRtlTextRun(chars, start, count, contextCount, buffer.get())) {
canvas->drawText(buffer.get(), count << 1, x_, y_, *paint);
- } else {
- LOG(LOG_WARN, "LAYOUT", "drawTextRun error %d\n", status);
}
} else {
canvas->drawText(chars + start, count << 1, x_, y_, *paint);
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index 3d05e18..8f666c0 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -66,6 +66,9 @@
static bool prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
const jchar** outText, int32_t* outBytes, jchar** outBuffer);
+ static bool prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
+ jsize contextCount, jchar* shaped);
+
private:
static bool needsLayout(const jchar* text, jint len, jint bidiFlags);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index bb1a9e3..be29433 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -27,6 +27,7 @@
#include <SkPaint.h>
#include <SkRegion.h>
#include <SkScalerContext.h>
+#include <SkTemplates.h>
#include <SkXfermode.h>
#include <OpenGLRenderer.h>
@@ -275,6 +276,23 @@
}
}
+static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
+ jint start, jint count, jint contextCount, jfloat x, jfloat y,
+ int flags, SkPaint* paint) {
+ uint8_t rtl = flags & 0x1;
+ if (rtl) {
+ SkAutoSTMalloc<80, jchar> buffer(contextCount);
+ jchar* shaped = buffer.get();
+ if (TextLayout::prepareRtlTextRun(text, start, count, contextCount, shaped)) {
+ renderer->drawText((const char*) shaped, count << 1, count, x, y, paint);
+ } else {
+ LOGW("drawTextRun error");
+ }
+ } else {
+ renderer->drawText((const char*) (text + start), count << 1, count, x, y, paint);
+ }
+}
+
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) {
@@ -291,6 +309,28 @@
env->ReleaseStringChars(text, textArray);
}
+static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, jcharArray text, int index, int count,
+ int contextIndex, int contextCount, jfloat x, jfloat y, int dirFlags,
+ SkPaint* paint) {
+ jchar* textArray = env->GetCharArrayElements(text, NULL);
+ renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
+ count, contextCount, x, y, dirFlags, paint);
+ env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
+ }
+
+static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, jstring text, int start, int end,
+ int contextStart, int contextEnd, jfloat x, jfloat y, int dirFlags,
+ SkPaint* paint) {
+ const jchar* textArray = env->GetStringChars(text, NULL);
+ jint count = end - start;
+ jint contextCount = contextEnd - contextStart;
+ renderTextRun(renderer, textArray + contextStart, start - contextStart,
+ count, contextCount, x, y, dirFlags, paint);
+ env->ReleaseStringChars(text, textArray);
+}
+
#endif // USE_OPENGL_RENDERER
// ----------------------------------------------------------------------------
@@ -312,50 +352,54 @@
const char* const kClassPathName = "android/view/GLES20Canvas";
static JNINativeMethod gMethods[] = {
- { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
+ { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
+
#ifdef USE_OPENGL_RENDERER
+ { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer },
+ { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
+ { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
+ { "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare },
- { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer },
- { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
- { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
- { "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare },
+ { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
+ { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
+ { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount },
+ { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
- { "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
- { "nRestore", "(I)V", (void*) android_view_GLES20Canvas_restore },
- { "nRestoreToCount", "(II)V", (void*) android_view_GLES20Canvas_restoreToCount },
- { "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
+ { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
+ { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
- { "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
- { "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
+ { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
+ { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
+ { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
- { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
- { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
- { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
+ { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
+ { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
+ { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale },
- { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
- { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
- { "nScale", "(IFF)V", (void*) android_view_GLES20Canvas_scale },
+ { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix },
+ { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
+ { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
- { "nSetMatrix", "(II)V", (void*) android_view_GLES20Canvas_setMatrix },
- { "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
- { "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
+ { "nDrawBitmap", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
+ { "nDrawBitmap", "(IIFFFFFFFFI)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
+ { "nDrawBitmap", "(IIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
+ { "nDrawPatch", "(II[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
+ { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
+ { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
+ { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath },
- { "nDrawBitmap", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
- { "nDrawBitmap", "(IIFFFFFFFFI)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
- { "nDrawBitmap", "(IIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
- { "nDrawPatch", "(II[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
- { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
- { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
- { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath },
+ { "nResetModifiers", "(I)V", (void*) android_view_GLES20Canvas_resetModifiers },
+ { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader },
+ { "nSetupColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setupColorFilter },
- { "nResetModifiers", "(I)V", (void*) android_view_GLES20Canvas_resetModifiers },
- { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader },
- { "nSetupColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setupColorFilter },
-
- { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray },
- { "nDrawText", "(ILjava/lang/String;IIFFII)V",
+ { "nDrawText", "(I[CIIFFII)V", (void*) android_view_GLES20Canvas_drawTextArray },
+ { "nDrawText", "(ILjava/lang/String;IIFFII)V",
(void*) android_view_GLES20Canvas_drawText },
+ { "nDrawTextRun", "(I[CIIIIFFII)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
+ { "nDrawTextRun", "(ILjava/lang/String;IIIIFFII)V",
+ (void*) android_view_GLES20Canvas_drawTextRun },
+
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
(void*) android_view_GLES20Canvas_getClipBounds },
#endif
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index cb2c6a2..8251881 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -24,6 +24,10 @@
* text on a path.
*/
public class Path {
+ /**
+ * @hide
+ */
+ public final int mNativePath;
/**
* Create an empty path
@@ -537,8 +541,8 @@
super.finalize();
}
}
-
- /*package*/ final int ni() {
+
+ final int ni() {
return mNativePath;
}
@@ -592,9 +596,4 @@
int dst_path);
private static native void native_transform(int nPath, int matrix);
private static native void finalizer(int nPath);
-
- /**
- * @hide
- */
- public final int mNativePath;
}
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index 489ef83..e540806 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -20,6 +20,10 @@
import android.os.Parcelable;
public class Region implements Parcelable {
+ /**
+ * @hide
+ */
+ public final int mNativeRegion;
// the native values for these must match up with the enum in SkRegion.h
public enum Op {
@@ -329,10 +333,14 @@
}
protected void finalize() throws Throwable {
- nativeDestructor(mNativeRegion);
+ try {
+ nativeDestructor(mNativeRegion);
+ } finally {
+ super.finalize();
+ }
}
- /*package*/ Region(int ni) {
+ Region(int ni) {
if (ni == 0) {
throw new RuntimeException();
}
@@ -345,7 +353,7 @@
this(ni);
}
- /*package*/ final int ni() {
+ final int ni() {
return mNativeRegion;
}
@@ -374,6 +382,4 @@
Parcel p);
private static native boolean nativeEquals(int native_r1, int native_r2);
-
- private final int mNativeRegion;
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 33ecbea..88f6d43 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -313,18 +313,16 @@
case RECTANGLE:
if (st.mRadiusArray != null) {
mPath.reset();
- mPath.addRoundRect(mRect, st.mRadiusArray,
- Path.Direction.CW);
+ mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
canvas.drawPath(mPath, mFillPaint);
if (haveStroke) {
canvas.drawPath(mPath, mStrokePaint);
}
- }
- else {
+ } else if (st.mRadius > 0.0f) {
// since the caller is only giving us 1 value, we will force
// it to be square if the rect is too small in one dimension
// to show it. If we did nothing, Skia would clamp the rad
- // independently along each axis, giving us a thin ellips
+ // independently along each axis, giving us a thin ellipse
// if the rect were very wide but not very tall
float rad = st.mRadius;
float r = Math.min(mRect.width(), mRect.height()) * 0.5f;
@@ -335,6 +333,11 @@
if (haveStroke) {
canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
}
+ } else {
+ canvas.drawRect(mRect, mFillPaint);
+ if (haveStroke) {
+ canvas.drawRect(mRect, mStrokePaint);
+ }
}
break;
case OVAL:
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 8d00e85..e807aba 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -69,16 +69,16 @@
int width = (int) glyph->mBitmapWidth;
int height = (int) glyph->mBitmapHeight;
- if(bounds->bottom > nPenY) {
+ if (bounds->bottom > nPenY) {
bounds->bottom = nPenY;
}
- if(bounds->left > nPenX) {
+ if (bounds->left > nPenX) {
bounds->left = nPenX;
}
- if(bounds->right < nPenX + width) {
+ if (bounds->right < nPenX + width) {
bounds->right = nPenX + width;
}
- if(bounds->top < nPenY + height) {
+ if (bounds->top < nPenY + height) {
bounds->top = nPenY + height;
}
}
@@ -102,7 +102,7 @@
}
void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
int nPenX = x + glyph->mBitmapLeft;
int nPenY = y + glyph->mBitmapTop;
@@ -116,7 +116,7 @@
int32_t bX = 0, bY = 0;
for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
- if(bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) {
+ if (bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) {
LOGE("Skipping invalid index");
continue;
}
@@ -143,22 +143,19 @@
}
void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
- if(bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
- renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP,
- bitmap, bitmapW, bitmapH, NULL);
- }
- else {
- renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER,
- NULL, 0, 0, NULL);
+ int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+ if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
+ renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
+ bitmapW, bitmapH, NULL);
+ } else {
+ renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL);
}
}
void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, Rect *bounds) {
- if(bounds == NULL) {
+ int numGlyphs, Rect *bounds) {
+ if (bounds == NULL) {
LOGE("No return rectangle provided to measure text");
return;
}
@@ -167,9 +164,8 @@
}
void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y, RenderMode mode,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect *bounds) {
+ int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+ uint32_t bitmapW, uint32_t bitmapH,Rect *bounds) {
if (numGlyphs == 0 || text == NULL || len == 0) {
return;
}
@@ -185,7 +181,7 @@
while (glyphsLeft > 0) {
int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
- // Reached the end of the string or encountered
+ // Reached the end of the string
if (utfChar < 0) {
break;
}
@@ -422,7 +418,7 @@
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Initialize texture dimentions
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mCacheWidth, mCacheHeight, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+ GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -527,7 +523,6 @@
}
void FontRenderer::issueDrawCommand() {
-
checkTextureUpdate();
float* vtx = mTextMeshPtr;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5d30b1a..ff00ba6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -435,6 +435,7 @@
return;
}
+ glActiveTexture(GL_TEXTURE0);
const Texture* texture = mTextureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -451,6 +452,7 @@
return;
}
+ glActiveTexture(GL_TEXTURE0);
const Texture* texture = mTextureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -466,6 +468,7 @@
return;
}
+ glActiveTexture(GL_TEXTURE0);
const Texture* texture = mTextureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -491,6 +494,7 @@
return;
}
+ glActiveTexture(GL_TEXTURE0);
const Texture* texture = mTextureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 4a01ffa..9a22dc0 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -162,7 +162,8 @@
glGenTextures(1, &texture->id);
glBindTexture(GL_TEXTURE_2D, texture->id);
- glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap.bytesPerPixel());
+ // Textures are Alpha8
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
texture->blend = true;
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap.rowBytesAsPixels(), texture->height, 0,
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 8a97b4c..2449b6d 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -376,6 +376,9 @@
}
shader.append(" return vec2(");
switch (wrapS) {
+ case GL_CLAMP_TO_EDGE:
+ shader.append("texCoords.x");
+ break;
case GL_REPEAT:
shader.append("mod(texCoords.x, 1.0)");
break;
@@ -385,6 +388,9 @@
}
shader.append(", ");
switch (wrapT) {
+ case GL_CLAMP_TO_EDGE:
+ shader.append("texCoords.y");
+ break;
case GL_REPEAT:
shader.append("mod(texCoords.y, 1.0)");
break;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 42c0621..15a4e88 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -89,7 +89,8 @@
description.hasBitmap = true;
// The driver does not support non-power of two mirrored/repeated
// textures, so do it ourselves
- if (!extensions.hasNPot() && !isPowerOfTwo(width) && !isPowerOfTwo(height)) {
+ if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
+ (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
description.isBitmapNpot = true;
description.bitmapWrapS = gTileModes[mTileX];
description.bitmapWrapT = gTileModes[mTileY];
@@ -136,6 +137,9 @@
SkMatrix* matrix, bool blend):
SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
+ for (int i = 0; i < count; i++) {
+ LOGD("[GL] Gradient color %d = 0x%x", i, colors[i]);
+ }
}
SkiaLinearGradientShader::~SkiaLinearGradientShader() {
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 924737e..a12edf2 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -39,6 +39,8 @@
#undef CALL_GL_API
#undef CALL_GL_API_RETURN
+#define DEBUG_CALL_GL_API 0
+
#if USE_FAST_TLS_KEY
#ifdef HAVE_ARM_TLS_REGISTER
@@ -73,10 +75,24 @@
#define API_ENTRY(_api) _api
+#if DEBUG_CALL_GL_API
+
#define CALL_GL_API(_api, ...) \
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
- _c->_api(__VA_ARGS__)
-
+ _c->_api(__VA_ARGS__); \
+ GLenum status = GL_NO_ERROR; \
+ while ((status = glGetError()) != GL_NO_ERROR) { \
+ LOGD("[" #_api "] 0x%x", status); \
+ }
+
+#else
+
+ #define CALL_GL_API(_api, ...) \
+ gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
+ _c->_api(__VA_ARGS__);
+
+#endif
+
#define CALL_GL_API_RETURN(_api, ...) \
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \
return _c->_api(__VA_ARGS__)
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 73994f7..90c82ee 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -171,5 +171,14 @@
</intent-filter>
</activity>
+ <activity
+ android:name="SimplePathsActivity"
+ android:label="_SimplePaths">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java
new file mode 100644
index 0000000..071a118
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 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 com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SimplePathsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout layout = new FrameLayout(this);
+ EditText text = new EditText(this);
+ layout.addView(text, new FrameLayout.LayoutParams(600, 350, Gravity.CENTER));
+ text.setText("This is an example of an EditText widget \n" +
+ "using simple paths to create the selection.");
+ //text.setSelection(0, text.getText().length());
+
+ setContentView(layout);
+ }
+}
\ No newline at end of file