line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#======================================================================== |
2
|
|
|
|
|
|
|
# Kite::XML2PS |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# DESCRIPTION |
5
|
|
|
|
|
|
|
# Perl module to convert a curve definition from OpenKite XML format |
6
|
|
|
|
|
|
|
# to PostScript, with automatic page tiling and registration mark |
7
|
|
|
|
|
|
|
# control. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# AUTHORS |
10
|
|
|
|
|
|
|
# Simon Stapleton wrote the original xml2ps.pl |
11
|
|
|
|
|
|
|
# utility which performs the XML -> PostScript conversion. |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
# Andy Wardley re-packaged it into a module for |
14
|
|
|
|
|
|
|
# integration into the Kite bundle. |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
# COPYRIGHT |
17
|
|
|
|
|
|
|
# Copyright (C) 2000 Simon Stapleton, Andy Wardley. All Rights Reserved. |
18
|
|
|
|
|
|
|
# |
19
|
|
|
|
|
|
|
# This module is free software; you can redistribute it and/or |
20
|
|
|
|
|
|
|
# modify it under the same terms as Perl itself. |
21
|
|
|
|
|
|
|
# |
22
|
|
|
|
|
|
|
# VERSION |
23
|
|
|
|
|
|
|
# $Id: XML2PS.pm,v 1.3 2000/10/17 12:19:28 abw Exp $ |
24
|
|
|
|
|
|
|
# |
25
|
|
|
|
|
|
|
#======================================================================== |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
package Kite::XML2PS; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
require 5.004; |
30
|
|
|
|
|
|
|
|
31
|
1
|
|
|
1
|
|
3703
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
47
|
|
32
|
1
|
|
|
1
|
|
436
|
use Kite::Base; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
33
|
1
|
|
|
1
|
|
543
|
use Kite::XML::Parser; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
use base qw( Kite::Base ); |
36
|
|
|
|
|
|
|
use vars qw( $VERSION $ERROR $DEBUG $PARAMS ); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
$VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/); |
39
|
|
|
|
|
|
|
$DEBUG = 0 unless defined $DEBUG; |
40
|
|
|
|
|
|
|
$ERROR = ''; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# define parameters for this class, used by Kite::Base init() method |
43
|
|
|
|
|
|
|
$PARAMS = { |
44
|
|
|
|
|
|
|
FILENAME => undef, |
45
|
|
|
|
|
|
|
TITLE => '', |
46
|
|
|
|
|
|
|
REGMARKS => 1, |
47
|
|
|
|
|
|
|
BORDER => 5, |
48
|
|
|
|
|
|
|
MAP => 1, |
49
|
|
|
|
|
|
|
}; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
53
|
|
|
|
|
|
|
# init($config) |
54
|
|
|
|
|
|
|
# |
55
|
|
|
|
|
|
|
# Initialisation method called by the base class new() constructor |
56
|
|
|
|
|
|
|
# method. Calls the base class init() to set any parameters from the |
57
|
|
|
|
|
|
|
# $PARAMS hash and then calls process_file() to process the XML |
58
|
|
|
|
|
|
|
# file to generate internal PATH and IMAGE definitions. |
59
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub init { |
62
|
|
|
|
|
|
|
my ($self, $config) = @_; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# call base class to read config params |
65
|
|
|
|
|
|
|
$self->SUPER::init($config) |
66
|
|
|
|
|
|
|
|| return undef; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# process file |
69
|
|
|
|
|
|
|
$self->process_file() |
70
|
|
|
|
|
|
|
|| return undef; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# OK |
73
|
|
|
|
|
|
|
return $self; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
78
|
|
|
|
|
|
|
# process_file() |
79
|
|
|
|
|
|
|
# process_file($filename) |
80
|
|
|
|
|
|
|
# |
81
|
|
|
|
|
|
|
# Processes the file specified as a parameter, or set internally as |
82
|
|
|
|
|
|
|
# the FILENAME item, reading the XML contained therein and generating |
83
|
|
|
|
|
|
|
# internal PATH and IMAGE definitions which can be retrieved via the |
84
|
|
|
|
|
|
|
# path() and image() methods (handled automatically by the base class |
85
|
|
|
|
|
|
|
# AUTOLOAD method). |
86
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub process_file { |
89
|
|
|
|
|
|
|
my $self = shift; |
90
|
|
|
|
|
|
|
my $file = @_ ? shift : $self->{ FILENAME }; |
91
|
|
|
|
|
|
|
my ($parser, $doc); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
return $self->error('no filename specified') |
94
|
|
|
|
|
|
|
unless defined $file; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# parse XML file, trapping any errors thrown via die() |
97
|
|
|
|
|
|
|
$parser = Kite::XML::Parser->new(); |
98
|
|
|
|
|
|
|
eval { |
99
|
|
|
|
|
|
|
$doc = $parser->parsefile($file); |
100
|
|
|
|
|
|
|
}; |
101
|
|
|
|
|
|
|
return $self->error($@) |
102
|
|
|
|
|
|
|
if $@; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
my $path = 'newpath '; |
105
|
|
|
|
|
|
|
my $image = ''; |
106
|
|
|
|
|
|
|
my ($x, $y, $xt, $yt, $angle, $anglet); |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
$self->{ KITE } = $doc; |
109
|
|
|
|
|
|
|
$self->{ TITLE } ||= $doc->title(); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# generate PS for each kite part |
112
|
|
|
|
|
|
|
foreach my $part (@{ $doc->part() }) |
113
|
|
|
|
|
|
|
{ |
114
|
|
|
|
|
|
|
$xt = $part->layout->x() || 0; |
115
|
|
|
|
|
|
|
$yt = $part->layout->y() || 0; |
116
|
|
|
|
|
|
|
$anglet = $part->layout->angle || 0; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
$image .= "gsave $xt mm $yt mm translate $anglet rotate "; |
119
|
|
|
|
|
|
|
$path .= "$xt mm $yt mm translate $anglet rotate "; |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# add path segments as a series of PS moveto/lineto ops |
122
|
|
|
|
|
|
|
foreach my $curve (@{ $part->markup->curve }) |
123
|
|
|
|
|
|
|
{ |
124
|
|
|
|
|
|
|
$image .= "gsave "; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
my $linetype = $curve->linetype || "normal"; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
if ($linetype eq 'normal') { |
129
|
|
|
|
|
|
|
$image .= "0.5 setlinewidth "; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
elsif ($linetype eq 'heavy') { |
132
|
|
|
|
|
|
|
$image .= "0.75 setlinewidth "; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
elsif ($linetype eq "light") { |
135
|
|
|
|
|
|
|
$image .= "0.25 setlinewidth "; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
elsif ($linetype eq "dotted") { |
138
|
|
|
|
|
|
|
$image .= "0.55 setlinewidth [3 5 1 5] 0 setdash "; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
my $incurve = undef; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
foreach my $point (@{ $curve->point }) |
144
|
|
|
|
|
|
|
{ |
145
|
|
|
|
|
|
|
$x = $point->x; |
146
|
|
|
|
|
|
|
$y = $point->y; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
if (defined $incurve) |
149
|
|
|
|
|
|
|
{ |
150
|
|
|
|
|
|
|
$image .= "$x mm $y mm lineto "; |
151
|
|
|
|
|
|
|
$path .= "$x mm $y mm lineto "; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
else |
154
|
|
|
|
|
|
|
{ |
155
|
|
|
|
|
|
|
$image .= "newpath $x mm $y mm moveto "; |
156
|
|
|
|
|
|
|
$path .= "$x mm $y mm moveto "; |
157
|
|
|
|
|
|
|
$incurve = 1; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# add text using PS pathtext function |
162
|
|
|
|
|
|
|
foreach my $text (@{ $curve->text || [] }) |
163
|
|
|
|
|
|
|
{ |
164
|
|
|
|
|
|
|
my $font = $text->font || "Helvetica"; |
165
|
|
|
|
|
|
|
my $size = $text->size || "6"; |
166
|
|
|
|
|
|
|
$text = $text->char; |
167
|
|
|
|
|
|
|
for ($text) { # remove leading and trailing whitespace |
168
|
|
|
|
|
|
|
s/^\s*//; |
169
|
|
|
|
|
|
|
s/\s*$//; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
$image .= "gsave /$font findfont $size mm scalefont setfont "; |
172
|
|
|
|
|
|
|
$image .= "($text) 0 pathtext grestore "; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
$image .= "stroke grestore "; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# add transformations |
178
|
|
|
|
|
|
|
$path .= "$anglet neg rotate $xt neg mm $yt neg mm translate "; |
179
|
|
|
|
|
|
|
$image .= "grestore "; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# save image and path definitions internally and return happy |
183
|
|
|
|
|
|
|
$self->{ IMAGE } = $image; |
184
|
|
|
|
|
|
|
$self->{ PATH } = $path; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
return 1; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
191
|
|
|
|
|
|
|
# doc() |
192
|
|
|
|
|
|
|
# |
193
|
|
|
|
|
|
|
# Generate a complete PostScript document to print the kite parts, |
194
|
|
|
|
|
|
|
# with automatic multiple page tiling (page-size independant), |
195
|
|
|
|
|
|
|
# registration marks and many other glorious features. Returns the |
196
|
|
|
|
|
|
|
# generated PostScript as a string. |
197
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub doc { |
200
|
|
|
|
|
|
|
my $self = shift; |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
require Kite::PScript::Defs; |
203
|
|
|
|
|
|
|
require Template; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
my $doc = $self->ps_template(); |
206
|
|
|
|
|
|
|
my $template = Template->new( POST_CHOMP => 1); |
207
|
|
|
|
|
|
|
my $vars = { |
208
|
|
|
|
|
|
|
defs => bless { }, 'Kite::PScript::Defs', |
209
|
|
|
|
|
|
|
}; |
210
|
|
|
|
|
|
|
my @keys = qw( kite title regmarks border map image path ); |
211
|
|
|
|
|
|
|
@$vars{ @keys } = @$self{ map { uc } @keys }; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
my $out = ''; |
214
|
|
|
|
|
|
|
$template->process(\$doc, $vars, \$out) |
215
|
|
|
|
|
|
|
|| return $self->error($template->error()); |
216
|
|
|
|
|
|
|
return $out; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
220
|
|
|
|
|
|
|
# ps_template() |
221
|
|
|
|
|
|
|
# |
222
|
|
|
|
|
|
|
# Returns a Template Toolkit template for generating the PostScript. |
223
|
|
|
|
|
|
|
#------------------------------------------------------------------------ |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub ps_template { |
226
|
|
|
|
|
|
|
return <<'EOF'; |
227
|
|
|
|
|
|
|
[% USE fix = format('%.2f') -%] |
228
|
|
|
|
|
|
|
%!PS-Adobe-3.0 |
229
|
|
|
|
|
|
|
[% IF title %] |
230
|
|
|
|
|
|
|
%%Title: [% title %] |
231
|
|
|
|
|
|
|
[% END %] |
232
|
|
|
|
|
|
|
%%EndComments |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
[% defs.mm %] |
235
|
|
|
|
|
|
|
[% defs.lines %] |
236
|
|
|
|
|
|
|
[% defs.cross %] |
237
|
|
|
|
|
|
|
[% defs.dot %] |
238
|
|
|
|
|
|
|
[% defs.circle %] |
239
|
|
|
|
|
|
|
[% defs.crop %] |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
/border [% border %] mm def |
242
|
|
|
|
|
|
|
[% defs.clip +%] |
243
|
|
|
|
|
|
|
[% regmarks ? defs.reg : defs.noreg +%] |
244
|
|
|
|
|
|
|
[% defs.tiles +%] |
245
|
|
|
|
|
|
|
[% defs.tilemap +%] |
246
|
|
|
|
|
|
|
[% defs.pathtext %] |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
% define image, path and page procedures for tiling |
249
|
|
|
|
|
|
|
/tileimage { |
250
|
|
|
|
|
|
|
[% image %] |
251
|
|
|
|
|
|
|
} def |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
/tilepath { |
254
|
|
|
|
|
|
|
[% path %] |
255
|
|
|
|
|
|
|
} def |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
/tilepage { |
258
|
|
|
|
|
|
|
regmarks |
259
|
|
|
|
|
|
|
[% IF title %] |
260
|
|
|
|
|
|
|
/Times-Roman findfont 24 scalefont setfont |
261
|
|
|
|
|
|
|
clipblx 3 mm add clipbly 3 mm add moveto |
262
|
|
|
|
|
|
|
([% title %]) show |
263
|
|
|
|
|
|
|
[% END %] |
264
|
|
|
|
|
|
|
[% " tilemap\n" IF map %] |
265
|
|
|
|
|
|
|
} def |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
tilepath tiles |
268
|
|
|
|
|
|
|
[% defs.dotiles %] |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
EOF |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
1; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
__END__ |