kCoeffCount
};
- /** If the xfermode can be expressed as an equation using the coefficients
- in Coeff, then asCoeff() returns true, and sets (if not null) src and
- dst accordingly.
-
- result = src_coeff * src_color + dst_coeff * dst_color;
-
- As examples, here are some of the porterduff coefficients
-
- MODE SRC_COEFF DST_COEFF
- clear zero zero
- src one zero
- dst zero one
- srcover one isa
- dstover ida one
- */
- virtual bool asCoeff(Coeff* src, Coeff* dst) const;
-
- /**
- * The same as calling xfermode->asCoeff(..), except that this also checks
- * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
- */
- static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst);
-
/** List of predefined xfermodes.
The algebra for the modes uses the following symbols:
Sa, Sc - source alpha and color
return AsMode(xfer, mode);
}
+ /**
+ * Returns whether or not the xfer mode can support treating coverage as alpha
+ */
+ virtual bool supportsCoverageAsAlpha() const;
+
+ /**
+ * The same as calling xfermode->supportsCoverageAsAlpha(), except that this also checks if
+ * the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+ */
+ static bool SupportsCoverageAsAlpha(const SkXfermode* xfer);
+
+ enum SrcColorOpacity {
+ // The src color is known to be opaque (alpha == 255)
+ kOpaque_SrcColorOpacity = 0,
+ // The src color is known to be fully transparent (color == 0)
+ kTransparentBlack_SrcColorOpacity = 1,
+ // The src alpha is known to be fully transparent (alpha == 0)
+ kTransparentAlpha_SrcColorOpacity = 2,
+ // The src color opacity is unknown
+ kUnknown_SrcColorOpacity = 3
+ };
+
+ /**
+ * Returns whether or not the result of the draw with the xfer mode will be opaque or not. The
+ * input to this call is an enum describing known information about the opacity of the src color
+ * that will be given to the xfer mode.
+ */
+ virtual bool isOpaque(SrcColorOpacity opacityType) const;
+
+ /**
+ * The same as calling xfermode->isOpaque(...), except that this also checks if
+ * the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
+ */
+ static bool IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType);
+
/** Implemented by a subclass to support use as an image filter in the GPU backend. When used as
an image filter the xfer mode blends the source color against a background texture rather
than the destination. It is implemented as a fragment processor. This can be called with
return x + SkScalarHalf(y);
}
-static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
- SkXfermode::Coeff dc;
- if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) {
- return false;
- }
-
- switch (dc) {
- case SkXfermode::kOne_Coeff:
- case SkXfermode::kISA_Coeff:
- case SkXfermode::kISC_Coeff:
- return true;
- default:
- return false;
- }
-}
-
bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
SkScalar* coverage) {
SkASSERT(strokeWidth > 0);
if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
if (SK_Scalar1 == coverage) {
paint.writable()->setStrokeWidth(0);
- } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
+ } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) {
U8CPU newAlpha;
#if 0
newAlpha = SkToU8(SkScalarRoundToInt(coverage *
#include "SkShader.h"
bool isPaintOpaque(const SkPaint* paint, SkPaintBitmapOpacity contentType) {
- // TODO: SkXfermode should have a virtual isOpaque method, which would
- // make it possible to test modes that do not have a Coeff representation.
-
if (!paint) {
return contentType != kUnknown_SkPaintBitmapOpacity;
}
-
- SkXfermode::Coeff srcCoeff, dstCoeff;
- if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
- if (SkXfermode::kDA_Coeff == srcCoeff || SkXfermode::kDC_Coeff == srcCoeff ||
- SkXfermode::kIDA_Coeff == srcCoeff || SkXfermode::kIDC_Coeff == srcCoeff) {
- return false;
- }
- switch (dstCoeff) {
- case SkXfermode::kZero_Coeff:
- return true;
- case SkXfermode::kISA_Coeff:
- if (paint->getAlpha() != 255) {
- break;
- }
- if (contentType == kUnknown_SkPaintBitmapOpacity) {
- break;
- } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
- break;
- }
- if (paint->getColorFilter() &&
- ((paint->getColorFilter()->getFlags() &
- SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
- break;
- }
- return true;
- case SkXfermode::kSA_Coeff:
- if (paint->getAlpha() != 0) {
- break;
- }
- if (paint->getColorFilter() &&
- ((paint->getColorFilter()->getFlags() &
- SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
- break;
- }
- return true;
- case SkXfermode::kSC_Coeff:
- if (paint->getColor() != 0) { // all components must be 0
- break;
- }
- if (contentType != kNoBitmap_SkPaintBitmapOpacity || paint->getShader()) {
- break;
- }
- if (paint->getColorFilter() && (
- (paint->getColorFilter()->getFlags() &
- SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
- break;
- }
- return true;
- default:
- break;
+ SkXfermode::SrcColorOpacity opacityType = SkXfermode::kUnknown_SrcColorOpacity;
+
+ if (!paint->getColorFilter() ||
+ ((paint->getColorFilter()->getFlags() &
+ SkColorFilter::kAlphaUnchanged_Flag) != 0)) {
+ if (0xff == paint->getAlpha() &&
+ contentType != kUnknown_SkPaintBitmapOpacity &&
+ (!paint->getShader() || paint->getShader()->isOpaque())) {
+ opacityType = SkXfermode::kOpaque_SrcColorOpacity;
+ } else if (0 == paint->getColor() &&
+ contentType == kNoBitmap_SkPaintBitmapOpacity &&
+ !paint->getShader()) {
+ opacityType = SkXfermode::kTransparentBlack_SrcColorOpacity;
+ } else if (0 == paint->getAlpha()) {
+ opacityType = SkXfermode::kTransparentAlpha_SrcColorOpacity;
}
}
- return false;
+
+ return SkXfermode::IsOpaque(paint->getXfermode(), opacityType);
}
bool isPaintOpaque(const SkPaint* paint, const SkBitmap* bmpReplacesShader) {
///////////////////////////////////////////////////////////////////////////////
-bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
- return false;
-}
-
bool SkXfermode::asMode(Mode* mode) const {
return false;
}
}
}
+bool SkXfermode::supportsCoverageAsAlpha() const {
+ return false;
+}
+
+bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
+ return false;
+}
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
return true;
}
-bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
+bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
if (CANNOT_USE_COEFF == fSrcCoeff) {
return false;
}
- if (sc) {
- *sc = fSrcCoeff;
+ switch (fDstCoeff) {
+ case SkXfermode::kOne_Coeff:
+ case SkXfermode::kISA_Coeff:
+ case SkXfermode::kISC_Coeff:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
+ if (CANNOT_USE_COEFF == fSrcCoeff) {
+ return false;
}
- if (dc) {
- *dc = fDstCoeff;
+
+ if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
+ SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
+ return false;
}
- return true;
+
+ switch (fDstCoeff) {
+ case SkXfermode::kZero_Coeff:
+ return true;
+ case SkXfermode::kISA_Coeff:
+ return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
+ case SkXfermode::kSA_Coeff:
+ return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
+ SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
+ case SkXfermode::kSC_Coeff:
+ return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
+ default:
+ return false;
+ }
+
}
void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
return xfer->asMode(mode);
}
-bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
- if (NULL == xfer) {
- return ModeAsCoeff(kSrcOver_Mode, src, dst);
- }
- return xfer->asCoeff(src, dst);
-}
-
bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
// if xfer==null then the mode is srcover
Mode m = kSrcOver_Mode;
return mode == m;
}
+bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
+ // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
+ if (!xfer) {
+ return true;
+ }
+
+ return xfer->supportsCoverageAsAlpha();
+}
+
+bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
+ // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
+ if (!xfer) {
+ return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
+ }
+
+ return xfer->isOpaque(opacityType);
+}
+
///////////////////////////////////////////////////////////////////////////////
//////////// 16bit xfermode procs
bool asMode(Mode* mode) const SK_OVERRIDE;
- bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE;
+ bool supportsCoverageAsAlpha() const SK_OVERRIDE;
+
+ bool isOpaque(SkXfermode::SrcColorOpacity opacityType) const SK_OVERRIDE;
#if SK_SUPPORT_GPU
virtual bool asFragmentProcessor(GrFragmentProcessor**,