summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wei <markwei@google.com>2014-06-25 15:40:38 -0700
committerMark Wei <markwei@google.com>2014-06-25 15:40:38 -0700
commitdf01966f999ddcc69b3e479c9efbd733ad86bc84 (patch)
tree2485e1250e97b3ba29e0a58c335da9980e2c675f
parent2d10993c4276db5b28ef7cb909362fbbc26c460c (diff)
downloadbitmap-df01966f999ddcc69b3e479c9efbd733ad86bc84.tar.gz
Import latest changes to the bitmap library.
Main development is now going on in the Bigtop fork. This import includes the following changes: cl/68071490 Cache BitmapShader instance in CircularBitmapDrawable. This simple implementation is eliminating almost all of the BitmapShader construction during startup. cl/69907083 Add compatibility mode to StyledCornersBitmapDrawable for b/15023700 in 4.4.3 The rounded corners and flaps are now drawn on the canvas, instead of clipped with a path. This part is in the bitmap library. The drawn corners must match the color of the background color of the container. The bt_megalist_selected_item_background color has been pre-mixed with @android:color/white so it's in a ColorDrawable instead of a LayerDrawable, and so its color can be used to draw the fake corners. This part is in the Bigtop codebase. Change-Id: I21a22d8550fbe1dd3de7410cd82969ff947c27ea
-rw-r--r--src/com/android/bitmap/drawable/CircularBitmapDrawable.java15
-rw-r--r--src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java143
2 files changed, 146 insertions, 12 deletions
diff --git a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
index 8536f58..a4af368 100644
--- a/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/CircularBitmapDrawable.java
@@ -43,6 +43,7 @@ public class CircularBitmapDrawable extends ExtendedBitmapDrawable {
private final Paint mBorderPaint = new Paint();
private float mBorderWidth;
+ private Bitmap mShaderBitmap;
public CircularBitmapDrawable(Resources res,
BitmapCache cache, boolean limitDensity) {
@@ -120,20 +121,22 @@ public class CircularBitmapDrawable extends ExtendedBitmapDrawable {
protected void onDrawCircularBitmap(final Bitmap bitmap, final Canvas canvas,
final Rect src, final Rect dst, final float alpha) {
// Draw bitmap through shader first.
- BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP,
- TileMode.CLAMP);
- sMatrix.reset();
+ BitmapShader shader = (BitmapShader) mBitmapPaint.getShader();
+ if (shader == null || mShaderBitmap != bitmap) {
+ shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
+ mShaderBitmap = bitmap;
+ mBitmapPaint.setShader(shader);
+ }
+ sMatrix.reset();
// Fit bitmap to bounds.
float scale = Math.max((float) dst.width() / src.width(),
(float) dst.height() / src.height());
sMatrix.postScale(scale, scale);
-
// Translate bitmap to dst bounds.
sMatrix.postTranslate(dst.left, dst.top);
-
shader.setLocalMatrix(sMatrix);
- mBitmapPaint.setShader(shader);
+
int oldAlpha = mBitmapPaint.getAlpha();
mBitmapPaint.setAlpha((int) (oldAlpha * alpha));
canvas.drawCircle(dst.centerX(), dst.centerY(), dst.width() / 2,
diff --git a/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java b/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
index d5d04b3..e23642d 100644
--- a/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
+++ b/src/com/android/bitmap/drawable/StyledCornersBitmapDrawable.java
@@ -53,7 +53,9 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
private final Paint mFlapPaint = new Paint();
private final Paint mBorderPaint = new Paint();
+ private final Paint mCompatibilityModeBackgroundPaint = new Paint();
private final Path mClipPath = new Path();
+ private final Path mCompatibilityModePath = new Path();
private final float mCornerRoundRadius;
private final float mCornerFlapSide;
@@ -63,6 +65,7 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
private int mBottomLeftCornerStyle = CORNER_STYLE_SHARP;
private int mScrimColor;
private float mBorderWidth;
+ private boolean mIsCompatibilityMode;
/**
* Create a new StyledCornersBitmapDrawable.
@@ -77,12 +80,17 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
mFlapPaint.setColor(Color.TRANSPARENT);
mFlapPaint.setStyle(Style.FILL);
+ mFlapPaint.setAntiAlias(true);
mBorderPaint.setColor(Color.TRANSPARENT);
mBorderPaint.setStyle(Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setAntiAlias(true);
+ mCompatibilityModeBackgroundPaint.setColor(Color.TRANSPARENT);
+ mCompatibilityModeBackgroundPaint.setStyle(Style.FILL);
+ mCompatibilityModeBackgroundPaint.setAntiAlias(true);
+
mScrimColor = Color.TRANSPARENT;
}
@@ -129,6 +137,13 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
}
/**
+ * Get the flap color for all corners that have style {@link #CORNER_STYLE_SHARP}.
+ */
+ public int getFlapColor() {
+ return mFlapPaint.getColor();
+ }
+
+ /**
* Set the flap color for all corners that have style {@link #CORNER_STYLE_SHARP}.
*
* Use {@link android.graphics.Color#TRANSPARENT} to disable flap colors.
@@ -163,6 +178,34 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
}
}
+ /**
+ * Sets whether we should work around an issue introduced in Android 4.4.3,
+ * where a WebView can corrupt the stencil buffer of the canvas when the canvas is clipped
+ * using a non-rectangular Path.
+ */
+ public void setCompatibilityMode(boolean isCompatibilityMode) {
+ boolean changed = mIsCompatibilityMode != isCompatibilityMode;
+ mIsCompatibilityMode = isCompatibilityMode;
+
+ if (changed) {
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Sets the color of the container that this drawable is in. The given color will be used in
+ * {@link #setCompatibilityMode compatibility mode} to draw fake corners to emulate clipped
+ * corners.
+ */
+ public void setCompatibilityModeBackgroundColor(int color) {
+ boolean changed = mCompatibilityModeBackgroundPaint.getColor() != color;
+ mCompatibilityModeBackgroundPaint.setColor(color);
+
+ if (changed) {
+ invalidateSelf();
+ }
+ }
+
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
@@ -182,8 +225,10 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
}
// Clip to path.
- canvas.save();
- canvas.clipPath(mClipPath);
+ if (!mIsCompatibilityMode) {
+ canvas.save();
+ canvas.clipPath(mClipPath);
+ }
// Draw parent within path.
super.draw(canvas);
@@ -191,7 +236,7 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
// Draw scrim on top of parent.
canvas.drawColor(mScrimColor);
- // Draw flap.
+ // Draw flaps.
float left = bounds.left + mBorderWidth / 2;
float top = bounds.top + mBorderWidth / 2;
float right = bounds.right - mBorderWidth / 2;
@@ -221,14 +266,100 @@ public class StyledCornersBitmapDrawable extends ExtendedBitmapDrawable {
mCornerRoundRadius, mFlapPaint);
}
- canvas.restore();
+ if (!mIsCompatibilityMode) {
+ canvas.restore();
+ }
+
+ if (mIsCompatibilityMode) {
+ drawFakeCornersForCompatibilityMode(canvas);
+ }
// Draw border around path.
canvas.drawPath(mClipPath, mBorderPaint);
}
- protected Path getClipPath() {
- return mClipPath;
+ protected void drawFakeCornersForCompatibilityMode(final Canvas canvas) {
+ final Rect bounds = getBounds();
+
+ float left = bounds.left;
+ float top = bounds.top;
+ float right = bounds.right;
+ float bottom = bounds.bottom;
+
+ // Draw fake round corners.
+ RectF fakeCornerRectF = sRectF;
+ fakeCornerRectF.set(0, 0, mCornerRoundRadius * 2, mCornerRoundRadius * 2);
+ if (mTopLeftCornerStyle == CORNER_STYLE_ROUND) {
+ fakeCornerRectF.offsetTo(left, top);
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(left, top);
+ mCompatibilityModePath.lineTo(left + mCornerRoundRadius, top);
+ mCompatibilityModePath.arcTo(fakeCornerRectF, START_TOP, -QUARTER_CIRCLE);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mTopRightCornerStyle == CORNER_STYLE_ROUND) {
+ fakeCornerRectF.offsetTo(right - fakeCornerRectF.width(), top);
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(right, top);
+ mCompatibilityModePath.lineTo(right, top + mCornerRoundRadius);
+ mCompatibilityModePath.arcTo(fakeCornerRectF, START_RIGHT, -QUARTER_CIRCLE);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mBottomRightCornerStyle == CORNER_STYLE_ROUND) {
+ fakeCornerRectF
+ .offsetTo(right - fakeCornerRectF.width(), bottom - fakeCornerRectF.height());
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(right, bottom);
+ mCompatibilityModePath.lineTo(right - mCornerRoundRadius, bottom);
+ mCompatibilityModePath.arcTo(fakeCornerRectF, START_BOTTOM, -QUARTER_CIRCLE);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mBottomLeftCornerStyle == CORNER_STYLE_ROUND) {
+ fakeCornerRectF.offsetTo(left, bottom - fakeCornerRectF.height());
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(left, bottom);
+ mCompatibilityModePath.lineTo(left, bottom - mCornerRoundRadius);
+ mCompatibilityModePath.arcTo(fakeCornerRectF, START_LEFT, -QUARTER_CIRCLE);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+
+ // Draw fake flap corners.
+ if (mTopLeftCornerStyle == CORNER_STYLE_FLAP) {
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(left, top);
+ mCompatibilityModePath.lineTo(left + mCornerFlapSide, top);
+ mCompatibilityModePath.lineTo(left, top + mCornerFlapSide);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mTopRightCornerStyle == CORNER_STYLE_FLAP) {
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(right, top);
+ mCompatibilityModePath.lineTo(right, top + mCornerFlapSide);
+ mCompatibilityModePath.lineTo(right - mCornerFlapSide, top);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mBottomRightCornerStyle == CORNER_STYLE_FLAP) {
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(right, bottom);
+ mCompatibilityModePath.lineTo(right - mCornerFlapSide, bottom);
+ mCompatibilityModePath.lineTo(right, bottom - mCornerFlapSide);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
+ if (mBottomLeftCornerStyle == CORNER_STYLE_FLAP) {
+ mCompatibilityModePath.rewind();
+ mCompatibilityModePath.moveTo(left, bottom);
+ mCompatibilityModePath.lineTo(left, bottom - mCornerFlapSide);
+ mCompatibilityModePath.lineTo(left + mCornerFlapSide, bottom);
+ mCompatibilityModePath.close();
+ canvas.drawPath(mCompatibilityModePath, mCompatibilityModeBackgroundPaint);
+ }
}
private void recalculatePath() {