Draw a brush stroke along the masks of a block with the stroke effect.
The stroke effect draws a brush stroke along the path of a mask. It uses the same effect API as all other effects: createEffect, the property setters and appendEffect. Scenes that use this effect do not open in earlier versions of CE.SDK. The example draws three strokes along an ellipse mask: over the image, on a transparent block, and along half of the path. For the general effect API, see Apply a Filter or Effect.
Adding a Mask#
The stroke follows a mask, so each block needs a mask first. createMask creates the mask, setShape gives it an ellipse shape and appendMask attaches it to the block. A mask normally cuts the block to its shape. The "None" mode keeps the whole block and only gives the stroke its path. For more about masks, see Masks and Mattes.
// An ellipse mask in the "None" mode gives the stroke a path without cutting the blockfun addEllipseMask(block: DesignBlock) { val mask = engine.block.createMask() engine.block.setShape(block = mask, shape = engine.block.createShape(ShapeType.Ellipse)) engine.block.setEnum(block = mask, property = "mask/mode", value = "None") engine.block.appendMask(block = block, maskBlock = mask)}
addEllipseMask(overImageBlock)addEllipseMask(transparentBlock)addEllipseMask(halfStrokeBlock)A mask in the default "Add" mode cuts the block to the ellipse. It also cuts the outer half of the stroke.
Drawing the Stroke#
color sets the stroke color. brushSize is the brush radius in design units, so the line is twice as wide. hardness sets how sharp the edge is, from 0 (soft) to 1 (hard). The stroke draws along the first mask of the block, because maskIndex is 0 by default.
// A hard yellow brush stroke, 12 design units wide, along the first maskval stroke = engine.block.createEffect(EffectType.Stroke)engine.block.setColor(block = stroke, property = "effect/stroke/color", value = Color.fromRGBA(r = 1F, g = 0.8F, b = 0.1F))engine.block.setFloat(block = stroke, property = "effect/stroke/brushSize", value = 6F)engine.block.setFloat(block = stroke, property = "effect/stroke/hardness", value = 1F)engine.block.appendEffect(block = overImageBlock, effectBlock = stroke)Choosing the Mask and the Paint Style#
maskIndex picks the mask to stroke. An index outside the mask list draws no stroke. Set allMasks to true to stroke every mask of the block. paintStyle is "OnOriginalImage" to draw over the fill, or "OnTransparent" to draw only the stroke. Here the second block shows only the yellow ring.
// Stroke every mask of the block, and draw only the stroke without the imageval transparentStroke = engine.block.createEffect(EffectType.Stroke)engine.block.setBoolean(block = transparentStroke, property = "effect/stroke/allMasks", value = true)engine.block.setEnum(block = transparentStroke, property = "effect/stroke/paintStyle", value = "OnTransparent")engine.block.setColor(block = transparentStroke, property = "effect/stroke/color", value = Color.fromRGBA(r = 1F, g = 0.8F, b = 0.1F))engine.block.setFloat(block = transparentStroke, property = "effect/stroke/brushSize", value = 6F)engine.block.appendEffect(block = transparentBlock, effectBlock = transparentStroke)Trimming the Stroke#
start and end draw only a part of each mask path, as fractions of its length from 0 to 1. A start after end swaps the two values. Here the third block gets half a ring.
// Draw only the first half of the mask pathval halfStroke = engine.block.createEffect(EffectType.Stroke)engine.block.setInt(block = halfStroke, property = "effect/stroke/maskIndex", value = 0)engine.block.setFloat(block = halfStroke, property = "effect/stroke/start", value = 0F)engine.block.setFloat(block = halfStroke, property = "effect/stroke/end", value = 0.5F)engine.block.setColor(block = halfStroke, property = "effect/stroke/color", value = Color.fromRGBA(r = 1F, g = 0.8F, b = 0.1F))engine.block.setFloat(block = halfStroke, property = "effect/stroke/brushSize", value = 6F)engine.block.appendEffect(block = halfStrokeBlock, effectBlock = halfStroke)Exporting the Result#
We export the page as a PNG to see the three strokes.
val previewPng = engine.block.export(block = page, mimeType = MimeType.PNG)Troubleshooting#
- The stroke does not show: add a mask to the block, and check that
maskIndexpoints to it. AbrushSizeof 0 also draws nothing. - The block shows only the inside of the mask: set
mask/modeto"None". - The stroke is half as wide as expected: the mask is in the
"Add"mode and cuts the outer half of the stroke. Setmask/modeto"None".
API Reference#
| Method | Description |
|---|---|
engine.block.createMask() |
Create a mask for the stroke path |
engine.block.createShape(type=ShapeType.Ellipse) |
Create the ellipse shape of the mask |
engine.block.setShape(block=_, shape=_) |
Give the mask its shape |
engine.block.setEnum(block=_, property="mask/mode", value=_) |
Set the mode of the mask |
engine.block.appendMask(block=_, maskBlock=_) |
Attach the mask to a block |
engine.block.createEffect(type=EffectType.Stroke) |
Create a stroke effect |
engine.block.setColor(block=_, property="effect/stroke/color", value=_) |
Set the stroke color |
engine.block.setFloat(block=_, property="effect/stroke/brushSize", value=_) |
Set the brush radius in design units |
engine.block.setFloat(block=_, property="effect/stroke/hardness", value=_) |
Set how sharp the brush edge is |
engine.block.setBoolean(block=_, property="effect/stroke/allMasks", value=_) |
Stroke every mask of the block |
engine.block.setEnum(block=_, property="effect/stroke/paintStyle", value=_) |
Draw over the fill or on transparency |
engine.block.setInt(block=_, property="effect/stroke/maskIndex", value=_) |
Pick the mask to stroke |
engine.block.setFloat(block=_, property="effect/stroke/start", value=_) |
Set where the stroke starts on each mask path |
engine.block.setFloat(block=_, property="effect/stroke/end", value=_) |
Set where the stroke ends on each mask path |
engine.block.appendEffect(block=_, effectBlock=_) |
Add the stroke effect to a block |
engine.block.export(block=_, mimeType=_) |
Export the page with all strokes |
Next Steps#
- Masks and Mattes: create and combine masks.
- Apply a Filter or Effect: insert, disable and remove effects.
- Supported Filters and Effects: look up the properties of every effect type.
- Color Effects: remap the colors of a block.
- Wipe Effects: hide parts of a block.