diff options
author | Deepanshu Gupta <deepanshu@google.com> | 2014-06-21 19:45:30 -0700 |
---|---|---|
committer | Deepanshu Gupta <deepanshu@google.com> | 2014-06-22 13:02:54 -0700 |
commit | f2af1f5d8aaff684f8cc6d8e31454c945e190976 (patch) | |
tree | 61d71869bd25d7616b16cf2b16e0a7d66c102a65 | |
parent | 367a0ce902edbdbea7d63aedd9c98820c00909ae (diff) | |
download | frameworks_base-f2af1f5d8aaff684f8cc6d8e31454c945e190976.zip frameworks_base-f2af1f5d8aaff684f8cc6d8e31454c945e190976.tar.gz frameworks_base-f2af1f5d8aaff684f8cc6d8e31454c945e190976.tar.bz2 |
LayoutLib: Support PorterDuffColorFilter
Add support for select modes for PorterDuffColorFilter.
Change-Id: Ia7b4a6a92c326be977dd87a70f54c1f8954b546d
9 files changed, 318 insertions, 150 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index a417479..80f3b18 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -627,8 +627,7 @@ public final class Canvas_Delegate { // set the color graphics.setColor(new Color(color, true /*alpha*/)); - Composite composite = PorterDuffXfermode_Delegate.getComposite( - PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF); + Composite composite = PorterDuffXfermode_Delegate.getComposite(mode, 0xFF); if (composite != null) { graphics.setComposite(composite); } diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java index bf03a5e..bd934d0 100644 --- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java @@ -19,6 +19,8 @@ package android.graphics; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; +import java.awt.Graphics2D; + /** * Delegate implementing the native methods of android.graphics.ColorFilter * @@ -50,9 +52,17 @@ public abstract class ColorFilter_Delegate { return sManager.getDelegate(nativeShader); } - public abstract boolean isSupported(); public abstract String getSupportMessage(); + public boolean isSupported() { + return false; + } + + public void applyFilter(Graphics2D g, int width, int height) { + // This should never be called directly. If supported, the sub class should override this. + assert false; + } + // ---- native methods ---- @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java index 9aac2bd..6739484 100644 --- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java @@ -43,11 +43,6 @@ public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate { // ---- Public Helper methods ---- @Override - public boolean isSupported() { - return false; - } - - @Override public String getSupportMessage() { return "ColorMatrix Color Filters are not supported."; } diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java index 501d55c..0dd9703 100644 --- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java @@ -43,11 +43,6 @@ public class LightingColorFilter_Delegate extends ColorFilter_Delegate { // ---- Public Helper methods ---- @Override - public boolean isSupported() { - return false; - } - - @Override public String getSupportMessage() { return "Lighting Color Filters are not supported."; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index c7c2e97..5adf4ca 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -827,8 +827,8 @@ public class Paint_Delegate { delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter); - // since none of those are supported, display a fidelity warning right away - if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) { + // Log warning if it's not supported. + if (delegate.mColorFilter != null && !delegate.mColorFilter.isSupported()) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER, delegate.mColorFilter.getSupportMessage(), null, null /*data*/); } @@ -873,7 +873,7 @@ public class Paint_Delegate { delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter); // since none of those are supported, display a fidelity warning right away - if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) { + if (delegate.mMaskFilter != null && !delegate.mMaskFilter.isSupported()) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER, delegate.mMaskFilter.getSupportMessage(), null, null /*data*/); } @@ -906,7 +906,7 @@ public class Paint_Delegate { delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer); // since none of those are supported, display a fidelity warning right away - if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) { + if (delegate.mRasterizer != null && !delegate.mRasterizer.isSupported()) { Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER, delegate.mRasterizer.getSupportMessage(), null, null /*data*/); } diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java index 1bc3033..0543f4f 100644 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java @@ -19,6 +19,15 @@ package android.graphics; import com.android.layoutlib.bridge.impl.DelegateManager; 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.getPorterDuffMode; + /** * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter * @@ -40,25 +49,80 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate { // ---- delegate data ---- + private final int mSrcColor; + private final Mode mMode; + private int mWidth; + private int mHeight; + private BufferedImage mImage; + + // ---- Public Helper methods ---- @Override public boolean isSupported() { + switch (mMode) { + case CLEAR: + case SRC: + case SRC_IN: + case DST_IN: + case SRC_ATOP: + return true; + } + return false; } @Override public String getSupportMessage() { - return "PorterDuff Color Filters are not supported."; + return "PorterDuff Color Filter is not supported for mode: " + mMode.name() + "."; + } + + @Override + public void applyFilter(Graphics2D g, int width, int height) { + createFilterImage(width, height); + g.setComposite(getComposite()); + g.drawImage(mImage, 0, 0, null); } // ---- native methods ---- @LayoutlibDelegate /*package*/ static long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) { - PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate(); + PorterDuffColorFilter_Delegate newDelegate = + new PorterDuffColorFilter_Delegate(srcColor, porterDuffMode); return sManager.addNewDelegate(newDelegate); } + // ---- Private delegate/helper methods ---- + + private PorterDuffColorFilter_Delegate(int srcColor, int mode) { + mSrcColor = srcColor; + mMode = getPorterDuffMode(mode); + } + + private void createFilterImage(int width, int height) { + if (mWidth == width && mHeight == height && mImage != null) { + return; + } + mWidth = width; + mHeight = height; + mImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = mImage.createGraphics(); + try { + graphics.setColor(new java.awt.Color(mSrcColor, true /* hasAlpha */)); + graphics.fillRect(0, 0, width, height); + } finally { + graphics.dispose(); + } + } + + private AlphaComposite getComposite() { + return AlphaComposite.getInstance(getAlphaCompositeRule(mMode), + getAlpha() / 255f); + } + + private int getAlpha() { + return mSrcColor >>> 24; + } } diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java index a89fd57..f6c36b6 100644 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java @@ -21,9 +21,14 @@ import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; 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; + /** * Delegate implementing the native methods of android.graphics.PorterDuffXfermode * @@ -43,17 +48,17 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { // ---- delegate data ---- - private final int mMode; + private final Mode mMode; // ---- Public Helper methods ---- - public PorterDuff.Mode getMode() { - return getPorterDuffMode(mMode); + public Mode getMode() { + return mMode; } @Override public Composite getComposite(int alpha) { - return getComposite(getPorterDuffMode(mMode), alpha); + return getComposite(mMode, alpha); } @Override @@ -67,61 +72,8 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { return null; } - public static PorterDuff.Mode getPorterDuffMode(int mode) { - for (PorterDuff.Mode m : PorterDuff.Mode.values()) { - if (m.nativeInt == mode) { - return m; - } - } - - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/); - assert false; - return PorterDuff.Mode.SRC_OVER; - } - - public static Composite getComposite(PorterDuff.Mode mode, int alpha) { - float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f; - switch (mode) { - case CLEAR: - return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha); - case DARKEN: - break; - case DST: - return AlphaComposite.getInstance(AlphaComposite.DST, falpha); - case DST_ATOP: - return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha); - case DST_IN: - return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha); - case DST_OUT: - return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha); - case DST_OVER: - return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha); - case LIGHTEN: - break; - case MULTIPLY: - break; - case SCREEN: - break; - case SRC: - return AlphaComposite.getInstance(AlphaComposite.SRC, falpha); - case SRC_ATOP: - return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha); - case SRC_IN: - return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha); - case SRC_OUT: - return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha); - case SRC_OVER: - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha); - case XOR: - return AlphaComposite.getInstance(AlphaComposite.XOR, falpha); - } - - Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN, - String.format("Unsupported PorterDuff Mode: %s", mode.name()), - null, null /*data*/); - - return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha); + public static Composite getComposite(int mode, int alpha) { + return getComposite(getPorterDuffMode(mode), alpha); } // ---- native methods ---- @@ -135,6 +87,20 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { // ---- Private delegate/helper methods ---- private PorterDuffXfermode_Delegate(int mode) { - mMode = mode; + 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); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java index 21d6b1a..3a0321a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java @@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; +import android.graphics.ColorFilter_Delegate; import android.graphics.Paint; import android.graphics.Paint_Delegate; import android.graphics.Rect; @@ -48,8 +49,8 @@ import java.util.ArrayList; * This is based on top of {@link Graphics2D} but can operate independently if none are available * yet when setting transforms and clip information. * <p> - * This allows for drawing through {@link #draw(Drawable, Paint_Delegate)} and - * {@link #draw(Drawable, Paint_Delegate)} + * This allows for drawing through {@link #draw(Drawable, Paint_Delegate, boolean, boolean)} and + * {@link #draw(Drawable)} * * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer} @@ -203,7 +204,7 @@ public class GcSnapshot { * called before the snapshot can be used to draw. Transform and clip operations are permitted * before. * - * @param image the image to associate to the snapshot or null. + * @param bitmap the image to associate to the snapshot or null. * @return the root snapshot */ public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) { @@ -557,7 +558,6 @@ public class GcSnapshot { * Executes the Drawable's draw method, with a null paint delegate. * <p/> * Note that the method can be called several times if there are more than one active layer. - * @param drawable */ public void draw(Drawable drawable) { draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/); @@ -567,20 +567,19 @@ public class GcSnapshot { * Executes the Drawable's draw method. * <p/> * Note that the method can be called several times if there are more than one active layer. - * @param drawable - * @param paint * @param compositeOnly whether the paint is used for composite only. This is typically * the case for bitmaps. * @param forceSrcMode if true, this overrides the composite to be SRC */ public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly, boolean forceSrcMode) { + int forceMode = forceSrcMode ? AlphaComposite.SRC : 0; // the current snapshot may not have a mLocalLayer (ie it was created on save() instead // of saveLayer(), but that doesn't mean there's no layer. // mLayers however saves all the information we need (flags). if (mLayers.size() == 1) { // no layer, only base layer. easy case. - drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceSrcMode); + drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceMode); } else { // draw in all the layers until the layer save flags tells us to stop (ie drawing // in that layer is limited to the layer itself. @@ -590,7 +589,7 @@ public class GcSnapshot { do { Layer layer = mLayers.get(i); - drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode); + drawInLayer(layer, drawable, paint, compositeOnly, forceMode); // then go to previous layer, only if there are any left, and its flags // doesn't restrict drawing to the layer itself. @@ -601,20 +600,61 @@ public class GcSnapshot { } private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint, - boolean compositeOnly, boolean forceSrcMode) { + boolean compositeOnly, int forceMode) { Graphics2D originalGraphics = layer.getGraphics(); - // get a Graphics2D object configured with the drawing parameters. - Graphics2D configuredGraphics2D = - paint != null ? - createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) : - (Graphics2D) originalGraphics.create(); + if (paint == null) { + drawOnGraphics((Graphics2D) originalGraphics.create(), drawable, + null /*paint*/, layer); + } else { + ColorFilter_Delegate filter = paint.getColorFilter(); + if (filter == null || !filter.isSupported()) { + // get a Graphics2D object configured with the drawing parameters. + Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint, + compositeOnly, forceMode); + drawOnGraphics(configuredGraphics, drawable, paint, layer); + return; + } + + int width = layer.getImage().getWidth(); + int height = layer.getImage().getHeight(); + + // Create a temporary image to which the color filter will be applied. + BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + Graphics2D imageBaseGraphics = (Graphics2D) image.getGraphics(); + // Configure the Graphics2D object with drawing parameters and shader. + Graphics2D imageGraphics = createCustomGraphics( + imageBaseGraphics, paint, compositeOnly, + AlphaComposite.SRC_OVER); + // get a Graphics2D object configured with the drawing parameters, but no shader. + Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint, + true /*compositeOnly*/, forceMode); + try { + // The main draw operation. + drawable.draw(imageGraphics, paint); + + // Apply the color filter. + filter.applyFilter(imageGraphics, width, height); + + // Draw the tinted image on the main layer. + configuredGraphics.drawImage(image, 0, 0, null); + layer.change(); + } finally { + // dispose Graphics2D objects + imageGraphics.dispose(); + imageBaseGraphics.dispose(); + configuredGraphics.dispose(); + } + } + } + private void drawOnGraphics(Graphics2D g, Drawable drawable, Paint_Delegate paint, + Layer layer) { try { - drawable.draw(configuredGraphics2D, paint); + drawable.draw(g, paint); layer.change(); } finally { - // dispose Graphics2D object - configuredGraphics2D.dispose(); + g.dispose(); } } @@ -685,7 +725,7 @@ public class GcSnapshot { // now draw put the content of the local layer onto the layer, // using the paint information Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint, - true /*alphaOnly*/, false /*forceSrcMode*/); + true /*alphaOnly*/, 0 /*forceMode*/); g.drawImage(mLocalLayer.getImage(), mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom, @@ -701,7 +741,7 @@ public class GcSnapshot { * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. */ private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint, - boolean compositeOnly, boolean forceSrcMode) { + boolean compositeOnly, int forceMode) { // make new one graphics Graphics2D g = (Graphics2D) original.create(); @@ -714,70 +754,73 @@ public class GcSnapshot { RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } + // set the shader first, as it'll replace the color if it can be used it. boolean customShader = false; + if (!compositeOnly) { + customShader = setShader(g, paint); + // set the stroke + g.setStroke(paint.getJavaStroke()); + } + // set the composite. + setComposite(g, paint, compositeOnly || customShader, forceMode); - // get the shader first, as it'll replace the color if it can be used it. - if (compositeOnly == false) { - Shader_Delegate shaderDelegate = paint.getShader(); - if (shaderDelegate != null) { - if (shaderDelegate.isSupported()) { - java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint(); - assert shaderPaint != null; - if (shaderPaint != null) { - g.setPaint(shaderPaint); - customShader = true; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER, - shaderDelegate.getSupportMessage(), - null /*throwable*/, null /*data*/); + return g; + } + + private boolean setShader(Graphics2D g, Paint_Delegate paint) { + Shader_Delegate shaderDelegate = paint.getShader(); + if (shaderDelegate != null) { + if (shaderDelegate.isSupported()) { + java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint(); + assert shaderPaint != null; + if (shaderPaint != null) { + g.setPaint(shaderPaint); + return true; } + } else { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER, + shaderDelegate.getSupportMessage(), + null /*throwable*/, null /*data*/); } + } - // if no shader, use the paint color - if (customShader == false) { - g.setColor(new Color(paint.getColor(), true /*hasAlpha*/)); - } + // if no shader, use the paint color + g.setColor(new Color(paint.getColor(), true /*hasAlpha*/)); - // set the stroke - g.setStroke(paint.getJavaStroke()); - } + return false; + } + private void setComposite(Graphics2D g, Paint_Delegate paint, boolean usePaintAlpha, + int forceMode) { // the alpha for the composite. Always opaque if the normal paint color is used since // it contains the alpha - int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF; - - if (forceSrcMode) { - g.setComposite(AlphaComposite.getInstance( - AlphaComposite.SRC, (float) alpha / 255.f)); - } else { - boolean customXfermode = false; - Xfermode_Delegate xfermodeDelegate = paint.getXfermode(); - if (xfermodeDelegate != null) { - if (xfermodeDelegate.isSupported()) { - Composite composite = xfermodeDelegate.getComposite(alpha); - assert composite != null; - if (composite != null) { - g.setComposite(composite); - customXfermode = true; - } - } else { - Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE, - xfermodeDelegate.getSupportMessage(), - null /*throwable*/, null /*data*/); + int alpha = usePaintAlpha ? paint.getAlpha() : 0xFF; + if (forceMode != 0) { + g.setComposite(AlphaComposite.getInstance(forceMode, (float) alpha / 255.f)); + return; + } + Xfermode_Delegate xfermodeDelegate = paint.getXfermode(); + if (xfermodeDelegate != null) { + if (xfermodeDelegate.isSupported()) { + Composite composite = xfermodeDelegate.getComposite(alpha); + assert composite != null; + if (composite != null) { + g.setComposite(composite); + return; } - } - - // if there was no custom xfermode, but we have alpha (due to a shader and a non - // opaque alpha channel in the paint color), then we create an AlphaComposite anyway - // that will handle the alpha. - if (customXfermode == false && alpha != 0xFF) { - g.setComposite(AlphaComposite.getInstance( - AlphaComposite.SRC_OVER, (float) alpha / 255.f)); + } else { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE, + xfermodeDelegate.getSupportMessage(), + null /*throwable*/, null /*data*/); } } - - return g; + // if there was no custom xfermode, but we have alpha (due to a shader and a non + // opaque alpha channel in the paint color), then we create an AlphaComposite anyway + // that will handle the alpha. + if (alpha != 0xFF) { + g.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, (float) alpha / 255.f)); + } } private void mapRect(AffineTransform matrix, RectF dst, RectF src) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java new file mode 100644 index 0000000..bc53e93 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2014 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 com.android.layoutlib.bridge.impl; + +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.layoutlib.bridge.Bridge; + +import android.graphics.PorterDuff.Mode; +import android.graphics.PorterDuffColorFilter_Delegate; +import android.graphics.PorterDuffXfermode_Delegate; + +import java.awt.AlphaComposite; + +/** + * Provides various utility methods for {@link PorterDuffColorFilter_Delegate} and {@link + * PorterDuffXfermode_Delegate}. + */ +public final class PorterDuffUtility { + + // Make the class non-instantiable. + private PorterDuffUtility() { + } + + /** + * Convert the porterDuffMode from the framework to its corresponding enum. This defaults to + * {@link Mode#SRC_OVER} for invalid modes. + */ + public static Mode getPorterDuffMode(int porterDuffMode) { + Mode[] values = Mode.values(); + if (porterDuffMode >= 0 && porterDuffMode < values.length) { + return values[porterDuffMode]; + } + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null /*data*/); + assert false; + return Mode.SRC_OVER; + } + + /** + * 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. + */ + public static int getAlphaCompositeRule(Mode porterDuffMode) { + switch (porterDuffMode) { + case CLEAR: + return AlphaComposite.CLEAR; + case DARKEN: + break; + case DST: + return AlphaComposite.DST; + case DST_ATOP: + return AlphaComposite.DST_ATOP; + case DST_IN: + return AlphaComposite.DST_IN; + case DST_OUT: + return AlphaComposite.DST_OUT; + case DST_OVER: + return AlphaComposite.DST_OVER; + case LIGHTEN: + break; + case MULTIPLY: + break; + 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; + + } +} |