Index: src/opts/SkBlitMask_opts.h |
diff --git a/src/opts/SkBlitMask_opts.h b/src/opts/SkBlitMask_opts.h |
index 9129560ef4de7d84ceda58786d2cdb304cda17a7..d66323a8b01ac259d16278c698e7cd00807a1f07 100644 |
--- a/src/opts/SkBlitMask_opts.h |
+++ b/src/opts/SkBlitMask_opts.h |
@@ -12,11 +12,10 @@ |
namespace SK_OPTS_NS { |
-static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, |
- const SkAlpha* mask, size_t maskRB, |
- SkColor color, int w, int h) { |
+static void blit_mask_d32_a8_general(SkPMColor* dst, size_t dstRB, |
+ const SkAlpha* mask, size_t maskRB, |
+ SkColor color, int w, int h) { |
auto s = Sk4px::DupPMColor(SkPreMultiplyColor(color)); |
- |
auto fn = [&](const Sk4px& d, const Sk4px& aa) { |
// = (s + d(1-sa))aa + d(1-aa) |
// = s*aa + d(1-sa*aa) |
@@ -24,7 +23,26 @@ static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, |
right = d.approxMulDiv255(left.alphas().inv()); |
return left + right; // This does not overflow (exhaustively checked). |
}; |
+ while (h --> 0) { |
+ Sk4px::MapDstAlpha(w, dst, mask, fn); |
+ dst += dstRB / sizeof(*dst); |
+ mask += maskRB / sizeof(*mask); |
+ } |
+} |
+// As above, but made slightly simpler by requiring that color is opaque. |
+static void blit_mask_d32_a8_opaque(SkPMColor* dst, size_t dstRB, |
+ const SkAlpha* mask, size_t maskRB, |
+ SkColor color, int w, int h) { |
+ SkASSERT(SkColorGetA(color) == 0xFF); |
+ auto s = Sk4px::DupPMColor(SkPreMultiplyColor(color)); |
+ auto fn = [&](const Sk4px& d, const Sk4px& aa) { |
+ // = (s + d(1-sa))aa + d(1-aa) |
+ // = s*aa + d(1-sa*aa) |
+ // ~~~> |
+ // = s*aa + d(1-aa) |
+ return s.approxMulDiv255(aa) + d.approxMulDiv255(aa.inv()); |
+ }; |
while (h --> 0) { |
Sk4px::MapDstAlpha(w, dst, mask, fn); |
dst += dstRB / sizeof(*dst); |
@@ -32,6 +50,37 @@ static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, |
} |
} |
+// Same as _opaque, but assumes color == SK_ColorBLACK, a very common and even simpler case. |
+static void blit_mask_d32_a8_black(SkPMColor* dst, size_t dstRB, |
+ const SkAlpha* mask, size_t maskRB, |
+ int w, int h) { |
+ auto fn = [](const Sk4px& d, const Sk4px& aa) { |
+ // = (s + d(1-sa))aa + d(1-aa) |
+ // = s*aa + d(1-sa*aa) |
+ // ~~~> |
+ // a = 1*aa + d(1-1*aa) = aa + d(1-aa) |
+ // c = 0*aa + d(1-1*aa) = d(1-aa) |
+ return aa.zeroColors() + d.approxMulDiv255(aa.inv()); |
+ }; |
+ while (h --> 0) { |
+ Sk4px::MapDstAlpha(w, dst, mask, fn); |
+ dst += dstRB / sizeof(*dst); |
+ mask += maskRB / sizeof(*mask); |
+ } |
+} |
+ |
+static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, |
+ const SkAlpha* mask, size_t maskRB, |
+ SkColor color, int w, int h) { |
+ if (color == SK_ColorBLACK) { |
+ blit_mask_d32_a8_black(dst, dstRB, mask, maskRB, w, h); |
+ } else if (SkColorGetA(color) == 0xFF) { |
+ blit_mask_d32_a8_opaque(dst, dstRB, mask, maskRB, color, w, h); |
+ } else { |
+ blit_mask_d32_a8_general(dst, dstRB, mask, maskRB, color, w, h); |
+ } |
+} |
+ |
} // SK_OPTS_NS |
#endif//SkBlitMask_opts_DEFINED |