Bug 1057438 - Only re-create LinearGradient when necessary. r=bnicholson, a=lmandel
authorLucas Rocha <lucasr@mozilla.com>
Tue, 02 Sep 2014 10:52:08 +0100
changeset 224673 9be2c92a3f288dbfe3407e918ff274f37800f749
parent 224672 b0af000f6c88ac4d76ee21388ba3c05c19be347a
child 224674 b20758e5f09eb1a6ac0cae74f231aa36a8b4bc29
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbnicholson, lmandel
bugs1057438
milestone34.0a2
Bug 1057438 - Only re-create LinearGradient when necessary. r=bnicholson, a=lmandel
mobile/android/base/home/FadedTextView.java
mobile/android/base/resources/values-large-land-v11/styles.xml
mobile/android/base/resources/values/styles.xml
--- a/mobile/android/base/home/FadedTextView.java
+++ b/mobile/android/base/home/FadedTextView.java
@@ -6,75 +6,104 @@
 package org.mozilla.gecko.home;
 
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.LinearGradient;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
+import android.text.Layout;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
 import org.mozilla.gecko.R;
 
 /**
  * FadedTextView fades the ends of the text by fadeWidth amount,
  * if the text is too long and requires an ellipsis.
  */
 public class FadedTextView extends TextView {
 
     // Width of the fade effect from end of the view.
-    private int mFadeWidth;
+    private final int mFadeWidth;
 
-    // Padding for compound drawables.
-    private int mCompoundPadding;
+    // Shader for the fading edge.
+    private FadedTextGradient mTextGradient;
 
     public FadedTextView(Context context) {
         this(context, null);
     }
 
     public FadedTextView(Context context, AttributeSet attrs) {
         this(context, attrs, android.R.attr.textViewStyle);
     }
 
     public FadedTextView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
+        setSingleLine(true);
+        setEllipsize(null);
+
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FadedTextView);
         mFadeWidth = a.getDimensionPixelSize(R.styleable.FadedTextView_fadeWidth, 0);
         a.recycle();
+    }
 
-        mCompoundPadding = getCompoundDrawablePadding();
+    private int getAvailableWidth() {
+        return getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
+    }
+
+    private boolean needsEllipsis() {
+        final int width = getAvailableWidth();
+        if (width <= 0) {
+            return false;
+        }
+
+        final Layout layout = getLayout();
+        return (layout != null && layout.getLineWidth(0) > width);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    private void updateGradientShader() {
+        final int color = getCurrentTextColor();
+        final int width = getAvailableWidth();
+
+        final boolean needsNewGradient = (mTextGradient == null ||
+                                          mTextGradient.getColor() != color ||
+                                          mTextGradient.getWidth() != width);
+
+        final boolean needsEllipsis = needsEllipsis();
+        if (needsEllipsis && needsNewGradient) {
+            mTextGradient = new FadedTextGradient(width, mFadeWidth, color);
+        }
+
+        getPaint().setShader(needsEllipsis ? mTextGradient : null);
+    }
+
     @Override
     public void onDraw(Canvas canvas) {
-        int width = getMeasuredWidth();
+        updateGradientShader();
+        super.onDraw(canvas);
+    }
+
+    private static class FadedTextGradient extends LinearGradient {
+        private final int mWidth;
+        private final int mColor;
 
-        // Layout doesn't return a proper width for getWidth().
-        // Instead check the width of the first line, as we've restricted to just one line.
-        if (getLayout().getLineWidth(0) > width) {
-            final Drawable leftDrawable = getCompoundDrawables()[0];
-            int drawableWidth = 0;
-            if (leftDrawable != null) {
-                drawableWidth = leftDrawable.getIntrinsicWidth() + mCompoundPadding;
-                width -= drawableWidth;
-            }
+        public FadedTextGradient(int width, int fadeWidth, int color) {
+            super(0, 0, width, 0,
+                  new int[] { color, color, 0x0 },
+                  new float[] { 0,  ((float) (width - fadeWidth) / (float) width), 1.0f },
+                  Shader.TileMode.CLAMP);
 
-            int color = getCurrentTextColor();
-            float stop = ((float) (width - mFadeWidth) / (float) width);
-            LinearGradient gradient = new LinearGradient(0, 0, width, 0,
-                                                         new int[] { color, color, 0x0 },
-                                                         new float[] { 0, stop, 1.0f - (drawableWidth / width) },
-                                                         Shader.TileMode.CLAMP);
-            getPaint().setShader(gradient);
-        } else {
-            getPaint().setShader(null);
+            mWidth = width;
+            mColor = color;
         }
 
-        // Do a default draw.
-        super.onDraw(canvas);
+        public int getWidth() {
+            return mWidth;
+        }
+
+        public int getColor() {
+            return mColor;
+        }
     }
 }
--- a/mobile/android/base/resources/values-large-land-v11/styles.xml
+++ b/mobile/android/base/resources/values-large-land-v11/styles.xml
@@ -6,16 +6,18 @@
 <resources>
 
     <style name="TabsList" parent="TabsListBase">
          <item name="android:orientation">vertical</item>
          <item name="android:scrollbars">vertical</item>
     </style>
 
     <style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">none</item>
         <item name="android:paddingLeft">60dip</item>
         <item name="android:drawablePadding">10dip</item>
         <item name="android:drawableLeft">@drawable/bookmark_folder</item>
     </style>
 
     <style name="Widget.BookmarkItemView" parent="Widget.TwoLinePageRow">
         <item name="android:paddingLeft">50dp</item>
         <item name="android:paddingRight">50dp</item>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -109,28 +109,28 @@
         <item name="android:ellipsize">middle</item>
         <item name="android:textSize">@dimen/menu_item_textsize</item>
     </style>
 
     <style name="Widget.TwoLinePageRow" />
 
     <style name="Widget.TwoLinePageRow.Title">
         <item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemTitle</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:ellipsize">none</item>
     </style>
 
     <style name="Widget.TwoLinePageRow.Url">
         <item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemDescription</item>
         <item name="android:includeFontPadding">false</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">middle</item>
     </style>
 
     <style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">none</item>
         <item name="android:paddingLeft">10dip</item>
         <item name="android:drawablePadding">10dip</item>
         <item name="android:drawableLeft">@drawable/bookmark_folder</item>
     </style>
 
     <style name="Widget.PanelItemView" />
 
     <style name="Widget.PanelItemView.Title">
@@ -184,18 +184,16 @@
       <item name="android:minWidth">30dip</item>
       <item name="android:minHeight">30dip</item>
       <item name="android:padding">0dip</item>
     </style>
 
     <style name="Widget.TopSitesGridItemTitle">
       <item name="android:textColor">@color/top_sites_grid_item_title</item>
       <item name="android:textSize">12sp</item>
-      <item name="android:singleLine">true</item>
-      <item name="android:ellipsize">none</item>
       <item name="android:paddingTop">5dip</item>
       <item name="android:gravity">left</item>
     </style>
 
     <style name="Widget.HomeListView" parent="Widget.ListView">
         <item name="android:divider">#E7ECF0</item>
     </style>