in display_list/display_list_utils.cc [616:690]
bool DisplayListBoundsCalculator::paint_nops_on_transparency() {
// SkImageFilter::canComputeFastBounds tests for transparency behavior
// This test assumes that the blend mode checked down below will
// NOP on transparent black.
if (image_filter_ && !image_filter_->canComputeFastBounds()) {
return false;
}
// We filter the transparent black that is used for the background of a
// saveLayer and make sure it returns transparent black. If it does, then
// the color filter will leave all area surrounding the contents of the
// save layer untouched out to the edge of the output surface.
// This test assumes that the blend mode checked down below will
// NOP on transparent black.
if (color_filter_ &&
color_filter_->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT) {
return false;
}
if (!blend_mode_) {
return false; // can we query other blenders for this?
}
// Unusual blendmodes require us to process a saved layer
// even with operations outisde the clip.
// For example, DstIn is used by masking layers.
// https://code.google.com/p/skia/issues/detail?id=1291
// https://crbug.com/401593
switch (blend_mode_.value()) {
// For each of the following transfer modes, if the source
// alpha is zero (our transparent black), the resulting
// blended pixel is not necessarily equal to the original
// destination pixel.
// Mathematically, any time in the following equations where
// the result is not d assuming source is 0
case SkBlendMode::kClear: // r = 0
case SkBlendMode::kSrc: // r = s
case SkBlendMode::kSrcIn: // r = s * da
case SkBlendMode::kDstIn: // r = d * sa
case SkBlendMode::kSrcOut: // r = s * (1-da)
case SkBlendMode::kDstATop: // r = d*sa + s*(1-da)
case SkBlendMode::kModulate: // r = s*d
return false;
break;
// And in these equations, the result must be d if the
// source is 0
case SkBlendMode::kDst: // r = d
case SkBlendMode::kSrcOver: // r = s + (1-sa)*d
case SkBlendMode::kDstOver: // r = d + (1-da)*s
case SkBlendMode::kDstOut: // r = d * (1-sa)
case SkBlendMode::kSrcATop: // r = s*da + d*(1-sa)
case SkBlendMode::kXor: // r = s*(1-da) + d*(1-sa)
case SkBlendMode::kPlus: // r = min(s + d, 1)
case SkBlendMode::kScreen: // r = s + d - s*d
case SkBlendMode::kOverlay: // multiply or screen, depending on dest
case SkBlendMode::kDarken: // rc = s + d - max(s*da, d*sa),
// ra = kSrcOver
case SkBlendMode::kLighten: // rc = s + d - min(s*da, d*sa),
// ra = kSrcOver
case SkBlendMode::kColorDodge: // brighten destination to reflect source
case SkBlendMode::kColorBurn: // darken destination to reflect source
case SkBlendMode::kHardLight: // multiply or screen, depending on source
case SkBlendMode::kSoftLight: // lighten or darken, depending on source
case SkBlendMode::kDifference: // rc = s + d - 2*(min(s*da, d*sa)),
// ra = kSrcOver
case SkBlendMode::kExclusion: // rc = s + d - two(s*d), ra = kSrcOver
case SkBlendMode::kMultiply: // r = s*(1-da) + d*(1-sa) + s*d
case SkBlendMode::kHue: // ra = kSrcOver
case SkBlendMode::kSaturation: // ra = kSrcOver
case SkBlendMode::kColor: // ra = kSrcOver
case SkBlendMode::kLuminosity: // ra = kSrcOver
return true;
break;
}
}