line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CAD::Drawing::IO; |
2
|
|
|
|
|
|
|
our $VERSION = '0.26'; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
#use CAD::Drawing; |
5
|
3
|
|
|
3
|
|
16
|
use CAD::Drawing::Defined; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
568
|
|
6
|
|
|
|
|
|
|
|
7
|
3
|
|
|
3
|
|
3564
|
use Storable; |
|
3
|
|
|
|
|
12082
|
|
|
3
|
|
|
|
|
265
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# value set within BEGIN block: |
10
|
|
|
|
|
|
|
my $plgindbg = $CAD::Drawing::IO::plgindbg; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
3
|
|
|
3
|
|
26
|
use warnings; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
100
|
|
14
|
3
|
|
|
3
|
|
17
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
100
|
|
15
|
3
|
|
|
3
|
|
16
|
use Carp; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
1122
|
|
16
|
|
|
|
|
|
|
######################################################################## |
17
|
|
|
|
|
|
|
=pod |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 NAME |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
CAD::Drawing::IO - I/O methods for the CAD::Drawing module |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 Description |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
This module provides the load() and save() functions for CAD::Drawing |
26
|
|
|
|
|
|
|
and provides a point of flow-control to deal with the inheritance and |
27
|
|
|
|
|
|
|
other trickiness of having multiple formats handled through a single |
28
|
|
|
|
|
|
|
module. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 AUTHOR |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Eric L. Wilhelm |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
http://scratchcomputing.com |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 COPYRIGHT |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
This module is copyright (C) 2004-2006 by Eric L. Wilhelm. Portions |
39
|
|
|
|
|
|
|
copyright (C) 2003 by Eric L. Wilhelm and A. Zahner Co. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 LICENSE |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
This module is distributed under the same terms as Perl. See the Perl |
44
|
|
|
|
|
|
|
source package for details. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
You may use this software under one of the following licenses: |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
(1) GNU General Public License |
49
|
|
|
|
|
|
|
(found at http://www.gnu.org/copyleft/gpl.html) |
50
|
|
|
|
|
|
|
(2) Artistic License |
51
|
|
|
|
|
|
|
(found at http://www.perl.com/pub/language/misc/Artistic.html) |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 NO WARRANTY |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
This software is distributed with ABSOLUTELY NO WARRANTY. The author, |
56
|
|
|
|
|
|
|
his former employer, and any other contributors will in no way be held |
57
|
|
|
|
|
|
|
liable for any loss or damages resulting from its use. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head1 Modifications |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
The source code of this module is made freely available and |
62
|
|
|
|
|
|
|
distributable under the GPL or Artistic License. Modifications to and |
63
|
|
|
|
|
|
|
use of this software must adhere to one of these licenses. Changes to |
64
|
|
|
|
|
|
|
the code should be noted as such and this notification (as well as the |
65
|
|
|
|
|
|
|
above copyright information) must remain intact on all copies of the |
66
|
|
|
|
|
|
|
code. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Additionally, while the author is actively developing this code, |
69
|
|
|
|
|
|
|
notification of any intended changes or extensions would be most helpful |
70
|
|
|
|
|
|
|
in avoiding repeated work for all parties involved. Please contact the |
71
|
|
|
|
|
|
|
author with any such development plans. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 SEE ALSO |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=over |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=item L |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
The frontend. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=back |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head2 Builtin Backends |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
The following modules are included in the main distribution. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=over |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item L |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=item L |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item L |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=item L |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=back |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 External Backends |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=over |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item L |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
DWG/DXF handling using the OpenDWG toolkit. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item L |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Postscript output. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=item L |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Image::Magick based output. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=item L |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
PostgreSQL connected drawing database. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=item L |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Tk::WorldCanvas popup viewer -- not exactly an input/output backend, but |
122
|
|
|
|
|
|
|
it uses much of the same facility because it is primarily just output to |
123
|
|
|
|
|
|
|
a display. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=back |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=cut |
128
|
|
|
|
|
|
|
######################################################################## |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head1 front-end Input and output methods |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
The functions load() and save() are responsible for determining the |
133
|
|
|
|
|
|
|
filetype (with forced types available via $options{type}.) These then |
134
|
|
|
|
|
|
|
call the appropriate ::load() or ::save() functions. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
See the Plug-In Architecture section for details on how to add support |
137
|
|
|
|
|
|
|
for additional filetypes. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Beginning with version 0.26, a string-based type specification is |
140
|
|
|
|
|
|
|
available by using $filename = "$type:filename". While this prevents |
141
|
|
|
|
|
|
|
you from saving files with colons in the names, an explicit type passed |
142
|
|
|
|
|
|
|
in the options will allow it. This gives the added bonus that your |
143
|
|
|
|
|
|
|
program's users may directly control the output type simply by giving a |
144
|
|
|
|
|
|
|
: argument on the command line (if that is where you get |
145
|
|
|
|
|
|
|
your filenames.) |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head2 save |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Saves a file to disk. See the save functions in this file and the |
150
|
|
|
|
|
|
|
other filetype functions in the CAD::Drawing::IO:: modules. |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
See each save function for available options for that type. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
While you may call the save function directly (if you include the |
155
|
|
|
|
|
|
|
module), it is recommended that you stick to the single point of |
156
|
|
|
|
|
|
|
interface provided here so that your code does not become overwhelmingly |
157
|
|
|
|
|
|
|
infected with hard-coded filetypes. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Note that this method also implements forking. If $options{forkokay} is |
160
|
|
|
|
|
|
|
true, save() will return the pid of the child process to the parent |
161
|
|
|
|
|
|
|
process and setup the child to exit after saving (with currently no way |
162
|
|
|
|
|
|
|
for the child to give a return value to the parent (but (-e $filename) |
163
|
|
|
|
|
|
|
might work for you).) |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
$drw->save($filename, \%options); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
sub save { |
169
|
0
|
|
|
0
|
|
|
my $self = shift; |
170
|
0
|
|
|
|
|
|
my ( $filename, $opt) = @_; |
171
|
0
|
|
|
|
|
|
my $type = $$opt{type}; |
172
|
0
|
0
|
|
|
|
|
if($$opt{forkokay}) { |
173
|
0
|
|
|
|
|
|
$SIG{CHLD} = 'IGNORE'; |
174
|
0
|
|
|
|
|
|
my $kidpid; |
175
|
0
|
0
|
|
|
|
|
if($kidpid = fork) { |
176
|
0
|
|
|
|
|
|
return($kidpid); |
177
|
|
|
|
|
|
|
} |
178
|
0
|
0
|
|
|
|
|
defined($kidpid) or die "cannot fork $!\n"; |
179
|
0
|
|
|
|
|
|
$$opt{forkokay} = 0; |
180
|
0
|
|
|
|
|
|
$self->diskaction("save", $filename, $type, $opt); |
181
|
0
|
|
|
|
|
|
exit; |
182
|
|
|
|
|
|
|
} |
183
|
0
|
|
|
|
|
|
return($self->diskaction("save", $filename, $type, $opt)); |
184
|
|
|
|
|
|
|
} # end subroutine save definition |
185
|
|
|
|
|
|
|
######################################################################## |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head2 load |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Loads a file from disk. See the load functions in this file and |
190
|
|
|
|
|
|
|
the other filetype functions in the CAD::Drawing::IO:: modules. |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
See each load function for available options for that type. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
In most cases %options may contain the selection methods available via |
195
|
|
|
|
|
|
|
the CAD::Drawing::check_select() function. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
While you may call the load function directly (if you include the |
198
|
|
|
|
|
|
|
module), it is recommended that you stick to the single point of |
199
|
|
|
|
|
|
|
interface provided here. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
$drw->load($filename, \%options); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=cut |
204
|
|
|
|
|
|
|
sub load { |
205
|
0
|
|
|
0
|
|
|
my $self = shift; |
206
|
0
|
|
|
|
|
|
my ($filename, $opt) = @_; |
207
|
0
|
|
|
|
|
|
my $type = $$opt{type}; |
208
|
0
|
|
|
|
|
|
return($self->diskaction("load", $filename, $type, $opt)); |
209
|
|
|
|
|
|
|
} # end subroutine load definition |
210
|
|
|
|
|
|
|
######################################################################## |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head2 can_load |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Returns true if the plugins think they can load this filename (no |
215
|
|
|
|
|
|
|
test-loading is done, only verification of the type.) |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
$drw->can_load($filename); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=cut |
220
|
|
|
|
|
|
|
sub can_load { |
221
|
0
|
|
|
0
|
|
|
my $self = shift; |
222
|
0
|
|
|
|
|
|
my ($filename, $opt) = @_; |
223
|
0
|
|
|
|
|
|
my $type = $$opt{type}; |
224
|
0
|
|
|
|
|
|
return($self->diskaction("check", $filename, $type)); |
225
|
|
|
|
|
|
|
} # end subroutine can_load definition |
226
|
|
|
|
|
|
|
######################################################################## |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=head1 Plug-In Architecture |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
Plug-ins are modules which are under the CAD::Drawing::IO::* |
231
|
|
|
|
|
|
|
namespace. This namespace is searched at compile time, and any modules |
232
|
|
|
|
|
|
|
found are require()d inside of an eval() block (see BEGIN.) Compile |
233
|
|
|
|
|
|
|
failure in any one of these modules will be printed to STDERR, but will |
234
|
|
|
|
|
|
|
not halt the running program. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
Each plug-in is responsible for declaring one or all of the following |
237
|
|
|
|
|
|
|
variables: |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
our $can_save_type = "type"; |
240
|
|
|
|
|
|
|
our $can_load_type = "type (or another type)"; |
241
|
|
|
|
|
|
|
our $is_inherited = 1; # or 0 (or undef()) |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
If a package claims to be able to load or save a type, then it must |
244
|
|
|
|
|
|
|
contain the functions load() or save() (respectively.) Package which |
245
|
|
|
|
|
|
|
declare $is_inherited as a true value will become methods of the |
246
|
|
|
|
|
|
|
CAD::Drawing class (though their load() and save() functions will not |
247
|
|
|
|
|
|
|
be visible due to their location in the inheritance tree.) |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head2 BEGIN |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
The BEGIN block implements the module path searching (looking only in |
252
|
|
|
|
|
|
|
directories of @INC which contain a "CAD/Drawing/IO/" directory.) |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
For each plug-in which is found, code references are saved for later |
255
|
|
|
|
|
|
|
use by the diskaction() function. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=cut |
258
|
|
|
|
|
|
|
BEGIN { |
259
|
3
|
|
|
3
|
|
18
|
use File::Find; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
374
|
|
260
|
|
|
|
|
|
|
my %found; |
261
|
|
|
|
|
|
|
our %handlers; |
262
|
|
|
|
|
|
|
our %check_type; |
263
|
|
|
|
|
|
|
our @ISA; |
264
|
|
|
|
|
|
|
our $plgindbg = 0; |
265
|
3
|
|
|
3
|
|
15
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
4252
|
|
266
|
|
|
|
|
|
|
foreach my $inc (@INC) { |
267
|
|
|
|
|
|
|
# (if it starts with CAD/Drawing/IO/, then we are good) |
268
|
|
|
|
|
|
|
my $look = "$inc/CAD/Drawing/IO/"; |
269
|
|
|
|
|
|
|
(-d "$look") || next; |
270
|
|
|
|
|
|
|
# print "looking in $look\n"; |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# I suppose deeper nested namespaces are allowed |
273
|
|
|
|
|
|
|
find(sub { |
274
|
|
|
|
|
|
|
($_ =~ m/\.pm$/) or return; |
275
|
|
|
|
|
|
|
my $mod = $File::Find::name; |
276
|
|
|
|
|
|
|
$mod =~ s#^$inc/+##; |
277
|
|
|
|
|
|
|
$mod =~ s#/+#::#g; |
278
|
|
|
|
|
|
|
$mod =~ s/\.pm//; |
279
|
|
|
|
|
|
|
$found{$mod} and return; |
280
|
|
|
|
|
|
|
$found{$mod}++; |
281
|
|
|
|
|
|
|
# print "$File::Find::name\n"; |
282
|
|
|
|
|
|
|
# print "mod: $mod\n"; |
283
|
|
|
|
|
|
|
}, $look ); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
foreach my $mod (keys(%found)) { |
286
|
|
|
|
|
|
|
# see if they are usable |
287
|
|
|
|
|
|
|
$plgindbg && print "checking $mod\n"; |
288
|
|
|
|
|
|
|
if(eval("require " . $mod)) { |
289
|
|
|
|
|
|
|
my $useful; |
290
|
|
|
|
|
|
|
foreach my $action qw(load save) { |
291
|
|
|
|
|
|
|
my $type = eval( |
292
|
|
|
|
|
|
|
'$' . $mod . '::can_' . $action . '_type' |
293
|
|
|
|
|
|
|
); |
294
|
|
|
|
|
|
|
$type or next; |
295
|
|
|
|
|
|
|
$handlers{$action}{$type} and next; |
296
|
|
|
|
|
|
|
$useful++; |
297
|
|
|
|
|
|
|
$handlers{$action}{$type} = $mod . '::' . $action; |
298
|
|
|
|
|
|
|
$check_type{$type} = $mod . '::check_type'; |
299
|
|
|
|
|
|
|
$plgindbg and |
300
|
|
|
|
|
|
|
print "$action ($type) claimed by $mod\n"; |
301
|
|
|
|
|
|
|
$plgindbg and |
302
|
|
|
|
|
|
|
print "(found $handlers{$action}{$type})\n"; |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
if(eval('$' . $mod . '::is_inherited')) { |
305
|
|
|
|
|
|
|
push(@ISA, $mod); |
306
|
|
|
|
|
|
|
$useful++; |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
$plgindbg and ($useful and print "using $mod\n"); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
else { |
311
|
|
|
|
|
|
|
$@ and warn("warning:\n$@ for $mod\n\n"); |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
} # end foreach $mod |
314
|
|
|
|
|
|
|
} # end BEGIN |
315
|
|
|
|
|
|
|
######################################################################## |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head2 diskaction |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
This function is for internal use, intended to consolidate the type |
320
|
|
|
|
|
|
|
selection and calling of load/save methods. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
$drw->diskaction("load|save", $filename, $type, \%options); |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
For each plug-in package which was located in the BEGIN block, the |
325
|
|
|
|
|
|
|
function ::check_type() will be called, and must return a true |
326
|
|
|
|
|
|
|
value for the package to be used for $action. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=cut |
329
|
|
|
|
|
|
|
sub diskaction { |
330
|
|
|
|
|
|
|
my $self = shift; |
331
|
|
|
|
|
|
|
my ($action, $filename, $type, $opt) = @_; |
332
|
|
|
|
|
|
|
my %opts; |
333
|
|
|
|
|
|
|
(ref($opt) eq "HASH") && (%opts = %$opt); |
334
|
|
|
|
|
|
|
($action =~ m/save|load|check/) or |
335
|
|
|
|
|
|
|
croak("Cannot access disk with action: $action\n"); |
336
|
|
|
|
|
|
|
$filename or |
337
|
|
|
|
|
|
|
croak("Cannot $action without filename\n"); |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Hopefully this is fixed: if type is passed explicitly, we were |
340
|
|
|
|
|
|
|
# still strolling through the list to determine which module to |
341
|
|
|
|
|
|
|
# call. New strategy is to try using the explicit type first. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
#################################################################### |
344
|
|
|
|
|
|
|
# choose filetype: |
345
|
|
|
|
|
|
|
my %handlers = %CAD::Drawing::IO::handlers; |
346
|
|
|
|
|
|
|
my $og_fn = $filename; |
347
|
|
|
|
|
|
|
unless(defined($type)) { |
348
|
|
|
|
|
|
|
$plgindbg and |
349
|
|
|
|
|
|
|
print "type was undefined, trying split(/:/, \$file)\n"; |
350
|
|
|
|
|
|
|
my ($t, $n) = split(/:/, $filename, 2); |
351
|
|
|
|
|
|
|
if(defined($n)) { |
352
|
|
|
|
|
|
|
$plgindbg and print "got type: $t and name $n\n"; |
353
|
|
|
|
|
|
|
$filename = $n; |
354
|
|
|
|
|
|
|
$type = $t; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
# now we may have an explicit type (so backends should not be |
358
|
|
|
|
|
|
|
# allowed to claim solely on extension) |
359
|
|
|
|
|
|
|
if(defined($type) and ($action ne "check")) { |
360
|
|
|
|
|
|
|
if(my $call = $handlers{$action}{$type}) { |
361
|
|
|
|
|
|
|
no strict 'refs'; |
362
|
|
|
|
|
|
|
$plgindbg and print "quickly trying $call (for $type / $action)\n"; |
363
|
|
|
|
|
|
|
return($call->($self, $filename, {%opts, type => $type})); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
else { |
366
|
|
|
|
|
|
|
warn("explicit type '$type' bypassed...\n ", |
367
|
|
|
|
|
|
|
"exhaustive checks now"); |
368
|
|
|
|
|
|
|
$filename = $og_fn; |
369
|
|
|
|
|
|
|
undef($type); |
370
|
|
|
|
|
|
|
$plgindbg and warn("name now $filename\n"); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
my %check = %CAD::Drawing::IO::check_type; |
374
|
|
|
|
|
|
|
my $check_only = ($action eq "check"); |
375
|
|
|
|
|
|
|
$check_only and ($action = "load"); |
376
|
|
|
|
|
|
|
foreach my $mod (keys(%{$handlers{$action}})) { |
377
|
|
|
|
|
|
|
$plgindbg && print "checking $mod ($check{$mod})\n"; |
378
|
|
|
|
|
|
|
no strict 'refs'; |
379
|
|
|
|
|
|
|
my $real_type = $check{$mod}($filename, $type); |
380
|
|
|
|
|
|
|
# check must return true |
381
|
|
|
|
|
|
|
$real_type || next; |
382
|
|
|
|
|
|
|
# if we just want to know if it can be loaded, the answer is: |
383
|
|
|
|
|
|
|
$check_only and return(1); |
384
|
|
|
|
|
|
|
# XXX it would be good to have a real_filename here (so we could |
385
|
|
|
|
|
|
|
# do a -e on it when in check_only mode) |
386
|
|
|
|
|
|
|
my $call = $handlers{$action}{$mod}; |
387
|
|
|
|
|
|
|
$plgindbg && print "trying $call\n"; |
388
|
|
|
|
|
|
|
return($call->($self, $filename, {%opts, type => $real_type})); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
# FIXME: # maybe the fallback is a Storable or YAML file? |
391
|
|
|
|
|
|
|
$check_only and return(0); |
392
|
|
|
|
|
|
|
croak("could not $action $filename as type: $type"); |
393
|
|
|
|
|
|
|
} # end subroutine diskaction definition |
394
|
|
|
|
|
|
|
######################################################################## |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=head1 Utility Functions |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
These are simply inherited by the CAD::Drawing module for your direct |
399
|
|
|
|
|
|
|
usage. |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
=head2 outloop |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
Crazy new experimental output method. Each entity supported by the |
404
|
|
|
|
|
|
|
format should have a key to a function in %functions, which is expected |
405
|
|
|
|
|
|
|
to accept the following input data: |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
$functions{$ent_type}->($obj, \%data); |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
The %data hash is passed verbatim to each function. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
$count = $drw->outloop(\%functions, \%data); |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
In addition to each of the $ent_type keys, functions for the keys |
414
|
|
|
|
|
|
|
'before' and 'after' may also be defined. These (if they are defined) |
415
|
|
|
|
|
|
|
will be called before and after each entity, with the same arguments as |
416
|
|
|
|
|
|
|
the $ent_type functions. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=cut |
419
|
|
|
|
|
|
|
sub outloop { |
420
|
|
|
|
|
|
|
my $self = shift; |
421
|
|
|
|
|
|
|
my ($funcs, $data) = @_; |
422
|
|
|
|
|
|
|
my %functions = %$funcs; |
423
|
|
|
|
|
|
|
# we should ignore data here |
424
|
|
|
|
|
|
|
my $count = 0; |
425
|
|
|
|
|
|
|
foreach my $layer (keys(%{$self->{g}})) { |
426
|
|
|
|
|
|
|
foreach my $ent (keys(%{$self->{g}{$layer}})) { |
427
|
|
|
|
|
|
|
if($functions{$ent}) { |
428
|
|
|
|
|
|
|
foreach my $id (keys(%{$self->{g}{$layer}{$ent}})) { |
429
|
|
|
|
|
|
|
my %addr = ( |
430
|
|
|
|
|
|
|
"layer" => $layer, |
431
|
|
|
|
|
|
|
"type" => $ent, |
432
|
|
|
|
|
|
|
"id" => $id, |
433
|
|
|
|
|
|
|
); |
434
|
|
|
|
|
|
|
my $obj = $self->getobj(\%addr); |
435
|
|
|
|
|
|
|
$functions{before} && ($functions{before}->($obj, $data)); |
436
|
|
|
|
|
|
|
$functions{$ent}->($obj, $data); |
437
|
|
|
|
|
|
|
$functions{after} && ($functions{after}->($obj, $data)); |
438
|
|
|
|
|
|
|
$count++; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
else { |
442
|
|
|
|
|
|
|
carp("not supporting type: $ent"); |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
return($count); |
448
|
|
|
|
|
|
|
} # end subroutine outloop definition |
449
|
|
|
|
|
|
|
######################################################################## |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=head2 is_persistent |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
Returns 1 if $filename points to a persistent (directory / db) drawing. |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
$drw->is_persistent($filename); |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=cut |
458
|
|
|
|
|
|
|
sub is_persistent { |
459
|
|
|
|
|
|
|
my $self = shift; |
460
|
|
|
|
|
|
|
my $filename = shift; |
461
|
|
|
|
|
|
|
# XXX punting here: |
462
|
|
|
|
|
|
|
($filename =~ m/^split:/) and return(1); |
463
|
|
|
|
|
|
|
# FIXME backends really need to answer this |
464
|
|
|
|
|
|
|
return(0); |
465
|
|
|
|
|
|
|
} # end subroutine is_persistent definition |
466
|
|
|
|
|
|
|
######################################################################## |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
1; |