Hi,
@Mike, u were right about the premultiplyargb thing, SKIA premultiplies ARGB (think its more of an optimization to avoid per pixel alpha multiplication) so I removed the color conversion from SkPreMultiplyARGB,
new code:
SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
if (a != 255) {
#if 0
unsigned scale = SkAlpha255To256(a);
r = SkAlphaMul(r, scale);
g = SkAlphaMul(g, scale);
b = SkAlphaMul(b, scale);
#else
// r = SkMulDiv255Round(r, a);
// g = SkMulDiv255Round(g, a);
// b = SkMulDiv255Round(b, a);
#endif
}
return SkPackARGB32(a, r, g, b);
}
but doing this alone doesn't solve the problem rather generates strange outputs, I think that's happening because SKIA ignores the source alpha while rendering (optimization again!) so i ve changed a blitting function in SkColorPriv.h to the following it's basically now taking source alpha also into consideration.
Code:
static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
unsigned sr = SkGetPackedR32(src);
unsigned sg = SkGetPackedG32(src);
unsigned sb = SkGetPackedB32(src);
unsigned dr = SkGetPackedR16(dst);
unsigned dg = SkGetPackedG16(dst);
unsigned db = SkGetPackedB16(dst);
unsigned isa = 255 - SkGetPackedA32(src);
dr = (SkMul16ShiftRound(sr>>3, SkGetPackedA32(src), SK_R16_BITS) + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
dg = (SkMul16ShiftRound(sg>>2, SkGetPackedA32(src), SK_G16_BITS) + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
db = (SkMul16ShiftRound(sb>>3, SkGetPackedA32(src), SK_B16_BITS) + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
/* dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);*/
return SkPackRGB16(dr, dg, db);
}
after these changes i am getting the correct output. Though I think i has affected the performance, I have not measured that though.
An ideal solution should be where SKIA ignores the premultiplication for gradients and doesn't ignore source alpha while rendering gradients. I think this applies for other xfermodes also.
waiting for your comments
regards
deepak