origami 1.0.4 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +40 -49
- data/bin/gui/about.rb +1 -1
- data/bin/pdfencrypt +10 -4
- data/origami/actions.rb +0 -1
- data/origami/docmdp.rb +96 -0
- data/origami/encryption.rb +103 -14
- data/origami/graphics.rb +1 -0
- data/origami/graphics/colors.rb +23 -23
- data/origami/graphics/instruction.rb +7 -29
- data/origami/graphics/path.rb +53 -19
- data/origami/graphics/render.rb +69 -0
- data/origami/graphics/state.rb +9 -9
- data/origami/graphics/text.rb +66 -48
- data/origami/graphics/xobject.rb +65 -50
- data/origami/javascript.rb +135 -0
- data/origami/metadata.rb +24 -0
- data/origami/object.rb +1 -1
- data/origami/page.rb +12 -0
- data/origami/parsers/pdf/linear.rb +0 -0
- data/origami/pdf.rb +2 -2
- metadata +77 -75
- data/VERSION +0 -1
data/origami/graphics.rb
CHANGED
data/origami/graphics/colors.rb
CHANGED
@@ -24,7 +24,7 @@
|
|
24
24
|
=end
|
25
25
|
|
26
26
|
begin
|
27
|
-
require 'color'
|
27
|
+
require 'color'
|
28
28
|
rescue LoadError
|
29
29
|
end
|
30
30
|
|
@@ -118,73 +118,73 @@ module Origami
|
|
118
118
|
|
119
119
|
class PDF::Instruction
|
120
120
|
|
121
|
-
insn 'CS', Name do |
|
122
|
-
insn 'cs', Name do |
|
123
|
-
insn 'SC', '*' do |
|
124
|
-
insn 'sc', '*' do |
|
121
|
+
insn 'CS', Name do |canvas, cs| canvas.gs.stroking_colorspace = cs end
|
122
|
+
insn 'cs', Name do |canvas, cs| canvas.gs.nonstroking_colorspace = cs end
|
123
|
+
insn 'SC', '*' do |canvas, *c| canvas.gs.stroking_color = c end
|
124
|
+
insn 'sc', '*' do |canvas, *c| canvas.gs.nonstroking_color = c end
|
125
125
|
|
126
|
-
insn 'G', Real do |
|
126
|
+
insn 'G', Real do |canvas, c|
|
127
127
|
unless (0..1).include? c
|
128
128
|
raise Graphics::InvalidColorError,
|
129
129
|
"Not a valid color for DeviceGray: #{c}"
|
130
130
|
end
|
131
131
|
|
132
|
-
gs.stroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
|
133
|
-
gs.stroking_color = [ c ]
|
132
|
+
canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
|
133
|
+
canvas.gs.stroking_color = [ c ]
|
134
134
|
end
|
135
135
|
|
136
|
-
insn 'g', Real do |
|
136
|
+
insn 'g', Real do |canvas, c|
|
137
137
|
unless (0..1).include? c
|
138
138
|
raise Graphics::InvalidColorError,
|
139
139
|
"Not a valid color for DeviceGray: #{c}"
|
140
140
|
end
|
141
141
|
|
142
|
-
gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
|
143
|
-
gs.nonstroking_color = [ c ]
|
142
|
+
canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_GRAY
|
143
|
+
canvas.gs.nonstroking_color = [ c ]
|
144
144
|
end
|
145
145
|
|
146
|
-
insn 'RG', Real, Real, Real do |
|
146
|
+
insn 'RG', Real, Real, Real do |canvas, r,g,b|
|
147
147
|
c = [ r, g, b ]
|
148
148
|
unless c.all? {|b| (0..1).include? b}
|
149
149
|
raise Graphics::InvalidColorError,
|
150
150
|
"Not a valid color for DeviceRGB: #{c.inspect}"
|
151
151
|
end
|
152
152
|
|
153
|
-
gs.stroking_colorspace = Graphics::Color::Space::DEVICE_RGB
|
154
|
-
gs.stroking_color = c
|
153
|
+
canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_RGB
|
154
|
+
canvas.gs.stroking_color = c
|
155
155
|
end
|
156
156
|
|
157
|
-
insn 'rg', Real, Real, Real do |
|
157
|
+
insn 'rg', Real, Real, Real do |canvas, r,g,b|
|
158
158
|
c = [ r, g, b ]
|
159
159
|
unless c.all? {|b| (0..1).include? b}
|
160
160
|
raise Graphics::InvalidColorError,
|
161
161
|
"Not a valid color for DeviceRGB: #{c.inspect}"
|
162
162
|
end
|
163
163
|
|
164
|
-
gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_RGB
|
165
|
-
gs.nonstroking_color = c
|
164
|
+
canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_RGB
|
165
|
+
canvas.gs.nonstroking_color = c
|
166
166
|
end
|
167
167
|
|
168
|
-
insn 'K', Real, Real, Real, Real do |
|
168
|
+
insn 'K', Real, Real, Real, Real do |canvas, c,m,y,k|
|
169
169
|
c = [ c, m, y, k ]
|
170
170
|
unless c.all? {|b| (0..1).include? b}
|
171
171
|
raise Graphics::InvalidColorError,
|
172
172
|
"Not a valid color for DeviceCMYK: #{c.inspect}"
|
173
173
|
end
|
174
174
|
|
175
|
-
gs.stroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
|
176
|
-
gs.stroking_color = c
|
175
|
+
canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
|
176
|
+
canvas.gs.stroking_color = c
|
177
177
|
end
|
178
178
|
|
179
|
-
insn 'k', Real, Real, Real, Real do |
|
179
|
+
insn 'k', Real, Real, Real, Real do |canvas, c,m,y,k|
|
180
180
|
c = [ c, m, y, k ]
|
181
181
|
unless c.all? {|b| (0..1).include? b}
|
182
182
|
raise Graphics::InvalidColorError,
|
183
183
|
"Not a valid color for DeviceCMYK: #{c.inspect}"
|
184
184
|
end
|
185
185
|
|
186
|
-
gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
|
187
|
-
gs.nonstroking_color = c
|
186
|
+
canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_CMYK
|
187
|
+
canvas.gs.nonstroking_color = c
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
@@ -31,7 +31,7 @@ module Origami
|
|
31
31
|
attr_accessor :operands
|
32
32
|
|
33
33
|
@@regexp = Regexp.new('([^ \\t\\r\\n\\0\\[\\]<>()%\\/]+)')
|
34
|
-
@insns = Hash.new(:operands => [], :
|
34
|
+
@insns = Hash.new(:operands => [], :render => lambda{})
|
35
35
|
|
36
36
|
def initialize(operator, *operands)
|
37
37
|
@operator = operator
|
@@ -47,17 +47,8 @@ module Origami
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
def
|
51
|
-
self.class.
|
52
|
-
self
|
53
|
-
end
|
54
|
-
|
55
|
-
def render
|
56
|
-
end
|
57
|
-
|
58
|
-
def exec(gs)
|
59
|
-
update_state(gs)
|
60
|
-
self.class.get_callback(@operator)[gs] if self.class.has_callback?(@operator)
|
50
|
+
def render(canvas)
|
51
|
+
self.class.get_render_proc(@operator)[canvas, *@operands]
|
61
52
|
|
62
53
|
self
|
63
54
|
end
|
@@ -67,31 +58,18 @@ module Origami
|
|
67
58
|
end
|
68
59
|
|
69
60
|
class << self
|
70
|
-
def insn(operator, *operands, &
|
61
|
+
def insn(operator, *operands, &render_proc)
|
71
62
|
@insns[operator] = {}
|
72
63
|
@insns[operator][:operands] = operands
|
73
|
-
@insns[operator][:
|
64
|
+
@insns[operator][:render] = render_proc || lambda{}
|
74
65
|
end
|
75
66
|
|
76
67
|
def has_op?(operator)
|
77
68
|
@insns.has_key? operator
|
78
69
|
end
|
79
70
|
|
80
|
-
def
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
def has_callback?(operator)
|
85
|
-
self.has_op?(operator) and @insns[operator].has_key?(:callback)
|
86
|
-
end
|
87
|
-
|
88
|
-
def set_callback(operator, &b)
|
89
|
-
raise RuntimeError, "Operator `#{operator}' does not exist" unless @insns.has_key?(operator)
|
90
|
-
@insns[operator][:callback] = b
|
91
|
-
end
|
92
|
-
|
93
|
-
def get_proc(operator)
|
94
|
-
@insns[operator][:proc]
|
71
|
+
def get_render_proc(operator)
|
72
|
+
@insns[operator][:render]
|
95
73
|
end
|
96
74
|
|
97
75
|
def get_operands(operator)
|
data/origami/graphics/path.rb
CHANGED
@@ -105,49 +105,83 @@ module Origami
|
|
105
105
|
end
|
106
106
|
|
107
107
|
class PDF::Instruction
|
108
|
-
insn 'm', Real, Real do |
|
109
|
-
gs.current_path << (subpath = Graphics::Path.new)
|
108
|
+
insn 'm', Real, Real do |canvas, x,y|
|
109
|
+
canvas.gs.current_path << (subpath = Graphics::Path.new)
|
110
110
|
subpath.current_point = [x,y]
|
111
111
|
end
|
112
112
|
|
113
|
-
insn 'l', Real, Real do |
|
114
|
-
if gs.current_path.empty?
|
113
|
+
insn 'l', Real, Real do |canvas, x,y|
|
114
|
+
if canvas.gs.current_path.empty?
|
115
115
|
raise InvalidPathError, "No current point is defined"
|
116
116
|
end
|
117
117
|
|
118
|
-
subpath = gs.current_path.last
|
118
|
+
subpath = canvas.gs.current_path.last
|
119
119
|
|
120
120
|
from = subpath.current_point
|
121
121
|
to = [x,y]
|
122
122
|
subpath.add_segment(Graphics::Path::Line.new(from, to))
|
123
123
|
end
|
124
124
|
|
125
|
-
insn 'h' do |
|
126
|
-
unless gs.current_path.empty?
|
127
|
-
subpath = gs.current_path.last
|
125
|
+
insn 'h' do |canvas|
|
126
|
+
unless canvas.gs.current_path.empty?
|
127
|
+
subpath = canvas.gs.current_path.last
|
128
128
|
subpath.close! unless subpath.is_closed?
|
129
129
|
end
|
130
130
|
end
|
131
131
|
|
132
|
-
insn 're', Real, Real, Real, Real do |
|
132
|
+
insn 're', Real, Real, Real, Real do |canvas, x,y,width,height|
|
133
133
|
tx = x + width
|
134
134
|
ty = y + height
|
135
|
-
gs.current_path << (subpath = Graphics::Path.new)
|
135
|
+
canvas.gs.current_path << (subpath = Graphics::Path.new)
|
136
136
|
subpath.segments << Graphics::Path::Line.new([x,y], [tx,y])
|
137
137
|
subpath.segments << Graphics::Path::Line.new([tx,y], [tx, ty])
|
138
138
|
subpath.segments << Graphics::Path::Line.new([tx, ty], [x, ty])
|
139
139
|
subpath.close!
|
140
140
|
end
|
141
141
|
|
142
|
-
insn 'S'
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
insn '
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
142
|
+
insn 'S' do |canvas|
|
143
|
+
canvas.stroke_path
|
144
|
+
end
|
145
|
+
|
146
|
+
insn 's' do |canvas|
|
147
|
+
canvas.gs.current_path.last.close!
|
148
|
+
canvas.stroke_path
|
149
|
+
end
|
150
|
+
|
151
|
+
insn 'f' do |canvas|
|
152
|
+
canvas.fill_path
|
153
|
+
end
|
154
|
+
|
155
|
+
insn 'F' do |canvas|
|
156
|
+
canvas.fill_path
|
157
|
+
end
|
158
|
+
|
159
|
+
insn 'f*' do |canvas|
|
160
|
+
canvas.fill_path
|
161
|
+
end
|
162
|
+
|
163
|
+
insn 'B' do |canvas|
|
164
|
+
canvas.fill_path
|
165
|
+
canvas.stroke_path
|
166
|
+
end
|
167
|
+
|
168
|
+
insn 'B*' do |canvas|
|
169
|
+
canvas.fill_path
|
170
|
+
canvas.stroke_path
|
171
|
+
end
|
172
|
+
|
173
|
+
insn 'b' do |canvas|
|
174
|
+
canvas.gs.current_path.last.close!
|
175
|
+
canvas.fill_path
|
176
|
+
canvas.stroke_path
|
177
|
+
end
|
178
|
+
|
179
|
+
insn 'b*' do |canvas|
|
180
|
+
canvas.gs.current_path.last.close!
|
181
|
+
canvas.fill_path
|
182
|
+
canvas.stroke_path
|
183
|
+
end
|
184
|
+
|
151
185
|
insn 'n'
|
152
186
|
end
|
153
187
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
graphics/render.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU Lesser General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public License
|
22
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Origami
|
27
|
+
|
28
|
+
module Graphics
|
29
|
+
|
30
|
+
module Canvas
|
31
|
+
attr_reader :gs
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@gs = Graphics::State.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear
|
38
|
+
@gs.reset
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_text(s); end
|
42
|
+
def stroke_path; end
|
43
|
+
def fill_path; end
|
44
|
+
end
|
45
|
+
|
46
|
+
class DummyCanvas
|
47
|
+
include Canvas
|
48
|
+
end
|
49
|
+
|
50
|
+
class TextCanvas
|
51
|
+
include Canvas
|
52
|
+
|
53
|
+
def initialize(output = STDOUT, columns = 80, lines = 25)
|
54
|
+
super()
|
55
|
+
|
56
|
+
@output = output
|
57
|
+
@columns, @lines = columns, lines
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_text(s)
|
61
|
+
@output.print(s)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
data/origami/graphics/state.rb
CHANGED
@@ -147,18 +147,18 @@ module Origami
|
|
147
147
|
end #module Graphics
|
148
148
|
|
149
149
|
class PDF::Instruction
|
150
|
-
insn 'q' do |
|
151
|
-
insn 'Q' do |
|
152
|
-
insn 'w', Real do |
|
153
|
-
insn 'J', Real do |
|
154
|
-
insn 'j', Real do |
|
155
|
-
insn 'M', Real do |
|
150
|
+
insn 'q' do |canvas| canvas.gs.save; canvas.gs.reset end
|
151
|
+
insn 'Q' do |canvas| canvas.gs.restore end
|
152
|
+
insn 'w', Real do |canvas, lw| canvas.gs.line_width = lw end
|
153
|
+
insn 'J', Real do |canvas, lc| canvas.gs.line_cap = lc end
|
154
|
+
insn 'j', Real do |canvas, lj| canvas.gs.line_join = lj end
|
155
|
+
insn 'M', Real do |canvas, ml| canvas.gs.miter_limit = ml end
|
156
156
|
|
157
|
-
insn 'd', Array, Integer do |
|
158
|
-
gs.dash_pattern = Graphics::DashPattern.new array, phase
|
157
|
+
insn 'd', Array, Integer do |canvas, array, phase|
|
158
|
+
canvas.gs.dash_pattern = Graphics::DashPattern.new array, phase
|
159
159
|
end
|
160
160
|
|
161
|
-
insn 'ri', Name do |
|
161
|
+
insn 'ri', Name do |canvas, ri| canvas.gs.rendering_intent = ri end
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
data/origami/graphics/text.rb
CHANGED
@@ -119,106 +119,124 @@ module Origami
|
|
119
119
|
|
120
120
|
class PDF::Instruction
|
121
121
|
# Text instructions definitions
|
122
|
-
insn 'Tc', Real do |
|
123
|
-
insn 'Tw', Real do |
|
124
|
-
insn 'Tz', Real do |
|
125
|
-
insn 'TL', Real do |
|
122
|
+
insn 'Tc', Real do |canvas, cS| canvas.gs.text_state.char_spacing = cS end
|
123
|
+
insn 'Tw', Real do |canvas, wS| canvas.gs.text_state.word_spacing = wS end
|
124
|
+
insn 'Tz', Real do |canvas, s| canvas.gs.text_state.scaling = s end
|
125
|
+
insn 'TL', Real do |canvas, l| canvas.gs.text_state.leading = l end
|
126
126
|
|
127
|
-
insn 'Tf', Name, Real do |
|
128
|
-
gs.text_state.font = font
|
129
|
-
gs.text_state.font_size = size
|
127
|
+
insn 'Tf', Name, Real do |canvas, font, size|
|
128
|
+
canvas.gs.text_state.font = font
|
129
|
+
canvas.gs.text_state.font_size = size
|
130
130
|
end
|
131
131
|
|
132
|
-
insn 'Tr', Integer do |
|
133
|
-
insn 'Ts', Real do |
|
134
|
-
insn 'BT' do |
|
135
|
-
insn 'ET' do |
|
132
|
+
insn 'Tr', Integer do |canvas, r| canvas.gs.text_state.rendering_mode = r end
|
133
|
+
insn 'Ts', Real do |canvas, s| canvas.gs.text_state.text_rise = s end
|
134
|
+
insn 'BT' do |canvas| canvas.gs.text_state.begin_text_object end
|
135
|
+
insn 'ET' do |canvas| canvas.gs.text_state.end_text_object end
|
136
136
|
|
137
|
-
insn 'Td', Real, Real do |
|
138
|
-
unless gs.text_state.is_in_text_object?
|
137
|
+
insn 'Td', Real, Real do |canvas, tx, ty|
|
138
|
+
unless canvas.gs.text_state.is_in_text_object?
|
139
139
|
raise TextStateError,
|
140
140
|
"Must be in a text object to use operator : Td"
|
141
141
|
end
|
142
142
|
|
143
|
-
gs.text_state.text_matrix =
|
144
|
-
gs.text_state.text_line_matrix =
|
145
|
-
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * gs.text_state.text_line_matrix
|
143
|
+
canvas.gs.text_state.text_matrix =
|
144
|
+
canvas.gs.text_state.text_line_matrix =
|
145
|
+
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
146
146
|
end
|
147
147
|
|
148
|
-
insn 'TD', Real, Real do |
|
149
|
-
unless gs.text_state.is_in_text_object?
|
148
|
+
insn 'TD', Real, Real do |canvas, tx, ty|
|
149
|
+
unless canvas.gs.text_state.is_in_text_object?
|
150
150
|
raise TextStateError,
|
151
151
|
"Must be in a text object to use operator : TD"
|
152
152
|
end
|
153
153
|
|
154
|
-
gs.text_state.leading = -ty
|
154
|
+
canvas.gs.text_state.leading = -ty
|
155
155
|
|
156
|
-
gs.text_state.text_matrix =
|
157
|
-
gs.text_state.text_line_matrix =
|
158
|
-
Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * gs.text_state.text_line_matrix
|
156
|
+
canvas.gs.text_state.text_matrix =
|
157
|
+
canvas.gs.text_state.text_line_matrix =
|
158
|
+
Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * canvas.gs.text_state.text_line_matrix
|
159
159
|
end
|
160
160
|
|
161
|
-
insn 'Tm', Real, Real, Real, Real, Real, Real do |
|
162
|
-
unless gs.text_state.is_in_text_object?
|
161
|
+
insn 'Tm', Real, Real, Real, Real, Real, Real do |canvas, a,b,c,d,e,f,g|
|
162
|
+
unless canvas.gs.text_state.is_in_text_object?
|
163
163
|
raise TextStateError,
|
164
164
|
"Must be in a text object to use operator : Tm"
|
165
165
|
end
|
166
166
|
|
167
|
-
gs.text_state.text_matrix =
|
168
|
-
gs.text_state.text_line_matrix =
|
167
|
+
canvas.gs.text_state.text_matrix =
|
168
|
+
canvas.gs.text_state.text_line_matrix =
|
169
169
|
Matrix.rows([[a,b,0],[c,d,0],[e,f,1]])
|
170
170
|
end
|
171
171
|
|
172
|
-
insn 'T*' do |
|
173
|
-
unless gs.text_state.is_in_text_object?
|
172
|
+
insn 'T*' do |canvas|
|
173
|
+
unless canvas.gs.text_state.is_in_text_object?
|
174
174
|
raise TextStateError,
|
175
175
|
"Must be in a text object to use operator : T*"
|
176
176
|
end
|
177
177
|
|
178
|
-
tx, ty = 0, -gs.text_state.leading
|
178
|
+
tx, ty = 0, -canvas.gs.text_state.leading
|
179
179
|
|
180
|
-
gs.text_state.text_matrix =
|
181
|
-
gs.text_state.text_line_matrix =
|
182
|
-
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * gs.text_state.text_line_matrix
|
180
|
+
canvas.gs.text_state.text_matrix =
|
181
|
+
canvas.gs.text_state.text_line_matrix =
|
182
|
+
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
183
183
|
end
|
184
184
|
|
185
|
-
insn 'Tj', String do |
|
186
|
-
unless gs.text_state.is_in_text_object?
|
185
|
+
insn 'Tj', String do |canvas, s|
|
186
|
+
unless canvas.gs.text_state.is_in_text_object?
|
187
187
|
raise TextStateError,
|
188
188
|
"Must be in a text object to use operator : Tj"
|
189
189
|
end
|
190
|
+
|
191
|
+
canvas.write_text(s)
|
190
192
|
end
|
191
193
|
|
192
|
-
insn "'", String do |
|
193
|
-
unless gs.text_state.is_in_text_object?
|
194
|
+
insn "'", String do |canvas, s|
|
195
|
+
unless canvas.gs.text_state.is_in_text_object?
|
194
196
|
raise TextStateError,
|
195
197
|
"Must be in a text object to use operator : '"
|
196
198
|
end
|
197
199
|
|
198
|
-
tx, ty = 0, -gs.text_state.leading
|
200
|
+
tx, ty = 0, -canvas.gs.text_state.leading
|
201
|
+
|
202
|
+
canvas.gs.text_state.text_matrix =
|
203
|
+
canvas.gs.text_state.text_line_matrix =
|
204
|
+
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
199
205
|
|
200
|
-
|
201
|
-
gs.text_state.text_line_matrix =
|
202
|
-
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * gs.text_state.text_line_matrix
|
206
|
+
canvas.write_text(s)
|
203
207
|
end
|
204
208
|
|
205
|
-
insn '"', Real, Real, String do |
|
206
|
-
unless gs.text_state.is_in_text_object?
|
209
|
+
insn '"', Real, Real, String do |canvas, w, c, s|
|
210
|
+
unless canvas.gs.text_state.is_in_text_object?
|
207
211
|
raise TextStateError,
|
208
212
|
"Must be in a text object to use operator : \""
|
209
213
|
end
|
210
214
|
|
211
|
-
gs.text_state.word_spacing = w
|
212
|
-
gs.text_state.char_spacing = c
|
215
|
+
canvas.gs.text_state.word_spacing = w
|
216
|
+
canvas.gs.text_state.char_spacing = c
|
213
217
|
|
214
218
|
tx, ty = 0, -gs.text_state.leading
|
215
219
|
|
216
|
-
gs.text_state.text_matrix =
|
217
|
-
gs.text_state.text_line_matrix =
|
218
|
-
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * gs.text_state.text_line_matrix
|
220
|
+
canvas.gs.text_state.text_matrix =
|
221
|
+
canvas.gs.text_state.text_line_matrix =
|
222
|
+
Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix
|
223
|
+
|
224
|
+
canvas.write_text(s)
|
219
225
|
end
|
220
226
|
|
221
|
-
insn 'TJ', Array
|
227
|
+
insn 'TJ', Array do |canvas, arr|
|
228
|
+
arr.each do |g|
|
229
|
+
case g
|
230
|
+
when Fixnum,Float then
|
231
|
+
# XXX: handle this in text space ?
|
232
|
+
when ::String then
|
233
|
+
canvas.write_text(g)
|
234
|
+
else
|
235
|
+
raise InvalidPDFInstructionError,
|
236
|
+
"Invalid component type `#{g.class}` in TJ operand"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
222
240
|
end
|
223
241
|
|
224
242
|
end
|