File Coverage

blib/lib/Graphics/Fig/Parameters.pm
Criterion Covered Total %
statement 498 653 76.2
branch 138 248 55.6
condition 27 87 31.0
subroutine 33 42 78.5
pod 0 38 0.0
total 696 1068 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.5';
19              
20 12     12   75 use strict;
  12         30  
  12         363  
21 12     12   66 use warnings;
  12         20  
  12         274  
22 12     12   53 use Carp;
  12         20  
  12         624  
23 12     12   6259 use Math::Trig qw(deg2rad);
  12         150758  
  12         80945  
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,
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 87 my $fig = shift;
222 53         75 my $prefix = shift;
223 53         79 my $value = shift;
224 53         70 my $context = shift;
225 53         81 my $result;
226             my $temp;
227              
228 53 50       907 if (!($value =~ m/^\s*($RE_REAL)/)) {
229 0         0 croak("${prefix}: error: ${value}: expected angle");
230             }
231 53         213 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 17 my $fig = shift;
243 7         15 my $prefix = shift;
244 7         12 my $value = shift;
245 7         14 my $context = shift;
246 7         11 my $temp;
247              
248 7 50       34 if ($value =~ /^\d+$/) {
249 0         0 return $value;
250             }
251 7         18 $value = lc($value);
252 7 100       29 if (defined($temp = $AreaFills{$value})) {
253 6         14 return $temp;
254             }
255 1 50       5 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     8 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         4 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 63 my $fig = shift;
283 31         50 my $prefix = shift;
284 31         47 my $value = shift;
285 31         45 my $context = shift;
286              
287 31 100       81 if ($value eq "none") {
288 1         3 return 0;
289             }
290 30 100 66     95 if ($value eq "forw" || $value eq "forward") {
291 27         57 return 1;
292             }
293 3 100 66     21 if ($value eq "back" || $value eq "backward") {
294 1         3 return 2;
295             }
296 2 50       31 if ($value eq "both") {
297 2         7 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 14 my $fig = shift;
311 7         26 my $prefix = shift;
312 7         15 my $value = shift;
313 7         9 my $context = shift;
314 7         15 my $temp;
315              
316 7 50 33     23 if (ref($value) eq "ARRAY" && scalar(@{$value}) == 2) {
  0         0  
317 0         0 return $value;
318             }
319 7 50       40 if (defined($temp = $ArrowStyles{$value})) {
320 7         17 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 8 my $fig = shift;
334 5         8 my $prefix = shift;
335 5         18 my $value = shift;
336 5         9 my $context = shift;
337              
338 5 50 33     25 if ($value eq "false" || $value eq "0") {
339 0         0 return 0;
340             }
341 5 50 33     24 if ($value eq "true" || $value eq "1") {
342 5         11 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 3 my $fig = shift;
356 1         4 my $prefix = shift;
357 1         2 my $value = shift;
358 1         2 my $context = shift;
359 1         2 my $temp;
360              
361 1 50       5 if ($value =~ m/^\d+$/) {
362 0         0 return $value;
363             }
364 1         4 $value = lc($value);
365 1 50       5 if (defined($temp = $CapStyles{$value})) {
366 1         3 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 74 my $fig = shift;
380 42         60 my $prefix = shift;
381 42         65 my $value = shift;
382 42         69 my $context = shift;
383              
384 42         65 my $rv = eval {
385 42         57 return ${$fig}{"colors"}->convert($value);
  42         143  
386             };
387 42 50       136 if ($@) {
388 0         0 $@ =~ s/ at [^\s]* line \d+\.\n//;
389 0         0 croak("${prefix}: $@");
390             }
391 42         119 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 25 my $fig = shift;
403 12         35 my $prefix = shift;
404 12         20 my $value = shift;
405 12         20 my $context = shift;
406              
407 12 50 33     243 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         34 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($value) 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 3 my $fig = shift;
446 1         2 my $prefix = shift;
447 1         2 my $value = shift;
448 1         2 my $context = shift;
449 1         2 my $flags = 0;
450              
451 1 50       3 if (defined(${$context}{"fontFlags"})) {
  1         5  
452 0         0 $flags = ${$context}{"fontFlags"};
  0         0  
453             }
454 1         2 $value =~ y/[A-Z]/[a-z]/;
455 1         9 while ($value =~ s/^\s*([-+]?)\s*([a-z]+)//) {
456 3         8 my $op = $1;
457 3         5 my $flag = $2;
458 3         4 my $mask;
459              
460 3 100       13 if ($flag eq "rigid") {
    100          
    50          
    50          
461 1         2 $mask = 1;
462             } elsif ($flag eq "special") {
463 1         2 $mask = 2;
464             } elsif ($flag eq "postscript") {
465 0         0 $mask = 4;
466             } elsif ($flag eq "hidden") {
467 1         2 $mask = 8;
468             } else {
469 0         0 croak("${prefix}: error: ${value}: unknown font flag (${flag})");
470             }
471 3 100       8 if ($op eq "-") {
472 2         9 $flags &= ~$mask;
473             } else {
474 1         6 $flags |= $mask;
475             }
476             }
477 1         2 $value =~ s/\s//;
478 1 50       3 if ($value ne "") {
479 0         0 croak("${prefix}: error: invalid font flags");
480             }
481 1         3 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 =~ s/^\s*($RE_REAL)//) && $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 7 my $fig = shift;
534 5         5 my $prefix = shift;
535 5         8 my $value = shift;
536 5         6 my $context = shift;
537 5         6 my $result;
538             my $temp;
539              
540 5 50       45 if (!($value =~ m/^\s*($RE_INT)/)) {
541 0         0 croak("${prefix}: error: ${value}: expected integer");
542             }
543 5         12 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 861 my $fig = shift;
579 650         809 my $prefix = shift;
580 650         881 my $value = shift;
581 650         864 my $context = shift;
582 650         813 my $result;
583             my $temp;
584              
585 650 50       5362 if (!($value =~ s/^\s*($RE_REAL)//)) {
586 0         0 croak("${prefix}: error: ${value}: invalid number");
587             }
588 650         1543 $result = $1;
589 650         1428 $value =~ s/^\s*//;
590 650 100       1208 if ($value eq "") {
    50          
591 638         731 $result *= ${$context}{"units"}[0];
  638         1333  
592             } elsif (defined($temp = $Units{$value})) {
593 12         22 $result *= ${$temp}[0];
  12         39  
594             } else {
595 0         0 croak("${prefix}: error: ${value}: unrecognized unit");
596             }
597 650         1366 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 10 my $fig = shift;
609 5         9 my $prefix = shift;
610 5         9 my $value = shift;
611 5         8 my $context = shift;
612 5         10 my $temp;
613              
614 5 50       21 if ($value =~ /^\d+$/) {
615 0         0 return $value;
616             }
617 5         12 $value = lc($value);
618 5 50       27 if (defined($temp = $LineStyles{$value})) {
619 5         12 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 3 my $fig = shift;
655 1         2 my $prefix = shift;
656 1         2 my $value = shift;
657 1         2 my $context = shift;
658              
659 1 50       4 if ($value =~ m/^Landscape$/i) {
660 0         0 return "Landscape";
661             }
662 1 50       6 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 396 my $fig = shift;
720 280         390 my $prefix = shift;
721 280         351 my $value = shift;
722 280         334 my $context = shift;
723              
724 280 50 33     656 if (ref($value) ne "ARRAY" || scalar(@{$value}) != 2 ||
  280   33     775  
      33        
725 280         777 !defined(${$value}[0]) || !defined(${$value}[1])) {
  280         782  
726 0         0 croak("${prefix}: error: expected [x, y] point");
727             }
728 280         446 my $x = &convertLength($fig, $prefix, ${$value}[0], $context);
  280         560  
729 280         450 my $y = &convertLength($fig, $prefix, ${$value}[1], $context);
  280         498  
730 280         704 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 147 my $fig = shift;
742 82         130 my $prefix = shift;
743 82         114 my $value = shift;
744 82         120 my $context = shift;
745 82         121 my @result;
746              
747 82 50       293 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     118 if (scalar(@{$value}) == 2 &&
  82   66     262  
753 59         254 ref(${$value}[0]) eq "" && ref(${$value}[1]) eq "") {
  19         52  
754 19         65 push(@result, &convertPoint($fig, $prefix, $value, $context));
755              
756             } else {
757 63         96 foreach my $point (@{$value}) {
  63         199  
758 170         441 push(@result, &convertPoint($fig, $prefix, $point, $context));
759             }
760             }
761 82         209 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 =~ s/^($RE_REAL)$// && $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 13 my $fig = shift;
792 7         14 my $prefix = shift;
793 7         13 my $value = shift;
794 7         13 my $context = shift;
795 7         13 my $u;
796             my $v;
797              
798 7 50       30 if (ref($value) eq "ARRAY") {
799 7 50 33     12 if (scalar(@{$value}) != 2 ||
  7   33     29  
      33        
      33        
800 7         34 !defined($u = ${$value}[0]) || !defined($v = ${$value}[1]) ||
  7         627  
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         42 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 21 my $fig = shift;
824 14         16 my $prefix = shift;
825 14         20 my $value = shift;
826 14         18 my $context = shift;
827              
828 14 100       24 if ($value eq "open-approximated") {
829 1         2 return 0;
830             }
831 13 100       28 if ($value eq "closed-approximated") {
832 1         2 return 1;
833             }
834 12 100       20 if ($value eq "open-interpolated") {
835 3         5 return 2;
836             }
837 9 100       18 if ($value eq "closed-interpolated") {
838 1         2 return 3;
839             }
840 8 100       15 if ($value eq "open-x") {
841 7         12 return 4;
842             }
843 1 50       4 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         3 my $prefix = shift;
866 1         2 my $value = shift;
867 1         2 my $context = shift;
868 1         2 my $temp = $value;
869              
870 1         5 utf8::encode($temp);
871 1         10 for (my $i = 0; $i < length($temp); ++$i) {
872 12         20 my $n = ord(substr($temp, $i, 1));
873 12 50 33     46 die if $n < 0 || $n > 255;
874 12 50 33     49 if ($n < 32 || $n == 127) {
875 0         0 croak("${prefix}: error: ${value}: " .
876             "invalid character ${n} in string");
877             }
878             }
879 1         3 return $value;
880             }
881              
882             #
883             # Graphics::Fig::Parameters::convertTextJustification
884             # $fig: Fig instance
885             # $prefix: error message prefix
886             # $value: "left", "center" or "right"
887             # $context: parameter context
888             #
889             sub convertTextJustification {
890 1     1 0 3 my $fig = shift;
891 1         2 my $prefix = shift;
892 1         2 my $value = shift;
893 1         2 my $context = shift;
894              
895 1         4 $value =~ y/[A-Z]/[a-z]/;
896 1 50       4 if ($value eq "left") {
897 0         0 return 0;
898             }
899 1 50       6 if ($value eq "center") {
900 1         2 return 1;
901             }
902 0 0       0 if ($value eq "right") {
903 0         0 return 2;
904             }
905 0 0 0     0 if (!($value =~ m/^$RE_INT$/) || $value < 0 || $value > 2) {
      0        
906 0         0 croak("${prefix}: error: ${value}: expected " .
907             "left|center|right");
908             }
909 0         0 return $value + 0;
910             }
911              
912             #
913             # Graphics::Fig::Parameters::convertTransparentColor: for gif export
914             # $fig: Fig instance
915             # $prefix: error message prefix
916             # $value: optional number followed by unit
917             # $context: parameter context
918             #
919             sub convertTransparentColor {
920 0     0 0 0 my $fig = shift;
921 0         0 my $prefix = shift;
922 0         0 my $value = shift;
923 0         0 my $context = shift;
924              
925 0 0 0     0 if ($value == -1 || $value == -2) {
926 0         0 return $value;
927             }
928 0         0 my $rv = eval {
929 0         0 return ${$fig}{"colors"}->convert($value);
  0         0  
930             };
931 0 0       0 if ($@) {
932 0         0 $@ =~ s/ at [^\s]* line \d+\.\n//;
933 0         0 croak("${prefix}: $@");
934             }
935 0         0 return $rv;
936             }
937              
938             #
939             # Graphics::Fig::Parameters::convertUnits
940             # $fig: Fig instance
941             # $prefix: error message prefix
942             # $value: optional number followed by unit
943             # $context: parameter context
944             #
945             sub convertUnits {
946 2     2 0 5 my $fig = shift;
947 2         6 my $prefix = shift;
948 2         4 my $value = shift;
949 2         5 my $context = shift;
950 2         5 my $scalar = 1.0;
951 2         4 my $temp;
952              
953 2 100       155 if ($value =~ s/^\s*($RE_REAL)//) {
954 1         5 $scalar = $1;
955             }
956 2         14 $value =~ s/^\s*//;
957 2 50       12 if (!defined($temp = $Units{$value})) {
958 0         0 croak("${prefix}: error: ${value}: unknown unit");
959             }
960 2         6 $scalar *= ${$temp}[0];
  2         7  
961 2         6 return [ $scalar, ${$temp}[1] ];
  2         7  
962             }
963              
964             #
965             # Graphics::Fig::Parameters::getParameterSignature: positional parameters sig
966             # @_: positional arguments
967             #
968             sub getParameterSignature {
969 393     393 0 622 my $result = "";
970              
971 393         712 foreach my $arg (@_) {
972 231         417 my $type = ref($arg);
973 231 100       552 if ($type eq "") {
    50          
    50          
    0          
    0          
    0          
    0          
    0          
974 157         266 $result .= '.';
975             } elsif ($type eq "SCALAR") {
976 0         0 $result .= '$';
977             } elsif ($type eq "ARRAY") {
978 74         144 $result .= '@';
979             } elsif ($type eq "HASH") {
980 0         0 $result .= '%';
981             } elsif ($type eq "CODE") {
982 0         0 $result .= '&';
983             } elsif ($type eq "REF") {
984 0         0 $result .= '\\';
985             } elsif ($type eq "GLOB") {
986 0         0 $result .= '*';
987             } elsif ($type eq "LVALUE") { # like scalar when reading
988 0         0 $result .= '$';
989             } else {
990 0         0 $result .= '?';
991             }
992             }
993 393         772 return $result;
994             }
995              
996              
997             our @ArrowParameters = (
998             {
999             name => "arrowMode",
1000             convert => \&convertArrowMode,
1001             default => 0,
1002             },
1003             {
1004             name => "arrowStyle",
1005             convert => \&convertArrowStyle,
1006             default => [ 0, 0 ],
1007             },
1008             {
1009             name => "fArrowStyle",
1010             convert => \&convertArrowStyle,
1011             },
1012             {
1013             name => "bArrowStyle",
1014             convert => \&convertArrowStyle,
1015             },
1016             {
1017             name => "arrowThickness",
1018             convert => \&convertLength,
1019             default => 1.0 / 80.0,
1020             },
1021             {
1022             name => "fArrowThickness",
1023             convert => \&convertLength,
1024             },
1025             {
1026             name => "bArrowThickness",
1027             convert => \&convertLength,
1028             },
1029             {
1030             name => "arrowWidth",
1031             convert => \&convertLength,
1032             default => 60.0 / 1200.0,
1033             },
1034             {
1035             name => "fArrowWidth",
1036             convert => \&convertLength,
1037             },
1038             {
1039             name => "bArrowWidth",
1040             convert => \&convertLength,
1041             },
1042             {
1043             name => "arrowHeight",
1044             convert => \&convertLength,
1045             default => 120.0 / 1200.0,
1046             },
1047             {
1048             name => "fArrowHeight",
1049             convert => \&convertLength,
1050             },
1051             {
1052             name => "bArrowHeight",
1053             convert => \&convertLength,
1054             },
1055             );
1056              
1057             our %CapStyleParameter = (
1058             name => "capStyle",
1059             convert => \&convertCapStyle,
1060             default => 0,
1061             );
1062              
1063             our %CenterParameter = (
1064             name => "center",
1065             convert => \&convertPoint,
1066             );
1067              
1068             our %ColorParameter = (
1069             name => "penColor",
1070             aliases => [ "color" ],
1071             convert => \&convertColor,
1072             default => 0,
1073             );
1074              
1075             our %CornerRadiusParameter = (
1076             name => "cornerRadius",
1077             convert => \&convertLength,
1078             );
1079              
1080             our %DepthParameter = (
1081             name => "depth",
1082             convert => \&convertDepth,
1083             default => 50,
1084             );
1085              
1086             our %DetachedLinetoParameter = (
1087             name => "detachedLineto",
1088             convert => \&convertBool,
1089             default => 0,
1090             );
1091              
1092             our @ExportParameters = (
1093             {
1094             name => "exportFormat",
1095             },
1096             {
1097             name => "exportOptions",
1098             convert => \&convertExportOptions,
1099             },
1100             );
1101              
1102             our @FillParameters = (
1103             {
1104             name => "fillColor",
1105             convert => \&convertColor,
1106             default => 7,
1107             },
1108             {
1109             name => "areaFill",
1110             convert => \&convertAreaFill,
1111             default => -1,
1112             },
1113             );
1114              
1115             our %GridParameter = (
1116             name => "grid",
1117             convert => \&convertLength,
1118             );
1119              
1120             our %JoinStyleParameter = (
1121             name => "joinStyle",
1122             convert => \&convertJoinStyle,
1123             default => 0,
1124             );
1125              
1126             our @LineParameters = (
1127             {
1128             name => "lineStyle",
1129             convert => \&convertLineStyle,
1130             default => 0,
1131             },
1132             {
1133             name => "lineThickness",
1134             convert => \&convertLength,
1135             default => 1.0 / 80.0,
1136             },
1137             {
1138             name => "styleVal",
1139             convert => \&convertLength,
1140             default => 0.075,
1141             },
1142             );
1143              
1144             our %OffsetParameter = (
1145             name => "offset",
1146             convert => \&convertPoint
1147             );
1148              
1149             our %PointParameter = (
1150             name => "point",
1151             convert => \&convertPoint,
1152             );
1153              
1154             our %PointsParameter = (
1155             name => "points",
1156             convert => \&convertPointList,
1157             aliases => [ "point" ],
1158             );
1159              
1160             our %PositionParameter = (
1161             name => "position",
1162             convert => \&convertPoint,
1163             default => [ 0.0, 0.0 ]
1164             );
1165              
1166             our %RotationParameter = (
1167             name => "rotation",
1168             convert => \&convertAngle,
1169             );
1170              
1171             our @SaveParameters = (
1172             {
1173             name => "orientation",
1174             convert => \&convertOrientation,
1175             default => "Landscape"
1176             },
1177             {
1178             name => "pageJustification",
1179             convert => \&convertPageJustification,
1180             default => "Center"
1181             },
1182             {
1183             name => "paperSize",
1184             convert => \&convertPaperSize,
1185             default => "Letter"
1186             },
1187             {
1188             name => "magnification",
1189             convert => \&convertPositiveReal,
1190             default => 100.0
1191             },
1192             {
1193             name => "multiplePage",
1194             convert => \&convertMultiplePage,
1195             default => "Single"
1196             },
1197             {
1198             name => "transparentColor",
1199             convert => \&convertTransparentColor,
1200             default => -2
1201             },
1202             {
1203             name => "comment",
1204             default => "",
1205             },
1206             );
1207              
1208             our %ScaleParameter = (
1209             name => "scale",
1210             convert => \&convertScale
1211             );
1212              
1213             our %SplineSubtypeParameter = (
1214             name => "splineSubtype",
1215             convert => \&convertSplineSubtype,
1216             default => 0,
1217             );
1218              
1219             our @TextParameters = (
1220             {
1221             name => "textJustification",
1222             convert => \&convertTextJustification,
1223             aliases => [ "justification" ],
1224             default => 0,
1225             },
1226             {
1227             name => "fontName",
1228             convert => \&convertFontName,
1229             aliases => [ "font" ],
1230             default => [ 0, 0 ],
1231             },
1232             {
1233             name => "fontSize",
1234             convert => \&convertFontSize,
1235             default => 12,
1236             },
1237             {
1238             name => "fontFlags",
1239             convert => \&convertFontFlags,
1240             default => 0,
1241             },
1242             );
1243              
1244             our %UnitsParameter = (
1245             name => "units",
1246             convert => \&convertUnits,
1247             default => [ 1.0, "Inches" ],
1248             );
1249              
1250             #
1251             # Graphics::Fig::Parameters::parse
1252             # $fig fig object
1253             # $context: error message context
1254             # $arglist: reference to caller's @_
1255             # $template: reference to option descriptor array
1256             # $defaults: optional ref to hash of default values
1257             # $result: reference to result hash
1258             #
1259             sub parse {
1260 393     393 0 580 my $fig = shift;
1261 393         619 my $context = shift;
1262 393         485 my $template = shift;
1263 393         528 my $defaults = shift;
1264 393         513 my $result = shift;
1265              
1266 393         496 my $positionalTemplate = ${$template}{"positional"};
  393         726  
1267 393         525 my $namedTemplate = ${$template}{"named"};
  393         616  
1268 393 50       808 if (!defined($namedTemplate)) {
1269 0         0 $namedTemplate = [];
1270             }
1271              
1272             #
1273             # If the last parameter is a reference to HASH, remove it as the
1274             # named namedParameters list.
1275             #
1276 393         516 my %namedParameters;
1277             {
1278 393         502 my $last = $#_;
  393         571  
1279 393 100 100     1486 if ($last >= 0 && ref($_[$last]) eq "HASH") {
1280 200         283 %namedParameters = %{pop(@_)};
  200         707  
1281             }
1282             }
1283              
1284             #
1285             # Validate the positional parameters and convert them into named
1286             # parameters.
1287             #
1288 393         877 my $signature = &getParameterSignature(@_);
1289 393 100       828 if ($signature ne "") {
1290 182         233 my $positionalParameterNames = ${$positionalTemplate}{$signature};
  182         386  
1291 182 50       381 if (!defined($positionalParameterNames)) {
1292 0         0 croak("${context}: invalid parameter list");
1293             }
1294 182         260 for (my $i = 0; $i < scalar(@{$positionalParameterNames}); ++$i) {
  413         797  
1295 231         288 my $name = ${$positionalParameterNames}[$i];
  231         397  
1296              
1297 231 50       466 if (defined($namedParameters{$name})) {
1298 0         0 croak("${context}: error: parameter ${name}: specified in " .
1299             "both positional and named lists");
1300             }
1301 231         493 $namedParameters{$name} = $_[$i];
1302             }
1303             }
1304              
1305             #
1306             # Go through the named parameter template in order. If the parameter
1307             # is defined in %namedParameters, use it. Otherwise, check if it's
1308             # defined in %{$defaults}. Otherwise, test if a default value was
1309             # given in the template. As we go, remove each parameter from the
1310             # named parameter hash.
1311             #
1312 393         523 foreach my $entry (@{$namedTemplate}) {
  393         737  
1313 9690         10966 my $name = ${$entry}{"name"};
  9690         13635  
1314 9690         12158 my $aliases = ${$entry}{"aliases"};
  9690         12013  
1315 9690         11022 my $convert = ${$entry}{"convert"};
  9690         11943  
1316 9690         10912 my $default = ${$entry}{"default"};
  9690         11806  
1317 9690         17964 my $subcontext = sprintf("%s: %s", $context, $name);
1318 9690         12654 my $pname;
1319             my $value;
1320              
1321 9690 100       14709 if (!defined($aliases)) {
1322 8855         11120 $aliases = [];
1323             }
1324 9690         11607 foreach my $tempName ($name, @{$aliases}) {
  9690         13674  
1325 10525         13474 my $tempValue = $namedParameters{$tempName};
1326 10525 100       17761 if (defined($tempValue)) {
1327 561 50       979 if (defined($pname)) {
1328 0         0 croak("${context}: error: " .
1329             "cannot specify both ${pname} and ${tempName}");
1330             }
1331 561         729 $pname = $tempName;
1332 561         704 $value = $tempValue;
1333 561         1089 delete $namedParameters{$pname};
1334             }
1335             }
1336 9690 100       14576 if (defined($value)) {
1337 561 100       927 if (defined($convert)) {
1338 478         658 ${$result}{$name} = &{$convert}($fig, $subcontext,
  478         1374  
  478         1032  
1339             $value, $result);
1340             } else {
1341 83         133 ${$result}{$name} = $value;
  83         153  
1342             }
1343 561         1141 next;
1344             }
1345 9129 100       13425 if (defined($defaults)) {
1346 6583 100       7516 if (defined($value = ${$defaults}{$name})) {
  6583         11668  
1347 2711         3175 ${$result}{$name} = $value;
  2711         4088  
1348 2711         4616 next;
1349             }
1350             }
1351 6418 100       10755 if (defined($default)) {
1352 3664         4144 ${$result}{$name} = $default;
  3664         5675  
1353 3664         5827 next;
1354             }
1355             }
1356              
1357             #
1358             # If any named parameters remain, report the first as unknown.
1359             #
1360 393         776 foreach my $key (keys %namedParameters) {
1361 0         0 croak("${context}: unknown parameter: ${key}");
1362             }
1363 393         1249 return 1;
1364             }
1365              
1366             #
1367             # Graphics::Fig::Parameters::translatePoints: translate by offset
1368             # $parameters: parameter list (offset)
1369             # ( [ x, y ], ... )
1370             #
1371             sub translatePoints {
1372 23     23 0 32 my $parameters = shift;
1373 23         56 my $offset = ${$parameters}{"offset"};
  23         43  
1374 23 50       50 die unless defined($offset);
1375 23 50       53 die unless ref($offset) eq "ARRAY";
1376 23         33 my $dx = ${$offset}[0];
  23         35  
1377 23         32 my $dy = ${$offset}[1];
  23         36  
1378 23         30 my @result;
1379              
1380 23         40 foreach my $point (@_) {
1381 74         97 push(@result, [ ${$point}[0] + $dx, ${$point}[1] + $dy ]);
  74         99  
  74         166  
1382             }
1383 23         54 return @result;
1384             }
1385              
1386             #
1387             # Graphics::Fig::Parameters::rotatePoints: rotate about center
1388             # $parameters: parameter list (center, rotation)
1389             # ( [ x, y ], ... )
1390             #
1391             sub rotatePoints {
1392 24     24 0 35 my $parameters = shift;
1393 24         35 my $rotation = ${$parameters}{"rotation"};
  24         38  
1394 24         36 my $center = ${$parameters}{"center"};
  24         40  
1395 24 100       51 if (!defined($center)) {
1396 18         28 $center = ${$parameters}{"position"};
  18         26  
1397             }
1398 24 50       49 die unless defined($center);
1399 24 50       49 die unless defined($rotation);
1400 24         49 my $xc = ${$center}[0];
  24         42  
1401 24         33 my $yc = ${$center}[1];
  24         36  
1402 24         176 my $c = cos($rotation);
1403 24         45 my $s = sin($rotation);
1404 24         35 my @result;
1405              
1406 24         61 foreach my $point (@_) {
1407 75         93 my ($x, $y) = @{$point};
  75         139  
1408 75         98 $x -= $xc;
1409 75         93 $y -= $yc;
1410 75         152 ( $x, $y ) = ( $c * $x + $s * $y, -$s * $x + $c * $y );
1411 75         107 $x += $xc;
1412 75         88 $y += $yc;
1413 75         162 push(@result, [ $x, $y ]);
1414             }
1415 24         58 return @result;
1416             }
1417              
1418             #
1419             # Graphics::Fig::Parameters::scalePoints: scale about center
1420             # $parameters: parameter list (center, scale)
1421             # ( [ x, y ], ... )
1422             #
1423             sub scalePoints {
1424 8     8 0 15 my $parameters = shift;
1425 8         16 my $scale = ${$parameters}{"scale"};
  8         17  
1426 8         14 my $center = ${$parameters}{"center"};
  8         13  
1427 8 50       22 if (!defined($center)) {
1428 8         14 $center = ${$parameters}{"position"};
  8         18  
1429             }
1430 8 50       25 die unless defined($scale);
1431 8 50       21 die unless defined($center);
1432 8         14 my $xc = ${$center}[0];
  8         18  
1433 8         26 my $yc = ${$center}[1];
  8         1162  
1434 8         19 my $u = ${$scale}[0];
  8         27  
1435 8         13 my $v = ${$scale}[1];
  8         15  
1436 8         15 my @result;
1437              
1438 8         23 foreach my $point (@_) {
1439 31 50       69 die unless ref($point) eq "ARRAY";
1440 31         40 my ($x, $y) = @{$point};
  31         51  
1441 31         64 $x = $xc + ($x - $xc) * $u;
1442 31         39 $y = $yc + ($y - $yc) * $v;
1443 31         72 push(@result, [ $x, $y ]);
1444             }
1445 8         28 return @result;
1446             }
1447              
1448             #
1449             # Graphics::Fig::Parameters:getbboxFromPoints: find top-left bottom-right
1450             # from pts
1451             # @points
1452             #
1453             sub getbboxFromPoints {
1454 29     29 0 47 my ($x_min, $y_min, $x_max, $y_max);
1455              
1456 29         49 foreach my $point (@_) {
1457 100 100       168 if (!defined($x_min)) {
1458 29         42 $x_min = ${$point}[0];
  29         49  
1459 29         38 $y_min = ${$point}[1];
  29         42  
1460 29         43 $x_max = ${$point}[0];
  29         40  
1461 29         40 $y_max = ${$point}[1];
  29         43  
1462 29         47 next;
1463             }
1464 71 100       91 if (${$point}[0] < $x_min) {
  71         135  
1465 32         40 $x_min = ${$point}[0];
  32         45  
1466             }
1467 71 100       96 if (${$point}[1] < $y_min) {
  71         126  
1468 21         26 $y_min = ${$point}[1];
  21         31  
1469             }
1470 71 100       108 if (${$point}[0] > $x_max) {
  71         139  
1471 15         20 $x_max = ${$point}[0];
  15         24  
1472             }
1473 71 100       90 if (${$point}[1] > $y_max) {
  71         140  
1474 23         31 $y_max = ${$point}[1];
  23         40  
1475             }
1476             }
1477 29         100 return [ [ $x_min, $y_min ], [ $x_max, $y_max ] ];
1478             }
1479              
1480             #
1481             # Graphics::Fig::Parameters::copyArrowParameters: set fArrow, bArrow in object
1482             # $object: object to modify
1483             # $parameters: parameter list (center, scale)
1484             #
1485             sub copyArrowParameters {
1486 69     69 0 104 my $object = shift;
1487 69         95 my $parameters = shift;
1488              
1489 69         199 my @prefixes = ( "f", "b" );
1490 69         98 my $arrowMode = ${$parameters}{"arrowMode"};
  69         119  
1491 69         169 for (my $i = 0; $i < 2; ++$i) {
1492 138         243 my $prefix = $prefixes[$i];
1493 138         177 my $value = undef;
1494              
1495 138 100       297 if ($arrowMode & (1 << $i)) {
1496 45         70 my @R;
1497             my $temp;
1498 45 100       62 if (!defined($temp = ${$parameters}{"${prefix}ArrowStyle"})) {
  45         150  
1499 43         59 $temp = ${$parameters}{"arrowStyle"};
  43         78  
1500             }
1501 45         71 ( $R[0], $R[1] ) = @{$temp};
  45         139  
1502 45 100       66 if (!defined($temp = ${$parameters}{"${prefix}ArrowThickness"})) {
  45         127  
1503 44         62 $temp = ${$parameters}{"arrowThickness"};
  44         70  
1504             }
1505 45         86 $R[2] = $temp;
1506 45 100       68 if (!defined($temp = ${$parameters}{"${prefix}ArrowWidth"})) {
  45         121  
1507 44         62 $temp = ${$parameters}{"arrowWidth"};
  44         67  
1508             }
1509 45         72 $R[3] = $temp;
1510 45 100       57 if (!defined($temp = ${$parameters}{"${prefix}ArrowHeight"})) {
  45         137  
1511 44         55 $temp = ${$parameters}{"arrowHeight"};
  44         68  
1512             }
1513 45         80 $R[4] = $temp;
1514 45         88 $value = \@R;
1515             }
1516 138         176 ${$object}{"${prefix}Arrow"} = $value;
  138         361  
1517             }
1518 69         157 1;
1519             }
1520              
1521             #
1522             # Graphics::Fig::Parameters::compareArrowParameters: compare arrow parameters
1523             # $object: object to modify
1524             # $parameters: parameter list (center, scale)
1525             #
1526             sub compareArrowParameters {
1527 15     15 0 38 my $object = shift;
1528 15         20 my $parameters = shift;
1529 15         20 my $result;
1530              
1531 15         32 my @prefixes = ( "f", "b" );
1532 15         18 my $arrowMode = ${$parameters}{"arrowMode"};
  15         24  
1533 15         36 for (my $i = 0; $i < 2; ++$i) {
1534 30         45 my $prefix = $prefixes[$i];
1535 30         35 my $value;
1536              
1537 30 100       53 if ($arrowMode & (1 << $i)) {
    50          
1538 13 50       16 if (!defined($value = ${$object}{"${prefix}Arrow"})) {
  13         37  
1539 0         0 return -1;
1540             }
1541 13         18 my $temp;
1542 13 50       14 if (!defined($temp = ${$parameters}{"${prefix}arrowStyle"})) {
  13         27  
1543 13         18 $temp = ${$parameters}{"arrowStyle"};
  13         18  
1544             }
1545 13 50       15 if (($result = (${$value}[0] <=> ${$temp}[0])) != 0) {
  13         18  
  13         29  
1546 0         0 return $result;
1547             }
1548 13 50       15 if (($result = (${$value}[1] <=> ${$temp}[1])) != 0) {
  13         16  
  13         26  
1549 0         0 return $result;
1550             }
1551 13 50       16 if (!defined($temp = ${$parameters}{"${prefix}arrowThickness"})) {
  13         30  
1552 13         15 $temp = ${$parameters}{"arrowThickness"};
  13         20  
1553             }
1554 13 50       16 if (($result = (${$value}[2] <=> $temp)) != 0) {
  13         30  
1555 0         0 return $result;
1556             }
1557 13 50       17 if (!defined($temp = ${$parameters}{"${prefix}arrowWidth"})) {
  13         35  
1558 13         15 $temp = ${$parameters}{"arrowWidth"};
  13         18  
1559             }
1560 13 50       13 if (($result = (${$value}[3] <=> $temp)) != 0) {
  13         39  
1561 0         0 return $result;
1562             }
1563 13 50       17 if (!defined($temp = ${$parameters}{"${prefix}arrowHeight"})) {
  13         30  
1564 13         16 $temp = ${$parameters}{"arrowHeight"};
  13         18  
1565             }
1566 13 50       17 if (($result = (${$value}[4] <=> $temp)) != 0) {
  13         32  
1567 0         0 return $result;
1568             }
1569              
1570 17         51 } elsif (defined(${$object}{"${prefix}Arrow"})) {
1571 0         0 return +1;
1572             }
1573             }
1574 15         45 return 0;
1575             }
1576              
1577             #
1578             # Graphics::Fig::Parameters::printArrowParameters
1579             # $object: fig sub-object
1580             # $fh: reference to file handle
1581             # $parameters: save parameters
1582             #
1583             sub printArrowParameters {
1584 112     112 0 186 my $object = shift; # fArrow, bArrow
1585 112         159 my $fh = shift;
1586 112         147 my $parameters = shift;
1587              
1588 112         217 my $figPerInch = Graphics::Fig::_figPerInch($parameters);
1589 112         183 my ($fArrow, $bArrow);
1590 112 100       154 if (defined($fArrow = ${$object}{"fArrow"})) {
  112         302  
1591 42         70 my @A = @{$fArrow};
  42         112  
1592 42         336 printf $fh ("\t%d %d %.2f %.2f %.2f\n",
1593             $A[0], $A[1], $A[2] * 80.0,
1594             $A[3] * $figPerInch, $A[4] * $figPerInch);
1595             }
1596 112 100       167 if (defined($bArrow = ${$object}{"bArrow"})) {
  112         362  
1597 3         6 my @A = @{$bArrow};
  3         18  
1598 3         34 printf $fh ("\t%d %d %.2f %.2f %.2f\n",
1599             $A[0], $A[1], $A[2] * 80.0,
1600             $A[3] * $figPerInch, $A[4] * $figPerInch);
1601             }
1602             }
1603              
1604             1;