Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4291b03 authored by Diego Perez's avatar Diego Perez
Browse files

Fix BitmapShader to work with adaptive icons

Test: Existing test should pass
Change-Id: Ie4c78eab4dfacf1eb6060d71edb98b836c4eff78
parent f33a0379
Loading
Loading
Loading
Loading
+34 −4
Original line number Diff line number Diff line
@@ -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++) {
            argb[i] &= 0xFF000000;
            if (texture != null) {
                argb[i] |= texture.getElem(i) & 0x00FFFFFF;
            }
        }

        image.setRGB(0, 0, w, h, argb, 0, w);
    }

+0 −59
Original line number Diff line number Diff line
/*
 * 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);
        }
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -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"