diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 8f4ece04b1135..fec0d4b94e8fc 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -32,20 +32,20 @@ public abstract class DisplayList {
*
* @return A canvas to record drawing operations.
*/
- abstract HardwareCanvas start();
+ public abstract HardwareCanvas start();
/**
* Ends the recording for this display list. A display list cannot be
* replayed if recording is not finished.
*/
- abstract void end();
+ public abstract void end();
/**
* Invalidates the display list, indicating that it should be repopulated
* with new drawing commands prior to being used again. Calling this method
* causes calls to {@link #isValid()} to return false.
*/
- abstract void invalidate();
+ public abstract void invalidate();
/**
* Returns whether the display list is currently usable. If this returns false,
@@ -53,12 +53,12 @@ public abstract class DisplayList {
*
* @return boolean true if the display list is able to be replayed, false otherwise.
*/
- abstract boolean isValid();
+ public abstract boolean isValid();
/**
* Return the amount of memory used by this display list.
*
* @return The size of this display list in bytes
*/
- abstract int getSize();
+ public abstract int getSize();
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 43a451d0cdc53..8a9be8563d91e 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -247,7 +247,7 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nDisableVsync();
@Override
- void onPreDraw(Rect dirty) {
+ public void onPreDraw(Rect dirty) {
if (dirty != null) {
nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque);
} else {
@@ -260,7 +260,7 @@ class GLES20Canvas extends HardwareCanvas {
boolean opaque);
@Override
- void onPostDraw() {
+ public void onPostDraw() {
nFinish(mRenderer);
}
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 4ca5e9844ffb4..0cb9449571309 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -43,7 +43,7 @@ class GLES20DisplayList extends DisplayList {
}
@Override
- HardwareCanvas start() {
+ public HardwareCanvas start() {
if (mCanvas != null) {
throw new IllegalStateException("Recording has already started");
}
@@ -55,7 +55,7 @@ class GLES20DisplayList extends DisplayList {
}
@Override
- void invalidate() {
+ public void invalidate() {
if (mCanvas != null) {
mCanvas.recycle();
mCanvas = null;
@@ -64,12 +64,12 @@ class GLES20DisplayList extends DisplayList {
}
@Override
- boolean isValid() {
+ public boolean isValid() {
return mValid;
}
@Override
- void end() {
+ public void end() {
if (mCanvas != null) {
if (mFinalizer != null) {
mCanvas.end(mFinalizer.mNativeDisplayList);
@@ -83,7 +83,7 @@ class GLES20DisplayList extends DisplayList {
}
@Override
- int getSize() {
+ public int getSize() {
if (mFinalizer == null) return 0;
return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList);
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 23b3abcc3cd6f..cbdbbde45b709 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -42,12 +42,12 @@ public abstract class HardwareCanvas extends Canvas {
*
* @param dirty The dirty rectangle to update, can be null.
*/
- abstract void onPreDraw(Rect dirty);
+ public abstract void onPreDraw(Rect dirty);
/**
* Invoked after all drawing operation have been performed.
*/
- abstract void onPostDraw();
+ public abstract void onPostDraw();
/**
* Draws the specified display list onto this canvas.
@@ -61,7 +61,7 @@ public abstract class HardwareCanvas extends Canvas {
* @return True if the content of the display list requires another
* drawing pass (invalidate()), false otherwise
*/
- abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty);
+ public abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty);
/**
* Outputs the specified display list to the log. This method exists for use by
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 89eb725014031..4592ae6c1a573 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -276,7 +276,7 @@ public abstract class HardwareRenderer {
*
* @return A new display list.
*/
- abstract DisplayList createDisplayList();
+ public abstract DisplayList createDisplayList();
/**
* Creates a new hardware layer. A hardware layer built by calling this
@@ -1082,7 +1082,7 @@ public abstract class HardwareRenderer {
}
@Override
- DisplayList createDisplayList() {
+ public DisplayList createDisplayList() {
return new GLES20DisplayList();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 64f862aa0ea1f..e28028634852f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10432,6 +10432,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
}
+ /**
+ * @return The HardwareRenderer associated with that view or null if hardware rendering
+ * is not supported or this this has not been attached to a window.
+ *
+ * @hide
+ */
+ public HardwareRenderer getHardwareRenderer() {
+ if (mAttachInfo != null) {
+ return mAttachInfo.mHardwareRenderer;
+ }
+ return null;
+ }
+
/**
*
Returns a display list that can be used to draw this view again * without executing its draw method.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 3dd7a9f2832ea..acea1a1a782e4 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -84,6 +84,7 @@ import android.text.method.TimeKeyListener; import android.text.method.TransformationMethod; import android.text.method.TransformationMethod2; import android.text.method.WordIterator; +import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.EasyEditSpan; import android.text.style.ParagraphStyle; @@ -101,9 +102,11 @@ import android.util.Log; import android.util.TypedValue; import android.view.ActionMode; import android.view.ActionMode.Callback; +import android.view.DisplayList; import android.view.DragEvent; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.HardwareCanvas; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -283,6 +286,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } private Drawables mDrawables; + private DisplayList mTextDisplayList; + private boolean mTextDisplayListIsValid; + private CharSequence mError; private boolean mErrorWasChanged; private ErrorPopup mPopup; @@ -4520,6 +4526,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener resetResolvedDrawables(); + if (mTextDisplayList != null) { + mTextDisplayList.invalidate(); + } + if (mSpellChecker != null) { mSpellChecker.closeSession(); // Forces the creation of a new SpellChecker next time this window is created. @@ -4970,17 +4980,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - /* Comment out until we decide what to do about animations - boolean isLinearTextOn = false; - if (currentTransformation != null) { - isLinearTextOn = mTextPaint.isLinearTextOn(); - Matrix m = currentTransformation.getMatrix(); - if (!m.isIdentity()) { - // mTextPaint.setLinearTextOn(true); - } - } - */ - final InputMethodState ims = mInputMethodState; final int cursorOffsetVertical = voffsetCursor - voffsetText; if (ims != null && ims.mBatchEditNesting == 0) { @@ -5038,19 +5037,39 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlight = null; } - layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); + if (canHaveDisplayList() && canvas.isHardwareAccelerated()) { + final int width = mRight - mLeft; + final int height = mBottom - mTop; + + if (mTextDisplayList == null || !mTextDisplayList.isValid() || + !mTextDisplayListIsValid) { + if (mTextDisplayList == null) { + mTextDisplayList = getHardwareRenderer().createDisplayList(); + } + + final HardwareCanvas hardwareCanvas = mTextDisplayList.start(); + try { + hardwareCanvas.setViewport(width, height); + // The dirty rect should always be null for a display list + hardwareCanvas.onPreDraw(null); + layout.draw(hardwareCanvas, highlight, mHighlightPaint, cursorOffsetVertical); + } finally { + hardwareCanvas.onPostDraw(); + mTextDisplayList.end(); + mTextDisplayListIsValid = true; + } + } + ((HardwareCanvas) canvas).drawDisplayList(mTextDisplayList, + mScrollX + width, mScrollY + height, null); + } else { + layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); + } if (mMarquee != null && mMarquee.shouldDrawGhost()) { canvas.translate((int) mMarquee.getGhostOffset(), 0.0f); layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); } - /* Comment out until we decide what to do about animations - if (currentTransformation != null) { - mTextPaint.setLinearTextOn(isLinearTextOn); - } - */ - canvas.restore(); } @@ -7562,6 +7581,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ protected void onSelectionChanged(int selStart, int selEnd) { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); + mTextDisplayListIsValid = false; } /** @@ -7641,6 +7661,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } updateSpellCheckSpans(start, start + after, false); + mTextDisplayListIsValid = false; // Hide the controllers as soon as text is modified (typing, procedural...) // We do not hide the span controllers, since they can be added when a new text is @@ -7743,7 +7764,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if (what instanceof UpdateAppearance || what instanceof ParagraphStyle) { + if (what instanceof UpdateAppearance || what instanceof ParagraphStyle || + what instanceof CharacterStyle) { if (ims == null || ims.mBatchEditNesting == 0) { invalidate(); mHighlightPathBogus = true; @@ -7751,6 +7773,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else { ims.mContentChanged = true; } + mTextDisplayListIsValid = false; } if (MetaKeyKeyListener.isMetaTracker(buf, what)) {