Bug 1335895 - part 32: Fix rendering of toolbar "curve" so that it works with software rendering r=jchen,kats draft
authorRandall Barker <rbarker@mozilla.com>
Sat, 01 Apr 2017 15:45:35 -0700
changeset 558774 fa6a016c1105788c4db7b42f43165742c9306984
parent 558773 dd581a4c376237e583d0eb14a70c3198284c519a
child 558775 b17c5dac5baf5fb8f377c312f8525f3cd3bb4104
push id52941
push userbmo:rbarker@mozilla.com
push dateFri, 07 Apr 2017 23:43:33 +0000
reviewersjchen, kats
bugs1335895
milestone55.0a1
Bug 1335895 - part 32: Fix rendering of toolbar "curve" so that it works with software rendering r=jchen,kats The issue appears to be PorterDuff DEST_IN is busted when doing software rendering. Inverting the curve and using PorterDuff DEST_OUT fixed the issue.
mobile/android/base/java/org/mozilla/gecko/toolbar/CanvasDelegate.java
mobile/android/base/java/org/mozilla/gecko/toolbar/PhoneTabsButton.java
mobile/android/base/java/org/mozilla/gecko/toolbar/ShapedButton.java
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/CanvasDelegate.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/CanvasDelegate.java
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.toolbar;
 
 import org.mozilla.gecko.AppConstants.Versions;
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Shader;
 
 class CanvasDelegate {
     Paint mPaint;
@@ -29,34 +30,29 @@ class CanvasDelegate {
 
         // DST_IN masks, DST_OUT clips.
         mMode = new PorterDuffXfermode(mode);
 
         mPaint = paint;
     }
 
     void draw(Canvas canvas, Path path, int width, int height) {
-        // Save the canvas. All PorterDuff operations should be done in a offscreen bitmap.
-        int count = canvas.saveLayer(0, 0, width, height, null,
-                                     Canvas.MATRIX_SAVE_FLAG |
-                                     Canvas.CLIP_SAVE_FLAG |
-                                     Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
-                                     Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
-                                     Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+        Bitmap offscreen = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas offscreenCanvas = new Canvas(offscreen);
 
         // Do a default draw.
-        mDrawManager.defaultDraw(canvas);
+        mDrawManager.defaultDraw(offscreenCanvas);
 
         if (path != null && !path.isEmpty()) {
             // ICS added double-buffering, which made it easier for drawing the Path directly over the DST.
             // In pre-ICS, drawPath() doesn't seem to use ARGB_8888 mode for performance, hence transparency is not preserved.
             mPaint.setXfermode(mMode);
-            canvas.drawPath(path, mPaint);
+            offscreenCanvas.drawPath(path, mPaint);
         }
 
-        // Restore the canvas.
-        canvas.restoreToCount(count);
+        offscreen.prepareToDraw();
+        canvas.drawBitmap(offscreen, 0, 0, null);
     }
 
     void setShader(Shader shader) {
         mPaint.setShader(shader);
     }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/PhoneTabsButton.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PhoneTabsButton.java
@@ -37,18 +37,17 @@ public class PhoneTabsButton extends Sha
 
         Point[] nodes = getDirectionalNodes(width, height, layoutDirection);
         TabCurve.Direction directionalCurve = getDirectionalCurve(layoutDirection);
 
         mPath.reset();
 
         mPath.moveTo(nodes[0].x, nodes[0].y);
         TabCurve.drawFromTop(mPath, nodes[1].x, nodes[1].y, directionalCurve);
-        mPath.lineTo(nodes[2].x, nodes[2].y);
-        mPath.lineTo(nodes[3].x, nodes[3].y);
+        mPath.lineTo(nodes[1].x, nodes[1].y);
         mPath.lineTo(nodes[0].x, nodes[0].y);
     }
 
     private static TabCurve.Direction getDirectionalCurve(int direction) {
         if (direction == ViewCompat.LAYOUT_DIRECTION_RTL) {
             //  right to LEFT
             return TabCurve.Direction.LEFT;
         } else {
@@ -58,23 +57,20 @@ public class PhoneTabsButton extends Sha
     }
 
     private static Point[] getDirectionalNodes(int width, int height, int layoutDirection) {
         final Point[] nodes;
         if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
             nodes = new Point[] {
                     new Point(width, 0)
                     , new Point(width, height)
-                    , new Point(0, height)
-                    , new Point(0, 0)
             };
         } else {
             nodes = new Point[]{
                     new Point(0, 0)
                     , new Point(0, height)
-                    , new Point(width, height)
-                    , new Point(width, 0)
             };
+
         }
         return nodes;
     }
 
 }
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/ShapedButton.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/ShapedButton.java
@@ -35,17 +35,17 @@ public class ShapedButton extends Themed
 
         // Path is clipped.
         mPath = new Path();
 
         final Paint paint = new Paint();
         paint.setAntiAlias(true);
         paint.setColor(ContextCompat.getColor(context, R.color.canvas_delegate_paint));
         paint.setStrokeWidth(0.0f);
-        mCanvasDelegate = new CanvasDelegate(this, Mode.DST_IN, paint);
+        mCanvasDelegate = new CanvasDelegate(this, Mode.DST_OUT, paint);
 
         setWillNotDraw(false);
     }
 
     @Override
     @SuppressLint("MissingSuperCall") // Super gets called from defaultDraw().
                                       // It is intentionally not called in the other case.
     public void draw(Canvas canvas) {