[cairo] ruby current_path
MenTaLguY
mental at rydia.net
Wed Feb 9 21:43:01 PST 2005
On Wed, 2005-02-09 at 13:01, Øyvind Kolås wrote:
> On Wed, 9 Feb 2005 10:49:40 -0500, mental at rydia.net <mental at rydia.net> wrote:
> > (that is also why for current_path, I return an array from C and
> > iterate over it in Ruby)
>
> Could you make a small sample of how this api is used? Having a sample
> would make it easier to see
> how it can be used.
This is from memory, so no promises this code will work as written, but
it should give you an idea...
# generate an SVG path string from the current path
path = ""
context.current_path {|op, *coords|
case op
when :move_to
path << "M"
when :line_to
path << "L"
when :curve_to
path << "C"
when :close_path
path << "z"
end
path << coords.join(",")
}
puts path
You can do SAX-like things with path events:
class SVGPathBuilder
def initialize(stream)
@stream = stream
end
def move_to(x, y)
@stream << "M#{x},#{y}"
end
def line_to(x, y)
@stream << "L#{x},#{y}"
end
def curve_to(x1, y1, x2, y2, x3, y3)
@stream << "C#{x1},#{y1},#{x2},#{y2},#{x3},#{y3}"
end
def close_path
@stream << "z"
end
end
path = ""
handler = SVGPathBuilder.new(path)
context.current_path {|event| handler.send(*event) }
puts path
[ or even: context.current_path(&handler.method(:send)) ]
You can have stackable filters:
# okay, cheap, but it's just an example
class CurvesToLines
def initialize(handler)
@handler = handler
end
def move_to(x, y)
@handler.move_to(x, y)
end
def line_to(x, y)
@handler.line_to(x, y)
end
def curve_to(x1, y1, x2, y2, x3, y3)
@handler.line_to(x3, y3) # throw away intermediate control points
end
def close_path
@handler.close_path
end
end
And the observant will notice that Cairo::Context implements this "path
handler" protocol itself:
# copy path from one context to another
other_context.new_path
context.current_path {|event| other_context.send(*event) }
You can also simply fetch an array of these events...
events = context.current_path
...and do things with it:
filter = CurvesToLines.new(context)
context.new_path
events.select {|event|
event[0] != :close_path # skip all close_paths
}.each {|event|
filter.send(*event) # apply the filter
}
These are all pretty contrived, but they should at least give you a
rough idea of what can be done with the API.
In retrospect, it might not hurt to add an (optional) single argument
for #current_path, so you could simply do:
context.current_path(handler)
as shorthand for:
context.current_path {|event| handler.send(*event) }
but really this is all icing. I doubt current_path will ever get used
that much.
-mental
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050210/ffa69e1a/attachment.pgp
More information about the cairo
mailing list