File Coverage

lib/Graphics/Fig/Parameters.pm
Criterion Covered Total %
statement 495 650 76.1
branch 137 246 55.6
condition 27 87 31.0
subroutine 33 42 78.5
pod 0 38 0.0
total 692 1063 65.1


line stmt bran cond sub pod time code
1             #
2             # XFig Drawing Library
3             #
4             # Copyright (c) 2017 D Scott Guthridge
5             #
6             # This program is free software: you can redistribute it and/or modify it under
7             # the terms of the Artistic License as published by the Perl Foundation, either
8             # version 2.0 of the License, or (at your option) any later version.
9             #
10             # This program is distributed in the hope that it will be useful, but WITHOUT
11             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12             # FOR A PARTICULAR PURPOSE. See the Artistic License for more details.
13             #
14             # You should have received a copy of the Artistic License along with this
15             # program. If not, see .
16             #
17             package Graphics::Fig::Parameters;
18             our $VERSION = 'v1.0.8';
19              
20 12     12   67 use strict;
  12         19  
  12         333  
21 12     12   48 use warnings;
  12         17  
  12         320  
22 12     12   48 use Carp;
  12         19  
  12         541  
23 12     12   3492 use Math::Trig qw(deg2rad);
  12         91819  
  12         73355  
24              
25             #
26             # RE_INT: regular expression matching an integer
27             #
28             my $RE_INT = "(?:(?:[-+]?)(?:[0123456789]+))";
29              
30             #
31             # RE_REAL regular expression matching a floating point number
32             #
33             my $RE_REAL = "(?:(?i)(?:[-+]?)(?:(?=[.]?[0123456789])(?:[0123456789]*)" .
34             "(?:(?:[.])(?:[0123456789]{0,}))?)(?:(?:[E])(?:(?:[-+]?)" .
35             "(?:[0123456789]+))|))";
36              
37             my %ArrowStyles = (
38             "stick" => [ 0, 0 ],
39             "triangle" => [ 1, 0 ],
40             "filled-triangle" => [ 1, 1 ],
41             "indented" => [ 2, 0 ],
42             "filled-indented" => [ 2, 1 ],
43             "pointed" => [ 3, 0 ],
44             "filled-pointed" => [ 3, 1 ],
45             "diamond" => [ 4, 0 ],
46             "filled-diamond" => [ 4, 1 ],
47             "circle" => [ 5, 0 ],
48             "filled-circle" => [ 5, 1 ],
49             "goblet" => [ 6, 0 ],
50             "filled-goblet" => [ 6, 1 ],
51             "square" => [ 7, 0 ],
52             "filled-square" => [ 7, 1 ],
53             "reverse-triangle" => [ 8, 0 ],
54             "filled-reverse-triangle" => [ 8, 1 ],
55             "left-indented" => [ 9, 0 ],
56             "right-indented" => [ 9, 0 ],
57             "half-triangle" => [ 10, 0 ],
58             "filled-half-triangle" => [ 10, 1 ],
59             "half-indented" => [ 11, 0 ],
60             "filled-half-indented" => [ 11, 1 ],
61             "half-pointed" => [ 12, 0 ],
62             "filled-half-pointed" => [ 12, 1 ],
63             "y" => [ 13, 0 ],
64             "t" => [ 13, 1 ],
65             "goal" => [ 14, 0 ],
66             "gallows" => [ 14, 1 ],
67             );
68              
69             my %CapStyles = (
70             "butt" => 0,
71             "round" => 1,
72             "projecting" => 2,
73             );
74              
75             my %AreaFills = (
76             "not-filled" => -1,
77             "black" => 0,
78             "full" => 20,
79             "saturated" => 20, # alias for compatibility
80             "white" => 40,
81             "left-diagonal-30" => 41,
82             "right-diagonal-30" => 42,
83             "crosshatch-30" => 43,
84             "left-diagonal-45" => 44,
85             "right-diagonal-45" => 45,
86             "crosshatch-45" => 46,
87             "horizontal-bricks" => 47,
88             "vertical-bricks" => 48,
89             "horizontal-lines" => 49,
90             "vertical-lines" => 50,
91             "crosshatch" => 51,
92             "horizontal-right-shingles" => 52,
93             "horizontal-left-shingles" => 53,
94             "vertical-descending-shingles" => 54,
95             "vertical-ascending-shingles" => 55,
96             "fish-scales" => 56,
97             "small-fish-scales" => 57,
98             "circles" => 58,
99             "hexagons" => 59,
100             "octagons" => 60,
101             "horizontal-tire-treads" => 61,
102             "vertical-tire-treads" => 62,
103             );
104              
105             my %FontNames = (
106             # LaTeX fonts
107             "default" => [ 0, 0 ],
108             "roman" => [ 0, 1 ],
109             "bold" => [ 0, 2 ],
110             "italic" => [ 0, 3 ],
111             "sans serif" => [ 0, 4 ],
112             "typewriter" => [ 0, 5 ],
113              
114             # PostScript fonts
115             "postscript default" => [ 4, -1 ],
116             "times roman" => [ 4, 0 ],
117             "times italic" => [ 4, 1 ],
118             "times bold" => [ 4, 2 ],
119             "times bold italic" => [ 4, 3 ],
120             "avantgarde book" => [ 4, 4 ],
121             "avantgarde book oblique" => [ 4, 5 ],
122             "avantgarde demi" => [ 4, 6 ],
123             "avantgarde demi oblique" => [ 4, 7 ],
124             "bookman light" => [ 4, 8 ],
125             "bookman light italic" => [ 4, 9 ],
126             "bookman demi" => [ 4, 10 ],
127             "bookman demi italic" => [ 4, 11 ],
128             "courier" => [ 4, 12 ],
129             "courier oblique" => [ 4, 13 ],
130             "courier bold" => [ 4, 14 ],
131             "courier bold oblique" => [ 4, 15 ],
132             "helvetica" => [ 4, 16 ],
133             "helvetica oblique" => [ 4, 17 ],
134             "helvetica bold" => [ 4, 18 ],
135             "helvetica bold oblique" => [ 4, 19 ],
136             "helvetica narrow" => [ 4, 20 ],
137             "helvetica narrow oblique" => [ 4, 21 ],
138             "helvetica narrow bold" => [ 4, 22 ],
139             "helvetica narrow bold oblique" => [ 4, 23 ],
140             "new century schoolbook roman" => [ 4, 24 ],
141             "new century schoolbook italic" => [ 4, 25 ],
142             "new century schoolbook bold" => [ 4, 26 ],
143             "new century schoolbook bold italic" => [ 4, 27 ],
144             "palatino roman" => [ 4, 28 ],
145             "palatino italic" => [ 4, 29 ],
146             "palatino bold" => [ 4, 30 ],
147             "palatino bold italic" => [ 4, 31 ],
148             "symbol" => [ 4, 32 ],
149             "zapf chancery medium italic" => [ 4, 33 ],
150             "zapf dingbats" => [ 4, 34 ],
151             );
152              
153             my %JoinStyles = (
154             "miter" => 0,
155             "round" => 1,
156             "bevel" => 2,
157             );
158              
159             my %LineStyles = (
160             "default" => -1,
161             "solid" => 0,
162             "dashed" => 1,
163             "dotted" => 2,
164             "dash-dotted" => 3,
165             "dash-double-dotted" => 4,
166             "dash-triple-dotted" => 5,
167             );
168              
169             my %PaperSizes = (
170             "Letter" => 1,
171             "Legal" => 1,
172             "Ledger" => 1,
173             "Tabloid" => 1,
174             "A" => 1,
175             "B" => 1,
176             "C" => 1,
177             "D" => 1,
178             "E" => 1,
179             "A4" => 1,
180             "A3" => 1,
181             "A2" => 1,
182             "A1" => 1,
183             "A0" => 1,
184             "B5" => 1,
185             );
186              
187             my %Units = (
188             ft => [ 12.0, "Inches" ],
189             foot => [ 12.0, "Inches" ],
190             feet => [ 12.0, "Inches" ],
191             in => [ 1.0, "Inches" ],
192             inch => [ 1.0, "Inches" ],
193             inches => [ 1.0, "Inches" ],
194             mil => [ 0.001, "Inches" ],
195             pt => [ 1.0 / 80.0, "Inches" ],
196             point => [ 1.0 / 80.0, "Inches" ],
197             m => [ 1.0 / 0.0254, "Metric" ],
198             meter => [ 1.0 / 0.0254, "Metric" ],
199             metre => [ 1.0 / 0.0254, "Metric" ],
200             dam => [ 1.0 / 0.254, "Metric" ],
201             dekameter => [ 1.0 / 0.254, "Metric" ],
202             dekametre => [ 1.0 / 0.254, "Metric" ],
203             cm => [ 1.0 / 2.54, "Metric" ],
204             centimeter => [ 1.0 / 2.54, "Metric" ],
205             centimetre => [ 1.0 / 2.54, "Metric" ],
206             mm => [ 1.0 / 25.4, "Metric" ],
207             millimeter => [ 1.0 / 25.4, "Metric" ],
208             millimetre => [ 1.0 / 25.4, "Metric" ],
209             fig => [ 1.0 / 1200.0, "Inches" ],
210             );
211              
212              
213             #
214             # Graphics::Fig::Parameters::convertAngle
215             # $fig: Fig instance
216             # $prefix: error message prefix
217             # $value: angle (degrees)
218             # $context: parameter context
219             #
220             sub convertAngle {
221 53     53 0 68 my $fig = shift;
222 53         69 my $prefix = shift;
223 53         63 my $value = shift;
224 53         57 my $context = shift;
225 53         72 my $result;
226             my $temp;
227              
228 53 50       844 if (!($value =~ m/^\s*($RE_REAL)/)) {
229 0         0 croak("${prefix}: error: ${value}: expected angle");
230             }
231 53         191 return deg2rad($value);
232             }
233              
234             #
235             # Graphics::Fig::Parameters::convertAreaFill
236             # $fig: Fig instance
237             # $prefix: error message prefix
238             # $value: fill style
239             # $context: parameter context
240             #
241             sub convertAreaFill {
242 7     7 0 12 my $fig = shift;
243 7         11 my $prefix = shift;
244 7         19 my $value = shift;
245 7         8 my $context = shift;
246 7         9 my $temp;
247              
248 7 50       30 if ($value =~ /^\d+$/) {
249 0         0 return $value;
250             }
251 7         17 $value = lc($value);
252 7 100       23 if (defined($temp = $AreaFills{$value})) {
253 6         10 return $temp;
254             }
255 1 50       3 if ($value =~ m/^shade(\d+)$/) {
256 0         0 my $val = $1;
257 0 0 0     0 if ($val < 1 || $val > 19) {
258 0         0 croak("${prefix}: error: $value: fill shade value must be " .
259             "between 1 and 19");
260             }
261 0         0 return $val;
262             }
263 1 50       5 if ($value =~ m/^tint(\d+)$/) {
264 1         3 my $val = $1;
265 1 50 33     6 if ($val < 1 || $val > 19) {
266 0         0 croak("${prefix}: error: $value: fill tint value must be " .
267             "between 1 and 19");
268             }
269 1         3 return 20 + $val;
270             }
271 0         0 croak("${prefix}: error: ${value}: expected area fill style");
272             }
273              
274             #
275             # Graphics::Fig::Parameters::convertArrowMode
276             # $fig: fig object
277             # $prefix: error message prefix
278             # $value: arrow mode
279             # $context: parameter context
280             #
281             sub convertArrowMode {
282 31     31 0 47 my $fig = shift;
283 31         32 my $prefix = shift;
284 31         42 my $value = shift;
285 31         38 my $context = shift;
286              
287 31 100       58 if ($value eq "none") {
288 1         1 return 0;
289             }
290 30 100 66     77 if ($value eq "forw" || $value eq "forward") {
291 27         38 return 1;
292             }
293 3 100 66     17 if ($value eq "back" || $value eq "backward") {
294 1         1 return 2;
295             }
296 2 50       5 if ($value eq "both") {
297 2         4 return 3;
298             }
299 0         0 croak("${prefix}: error: ${value}: expected {none|forw|back|both}");
300             }
301              
302             #
303             # Graphics::Fig::Parameters::convertArrowStyle
304             # $fig: Fig instance
305             # $prefix: error message prefix
306             # $value: arrow type
307             # $context: parameter context
308             #
309             sub convertArrowStyle {
310 7     7 0 8 my $fig = shift;
311 7         9 my $prefix = shift;
312 7         10 my $value = shift;
313 7         6 my $context = shift;
314 7         10 my $temp;
315              
316 7 50 33     22 if (ref($value) eq "ARRAY" && scalar(@{$value}) == 2) {
  0         0  
317 0         0 return $value;
318             }
319 7 50       16 if (defined($temp = $ArrowStyles{$value})) {
320 7         10 return $temp;
321             }
322 0         0 croak("${prefix}: error: ${value}: expected arrow style or [m, n]");
323             }
324              
325             #
326             # Graphics::Fig::Parameters::convertBool
327             # $fig: fig object
328             # $prefix: error message prefix
329             # $value: parameter value
330             # $context: parameter context
331             #
332             sub convertBool {
333 5     5 0 7 my $fig = shift;
334 5         7 my $prefix = shift;
335 5         6 my $value = shift;
336 5         6 my $context = shift;
337              
338 5 50 33     41 if ($value eq "false" || $value eq "0") {
339 0         0 return 0;
340             }
341 5 50 33     16 if ($value eq "true" || $value eq "1") {
342 5         7 return 1;
343             }
344 0         0 croak("${prefix}: error: ${value}: expected {true|false}");
345             }
346              
347             #
348             # Graphics::Fig::Parameters::convertCapStyle
349             # $fig: Fig instance
350             # $prefix: error message prefix
351             # $value: cap style
352             # $context: parameter context
353             #
354             sub convertCapStyle {
355 1     1 0 954 my $fig = shift;
356 1         4 my $prefix = shift;
357 1         2 my $value = shift;
358 1         2 my $context = shift;
359 1         1 my $temp;
360              
361 1 50       7 if ($value =~ m/^\d+$/) {
362 0         0 return $value;
363             }
364 1         3 $value = lc($value);
365 1 50       4 if (defined($temp = $CapStyles{$value})) {
366 1         2 return $temp;
367             }
368 0         0 croak("${prefix}: error: ${value}: expected {butt|round|projecting}");
369             }
370              
371             #
372             # Graphics::Fig::Parameters::convertColor
373             # $fig: Fig instance
374             # $prefix: error message prefix
375             # $value: color name
376             # $context: parameter context
377             #
378             sub convertColor {
379 42     42 0 51 my $fig = shift;
380 42         51 my $prefix = shift;
381 42         42 my $value = shift;
382 42         44 my $context = shift;
383              
384 42         42 my $rv = eval {
385 42         43 return ${$fig}{"colors"}->convert($value);
  42         123  
386             };
387 42 50       98 if ($@) {
388 0         0 $@ =~ s/ at [^\s]* line \d+\.\n//;
389 0         0 croak("${prefix}: $@");
390             }
391 42         51 return $rv;
392             }
393              
394             #
395             # Graphics::Fig::Parameters::convertDepth
396             # $fig: fig object
397             # $prefix: error message prefix
398             # $value: object depth
399             # $context: parameter context
400             #
401             sub convertDepth {
402 12     12 0 16 my $fig = shift;
403 12         14 my $prefix = shift;
404 12         15 my $value = shift;
405 12         14 my $context = shift;
406              
407 12 50 33     185 if (!($value =~ m/^$RE_INT$/) || $value < 0 || $value > 999) {
      33        
408 0         0 croak("${prefix}: error: ${value}: expected integer from 0 to 999");
409             }
410 12         36 return $value;
411             }
412              
413             #
414             # Graphics::Fig::Parameters::convertExportOptions
415             # $fig: Fig instance
416             # $prefix: error message prefix
417             # $value: angle (degrees)
418             # $context: parameter context
419             #
420             sub convertExportOptions {
421 0     0 0 0 my $fig = shift;
422 0         0 my $prefix = shift;
423 0         0 my $value = shift;
424 0         0 my $context = shift;
425              
426 0 0       0 if (ref($value) ne "ARRAY") {
427 0         0 croak("${prefix}: error: expected reference to array of scalars");
428             }
429 0         0 foreach my $item (@{$value}) {
  0         0  
430 0 0       0 if (ref($item) ne "") {
431 0         0 croak("${prefix}: error: expected reference to array of scalars");
432             }
433             }
434 0         0 return $value;
435             }
436              
437             #
438             # Graphics::Fig::Parameters::convertFontFlags
439             # $fig: fig object
440             # $prefix: error message prefix
441             # $value: font flags list
442             # $context: parameter context
443             #
444             sub convertFontFlags {
445 1     1 0 1 my $fig = shift;
446 1         2 my $prefix = shift;
447 1         1 my $value = shift;
448 1         2 my $context = shift;
449 1         2 my $flags = 0;
450              
451 1 50       1 if (defined(${$context}{"fontFlags"})) {
  1         3  
452 0         0 $flags = ${$context}{"fontFlags"};
  0         0  
453             }
454 1         2 $value =~ y/[A-Z]/[a-z]/;
455 1         6 while ($value =~ s/^\s*([-+]?)\s*([a-z]+)//) {
456 3         5 my $op = $1;
457 3         4 my $flag = $2;
458 3         3 my $mask;
459              
460 3 100       11 if ($flag eq "rigid") {
    100          
    50          
    50          
461 1         2 $mask = 1;
462             } elsif ($flag eq "special") {
463 1         1 $mask = 2;
464             } elsif ($flag eq "postscript") {
465 0         0 $mask = 4;
466             } elsif ($flag eq "hidden") {
467 1         1 $mask = 8;
468             } else {
469 0         0 croak("${prefix}: error: ${value}: unknown font flag (${flag})");
470             }
471 3 100       6 if ($op eq "-") {
472 2         6 $flags &= ~$mask;
473             } else {
474 1         4 $flags |= $mask;
475             }
476             }
477 1         2 $value =~ s/\s//;
478 1 50       2 if ($value ne "") {
479 0         0 croak("${prefix}: error: invalid font flags");
480             }
481 1         2 return $flags;
482             }
483              
484             #
485             # Graphics::Fig::Parameters::convertFontName
486             # $fig: fig object
487             # $prefix: error message prefix
488             # $value: font name
489             # $context: parameter context
490             #
491             sub convertFontName {
492 0     0 0 0 my $fig = shift;
493 0         0 my $prefix = shift;
494 0         0 my $value = shift;
495 0         0 my $context = shift;
496 0         0 my $temp;
497              
498 0         0 $value =~ y/[A-Z]/[a-z]/;
499 0 0       0 if (!(defined($temp = $FontNames{$value}))) {
500 0         0 croak("${prefix}: error: ${value}: unknown font name");
501             }
502 0         0 return $temp;
503             }
504              
505             #
506             # Graphics::Fig::Parameters::convertFontSize
507             # $fig: fig object
508             # $prefix: error message prefix
509             # $value: font size in points (1/72th of an inch)
510             # $context: parameter context
511             #
512             sub convertFontSize {
513 0     0 0 0 my $fig = shift;
514 0         0 my $prefix = shift;
515 0         0 my $value = shift;
516 0         0 my $context = shift;
517 0         0 my $temp;
518              
519 0 0 0     0 if (!($value =~ m/^\s*($RE_REAL)\s*$/) || $value <= 0) {
520 0         0 croak("${prefix}: error: ${value}: invalid font size");
521             }
522 0         0 return $value + 0;
523             }
524              
525             #
526             # Graphics::Fig::Parameters::convertInt
527             # $fig: Fig instance
528             # $prefix: error message prefix
529             # $value: integer
530             # $context: parameter context
531             #
532             sub convertInt {
533 5     5 0 8 my $fig = shift;
534 5         7 my $prefix = shift;
535 5         10 my $value = shift;
536 5         5 my $context = shift;
537 5         9 my $result;
538             my $temp;
539              
540 5 50       68 if (!($value =~ m/^\s*($RE_INT)/)) {
541 0         0 croak("${prefix}: error: ${value}: expected integer");
542             }
543 5         9 return $value;
544             }
545            
546             #
547             # Graphics::Fig::Parameters::convertJoinStyle
548             # $fig: Fig instance
549             # $prefix: error message prefix
550             # $value: join sytle
551             # $context: parameter context
552             #
553             sub convertJoinStyle {
554 0     0 0 0 my $fig = shift;
555 0         0 my $prefix = shift;
556 0         0 my $value = shift;
557 0         0 my $context = shift;
558 0         0 my $temp;
559              
560 0 0       0 if ($value =~ m/^\d+$/) {
561 0         0 return $value;
562             }
563 0         0 $value = lc($value);
564 0 0       0 if (defined($temp = $JoinStyles{$value})) {
565 0         0 return $temp;
566             }
567 0         0 croak("${prefix}: error: ${value}: expected {miter|round|bevel}");
568             }
569              
570             #
571             # Graphics::Fig::Parameters::convertLength
572             # $fig: Fig instance
573             # $prefix: error message prefix
574             # $value: number with optional unit
575             # $context: parameter context
576             #
577             sub convertLength {
578 650     650 0 604 my $fig = shift;
579 650         600 my $prefix = shift;
580 650         573 my $value = shift;
581 650         611 my $context = shift;
582 650         593 my $result;
583             my $temp;
584              
585 650 50       4751 if (!($value =~ s/^\s*($RE_REAL)//)) {
586 0         0 croak("${prefix}: error: ${value}: invalid number");
587             }
588 650         1122 $result = $1;
589 650         1105 $value =~ s/^\s*//;
590 650 100       924 if ($value eq "") {
    50          
591 638         603 $result *= ${$context}{"units"}[0];
  638         998  
592             } elsif (defined($temp = $Units{$value})) {
593 12         36 $result *= ${$temp}[0];
  12         33  
594             } else {
595 0         0 croak("${prefix}: error: ${value}: unrecognized unit");
596             }
597 650         1022 return $result;
598             }
599              
600             #
601             # Graphics::Fig::Parameters::convertLineStyle:
602             # $fig: Fig instance
603             # $prefix: error message prefix
604             # $value: line style
605             # $context: parameter context
606             #
607             sub convertLineStyle {
608 5     5 0 6 my $fig = shift;
609 5         4 my $prefix = shift;
610 5         5 my $value = shift;
611 5         4 my $context = shift;
612 5         6 my $temp;
613              
614 5 50       13 if ($value =~ /^\d+$/) {
615 0         0 return $value;
616             }
617 5         7 $value = lc($value);
618 5 50       9 if (defined($temp = $LineStyles{$value})) {
619 5         6 return $temp;
620             }
621 0         0 croak("${prefix}: error: ${value}: unknown line style");
622             }
623              
624             #
625             # Graphics::Fig::Parameters::convertMultiplePage: page setup for printing
626             # $fig: Fig instance
627             # $prefix: error message prefix
628             # $value: optional number followed by unit
629             # $context: parameter context
630             #
631             sub convertMultiplePage {
632 0     0 0 0 my $fig = shift;
633 0         0 my $prefix = shift;
634 0         0 my $value = shift;
635 0         0 my $context = shift;
636              
637 0 0       0 if ($value =~ m/^Single$/i) {
638 0         0 return "Single";
639             }
640 0 0       0 if ($value =~ m/^Multiple$/i) {
641 0         0 return "Multiple";
642             }
643 0         0 croak("${prefix}: error: ${value}: expected Single or Multiple");
644             }
645              
646             #
647             # Graphics::Fig::Parameters::convertOrientation: orientation for printing
648             # $fig: Fig instance
649             # $prefix: error message prefix
650             # $value: optional number followed by unit
651             # $context: parameter context
652             #
653             sub convertOrientation {
654 1     1 0 2 my $fig = shift;
655 1         3 my $prefix = shift;
656 1         2 my $value = shift;
657 1         1 my $context = shift;
658              
659 1 50       4 if ($value =~ m/^Landscape$/i) {
660 0         0 return "Landscape";
661             }
662 1 50       5 if ($value =~ m/^Portrait$/i) {
663 1         2 return "Portrait";
664             }
665 0         0 croak("${prefix}: error: ${value}: expected Landscape or Portrait");
666             }
667              
668             #
669             # Graphics::Fig::Parameters::convertPageJustification: printing justification
670             # printing
671             # $fig: Fig instance
672             # $prefix: error message prefix
673             # $value: optional number followed by unit
674             # $context: parameter context
675             #
676             sub convertPageJustification {
677 0     0 0 0 my $fig = shift;
678 0         0 my $prefix = shift;
679 0         0 my $value = shift;
680 0         0 my $context = shift;
681              
682 0 0       0 if ($value =~ m/^Center$/i) {
683 0         0 return "Center";
684             }
685 0 0       0 if ($value =~ m/^Flush\s*left$/i) {
686 0         0 return "Flush left";
687             }
688 0         0 croak("${prefix}: error: ${value}: expected \"Center\" or \"Flush left\"");
689             }
690              
691             #
692             # Graphics::Fig::Parameters::convertPaperSize: paper size for printing
693             # $fig: Fig instance
694             # $prefix: error message prefix
695             # $value: optional number followed by unit
696             # $context: parameter context
697             #
698             sub convertPaperSize {
699 0     0 0 0 my $fig = shift;
700 0         0 my $prefix = shift;
701 0         0 my $value = shift;
702 0         0 my $context = shift;
703              
704 0         0 $value =~ s/(.)(.*)/\u$1\L$2/;
705 0 0       0 if (defined($PaperSizes{$value})) {
706 0         0 return $value;
707             }
708 0         0 croak("${prefix}: error: ${value}: unknown paper size");
709             }
710              
711             #
712             # Graphics::Fig::Parameters::convertPoint
713             # $fig: Fig instance
714             # $prefix: error message prefix
715             # $value: reference to an [x, y] point
716             # $context: parameter context
717             #
718             sub convertPoint {
719 280     280 0 270 my $fig = shift;
720 280         281 my $prefix = shift;
721 280         264 my $value = shift;
722 280         285 my $context = shift;
723              
724 280 50 33     538 if (ref($value) ne "ARRAY" || scalar(@{$value}) != 2 ||
  280   33     622  
      33        
725 280         618 !defined(${$value}[0]) || !defined(${$value}[1])) {
  280         548  
726 0         0 croak("${prefix}: error: expected [x, y] point");
727             }
728 280         326 my $x = &convertLength($fig, $prefix, ${$value}[0], $context);
  280         430  
729 280         732 my $y = &convertLength($fig, $prefix, ${$value}[1], $context);
  280         609  
730 280         569 return [ $x, $y ];
731             }
732              
733             #
734             # Graphics::Fig::Parameters::convertPointList
735             # $fig: Fig instance
736             # $prefix: error message prefix
737             # $value: reference to an [[x1, y1], [x2, y2], ...] point list
738             # $context: parameter context
739             #
740             sub convertPointList {
741 82     82 0 94 my $fig = shift;
742 82         97 my $prefix = shift;
743 82         95 my $value = shift;
744 82         83 my $context = shift;
745 82         87 my @result;
746              
747 82 50       207 if (ref($value) ne "ARRAY") {
748 0         0 croak("${prefix}: error: expected [[x1, y1], [x2, y2], ...] " .
749             "point list");
750             }
751             # allow a single [x1, y1] point
752 82 100 100     77 if (scalar(@{$value}) == 2 &&
  82   66     231  
753 59         198 ref(${$value}[0]) eq "" && ref(${$value}[1]) eq "") {
  19         46  
754 19         53 push(@result, &convertPoint($fig, $prefix, $value, $context));
755              
756             } else {
757 63         70 foreach my $point (@{$value}) {
  63         96  
758 170         258 push(@result, &convertPoint($fig, $prefix, $point, $context));
759             }
760             }
761 82         135 return \@result;
762             }
763              
764             #
765             # Graphics::Fig::Parameters::convertPositiveReal
766             # $fig: Fig instance
767             # $prefix: error message prefix
768             # $value: optional number followed by unit
769             # $context: parameter context
770             #
771             sub convertPositiveReal {
772 0     0 0 0 my $fig = shift;
773 0         0 my $prefix = shift;
774 0         0 my $value = shift;
775 0         0 my $context = shift;
776              
777 0 0 0     0 if ($value =~ m/^\s*($RE_REAL)\s*$/ && $value > 0) {
778 0         0 return $value;
779             }
780 0         0 croak("${prefix}: error: ${value}: expected positive number");
781             }
782              
783             #
784             # Graphics::Fig::Parameters::convertScale
785             # $fig: Fig instance
786             # $prefix: error message prefix
787             # $value: u or [ u, v ]
788             # $context: parameter context
789             #
790             sub convertScale {
791 7     7 0 11 my $fig = shift;
792 7         10 my $prefix = shift;
793 7         9 my $value = shift;
794 7         9 my $context = shift;
795 7         11 my $u;
796             my $v;
797              
798 7 50       22 if (ref($value) eq "ARRAY") {
799 7 50 33     5 if (scalar(@{$value}) != 2 ||
  7   33     24  
      33        
      33        
800 7         24 !defined($u = ${$value}[0]) || !defined($v = ${$value}[1]) ||
  7         562  
801             !($u =~ m/^$RE_REAL/) || !($v =~ m/^\s*$RE_REAL/)) {
802 0         0 croak("${prefix} error: expected scalar or [u, v] pair");
803             }
804             } else {
805 0 0 0     0 if (!defined($value) || !ref($value) eq "" ||
      0        
806             !($value =~ m/$RE_REAL/)) {
807 0         0 croak("${prefix} error: expected scalar or [u, v] pair");
808             }
809 0         0 $u = $value;
810 0         0 $v = $value;
811             }
812 7         34 return [ $u, $v ];
813             }
814              
815             #
816             # Graphics::Fig::Spline::convertSplineSubtype
817             # $fig: fig object
818             # $prefix: error message prefix
819             # $value: subtype
820             # $context: parameter context
821             #
822             sub convertSplineSubtype {
823 14     14 0 14 my $fig = shift;
824 14         15 my $prefix = shift;
825 14         13 my $value = shift;
826 14         15 my $context = shift;
827              
828 14 100       24 if ($value eq "open-approximated") {
829 1         3 return 0;
830             }
831 13 100       22 if ($value eq "closed-approximated") {
832 1         2 return 1;
833             }
834 12 100       21 if ($value eq "open-interpolated") {
835 3         4 return 2;
836             }
837 9 100       15 if ($value eq "closed-interpolated") {
838 1         2 return 3;
839             }
840 8 100       13 if ($value eq "open-x") {
841 7         22 return 4;
842             }
843 1 50       3 if ($value eq "closed-x") {
844 1         3 return 5;
845             }
846 0 0       0 if ($value =~ m/^\s*($RE_INT)/) {
847 0 0 0     0 if ($value < 0 || $value > 5) {
848 0         0 croak("${prefix}: error: ${value}: expected integer in 0..5");
849             }
850 0         0 return $value;
851             }
852 0         0 croak("${prefix}: error: ${value}: expected " .
853             "{open|closed}-{approximated|interpolated|x}");
854             }
855              
856             #
857             # Graphics::Fig::Parameters::convertText
858             # $fig: Fig instance
859             # $prefix: error message prefix
860             # $value: optional number followed by unit
861             # $context: parameter context
862             #
863             sub convertText {
864 1     1 0 2 my $fig = shift;
865 1         2 my $prefix = shift;
866 1         2 my $value = shift;
867 1         1 my $context = shift;
868              
869             #
870             # Standard xfig supports only ASCII and the Latin-1 code supplement
871             # pages. Make sure there are no code points outside of the supported
872             # range. Also disallow control characters.
873             #
874 1         9 for (my $i = 0; $i < length($value); ++$i) {
875 12         15 my $n = ord(substr($value, $i, 1));
876 12 50 33     42 if ($n < 32 || $n == 0x7F || $n > 0xFF) {
      33        
877 0         0 croak("${prefix}: error: ${value}: " .
878             "invalid character ${n} in string");
879             }
880             }
881 1         2 return $value;
882             }
883              
884             #
885             # Graphics::Fig::Parameters::convertTextJustification
886             # $fig: Fig instance
887             # $prefix: error message prefix
888             # $value: "left", "center" or "right"
889             # $context: parameter context
890             #
891             sub convertTextJustification {
892 1     1 0 1 my $fig = shift;
893 1         2 my $prefix = shift;
894 1         1 my $value = shift;
895 1         2 my $context = shift;
896              
897 1         3 $value =~ y/[A-Z]/[a-z]/;
898 1 50       4 if ($value eq "left") {
899 0         0 return 0;
900             }
901 1 50       3 if ($value eq "center") {
902 1         1 return 1;
903             }
904 0 0       0 if ($value eq "right") {
905 0         0 return 2;
906             }
907 0 0 0     0 if (!($value =~ m/^$RE_INT$/) || $value < 0 || $value > 2) {
      0        
908 0         0 croak("${prefix}: error: ${value}: expected " .
909             "left|center|right");
910             }
911 0         0 return $value + 0;
912             }
913              
914             #
915             # Graphics::Fig::Parameters::convertTransparentColor: for gif export
916             # $fig: Fig instance
917             # $prefix: error message prefix
918             # $value: optional number followed by unit
919             # $context: parameter context
920             #
921             sub convertTransparentColor {
922 0     0 0 0 my $fig = shift;
923 0         0 my $prefix = shift;
924 0         0 my $value = shift;
925 0         0 my $context = shift;
926              
927 0 0 0     0 if ($value == -1 || $value == -2) {
928 0         0 return $value;
929             }
930 0         0 my $rv = eval {
931 0         0 return ${$fig}{"colors"}->convert($value);
  0         0  
932             };
933 0 0       0 if ($@) {
934 0         0 $@ =~ s/ at [^\s]* line \d+\.\n//;
935 0         0 croak("${prefix}: $@");
936             }
937 0         0 return $rv;
938             }
939              
940             #
941             # Graphics::Fig::Parameters::convertUnits
942             # $fig: Fig instance
943             # $prefix: error message prefix
944             # $value: optional number followed by unit
945             # $context: parameter context
946             #
947             sub convertUnits {
948 2     2 0 5 my $fig = shift;
949 2         3 my $prefix = shift;
950 2         4 my $value = shift;
951 2         4 my $context = shift;
952 2         3 my $scalar = 1.0;
953 2         3 my $temp;
954              
955 2 100       154 if ($value =~ s/^\s*($RE_REAL)//) {
956 1         4 $scalar = $1;
957             }
958 2         11 $value =~ s/^\s*//;
959 2 50       10 if (!defined($temp = $Units{$value})) {
960 0         0 croak("${prefix}: error: ${value}: unknown unit");
961             }
962 2         3 $scalar *= ${$temp}[0];
  2         9  
963 2         4 return [ $scalar, ${$temp}[1] ];
  2         79  
964             }
965              
966             #
967             # Graphics::Fig::Parameters::getParameterSignature: positional parameters sig
968             # @_: positional arguments
969             #
970             sub getParameterSignature {
971 393     393 0 462 my $result = "";
972              
973 393         529 foreach my $arg (@_) {
974 231         272 my $type = ref($arg);
975 231 100       444 if ($type eq "") {
    50          
    50          
    0          
    0          
    0          
    0          
    0          
976 157         211 $result .= '.';
977             } elsif ($type eq "SCALAR") {
978 0         0 $result .= '$';
979             } elsif ($type eq "ARRAY") {
980 74         123 $result .= '@';
981             } elsif ($type eq "HASH") {
982 0         0 $result .= '%';
983             } elsif ($type eq "CODE") {
984 0         0 $result .= '&';
985             } elsif ($type eq "REF") {
986 0         0 $result .= '\\';
987             } elsif ($type eq "GLOB") {
988 0         0 $result .= '*';
989             } elsif ($type eq "LVALUE") { # like scalar when reading
990 0         0 $result .= '$';
991             } else {
992 0         0 $result .= '?';
993             }
994             }
995 393         592 return $result;
996             }
997              
998              
999             our @ArrowParameters = (
1000             {
1001             name => "arrowMode",
1002             convert => \&convertArrowMode,
1003             default => 0,
1004             },
1005             {
1006             name => "arrowStyle",
1007             convert => \&convertArrowStyle,
1008             default => [ 0, 0 ],
1009             },
1010             {
1011             name => "fArrowStyle",
1012             convert => \&convertArrowStyle,
1013             },
1014             {
1015             name => "bArrowStyle",
1016             convert => \&convertArrowStyle,
1017             },
1018             {
1019             name => "arrowThickness",
1020             convert => \&convertLength,
1021             default => 1.0 / 80.0,
1022             },
1023             {
1024             name => "fArrowThickness",
1025             convert => \&convertLength,
1026             },
1027             {
1028             name => "bArrowThickness",
1029             convert => \&convertLength,
1030             },
1031             {
1032             name => "arrowWidth",
1033             convert => \&convertLength,
1034             default => 60.0 / 1200.0,
1035             },
1036             {
1037             name => "fArrowWidth",
1038             convert => \&convertLength,
1039             },
1040             {
1041             name => "bArrowWidth",
1042             convert => \&convertLength,
1043             },
1044             {
1045             name => "arrowHeight",
1046             convert => \&convertLength,
1047             default => 120.0 / 1200.0,
1048             },
1049             {
1050             name => "fArrowHeight",
1051             convert => \&convertLength,
1052             },
1053             {
1054             name => "bArrowHeight",
1055             convert => \&convertLength,
1056             },
1057             );
1058              
1059             our %CapStyleParameter = (
1060             name => "capStyle",
1061             convert => \&convertCapStyle,
1062             default => 0,
1063             );
1064              
1065             our %CenterParameter = (
1066             name => "center",
1067             convert => \&convertPoint,
1068             );
1069              
1070             our %ColorParameter = (
1071             name => "penColor",
1072             aliases => [ "color" ],
1073             convert => \&convertColor,
1074             default => 0,
1075             );
1076              
1077             our %CornerRadiusParameter = (
1078             name => "cornerRadius",
1079             convert => \&convertLength,
1080             );
1081              
1082             our %DepthParameter = (
1083             name => "depth",
1084             convert => \&convertDepth,
1085             default => 50,
1086             );
1087              
1088             our %DetachedLinetoParameter = (
1089             name => "detachedLineto",
1090             convert => \&convertBool,
1091             default => 0,
1092             );
1093              
1094             our @ExportParameters = (
1095             {
1096             name => "exportFormat",
1097             },
1098             {
1099             name => "exportOptions",
1100             convert => \&convertExportOptions,
1101             },
1102             );
1103              
1104             our @FillParameters = (
1105             {
1106             name => "fillColor",
1107             convert => \&convertColor,
1108             default => 7,
1109             },
1110             {
1111             name => "areaFill",
1112             convert => \&convertAreaFill,
1113             default => -1,
1114             },
1115             );
1116              
1117             our %GridParameter = (
1118             name => "grid",
1119             convert => \&convertLength,
1120             );
1121              
1122             our %JoinStyleParameter = (
1123             name => "joinStyle",
1124             convert => \&convertJoinStyle,
1125             default => 0,
1126             );
1127              
1128             our @LineParameters = (
1129             {
1130             name => "lineStyle",
1131             convert => \&convertLineStyle,
1132             default => 0,
1133             },
1134             {
1135             name => "lineThickness",
1136             convert => \&convertLength,
1137             default => 1.0 / 80.0,
1138             },
1139             {
1140             name => "styleVal",
1141             convert => \&convertLength,
1142             default => 0.075,
1143             },
1144             );
1145              
1146             our %OffsetParameter = (
1147             name => "offset",
1148             convert => \&convertPoint
1149             );
1150              
1151             our %PointParameter = (
1152             name => "point",
1153             convert => \&convertPoint,
1154             );
1155              
1156             our %PointsParameter = (
1157             name => "points",
1158             convert => \&convertPointList,
1159             aliases => [ "point" ],
1160             );
1161              
1162             our %PositionParameter = (
1163             name => "position",
1164             convert => \&convertPoint,
1165             default => [ 0.0, 0.0 ]
1166             );
1167              
1168             our %RotationParameter = (
1169             name => "rotation",
1170             convert => \&convertAngle,
1171             );
1172              
1173             our @SaveParameters = (
1174             {
1175             name => "orientation",
1176             convert => \&convertOrientation,
1177             default => "Landscape"
1178             },
1179             {
1180             name => "pageJustification",
1181             convert => \&convertPageJustification,
1182             default => "Center"
1183             },
1184             {
1185             name => "paperSize",
1186             convert => \&convertPaperSize,
1187             default => "Letter"
1188             },
1189             {
1190             name => "magnification",
1191             convert => \&convertPositiveReal,
1192             default => 100.0
1193             },
1194             {
1195             name => "multiplePage",
1196             convert => \&convertMultiplePage,
1197             default => "Single"
1198             },
1199             {
1200             name => "transparentColor",
1201             convert => \&convertTransparentColor,
1202             default => -2
1203             },
1204             {
1205             name => "comment",
1206             default => "",
1207             },
1208             );
1209              
1210             our %ScaleParameter = (
1211             name => "scale",
1212             convert => \&convertScale
1213             );
1214              
1215             our %SplineSubtypeParameter = (
1216             name => "splineSubtype",
1217             convert => \&convertSplineSubtype,
1218             default => 0,
1219             );
1220              
1221             our @TextParameters = (
1222             {
1223             name => "textJustification",
1224             convert => \&convertTextJustification,
1225             aliases => [ "justification" ],
1226             default => 0,
1227             },
1228             {
1229             name => "fontName",
1230             convert => \&convertFontName,
1231             aliases => [ "font" ],
1232             default => [ 0, 0 ],
1233             },
1234             {
1235             name => "fontSize",
1236             convert => \&convertFontSize,
1237             default => 12,
1238             },
1239             {
1240             name => "fontFlags",
1241             convert => \&convertFontFlags,
1242             default => 0,
1243             },
1244             );
1245              
1246             our %UnitsParameter = (
1247             name => "units",
1248             convert => \&convertUnits,
1249             default => [ 1.0, "Inches" ],
1250             );
1251              
1252             #
1253             # Graphics::Fig::Parameters::parse
1254             # $fig fig object
1255             # $context: error message context
1256             # $arglist: reference to caller's @_
1257             # $template: reference to option descriptor array
1258             # $defaults: optional ref to hash of default values
1259             # $result: reference to result hash
1260             #
1261             sub parse {
1262 393     393 0 452 my $fig = shift;
1263 393         439 my $context = shift;
1264 393         409 my $template = shift;
1265 393         388 my $defaults = shift;
1266 393         364 my $result = shift;
1267              
1268 393         366 my $positionalTemplate = ${$template}{"positional"};
  393         520  
1269 393         379 my $namedTemplate = ${$template}{"named"};
  393         441  
1270 393 50       625 if (!defined($namedTemplate)) {
1271 0         0 $namedTemplate = [];
1272             }
1273              
1274             #
1275             # If the last parameter is a reference to HASH, remove it as the
1276             # named namedParameters list.
1277             #
1278 393         376 my %namedParameters;
1279             {
1280 393         453 my $last = $#_;
  393         422  
1281 393 100 100     1237 if ($last >= 0 && ref($_[$last]) eq "HASH") {
1282 200         226 %namedParameters = %{pop(@_)};
  200         569  
1283             }
1284             }
1285              
1286             #
1287             # Validate the positional parameters and convert them into named
1288             # parameters.
1289             #
1290 393         645 my $signature = &getParameterSignature(@_);
1291 393 100       644 if ($signature ne "") {
1292 182         179 my $positionalParameterNames = ${$positionalTemplate}{$signature};
  182         373  
1293 182 50       303 if (!defined($positionalParameterNames)) {
1294 0         0 croak("${context}: invalid parameter list");
1295             }
1296 182         245 for (my $i = 0; $i < scalar(@{$positionalParameterNames}); ++$i) {
  413         641  
1297 231         205 my $name = ${$positionalParameterNames}[$i];
  231         321  
1298              
1299 231 50       355 if (defined($namedParameters{$name})) {
1300 0         0 croak("${context}: error: parameter ${name}: specified in " .
1301             "both positional and named lists");
1302             }
1303 231         387 $namedParameters{$name} = $_[$i];
1304             }
1305             }
1306              
1307             #
1308             # Go through the named parameter template in order. If the parameter
1309             # is defined in %namedParameters, use it. Otherwise, check if it's
1310             # defined in %{$defaults}. Otherwise, test if a default value was
1311             # given in the template. As we go, remove each parameter from the
1312             # named parameter hash.
1313             #
1314 393         366 foreach my $entry (@{$namedTemplate}) {
  393         536  
1315 9690         7450 my $name = ${$entry}{"name"};
  9690         9851  
1316 9690         7855 my $aliases = ${$entry}{"aliases"};
  9690         8262  
1317 9690         7631 my $convert = ${$entry}{"convert"};
  9690         8696  
1318 9690         7360 my $default = ${$entry}{"default"};
  9690         8426  
1319 9690         13964 my $subcontext = sprintf("%s: %s", $context, $name);
1320 9690         8536 my $pname;
1321             my $value;
1322              
1323 9690 100       11317 if (!defined($aliases)) {
1324 8855         7862 $aliases = [];
1325             }
1326 9690         7878 foreach my $tempName ($name, @{$aliases}) {
  9690         9966  
1327 10525         9810 my $tempValue = $namedParameters{$tempName};
1328 10525 100       13915 if (defined($tempValue)) {
1329 561 50       688 if (defined($pname)) {
1330 0         0 croak("${context}: error: " .
1331             "cannot specify both ${pname} and ${tempName}");
1332             }
1333 561         555 $pname = $tempName;
1334 561         500 $value = $tempValue;
1335 561         836 delete $namedParameters{$pname};
1336             }
1337             }
1338 9690 100       10763 if (defined($value)) {
1339 561 100       682 if (defined($convert)) {
1340 478         447 ${$result}{$name} = &{$convert}($fig, $subcontext,
  478         1176  
  478         787  
1341             $value, $result);
1342             } else {
1343 83         77 ${$result}{$name} = $value;
  83         118  
1344             }
1345 561         857 next;
1346             }
1347 9129 100       9876 if (defined($defaults)) {
1348 6583 100       5021 if (defined($value = ${$defaults}{$name})) {
  6583         8908  
1349 2711         2144 ${$result}{$name} = $value;
  2711         3229  
1350 2711         3384 next;
1351             }
1352             }
1353 6418 100       8101 if (defined($default)) {
1354 3664         2839 ${$result}{$name} = $default;
  3664         4274  
1355 3664         4414 next;
1356             }
1357             }
1358              
1359             #
1360             # If any named parameters remain, report the first as unknown.
1361             #
1362 393         609 foreach my $key (keys %namedParameters) {
1363 0         0 croak("${context}: unknown parameter: ${key}");
1364             }
1365 393         909 return 1;
1366             }
1367              
1368             #
1369             # Graphics::Fig::Parameters::translatePoints: translate by offset
1370             # $parameters: parameter list (offset)
1371             # ( [ x, y ], ... )
1372             #
1373             sub translatePoints {
1374 23     23 0 123 my $parameters = shift;
1375 23         69 my $offset = ${$parameters}{"offset"};
  23         26  
1376 23 50       36 die unless defined($offset);
1377 23 50       39 die unless ref($offset) eq "ARRAY";
1378 23         25 my $dx = ${$offset}[0];
  23         30  
1379 23         17 my $dy = ${$offset}[1];
  23         27  
1380 23         24 my @result;
1381              
1382 23         34 foreach my $point (@_) {
1383 74         64 push(@result, [ ${$point}[0] + $dx, ${$point}[1] + $dy ]);
  74         70  
  74         98  
1384             }
1385 23         36 return @result;
1386             }
1387              
1388             #
1389             # Graphics::Fig::Parameters::rotatePoints: rotate about center
1390             # $parameters: parameter list (center, rotation)
1391             # ( [ x, y ], ... )
1392             #
1393             sub rotatePoints {
1394 24     24 0 26 my $parameters = shift;
1395 24         25 my $rotation = ${$parameters}{"rotation"};
  24         32  
1396 24         24 my $center = ${$parameters}{"center"};
  24         22  
1397 24 100       57 if (!defined($center)) {
1398 18         19 $center = ${$parameters}{"position"};
  18         21  
1399             }
1400 24 50       36 die unless defined($center);
1401 24 50       32 die unless defined($rotation);
1402 24         23 my $xc = ${$center}[0];
  24         29  
1403 24         24 my $yc = ${$center}[1];
  24         27  
1404 24         88 my $c = cos($rotation);
1405 24         55 my $s = sin($rotation);
1406 24         23 my @result;
1407              
1408 24         39 foreach my $point (@_) {
1409 75         63 my ($x, $y) = @{$point};
  75         99  
1410 75         61 $x -= $xc;
1411 75         66 $y -= $yc;
1412 75         112 ( $x, $y ) = ( $c * $x + $s * $y, -$s * $x + $c * $y );
1413 75         70 $x += $xc;
1414 75         59 $y += $yc;
1415 75         120 push(@result, [ $x, $y ]);
1416             }
1417 24         122 return @result;
1418             }
1419              
1420             #
1421             # Graphics::Fig::Parameters::scalePoints: scale about center
1422             # $parameters: parameter list (center, scale)
1423             # ( [ x, y ], ... )
1424             #
1425             sub scalePoints {
1426 8     8 0 10 my $parameters = shift;
1427 8         10 my $scale = ${$parameters}{"scale"};
  8         13  
1428 8         9 my $center = ${$parameters}{"center"};
  8         11  
1429 8 50       18 if (!defined($center)) {
1430 8         8 $center = ${$parameters}{"position"};
  8         13  
1431             }
1432 8 50       16 die unless defined($scale);
1433 8 50       38 die unless defined($center);
1434 8         12 my $xc = ${$center}[0];
  8         14  
1435 8         8 my $yc = ${$center}[1];
  8         13  
1436 8         8 my $u = ${$scale}[0];
  8         18  
1437 8         10 my $v = ${$scale}[1];
  8         10  
1438 8         12 my @result;
1439              
1440 8         14 foreach my $point (@_) {
1441 31 50       55 die unless ref($point) eq "ARRAY";
1442 31         24 my ($x, $y) = @{$point};
  31         38  
1443 31         39 $x = $xc + ($x - $xc) * $u;
1444 31         26 $y = $yc + ($y - $yc) * $v;
1445 31         52 push(@result, [ $x, $y ]);
1446             }
1447 8         20 return @result;
1448             }
1449              
1450             #
1451             # Graphics::Fig::Parameters:getbboxFromPoints: find top-left bottom-right
1452             # from pts
1453             # @points
1454             #
1455             sub getbboxFromPoints {
1456 29     29 0 34 my ($x_min, $y_min, $x_max, $y_max);
1457              
1458 29         38 foreach my $point (@_) {
1459 100 100       120 if (!defined($x_min)) {
1460 29         26 $x_min = ${$point}[0];
  29         34  
1461 29         26 $y_min = ${$point}[1];
  29         27  
1462 29         27 $x_max = ${$point}[0];
  29         29  
1463 29         29 $y_max = ${$point}[1];
  29         28  
1464 29         32 next;
1465             }
1466 71 100       56 if (${$point}[0] < $x_min) {
  71         104  
1467 33         26 $x_min = ${$point}[0];
  33         33  
1468             }
1469 71 100       52 if (${$point}[1] < $y_min) {
  71         102  
1470 19         13 $y_min = ${$point}[1];
  19         21  
1471             }
1472 71 100       56 if (${$point}[0] > $x_max) {
  71         99  
1473 14         11 $x_max = ${$point}[0];
  14         15  
1474             }
1475 71 100       93 if (${$point}[1] > $y_max) {
  71         101  
1476 25         22 $y_max = ${$point}[1];
  25         50  
1477             }
1478             }
1479 29         84 return [ [ $x_min, $y_min ], [ $x_max, $y_max ] ];
1480             }
1481              
1482             #
1483             # Graphics::Fig::Parameters::copyArrowParameters: set fArrow, bArrow in object
1484             # $object: object to modify
1485             # $parameters: parameter list (center, scale)
1486             #
1487             sub copyArrowParameters {
1488 69     69 0 105 my $object = shift;
1489 69         75 my $parameters = shift;
1490              
1491 69         115 my @prefixes = ( "f", "b" );
1492 69         73 my $arrowMode = ${$parameters}{"arrowMode"};
  69         98  
1493 69         142 for (my $i = 0; $i < 2; ++$i) {
1494 138         145 my $prefix = $prefixes[$i];
1495 138         121 my $value = undef;
1496              
1497 138 100       227 if ($arrowMode & (1 << $i)) {
1498 45         49 my @R;
1499             my $temp;
1500 45 100       45 if (!defined($temp = ${$parameters}{"${prefix}ArrowStyle"})) {
  45         114  
1501 43         46 $temp = ${$parameters}{"arrowStyle"};
  43         51  
1502             }
1503 45         50 ( $R[0], $R[1] ) = @{$temp};
  45         105  
1504 45 100       48 if (!defined($temp = ${$parameters}{"${prefix}ArrowThickness"})) {
  45         105  
1505 44         36 $temp = ${$parameters}{"arrowThickness"};
  44         57  
1506             }
1507 45         56 $R[2] = $temp;
1508 45 100       63 if (!defined($temp = ${$parameters}{"${prefix}ArrowWidth"})) {
  45         85  
1509 44         48 $temp = ${$parameters}{"arrowWidth"};
  44         64  
1510             }
1511 45         63 $R[3] = $temp;
1512 45 100       44 if (!defined($temp = ${$parameters}{"${prefix}ArrowHeight"})) {
  45         89  
1513 44         43 $temp = ${$parameters}{"arrowHeight"};
  44         48  
1514             }
1515 45         71 $R[4] = $temp;
1516 45         59 $value = \@R;
1517             }
1518 138         125 ${$object}{"${prefix}Arrow"} = $value;
  138         293  
1519             }
1520 69         107 1;
1521             }
1522              
1523             #
1524             # Graphics::Fig::Parameters::compareArrowParameters: compare arrow parameters
1525             # $object: object to modify
1526             # $parameters: parameter list (center, scale)
1527             #
1528             sub compareArrowParameters {
1529 15     15 0 22 my $object = shift;
1530 15         16 my $parameters = shift;
1531 15         12 my $result;
1532              
1533 15         41 my @prefixes = ( "f", "b" );
1534 15         16 my $arrowMode = ${$parameters}{"arrowMode"};
  15         21  
1535 15         41 for (my $i = 0; $i < 2; ++$i) {
1536 30         36 my $prefix = $prefixes[$i];
1537 30         25 my $value;
1538              
1539 30 100       47 if ($arrowMode & (1 << $i)) {
    50          
1540 13 50       12 if (!defined($value = ${$object}{"${prefix}Arrow"})) {
  13         31  
1541 0         0 return -1;
1542             }
1543 13         13 my $temp;
1544 13 50       12 if (!defined($temp = ${$parameters}{"${prefix}arrowStyle"})) {
  13         24  
1545 13         13 $temp = ${$parameters}{"arrowStyle"};
  13         16  
1546             }
1547 13 50       12 if (($result = (${$value}[0] <=> ${$temp}[0])) != 0) {
  13         14  
  13         28  
1548 0         0 return $result;
1549             }
1550 13 50       14 if (($result = (${$value}[1] <=> ${$temp}[1])) != 0) {
  13         13  
  13         29  
1551 0         0 return $result;
1552             }
1553 13 50       14 if (!defined($temp = ${$parameters}{"${prefix}arrowThickness"})) {
  13         26  
1554 13         13 $temp = ${$parameters}{"arrowThickness"};
  13         16  
1555             }
1556 13 50       12 if (($result = (${$value}[2] <=> $temp)) != 0) {
  13         26  
1557 0         0 return $result;
1558             }
1559 13 50       11 if (!defined($temp = ${$parameters}{"${prefix}arrowWidth"})) {
  13         26  
1560 13         12 $temp = ${$parameters}{"arrowWidth"};
  13         16  
1561             }
1562 13 50       13 if (($result = (${$value}[3] <=> $temp)) != 0) {
  13         20  
1563 0         0 return $result;
1564             }
1565 13 50       13 if (!defined($temp = ${$parameters}{"${prefix}arrowHeight"})) {
  13         27  
1566 13         12 $temp = ${$parameters}{"arrowHeight"};
  13         15  
1567             }
1568 13 50       14 if (($result = (${$value}[4] <=> $temp)) != 0) {
  13         32  
1569 0         0 return $result;
1570             }
1571              
1572 17         45 } elsif (defined(${$object}{"${prefix}Arrow"})) {
1573 0         0 return +1;
1574             }
1575             }
1576 15         49 return 0;
1577             }
1578              
1579             #
1580             # Graphics::Fig::Parameters::printArrowParameters
1581             # $object: fig sub-object
1582             # $fh: reference to file handle
1583             # $parameters: save parameters
1584             #
1585             sub printArrowParameters {
1586 112     112 0 130 my $object = shift; # fArrow, bArrow
1587 112         105 my $fh = shift;
1588 112         113 my $parameters = shift;
1589              
1590 112         171 my $figPerInch = Graphics::Fig::_figPerInch($parameters);
1591 112         148 my ($fArrow, $bArrow);
1592 112 100       103 if (defined($fArrow = ${$object}{"fArrow"})) {
  112         213  
1593 42         40 my @A = @{$fArrow};
  42         91  
1594 42         279 printf $fh ("\t%d %d %.2f %.2f %.2f\n",
1595             $A[0], $A[1], $A[2] * 80.0,
1596             $A[3] * $figPerInch, $A[4] * $figPerInch);
1597             }
1598 112 100       134 if (defined($bArrow = ${$object}{"bArrow"})) {
  112         285  
1599 3         4 my @A = @{$bArrow};
  3         4  
1600 3         20 printf $fh ("\t%d %d %.2f %.2f %.2f\n",
1601             $A[0], $A[1], $A[2] * 80.0,
1602             $A[3] * $figPerInch, $A[4] * $figPerInch);
1603             }
1604             }
1605              
1606             1;