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

Commit 8ee6bcf8 authored by Deepanshu Gupta's avatar Deepanshu Gupta
Browse files

Use BlendComposite for advanced PorterDuff Modes. [DO NOT MERGE]

Not all PorterDuff modes are supported by Java's AlphaComposite. Use
BlendComposite for such modes.

Change-Id: I51486a40f09186cf8a87ce1e6a3d1cfcf39fb2d3
(cherry picked from commit b15709cd36d28c47660b0ae30918642bfd3d85f7)
parent 47fa5c92
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.graphics.Bitmap.Config;
@@ -534,7 +535,8 @@ public final class Canvas_Delegate {
                // set the color
                graphics.setColor(new Color(color, true /*alpha*/));

                Composite composite = PorterDuffXfermode_Delegate.getComposite(mode, 0xFF);
                Composite composite = PorterDuffUtility.getComposite(
                        PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
                if (composite != null) {
                    graphics.setComposite(composite);
                }
+27 −41
Original line number Diff line number Diff line
@@ -21,11 +21,10 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.graphics.PorterDuff.Mode;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getComposite;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;

/**
@@ -57,7 +56,7 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {

    @Override
    public boolean isSupported() {
        return getAlphaCompositeRule(mMode) != -1;
        return true;
    }

    @Override
@@ -68,7 +67,7 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
    @Override
    public void applyFilter(Graphics2D g, int width, int height) {
        BufferedImage image = createFilterImage(width, height);
        g.setComposite(getComposite());
        g.setComposite(getComposite(mMode, 0xFF));
        g.drawImage(image, 0, 0, null);
    }

@@ -101,26 +100,17 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
        return image;
    }

    private AlphaComposite getComposite() {
        return AlphaComposite.getInstance(getAlphaCompositeRule(mMode));
    }

    // For filtering the colors, the src image should contain the "color" only for pixel values
    // which are not transparent in the target image. But, we are using a simple rectangular image
    // completely filled with color. Hence some AlphaComposite rules do not apply as intended.
    // However, in such cases, they can usually be mapped to some other mode, which produces an
    // completely filled with color. Hence some Composite rules do not apply as intended. However,
    // in such cases, they can usually be mapped to some other mode, which produces an
    // equivalent result.
    private Mode getCompatibleMode(Mode mode) {
        Mode m = mode;
        // Modes that are directly supported:
        // CLEAR, DST, SRC_IN, DST_IN, DST_OUT, SRC_ATOP, DARKEN, LIGHTEN, MULTIPLY, SCREEN,
        // ADD, OVERLAY
        switch (mode) {
            // Modes that are directly supported.
            case CLEAR:
            case DST:
            case SRC_IN:
            case DST_IN:
            case DST_OUT:
            case SRC_ATOP:
                break;
        // Modes that can be mapped to one of the supported modes.
        case SRC:
            m = Mode.SRC_IN;
@@ -140,10 +130,6 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
        case XOR:
            m = Mode.DST_OUT;
            break;
            // This mode is not supported, but used by Action Bar Overflow Popup Menus. We map this
            // to the closest supported mode, to prevent showing excessive warnings to the user.
            case MULTIPLY:
                m = Mode.SRC_IN;
        }
        return m;
    }
+2 −21
Original line number Diff line number Diff line
@@ -16,17 +16,14 @@

package android.graphics;

import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;

import android.graphics.PorterDuff.Mode;

import java.awt.AlphaComposite;
import java.awt.Composite;

import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;

/**
@@ -58,7 +55,7 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {

    @Override
    public Composite getComposite(int alpha) {
        return getComposite(mMode, alpha);
        return PorterDuffUtility.getComposite(mMode, alpha);
    }

    @Override
@@ -72,9 +69,6 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
        return null;
    }

    public static Composite getComposite(int mode, int alpha) {
        return getComposite(getPorterDuffMode(mode), alpha);
    }

    // ---- native methods ----

@@ -90,17 +84,4 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
        mMode = getPorterDuffMode(mode);
    }

    private static Composite getComposite(Mode mode, int alpha255) {
        float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
        int rule = getAlphaCompositeRule(mode);
        if (rule >= 0) {
            return AlphaComposite.getInstance(rule, alpha1);
        }

        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
                String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
                null, null /*data*/);

        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
    }
}
+43 −32
Original line number Diff line number Diff line
@@ -19,11 +19,14 @@ package com.android.layoutlib.bridge.impl;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;

import android.graphics.BlendComposite;
import android.graphics.BlendComposite.BlendingMode;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter_Delegate;
import android.graphics.PorterDuffXfermode_Delegate;

import java.awt.AlphaComposite;
import java.awt.Composite;

/**
 * Provides various utility methods for {@link PorterDuffColorFilter_Delegate} and {@link
@@ -51,46 +54,54 @@ public final class PorterDuffUtility {
    }

    /**
     * A utility method to convert the porterDuffMode to an int to be used as a rule for {@link
     * AlphaComposite}. If {@code AlphaComposite} doesn't support the mode, -1 is returned.
     * A utility method to get the {@link Composite} that represents the filter for the given
     * PorterDuff mode and the alpha. Defaults to {@link Mode#SRC_OVER} for invalid modes.
     */
    public static int getAlphaCompositeRule(Mode porterDuffMode) {
        switch (porterDuffMode) {
    public static Composite getComposite(Mode mode, int alpha255) {
        float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
        switch (mode) {
            case CLEAR:
                return AlphaComposite.CLEAR;
            case DARKEN:
                break;
                return AlphaComposite.getInstance(AlphaComposite.CLEAR, alpha1);
            case SRC:
                return AlphaComposite.getInstance(AlphaComposite.SRC, alpha1);
            case DST:
                return AlphaComposite.DST;
            case DST_ATOP:
                return AlphaComposite.DST_ATOP;
                return AlphaComposite.getInstance(AlphaComposite.DST, alpha1);
            case SRC_OVER:
                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
            case DST_OVER:
                return AlphaComposite.getInstance(AlphaComposite.DST_OVER, alpha1);
            case SRC_IN:
                return AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha1);
            case DST_IN:
                return AlphaComposite.DST_IN;
                return AlphaComposite.getInstance(AlphaComposite.DST_IN, alpha1);
            case SRC_OUT:
                return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, alpha1);
            case DST_OUT:
                return AlphaComposite.DST_OUT;
            case DST_OVER:
                return AlphaComposite.DST_OVER;
                return AlphaComposite.getInstance(AlphaComposite.DST_OUT, alpha1);
            case SRC_ATOP:
                return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha1);
            case DST_ATOP:
                return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, alpha1);
            case XOR:
                return AlphaComposite.getInstance(AlphaComposite.XOR, alpha1);
            case DARKEN:
                return BlendComposite.getInstance(BlendingMode.DARKEN, alpha1);
            case LIGHTEN:
                break;
                return BlendComposite.getInstance(BlendingMode.LIGHTEN, alpha1);
            case MULTIPLY:
                break;
                return BlendComposite.getInstance(BlendingMode.MULTIPLY, alpha1);
            case SCREEN:
                break;
            case SRC:
                return AlphaComposite.SRC;
            case SRC_ATOP:
                return AlphaComposite.SRC_ATOP;
            case SRC_IN:
                return AlphaComposite.SRC_IN;
            case SRC_OUT:
                return AlphaComposite.SRC_OUT;
            case SRC_OVER:
                return AlphaComposite.SRC_OVER;
            case XOR:
                return AlphaComposite.XOR;
        }
        // This is an unsupported mode.
        return -1;
                return BlendComposite.getInstance(BlendingMode.SCREEN, alpha1);
            case ADD:
                return BlendComposite.getInstance(BlendingMode.ADD, alpha1);
            case OVERLAY:
                return BlendComposite.getInstance(BlendingMode.OVERLAY, alpha1);
            default:
                Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
                        String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
                        null, null /*data*/);

                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
        }
    }
}