[cairo] cairo-1.13 finally opens

Henry (Yu) Song - SISA henry.song at samsung.com
Thu Sep 5 16:43:36 PDT 2013


Hi, Bill


Draw a drop shadow is in the following sequence

/* set up shadow spec */
cairo_set_shadow (cr, CAIRO_SHADOW_DROP);
cairo_set_shadow_rgba (cr, ....);
cairo_set_shadow_offset (cr, x, y);
cairo_set_shadow_blur (cr, blur_x, blur_y);

/* setup draw path */
cairo_arc (cr, ......);
cairo_set_source_rgba (cr, ......);

/* draw both shadow and object */
cairo_fill/stroke (cr); 


What implementation does internally is

1. draw the path with shadow offsets to a temp surface with source pattern
2. blur the temp surface
3. use the blurred temp surface as mask and shadow color as source, use current operator, onto the destination
4. draw the object with path with current operator onto the destination.


You can also draw custom drop shadow, as following example

/* set up shadow spec */
cairo_set_shadow (cr, CAIRO_SHADOW_DROP);
cairo_set_shadow_rgba (cr, ....);
cairo_set_shadow_offset (cr, x, y);
cairo_set_shadow_blur (cr, blur_x, blur_y);
cairo_set_draw_shadow_only (cr, TRUE);  // this inform cairo to draw shadow with current path without drawing the object itself */

/* setup draw path for a custom shadow */
cairo_arc (cr, ......);

/* draw shadow only with current path */
cairo_fill/stroke (cr);  

/* disable shadow and draw object */
cairo_set_shadow (cr, CAIRO_SHADOW_NONE); /* this disables shadow */
cairo_rectangle (cr, ......);
cairo_set_source_rgba (cr, .....);
/* draw object itself */
cairo_fill/stroke (cr);

Inset shadow is a different story, inset shadow requires blur inwards instead of outwards.  so the ugly API I come up with is used for draw a custom shadow path, tells cairo to blur it inwards. and app uses clip to bound the drawing area.  This is only if you want to have a custom shadow path for inset shadow.  If you don't need a custom shadow path,  it is drawn like example above. for example

/* set up shadow spec */
cairo_set_shadow (cr, CAIRO_SHADOW_INSET);
cairo_set_shadow_rgba (cr, ....);
cairo_set_shadow_offset (cr, x, y);
cairo_set_shadow_blur (cr, blur_x, blur_y);

/* setup draw path */
cairo_arc (cr, ......);
cairo_set_source_rgba (cr, ......);

/* draw both shadow and object */
cairo_fill/stroke (cr); 

This will give a object with inset shadow inside the object path.  What it does internally

1. draw object itself
2. create a temp surface with shadow color;
3. draw the path with CLEAR operator
4. blur the temp surface
5. cairo_fill/stroke with temp surface as source, and current operator on to the destination

Thanks

________________________________________
From: Bill Spitzak [spitzak at gmail.com]
Sent: Thursday, September 05, 2013 3:59 PM
To: Henry (Yu) Song - SISA
Cc: Chris Wilson; cairo at cairographics.org
Subject: Re: [cairo] cairo-1.13 finally opens

Henry (Yu) Song - SISA wrote:

> 5. as an optimization, the image to be blurred is scaled down first and scale up using bilinear sampling - similar to skia

Yes this can be a big win. Limit the downscale to powers of 2 however.

> The shadow parameters (blur, offset) are not affected by CTM (recall somewhere in html/css spec that shadow blur/offset should not be affected by ctm).

This is probably not a good idea for matching the rest of cairo. However
it can do "locking" of the blur and offset. If the caller wants them in
output pixels, they push the state, reset the transform to the identity,
set the blur/offset, then pop the state. The values are transformed to
the final result at the moment they are set by the CTM and thus "lock".
I think everybody decided cairo would have been better if this was true
for line widths, and there are proposals to add an option to make this
the default.

A w/h can be transformed to an "approximate" w/h in another space by
something that produces the correct area of the w*h rectangle, and
matches for 90 degree rotations. I posted some code to do this before

> CSS3 only defines blur, offset, and spread.  The current implementation of shadow is much more flexible than that, it allows arbitrary shadow path to be drawn similar to osx's CALayer.shadowPath

My problem here is the CSS3 description uses filtering of a mask image,
rather than altering the path. Correctly altering the path is really
complex and won't work if the alpha is from an image (as the html
examples I saw seemed to want).

> Regarding to different operators with shadow.  The drop shadow implementation follows what HTML/css spec, it draws drop shadow with current compositing operator, then draw drawing itself with again the current operator.  The problem is the inset shadow.  I am not clear about that with operators other than OVER.

So you don't think there would be a problem if drawing the shadow and
the object were two different cairo calls? That seems the easiest way to
reduce the amount of cairo api.

It looks to me like inset shadows draw the inverse of the outset shadows
clipped to the path. I guess this would have to be a different call, and
it would be done after the object is drawn.


More information about the cairo mailing list