template <DstType D> void srcover_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f& src, int count, const SkAlpha aa[]) { Sk4f s4 = Sk4f::Load(src.fVec); Sk4f scale = Sk4f(1 - get_alpha(s4)); if (aa) { for (int i = 0; i < count; ++i) { unsigned a = aa[i]; if (0 == a) { continue; } Sk4f d4 = load_dst<D>(dst[i]); Sk4f r4; if (a != 0xFF) { s4 = scale_by_coverage(s4, a); r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); } else { r4 = s4 + d4 * scale; } dst[i] = store_dst<D>(r4); } } else { for (int i = 0; i < count; ++i) { Sk4f d4 = load_dst<D>(dst[i]); Sk4f r4 = s4 + d4 * scale; dst[i] = store_dst<D>(r4); } } }
static void srcover_srgb_dst_1(const SkXfermode*, uint32_t dst[], const SkPM4f* src, int count, const SkAlpha aa[]) { Sk4f s4 = src->to4f_pmorder(); Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); if (aa) { for (int i = 0; i < count; ++i) { unsigned a = aa[i]; if (0 == a) { continue; } Sk4f d4 = srgb_4b_to_linear_unit(dst[i]); Sk4f r4; if (a != 0xFF) { const Sk4f s4_aa = scale_by_coverage(s4, a); r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); } else { r4 = s4 + d4 * dst_scale; } dst[i] = to_4b(linear_unit_to_srgb_255f(r4)); } } else { while (count >= 4) { auto d = load_4_srgb(dst); auto s = Sk4x4f{{ src->r() }, { src->g() }, { src->b() }, { src->a() }}; #if defined(SK_PMCOLOR_IS_BGRA) SkTSwap(s.r, s.b); #endif auto invSA = 1.0f - s.a; auto r = s.r + d.r * invSA, g = s.g + d.g * invSA, b = s.b + d.b * invSA, a = s.a + d.a * invSA; store_4_srgb(dst, Sk4x4f{r,g,b,a}); count -= 4; dst += 4; } for (int i = 0; i < count; ++i) { Sk4f d4 = srgb_4b_to_linear_unit(dst[i]); dst[i] = to_4b(linear_unit_to_srgb_255f(s4 + d4 * dst_scale)); } } }
template <DstType D> void srcover_n(const SkXfermode*, uint32_t dst[], const SkPM4f src[], int count, const SkAlpha aa[]) { if (aa) { for (int i = 0; i < count; ++i) { unsigned a = aa[i]; if (0 == a) { continue; } Sk4f s4 = src[i].to4f_pmorder(); Sk4f d4 = load_dst<D>(dst[i]); if (a != 0xFF) { s4 = scale_by_coverage(s4, a); } Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); dst[i] = store_dst<D>(r4); } } else { while (count >= 4 && D == kSRGB_Dst) { auto d = load_4_srgb(dst); auto s = Sk4x4f::Transpose(src->fVec); #if defined(SK_PMCOLOR_IS_BGRA) SkTSwap(s.r, s.b); #endif auto invSA = 1.0f - s.a; auto r = s.r + d.r * invSA, g = s.g + d.g * invSA, b = s.b + d.b * invSA, a = s.a + d.a * invSA; store_4_srgb(dst, Sk4x4f{r,g,b,a}); count -= 4; dst += 4; src += 4; } for (int i = 0; i < count; ++i) { Sk4f s4 = src[i].to4f_pmorder(); Sk4f d4 = load_dst<D>(dst[i]); Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); dst[i] = store_dst<D>(r4); } } }
static void srcover_linear_dst_1(const SkXfermode*, uint32_t dst[], const SkPM4f* src, int count, const SkAlpha aa[]) { const Sk4f s4 = src->to4f_pmorder(); const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); if (aa) { for (int i = 0; i < count; ++i) { unsigned a = aa[i]; if (0 == a) { continue; } Sk4f d4 = Sk4f_fromL32(dst[i]); Sk4f r4; if (a != 0xFF) { Sk4f s4_aa = scale_by_coverage(s4, a); r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); } else { r4 = s4 + d4 * dst_scale; } dst[i] = Sk4f_toL32(r4); } } else { const Sk4f s4_255 = s4 * Sk4f(255) + Sk4f(0.5f); // +0.5 to pre-bias for rounding while (count >= 4) { Sk4f d0 = to_4f(dst[0]); Sk4f d1 = to_4f(dst[1]); Sk4f d2 = to_4f(dst[2]); Sk4f d3 = to_4f(dst[3]); Sk4f_ToBytes((uint8_t*)dst, s4_255 + d0 * dst_scale, s4_255 + d1 * dst_scale, s4_255 + d2 * dst_scale, s4_255 + d3 * dst_scale); dst += 4; count -= 4; } for (int i = 0; i < count; ++i) { Sk4f d4 = to_4f(dst[i]); dst[i] = to_4b(s4_255 + d4 * dst_scale); } } }