Custom behavior for strokepath and fillpath

There are four functions that "paint" the current path to the drawing: they are strokepath , strokepreserve , fillpath, and fillpreserve. Other mechanisms to draw on the canvas are clip , clippreserve and paint. (text is another function that draws on the canvas but is not considered here)

If you would like to have some custom behavior for these functions, such as adding a way to extract or modify paths etc.), Luxor provides a way to do so.

These four functions are basically defined as:

funcname() = funcname(DISPATCHER[1]) funcname(::DefaultLuxor) = {...do_some_graphics_work...} funcname(::LDispatcher) = funcname(DefaultLuxor())

DISPATCHER[1] is defined as an instance of a struct (with no fields) DefaultLuxor. The datatype DefaultLuxor is a subtype of LDispatcher. DISPATCHER as such is defined as an array of LDispatcher. This is to make it mutable. Only the first element ie. DISPATCHER[1] is ever used.

You can make custom behavior for the functions in the following way:

1 Define a new struct MyDispatcher <: Luxor.LDispatcher (it needn't have any fields).

2 Define a function that dispatches on the above struct.

3 Change Luxor.DISPATCHER[1] to an instance of your struct.

Here's an example of a method that changes the behavior of all calls to strokepath() such that the current color is printed to the terminal as the path is drawn.

struct MyDispatcher <: Luxor.LDispatcher end
function Luxor.strokepath(::MyDispatcher)
    println("$(Luxor.get_current_color())")
	return Luxor.strokepath(Luxor.DefaultLuxor())
end
Luxor.DISPATCHER[1] = MyDispatcher()

@draw begin
    for i in 1:20
        randomhue()
        star(rand(BoundingBox()), 30, 6, 0.5, action = :stroke)
    end
end

Now, all calls to strokepath() whether explicitly called or through other functions (for example, with the :stroke action) will print the current color just before the path is stroked.

Similar dispatches can be written for strokepreserve, fillpath, fillpreserve, clip, clippreserve, and paint.

Functions which don't have methods defined for the types will default to calling funcname(Luxor.DefaultLuxor())