Bug 1335895 - part 32: Fix rendering of toolbar "curve" so that it works with software rendering r=jchen
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.
MozReview-Commit-ID: NTwcEeh2Vi
--- 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) {