Created
May 19, 2012 23:35
-
-
Save practicingruby/2732815 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
eval(DATA.read) # :trollface: | |
## USE VELLUM TO DESCRIBE A DRAWING IN THE ABSTRACT | |
drawing = Vellum::Drawing.new(300,400) | |
drawing.layer(:box) do |g| | |
g.rect(g.top_left, g.width, g.height) | |
end | |
drawing.layer(:x) do |g| | |
g.line(g.top_left, g.bottom_right) | |
.line(g.top_right, g.bottom_left) | |
end | |
drawing.layer(:cross) do |g| | |
g.line([g.width / 2, 0], [g.width / 2, g.height]) | |
.line([0, g.height / 2], [g.width, g.height/2]) | |
end | |
drawing.style(:x, :stroke_color => "ff0000") | |
drawing.style(:box, :line_width => 2, | |
:fill_color => "ffffcc") | |
drawing.style(:cross, :stroke_color => "00ff00") | |
## BEGIN PRAWN SPECIFIC CODE | |
require "prawn" | |
pdf = Prawn::Document.new | |
renderer = Vellum::Renderer.new | |
renderer.on(Object) do |shape, style| | |
pdf.stroke_color = style.fetch(:stroke_color, "000000") | |
pdf.fill_color = style.fetch(:fill_color, "ffffff") | |
pdf.line_width = style.fetch(:line_width, 1) | |
end | |
renderer.on(Vellum::Line) do |shape, style| | |
pdf.stroke_line(shape.p1, shape.p2) | |
end | |
renderer.on(Vellum::Rectangle) do |shape, style| | |
pdf.fill_and_stroke_rectangle(shape.point, shape.width, shape.height) | |
end | |
renderer.render(drawing) | |
pdf.render_file("foo.pdf") | |
__END__ | |
## BEGIN VELLUM IMPLEMENTATION | |
require "forwardable" | |
module Vellum | |
class Box | |
def initialize(width, height) | |
@width = width | |
@height = height | |
end | |
attr_reader :width, :height | |
def top_left | |
[0, height] | |
end | |
def top_right | |
[width, height] | |
end | |
def bottom_left | |
[0, 0] | |
end | |
def bottom_right | |
[width, 0] | |
end | |
end | |
class Drawing | |
def initialize(width, height) | |
@dimensions = Box.new(width, height) | |
@layers = [] | |
@styles = {} | |
end | |
attr_reader :dimensions, :layers | |
def layer(name) | |
new_layer = Layer.new(name) | |
yield Graphic.new(self, new_layer) | |
layers << new_layer | |
end | |
def style(name, params) | |
@styles[name] = params | |
end | |
def each | |
layers.each do |layer| | |
layer.elements.each do |shape| | |
yield shape, @styles.fetch(layer.name, {}) | |
end | |
end | |
end | |
end | |
class Layer | |
def initialize(name) | |
@name = name | |
@elements = [] | |
end | |
attr_reader :name, :elements | |
def <<(element) | |
elements << element | |
self | |
end | |
end | |
class Renderer | |
def initialize | |
@matchers = [] | |
end | |
def on(pattern, &block) | |
@matchers << [pattern, block] | |
end | |
def render(document) | |
document.each do |shape, style| | |
@matchers.each do |pattern, action| | |
action.call(shape, style) if pattern === shape | |
end | |
end | |
end | |
private | |
attr_reader :matchers | |
end | |
class Graphic | |
extend Forwardable | |
delegate Box.instance_methods(false) => :dimensions | |
def initialize(drawing, layer) | |
@drawing = drawing | |
@layer = layer | |
end | |
attr_reader :drawing, :layer | |
def dimensions | |
@drawing.dimensions | |
end | |
def line(*a, &b) | |
layer << Line.new(*a, &b) | |
self | |
end | |
def rect(*a, &b) | |
layer << Rectangle.new(*a, &b) | |
self | |
end | |
end | |
Line = Struct.new(:p1, :p2) | |
Rectangle = Struct.new(:point, :width, :height) | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment