Linear gradient on SKIA

200 views
Skip to first unread message

Dilip Dilip

unread,
Jun 29, 2009, 11:18:29 AM6/29/09
to skia-d...@googlegroups.com, re...@android.com
Is LinearGradient with 2 colors working on SKIA ?
Can anybody explain me how to use it? 
I tried it out but i am not getting the second color properly.  I tried with green ( with alpha zero) and black (with alpha 1 ) .

Thanks in Advance.

Best Regards,
  Vivek R

Mike Reed

unread,
Jun 29, 2009, 8:04:39 PM6/29/09
to Dilip Dilip, skia-d...@googlegroups.com
They should be working. If you include a code-snippet of how you are
trying to construct the gradient, and what you are seeing, we may be
able to help.

Dilip Dilip

unread,
Jun 30, 2009, 1:00:51 AM6/30/09
to skia-d...@googlegroups.com, Mike Reed
http://hixie.ch/tests/adhoc/html/canvas/042.html
What i could see for above test case is that, the output on mozilla is different from google chrome.
I am attaching the screen shots of the  outputs of mozilla , google chrome.. Please tell me which one is correct.

Thanks and Regards,
  Vivek R
chrome_canvas_042.png
mozilla_canvas.png

Mike Reed

unread,
Jul 1, 2009, 8:08:51 PM7/1/09
to Dilip Dilip, skia-d...@googlegroups.com
Wow, what a great bug! Thanks you for finding this. I understand the
problem now, and I work on a fix.

Dilip Dilip

unread,
Jul 1, 2009, 10:59:03 PM7/1/09
to Mike Reed, skia-d...@googlegroups.com
Thanks mike. Even I am trying to fix this bug. Let me know if you fix this one. 

Thanks and Regards,
  Vivek R

Mike Reed

unread,
Jul 2, 2009, 1:26:54 AM7/2/09
to Dilip Dilip, skia-d...@googlegroups.com
The problem is that skia's gradient converts the colors to
premultiplied before they are interpolated. The fix is to interpolate
as unpremultiplied, and the convert to premultiplied afterwards. I
will work on a fix as well.

deepak garg

unread,
Jul 2, 2009, 8:18:46 AM7/2/09
to skia-d...@googlegroups.com, re...@android.com
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

Mike Reed

unread,
Jul 2, 2009, 11:10:39 AM7/2/09
to deepak garg, skia-d...@googlegroups.com
I have checked in a patch to SkGradientShader.cpp. Let me know how
that works for you.

Dilip Dilip

unread,
Jul 6, 2009, 1:17:06 AM7/6/09
to skia-d...@googlegroups.com, Mike Reed
Thanks Mike.
I have checked it. Its working fine.

Best Regards,
  Vivek R

L2000

unread,
Jun 19, 2024, 7:24:42 AMJun 19
to skia-discuss
Hi
   I am facing  linear gradient problem for two colors like you mentioned above. Here is my code :

unsigned int red = 50, green= 217, blue= 119 ;

SkScalar positions[] = {0.0f, 1.0f};

SkPoint points[] = { SkPoint::Make(drawingRect.fLeft, drawingRect.fTop) ,

                                    SkPoint::Make(drawingRect.fRight, drawingRect.fTop) };

SkColor color1 = SkColorSetRGB(red, green, blue);

SkColor color2 = SkColorSetARGB(20,red, green, blue);

SkColor colors[] = {color1, color2};

sk_sp<SkShader> linearGradient = SkGradientShader::MakeLinear(points, colors, positions, 2, SkTileMode::kClamp);

SkPaint paint;

paint.setStyle(SkPaint::kFill_Style);

paint.setShader(linearGradient);

canvas->drawRect(drawingRect, paint);

My Result :                                                 Expected Result :
Screenshot 2024-06-19 at 4.48.12 PM.png                    Screenshot 2024-06-19 at 4.47.16 PM.png

But when I provide colors as SkColor colors[] =  {SK_ColorGREEN, SK_ColorWHITE};, colors are distributed correctly like below :
Screenshot 2024-06-19 at 4.46.58 PM.png

What shoud i do to get the expected result?     

Regards,
Priya          

Reply all
Reply to author
Forward
0 new messages