static inline void process_channel(const fix15_t Cs, fix15_t &Cb) { if (Cs > 0) { const fix15_t tmp = fix15_div(fix15_one - Cb, Cs); if (tmp < fix15_one) { Cb = fix15_one - tmp; return; } } Cb = 0; }
inline void operator() (const fix15_short_t * const src, fix15_short_t * const dst, const fix15_short_t src_opacity) const { #ifndef HEAVY_DEBUG // Skip tile if it can't affect the backdrop const bool skip_empty_src = ! compositefunc.zero_alpha_has_effect; if (skip_empty_src && src_opacity == 0) { return; } #endif // Pixel loop fix15_t Rs,Gs,Bs,as, Rb,Gb,Bb,ab, one_minus_ab; #pragma omp parallel for private(Rs,Gs,Bs,as, Rb,Gb,Bb,ab, one_minus_ab) for (unsigned int i = 0; i < BUFSIZE; i += 4) { // Calculate unpremultiplied source RGB values as = src[i+3]; if (as == 0) { #ifndef HEAVY_DEBUG // Skip pixel if it can't affect the backdrop pixel if (skip_empty_src) { continue; } #endif // Otherwise just avoid the divide-by-zero by assuming the // value before premultiplication was also zero. Rs = Gs = Bs = 0; } else { Rs = fix15_short_clamp(fix15_div(src[i+0], as)); Gs = fix15_short_clamp(fix15_div(src[i+1], as)); Bs = fix15_short_clamp(fix15_div(src[i+2], as)); } #ifdef HEAVY_DEBUG assert(Rs <= fix15_one); assert(Rs >= 0); assert(Gs <= fix15_one); assert(Gs >= 0); assert(Bs <= fix15_one); assert(Bs >= 0); #endif // Calculate unpremultiplied backdrop RGB values if (DSTALPHA) { ab = dst[i+3]; if (ab == 0) { Rb = Gb = Bb = 0; } else { Rb = fix15_short_clamp(fix15_div(dst[i+0], ab)); Gb = fix15_short_clamp(fix15_div(dst[i+1], ab)); Bb = fix15_short_clamp(fix15_div(dst[i+2], ab)); } } else { ab = fix15_one; Rb = dst[i+0]; Gb = dst[i+1]; Bb = dst[i+2]; } #ifdef HEAVY_DEBUG assert(Rb <= fix15_one); assert(Rb >= 0); assert(Gb <= fix15_one); assert(Gb >= 0); assert(Bb <= fix15_one); assert(Bb >= 0); #endif // Apply the colour blend functor blendfunc(Rs, Gs, Bs, Rb, Gb, Bb); // Apply results of the blend in place if (DSTALPHA) { one_minus_ab = fix15_one - ab; Rb = fix15_sumprods(one_minus_ab, Rs, ab, Rb); Gb = fix15_sumprods(one_minus_ab, Gs, ab, Gb); Bb = fix15_sumprods(one_minus_ab, Bs, ab, Bb); } #ifdef HEAVY_DEBUG assert(Rb <= fix15_one); assert(Rb >= 0); assert(Gb <= fix15_one); assert(Gb >= 0); assert(Bb <= fix15_one); assert(Bb >= 0); #endif // Use the blend result as a source, and composite directly into // the destination buffer as premultiplied RGB. compositefunc(Rb, Gb, Bb, fix15_mul(as, src_opacity), dst[i+0], dst[i+1], dst[i+2], dst[i+3]); } }