[cairo] RFC v3: Path Effects API

Bill Spitzak spitzak at gmail.com
Tue Oct 18 16:27:19 UTC 2016


On Mon, Oct 17, 2016 at 11:15 AM, Bryce Harrington
<bryce at osg.samsung.com> wrote:
> In September 2013, Henry proposed[0] adding a feature for Gaussian blur
> and shadow, based on work carried in his cairogles branch[1].  The
> proposed API[2] was felt to have too many entry points to the context
> for setting all the various parameters (shadow color and type, blur
> direction, etc.), and Chris suggested[3] coming up with a more generic
> API that would handle path effects in a way more analogous to patterns.
>
> In 2014 I posted[4] a rough cut at such an API, following
> cairo_pattern's API design, and a v2 shortly thereafter[5].  Following
> is a v3 of that proposal, incorporating some of Chris Wilson's suggested
> changes.
>
> In particular, this divides the API into a base class (Effects), and
> sub-class (Path Effects), allowing for future introduction of pen
> effects, material effects, etc.  This common API is intended to
> provide a consistent way of handling all effects in the rendering
> pipeline.
>
> v2:
>   + Add get_data, set_data, reference_count for the cairo_object_t api
>   + Rename enums
> v3:
>   + Path Effects are handled as a subclass of Effects
>
> ---
>
> /*
>  * Effect lifecycle management
>  */
> cairo_public cairo_status_t
> cairo_effect_status (cairo_effect_t *effect);
>
> cairo_public cairo_effect_t *
> cairo_effect_reference (cairo_effect_t *effect);
>
> cairo_public void
> cairo_effect_destroy (cairo_effect_t *effect);
>
> cairo_public unsigned int
> cairo_effect_get_reference_count (cairo_effect_t *effect);
>
> cairo_public void *
> cairo_effect_get_user_data (cairo_effect_t *effect,
>                             const cairo_user_data_key_t *key);
> cairo_public cairo_status_t
> cairo_effect_set_user_data (cairo_effect_t *effect,
>                             const cairo_user_data_key_t *key,
>                             void *user_data,
>                             cairo_destroy_funct_t destroy);
>
> /*
>  * Effect properties
>  */
> typedef enum _cairo_effect_type {
>     CAIRO_EFFECT_TYPE_NONE = 0,
>     CAIRO_EFFECT_TYPE_PATH
> } cairo_effect_type_t;
>
> /* Future types might include:
>  *  CAIRO_EFFECT_TYPE_PEN
>  *  CAIRO_EFFECT_TYPE_MATERIAL
>  *  CAIRO_EFFECT_TYPE_OPERATOR
>  *  CAIRO_EFFECT_TYPE_CLIP
>  *  ...
>  */
>
> cairo_public cairo_effect_type_t
> cairo_effect_get_type (cairo_effect_t *effect);
>
>
>
> /* ---------------------------------------------------------------------- */
>
> /*
>  * Path effect creation
>  *
>  * These create effects of type CAIRO_EFFECT_TYPE_PATH.
>  */
> cairo_public cairo_effect_t *
> cairo_effect_create_drop_shadow_path (double x_offset, double y_offset,
>                                       double x_blur,   double y_blur);
>
> cairo_public cairo_effect_t *
> cairo_effect_create_inset_shadow_path (double x_inset, double y_inset,
>                                        double x_blur,  double y_blur);
>
> /*
>  * Applying path effects to the context
>  */
> cairo_public void
> cairo_set_path_effect (cairo_t *cr, cairo_effect_t *source);
>
> cairo_public cairo_effect_t *
> cairo_get_path_effect (cairo_t *cr);
>
> /*
>  * Path effect properties
>  */
> typedef enum _cairo_path_effect_type {
>     CAIRO_PATH_EFFECT_NONE = 0,
>     CAIRO_PATH_EFFECT_DROP_SHADOW,
>     CAIRO_PATH_EFFECT_INSET_SHADOW
> } cairo_path_effect_type_t;
>
> /* Future path effect types could include:
>  *  CAIRO_PATH_EFFECT_PATTERN
>  *  CAIRO_PATH_EFFECT_UNION
>  *  CAIRO_PATH_EFFECT_DIFFERENCE
>  *  CAIRO_PATH_EFFECT_INTERSECTION
>  *  ...
>  */
>
> cairo_public cairo_path_effect_type_t
> cairo_path_effect_get_subtype (cairo_effect_t *effect);
>
> cairo_public void
> cairo_path_effect_set_rgba (cairo_path_effect_t *path_effect,
>                             double red, double green, double blue,
>                             double alpha);
>
> Internally, both the effect type and subtype can be tracked in a single
> property, e.g.:
>
>     type = CAIRO_EFFECT_TYPE_PATH << 24 | CAIRO_PATH_EFFECT_DROP_SHADOW;
>
>
> Henry's API proposal included provision for shadow caching by the
> application.  That certainly made a huge difference in the demos, so
> maybe it's still going to be needed.  An idea is to provide a
> backend/user preference as to whether effects should be cached or
> applied on the fly, e.g. cairo_effect_set_cached.
>
> Bryce
>
> 0:  https://lists.cairographics.org/archives/cairo/2013-September/024596.html
> 1:  The cairogles branch is no longer available publically.  The private
>     branch is at https://github.com/SRA-SiliconValley/cairogles
> 2:  https://lists.cairographics.org/archives/cairo/2013-September/024598.html
> 3:  https://lists.cairographics.org/archives/cairo/2013-September/024597.html
> 4:  https://lists.cairographics.org/archives/cairo/2014-October/025748.html
> 5:  https://lists.cairographics.org/archives/cairo/2014-October/025766.html
> --
> cairo mailing list
> cairo at cairographics.org
> https://lists.cairographics.org/mailman/listinfo/cairo

Seems to me there is excessive namespacing here. There is no need for
an "effect type", it should just be clear from the effect description
whether it has an effect on stroke, fill, or text, or which parts of
the inputs it changes.

Possibly you are thinking that the effects would be mutually exclusive
and that the type is to identify the mutually exclusive set, but that
seems really limiting and I think you will end up with one "type" for
each effect. Instead just allow arbitrary sets of effects to be
active. If two effects can't be done at the same time, it is either an
error, or one of them takes precedence.

I would also remove "PATH" from all your enumerations and function
names. Some of them are really confusing now, for instance
"cairo_effect_create_inset_shadow_path" does not create a path, it
creates an effect.


More information about the cairo mailing list