Merge "LayoutLib: Support PorterDuffColorFilter" into lmp-preview-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
54c1c0db93
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,11 +42,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.";
|
||||
|
||||
@@ -42,11 +42,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.";
|
||||
|
||||
@@ -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*/);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
// 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*/);
|
||||
}
|
||||
}
|
||||
|
||||
// if no shader, use the paint color
|
||||
if (customShader == false) {
|
||||
g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
|
||||
}
|
||||
|
||||
if (!compositeOnly) {
|
||||
customShader = setShader(g, paint);
|
||||
// set the stroke
|
||||
g.setStroke(paint.getJavaStroke());
|
||||
}
|
||||
// set the composite.
|
||||
setComposite(g, paint, compositeOnly || customShader, 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;
|
||||
return g;
|
||||
}
|
||||
|
||||
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*/);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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_SHADER,
|
||||
shaderDelegate.getSupportMessage(),
|
||||
null /*throwable*/, null /*data*/);
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
// if no shader, use the paint color
|
||||
g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
} else {
|
||||
Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
|
||||
xfermodeDelegate.getSupportMessage(),
|
||||
null /*throwable*/, null /*data*/);
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user