prawn-format 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +37 -0
- data/Rakefile +31 -0
- data/examples/basic-formatting.rb +37 -0
- data/examples/christmas-carol.txt +717 -0
- data/examples/document.rb +61 -0
- data/examples/flowing.rb +24 -0
- data/examples/style-classes.rb +12 -0
- data/examples/syntax-highlighting.rb +31 -0
- data/examples/tags.rb +24 -0
- data/lib/prawn/format.rb +211 -0
- data/lib/prawn/format/effects/link.rb +30 -0
- data/lib/prawn/format/effects/underline.rb +32 -0
- data/lib/prawn/format/instructions/base.rb +62 -0
- data/lib/prawn/format/instructions/tag_close.rb +52 -0
- data/lib/prawn/format/instructions/tag_open.rb +95 -0
- data/lib/prawn/format/instructions/text.rb +89 -0
- data/lib/prawn/format/layout_builder.rb +113 -0
- data/lib/prawn/format/lexer.rb +222 -0
- data/lib/prawn/format/line.rb +99 -0
- data/lib/prawn/format/parser.rb +181 -0
- data/lib/prawn/format/state.rb +189 -0
- data/lib/prawn/format/text_object.rb +107 -0
- data/lib/prawn/format/version.rb +11 -0
- data/manual/html.rb +187 -0
- data/manual/include/basics.rb +6 -0
- data/manual/include/breaks.rb +13 -0
- data/manual/include/custom-tags.rb +10 -0
- data/manual/include/custom-tags2.rb +2 -0
- data/manual/include/indent.rb +4 -0
- data/manual/include/options.rb +15 -0
- data/manual/include/style-classes.rb +5 -0
- data/manual/manual.txt +101 -0
- data/manual/pdf.rb +204 -0
- data/prawn-format.gemspec +45 -0
- data/spec/layout_builder_spec.rb +27 -0
- data/spec/lexer_spec.rb +91 -0
- data/spec/parser_spec.rb +103 -0
- data/spec/spec_helper.rb +24 -0
- metadata +157 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require "prawn"
|
5
|
+
require "prawn/format"
|
6
|
+
|
7
|
+
Prawn::Document.generate("document.pdf") do
|
8
|
+
tags :h1 => { :font_size => "2em", :font_weight => :bold },
|
9
|
+
:h2 => { :font_size => "1.5em", :font_weight => :bold },
|
10
|
+
:stave => { :display => :break, :meta => { :name => :anchor }, :font_weight => :bold, :font_size => "2em" },
|
11
|
+
:title => { :font_weight => :bold, :font_size => "1.5em" },
|
12
|
+
:indent => { :width => "2em" }
|
13
|
+
|
14
|
+
font "Times-Roman", :size => 14
|
15
|
+
File.open("#{File.dirname(__FILE__)}/christmas-carol.txt") do |story|
|
16
|
+
line_number = 0
|
17
|
+
story.each_line do |line|
|
18
|
+
line_number += 1
|
19
|
+
next if line.strip == ""
|
20
|
+
|
21
|
+
type, data = line.match(/^(\w+)\.\s*(.*)/)[1,2]
|
22
|
+
|
23
|
+
case type
|
24
|
+
when "h1"
|
25
|
+
move_text_position 144
|
26
|
+
text "<h1>#{data}</h1>", :align => :center
|
27
|
+
move_text_position 72
|
28
|
+
|
29
|
+
when "h2"
|
30
|
+
text "<h2>#{data}</h2>", :align => :center
|
31
|
+
move_text_position 72
|
32
|
+
|
33
|
+
when "toc"
|
34
|
+
bounding_box [bounds.left+bounds.width/4, y-bounds.absolute_bottom], :width => bounds.width do
|
35
|
+
text(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
when "stave"
|
39
|
+
start_new_page
|
40
|
+
text(data, :align => :center)
|
41
|
+
move_text_position 72
|
42
|
+
|
43
|
+
when "p"
|
44
|
+
text("<indent/>" + data, :align => :justify)
|
45
|
+
|
46
|
+
when "song"
|
47
|
+
move_text_position font_size/2
|
48
|
+
text(data, :align => :center)
|
49
|
+
move_text_position font_size/2
|
50
|
+
|
51
|
+
when "block"
|
52
|
+
text(data, :align => :justify)
|
53
|
+
|
54
|
+
when "stop"
|
55
|
+
break
|
56
|
+
|
57
|
+
else raise "unknown block type #{type.inspect} (line \##{line_number})"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/examples/flowing.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require 'prawn'
|
5
|
+
require 'prawn/format'
|
6
|
+
|
7
|
+
dice = "#{Prawn::BASEDIR}/data/images/dice.png"
|
8
|
+
Prawn::Document.generate "flowing.pdf" do
|
9
|
+
# first, position an image that we'll flow around
|
10
|
+
width = bounds.width / 2 - 18 # give us some padding on the left of the image
|
11
|
+
info = image(dice, :width => width, :position => :right)
|
12
|
+
|
13
|
+
# create the layout helper that we'll use to flow the text
|
14
|
+
layout(DATA.read, :align => :justify) do |helper|
|
15
|
+
# fill the first box
|
16
|
+
y = helper.fill(bounds.left, bounds.top, width, :height => info.scaled_height + font_size - 1)
|
17
|
+
|
18
|
+
# fill the rest
|
19
|
+
self.y = helper.fill(bounds.left, y, bounds.width)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
__END__
|
24
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut neque. Maecenas scelerisque euismod purus. Nam venenatis. Sed velit mauris, cursus sit amet, semper vitae, sagittis quis, tortor. Nam at nisi. Sed ac nibh. Curabitur auctor ipsum nec tellus. Suspendisse potenti. Morbi dapibus magna a velit. Ut fringilla enim eu enim. Quisque lacinia, arcu dignissim gravida semper, eros quam tempor nisi, non scelerisque massa odio ut mi. Nullam ac ipsum. Proin volutpat tristique sem. Sed ipsum felis, volutpat vel, porttitor id, volutpat eu, mauris. Cras eget nulla sit amet dolor cursus semper. Curabitur nulla nunc, accumsan sit amet, vestibulum sit amet, adipiscing in, lorem. Pellentesque sodales purus sit amet odio. Cras commodo. Nam accumsan. Suspendisse potenti. Fusce posuere neque in nulla. Ut cursus blandit nisl. Phasellus ut nulla quis nunc tempus consequat. In hac habitasse platea dictumst. Praesent molestie nisl nec erat. Vivamus pretium nibh sit amet est. Integer dolor. Sed dictum blandit purus. Quisque et mauris vel diam dictum dignissim. Maecenas ultrices. Cras leo risus, tristique quis, hendrerit eu, condimentum tempor, mi. Nullam consectetur ante non nisl. Nulla dignissim sem in turpis. Cras purus felis, molestie ac, rhoncus sed, suscipit et, nisl. Donec tempus justo eu turpis. Aenean quis diam at dolor interdum tempor. Mauris sed nulla vitae erat lobortis lacinia. Nunc mauris. Aliquam mattis egestas ligula. Morbi magna dolor, convallis id, interdum lacinia, pellentesque eu, velit. In non arcu. Duis a nibh. Vestibulum volutpat erat et magna. Vivamus mi ante, aliquam et, vulputate sit amet, pretium non, ligula. Curabitur elementum, nisl ut gravida placerat, nisl sapien posuere augue, a placerat urna enim in velit. Cras nisi. Suspendisse volutpat. Ut eu lorem sed eros sollicitudin volutpat. Quisque blandit, libero sed mattis scelerisque, elit turpis ultricies purus, quis faucibus orci erat quis sem. Vestibulum imperdiet facilisis ante. Mauris dignissim, arcu vitae tincidunt congue, ante nulla aliquam purus, a porta tellus nisl at lectus. Phasellus commodo lacus et tortor. Etiam tortor leo, scelerisque sit amet, lobortis non, gravida vitae, mi. Donec eget augue. Sed ultrices ipsum eget risus. Aliquam rhoncus arcu vitae orci pellentesque pulvinar. Praesent ornare, lacus eget elementum ultrices, massa justo dignissim massa, a suscipit elit nibh quis arcu. Aliquam non massa. Etiam pharetra nisi at risus. Donec felis turpis, suscipit a, luctus vulputate, lobortis id, neque. Proin vitae nibh. Pellentesque nibh risus, volutpat sollicitudin, lobortis vitae, malesuada eu, elit. Duis felis nulla, sagittis id, faucibus luctus, viverra id, eros. Phasellus vulputate leo eget libero. Ut ut ipsum ac dui accumsan placerat. Integer porttitor. Quisque gravida dolor eu diam. Phasellus sodales sem sit amet urna. Morbi ornare viverra mauris.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require 'prawn'
|
5
|
+
require 'prawn/format'
|
6
|
+
|
7
|
+
Prawn::Document.generate "style-classes.pdf" do
|
8
|
+
styles :quote => { :font_style => :italic },
|
9
|
+
:product => { :font_weight => :bold, :color => "#007" }
|
10
|
+
|
11
|
+
text "<span class='product'>Prawn</span> is a fantastic utility for formatting PDF's. Jamis Buck may once have said, speaking of <span class='product'>Prawn</span>, <span class='quote'>\"<span class='product'>Prawn</span> is <em>the</em> single most fantastic PDF creation library ever to be written. In Ruby. In 2008. By Greg Brown.\"</span>"
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require 'prawn'
|
5
|
+
require 'prawn/format'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'coderay'
|
9
|
+
rescue LoadError
|
10
|
+
abort "This example (#{__FILE__}) requires the 'coderay' gem.\n" +
|
11
|
+
"Please make sure it is installed."
|
12
|
+
end
|
13
|
+
|
14
|
+
# Use CodeRay to parse the source and return HTML
|
15
|
+
html = CodeRay.scan(File.read(__FILE__), :ruby).html(:line_numbers => :inline)
|
16
|
+
|
17
|
+
# Use prawn and prawn/format to parse and format the HTML
|
18
|
+
Prawn::Document.generate "syntax-highlighting.pdf", :page_layout => :landscape do
|
19
|
+
styles :no => { :color => "gray" },
|
20
|
+
:c => { :color => "#666" },
|
21
|
+
:s => { :color => "#d20" },
|
22
|
+
:dl => { :color => "black" },
|
23
|
+
:co => { :color => "#036", :font_weight => :bold },
|
24
|
+
:pc => { :color => "#038", :font_weight => :bold },
|
25
|
+
:sy => { :color => "#A60" },
|
26
|
+
:r => { :color => "#080" },
|
27
|
+
:i => { :color => "#00D", :font_weight => :bold },
|
28
|
+
:idl => { :color => "#888", :font_weight => :bold }
|
29
|
+
|
30
|
+
text "<pre>#{html}</pre>"
|
31
|
+
end
|
data/examples/tags.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#coding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
require 'prawn'
|
5
|
+
require 'prawn/format'
|
6
|
+
|
7
|
+
CHINESE_FONT = "#{Prawn::BASEDIR}/data/fonts/gkai00mp.ttf"
|
8
|
+
|
9
|
+
Prawn::Document.generate "tags.pdf" do
|
10
|
+
# tweak an existing tag
|
11
|
+
tags[:em][:color] = "red"
|
12
|
+
|
13
|
+
# completely redefine an existing tag
|
14
|
+
tags[:strong] = { :text_decoration => :underline }
|
15
|
+
|
16
|
+
# define altogether new tags
|
17
|
+
tags :chinese => { :font_family => CHINESE_FONT },
|
18
|
+
:exp => { :vertical_align => :super, :font_size => "70%", :color => "blue", :font_weight => :bold },
|
19
|
+
:header => { :font_weight => :bold, :font_size => 24, :text_decoration => :underline }
|
20
|
+
|
21
|
+
text "<header>Fun with Tags</header>"
|
22
|
+
|
23
|
+
text "<em>Emphasized text</em>, <strong>strong text</strong>, <chinese>汉语</chinese>, and <code>E = mc<exp>2</exp></code>"
|
24
|
+
end
|
data/lib/prawn/format.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'prawn/format/layout_builder'
|
4
|
+
require 'prawn/format/text_object'
|
5
|
+
|
6
|
+
module Prawn
|
7
|
+
module Format
|
8
|
+
def self.included(mod)
|
9
|
+
mod.send :alias_method, :text_without_formatting, :text
|
10
|
+
mod.send :alias_method, :text, :text_with_formatting
|
11
|
+
|
12
|
+
mod.send :alias_method, :height_of_without_formatting, :height_of
|
13
|
+
mod.send :alias_method, :height_of, :height_of_with_formatting
|
14
|
+
end
|
15
|
+
|
16
|
+
# Overloaded version of #text. Call via #text, rather than #text_with_formatting
|
17
|
+
# (see above, where it aliased to #text).
|
18
|
+
def text_with_formatting(text, options={}) #:nodoc:
|
19
|
+
if unformatted?(text, options)
|
20
|
+
text_without_formatting(text, options)
|
21
|
+
else
|
22
|
+
format(text, options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Overloaded version of #height_of. Call via #height_of, rather than
|
27
|
+
# #height_of_with_formatting (see above, where it aliased to #height_of).
|
28
|
+
def height_of_with_formatting(string, line_width, size=font_size, options={}) #:nodoc:
|
29
|
+
if unformatted?(string, options)
|
30
|
+
height_of_without_formatting(string, line_width, size)
|
31
|
+
else
|
32
|
+
formatted_height(string, line_width, size, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
DEFAULT_TAGS = {
|
37
|
+
:a => { :meta => { :name => :anchor, :href => :target }, :color => "0000ff", :text_decoration => :underline },
|
38
|
+
:b => { :font_weight => :bold },
|
39
|
+
:br => { :display => :break },
|
40
|
+
:code => { :font_family => "Courier", :font_size => "90%" },
|
41
|
+
:em => { :font_style => :italic },
|
42
|
+
:font => { :meta => { :face => :font_family, :color => :color, :size => :font_size } },
|
43
|
+
:i => { :font_style => :italic },
|
44
|
+
:pre => { :white_space => :pre, :font_family => "Courier", :font_size => "90%" },
|
45
|
+
:span => {},
|
46
|
+
:strong => { :font_weight => :bold },
|
47
|
+
:sub => { :vertical_align => :sub, :font_size => "70%" },
|
48
|
+
:sup => { :vertical_align => :super, :font_size => "70%" },
|
49
|
+
:tt => { :font_family => "Courier" },
|
50
|
+
:u => { :text_decoration => :underline },
|
51
|
+
}.freeze
|
52
|
+
|
53
|
+
def tags(update={})
|
54
|
+
@tags ||= DEFAULT_TAGS.dup
|
55
|
+
@tags.update(update)
|
56
|
+
end
|
57
|
+
|
58
|
+
def styles(update={})
|
59
|
+
@styles ||= {}
|
60
|
+
@styles.update(update)
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_style
|
64
|
+
{ :font_family => font.family || font.name,
|
65
|
+
:font_size => font_size,
|
66
|
+
:color => fill_color }
|
67
|
+
end
|
68
|
+
|
69
|
+
def evaluate_measure(measure, options={})
|
70
|
+
case measure
|
71
|
+
when nil then nil
|
72
|
+
when Numeric then return measure
|
73
|
+
when Symbol then
|
74
|
+
mappings = options[:mappings] || {}
|
75
|
+
raise ArgumentError, "unrecognized value #{measure.inspect}" unless mappings.key?(measure)
|
76
|
+
return evaluate_measure(mappings[measure], options)
|
77
|
+
when String then
|
78
|
+
operator, value, unit = measure.match(/^([-+]?)(\d+(?:\.\d+)?)(.*)$/)[1,3]
|
79
|
+
|
80
|
+
value = case unit
|
81
|
+
when "%" then
|
82
|
+
relative = options[:relative] || 0
|
83
|
+
relative * value.to_f / 100
|
84
|
+
when "em" then
|
85
|
+
# not a true em, but good enough for approximating. patches welcome.
|
86
|
+
value.to_f * (options[:em] || font_size)
|
87
|
+
when "", "pt" then return value.to_f
|
88
|
+
when "pc" then return value.to_f * 12
|
89
|
+
when "in" then return value.to_f * 72
|
90
|
+
else raise ArgumentError, "unsupport units in style value: #{measure.inspect}"
|
91
|
+
end
|
92
|
+
|
93
|
+
current = options[:current] || 0
|
94
|
+
case operator
|
95
|
+
when "+" then return current + value
|
96
|
+
when "-" then return current - value
|
97
|
+
else return value
|
98
|
+
end
|
99
|
+
else return measure.to_f
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def draw_lines(x, y, width, lines, options={})
|
104
|
+
real_x, real_y = translate(x, y)
|
105
|
+
|
106
|
+
state = options[:state] || {}
|
107
|
+
options[:align] ||= :left
|
108
|
+
|
109
|
+
state = state.merge(:width => width,
|
110
|
+
:x => x, :y => y,
|
111
|
+
:real_x => real_x, :real_y => real_y,
|
112
|
+
:dx => 0, :dy => 0)
|
113
|
+
|
114
|
+
state[:cookies] ||= {}
|
115
|
+
state[:pending_effects] ||= []
|
116
|
+
|
117
|
+
return state if lines.empty?
|
118
|
+
|
119
|
+
text_object do |text|
|
120
|
+
text.rotate(real_x, real_y, options[:rotate] || 0)
|
121
|
+
state[:text] = text
|
122
|
+
lines.each { |line| line.draw_on(self, state, options) }
|
123
|
+
end
|
124
|
+
|
125
|
+
state.delete(:text)
|
126
|
+
|
127
|
+
#rectangle [x, y+state[:dy]], width, state[:dy]
|
128
|
+
#stroke
|
129
|
+
|
130
|
+
return state
|
131
|
+
end
|
132
|
+
|
133
|
+
def layout(text, options={})
|
134
|
+
helper = Format::LayoutBuilder.new(self, text, options)
|
135
|
+
yield helper if block_given?
|
136
|
+
return helper
|
137
|
+
end
|
138
|
+
|
139
|
+
def format(text, options={})
|
140
|
+
if options[:at]
|
141
|
+
x, y = options[:at]
|
142
|
+
format_positioned_text(text, x, y, options)
|
143
|
+
else
|
144
|
+
format_wrapped_text(text, options)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def text_object
|
149
|
+
object = TextObject.new
|
150
|
+
|
151
|
+
if block_given?
|
152
|
+
yield object.open
|
153
|
+
add_content(object.close)
|
154
|
+
end
|
155
|
+
|
156
|
+
return object
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def unformatted?(text, options={})
|
162
|
+
# If they have a preference, use it
|
163
|
+
if options.key?(:plain)
|
164
|
+
return options[:plain]
|
165
|
+
|
166
|
+
# Otherwise, if they're asking for full-justification, we must assume
|
167
|
+
# the text is formatted (since Prawn's text() method has no full justification)
|
168
|
+
elsif options[:align] == :justify
|
169
|
+
return false
|
170
|
+
|
171
|
+
# Otherwise, look for tags or XML entities in the text
|
172
|
+
else
|
173
|
+
return text !~ /<|&(?:#x?)?\w+;/
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def format_positioned_text(text, x, y, options={})
|
178
|
+
helper = layout(text, options)
|
179
|
+
line = helper.next
|
180
|
+
draw_lines(x, y+line.ascent, line.width, [line], options)
|
181
|
+
end
|
182
|
+
|
183
|
+
def format_wrapped_text(text, options={})
|
184
|
+
helper = layout(text, options)
|
185
|
+
|
186
|
+
start_new_page if self.y < bounds.absolute_bottom
|
187
|
+
|
188
|
+
until helper.done?
|
189
|
+
y = self.y - bounds.absolute_bottom
|
190
|
+
height = bounds.stretchy? ? bounds.absolute_top : y
|
191
|
+
|
192
|
+
y = helper.fill(bounds.left, y, bounds.width, options.merge(:height => height))
|
193
|
+
|
194
|
+
if helper.done?
|
195
|
+
self.y = y + bounds.absolute_bottom
|
196
|
+
else
|
197
|
+
start_new_page
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def formatted_height(string, line_width, size=font_size, options={})
|
203
|
+
helper = layout(string, options.merge(:size => font_size))
|
204
|
+
lines = helper.word_wrap(line_width)
|
205
|
+
return lines.inject(0) { |s, line| s + line.height }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
require 'prawn/document'
|
211
|
+
Prawn::Document.send(:include, Prawn::Format)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Prawn
|
4
|
+
module Format
|
5
|
+
module Effects
|
6
|
+
|
7
|
+
class Link
|
8
|
+
def initialize(target, x)
|
9
|
+
@target = target.sub(/^#/, "")
|
10
|
+
@x = x
|
11
|
+
end
|
12
|
+
|
13
|
+
def finish(document, draw_state)
|
14
|
+
x1 = draw_state[:real_x] + @x
|
15
|
+
x2 = draw_state[:real_x] + draw_state[:dx]
|
16
|
+
y = draw_state[:real_y] + draw_state[:dy]
|
17
|
+
|
18
|
+
rect = [x1, y + draw_state[:line].descent, x2, y + draw_state[:line].ascent]
|
19
|
+
document.link_annotation(rect, :Dest => @target, :Border => [0,0,0])
|
20
|
+
end
|
21
|
+
|
22
|
+
def wrap(document, draw_state)
|
23
|
+
finish(document, draw_state)
|
24
|
+
@x = 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Prawn
|
4
|
+
module Format
|
5
|
+
module Effects
|
6
|
+
|
7
|
+
class Underline
|
8
|
+
def initialize(from, state)
|
9
|
+
@from = from
|
10
|
+
@state = state
|
11
|
+
end
|
12
|
+
|
13
|
+
def finish(document, draw_state)
|
14
|
+
x1 = draw_state[:x] + @from
|
15
|
+
x2 = draw_state[:x] + draw_state[:dx]
|
16
|
+
y = draw_state[:y] + draw_state[:dy] - 2
|
17
|
+
|
18
|
+
document.stroke_color(@state.color)
|
19
|
+
document.move_to(x1, y)
|
20
|
+
document.line_to(x2, y)
|
21
|
+
document.stroke
|
22
|
+
end
|
23
|
+
|
24
|
+
def wrap(document, draw_state)
|
25
|
+
finish(document, draw_state)
|
26
|
+
@from = 0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Prawn
|
4
|
+
module Format
|
5
|
+
module Instructions
|
6
|
+
|
7
|
+
class Base
|
8
|
+
attr_reader :state, :ascent, :descent
|
9
|
+
|
10
|
+
def initialize(state)
|
11
|
+
@state = state
|
12
|
+
state.document.font_size(state.font_size) do
|
13
|
+
@height = state.font.height
|
14
|
+
@ascent = state.font.ascender
|
15
|
+
@descent = state.font.descender
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def spaces
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
def width(*args)
|
24
|
+
0
|
25
|
+
end
|
26
|
+
|
27
|
+
def height(*args)
|
28
|
+
@height
|
29
|
+
end
|
30
|
+
|
31
|
+
def break?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def force_break?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def discardable?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_verbatim?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def end_verbatim?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def style
|
52
|
+
{}
|
53
|
+
end
|
54
|
+
|
55
|
+
def accumulate(list)
|
56
|
+
list.push(self)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|