Merge "Fix BitmapShader to work with adaptive icons"

This commit is contained in:
Diego Perez
2017-03-17 18:01:26 +00:00
committed by Android (Google) Code Review
3 changed files with 34 additions and 66 deletions

View File

@@ -24,6 +24,7 @@ import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
import android.text.TextUtils;
import java.awt.*;
@@ -31,6 +32,8 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
public class BaseCanvas_Delegate {
// ---- delegate manager ----
@@ -646,9 +649,15 @@ public class BaseCanvas_Delegate {
forceSrcMode[0] = false;
// if the bitmap config is alpha_8, then we erase all color value from it
// before drawing it.
// before drawing it or apply the texture from the shader if present.
if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
fixAlpha8Bitmap(image);
Shader_Delegate shader = paint.getShader();
java.awt.Paint javaPaint = null;
if (shader instanceof BitmapShader_Delegate) {
javaPaint = shader.getJavaPaint();
}
fixAlpha8Bitmap(image, javaPaint);
} else if (!bitmap.hasAlpha()) {
// hasAlpha is merely a rendering hint. There can in fact be alpha values
// in the bitmap but it should be ignored at drawing time.
@@ -672,16 +681,37 @@ public class BaseCanvas_Delegate {
return image;
}
private static void fixAlpha8Bitmap(final BufferedImage image) {
/**
* This method will apply the correct color to the passed "only alpha" image. Colors on the
* passed image will be destroyed.
* If the passed javaPaint is null, the color will be set to 0. If a paint is passed, it will
* be used to obtain the color that will be applied.
* <p/>
* This will destroy the passed image color channel.
*/
private static void fixAlpha8Bitmap(final BufferedImage image,
@Nullable java.awt.Paint javaPaint) {
int w = image.getWidth();
int h = image.getHeight();
DataBuffer texture = null;
if (javaPaint != null) {
PaintContext context = javaPaint.createContext(ColorModel.getRGBdefault(), null, null,
new AffineTransform(), null);
texture = context.getRaster(0, 0, w, h).getDataBuffer();
}
int[] argb = new int[w * h];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
final int length = argb.length;
for (int i = 0 ; i < length; i++) {
for (int i = 0; i < length; i++) {
argb[i] &= 0xFF000000;
if (texture != null) {
argb[i] |= texture.getElem(i) & 0x00FFFFFF;
}
}
image.setRGB(0, 0, w, h, argb, 0, w);
}

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.graphics.drawable;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable.LayerState;
/**
* Delegate used to provide new implementation of a select few methods of {@link
* AdaptiveIconDrawable}
* <p>
* Through the layoutlib_create tool, the original methods of AdaptiveIconDrawable have been
* replaced by calls to methods of the same name in this delegate class.
*/
@SuppressWarnings("unused")
public class AdaptiveIconDrawable_Delegate {
@LayoutlibDelegate
/*package*/ static void draw(AdaptiveIconDrawable thisDrawable, Canvas canvas) {
// This is a workaround for the broken BitmapShader in layoutlib. This new draw methods
// avoids the use of the shader.
for (int i = 0; i < LayerState.N_CHILDREN; i++) {
if (thisDrawable.mLayerState.mChildren[i] == null) {
continue;
}
final Drawable dr = thisDrawable.mLayerState.mChildren[i].mDrawable;
if (dr != null) {
dr.draw(canvas);
}
}
if (thisDrawable.mMaskBitmap != null) {
Rect bounds = thisDrawable.getBounds();
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawBitmap(thisDrawable.mMaskBitmap, bounds.left, bounds.top, paint);
}
}
}

View File

@@ -163,7 +163,6 @@ public final class CreateInfo implements ICreateInfo {
"android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",
"android.graphics.BitmapFactory#setDensityFromOptions",
"android.graphics.drawable.AdaptiveIconDrawable#draw",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#onDraw",
"android.graphics.drawable.GradientDrawable#buildRing",
@@ -333,8 +332,6 @@ public final class CreateInfo implements ICreateInfo {
* needed when access from the delegate classes is needed.
*/
private final static String[] PROMOTED_FIELDS = new String[] {
"android.graphics.drawable.AdaptiveIconDrawable#mMaskBitmap",
"android.graphics.drawable.AdaptiveIconDrawable#mPaint",
"android.graphics.drawable.VectorDrawable#mVectorState",
"android.view.Choreographer#mLastFrameTimeNanos",
"android.graphics.FontFamily#mBuilderPtr"