File Coverage

lib/Graphics/Fig/Text.pm
Criterion Covered Total %
statement 113 143 79.0
branch 7 18 38.8
condition 2 6 33.3
subroutine 14 15 93.3
pod 0 7 0.0
total 136 189 71.9


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::Text;
18             our $VERSION = 'v1.0.8';
19              
20 12     12   121 use strict;
  12         21  
  12         334  
21 12     12   48 use warnings;
  12         15  
  12         264  
22 12     12   64 use Carp;
  12         13  
  12         630  
23 12     12   66 use Math::Trig;
  12         19  
  12         1631  
24 12     12   68 use Image::Info qw(image_info);
  12         16  
  12         450  
25 12     12   65 use Graphics::Fig::Color;
  12         20  
  12         245  
26 12     12   54 use Graphics::Fig::Parameters;
  12         19  
  12         238  
27 12     12   6369 use Graphics::Fig::FontSize;
  12         42  
  12         12527  
28              
29              
30             #
31             # Text Parameters
32             #
33             my %TextParameterTemplate = (
34             positional => {
35             "." => [ "text" ],
36             },
37             named => [
38             \%Graphics::Fig::Parameters::UnitsParameter, # must be first
39             \%Graphics::Fig::Parameters::PositionParameter, # must be second
40             \%Graphics::Fig::Parameters::ColorParameter,
41             \%Graphics::Fig::Parameters::DepthParameter,
42             \%Graphics::Fig::Parameters::RotationParameter,
43             @Graphics::Fig::Parameters::TextParameters,
44             {
45             name => "text",
46             convert => \&Graphics::Fig::Parameters::convertText,
47             },
48             ],
49             );
50              
51             #
52             # Graphics::Fig::Text::calcSize: calculate dimensions of text
53             #
54             sub calcSize {
55 1     1 0 1 my $self = shift;
56             my $size = &Graphics::Fig::FontSize::getTextSize($self->{fontRef},
57 1         4 $self->{fontSize}, $self->{text});
58 1         3 my $justification = $self->{justification};
59              
60 1 50       5 if ($justification == 1) { # centered
    0          
61 1         3 my $width = $size->{right} - $size->{left};
62              
63 1         2 $size->{left} = -$width / 2.0;
64 1         2 $size->{right} = $width / 2.0;
65              
66             } elsif ($justification == 2) { # right-justified
67 0         0 my $width = $size->{right} - $size->{left};
68              
69 0         0 $size->{left} = -$width;
70 0         0 $size->{right} = 0.0;
71             }
72 1         2 $self->{size} = $size;
73             }
74              
75             #
76             # Graphics::Fig::Text::text constructor
77             # $proto: prototype
78             # $fig: parent object
79             # @parameters: spline parameters
80             #
81             sub text {
82 1     1 0 3 my $proto = shift;
83 1         1 my $fig = shift;
84 1         2 my $text;
85             my $rotation;
86              
87             #
88             # Parse parameters.
89             #
90 1         0 my %parameters;
91 1         1 my $stack = ${$fig}{"stack"};
  1         2  
92 1         2 my $tos = ${$stack}[$#{$stack}];
  1         2  
  1         1  
93 1         2 eval {
94             Graphics::Fig::Parameters::parse($fig, "text",
95             \%TextParameterTemplate,
96 1         2 ${$tos}{"options"}, \%parameters, @_);
  1         3  
97             };
98 1 50       3 if ($@) {
99 0         0 $@ =~ s/ at [^\s]* line \d+\.\n//;
100 0         0 croak("$@");
101             }
102              
103 1 50       4 if (!defined($text = $parameters{"text"})) {
104 0         0 croak("text: no text string given");
105             }
106 1 50       3 if (!defined($rotation = $parameters{"rotation"})) {
107 1         2 $rotation = 0;
108             }
109              
110             #
111             # Construct the object.
112             #
113             my $self = {
114             justification => $parameters{"textJustification"},
115             penColor => $parameters{"penColor"},
116             depth => $parameters{"depth"},
117             fontRef => $parameters{"fontName"},
118             fontSize => $parameters{"fontSize"},
119             fontFlags => $parameters{"fontName"}[0],
120             rotation => $rotation,
121             size => undef,
122 1         8 points => [ $parameters{"position"} ],
123             text => $text,
124             };
125 1   33     5 my $class = ref($proto) || $proto;
126 1         2 bless($self, $class);
127              
128             #
129             # Apply font flags and calculate the text size.
130             #
131 1         1 ${$self}{"fontFlags"} |= $parameters{"fontFlags"} & ~4;
  1         6  
132 1         4 $self->calcSize();
133              
134 1         1 push(@{${$tos}{"objects"}}, $self);
  1         2  
  1         2  
135 1         5 return $self;
136             }
137              
138             #
139             # Graphics::Fig::Text::translate
140             # $self: object
141             # $parameters: reference to parameter hash
142             #
143             sub translate {
144 1     1 0 2 my $self = shift;
145 1         2 my $parameters = shift;
146              
147 1         2 @{${$self}{"points"}} = Graphics::Fig::Parameters::translatePoints(
  1         3  
148 1         8 $parameters, @{${$self}{"points"}});
  1         1  
  1         5  
149              
150 1         2 return 1;
151             }
152              
153             #
154             # Graphics::Fig::Text::rotate
155             # $self: object
156             # $parameters: reference to parameter hash
157             #
158             sub rotate {
159 1     1 0 2 my $self = shift;
160 1         2 my $parameters = shift;
161 1         9 my $rotation = ${$parameters}{"rotation"};
  1         3  
162              
163 1         1 @{${$self}{"points"}} = Graphics::Fig::Parameters::rotatePoints(
  1         3  
164 1         2 $parameters, @{${$self}{"points"}});
  1         1  
  1         4  
165 1         1 ${$self}{"rotation"} += $rotation;
  1         3  
166              
167 1         2 return 1;
168             }
169              
170             #
171             # Graphics::Fig::Text::scale
172             # $self: object
173             # $parameters: reference to parameter hash
174             #
175             sub scale {
176 0     0 0 0 my $self = shift;
177 0         0 my $parameters = shift;
178 0         0 my $scale = ${$parameters}{"scale"};
  0         0  
179 0 0       0 die unless defined($scale);
180 0         0 my $u = ${$scale}[0];
  0         0  
181 0         0 my $v = ${$scale}[1];
  0         0  
182              
183 0         0 @{${$self}{"points"}} = Graphics::Fig::Parameters::scalePoints(
  0         0  
184 0         0 $parameters, @{${$self}{"points"}});
  0         0  
  0         0  
185 0         0 $self->{size}->{left} *= $u;
186 0         0 $self->{size}->{right} *= $u;
187 0         0 $self->{size}->{up} *= $v;
188 0         0 $self->{size}->{down} *= $v;
189              
190 0         0 return 1;
191             }
192              
193             #
194             # Graphics::Fig::Text::getbbox
195             # $self: object
196             # $parameters: getbbox parameters
197             #
198             # Return [[xmin, ymin], [xmax, ymax]]
199             #
200             sub getbbox {
201 3     3 0 4 my $self = shift;
202 3         3 my $parameters = shift;
203              
204 3         1 my $position = ${$self}{"points"}[0];
  3         7  
205 3         4 my $xmin = $position->[0] + $self->{size}->{left};
206 3         4 my $xmax = $position->[0] + $self->{size}->{right};
207 3         4 my $ymin = $position->[1] + $self->{size}->{up};
208 3         4 my $ymax = $position->[1] + $self->{size}->{down};
209              
210 3         7 return [ [ $xmin, $ymin ], [ $xmax, $ymax ] ];
211             }
212              
213             #
214             # Graphics::Fig::Text::print
215             # $self: object
216             # $fh: reference to output file handle
217             # $parameters: save parameters
218             #
219             sub print {
220 1     1 0 2 my $self = shift;
221 1         2 my $fh = shift;
222 1         1 my $parameters = shift;
223 1         1 my $text_in = ${$self}{"text"};
  1         2  
224 1         2 my $text_out = "";
225              
226             #
227             # Encode backslashes and bytes above 127 with backslash escapes.
228             #
229 1         4 for (my $i = 0; $i < length($text_in); ++$i) {
230 12         13 my $c = substr($text_in, $i, 1);
231 12         10 my $n = ord($c);
232 12 50 33     26 die if $n < 0 || $n > 255; # enforced in convertText
233 12 50       14 if ($n == 0x5C) { # '\'
234 0         0 $text_out .= '\\';
235 0         0 $text_out .= $c;
236 0         0 next;
237             }
238 12 50       14 if ($n > 127) {
239 0         0 $text_out .= sprintf("\\%03o", $n);
240 0         0 next;
241             }
242 12         16 $text_out .= $c;
243             }
244              
245             #
246             # Print
247             #
248 1         3 my $figPerInch = Graphics::Fig::_figPerInch($parameters);
249 1         4 my $width = $self->{size}{right} - $self->{size}{left};
250 1         3 my $height = $self->{size}{down} - $self->{size}{up};
251             printf $fh ("4 %d %d %d -1 %d %.0f %.4f %u %.0f %.0f %d %d %s\\001\n",
252 1         2 ${$self}{"justification"},
253 1         9 ${$self}{"penColor"},
254 1         2 ${$self}{"depth"},
255 1         2 ${$self}{"fontRef"}[1],
256 1         2 ${$self}{"fontSize"},
257 1         2 ${$self}{"rotation"},
258 1         2 ${$self}{"fontFlags"},
259             $height * $figPerInch,
260             $width * $figPerInch,
261 1         2 ${$self}{"points"}[0][0] * $figPerInch,
262 1         1 ${$self}{"points"}[0][1] * $figPerInch,
  1         10  
263             $text_out);
264             }
265              
266             1;