diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/opts/SkBlitMask_opts.h | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/src/opts/SkBlitMask_opts.h b/src/opts/SkBlitMask_opts.h index 9129560ef4..d66323a8b0 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 |