| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# $Id: AxPoint.pm,v 1.49 2005/10/19 16:43:48 matt Exp $ |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package XML::Handler::AxPoint; |
|
4
|
2
|
|
|
2
|
|
37595
|
use strict; |
|
|
2
|
|
|
|
|
8
|
|
|
|
2
|
|
|
|
|
119
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
2433
|
use XML::SAX::Writer; |
|
|
2
|
|
|
|
|
119660
|
|
|
|
2
|
|
|
|
|
66
|
|
|
7
|
2
|
|
|
2
|
|
1879
|
use Text::Iconv; |
|
|
2
|
|
|
|
|
7306
|
|
|
|
2
|
|
|
|
|
125
|
|
|
8
|
2
|
|
|
2
|
|
15
|
use File::Spec; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
46
|
|
|
9
|
2
|
|
|
2
|
|
11
|
use File::Basename; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
178
|
|
|
10
|
2
|
|
|
2
|
|
2230
|
use Data::Dumper; |
|
|
2
|
|
|
|
|
15038
|
|
|
|
2
|
|
|
|
|
150
|
|
|
11
|
2
|
|
|
2
|
|
11710
|
use PDFLib 0.13; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use POSIX qw(ceil acos); |
|
13
|
|
|
|
|
|
|
use Time::Piece; |
|
14
|
|
|
|
|
|
|
use Carp qw(carp verbose); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
use vars qw($VERSION); |
|
17
|
|
|
|
|
|
|
$VERSION = '1.5'; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
|
20
|
|
|
|
|
|
|
my $class = shift; |
|
21
|
|
|
|
|
|
|
my $opt = (@_ == 1) ? { %{shift()} } : {@_}; |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
$opt->{Output} ||= *{STDOUT}{IO}; |
|
24
|
|
|
|
|
|
|
return bless $opt, $class; |
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub set_document_locator { |
|
28
|
|
|
|
|
|
|
my ($self, $locator) = @_; |
|
29
|
|
|
|
|
|
|
$self->{locator} = $locator; |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub start_document { |
|
33
|
|
|
|
|
|
|
my ($self, $doc) = @_; |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# setup consumer |
|
36
|
|
|
|
|
|
|
my $ref = ref $self->{Output}; |
|
37
|
|
|
|
|
|
|
if ($ref eq 'SCALAR') { |
|
38
|
|
|
|
|
|
|
$self->{Consumer} = XML::SAX::Writer::StringConsumer->new($self->{Output}); |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
elsif ($ref eq 'ARRAY') { |
|
41
|
|
|
|
|
|
|
$self->{Consumer} = XML::SAX::Writer::ArrayConsumer->new($self->{Output}); |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
elsif ($ref eq 'GLOB' or UNIVERSAL::isa($self->{Output}, 'IO::Handle')) { |
|
44
|
|
|
|
|
|
|
$self->{Consumer} = XML::SAX::Writer::HandleConsumer->new($self->{Output}); |
|
45
|
|
|
|
|
|
|
} |
|
46
|
|
|
|
|
|
|
elsif (not $ref) { |
|
47
|
|
|
|
|
|
|
local *FH; |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
open FH, '> ' . $self->{Output} or |
|
50
|
|
|
|
|
|
|
XML::SAX::Writer::Exception->throw( Message => "Error opening '" . |
|
51
|
|
|
|
|
|
|
$self->{Output} . "': $!" ); |
|
52
|
|
|
|
|
|
|
binmode FH; |
|
53
|
|
|
|
|
|
|
$self->{Consumer} = XML::SAX::Writer::HandleConsumer->new(*FH); |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
elsif (UNIVERSAL::can($self->{Output}, 'output')) { |
|
56
|
|
|
|
|
|
|
$self->{Consumer} = $self->{Output}; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
else { |
|
59
|
|
|
|
|
|
|
XML::SAX::Writer::Exception->throw({ Message => 'Unknown option for Output' }); |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
$self->{Encoder} = XML::SAX::Writer::NullConverter->new(); |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
$self->{text_encoder} = Text::Iconv->new('utf-8', 'ISO-8859-1'); |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# create PDF and set defaults |
|
67
|
|
|
|
|
|
|
$self->{pdf} = PDFLib->new(); |
|
68
|
|
|
|
|
|
|
$self->{pdf}->papersize("slides"); |
|
69
|
|
|
|
|
|
|
$self->{pdf}->set_border_style("solid", 0); |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$self->{headline_font} = "Helvetica"; |
|
72
|
|
|
|
|
|
|
$self->{headline_size} = 18.0; |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
$self->{title_font} = "Helvetica-Bold"; |
|
75
|
|
|
|
|
|
|
$self->{title_size} = 24.0; |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
$self->{subtitle_font} = "Helvetica-Bold"; |
|
78
|
|
|
|
|
|
|
$self->{subtitle_size} = 20.0; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
$self->{normal_font} = "Helvetica"; |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
$self->{todo} = []; |
|
83
|
|
|
|
|
|
|
$self->{bookmarks} = []; |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$self->{default_transition} = []; |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
$self->{gathered_text} = ''; |
|
88
|
|
|
|
|
|
|
$self->{bullets} = [ ' ', 'l', 'u', 'p', 'n', 'm', 'F' ]; |
|
89
|
|
|
|
|
|
|
$self->{numbers} = [ ' ', '$1.', '$a)', '$i.', '$A)', '$I' ]; |
|
90
|
|
|
|
|
|
|
$self->{captions} = []; |
|
91
|
|
|
|
|
|
|
$self->{list_index} = []; |
|
92
|
|
|
|
|
|
|
$self->{values} = { 'current-slide' => 0 }; |
|
93
|
|
|
|
|
|
|
$self->{slide_index} = [ 0 ]; |
|
94
|
|
|
|
|
|
|
$self->{boxtransition} = []; |
|
95
|
|
|
|
|
|
|
$self->{fill} = 1; |
|
96
|
|
|
|
|
|
|
$self->{stroke} = 0; |
|
97
|
|
|
|
|
|
|
$self->{coords} = 'svg'; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub run_todo { |
|
101
|
|
|
|
|
|
|
my $self = shift; |
|
102
|
|
|
|
|
|
|
while (my $todo = shift(@{$self->{todo}})) { |
|
103
|
|
|
|
|
|
|
$todo->(); |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub push_todo { |
|
108
|
|
|
|
|
|
|
my $self = shift; |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
push @{$self->{todo}}, shift; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub push_bookmark { |
|
114
|
|
|
|
|
|
|
my $self = shift; |
|
115
|
|
|
|
|
|
|
# warn("push_bookmark($_[0]) from ", caller, "\n"); |
|
116
|
|
|
|
|
|
|
push @{$self->{bookmarks}}, shift; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub top_bookmark { |
|
120
|
|
|
|
|
|
|
my $self = shift; |
|
121
|
|
|
|
|
|
|
return $self->{bookmarks}[-1]; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub pop_bookmark { |
|
125
|
|
|
|
|
|
|
my $self = shift; |
|
126
|
|
|
|
|
|
|
# warn("pop_bookmark() from ", caller, "\n"); |
|
127
|
|
|
|
|
|
|
pop @{$self->{bookmarks}}; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub end_document { |
|
131
|
|
|
|
|
|
|
my ($self) = @_; |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
$self->{pdf}->finish; |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$self->{Consumer}->output( $self->{pdf}->get_buffer ); |
|
136
|
|
|
|
|
|
|
$self->{Consumer}->finalize; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub new_page { |
|
140
|
|
|
|
|
|
|
my $self = shift; |
|
141
|
|
|
|
|
|
|
my ($trans,$type) = @_; |
|
142
|
|
|
|
|
|
|
$type ||= 'normal'; |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
$self->{pdf}->start_page; |
|
145
|
|
|
|
|
|
|
$self->{values}->{'current-slide'}++ unless $self->{transitional}; |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
my $transition = $trans || $self->get_transition || 'replace'; |
|
148
|
|
|
|
|
|
|
$transition = 'replace' if $transition eq 'none'; |
|
149
|
|
|
|
|
|
|
$transition = 'replace' if $self->{PrintMode}; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
$self->{pdf}->set_parameter(transition => lc($transition)); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
if ($type ne 'empty') { |
|
154
|
|
|
|
|
|
|
if (my $bg = $self->{bg}) { |
|
155
|
|
|
|
|
|
|
my @scale = split(/\*/,$bg->{scale}); |
|
156
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$self->{pdf}->get_value("imagewidth", $bg->{image}->img),$self->{pdf}->get_value("resx", $bg->{image}->img)); |
|
157
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$self->{pdf}->get_value("imageheight", $bg->{image}->img),$self->{pdf}->get_value("resy", $bg->{image}->img)); |
|
158
|
|
|
|
|
|
|
$self->{pdf}->add_image(img => $bg->{image}, x => 0, y => 0, w => $imgw, h => $imgh); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
if (my $logo = $self->{logo}) { |
|
162
|
|
|
|
|
|
|
my @scale = split(/\*/,$logo->{scale}); |
|
163
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$self->{pdf}->get_value("imagewidth", $logo->{image}->img),$self->{pdf}->get_value("resx", $logo->{image}->img)); |
|
164
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$self->{pdf}->get_value("imageheight", $logo->{image}->img),$self->{pdf}->get_value("resy", $logo->{image}->img)); |
|
165
|
|
|
|
|
|
|
$self->{pdf}->add_image(img => $logo->{image}, x => 612 - $imgw - $logo->{x}, y => $logo->{y}, w => $imgw, h => $imgh); |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
$self->{pagetype} = $type || 'normal'; |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
$self->process_css_styles("font-family:".$self->{headline_font}.";font-size:".$self->{headline_size}.";stroke:none;fill:black;font-weight:normal;font-style:normal;"); |
|
172
|
|
|
|
|
|
|
pop @{$self->{font_stack}}; |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
$self->{xindent} = []; |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos(80, 300); |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
sub get_node_transition { |
|
180
|
|
|
|
|
|
|
my $self = shift; |
|
181
|
|
|
|
|
|
|
my ($node) = @_; |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
if (exists($node->{Attributes}{"{}transition"})) { |
|
184
|
|
|
|
|
|
|
return $node->{Attributes}{"{}transition"}{Value}; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
return; |
|
187
|
|
|
|
|
|
|
} |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub get_scale { |
|
190
|
|
|
|
|
|
|
my ($self, $spec, $vertical, $rel, $res) = @_; |
|
191
|
|
|
|
|
|
|
$res = 72 if ($res <= 0); # substitute sensible fallback |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
my ($num, $unit) = ($spec =~ m/^\s*([0-9]*(?:\.[0-9]+)?)\s*(em|ex|pt|px|line|page|)\s*$/); |
|
194
|
|
|
|
|
|
|
die "unknown scale specifier: $spec" if !defined $unit; |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
my $pdf = $self->{bb} || $self->{pdf}; # don't use 'line' outside of a slide, will return "0". |
|
197
|
|
|
|
|
|
|
if ($unit eq 'em') { |
|
198
|
|
|
|
|
|
|
if ($vertical) { |
|
199
|
|
|
|
|
|
|
return $num*$pdf->get_value('capheight')*$pdf->get_value('fontsize'); |
|
200
|
|
|
|
|
|
|
} else { |
|
201
|
|
|
|
|
|
|
return $num*$pdf->string_width(text => 'M'); |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
} elsif ($unit eq 'ex') { |
|
204
|
|
|
|
|
|
|
if ($vertical) { |
|
205
|
|
|
|
|
|
|
# FIXME: (probably unfixable) this uses an estimation, not the real value |
|
206
|
|
|
|
|
|
|
return $num*$pdf->get_value('ascender')*2/3*$pdf->get_value('fontsize'); |
|
207
|
|
|
|
|
|
|
} else { |
|
208
|
|
|
|
|
|
|
return $num*$pdf->string_width(text => 'x'); |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
} elsif ($unit eq 'pt') { |
|
211
|
|
|
|
|
|
|
return $num; |
|
212
|
|
|
|
|
|
|
} elsif ($unit eq 'px') { |
|
213
|
|
|
|
|
|
|
return $num*72/$res; |
|
214
|
|
|
|
|
|
|
} elsif ($unit eq 'line') { |
|
215
|
|
|
|
|
|
|
if ($vertical) { |
|
216
|
|
|
|
|
|
|
return $num*$pdf->get_value('leading'); |
|
217
|
|
|
|
|
|
|
} else { |
|
218
|
|
|
|
|
|
|
return $num*($pdf->{w} || $self->{extents}[0]{w}); |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
} elsif ($unit eq 'page') { |
|
221
|
|
|
|
|
|
|
if ($vertical) { |
|
222
|
|
|
|
|
|
|
return $num*$pdf->get_value('pageheight'); |
|
223
|
|
|
|
|
|
|
} else { |
|
224
|
|
|
|
|
|
|
return $num*$pdf->get_value('pagewidth'); |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
} else { |
|
227
|
|
|
|
|
|
|
return $num*$rel*72/$res; |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
die "unknown unit: $unit"; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub get_transition { |
|
233
|
|
|
|
|
|
|
my $self = shift; |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my $node = $self->{SlideCurrent} || $self->{Current}; |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
my $transition; |
|
238
|
|
|
|
|
|
|
while ($node && !($transition = $self->get_node_transition($node))) { |
|
239
|
|
|
|
|
|
|
$node = $node->{Parent}; |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
return $transition; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub playback_cache { |
|
245
|
|
|
|
|
|
|
my $self = shift; |
|
246
|
|
|
|
|
|
|
$self->{cache_trash} = []; |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
while (@{$self->{cache}}) { |
|
249
|
|
|
|
|
|
|
my $thing = shift @{$self->{cache}}; |
|
250
|
|
|
|
|
|
|
my ($method, $node) = @$thing; |
|
251
|
|
|
|
|
|
|
$self->$method($node); |
|
252
|
|
|
|
|
|
|
push @{$self->{cache_trash}}, $thing; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
delete $self->{cache_trash}; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub start_element { |
|
259
|
|
|
|
|
|
|
my ($self, $el) = @_; |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
my $parent = $el->{Parent} = $self->{Current}; |
|
262
|
|
|
|
|
|
|
$self->{Current} = $el; |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
if ($self->{cache_until}) { |
|
265
|
|
|
|
|
|
|
push @{$self->{cache}}, ["slide_start_element", $el]; |
|
266
|
|
|
|
|
|
|
} |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
my $name = $el->{LocalName}; |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# warn("start_ $name\n"); |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
if ($name eq 'slideshow') { |
|
273
|
|
|
|
|
|
|
$self->push_todo(sub { $self->new_page(undef,$el->{Attributes}{"{}type"}{Value}) }); |
|
274
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
275
|
|
|
|
|
|
|
unshift @{$self->{default_transition}}, $el->{Attributes}{"{}default-transition"}{Value}; |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}coordinates"})) { |
|
278
|
|
|
|
|
|
|
$self->{coords} = $el->{Attributes}{"{}coordinates"}{Value}; |
|
279
|
|
|
|
|
|
|
if ($self->{coords} !~ /^(svg|old)$/) { |
|
280
|
|
|
|
|
|
|
Carp::croak("Unknown coordinate system: $self->{coords}"); |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
} |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
elsif ($name eq 'title') { |
|
285
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
elsif ($name eq 'metadata') { |
|
288
|
|
|
|
|
|
|
} |
|
289
|
|
|
|
|
|
|
elsif ($name eq 'total-slides') { |
|
290
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
elsif ($name eq 'speaker') { |
|
293
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
elsif ($name eq 'email') { |
|
296
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
297
|
|
|
|
|
|
|
} |
|
298
|
|
|
|
|
|
|
elsif ($name eq 'organisation') { |
|
299
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
elsif ($name eq 'link') { |
|
302
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
303
|
|
|
|
|
|
|
} |
|
304
|
|
|
|
|
|
|
elsif ($name eq 'logo') { |
|
305
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}scale"})) { |
|
306
|
|
|
|
|
|
|
$self->{logo}{scale} = $el->{Attributes}{"{}scale"}{Value}; |
|
307
|
|
|
|
|
|
|
} |
|
308
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}x"})) { |
|
309
|
|
|
|
|
|
|
$self->{logo}{x} = $el->{Attributes}{"{}x"}{Value}; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}y"})) { |
|
312
|
|
|
|
|
|
|
$self->{logo}{y} = $el->{Attributes}{"{}y"}{Value}; |
|
313
|
|
|
|
|
|
|
} |
|
314
|
|
|
|
|
|
|
$self->{logo}{x} ||= 0; |
|
315
|
|
|
|
|
|
|
$self->{logo}{y} ||= 0; |
|
316
|
|
|
|
|
|
|
$self->{logo}{scale} ||= 1.0; |
|
317
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
318
|
|
|
|
|
|
|
} |
|
319
|
|
|
|
|
|
|
elsif ($name eq 'background') { |
|
320
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}scale"})) { |
|
321
|
|
|
|
|
|
|
$self->{bg}{scale} = $el->{Attributes}{"{}scale"}{Value}; |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
$self->{bg}{scale} ||= 1.0; |
|
324
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
elsif ($name eq 'bullet' or $name eq 'numbers') { |
|
327
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
elsif ($name eq 'slideset') { |
|
330
|
|
|
|
|
|
|
$self->run_todo; |
|
331
|
|
|
|
|
|
|
$self->{slide_index}[0]++; |
|
332
|
|
|
|
|
|
|
unshift @{$self->{slide_index}}, 0; |
|
333
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
334
|
|
|
|
|
|
|
unshift @{$self->{default_transition}}, $el->{Attributes}{"{}default-transition"}{Value}; |
|
335
|
|
|
|
|
|
|
} |
|
336
|
|
|
|
|
|
|
$self->new_page(undef,$el->{Attributes}{"{}type"}{Value}) unless ($el->{Attributes}{"{}type"}{Value}||'normal') eq 'empty'; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
elsif ($name eq 'subtitle') { |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
elsif ($name eq 'slide') { |
|
341
|
|
|
|
|
|
|
$self->run_todo; # might need to create slideset here. |
|
342
|
|
|
|
|
|
|
$self->{pdf}->end_page; |
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
$self->{slide_index}[0]++; |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
347
|
|
|
|
|
|
|
unshift @{$self->{default_transition}}, $el->{Attributes}{"{}default-transition"}{Value}; |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
$self->{images} = []; |
|
350
|
|
|
|
|
|
|
# cache these events now... |
|
351
|
|
|
|
|
|
|
$self->{cache_until} = $el->{Name}; |
|
352
|
|
|
|
|
|
|
$self->{cache} = [["slide_start_element", $el]]; |
|
353
|
|
|
|
|
|
|
} |
|
354
|
|
|
|
|
|
|
elsif ($name eq 'image') { |
|
355
|
|
|
|
|
|
|
$self->gathered_text; |
|
356
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{http://www.w3.org/1999/xlink}href"})) { |
|
357
|
|
|
|
|
|
|
# uses xlink, not characters |
|
358
|
|
|
|
|
|
|
$self->characters({ Data => $el->{Attributes}{"{http://www.w3.org/1999/xlink}href"}{Value}}); |
|
359
|
|
|
|
|
|
|
} elsif (exists($el->{Attributes}{"{}href"})) { |
|
360
|
|
|
|
|
|
|
# workaround for XML::LibXML::SAX problem |
|
361
|
|
|
|
|
|
|
$self->characters({ Data => $el->{Attributes}{"{}href"}{Value}}); |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
elsif ($name =~ /^(source[_-]code|box|table|list|point|plain|value|i|b|u|colou?r|row|col|rect|circle|ellipse|polyline|line|path|text|g|span|variable)$/) { |
|
365
|
|
|
|
|
|
|
# passthrough to allow these types |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
else { |
|
368
|
|
|
|
|
|
|
warn("Unknown tag: $name"); |
|
369
|
|
|
|
|
|
|
} |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
sub end_element { |
|
373
|
|
|
|
|
|
|
my ($self, $el) = @_; |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
if ($self->{cache_until}) { |
|
376
|
|
|
|
|
|
|
push @{$self->{cache}}, ["slide_end_element", $el]; |
|
377
|
|
|
|
|
|
|
if ($el->{Name} eq $self->{cache_until}) { |
|
378
|
|
|
|
|
|
|
delete $self->{cache_until}; |
|
379
|
|
|
|
|
|
|
$self->playback_cache; |
|
380
|
|
|
|
|
|
|
} |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
$el = $self->{Current}; |
|
384
|
|
|
|
|
|
|
my $parent = $self->{Current} = $el->{Parent}; |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
my $name = $el->{LocalName}; |
|
387
|
|
|
|
|
|
|
# warn("end_ $name\n"); |
|
388
|
|
|
|
|
|
|
if ($name eq 'slideshow') { |
|
389
|
|
|
|
|
|
|
$self->run_todo; |
|
390
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
391
|
|
|
|
|
|
|
shift @{$self->{default_transition}}; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
$self->pop_bookmark; |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
elsif ($name eq 'title') { |
|
396
|
|
|
|
|
|
|
if ($parent->{LocalName} eq 'slideshow') { |
|
397
|
|
|
|
|
|
|
my $title = $self->gathered_text; |
|
398
|
|
|
|
|
|
|
$self->{values}->{'slideshow-title'} = $title; |
|
399
|
|
|
|
|
|
|
$self->push_todo(sub { |
|
400
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{title_font}, size => $self->{title_size}); |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
$self->push_bookmark( $self->{pdf}->add_bookmark(text => "Title", open => 1) ); |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
405
|
|
|
|
|
|
|
$self->{pdf}->print_boxed( |
|
406
|
|
|
|
|
|
|
$title, |
|
407
|
|
|
|
|
|
|
x => 20, y => 50, w => 570, h => 300, mode => "center"); |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
$self->{pdf}->print_line("") for (1..4); |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos(); |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{subtitle_font}, size => $self->{subtitle_size}); |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# speaker |
|
416
|
|
|
|
|
|
|
if ($self->{metadata}{speaker}) { |
|
417
|
|
|
|
|
|
|
$self->{pdf}->add_link(link => "mailto:" . $self->{metadata}{email}, |
|
418
|
|
|
|
|
|
|
x => 20, y => $y - 10, w => 570, h => 24) |
|
419
|
|
|
|
|
|
|
if defined $self->{metadata}{email}; |
|
420
|
|
|
|
|
|
|
$self->{pdf}->print_boxed( |
|
421
|
|
|
|
|
|
|
$self->{metadata}{speaker}, |
|
422
|
|
|
|
|
|
|
x => 20, y => 40, w => 570, h => $y - 24, mode => "center"); |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
426
|
|
|
|
|
|
|
(undef, $y) = $self->{pdf}->get_text_pos(); |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
# organisation |
|
429
|
|
|
|
|
|
|
if ($self->{metadata}{organisation}) { |
|
430
|
|
|
|
|
|
|
$self->{pdf}->add_link( |
|
431
|
|
|
|
|
|
|
link => $self->{metadata}{link}, |
|
432
|
|
|
|
|
|
|
x => 20, y => $y - 10, w => 570, h => 24); |
|
433
|
|
|
|
|
|
|
$self->{pdf}->print_boxed( |
|
434
|
|
|
|
|
|
|
$self->{metadata}{organisation}, |
|
435
|
|
|
|
|
|
|
x => 20, y => 40, w => 570, h => $y - 24, mode => "center"); |
|
436
|
|
|
|
|
|
|
} |
|
437
|
|
|
|
|
|
|
} |
|
438
|
|
|
|
|
|
|
}); |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
elsif ($parent->{LocalName} eq 'slideset') { |
|
441
|
|
|
|
|
|
|
my $title = $self->gathered_text; |
|
442
|
|
|
|
|
|
|
$self->push_bookmark( |
|
443
|
|
|
|
|
|
|
$self->{pdf}->add_bookmark( |
|
444
|
|
|
|
|
|
|
text => $title, |
|
445
|
|
|
|
|
|
|
level => 2, |
|
446
|
|
|
|
|
|
|
parent_of => $self->top_bookmark, |
|
447
|
|
|
|
|
|
|
open => 1, |
|
448
|
|
|
|
|
|
|
) |
|
449
|
|
|
|
|
|
|
); |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{title_font}, size => $self->{title_size}); |
|
452
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
453
|
|
|
|
|
|
|
$self->{pdf}->print_boxed( |
|
454
|
|
|
|
|
|
|
$title, |
|
455
|
|
|
|
|
|
|
x => 20, y => 50, w => 570, h => 200, mode => "center"); |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos(); |
|
458
|
|
|
|
|
|
|
$self->{pdf}->add_link( |
|
459
|
|
|
|
|
|
|
link => $el->{Attributes}{"{}href"}{Value}, |
|
460
|
|
|
|
|
|
|
x => 20, y => $y - 5, w => 570, h => 24) if exists($el->{Attributes}{"{}href"}); |
|
461
|
|
|
|
|
|
|
} |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
} |
|
464
|
|
|
|
|
|
|
elsif ($name eq 'metadata') { |
|
465
|
|
|
|
|
|
|
$self->run_todo; |
|
466
|
|
|
|
|
|
|
} |
|
467
|
|
|
|
|
|
|
elsif ($name eq 'total-slides') { |
|
468
|
|
|
|
|
|
|
$self->{metadata}{'total-slides'} = $self->gathered_text; |
|
469
|
|
|
|
|
|
|
} |
|
470
|
|
|
|
|
|
|
elsif ($name eq 'speaker') { |
|
471
|
|
|
|
|
|
|
$self->{metadata}{speaker} = $self->gathered_text; |
|
472
|
|
|
|
|
|
|
} |
|
473
|
|
|
|
|
|
|
elsif ($name eq 'email') { |
|
474
|
|
|
|
|
|
|
$self->{metadata}{email} = $self->gathered_text; |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
elsif ($name eq 'organisation') { |
|
477
|
|
|
|
|
|
|
$self->{metadata}{organisation} = $self->gathered_text; |
|
478
|
|
|
|
|
|
|
} |
|
479
|
|
|
|
|
|
|
elsif ($name eq 'link') { |
|
480
|
|
|
|
|
|
|
$self->{metadata}{link} = $self->gathered_text; |
|
481
|
|
|
|
|
|
|
} |
|
482
|
|
|
|
|
|
|
elsif ($name eq 'logo') { |
|
483
|
|
|
|
|
|
|
my $logo_file = |
|
484
|
|
|
|
|
|
|
File::Spec->rel2abs( |
|
485
|
|
|
|
|
|
|
$self->gathered_text, |
|
486
|
|
|
|
|
|
|
File::Basename::dirname($self->{locator}{SystemId} || '') |
|
487
|
|
|
|
|
|
|
); |
|
488
|
|
|
|
|
|
|
my $type = get_filetype($logo_file); |
|
489
|
|
|
|
|
|
|
my $logo = $self->{pdf}->load_image( |
|
490
|
|
|
|
|
|
|
filename => $logo_file, |
|
491
|
|
|
|
|
|
|
filetype => $type, |
|
492
|
|
|
|
|
|
|
) || die "Couldn't load $logo_file"; |
|
493
|
|
|
|
|
|
|
if (!$logo) { |
|
494
|
|
|
|
|
|
|
$self->{pdf}->finish; |
|
495
|
|
|
|
|
|
|
die "Cannot load image $logo_file!"; |
|
496
|
|
|
|
|
|
|
} |
|
497
|
|
|
|
|
|
|
$self->{logo}{image} = $logo; |
|
498
|
|
|
|
|
|
|
} |
|
499
|
|
|
|
|
|
|
elsif ($name eq 'background') { |
|
500
|
|
|
|
|
|
|
my $bg_file = |
|
501
|
|
|
|
|
|
|
File::Spec->rel2abs( |
|
502
|
|
|
|
|
|
|
$self->gathered_text, |
|
503
|
|
|
|
|
|
|
File::Basename::dirname($self->{locator}{SystemId} || '') |
|
504
|
|
|
|
|
|
|
); |
|
505
|
|
|
|
|
|
|
my $type = get_filetype($bg_file); |
|
506
|
|
|
|
|
|
|
my $bg = $self->{pdf}->load_image( |
|
507
|
|
|
|
|
|
|
filename => $bg_file, |
|
508
|
|
|
|
|
|
|
filetype => $type, |
|
509
|
|
|
|
|
|
|
) || die "Couldn't load $bg_file"; |
|
510
|
|
|
|
|
|
|
if (!$bg) { |
|
511
|
|
|
|
|
|
|
$self->{pdf}->finish; |
|
512
|
|
|
|
|
|
|
die "Cannot load image $bg_file!"; |
|
513
|
|
|
|
|
|
|
} |
|
514
|
|
|
|
|
|
|
$self->{bg}{image} = $bg; |
|
515
|
|
|
|
|
|
|
} |
|
516
|
|
|
|
|
|
|
elsif ($name eq 'bullet') { |
|
517
|
|
|
|
|
|
|
die "need 'level' attribute for bullet tag" if (!exists($el->{Attributes}{"{}level"})); |
|
518
|
|
|
|
|
|
|
die "'level' attribute of bullet tag must be an integer > 1" if (int($el->{Attributes}{"{}level"}) < 1); |
|
519
|
|
|
|
|
|
|
my $bullet = $self->gathered_text; |
|
520
|
|
|
|
|
|
|
die "bullet text must be a single character" if length($bullet) != 1; |
|
521
|
|
|
|
|
|
|
$self->{bullets}[int($el->{Attributes}{"{}level"}{Value})] = $bullet; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
elsif ($name eq 'numbers') { |
|
524
|
|
|
|
|
|
|
die "need 'level' attribute for numbers tag" if (!exists($el->{Attributes}{"{}level"})); |
|
525
|
|
|
|
|
|
|
die "'level' attribute of numbers tag must be an integer > 1" if (int($el->{Attributes}{"{}level"}) < 1); |
|
526
|
|
|
|
|
|
|
my $num = $self->gathered_text; |
|
527
|
|
|
|
|
|
|
$self->{numbers}[int($el->{Attributes}{"{}level"}{Value})] = $num; |
|
528
|
|
|
|
|
|
|
} |
|
529
|
|
|
|
|
|
|
elsif ($name eq 'slideset') { |
|
530
|
|
|
|
|
|
|
$self->pop_bookmark; |
|
531
|
|
|
|
|
|
|
shift @{$self->{slide_index}}; |
|
532
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
533
|
|
|
|
|
|
|
shift @{$self->{default_transition}}; |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
} |
|
536
|
|
|
|
|
|
|
elsif ($name eq 'subtitle') { |
|
537
|
|
|
|
|
|
|
if ($parent->{LocalName} eq 'slideset') { |
|
538
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{subtitle_font}, size => $self->{subtitle_size}); |
|
539
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
540
|
|
|
|
|
|
|
$self->{pdf}->print_boxed( |
|
541
|
|
|
|
|
|
|
$self->gathered_text, |
|
542
|
|
|
|
|
|
|
x => 20, y => 20, w => 570, h => 200, mode => "center"); |
|
543
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}href"})) { |
|
544
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos(); |
|
545
|
|
|
|
|
|
|
$self->{pdf}->add_link( |
|
546
|
|
|
|
|
|
|
link => $el->{Attributes}{"{}href"}{Value}, |
|
547
|
|
|
|
|
|
|
x => 20, y => $y - 5, w => 570, h => 18); |
|
548
|
|
|
|
|
|
|
} |
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
} |
|
551
|
|
|
|
|
|
|
} |
|
552
|
|
|
|
|
|
|
elsif ($name eq 'slide') { |
|
553
|
|
|
|
|
|
|
$self->run_todo; |
|
554
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
555
|
|
|
|
|
|
|
shift @{$self->{default_transition}}; |
|
556
|
|
|
|
|
|
|
} |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
elsif ($name eq 'image') { |
|
559
|
|
|
|
|
|
|
my $image = |
|
560
|
|
|
|
|
|
|
File::Spec->rel2abs( |
|
561
|
|
|
|
|
|
|
$self->gathered_text, |
|
562
|
|
|
|
|
|
|
File::Basename::dirname($self->{locator}{SystemId} || '') |
|
563
|
|
|
|
|
|
|
); |
|
564
|
|
|
|
|
|
|
my $image_ref = $self->{pdf}->load_image( |
|
565
|
|
|
|
|
|
|
filename => $image, |
|
566
|
|
|
|
|
|
|
filetype => get_filetype($image), |
|
567
|
|
|
|
|
|
|
) || die "Couldn't load $image"; |
|
568
|
|
|
|
|
|
|
my $scale = $el->{Attributes}{"{}scale"}{Value} || 1.0; |
|
569
|
|
|
|
|
|
|
my $href = $el->{Attributes}{"{}href"}{Value}; |
|
570
|
|
|
|
|
|
|
my $x = $el->{Attributes}{"{}x"}{Value}; |
|
571
|
|
|
|
|
|
|
my $y = $el->{Attributes}{"{}y"}{Value}; |
|
572
|
|
|
|
|
|
|
my $width = $el->{Attributes}{"{}width"}{Value}; |
|
573
|
|
|
|
|
|
|
my $height = $el->{Attributes}{"{}height"}{Value}; |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
push @{$self->{images}}, |
|
576
|
|
|
|
|
|
|
{ |
|
577
|
|
|
|
|
|
|
scale => $scale, |
|
578
|
|
|
|
|
|
|
image_ref => $image_ref, |
|
579
|
|
|
|
|
|
|
href => $href, |
|
580
|
|
|
|
|
|
|
x => $x, |
|
581
|
|
|
|
|
|
|
y => $y, |
|
582
|
|
|
|
|
|
|
width => $width, |
|
583
|
|
|
|
|
|
|
height => $height, |
|
584
|
|
|
|
|
|
|
}; |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
$self->{Current} = $parent; |
|
588
|
|
|
|
|
|
|
} |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub characters { |
|
591
|
|
|
|
|
|
|
my ($self, $chars) = @_; |
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
if ($self->{cache_until}) { |
|
594
|
|
|
|
|
|
|
push @{$self->{cache}}, ["slide_characters", $chars]; |
|
595
|
|
|
|
|
|
|
} |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
$self->{gathered_text} .= $self->{text_encoder}->convert($chars->{Data}); |
|
598
|
|
|
|
|
|
|
} |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub invalid_parent { |
|
601
|
|
|
|
|
|
|
my $self = shift; |
|
602
|
|
|
|
|
|
|
warn("Invalid tag nesting: <$self->{Current}{Parent}{LocalName}> <$self->{Current}{LocalName}>"); |
|
603
|
|
|
|
|
|
|
} |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub gathered_text { |
|
606
|
|
|
|
|
|
|
my $self = shift; |
|
607
|
|
|
|
|
|
|
return substr($self->{gathered_text}, 0, length($self->{gathered_text}), ''); |
|
608
|
|
|
|
|
|
|
} |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
sub image { |
|
611
|
|
|
|
|
|
|
my ($self, $scale, $file_handle, $href) = @_; |
|
612
|
|
|
|
|
|
|
my $pdf = $self->{pdf}; |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
$pdf->print_line(""); |
|
615
|
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
my ($x, $y) = $pdf->get_text_pos; |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
my @scale = split(/\*/,$scale); |
|
619
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$pdf->get_value("imagewidth", $file_handle->img),$pdf->get_value("resx", $file_handle->img)); |
|
620
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$pdf->get_value("imageheight", $file_handle->img),$pdf->get_value("resy", $file_handle->img)); |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
my $xpos = (($self->{extents}[0]{x} + ($self->{extents}[0]{w} / 2)) |
|
623
|
|
|
|
|
|
|
- ($imgw / 2)); |
|
624
|
|
|
|
|
|
|
my $ypos = ($y - $imgh); |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# warn("image: ($xpos,$ypos) $imgw x $imgh"); |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
$pdf->add_image(img => $file_handle, |
|
629
|
|
|
|
|
|
|
x => $xpos, |
|
630
|
|
|
|
|
|
|
y => $ypos, |
|
631
|
|
|
|
|
|
|
w => $imgw, |
|
632
|
|
|
|
|
|
|
h => $imgh); |
|
633
|
|
|
|
|
|
|
$pdf->add_link(link => $href, x => $xpos, y => $ypos, w => $imgw, h => $imgh) if $href; |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
$pdf->set_text_pos($x, $ypos); |
|
636
|
|
|
|
|
|
|
} |
|
637
|
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
sub bullet { |
|
639
|
|
|
|
|
|
|
my ($self, $el) = @_; |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
my $pdf = $self->{pdf}; |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
my ($char, $size); |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
my $level = $el->{Attributes}{"{}level"}{Value} || @{$self->{list_index}} || 1; |
|
646
|
|
|
|
|
|
|
my ($x, $y) = $pdf->get_text_pos; |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
if (@{$self->{xindent}} && $level <= $self->{xindent}[0]{level}) { |
|
649
|
|
|
|
|
|
|
my $last; |
|
650
|
|
|
|
|
|
|
while ($last = shift @{$self->{xindent}}) { |
|
651
|
|
|
|
|
|
|
if ($last->{level} == $level) { |
|
652
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($last->{x}, $y); |
|
653
|
|
|
|
|
|
|
$x = $last->{x}; |
|
654
|
|
|
|
|
|
|
last; |
|
655
|
|
|
|
|
|
|
} |
|
656
|
|
|
|
|
|
|
} |
|
657
|
|
|
|
|
|
|
} |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
if ($level == 1) { |
|
660
|
|
|
|
|
|
|
my $indent = 80 * ($self->{extents}[0]{w} / $self->{extents}[-1]{w}); |
|
661
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{extents}[0]{x} + $indent, $y); |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
$char = $self->{bullets}->[$level]; |
|
665
|
|
|
|
|
|
|
$size = 20-(2*$level); |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
if ($level == 1) { |
|
668
|
|
|
|
|
|
|
my ($x, $y) = $pdf->get_text_pos; |
|
669
|
|
|
|
|
|
|
$y += 9; |
|
670
|
|
|
|
|
|
|
$pdf->set_text_pos($x, $y); |
|
671
|
|
|
|
|
|
|
$pdf->print_line(""); |
|
672
|
|
|
|
|
|
|
} |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
($x, $y) = $pdf->get_text_pos; |
|
675
|
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
if (!@{$self->{xindent}} || $level > $self->{xindent}[0]{level}) { |
|
677
|
|
|
|
|
|
|
unshift @{$self->{xindent}}, {level => $level, x => $x}; |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
my $bw; |
|
681
|
|
|
|
|
|
|
if (!$el->{Attributes}{"{}level"}{Value} && @{$self->{list_index}} && $self->{list_index}->[-1] > 0) { |
|
682
|
|
|
|
|
|
|
my $index = $self->{list_index}->[-1]; |
|
683
|
|
|
|
|
|
|
$self->{list_index}->[-1]++; |
|
684
|
|
|
|
|
|
|
$char = $self->{numbers}->[$level]; |
|
685
|
|
|
|
|
|
|
$char =~ s/(([^\$]|^)(\$\$)*)\$1/$1$index/g; |
|
686
|
|
|
|
|
|
|
my $alpha = ('','a'..'z')[$index]; |
|
687
|
|
|
|
|
|
|
$char =~ s/(([^\$]|^)(\$\$)*)\$a/$1$alpha/g; |
|
688
|
|
|
|
|
|
|
$alpha = uc($alpha); |
|
689
|
|
|
|
|
|
|
$char =~ s/(([^\$]|^)(\$\$)*)\$A/$1$alpha/g; |
|
690
|
|
|
|
|
|
|
$alpha = ''; |
|
691
|
|
|
|
|
|
|
$alpha .= 'x', $index -= 10 while ($index > 10); |
|
692
|
|
|
|
|
|
|
$alpha .= ('','i','ii','iii','iv','v','vi','vii','viii','ix','x')[$index]; |
|
693
|
|
|
|
|
|
|
$char =~ s/(([^\$]|^)(\$\$)*)\$i/$1$alpha/g; |
|
694
|
|
|
|
|
|
|
$alpha = uc($alpha); |
|
695
|
|
|
|
|
|
|
$char =~ s/(([^\$]|^)(\$\$)*)\$I/$1$alpha/g; |
|
696
|
|
|
|
|
|
|
$char =~ s/\$\$/\$/g; |
|
697
|
|
|
|
|
|
|
$pdf->set_font(face => $self->{normal_font}, size => $size); |
|
698
|
|
|
|
|
|
|
$bw = $pdf->string_width(text => $char." "); |
|
699
|
|
|
|
|
|
|
$pdf->print($char); |
|
700
|
|
|
|
|
|
|
} else { |
|
701
|
|
|
|
|
|
|
$pdf->set_font(face => "ZapfDingbats", size => $size - 4, encoding => "builtin"); |
|
702
|
|
|
|
|
|
|
$bw = $pdf->string_width(text => $char); |
|
703
|
|
|
|
|
|
|
$pdf->print($char); |
|
704
|
|
|
|
|
|
|
$pdf->set_font(face => $self->{normal_font}, size => $size); |
|
705
|
|
|
|
|
|
|
} |
|
706
|
|
|
|
|
|
|
if ($pdf->string_width(text => " ") < $bw) { |
|
707
|
|
|
|
|
|
|
$pdf->print(" "); |
|
708
|
|
|
|
|
|
|
} else { |
|
709
|
|
|
|
|
|
|
$pdf->set_text_pos($x, $y); |
|
710
|
|
|
|
|
|
|
$pdf->print(" "); |
|
711
|
|
|
|
|
|
|
} |
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
return ($pdf->get_text_pos, $size); |
|
714
|
|
|
|
|
|
|
} |
|
715
|
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
sub get_filetype { |
|
717
|
|
|
|
|
|
|
my $filename = shift; |
|
718
|
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
my ($suffix) = $filename =~ /([^\.]+?)$/; |
|
720
|
|
|
|
|
|
|
$suffix = lc($suffix); |
|
721
|
|
|
|
|
|
|
if ($suffix eq 'jpg') { |
|
722
|
|
|
|
|
|
|
return 'jpeg'; |
|
723
|
|
|
|
|
|
|
} |
|
724
|
|
|
|
|
|
|
return $suffix; |
|
725
|
|
|
|
|
|
|
} |
|
726
|
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
my %colours = ( |
|
728
|
|
|
|
|
|
|
black => "000000", |
|
729
|
|
|
|
|
|
|
green => "008000", |
|
730
|
|
|
|
|
|
|
silver => "C0C0C0", |
|
731
|
|
|
|
|
|
|
lime => "00FF00", |
|
732
|
|
|
|
|
|
|
gray => "808080", |
|
733
|
|
|
|
|
|
|
olive => "808000", |
|
734
|
|
|
|
|
|
|
white => "FFFFFF", |
|
735
|
|
|
|
|
|
|
yellow => "FFFF00", |
|
736
|
|
|
|
|
|
|
maroon => "800000", |
|
737
|
|
|
|
|
|
|
navy => "000080", |
|
738
|
|
|
|
|
|
|
red => "FF0000", |
|
739
|
|
|
|
|
|
|
blue => "0000FF", |
|
740
|
|
|
|
|
|
|
purple => "800080", |
|
741
|
|
|
|
|
|
|
teal => "008080", |
|
742
|
|
|
|
|
|
|
fuchsia => "FF00FF", |
|
743
|
|
|
|
|
|
|
aqua => "00FFFF", |
|
744
|
|
|
|
|
|
|
); |
|
745
|
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
sub get_colour { |
|
747
|
|
|
|
|
|
|
my $colour = shift; |
|
748
|
|
|
|
|
|
|
if ($colour !~ s/^#//) { |
|
749
|
|
|
|
|
|
|
$colour = $colours{$colour} || die "Unknown colour: $colour"; |
|
750
|
|
|
|
|
|
|
} |
|
751
|
|
|
|
|
|
|
if ($colour !~ /^[0-9a-fA-F]{6}$/) { |
|
752
|
|
|
|
|
|
|
die "Invalid colour format: #$colour"; |
|
753
|
|
|
|
|
|
|
} |
|
754
|
|
|
|
|
|
|
my ($r, $g, $b) = map { hex()/255 } ($colour =~ /(..)/g); |
|
755
|
|
|
|
|
|
|
return [$r, $g, $b]; |
|
756
|
|
|
|
|
|
|
} |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
my $current_fill_colour = [0,0,0]; |
|
759
|
|
|
|
|
|
|
my $current_stroke_colour = [0,0,0]; |
|
760
|
|
|
|
|
|
|
my $current_rendering = 0; |
|
761
|
|
|
|
|
|
|
my $current_line_cap = 0; |
|
762
|
|
|
|
|
|
|
my $current_line_join = 0; |
|
763
|
|
|
|
|
|
|
my $current_line_width = 1; |
|
764
|
|
|
|
|
|
|
my $current_miter_limit = 10; |
|
765
|
|
|
|
|
|
|
my $current_fillrule = "winding"; |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
sub push_font { |
|
768
|
|
|
|
|
|
|
my ($self) = @_; |
|
769
|
|
|
|
|
|
|
my $pdf = $self->{bb} || $self->{pdf}; |
|
770
|
|
|
|
|
|
|
my $elt = $self->{SlideCurrent} || $self->{Current}; |
|
771
|
|
|
|
|
|
|
push @{$self->{font_stack}}, [ |
|
772
|
|
|
|
|
|
|
$pdf->get_parameter("fontname"), |
|
773
|
|
|
|
|
|
|
$pdf->get_value("fontsize"), |
|
774
|
|
|
|
|
|
|
$current_fill_colour, |
|
775
|
|
|
|
|
|
|
$current_stroke_colour, |
|
776
|
|
|
|
|
|
|
$pdf->{underline}, |
|
777
|
|
|
|
|
|
|
$elt->{LocalName}, |
|
778
|
|
|
|
|
|
|
$self->{fill}, |
|
779
|
|
|
|
|
|
|
$self->{stroke}, |
|
780
|
|
|
|
|
|
|
$current_line_cap, |
|
781
|
|
|
|
|
|
|
$current_line_join, |
|
782
|
|
|
|
|
|
|
$current_line_width, |
|
783
|
|
|
|
|
|
|
$current_miter_limit, |
|
784
|
|
|
|
|
|
|
$current_fillrule, |
|
785
|
|
|
|
|
|
|
$self->{transitional}, |
|
786
|
|
|
|
|
|
|
]; |
|
787
|
|
|
|
|
|
|
} |
|
788
|
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
sub pop_font { |
|
790
|
|
|
|
|
|
|
my ($self) = @_; |
|
791
|
|
|
|
|
|
|
my ($font, $size, $fill_colour, $stroke_colour, $underline, $name, $fill, $stroke, $lc, $lj, $lw, $ml, $fr, $trans) = @{pop @{$self->{font_stack}}}; |
|
792
|
|
|
|
|
|
|
my $pdf = $self->{bb} || $self->{pdf}; |
|
793
|
|
|
|
|
|
|
my $elt = $self->{SlideCurrent} || $self->{Current}; |
|
794
|
|
|
|
|
|
|
$pdf->set_font(face => $font, size => $size); |
|
795
|
|
|
|
|
|
|
$current_fill_colour = $fill_colour; |
|
796
|
|
|
|
|
|
|
$pdf->set_colour(rgb => $current_fill_colour, type => "fill"); |
|
797
|
|
|
|
|
|
|
$current_stroke_colour = $stroke_colour; |
|
798
|
|
|
|
|
|
|
$pdf->set_colour(rgb => $current_stroke_colour, type => "stroke"); |
|
799
|
|
|
|
|
|
|
$pdf->set_decoration($underline?"underline":"none"); |
|
800
|
|
|
|
|
|
|
$current_line_cap = $lc; |
|
801
|
|
|
|
|
|
|
$pdf->set_line_cap($lc); |
|
802
|
|
|
|
|
|
|
$current_line_join = $lj; |
|
803
|
|
|
|
|
|
|
$pdf->set_line_join($lj); |
|
804
|
|
|
|
|
|
|
$current_line_width = $lw; |
|
805
|
|
|
|
|
|
|
$pdf->set_line_width($lw); |
|
806
|
|
|
|
|
|
|
$current_miter_limit = $ml; |
|
807
|
|
|
|
|
|
|
$pdf->set_miter_limit($ml); |
|
808
|
|
|
|
|
|
|
$pdf->set_parameter("fillrule",$fr); |
|
809
|
|
|
|
|
|
|
$self->{fill} = $fill; |
|
810
|
|
|
|
|
|
|
$self->{stroke} = $stroke; |
|
811
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
812
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 2); |
|
813
|
|
|
|
|
|
|
} |
|
814
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
815
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 0); |
|
816
|
|
|
|
|
|
|
} |
|
817
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
818
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 1); |
|
819
|
|
|
|
|
|
|
} |
|
820
|
|
|
|
|
|
|
else { |
|
821
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 3); # invisible |
|
822
|
|
|
|
|
|
|
} |
|
823
|
|
|
|
|
|
|
} |
|
824
|
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
sub process_css_styles { |
|
826
|
|
|
|
|
|
|
my ($self, $style, $text_mode) = @_; |
|
827
|
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
if ($text_mode) { |
|
829
|
|
|
|
|
|
|
$self->{stroke} = 0; |
|
830
|
|
|
|
|
|
|
$self->{fill} = 1; |
|
831
|
|
|
|
|
|
|
} |
|
832
|
|
|
|
|
|
|
else { |
|
833
|
|
|
|
|
|
|
$self->{stroke} = 1; |
|
834
|
|
|
|
|
|
|
$self->{fill} = 0; |
|
835
|
|
|
|
|
|
|
} |
|
836
|
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
$self->push_font(); |
|
838
|
|
|
|
|
|
|
return unless $style; |
|
839
|
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
my $pdf = $self->{bb} || $self->{pdf}; |
|
841
|
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
my $new_font = $pdf->get_parameter("fontname"); |
|
843
|
|
|
|
|
|
|
my $bold = 0; |
|
844
|
|
|
|
|
|
|
my $italic = 0; |
|
845
|
|
|
|
|
|
|
my $underline = 0; |
|
846
|
|
|
|
|
|
|
my $size = $pdf->get_value('fontsize'); |
|
847
|
|
|
|
|
|
|
if ($new_font =~ s/-(.*)$//) { |
|
848
|
|
|
|
|
|
|
my $removed = $1; |
|
849
|
|
|
|
|
|
|
if ($removed =~ /Bold/i) { |
|
850
|
|
|
|
|
|
|
$bold = 1; |
|
851
|
|
|
|
|
|
|
} |
|
852
|
|
|
|
|
|
|
if ($removed =~ /(Oblique|Italic)/i) { |
|
853
|
|
|
|
|
|
|
$italic = 1; |
|
854
|
|
|
|
|
|
|
} |
|
855
|
|
|
|
|
|
|
} |
|
856
|
|
|
|
|
|
|
foreach my $part (split(/;\s*/s, $style)) { |
|
857
|
|
|
|
|
|
|
my ($key, $value) = split(/\s*:\s*/, $part, 2); |
|
858
|
|
|
|
|
|
|
# Keys we need to implement: |
|
859
|
|
|
|
|
|
|
# color, fill, font, font-style, font-weight, font-size, |
|
860
|
|
|
|
|
|
|
# font-family, stroke, stroke-linecap, stroke-linejoin, stroke-width, |
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
# warn("got $key = $value\n"); |
|
863
|
|
|
|
|
|
|
if ($key eq 'font') { |
|
864
|
|
|
|
|
|
|
# [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] |
|
865
|
|
|
|
|
|
|
if ($value =~ /^((\S+)\s+)?((\S+)\s+)(\S+)$/) { |
|
866
|
|
|
|
|
|
|
my ($attribs, $ptsize, $name) = ($2, $4, $5); |
|
867
|
|
|
|
|
|
|
$attribs ||= 'inherit'; |
|
868
|
|
|
|
|
|
|
if ($attribs eq 'normal') { |
|
869
|
|
|
|
|
|
|
$bold = 0; $italic = 0; |
|
870
|
|
|
|
|
|
|
} |
|
871
|
|
|
|
|
|
|
elsif ($attribs eq 'inherit') { |
|
872
|
|
|
|
|
|
|
# Do nothing |
|
873
|
|
|
|
|
|
|
} |
|
874
|
|
|
|
|
|
|
elsif ($attribs eq 'bold' || $attribs eq 'bolder') { |
|
875
|
|
|
|
|
|
|
$bold = 1; |
|
876
|
|
|
|
|
|
|
} |
|
877
|
|
|
|
|
|
|
elsif ($attribs eq 'italic' || $attribs eq 'oblique') { |
|
878
|
|
|
|
|
|
|
$italic = 1; |
|
879
|
|
|
|
|
|
|
} |
|
880
|
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
if ($ptsize !~ s/pt$//) { |
|
882
|
|
|
|
|
|
|
die "Cannot support fonts in anything but point sizes yet: $value"; |
|
883
|
|
|
|
|
|
|
} |
|
884
|
|
|
|
|
|
|
$size = $ptsize; |
|
885
|
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
$name =~ s/sans-serif/Helvetica/; |
|
887
|
|
|
|
|
|
|
$name =~ s/serif/Times/; |
|
888
|
|
|
|
|
|
|
$name =~ s/monospace/Courier/; |
|
889
|
|
|
|
|
|
|
$new_font = $name; |
|
890
|
|
|
|
|
|
|
} |
|
891
|
|
|
|
|
|
|
else { |
|
892
|
|
|
|
|
|
|
die "Failed to parse CSS font attribute: $value"; |
|
893
|
|
|
|
|
|
|
} |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
elsif ($key eq 'font-family') { |
|
896
|
|
|
|
|
|
|
$value =~ s/sans-serif/Helvetica/; |
|
897
|
|
|
|
|
|
|
$value =~ s/serif/Times/; |
|
898
|
|
|
|
|
|
|
$value =~ s/monospace/Courier/; |
|
899
|
|
|
|
|
|
|
$new_font = $value; |
|
900
|
|
|
|
|
|
|
} |
|
901
|
|
|
|
|
|
|
elsif ($key eq 'font-style') { |
|
902
|
|
|
|
|
|
|
if ($value eq 'normal') { |
|
903
|
|
|
|
|
|
|
$italic = 0; |
|
904
|
|
|
|
|
|
|
} |
|
905
|
|
|
|
|
|
|
elsif ($value eq 'italic') { |
|
906
|
|
|
|
|
|
|
$italic = 1; |
|
907
|
|
|
|
|
|
|
} |
|
908
|
|
|
|
|
|
|
} |
|
909
|
|
|
|
|
|
|
elsif ($key eq 'font-weight') { |
|
910
|
|
|
|
|
|
|
if ($value eq 'normal') { |
|
911
|
|
|
|
|
|
|
$bold = 0; |
|
912
|
|
|
|
|
|
|
} |
|
913
|
|
|
|
|
|
|
elsif ($value eq 'bold') { |
|
914
|
|
|
|
|
|
|
$bold = 1; |
|
915
|
|
|
|
|
|
|
} |
|
916
|
|
|
|
|
|
|
} |
|
917
|
|
|
|
|
|
|
elsif ($key eq 'text-decoration') { |
|
918
|
|
|
|
|
|
|
if ($value eq 'none') { |
|
919
|
|
|
|
|
|
|
$underline = 0; |
|
920
|
|
|
|
|
|
|
} |
|
921
|
|
|
|
|
|
|
elsif ($value eq 'underline') { |
|
922
|
|
|
|
|
|
|
$underline = 1; |
|
923
|
|
|
|
|
|
|
} |
|
924
|
|
|
|
|
|
|
} |
|
925
|
|
|
|
|
|
|
elsif ($key eq 'font-size') { |
|
926
|
|
|
|
|
|
|
if ($value !~ s/pt$// && $value =~ m/[a-z]/) { |
|
927
|
|
|
|
|
|
|
die "Can't do anything but font-size in pt yet"; |
|
928
|
|
|
|
|
|
|
} |
|
929
|
|
|
|
|
|
|
$size = $value; |
|
930
|
|
|
|
|
|
|
} |
|
931
|
|
|
|
|
|
|
elsif ($key eq 'color') { |
|
932
|
|
|
|
|
|
|
# set both the stroke and fill color |
|
933
|
|
|
|
|
|
|
$current_fill_colour = $current_stroke_colour = get_colour($value); |
|
934
|
|
|
|
|
|
|
$pdf->set_colour(rgb => $current_fill_colour, type => "both"); |
|
935
|
|
|
|
|
|
|
} |
|
936
|
|
|
|
|
|
|
elsif ($key eq 'fill') { |
|
937
|
|
|
|
|
|
|
if ($value eq 'none') { |
|
938
|
|
|
|
|
|
|
$self->{fill} = 0; |
|
939
|
|
|
|
|
|
|
} |
|
940
|
|
|
|
|
|
|
else { |
|
941
|
|
|
|
|
|
|
# it's a color |
|
942
|
|
|
|
|
|
|
$self->{fill} = 1; |
|
943
|
|
|
|
|
|
|
$current_fill_colour = get_colour($value); |
|
944
|
|
|
|
|
|
|
$pdf->set_colour(rgb => $current_fill_colour, type => "fill"); |
|
945
|
|
|
|
|
|
|
} |
|
946
|
|
|
|
|
|
|
} |
|
947
|
|
|
|
|
|
|
elsif ($key eq 'fill-rule') { |
|
948
|
|
|
|
|
|
|
$value = 'winding' if $value eq 'nonzero'; |
|
949
|
|
|
|
|
|
|
$pdf->set_parameter(fillrule => $value); |
|
950
|
|
|
|
|
|
|
$current_fillrule = $value; |
|
951
|
|
|
|
|
|
|
} |
|
952
|
|
|
|
|
|
|
elsif ($key eq 'stroke') { |
|
953
|
|
|
|
|
|
|
if ($value eq 'none') { |
|
954
|
|
|
|
|
|
|
$self->{stroke} = 0; |
|
955
|
|
|
|
|
|
|
} |
|
956
|
|
|
|
|
|
|
else { |
|
957
|
|
|
|
|
|
|
# it's a color |
|
958
|
|
|
|
|
|
|
$self->{stroke} = 1; |
|
959
|
|
|
|
|
|
|
$current_stroke_colour = get_colour($value); |
|
960
|
|
|
|
|
|
|
$pdf->set_colour(rgb => $current_stroke_colour, type => "stroke"); |
|
961
|
|
|
|
|
|
|
} |
|
962
|
|
|
|
|
|
|
} |
|
963
|
|
|
|
|
|
|
elsif ($key eq 'stroke-linecap') { |
|
964
|
|
|
|
|
|
|
$pdf->set_line_cap("${value}_end"); # PDFLib takes care of butt|round|square |
|
965
|
|
|
|
|
|
|
$current_line_cap = $value; |
|
966
|
|
|
|
|
|
|
} |
|
967
|
|
|
|
|
|
|
elsif ($key eq 'stroke-linejoin') { |
|
968
|
|
|
|
|
|
|
$pdf->set_line_join($value); # PDFLib takes care of miter|round|bevel |
|
969
|
|
|
|
|
|
|
$current_line_join = $value; |
|
970
|
|
|
|
|
|
|
} |
|
971
|
|
|
|
|
|
|
elsif ($key eq 'stroke-width') { |
|
972
|
|
|
|
|
|
|
$pdf->set_line_width($value); |
|
973
|
|
|
|
|
|
|
$current_line_width = $value; |
|
974
|
|
|
|
|
|
|
} |
|
975
|
|
|
|
|
|
|
elsif ($key eq 'stroke-miterlimit') { |
|
976
|
|
|
|
|
|
|
$pdf->set_miter_limit($value); |
|
977
|
|
|
|
|
|
|
$current_miter_limit = $value; |
|
978
|
|
|
|
|
|
|
} |
|
979
|
|
|
|
|
|
|
} |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
return unless $text_mode; |
|
982
|
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
$pdf->set_decoration($underline?"underline":"none"); |
|
984
|
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
my $ok = 0; |
|
986
|
|
|
|
|
|
|
# warn(sprintf("set_font(%s => %s, %s => %s, %s => %s, %s => %s)\n", |
|
987
|
|
|
|
|
|
|
# face => $new_font, |
|
988
|
|
|
|
|
|
|
# italic => $italic, |
|
989
|
|
|
|
|
|
|
# bold => $bold, |
|
990
|
|
|
|
|
|
|
# size => $size, |
|
991
|
|
|
|
|
|
|
# ) |
|
992
|
|
|
|
|
|
|
# ); |
|
993
|
|
|
|
|
|
|
foreach my $face (split(/\s*/, $new_font)) { |
|
994
|
|
|
|
|
|
|
eval { |
|
995
|
|
|
|
|
|
|
$pdf->set_font( |
|
996
|
|
|
|
|
|
|
face => $new_font, |
|
997
|
|
|
|
|
|
|
italic => $italic, |
|
998
|
|
|
|
|
|
|
bold => $bold, |
|
999
|
|
|
|
|
|
|
size => $size, |
|
1000
|
|
|
|
|
|
|
); |
|
1001
|
|
|
|
|
|
|
}; |
|
1002
|
|
|
|
|
|
|
if (!$@) { |
|
1003
|
|
|
|
|
|
|
$ok = 1; |
|
1004
|
|
|
|
|
|
|
last; |
|
1005
|
|
|
|
|
|
|
} |
|
1006
|
|
|
|
|
|
|
} |
|
1007
|
|
|
|
|
|
|
if (!$ok) { |
|
1008
|
|
|
|
|
|
|
die "Unable to find font: $new_font : $@"; |
|
1009
|
|
|
|
|
|
|
} |
|
1010
|
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1012
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 2); |
|
1013
|
|
|
|
|
|
|
} |
|
1014
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1015
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 0); |
|
1016
|
|
|
|
|
|
|
} |
|
1017
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1018
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 1); |
|
1019
|
|
|
|
|
|
|
} |
|
1020
|
|
|
|
|
|
|
else { |
|
1021
|
|
|
|
|
|
|
$pdf->set_value(textrendering => 3); # invisible |
|
1022
|
|
|
|
|
|
|
} |
|
1023
|
|
|
|
|
|
|
} |
|
1024
|
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
sub slide_start_element { |
|
1026
|
|
|
|
|
|
|
my ($self, $el) = @_; |
|
1027
|
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
$self->{SlideCurrent} = $el; |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
my $name = $el->{LocalName}; |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
#warn("slide_start_ $name ".join(",",map { $_."=>".$el->{Attributes}{$_}->{Value} } keys %{$el->{Attributes}})."\n"); |
|
1033
|
|
|
|
|
|
|
|
|
1034
|
|
|
|
|
|
|
# transitions... |
|
1035
|
|
|
|
|
|
|
if ( (!$self->{PrintMode}) && |
|
1036
|
|
|
|
|
|
|
$name =~ /^(point|plain|image|source[_-]code|table|col|row|circle|ellipse|rect|text|line|path)$/) { |
|
1037
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}transition"}) |
|
1038
|
|
|
|
|
|
|
|| @{$self->{default_transition}}) { |
|
1039
|
|
|
|
|
|
|
# has a transition |
|
1040
|
|
|
|
|
|
|
my $trans = $el->{Attributes}{"{}transition"}; |
|
1041
|
|
|
|
|
|
|
# default transition if unspecified (and not for table tags) |
|
1042
|
|
|
|
|
|
|
if ( (!$trans) && ($name ne 'table') && ($name ne 'row') && ($name ne 'col') && ($name ne 'box') ) { |
|
1043
|
|
|
|
|
|
|
$trans = { Value => $self->{default_transition}[0] }; |
|
1044
|
|
|
|
|
|
|
} |
|
1045
|
|
|
|
|
|
|
if ($trans && ($trans->{Value} ne 'none') ) { |
|
1046
|
|
|
|
|
|
|
my @cache = @{$self->{cache_trash}}; |
|
1047
|
|
|
|
|
|
|
local $self->{cache} = \@cache; |
|
1048
|
|
|
|
|
|
|
local $self->{cache_trash}; |
|
1049
|
|
|
|
|
|
|
# warn("playback on $el\n"); |
|
1050
|
|
|
|
|
|
|
$self->{transitional} = 1; |
|
1051
|
|
|
|
|
|
|
my $parent = $el->{Parent}; |
|
1052
|
|
|
|
|
|
|
while ($parent) { |
|
1053
|
|
|
|
|
|
|
last if $parent->{LocalName} eq 'slide'; |
|
1054
|
|
|
|
|
|
|
$parent = $parent->{Parent}; |
|
1055
|
|
|
|
|
|
|
} |
|
1056
|
|
|
|
|
|
|
die "No parent slide element" unless $parent; |
|
1057
|
|
|
|
|
|
|
local $parent->{Attributes}{"{}transition"}{Value} = $trans->{Value}; |
|
1058
|
|
|
|
|
|
|
$self->playback_cache; # should get us back here. |
|
1059
|
|
|
|
|
|
|
$self->run_todo; |
|
1060
|
|
|
|
|
|
|
# make sure we don't transition this node again |
|
1061
|
|
|
|
|
|
|
$el->{Attributes}{"{}transition"}{Value} = 'none'; |
|
1062
|
|
|
|
|
|
|
# warn("playback returns\n"); |
|
1063
|
|
|
|
|
|
|
$self->{transitional} = 0; |
|
1064
|
|
|
|
|
|
|
pop @{$self->{font_stack}} while (@{$self->{font_stack}} && $self->{font_stack}[-1][-1]); |
|
1065
|
|
|
|
|
|
|
} |
|
1066
|
|
|
|
|
|
|
} else { |
|
1067
|
|
|
|
|
|
|
$el->{Attributes}{"{}transition"}{Value} = 'none'; |
|
1068
|
|
|
|
|
|
|
} |
|
1069
|
|
|
|
|
|
|
} |
|
1070
|
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
if ($name =~ m/^(table|list|image|source[-_]code)$/ && $el->{Attributes}{'{}title'}) { |
|
1072
|
|
|
|
|
|
|
$self->push_font(); |
|
1073
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{normal_font}, italic => 1, size => 15); |
|
1074
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
1075
|
|
|
|
|
|
|
my $indent = 80 * ($self->{extents}[0]{w} / $self->{extents}[-1]{w}); |
|
1076
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{bb}?$self->{bb}->{x}:$self->{extents}[0]{x}+$indent, $y); |
|
1077
|
|
|
|
|
|
|
$self->{pdf}->print($el->{Attributes}{'{}title'}{Value}); |
|
1078
|
|
|
|
|
|
|
$self->{pdf}->print_line("") unless $name eq 'image'; |
|
1079
|
|
|
|
|
|
|
$self->pop_font(); |
|
1080
|
|
|
|
|
|
|
} |
|
1081
|
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
if ($name eq 'slide') { |
|
1083
|
|
|
|
|
|
|
$self->new_page(undef,$el->{Attributes}{"{}type"}{Value}); |
|
1084
|
|
|
|
|
|
|
$self->{image_id} = 0; |
|
1085
|
|
|
|
|
|
|
# if we do bullet/image transitions, make sure new pages don't use a transition |
|
1086
|
|
|
|
|
|
|
$el->{Attributes}{"{}transition"}{Value} = "replace"; |
|
1087
|
|
|
|
|
|
|
$self->{extents} = [{ x => 0, w => 612 }]; |
|
1088
|
|
|
|
|
|
|
} |
|
1089
|
|
|
|
|
|
|
elsif ($name eq 'title') { |
|
1090
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
1091
|
|
|
|
|
|
|
$self->{chars_ok} = 1; |
|
1092
|
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
1094
|
|
|
|
|
|
|
my $bb = $self->{pdf}->new_bounding_box( |
|
1095
|
|
|
|
|
|
|
x => 5, y => 400, w => 602, h => 50, |
|
1096
|
|
|
|
|
|
|
align => "centre", |
|
1097
|
|
|
|
|
|
|
); |
|
1098
|
|
|
|
|
|
|
$self->{bb} = $bb; |
|
1099
|
|
|
|
|
|
|
$bb->set_font( |
|
1100
|
|
|
|
|
|
|
face => $self->{title_font}, |
|
1101
|
|
|
|
|
|
|
size => $self->{title_size}, |
|
1102
|
|
|
|
|
|
|
); |
|
1103
|
|
|
|
|
|
|
} |
|
1104
|
|
|
|
|
|
|
} |
|
1105
|
|
|
|
|
|
|
elsif ($name eq 'table') { |
|
1106
|
|
|
|
|
|
|
# push extents. |
|
1107
|
|
|
|
|
|
|
$self->{extents} = [{ %{$self->{extents}[0]} }, @{$self->{extents}}]; |
|
1108
|
|
|
|
|
|
|
$self->{col_widths} = []; |
|
1109
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
1110
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{extents}[1]{x}, $y); |
|
1111
|
|
|
|
|
|
|
$self->{max_height} = $y; |
|
1112
|
|
|
|
|
|
|
$self->{row_number} = 0; |
|
1113
|
|
|
|
|
|
|
} |
|
1114
|
|
|
|
|
|
|
elsif ($name eq 'box') { |
|
1115
|
|
|
|
|
|
|
if (!$self->{transitional}) { |
|
1116
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}default-transition"})) { |
|
1117
|
|
|
|
|
|
|
unshift @{$self->{default_transition}}, $el->{Attributes}{"{}default-transition"}{Value}; |
|
1118
|
|
|
|
|
|
|
unshift @{$self->{boxtransition}}, 1; |
|
1119
|
|
|
|
|
|
|
delete $el->{Attributes}{"{}default-transition"}; |
|
1120
|
|
|
|
|
|
|
} else { |
|
1121
|
|
|
|
|
|
|
unshift @{$self->{boxtransition}}, 0; |
|
1122
|
|
|
|
|
|
|
} |
|
1123
|
|
|
|
|
|
|
} |
|
1124
|
|
|
|
|
|
|
# push extents. |
|
1125
|
|
|
|
|
|
|
$self->{extents} = [{ %{$self->{extents}[0]} }, @{$self->{extents}}]; |
|
1126
|
|
|
|
|
|
|
$self->{extents}[0]{x} = $el->{Attributes}{'{}x'}{Value}; |
|
1127
|
|
|
|
|
|
|
$self->{extents}[0]{w} = $el->{Attributes}{'{}width'}{Value}; |
|
1128
|
|
|
|
|
|
|
$self->{extents}[0]{y} = $el->{Attributes}{'{}y'}{Value}; |
|
1129
|
|
|
|
|
|
|
$self->{extents}[0]{h} = $el->{Attributes}{'{}height'}{Value}; |
|
1130
|
|
|
|
|
|
|
$self->{boxlast} = [ $self->{pdf}->get_text_pos() ]; |
|
1131
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{extents}[0]{x}, $self->{extents}[0]{y}); |
|
1132
|
|
|
|
|
|
|
} |
|
1133
|
|
|
|
|
|
|
elsif ($name eq 'row') { |
|
1134
|
|
|
|
|
|
|
$self->{col_number} = 0; |
|
1135
|
|
|
|
|
|
|
$self->{row_start} = []; |
|
1136
|
|
|
|
|
|
|
@{$self->{row_start}} = $self->{pdf}->get_text_pos; |
|
1137
|
|
|
|
|
|
|
} |
|
1138
|
|
|
|
|
|
|
elsif ($name eq 'col') { |
|
1139
|
|
|
|
|
|
|
my $width; |
|
1140
|
|
|
|
|
|
|
my $prev_x = $self->{extents}[1]{x}; |
|
1141
|
|
|
|
|
|
|
if ($self->{row_number} > 0) { |
|
1142
|
|
|
|
|
|
|
$width = $self->{col_widths}[$self->{col_number}]; |
|
1143
|
|
|
|
|
|
|
} |
|
1144
|
|
|
|
|
|
|
else { |
|
1145
|
|
|
|
|
|
|
$width = $el->{Attributes}{"{}width"}{Value}; |
|
1146
|
|
|
|
|
|
|
$width =~ s/%$// || die "Column widths must be in percentages"; |
|
1147
|
|
|
|
|
|
|
# warn("calculating ${width}% of $self->{extents}[1]{w}\n"); |
|
1148
|
|
|
|
|
|
|
$width = $self->{extents}[1]{w} * ($width/100); |
|
1149
|
|
|
|
|
|
|
$self->{col_widths}[$self->{col_number}] = $width; |
|
1150
|
|
|
|
|
|
|
} |
|
1151
|
|
|
|
|
|
|
if ($self->{col_number} > 0) { |
|
1152
|
|
|
|
|
|
|
my $up_to = $self->{col_number} - 1; |
|
1153
|
|
|
|
|
|
|
foreach my $col (0 .. $up_to) { |
|
1154
|
|
|
|
|
|
|
$prev_x += $self->{col_widths}[$col]; |
|
1155
|
|
|
|
|
|
|
} |
|
1156
|
|
|
|
|
|
|
} |
|
1157
|
|
|
|
|
|
|
# warn("col setting extents to x => $prev_x, w => $width\n"); |
|
1158
|
|
|
|
|
|
|
$self->{extents}[0]{x} = $prev_x; |
|
1159
|
|
|
|
|
|
|
$self->{extents}[0]{w} = $width; |
|
1160
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos(@{$self->{row_start}}); |
|
1161
|
|
|
|
|
|
|
} |
|
1162
|
|
|
|
|
|
|
elsif ($name eq 'value') { |
|
1163
|
|
|
|
|
|
|
my $type = $el->{Attributes}{'{}type'}{Value}; |
|
1164
|
|
|
|
|
|
|
my $pdf = $self->{bb} || $self->{pdf}; |
|
1165
|
|
|
|
|
|
|
if (exists $self->{values}->{$type}) { |
|
1166
|
|
|
|
|
|
|
$pdf->print($self->{values}->{$type}); |
|
1167
|
|
|
|
|
|
|
} elsif (exists $self->{metadata}->{$type}) { |
|
1168
|
|
|
|
|
|
|
$pdf->print($self->{metadata}->{$type}); |
|
1169
|
|
|
|
|
|
|
} elsif ($type eq 'today') { |
|
1170
|
|
|
|
|
|
|
$pdf->print(localtime->strftime($el->{Attributes}{'{}format'}{Value}||'%Y-%m-%d')); |
|
1171
|
|
|
|
|
|
|
} elsif ($type eq 'logo') { |
|
1172
|
|
|
|
|
|
|
if (my $logo = $self->{logo}) { |
|
1173
|
|
|
|
|
|
|
my @scale = split(/\*/,$logo->{scale}); |
|
1174
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$self->{pdf}->get_value("imagewidth", $logo->{image}->img),$self->{pdf}->get_value("resx", $logo->{image}->img)); |
|
1175
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$self->{pdf}->get_value("imageheight", $logo->{image}->img),$self->{pdf}->get_value("resy", $logo->{image}->img)); |
|
1176
|
|
|
|
|
|
|
my ($x, $y) = $pdf->get_text_pos(); |
|
1177
|
|
|
|
|
|
|
if ($self->{bb}) { |
|
1178
|
|
|
|
|
|
|
$pdf->push_todo('add_image',img => $logo->{image}, x => $x+$pdf->{cur_width}, y => $y, w => $imgw, h => $imgh); |
|
1179
|
|
|
|
|
|
|
$pdf->push_todo('set_text_pos',$x+$pdf->{cur_width}+$imgw,$y); |
|
1180
|
|
|
|
|
|
|
} else { |
|
1181
|
|
|
|
|
|
|
$pdf->add_image(img => $logo->{image}, x => $x, y => $y, w => $imgw, h => $imgh); |
|
1182
|
|
|
|
|
|
|
} |
|
1183
|
|
|
|
|
|
|
} |
|
1184
|
|
|
|
|
|
|
} elsif ($type eq 'background') { |
|
1185
|
|
|
|
|
|
|
if (my $bg = $self->{bg}) { |
|
1186
|
|
|
|
|
|
|
my @scale = split(/\*/,$bg->{scale}); |
|
1187
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$self->{pdf}->get_value("imagewidth", $bg->{image}->img),$self->{pdf}->get_value("resx", $bg->{image}->img)); |
|
1188
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$self->{pdf}->get_value("imageheight", $bg->{image}->img),$self->{pdf}->get_value("resy", $bg->{image}->img)); |
|
1189
|
|
|
|
|
|
|
my ($x, $y) = $pdf->get_text_pos(); |
|
1190
|
|
|
|
|
|
|
if ($self->{bb}) { |
|
1191
|
|
|
|
|
|
|
$pdf->push_todo('add_image',img => $bg->{image}, x => $x+$pdf->{cur_width}, y => $y, w => $imgw, h => $imgh); |
|
1192
|
|
|
|
|
|
|
$pdf->push_todo('set_text_pos',$x+$pdf->{cur_width}+$imgw,$y); |
|
1193
|
|
|
|
|
|
|
} else { |
|
1194
|
|
|
|
|
|
|
$pdf->add_image(img => $bg->{image}, x => $x, y => $y, w => $imgw, h => $imgh); |
|
1195
|
|
|
|
|
|
|
} |
|
1196
|
|
|
|
|
|
|
} |
|
1197
|
|
|
|
|
|
|
} elsif ($type eq 'current-slideset') { |
|
1198
|
|
|
|
|
|
|
$pdf->print(join(".",reverse @{$self->{slide_index}}).". "); |
|
1199
|
|
|
|
|
|
|
} |
|
1200
|
|
|
|
|
|
|
} |
|
1201
|
|
|
|
|
|
|
elsif ($name eq 'i') { |
|
1202
|
|
|
|
|
|
|
my $new = $self->{pdf}->get_parameter("fontname") || $self->{normal_font}; |
|
1203
|
|
|
|
|
|
|
my $bold = 0; |
|
1204
|
|
|
|
|
|
|
if ($new =~ s/-(.*)$//) { |
|
1205
|
|
|
|
|
|
|
my $removed = $1; |
|
1206
|
|
|
|
|
|
|
if ($removed =~ /Bold/i) { |
|
1207
|
|
|
|
|
|
|
$bold = 1; |
|
1208
|
|
|
|
|
|
|
} |
|
1209
|
|
|
|
|
|
|
} |
|
1210
|
|
|
|
|
|
|
$self->push_font(); |
|
1211
|
|
|
|
|
|
|
$self->{bb}->set_font(face => $new, italic => 1, bold => $bold); |
|
1212
|
|
|
|
|
|
|
} |
|
1213
|
|
|
|
|
|
|
elsif ($name eq 'b') { |
|
1214
|
|
|
|
|
|
|
my $new = $self->{pdf}->get_parameter("fontname") || $self->{normal_font}; |
|
1215
|
|
|
|
|
|
|
my $italic = 0; |
|
1216
|
|
|
|
|
|
|
if ($new =~ s/-(.*)$//) { |
|
1217
|
|
|
|
|
|
|
my $removed = $1; |
|
1218
|
|
|
|
|
|
|
if ($removed =~ /(Oblique|Italic)/i) { |
|
1219
|
|
|
|
|
|
|
$italic = 1; |
|
1220
|
|
|
|
|
|
|
} |
|
1221
|
|
|
|
|
|
|
} |
|
1222
|
|
|
|
|
|
|
$self->push_font(); |
|
1223
|
|
|
|
|
|
|
$self->{bb}->set_font(face => $new, italic => $italic, bold => 1); |
|
1224
|
|
|
|
|
|
|
} |
|
1225
|
|
|
|
|
|
|
elsif ($name eq 'u') { |
|
1226
|
|
|
|
|
|
|
$self->push_font(); |
|
1227
|
|
|
|
|
|
|
$self->{bb}->set_decoration("underline"); |
|
1228
|
|
|
|
|
|
|
} |
|
1229
|
|
|
|
|
|
|
elsif ($name eq 'plain') { |
|
1230
|
|
|
|
|
|
|
$self->{chars_ok} = 1; |
|
1231
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
1232
|
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
my $indent = 80 * ($self->{extents}[0]{w} / $self->{extents}[-1]{w}); |
|
1234
|
|
|
|
|
|
|
$y += 9; |
|
1235
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{extents}[0]{x} + $indent, $y); |
|
1236
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{normal_font}, size => 18); |
|
1237
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
1238
|
|
|
|
|
|
|
|
|
1239
|
|
|
|
|
|
|
($x, $y) = $self->{pdf}->get_text_pos; |
|
1240
|
|
|
|
|
|
|
my $align = $el->{Attributes}{"{}align"}{Value} || 'left'; |
|
1241
|
|
|
|
|
|
|
my $bb = $self->{pdf}->new_bounding_box( |
|
1242
|
|
|
|
|
|
|
x => $x, y => $y, w => ($self->{extents}[0]{w} - ($x - $self->{extents}[0]{x})), h => $y, align => $align |
|
1243
|
|
|
|
|
|
|
); |
|
1244
|
|
|
|
|
|
|
$self->{bb} = $bb; |
|
1245
|
|
|
|
|
|
|
} |
|
1246
|
|
|
|
|
|
|
elsif ($name eq 'point') { |
|
1247
|
|
|
|
|
|
|
$self->{chars_ok} = 1; |
|
1248
|
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
my ($x, $y, $size) = $self->bullet($el); |
|
1250
|
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
# warn(sprintf("creating new bb: %s => %d, %s => %d, %s => %d, %s => %d", |
|
1252
|
|
|
|
|
|
|
# x => $x, y => $y, w => ($self->{extents}[0]{w} - ($x - $self->{extents}[0]{x})), h => (450 - $y) |
|
1253
|
|
|
|
|
|
|
# )); |
|
1254
|
|
|
|
|
|
|
my $bb = $self->{pdf}->new_bounding_box( |
|
1255
|
|
|
|
|
|
|
x => $x, y => $y, w => ($self->{extents}[0]{w} - ($x - $self->{extents}[0]{x})), h => $y |
|
1256
|
|
|
|
|
|
|
); |
|
1257
|
|
|
|
|
|
|
$self->{bb} = $bb; |
|
1258
|
|
|
|
|
|
|
} |
|
1259
|
|
|
|
|
|
|
elsif ($name eq 'image') { |
|
1260
|
|
|
|
|
|
|
my $image = $self->{images}[$self->{image_id}]; |
|
1261
|
|
|
|
|
|
|
my ($scale, $handle, $href) = |
|
1262
|
|
|
|
|
|
|
($image->{scale}, $image->{image_ref}, $image->{href}); |
|
1263
|
|
|
|
|
|
|
if (defined($image->{x}) && defined($image->{y})) { |
|
1264
|
|
|
|
|
|
|
my $pdf = $self->{pdf}; |
|
1265
|
|
|
|
|
|
|
my @scale = split(/\*/,$scale); |
|
1266
|
|
|
|
|
|
|
my $imgw = $self->get_scale($scale[0],0,$pdf->get_value("imagewidth", $handle->img),$pdf->get_value("resx", $handle->img)); |
|
1267
|
|
|
|
|
|
|
my $imgh = $self->get_scale($scale[1]||$scale[0],1,$pdf->get_value("imageheight", $handle->img),$pdf->get_value("resy", $handle->img)); |
|
1268
|
|
|
|
|
|
|
$pdf->add_image(img => $handle, |
|
1269
|
|
|
|
|
|
|
x => $image->{x}, |
|
1270
|
|
|
|
|
|
|
y => $image->{y}, |
|
1271
|
|
|
|
|
|
|
w => $imgw, |
|
1272
|
|
|
|
|
|
|
h => $imgh |
|
1273
|
|
|
|
|
|
|
); |
|
1274
|
|
|
|
|
|
|
} |
|
1275
|
|
|
|
|
|
|
else { |
|
1276
|
|
|
|
|
|
|
$self->image($scale, $handle, $href); |
|
1277
|
|
|
|
|
|
|
} |
|
1278
|
|
|
|
|
|
|
} |
|
1279
|
|
|
|
|
|
|
elsif ($name eq 'source_code' || $name eq 'source-code') { |
|
1280
|
|
|
|
|
|
|
my $size = $el->{Attributes}{"{}fontsize"}{Value} || 14; |
|
1281
|
|
|
|
|
|
|
$self->{chars_ok} = 1; |
|
1282
|
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
1284
|
|
|
|
|
|
|
my $indent = 80 * ($self->{extents}[0]{w} / $self->{extents}[-1]{w}); |
|
1285
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{extents}[0]{x} + $indent, $y); |
|
1286
|
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
$self->push_font(); |
|
1288
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => "Courier", size => $size); |
|
1289
|
|
|
|
|
|
|
($x, $y) = $self->{pdf}->get_text_pos; |
|
1290
|
|
|
|
|
|
|
my $bb = $self->{pdf}->new_bounding_box( |
|
1291
|
|
|
|
|
|
|
x => $x, y => $y, w => ($self->{extents}[0]{w} - ($x - $self->{extents}[0]{x})), h => $y, |
|
1292
|
|
|
|
|
|
|
wrap => 0, |
|
1293
|
|
|
|
|
|
|
); |
|
1294
|
|
|
|
|
|
|
# warn("new_bounding_box( h => $y ) => $bb\n"); |
|
1295
|
|
|
|
|
|
|
$self->{bb} = $bb; |
|
1296
|
|
|
|
|
|
|
} |
|
1297
|
|
|
|
|
|
|
elsif ($name eq 'color' || $name eq 'colour') { |
|
1298
|
|
|
|
|
|
|
my $hex_colour; |
|
1299
|
|
|
|
|
|
|
if (exists($el->{Attributes}{"{}name"})) { |
|
1300
|
|
|
|
|
|
|
my $colour = lc($el->{Attributes}{"{}name"}{Value}); |
|
1301
|
|
|
|
|
|
|
$hex_colour = $colours{$colour} |
|
1302
|
|
|
|
|
|
|
|| die "No such colour: $colour"; |
|
1303
|
|
|
|
|
|
|
} |
|
1304
|
|
|
|
|
|
|
else { |
|
1305
|
|
|
|
|
|
|
$hex_colour = $el->{Attributes}{"{}rgb"}{Value}; |
|
1306
|
|
|
|
|
|
|
} |
|
1307
|
|
|
|
|
|
|
if (!$hex_colour) { |
|
1308
|
|
|
|
|
|
|
die "Missing colour attribute: name or rgb (found: " . join(', ', keys(%{$el->{Attributes}})) .")"; |
|
1309
|
|
|
|
|
|
|
} |
|
1310
|
|
|
|
|
|
|
$hex_colour =~ s/^#//; |
|
1311
|
|
|
|
|
|
|
if ($hex_colour !~ /^[0-9a-fA-F]{6}$/) { |
|
1312
|
|
|
|
|
|
|
die "Invalid hex format: $hex_colour"; |
|
1313
|
|
|
|
|
|
|
} |
|
1314
|
|
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
my ($r, $g, $b) = map { hex()/255 } ($hex_colour =~ /(..)/g); |
|
1316
|
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
$self->push_font(); |
|
1318
|
|
|
|
|
|
|
$self->{bb}->set_color(rgb => [$r,$g,$b]); |
|
1319
|
|
|
|
|
|
|
} |
|
1320
|
|
|
|
|
|
|
elsif ($name eq 'span') { |
|
1321
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}, 1); |
|
1322
|
|
|
|
|
|
|
} |
|
1323
|
|
|
|
|
|
|
elsif ($name eq 'g') { |
|
1324
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}, 1); |
|
1325
|
|
|
|
|
|
|
} |
|
1326
|
|
|
|
|
|
|
elsif ($name eq 'rect') { |
|
1327
|
|
|
|
|
|
|
my ($x, $y, $width, $height) = ( |
|
1328
|
|
|
|
|
|
|
$el->{Attributes}{"{}x"}{Value}, |
|
1329
|
|
|
|
|
|
|
$el->{Attributes}{"{}y"}{Value}, |
|
1330
|
|
|
|
|
|
|
$el->{Attributes}{"{}width"}{Value}, |
|
1331
|
|
|
|
|
|
|
$el->{Attributes}{"{}height"}{Value}, |
|
1332
|
|
|
|
|
|
|
); |
|
1333
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1334
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}); |
|
1335
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1336
|
|
|
|
|
|
|
$self->{pdf}->rect(x => $x, y => $self->{pdf}->get_value('pageheight')-$y-$height, w => $width, h => $height); |
|
1337
|
|
|
|
|
|
|
} |
|
1338
|
|
|
|
|
|
|
else { |
|
1339
|
|
|
|
|
|
|
$self->{pdf}->rect(x => $x, y => $y, w => $width, h => $height); |
|
1340
|
|
|
|
|
|
|
} |
|
1341
|
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1343
|
|
|
|
|
|
|
$self->{pdf}->fill_stroke; |
|
1344
|
|
|
|
|
|
|
} |
|
1345
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1346
|
|
|
|
|
|
|
$self->{pdf}->fill; |
|
1347
|
|
|
|
|
|
|
} |
|
1348
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1349
|
|
|
|
|
|
|
$self->{pdf}->stroke; |
|
1350
|
|
|
|
|
|
|
} |
|
1351
|
|
|
|
|
|
|
} |
|
1352
|
|
|
|
|
|
|
elsif ($name eq 'circle') { |
|
1353
|
|
|
|
|
|
|
my ($cx, $cy, $r) = ( |
|
1354
|
|
|
|
|
|
|
$el->{Attributes}{"{}cx"}{Value}, |
|
1355
|
|
|
|
|
|
|
$el->{Attributes}{"{}cy"}{Value}, |
|
1356
|
|
|
|
|
|
|
$el->{Attributes}{"{}r"}{Value}, |
|
1357
|
|
|
|
|
|
|
); |
|
1358
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1359
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}); |
|
1360
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1361
|
|
|
|
|
|
|
$self->{pdf}->circle(x => $cx, y => $self->{pdf}->get_value('pageheight')-$cy, r => $r); |
|
1362
|
|
|
|
|
|
|
} |
|
1363
|
|
|
|
|
|
|
else { |
|
1364
|
|
|
|
|
|
|
$self->{pdf}->circle(x => $cx, y => $cy, r => $r); |
|
1365
|
|
|
|
|
|
|
} |
|
1366
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1367
|
|
|
|
|
|
|
$self->{pdf}->fill_stroke; |
|
1368
|
|
|
|
|
|
|
} |
|
1369
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1370
|
|
|
|
|
|
|
$self->{pdf}->fill; |
|
1371
|
|
|
|
|
|
|
} |
|
1372
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1373
|
|
|
|
|
|
|
$self->{pdf}->stroke; |
|
1374
|
|
|
|
|
|
|
} |
|
1375
|
|
|
|
|
|
|
} |
|
1376
|
|
|
|
|
|
|
elsif ($name eq 'ellipse') { |
|
1377
|
|
|
|
|
|
|
my ($cx, $cy, $rx, $ry) = ( |
|
1378
|
|
|
|
|
|
|
$el->{Attributes}{"{}cx"}{Value}, |
|
1379
|
|
|
|
|
|
|
$el->{Attributes}{"{}cy"}{Value}, |
|
1380
|
|
|
|
|
|
|
$el->{Attributes}{"{}rx"}{Value}, |
|
1381
|
|
|
|
|
|
|
$el->{Attributes}{"{}ry"}{Value}, |
|
1382
|
|
|
|
|
|
|
); |
|
1383
|
|
|
|
|
|
|
my $r = $rx; |
|
1384
|
|
|
|
|
|
|
my $scale = $ry / $r; |
|
1385
|
|
|
|
|
|
|
$cy /= $scale; |
|
1386
|
|
|
|
|
|
|
# warn("ellipse at $cx, $cy, scale: $scale, r: $r\n"); |
|
1387
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1388
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}); |
|
1389
|
|
|
|
|
|
|
$self->{pdf}->coord_scale(1, $scale); |
|
1390
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1391
|
|
|
|
|
|
|
$self->{pdf}->circle(x => $cx, y => $self->{pdf}->get_value('pageheight')-$cy, r => $r); |
|
1392
|
|
|
|
|
|
|
} |
|
1393
|
|
|
|
|
|
|
else { |
|
1394
|
|
|
|
|
|
|
$self->{pdf}->circle(x => $cx, y => $cy, r => $r); |
|
1395
|
|
|
|
|
|
|
} |
|
1396
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1397
|
|
|
|
|
|
|
$self->{pdf}->fill_stroke; |
|
1398
|
|
|
|
|
|
|
} |
|
1399
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1400
|
|
|
|
|
|
|
$self->{pdf}->fill; |
|
1401
|
|
|
|
|
|
|
} |
|
1402
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1403
|
|
|
|
|
|
|
$self->{pdf}->stroke; |
|
1404
|
|
|
|
|
|
|
} |
|
1405
|
|
|
|
|
|
|
} |
|
1406
|
|
|
|
|
|
|
elsif ($name eq 'line') { |
|
1407
|
|
|
|
|
|
|
my ($x1, $y1, $x2, $y2) = ( |
|
1408
|
|
|
|
|
|
|
$el->{Attributes}{"{}x1"}{Value}, |
|
1409
|
|
|
|
|
|
|
$el->{Attributes}{"{}y1"}{Value}, |
|
1410
|
|
|
|
|
|
|
$el->{Attributes}{"{}x2"}{Value}, |
|
1411
|
|
|
|
|
|
|
$el->{Attributes}{"{}y2"}{Value}, |
|
1412
|
|
|
|
|
|
|
); |
|
1413
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1414
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}); |
|
1415
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1416
|
|
|
|
|
|
|
$self->{pdf}->move_to($x1, $self->{pdf}->get_value('pageheight')-$y1); |
|
1417
|
|
|
|
|
|
|
$self->{pdf}->line_to($x2, $self->{pdf}->get_value('pageheight')-$y2); |
|
1418
|
|
|
|
|
|
|
} |
|
1419
|
|
|
|
|
|
|
else { |
|
1420
|
|
|
|
|
|
|
$self->{pdf}->move_to($x1, $y1); |
|
1421
|
|
|
|
|
|
|
$self->{pdf}->line_to($x2, $y2); |
|
1422
|
|
|
|
|
|
|
} |
|
1423
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1424
|
|
|
|
|
|
|
$self->{pdf}->fill_stroke; |
|
1425
|
|
|
|
|
|
|
} |
|
1426
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1427
|
|
|
|
|
|
|
$self->{pdf}->fill; |
|
1428
|
|
|
|
|
|
|
} |
|
1429
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1430
|
|
|
|
|
|
|
$self->{pdf}->stroke; |
|
1431
|
|
|
|
|
|
|
} |
|
1432
|
|
|
|
|
|
|
} |
|
1433
|
|
|
|
|
|
|
elsif ($name eq 'text') { |
|
1434
|
|
|
|
|
|
|
my ($x, $y) = ( |
|
1435
|
|
|
|
|
|
|
$el->{Attributes}{"{}x"}{Value}, |
|
1436
|
|
|
|
|
|
|
$el->{Attributes}{"{}y"}{Value}, |
|
1437
|
|
|
|
|
|
|
); |
|
1438
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1439
|
|
|
|
|
|
|
$self->push_font(); |
|
1440
|
|
|
|
|
|
|
$self->{pdf}->set_font( face => $self->{normal_font}, size => 14.0 ) unless $el->{Parent}->{LocalName} eq 'g'; |
|
1441
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}, 1); |
|
1442
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1443
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($x, $self->{pdf}->get_value('pageheight')-$y); |
|
1444
|
|
|
|
|
|
|
} |
|
1445
|
|
|
|
|
|
|
else { |
|
1446
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($x, $y); |
|
1447
|
|
|
|
|
|
|
} |
|
1448
|
|
|
|
|
|
|
$self->{chars_ok} = 1; |
|
1449
|
|
|
|
|
|
|
$self->gathered_text; # reset |
|
1450
|
|
|
|
|
|
|
} |
|
1451
|
|
|
|
|
|
|
elsif ($name eq 'list') { |
|
1452
|
|
|
|
|
|
|
if ($el->{Attributes}{"{}ordered"}) { |
|
1453
|
|
|
|
|
|
|
push @{$self->{list_index}}, 1; |
|
1454
|
|
|
|
|
|
|
} else { |
|
1455
|
|
|
|
|
|
|
push @{$self->{list_index}}, 0; |
|
1456
|
|
|
|
|
|
|
} |
|
1457
|
|
|
|
|
|
|
} |
|
1458
|
|
|
|
|
|
|
elsif ($name eq 'path') { |
|
1459
|
|
|
|
|
|
|
my ($data) = ( |
|
1460
|
|
|
|
|
|
|
$el->{Attributes}{"{}d"}{Value}, |
|
1461
|
|
|
|
|
|
|
); |
|
1462
|
|
|
|
|
|
|
$self->{pdf}->save_graphics_state(); |
|
1463
|
|
|
|
|
|
|
$self->process_css_styles($el->{Attributes}{"{}style"}{Value}); |
|
1464
|
|
|
|
|
|
|
$self->process_path($data); |
|
1465
|
|
|
|
|
|
|
} |
|
1466
|
|
|
|
|
|
|
} |
|
1467
|
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
use constant PI => atan2(1, 1) * 4.0; |
|
1469
|
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
sub convert_from_svg |
|
1471
|
|
|
|
|
|
|
{ |
|
1472
|
|
|
|
|
|
|
my ($x0, $y0, $rx, $ry, $phi, $large_arc, $sweep, $x, $y) = @_; |
|
1473
|
|
|
|
|
|
|
my ($cx, $cy, $theta, $delta); |
|
1474
|
|
|
|
|
|
|
|
|
1475
|
|
|
|
|
|
|
# a plethora of temporary variables |
|
1476
|
|
|
|
|
|
|
my ( |
|
1477
|
|
|
|
|
|
|
$dx2, $dy2, $phi_r, $x1, $y1, |
|
1478
|
|
|
|
|
|
|
$rx_sq, $ry_sq, |
|
1479
|
|
|
|
|
|
|
$x1_sq, $y1_sq, |
|
1480
|
|
|
|
|
|
|
$sign, $sq, $coef, |
|
1481
|
|
|
|
|
|
|
$cx1, $cy1, $sx2, $sy2, |
|
1482
|
|
|
|
|
|
|
$p, $n, |
|
1483
|
|
|
|
|
|
|
$ux, $uy, $vx, $vy |
|
1484
|
|
|
|
|
|
|
); |
|
1485
|
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
# Compute 1/2 distance between current and final point |
|
1487
|
|
|
|
|
|
|
$dx2 = ($x0 - $x) / 2.0; |
|
1488
|
|
|
|
|
|
|
$dy2 = ($y0 - $y) / 2.0; |
|
1489
|
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
# Convert from degrees to radians |
|
1491
|
|
|
|
|
|
|
$phi %= 360; |
|
1492
|
|
|
|
|
|
|
$phi_r = $phi * PI / 180.0; |
|
1493
|
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
# Compute (x1, y1) |
|
1495
|
|
|
|
|
|
|
$x1 = cos($phi_r) * $dx2 + sin($phi_r) * $dy2; |
|
1496
|
|
|
|
|
|
|
$y1 = -sin($phi_r) * $dx2 + cos($phi_r) * $dy2; |
|
1497
|
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
# Make sure radii are large enough |
|
1499
|
|
|
|
|
|
|
$rx = abs($rx); $ry = abs($ry); |
|
1500
|
|
|
|
|
|
|
$rx_sq = $rx * $rx; |
|
1501
|
|
|
|
|
|
|
$ry_sq = $ry * $ry; |
|
1502
|
|
|
|
|
|
|
$x1_sq = $x1 * $x1; |
|
1503
|
|
|
|
|
|
|
$y1_sq = $y1 * $y1; |
|
1504
|
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
my $radius_check = ($x1_sq / $rx_sq) + ($y1_sq / $ry_sq); |
|
1506
|
|
|
|
|
|
|
if ($radius_check > 1) |
|
1507
|
|
|
|
|
|
|
{ |
|
1508
|
|
|
|
|
|
|
$rx *= sqrt($radius_check); |
|
1509
|
|
|
|
|
|
|
$ry *= sqrt($radius_check); |
|
1510
|
|
|
|
|
|
|
$rx_sq = $rx * $rx; |
|
1511
|
|
|
|
|
|
|
$ry_sq = $ry * $ry; |
|
1512
|
|
|
|
|
|
|
} |
|
1513
|
|
|
|
|
|
|
|
|
1514
|
|
|
|
|
|
|
# Step 2: Compute (cx1, cy1) |
|
1515
|
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
$sign = ($large_arc == $sweep) ? -1 : 1; |
|
1517
|
|
|
|
|
|
|
$sq = (($rx_sq * $ry_sq) - ($rx_sq * $y1_sq) - ($ry_sq * $x1_sq)) / |
|
1518
|
|
|
|
|
|
|
(($rx_sq * $y1_sq) + ($ry_sq * $x1_sq)); |
|
1519
|
|
|
|
|
|
|
$sq = ($sq < 0) ? 0 : $sq; |
|
1520
|
|
|
|
|
|
|
$coef = ($sign * sqrt($sq)); |
|
1521
|
|
|
|
|
|
|
$cx1 = round($coef * (($rx * $y1) / $ry)); |
|
1522
|
|
|
|
|
|
|
$cy1 = round($coef * -(($ry * $x1) / $rx)); |
|
1523
|
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
# Step 3: Compute (cx, cy) from (cx1, cy1) |
|
1525
|
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
$sx2 = ($x0 + $x) / 2.0; |
|
1527
|
|
|
|
|
|
|
$sy2 = ($y0 + $y) / 2.0; |
|
1528
|
|
|
|
|
|
|
|
|
1529
|
|
|
|
|
|
|
# Step 4: Compute angle start and angle extent |
|
1530
|
|
|
|
|
|
|
|
|
1531
|
|
|
|
|
|
|
#$ux = ($x0-$cx); |
|
1532
|
|
|
|
|
|
|
#$uy = ($y0-$cy); |
|
1533
|
|
|
|
|
|
|
#$vx = ($x-$cx); |
|
1534
|
|
|
|
|
|
|
#$vy = ($y-$cy); |
|
1535
|
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
#print STDERR " u: ($ux,$uy) | v: ($vx,$vy)\n"; |
|
1537
|
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
$ux = ($x1 - $cx1) / $rx; |
|
1539
|
|
|
|
|
|
|
$uy = ($y1 - $cy1) / $ry; |
|
1540
|
|
|
|
|
|
|
$vx = (-$x1 - $cx1) / $rx; |
|
1541
|
|
|
|
|
|
|
$vy = (-$y1 - $cy1) / $ry; |
|
1542
|
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
$n = sqrt( ($ux * $ux) + ($uy * $uy) ); |
|
1544
|
|
|
|
|
|
|
$p = $ux; # 1 * ux + 0 * uy |
|
1545
|
|
|
|
|
|
|
$sign = ($uy > 0) ? -1 : 1; |
|
1546
|
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
$theta = $sign * acos( $p / $n ); |
|
1548
|
|
|
|
|
|
|
$theta = $theta * 180 / PI; |
|
1549
|
|
|
|
|
|
|
|
|
1550
|
|
|
|
|
|
|
$n = sqrt(($ux * $ux + $uy * $uy) * ($vx * $vx + $vy * $vy)); |
|
1551
|
|
|
|
|
|
|
$p = $ux * $vx + $uy * $vy; |
|
1552
|
|
|
|
|
|
|
$sign = (($ux * $vy - $uy * $vx) > 0) ? -1 : 1; |
|
1553
|
|
|
|
|
|
|
$delta = $sign * acos( $p / $n ); |
|
1554
|
|
|
|
|
|
|
$delta = round($delta * 180 / PI); |
|
1555
|
|
|
|
|
|
|
#print STDERR " delta: $delta\n"; |
|
1556
|
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
if ($large_arc == 0 && $delta >= 180) { |
|
1558
|
|
|
|
|
|
|
$delta -= 360; |
|
1559
|
|
|
|
|
|
|
} elsif ($large_arc == 0 && $delta < -180) { |
|
1560
|
|
|
|
|
|
|
$delta += 360; |
|
1561
|
|
|
|
|
|
|
} elsif ($large_arc == 1 && $delta <= 180 && $delta > 0) { |
|
1562
|
|
|
|
|
|
|
$delta -= 360; |
|
1563
|
|
|
|
|
|
|
} elsif ($large_arc == 1 && $delta > -180 && $delta <= 0) { |
|
1564
|
|
|
|
|
|
|
$delta += 360; |
|
1565
|
|
|
|
|
|
|
} |
|
1566
|
|
|
|
|
|
|
|
|
1567
|
|
|
|
|
|
|
#print STDERR " actually doing arc ($large_arc,$sweep): $cx1, $cy1 $rx,$ry, $theta, $delta, $phi\n"; |
|
1568
|
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
return bezier_arc_approximation($cx1, $cy1, $rx, $ry, $theta, $delta, $phi_r, $sx2, $sy2); |
|
1570
|
|
|
|
|
|
|
} |
|
1571
|
|
|
|
|
|
|
|
|
1572
|
|
|
|
|
|
|
sub round { |
|
1573
|
|
|
|
|
|
|
return int(($_[0])*100+.5)/100; |
|
1574
|
|
|
|
|
|
|
} |
|
1575
|
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
# Taken from http://www.faqts.com/knowledge_base/view.phtml/aid/4313 |
|
1577
|
|
|
|
|
|
|
sub bezier_arc_approximation { |
|
1578
|
|
|
|
|
|
|
my ($cx, $cy, $rx, $ry, $start, $extent, $phi_r, $rcx, $rcy) = @_; |
|
1579
|
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
# The resulting coordinates are of the form (x1,y1, x2,y2, x3,y3, x4,y4) such that |
|
1581
|
|
|
|
|
|
|
# the curve goes from (x1, y1) to (x4, y4) with (x2, y2) and (x3, y3) as their |
|
1582
|
|
|
|
|
|
|
# respective Bézier control points. |
|
1583
|
|
|
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
my $nfrag = int(ceil(abs($extent)/90)); |
|
1585
|
|
|
|
|
|
|
my $fragAngle = $extent/$nfrag; |
|
1586
|
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
my $halfAng = $fragAngle * PI / 360; |
|
1588
|
|
|
|
|
|
|
my $kappa = 4 / 3 * (1-cos($halfAng))/sin($halfAng); |
|
1589
|
|
|
|
|
|
|
|
|
1590
|
|
|
|
|
|
|
my @ret; |
|
1591
|
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
for my $i (0..($nfrag-1)) { |
|
1593
|
|
|
|
|
|
|
my $theta0 = ($start + $i*$fragAngle) * PI / 180; |
|
1594
|
|
|
|
|
|
|
my $theta1 = ($start + ($i+1)*$fragAngle) * PI / 180; |
|
1595
|
|
|
|
|
|
|
push @ret, [ |
|
1596
|
|
|
|
|
|
|
rotate($rcx,$rcy,$phi_r, $cx + $rx * cos($theta0), $cy -$ry * sin($theta0)), |
|
1597
|
|
|
|
|
|
|
rotate($rcx,$rcy,$phi_r, $cx + $rx * (cos($theta0) - $kappa * sin($theta0)), $cy -$ry * (sin($theta0) + $kappa * cos($theta0))), |
|
1598
|
|
|
|
|
|
|
rotate($rcx,$rcy,$phi_r, $cx + $rx * (cos($theta1) + $kappa * sin($theta1)), $cy -$ry * (sin($theta1) - $kappa * cos($theta1))), |
|
1599
|
|
|
|
|
|
|
rotate($rcx,$rcy,$phi_r, $cx + $rx * cos($theta1), $cy -$ry * sin($theta1)), |
|
1600
|
|
|
|
|
|
|
]; |
|
1601
|
|
|
|
|
|
|
} |
|
1602
|
|
|
|
|
|
|
|
|
1603
|
|
|
|
|
|
|
return @ret; |
|
1604
|
|
|
|
|
|
|
} |
|
1605
|
|
|
|
|
|
|
|
|
1606
|
|
|
|
|
|
|
sub rotate { |
|
1607
|
|
|
|
|
|
|
my ($rcx, $rcy, $phi_r, $x, $y) = @_; |
|
1608
|
|
|
|
|
|
|
return (($rcx + (cos($phi_r) * $x - sin($phi_r) * $y)), ($rcy + (sin($phi_r) * $x + cos($phi_r) * $y))); |
|
1609
|
|
|
|
|
|
|
} |
|
1610
|
|
|
|
|
|
|
|
|
1611
|
|
|
|
|
|
|
sub process_path { |
|
1612
|
|
|
|
|
|
|
my $self = shift; |
|
1613
|
|
|
|
|
|
|
my ($data) = @_; |
|
1614
|
|
|
|
|
|
|
$data =~ s/^\s*//; |
|
1615
|
|
|
|
|
|
|
my @parts = split(/([A-Za-z])/, $data); |
|
1616
|
|
|
|
|
|
|
# warn("got: '", join("', '", @parts), "'\n"); |
|
1617
|
|
|
|
|
|
|
shift(@parts); # get rid of junk at start |
|
1618
|
|
|
|
|
|
|
my $ytotal = $self->{pdf}->get_value('pageheight'); |
|
1619
|
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
my $relative = 0; |
|
1621
|
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
my ($xoffset, $yoffset) = map { $self->{pdf}->get_value($_) } qw(currentx currenty); |
|
1623
|
|
|
|
|
|
|
$yoffset = $ytotal-$yoffset; |
|
1624
|
|
|
|
|
|
|
|
|
1625
|
|
|
|
|
|
|
my ($last_reflect_x, $last_reflect_y, $need_to_close); |
|
1626
|
|
|
|
|
|
|
|
|
1627
|
|
|
|
|
|
|
while (@parts) { |
|
1628
|
|
|
|
|
|
|
my $type = shift(@parts); |
|
1629
|
|
|
|
|
|
|
my $rest = shift(@parts); |
|
1630
|
|
|
|
|
|
|
|
|
1631
|
|
|
|
|
|
|
if ($type eq lc($type)) { |
|
1632
|
|
|
|
|
|
|
# warn("using relative coordinates\n"); |
|
1633
|
|
|
|
|
|
|
$relative++; |
|
1634
|
|
|
|
|
|
|
} |
|
1635
|
|
|
|
|
|
|
|
|
1636
|
|
|
|
|
|
|
my @coords = grep { /^[\d\.\-]+$/ } split(/[^\d\.\-]+/, $rest||''); |
|
1637
|
|
|
|
|
|
|
# warn("got coords: '", join("', '", @coords), "'\n"); |
|
1638
|
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
my ($x, $y); |
|
1640
|
|
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
if (lc($type) eq 'm') { # moveto |
|
1642
|
|
|
|
|
|
|
if (@coords % 2) { |
|
1643
|
|
|
|
|
|
|
warn("moveto coords must be in pairs, skipping.\n"); |
|
1644
|
|
|
|
|
|
|
next; |
|
1645
|
|
|
|
|
|
|
} |
|
1646
|
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1648
|
|
|
|
|
|
|
|
|
1649
|
|
|
|
|
|
|
($x, $y) = splice(@coords, 0, 2); |
|
1650
|
|
|
|
|
|
|
if ($relative) { |
|
1651
|
|
|
|
|
|
|
$x += $xoffset; |
|
1652
|
|
|
|
|
|
|
$y += $yoffset; |
|
1653
|
|
|
|
|
|
|
} |
|
1654
|
|
|
|
|
|
|
# warn("move_to($x, $y)\n"); |
|
1655
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1656
|
|
|
|
|
|
|
$self->{pdf}->move_to($x, $ytotal-$y); |
|
1657
|
|
|
|
|
|
|
} |
|
1658
|
|
|
|
|
|
|
else { |
|
1659
|
|
|
|
|
|
|
$self->{pdf}->move_to($x, $y); |
|
1660
|
|
|
|
|
|
|
} |
|
1661
|
|
|
|
|
|
|
|
|
1662
|
|
|
|
|
|
|
if (@coords) { |
|
1663
|
|
|
|
|
|
|
# more coords == lines |
|
1664
|
|
|
|
|
|
|
unshift @parts, ($relative ? 'l' : 'L'), join(',', @coords); |
|
1665
|
|
|
|
|
|
|
next; |
|
1666
|
|
|
|
|
|
|
} |
|
1667
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1668
|
|
|
|
|
|
|
} |
|
1669
|
|
|
|
|
|
|
elsif (lc($type) eq 'z') { # closepath |
|
1670
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1671
|
|
|
|
|
|
|
$self->{pdf}->close_path_fill_stroke; |
|
1672
|
|
|
|
|
|
|
} |
|
1673
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1674
|
|
|
|
|
|
|
$self->{pdf}->close_path_fill; |
|
1675
|
|
|
|
|
|
|
} |
|
1676
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1677
|
|
|
|
|
|
|
$self->{pdf}->close_path_stroke; |
|
1678
|
|
|
|
|
|
|
} |
|
1679
|
|
|
|
|
|
|
} |
|
1680
|
|
|
|
|
|
|
elsif (lc($type) eq 'l') { # lineto |
|
1681
|
|
|
|
|
|
|
if (@coords % 2) { |
|
1682
|
|
|
|
|
|
|
warn("moveto coords must be in pairs, skipping.\n"); |
|
1683
|
|
|
|
|
|
|
next; |
|
1684
|
|
|
|
|
|
|
} |
|
1685
|
|
|
|
|
|
|
|
|
1686
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1687
|
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
while(@coords) { |
|
1689
|
|
|
|
|
|
|
($x, $y) = splice(@coords, 0, 2); |
|
1690
|
|
|
|
|
|
|
# warn("line: $x, $y\n"); |
|
1691
|
|
|
|
|
|
|
if ($relative) { |
|
1692
|
|
|
|
|
|
|
$x += $xoffset; |
|
1693
|
|
|
|
|
|
|
$y += $yoffset; |
|
1694
|
|
|
|
|
|
|
} |
|
1695
|
|
|
|
|
|
|
# warn("line_to($x, $y)\n"); |
|
1696
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1697
|
|
|
|
|
|
|
$self->{pdf}->line_to($x, $ytotal-$y); |
|
1698
|
|
|
|
|
|
|
} |
|
1699
|
|
|
|
|
|
|
else { |
|
1700
|
|
|
|
|
|
|
$self->{pdf}->line_to($x, $y); |
|
1701
|
|
|
|
|
|
|
} |
|
1702
|
|
|
|
|
|
|
} |
|
1703
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1704
|
|
|
|
|
|
|
} |
|
1705
|
|
|
|
|
|
|
elsif (lc($type) eq 'h') { # horizontal lineto |
|
1706
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1707
|
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
while (@coords) { |
|
1709
|
|
|
|
|
|
|
$x = shift @coords; |
|
1710
|
|
|
|
|
|
|
if ($relative) { |
|
1711
|
|
|
|
|
|
|
$x += $xoffset; |
|
1712
|
|
|
|
|
|
|
} |
|
1713
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1714
|
|
|
|
|
|
|
$self->{pdf}->line_to($x, $ytotal-$yoffset); |
|
1715
|
|
|
|
|
|
|
} |
|
1716
|
|
|
|
|
|
|
else { |
|
1717
|
|
|
|
|
|
|
$self->{pdf}->line_to($x, $yoffset); |
|
1718
|
|
|
|
|
|
|
} |
|
1719
|
|
|
|
|
|
|
} |
|
1720
|
|
|
|
|
|
|
$xoffset = $x; |
|
1721
|
|
|
|
|
|
|
} |
|
1722
|
|
|
|
|
|
|
elsif (lc($type) eq 'v') { # vertical lineto |
|
1723
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1724
|
|
|
|
|
|
|
|
|
1725
|
|
|
|
|
|
|
while (@coords) { |
|
1726
|
|
|
|
|
|
|
$y = shift @coords; |
|
1727
|
|
|
|
|
|
|
if ($relative) { |
|
1728
|
|
|
|
|
|
|
$y += $yoffset; |
|
1729
|
|
|
|
|
|
|
} |
|
1730
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1731
|
|
|
|
|
|
|
$self->{pdf}->line_to($xoffset, $ytotal-$y); |
|
1732
|
|
|
|
|
|
|
} |
|
1733
|
|
|
|
|
|
|
else { |
|
1734
|
|
|
|
|
|
|
$self->{pdf}->line_to($xoffset, $y); |
|
1735
|
|
|
|
|
|
|
} |
|
1736
|
|
|
|
|
|
|
} |
|
1737
|
|
|
|
|
|
|
$yoffset = $y; |
|
1738
|
|
|
|
|
|
|
} |
|
1739
|
|
|
|
|
|
|
elsif (lc($type) eq 'c') { # curveto |
|
1740
|
|
|
|
|
|
|
if (@coords % 6) { |
|
1741
|
|
|
|
|
|
|
warn("curveto coords must be in 6's, skipping.\n"); |
|
1742
|
|
|
|
|
|
|
next; |
|
1743
|
|
|
|
|
|
|
} |
|
1744
|
|
|
|
|
|
|
|
|
1745
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1746
|
|
|
|
|
|
|
|
|
1747
|
|
|
|
|
|
|
while (@coords) { |
|
1748
|
|
|
|
|
|
|
my ($x1, $y1, $x2, $y2, $x3, $y3) = splice(@coords, 0, 6); |
|
1749
|
|
|
|
|
|
|
if ($relative) { |
|
1750
|
|
|
|
|
|
|
for ($x1, $x2, $x3) { |
|
1751
|
|
|
|
|
|
|
$_ += $xoffset; |
|
1752
|
|
|
|
|
|
|
} |
|
1753
|
|
|
|
|
|
|
for ($y1, $y2, $y3) { |
|
1754
|
|
|
|
|
|
|
$_ += $yoffset; |
|
1755
|
|
|
|
|
|
|
} |
|
1756
|
|
|
|
|
|
|
} |
|
1757
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1758
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1759
|
|
|
|
|
|
|
x1 => $x1, y1 => $ytotal-$y1, |
|
1760
|
|
|
|
|
|
|
x2 => $x2, y2 => $ytotal-$y2, |
|
1761
|
|
|
|
|
|
|
x3 => $x3, y3 => $ytotal-$y3, |
|
1762
|
|
|
|
|
|
|
); |
|
1763
|
|
|
|
|
|
|
} |
|
1764
|
|
|
|
|
|
|
else { |
|
1765
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1766
|
|
|
|
|
|
|
x1 => $x1, y1 => $y1, |
|
1767
|
|
|
|
|
|
|
x2 => $x2, y2 => $y2, |
|
1768
|
|
|
|
|
|
|
x3 => $x3, y3 => $y3, |
|
1769
|
|
|
|
|
|
|
); |
|
1770
|
|
|
|
|
|
|
} |
|
1771
|
|
|
|
|
|
|
($last_reflect_x, $last_reflect_y) = ($x2, $y2); |
|
1772
|
|
|
|
|
|
|
($x, $y) = ($x3, $y3); |
|
1773
|
|
|
|
|
|
|
} |
|
1774
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1775
|
|
|
|
|
|
|
} |
|
1776
|
|
|
|
|
|
|
elsif (lc($type) eq 's') { # shorthand/smooth curveto |
|
1777
|
|
|
|
|
|
|
if (@coords % 4) { |
|
1778
|
|
|
|
|
|
|
warn("shorthand curveto coords must be in 4's, skipping.\n"); |
|
1779
|
|
|
|
|
|
|
next; |
|
1780
|
|
|
|
|
|
|
} |
|
1781
|
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1783
|
|
|
|
|
|
|
|
|
1784
|
|
|
|
|
|
|
while (@coords) { |
|
1785
|
|
|
|
|
|
|
my ($x2, $y2, $x3, $y3) = splice(@coords, 0, 4); |
|
1786
|
|
|
|
|
|
|
if ($relative) { |
|
1787
|
|
|
|
|
|
|
$x2 += $xoffset; |
|
1788
|
|
|
|
|
|
|
$x3 += $xoffset; |
|
1789
|
|
|
|
|
|
|
$y2 += $yoffset; |
|
1790
|
|
|
|
|
|
|
$y3 += $yoffset; |
|
1791
|
|
|
|
|
|
|
} |
|
1792
|
|
|
|
|
|
|
my ($x1, $y1); |
|
1793
|
|
|
|
|
|
|
if (defined($last_reflect_x)) { |
|
1794
|
|
|
|
|
|
|
$x1 = $xoffset - ($last_reflect_x - $xoffset); |
|
1795
|
|
|
|
|
|
|
$y1 = $yoffset - ($last_reflect_y - $yoffset); |
|
1796
|
|
|
|
|
|
|
} |
|
1797
|
|
|
|
|
|
|
else { |
|
1798
|
|
|
|
|
|
|
$x1 = $xoffset; |
|
1799
|
|
|
|
|
|
|
$y1 = $yoffset; |
|
1800
|
|
|
|
|
|
|
} |
|
1801
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1802
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1803
|
|
|
|
|
|
|
x1 => $x1, y1 => $ytotal-$y1, |
|
1804
|
|
|
|
|
|
|
x2 => $x2, y2 => $ytotal-$y2, |
|
1805
|
|
|
|
|
|
|
x3 => $x3, y3 => $ytotal-$y3, |
|
1806
|
|
|
|
|
|
|
); |
|
1807
|
|
|
|
|
|
|
} |
|
1808
|
|
|
|
|
|
|
else { |
|
1809
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1810
|
|
|
|
|
|
|
x1 => $x1, y1 => $y1, |
|
1811
|
|
|
|
|
|
|
x2 => $x2, y2 => $y2, |
|
1812
|
|
|
|
|
|
|
x3 => $x3, y3 => $y3, |
|
1813
|
|
|
|
|
|
|
); |
|
1814
|
|
|
|
|
|
|
} |
|
1815
|
|
|
|
|
|
|
($last_reflect_x, $last_reflect_y) = ($x2, $y2); |
|
1816
|
|
|
|
|
|
|
($x, $y) = ($x3, $y3); |
|
1817
|
|
|
|
|
|
|
} |
|
1818
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1819
|
|
|
|
|
|
|
} |
|
1820
|
|
|
|
|
|
|
elsif (lc($type) eq 'q') { # quadratic bezier curveto |
|
1821
|
|
|
|
|
|
|
if (@coords % 4) { |
|
1822
|
|
|
|
|
|
|
warn("quadratic curveto coords must be in 4's, skipping.\n"); |
|
1823
|
|
|
|
|
|
|
next; |
|
1824
|
|
|
|
|
|
|
} |
|
1825
|
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1827
|
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
while (@coords) { |
|
1829
|
|
|
|
|
|
|
my ($x1, $y1, $x3, $y3) = splice(@coords, 0, 4); |
|
1830
|
|
|
|
|
|
|
if ($relative) { |
|
1831
|
|
|
|
|
|
|
for ($x1, $x3) { |
|
1832
|
|
|
|
|
|
|
$_ += $xoffset; |
|
1833
|
|
|
|
|
|
|
} |
|
1834
|
|
|
|
|
|
|
for ($y1, $y3) { |
|
1835
|
|
|
|
|
|
|
$_ += $yoffset; |
|
1836
|
|
|
|
|
|
|
} |
|
1837
|
|
|
|
|
|
|
} |
|
1838
|
|
|
|
|
|
|
my ($x2, $y2) = ($x1, $y1); |
|
1839
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1840
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1841
|
|
|
|
|
|
|
x1 => $x1, y1 => $ytotal-$y1, |
|
1842
|
|
|
|
|
|
|
x2 => $x2, y2 => $ytotal-$y2, |
|
1843
|
|
|
|
|
|
|
x3 => $x3, y3 => $ytotal-$y3, |
|
1844
|
|
|
|
|
|
|
); |
|
1845
|
|
|
|
|
|
|
} |
|
1846
|
|
|
|
|
|
|
else { |
|
1847
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1848
|
|
|
|
|
|
|
x1 => $x1, y1 => $y1, |
|
1849
|
|
|
|
|
|
|
x2 => $x2, y2 => $y2, |
|
1850
|
|
|
|
|
|
|
x3 => $x3, y3 => $y3, |
|
1851
|
|
|
|
|
|
|
); |
|
1852
|
|
|
|
|
|
|
} |
|
1853
|
|
|
|
|
|
|
($last_reflect_x, $last_reflect_y) = ($x2, $y2); |
|
1854
|
|
|
|
|
|
|
($x, $y) = ($x3, $y3); |
|
1855
|
|
|
|
|
|
|
} |
|
1856
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1857
|
|
|
|
|
|
|
} |
|
1858
|
|
|
|
|
|
|
elsif (lc($type) eq 't') { # shorthand/smooth quadratic bezier curveto |
|
1859
|
|
|
|
|
|
|
if (@coords % 2) { |
|
1860
|
|
|
|
|
|
|
warn("shorthand quadratic curveto coords must be in pairs, skipping.\n"); |
|
1861
|
|
|
|
|
|
|
next; |
|
1862
|
|
|
|
|
|
|
} |
|
1863
|
|
|
|
|
|
|
|
|
1864
|
|
|
|
|
|
|
$need_to_close = 1; |
|
1865
|
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
while (@coords) { |
|
1867
|
|
|
|
|
|
|
my ($x3, $y3) = splice(@coords, 0, 2); |
|
1868
|
|
|
|
|
|
|
if ($relative) { |
|
1869
|
|
|
|
|
|
|
$x3 += $xoffset; |
|
1870
|
|
|
|
|
|
|
$y3 += $yoffset; |
|
1871
|
|
|
|
|
|
|
} |
|
1872
|
|
|
|
|
|
|
my ($x1, $y1, $x2, $y2); |
|
1873
|
|
|
|
|
|
|
if (defined($last_reflect_x)) { |
|
1874
|
|
|
|
|
|
|
$x1 = $xoffset - ($last_reflect_x - $xoffset); |
|
1875
|
|
|
|
|
|
|
$y1 = $yoffset - ($last_reflect_y - $yoffset); |
|
1876
|
|
|
|
|
|
|
} |
|
1877
|
|
|
|
|
|
|
else { |
|
1878
|
|
|
|
|
|
|
$x1 = $xoffset; |
|
1879
|
|
|
|
|
|
|
$y1 = $yoffset; |
|
1880
|
|
|
|
|
|
|
} |
|
1881
|
|
|
|
|
|
|
($x2, $y2) = ($x1, $y1); |
|
1882
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1883
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1884
|
|
|
|
|
|
|
x1 => $x1, y1 => $ytotal-$y1, |
|
1885
|
|
|
|
|
|
|
x2 => $x2, y2 => $ytotal-$y2, |
|
1886
|
|
|
|
|
|
|
x3 => $x3, y3 => $ytotal-$y3, |
|
1887
|
|
|
|
|
|
|
); |
|
1888
|
|
|
|
|
|
|
} |
|
1889
|
|
|
|
|
|
|
else { |
|
1890
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1891
|
|
|
|
|
|
|
x1 => $x1, y1 => $y1, |
|
1892
|
|
|
|
|
|
|
x2 => $x2, y2 => $y2, |
|
1893
|
|
|
|
|
|
|
x3 => $x3, y3 => $y3, |
|
1894
|
|
|
|
|
|
|
); |
|
1895
|
|
|
|
|
|
|
} |
|
1896
|
|
|
|
|
|
|
($last_reflect_x, $last_reflect_y) = ($x2, $y2); |
|
1897
|
|
|
|
|
|
|
($x, $y) = ($x3, $y3); |
|
1898
|
|
|
|
|
|
|
} |
|
1899
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1900
|
|
|
|
|
|
|
} |
|
1901
|
|
|
|
|
|
|
elsif (lc($type) eq 'a') { # elliptical arc |
|
1902
|
|
|
|
|
|
|
if (@coords % 7) { |
|
1903
|
|
|
|
|
|
|
warn("elliptical arc coords must be in 7's, skipping.\n"); |
|
1904
|
|
|
|
|
|
|
next; |
|
1905
|
|
|
|
|
|
|
} |
|
1906
|
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
while (@coords) { |
|
1908
|
|
|
|
|
|
|
my ($rx, $ry, $rot, $large_arc_flag, $sweep_flag, $x2, $y2) = |
|
1909
|
|
|
|
|
|
|
splice(@coords, 0, 7); |
|
1910
|
|
|
|
|
|
|
|
|
1911
|
|
|
|
|
|
|
if ($relative) { |
|
1912
|
|
|
|
|
|
|
$x2 += $xoffset; |
|
1913
|
|
|
|
|
|
|
$y2 += $yoffset; |
|
1914
|
|
|
|
|
|
|
} |
|
1915
|
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
# warn("arc($xoffset,$yoffset $rest)\n"); |
|
1917
|
|
|
|
|
|
|
|
|
1918
|
|
|
|
|
|
|
#print STDERR "arc from $xoffset,$yoffset to $x2,$y2 ($large_arc_flag,$sweep_flag)\n"; |
|
1919
|
|
|
|
|
|
|
|
|
1920
|
|
|
|
|
|
|
my @curves = convert_from_svg( |
|
1921
|
|
|
|
|
|
|
$xoffset, $yoffset, |
|
1922
|
|
|
|
|
|
|
$rx, $ry, |
|
1923
|
|
|
|
|
|
|
$rot, int($large_arc_flag), int($sweep_flag), |
|
1924
|
|
|
|
|
|
|
$x2, $y2); |
|
1925
|
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
foreach my $curve (@curves) { |
|
1927
|
|
|
|
|
|
|
#$self->{pdf}->move_to($$curve[0],$ytotal-$$curve[1]); |
|
1928
|
|
|
|
|
|
|
#print STDERR " bezier: ($$curve[0],$$curve[1]) -> ($$curve[6],$$curve[7])\n"; |
|
1929
|
|
|
|
|
|
|
if ($self->{coords} eq 'svg') { |
|
1930
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1931
|
|
|
|
|
|
|
x1 => $$curve[2], |
|
1932
|
|
|
|
|
|
|
y1 => $ytotal-$$curve[3], |
|
1933
|
|
|
|
|
|
|
x2 => $$curve[4], |
|
1934
|
|
|
|
|
|
|
y2 => $ytotal-$$curve[5], |
|
1935
|
|
|
|
|
|
|
x3 => $$curve[6], |
|
1936
|
|
|
|
|
|
|
y3 => $ytotal-$$curve[7], |
|
1937
|
|
|
|
|
|
|
); |
|
1938
|
|
|
|
|
|
|
} |
|
1939
|
|
|
|
|
|
|
else { |
|
1940
|
|
|
|
|
|
|
$self->{pdf}->bezier( |
|
1941
|
|
|
|
|
|
|
x1 => $$curve[2], |
|
1942
|
|
|
|
|
|
|
y1 => $ytotal-$$curve[3], |
|
1943
|
|
|
|
|
|
|
x2 => $$curve[4], |
|
1944
|
|
|
|
|
|
|
y2 => $ytotal-$$curve[5], |
|
1945
|
|
|
|
|
|
|
x3 => $$curve[6], |
|
1946
|
|
|
|
|
|
|
y3 => $ytotal-$$curve[7], |
|
1947
|
|
|
|
|
|
|
); |
|
1948
|
|
|
|
|
|
|
} |
|
1949
|
|
|
|
|
|
|
} |
|
1950
|
|
|
|
|
|
|
|
|
1951
|
|
|
|
|
|
|
($x, $y) = ($x2, $y2); |
|
1952
|
|
|
|
|
|
|
} |
|
1953
|
|
|
|
|
|
|
$xoffset = $x; $yoffset = $y; |
|
1954
|
|
|
|
|
|
|
} |
|
1955
|
|
|
|
|
|
|
else { |
|
1956
|
|
|
|
|
|
|
warn("Unknown SVG path command: $type in $data"); |
|
1957
|
|
|
|
|
|
|
} |
|
1958
|
|
|
|
|
|
|
} |
|
1959
|
|
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
if ($need_to_close) { |
|
1961
|
|
|
|
|
|
|
if ($self->{fill} && $self->{stroke}) { |
|
1962
|
|
|
|
|
|
|
$self->{pdf}->fill_stroke; |
|
1963
|
|
|
|
|
|
|
} |
|
1964
|
|
|
|
|
|
|
elsif ($self->{fill}) { |
|
1965
|
|
|
|
|
|
|
$self->{pdf}->fill; |
|
1966
|
|
|
|
|
|
|
} |
|
1967
|
|
|
|
|
|
|
elsif ($self->{stroke}) { |
|
1968
|
|
|
|
|
|
|
$self->{pdf}->stroke; |
|
1969
|
|
|
|
|
|
|
} |
|
1970
|
|
|
|
|
|
|
} |
|
1971
|
|
|
|
|
|
|
} |
|
1972
|
|
|
|
|
|
|
|
|
1973
|
|
|
|
|
|
|
sub slide_end_element { |
|
1974
|
|
|
|
|
|
|
my ($self, $el) = @_; |
|
1975
|
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
my $name = $el->{LocalName}; |
|
1977
|
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
#warn("slide_end_ $name ".join(",",map { $_."=>".$el->{Attributes}{$_}->{Value} } keys %{$el->{Attributes}})."\n"); |
|
1979
|
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
$el = $self->{SlideCurrent}; |
|
1981
|
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
if ($name =~ /^(point|plain|source[_-]code)$/) { |
|
1983
|
|
|
|
|
|
|
# finish bounding box |
|
1984
|
|
|
|
|
|
|
my ($x, $y) = $self->{bb}->get_text_pos; |
|
1985
|
|
|
|
|
|
|
$self->{bb}->finish; |
|
1986
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{bb}->{x}, $y - 4); |
|
1987
|
|
|
|
|
|
|
my $bb = delete $self->{bb}; |
|
1988
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
1989
|
|
|
|
|
|
|
} |
|
1990
|
|
|
|
|
|
|
|
|
1991
|
|
|
|
|
|
|
if ($name eq 'title') { |
|
1992
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
1993
|
|
|
|
|
|
|
my ($x, $y) = $self->{bb}->get_text_pos; |
|
1994
|
|
|
|
|
|
|
$self->{bb}->finish; |
|
1995
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{bb}->{x}, $y - 4); |
|
1996
|
|
|
|
|
|
|
my $bb = delete $self->{bb}; |
|
1997
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
1998
|
|
|
|
|
|
|
} |
|
1999
|
|
|
|
|
|
|
# create bookmarks |
|
2000
|
|
|
|
|
|
|
if (!$self->{transitional}) { |
|
2001
|
|
|
|
|
|
|
my $text = $self->gathered_text; |
|
2002
|
|
|
|
|
|
|
$self->{values}->{'slide-title'} = $text; |
|
2003
|
|
|
|
|
|
|
$self->push_bookmark( |
|
2004
|
|
|
|
|
|
|
$self->{pdf}->add_bookmark( |
|
2005
|
|
|
|
|
|
|
text => $self->{text_encoder}->convert($text), |
|
2006
|
|
|
|
|
|
|
level => 3, |
|
2007
|
|
|
|
|
|
|
parent_of => $self->top_bookmark, |
|
2008
|
|
|
|
|
|
|
) |
|
2009
|
|
|
|
|
|
|
); |
|
2010
|
|
|
|
|
|
|
} |
|
2011
|
|
|
|
|
|
|
if ($self->{pagetype} ne 'empty') { |
|
2012
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos(); |
|
2013
|
|
|
|
|
|
|
$self->{pdf}->add_link( |
|
2014
|
|
|
|
|
|
|
link => $el->{Attributes}{"{}href"}{Value}, |
|
2015
|
|
|
|
|
|
|
x => 20, y => $y + $self->{pdf}->get_value('leading'), |
|
2016
|
|
|
|
|
|
|
w => 570, h => 24) if exists($el->{Attributes}{"{}href"}); |
|
2017
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos(60, $y); |
|
2018
|
|
|
|
|
|
|
} |
|
2019
|
|
|
|
|
|
|
$self->{chars_ok} = 0; |
|
2020
|
|
|
|
|
|
|
} |
|
2021
|
|
|
|
|
|
|
elsif ($name eq 'slide') { |
|
2022
|
|
|
|
|
|
|
$self->pop_bookmark unless $self->{transitional}; |
|
2023
|
|
|
|
|
|
|
} |
|
2024
|
|
|
|
|
|
|
elsif ($name eq 'i' || $name eq 'b' || $name eq 'span' || $name eq 'g' || $name eq 'u') { |
|
2025
|
|
|
|
|
|
|
$self->pop_font(); |
|
2026
|
|
|
|
|
|
|
} |
|
2027
|
|
|
|
|
|
|
elsif ($name eq 'point') { |
|
2028
|
|
|
|
|
|
|
$self->{chars_ok} = 0; |
|
2029
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos(); |
|
2030
|
|
|
|
|
|
|
$self->{pdf}->add_link( |
|
2031
|
|
|
|
|
|
|
link => $el->{Attributes}{"{}href"}{Value}, |
|
2032
|
|
|
|
|
|
|
x => 20, y => $y + $self->{pdf}->get_value('leading'), |
|
2033
|
|
|
|
|
|
|
w => 570, h => 24) if exists($el->{Attributes}{"{}href"}); |
|
2034
|
|
|
|
|
|
|
} |
|
2035
|
|
|
|
|
|
|
elsif ($name eq 'plain') { |
|
2036
|
|
|
|
|
|
|
$self->{chars_ok} = 0; |
|
2037
|
|
|
|
|
|
|
} |
|
2038
|
|
|
|
|
|
|
elsif ($name eq 'source_code' || $name eq 'source-code') { |
|
2039
|
|
|
|
|
|
|
$self->{chars_ok} = 0; |
|
2040
|
|
|
|
|
|
|
$self->pop_font(); |
|
2041
|
|
|
|
|
|
|
} |
|
2042
|
|
|
|
|
|
|
elsif ($name eq 'image') { |
|
2043
|
|
|
|
|
|
|
$self->{image_id}++; |
|
2044
|
|
|
|
|
|
|
} |
|
2045
|
|
|
|
|
|
|
elsif ($name eq 'colour' || $name eq 'color') { |
|
2046
|
|
|
|
|
|
|
$self->pop_font(); |
|
2047
|
|
|
|
|
|
|
} |
|
2048
|
|
|
|
|
|
|
elsif ($name eq 'table') { |
|
2049
|
|
|
|
|
|
|
shift @{$self->{extents}}; |
|
2050
|
|
|
|
|
|
|
} |
|
2051
|
|
|
|
|
|
|
elsif ($name eq 'box') { |
|
2052
|
|
|
|
|
|
|
shift @{$self->{extents}}; |
|
2053
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos(@{$self->{boxlast}}); |
|
2054
|
|
|
|
|
|
|
if (!$self->{transitional}) { |
|
2055
|
|
|
|
|
|
|
if ($self->{boxtransition}[0]) { |
|
2056
|
|
|
|
|
|
|
shift @{$self->{default_transition}}; |
|
2057
|
|
|
|
|
|
|
} |
|
2058
|
|
|
|
|
|
|
shift @{$self->{boxtransition}}; |
|
2059
|
|
|
|
|
|
|
} |
|
2060
|
|
|
|
|
|
|
} |
|
2061
|
|
|
|
|
|
|
elsif ($name eq 'row') { |
|
2062
|
|
|
|
|
|
|
$self->{row_number}++; |
|
2063
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{row_start}[0], $self->{max_height}); |
|
2064
|
|
|
|
|
|
|
} |
|
2065
|
|
|
|
|
|
|
elsif ($name eq 'col') { |
|
2066
|
|
|
|
|
|
|
$self->{col_number}++; |
|
2067
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
2068
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
2069
|
|
|
|
|
|
|
# warn("end-col: $y < $self->{max_height} ???"); |
|
2070
|
|
|
|
|
|
|
$self->{max_height} = $y if $y < $self->{max_height}; |
|
2071
|
|
|
|
|
|
|
} |
|
2072
|
|
|
|
|
|
|
elsif ($name eq 'text') { |
|
2073
|
|
|
|
|
|
|
my $text = $self->gathered_text; |
|
2074
|
|
|
|
|
|
|
$self->{chars_ok} = 0; |
|
2075
|
|
|
|
|
|
|
$self->{pdf}->print($text); |
|
2076
|
|
|
|
|
|
|
$self->{pdf}->restore_graphics_state(); |
|
2077
|
|
|
|
|
|
|
$self->pop_font(); |
|
2078
|
|
|
|
|
|
|
$self->pop_font(); |
|
2079
|
|
|
|
|
|
|
} |
|
2080
|
|
|
|
|
|
|
elsif ($name eq 'list') { |
|
2081
|
|
|
|
|
|
|
pop @{$self->{list_index}}; |
|
2082
|
|
|
|
|
|
|
} |
|
2083
|
|
|
|
|
|
|
elsif ($name =~ /^(circle|ellipse|line|rect|path)$/) { |
|
2084
|
|
|
|
|
|
|
$self->{pdf}->restore_graphics_state(); |
|
2085
|
|
|
|
|
|
|
$self->pop_font(); |
|
2086
|
|
|
|
|
|
|
} |
|
2087
|
|
|
|
|
|
|
|
|
2088
|
|
|
|
|
|
|
if ($name =~ m/^(table|list|image|source[-_]code)$/ && $el->{Attributes}{'{}caption'}) { |
|
2089
|
|
|
|
|
|
|
$self->push_font(); |
|
2090
|
|
|
|
|
|
|
$self->{pdf}->set_font(face => $self->{normal_font}, italic => 1, size => 14); |
|
2091
|
|
|
|
|
|
|
my ($x, $y) = $self->{pdf}->get_text_pos; |
|
2092
|
|
|
|
|
|
|
my $indent = 80 * ($self->{extents}[0]{w} / $self->{extents}[-1]{w}); |
|
2093
|
|
|
|
|
|
|
$self->{pdf}->set_text_pos($self->{bb}?$self->{bb}->{x}:$self->{extents}[0]{x}+$indent, $y); |
|
2094
|
|
|
|
|
|
|
$self->{pdf}->print_line(""); |
|
2095
|
|
|
|
|
|
|
$self->{pdf}->print($el->{Attributes}{'{}caption'}{Value}); |
|
2096
|
|
|
|
|
|
|
$self->pop_font(); |
|
2097
|
|
|
|
|
|
|
} |
|
2098
|
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
|
|
2100
|
|
|
|
|
|
|
$self->{SlideCurrent} = $el->{Parent}; |
|
2101
|
|
|
|
|
|
|
} |
|
2102
|
|
|
|
|
|
|
|
|
2103
|
|
|
|
|
|
|
sub slide_characters { |
|
2104
|
|
|
|
|
|
|
my ($self, $chars) = @_; |
|
2105
|
|
|
|
|
|
|
|
|
2106
|
|
|
|
|
|
|
return unless $self->{chars_ok}; |
|
2107
|
|
|
|
|
|
|
|
|
2108
|
|
|
|
|
|
|
$self->{gathered_text} .= $chars->{Data}; |
|
2109
|
|
|
|
|
|
|
|
|
2110
|
|
|
|
|
|
|
my $name = $self->{SlideCurrent}->{LocalName}; |
|
2111
|
|
|
|
|
|
|
my $text = $chars->{Data}; |
|
2112
|
|
|
|
|
|
|
return unless $text && $self->{bb}; |
|
2113
|
|
|
|
|
|
|
my $leftover = $self->{bb}->print($self->{text_encoder}->convert($text)); |
|
2114
|
|
|
|
|
|
|
if (defined $leftover && $leftover =~ m/\S/) { |
|
2115
|
|
|
|
|
|
|
die "Could not print: $leftover\nof: $text\n"; |
|
2116
|
|
|
|
|
|
|
} |
|
2117
|
|
|
|
|
|
|
} |
|
2118
|
|
|
|
|
|
|
|
|
2119
|
|
|
|
|
|
|
1; |
|
2120
|
|
|
|
|
|
|
__END__ |