File Coverage

blib/lib/CAM/PDF/GS.pm
Criterion Covered Total %
statement 68 141 48.2
branch 3 10 30.0
condition 1 3 33.3
subroutine 12 23 52.1
pod 18 18 100.0
total 102 195 52.3


line stmt bran cond sub pod time code
1             package CAM::PDF::GS;
2              
3 1     1   33 use 5.006;
  1         4  
  1         49  
4 1     1   6 use strict;
  1         3  
  1         38  
5 1     1   7 use warnings;
  1         1  
  1         40  
6 1     1   6 use base qw(CAM::PDF::GS::NoText);
  1         3  
  1         1095  
7              
8             our $VERSION = '1.60';
9              
10             =for stopwords subclasses
11              
12             =head1 NAME
13              
14             CAM::PDF::GS - PDF graphic state
15              
16             =head1 LICENSE
17              
18             See CAM::PDF.
19              
20             =head1 SYNOPSIS
21              
22             use CAM::PDF;
23             my $pdf = CAM::PDF->new($filename);
24             my $contentTree = $pdf->getPageContentTree(4);
25             my $gs = $contentTree->computeGS();
26              
27             =head1 DESCRIPTION
28              
29             This class is used to represent the graphic state at a point in the
30             rendering flow of a PDF page. Much of the functionality is actually
31             based in the parent class, CAM::PDF::GS::NoText.
32              
33             Subclasses that want to do something useful with text should override
34             the renderText() method.
35              
36             =head1 CONVERSION FUNCTIONS
37              
38             =over
39              
40             =item $self->getCoords($node)
41              
42             Computes device coordinates for the specified node. This implementation
43             handles text-printing nodes, and hands all other types to the
44             superclass.
45              
46             =cut
47              
48             my %text_cmds = map {$_ => 1} qw(TJ Tj quote doublequote);
49              
50             sub getCoords
51             {
52 0     0 1 0 my $self = shift;
53 0         0 my $node = shift;
54              
55 0 0       0 if ($text_cmds{$node->{name}})
56             {
57             ## no critic (Bangs::ProhibitNumberedNames)
58 0         0 my ($x1,$y1) = $self->userToDevice(@{$self->{last}});
  0         0  
59 0         0 my ($x2,$y2) = $self->userToDevice(@{$self->{current}});
  0         0  
60 0         0 return ($x1,$y1,$x2,$y2);
61             }
62             else
63             {
64 0         0 return $self->SUPER::getCoords($node);
65             }
66             }
67              
68             =item $self->textToUser($x, $y)
69              
70             Convert text coordinates (C) to user coordinates. Returns the
71             converted X and Y.
72              
73             =cut
74              
75             sub textToUser
76             {
77 1590     1590 1 1929 my $self = shift;
78 1590         1946 my $x = shift;
79 1590         1918 my $y = shift;
80              
81 1590         5723 return $self->dot($self->{Tm}, $x, $y);
82              
83             =for oldcode
84             ## PDF Ref page 313
85             #my $tf = [$self->{Tfs}*$self->{Tz}, 0,
86             # 0, $self->{Tfs},
87             # 0, $self->{Ts}];
88             #return $self->dot($self->{Tm}, $self->dot($tf, $x, $y));
89              
90             =cut
91              
92             }
93              
94             =item $self->textToDevice($x, $y)
95              
96             Convert text coordinates (C) to device coordinates. Returns
97             the converted X and Y.
98              
99             =cut
100              
101             sub textToDevice
102             {
103 0     0 1 0 my $self = shift;
104 0         0 my $x = shift;
105 0         0 my $y = shift;
106              
107 0         0 return $self->userToDevice($self->textToUser($x, $y));
108             }
109              
110             =item $self->textLineToUser($x, $y)
111              
112             Convert text coordinates (C) to user coordinates. Returns
113             the converted X and Y.
114              
115             =cut
116              
117             sub textLineToUser
118             {
119 0     0 1 0 my $self = shift;
120 0         0 my $x = shift;
121 0         0 my $y = shift;
122              
123 0         0 return $self->dot($self->{Tlm}, $x, $y);
124             }
125              
126             =item $self->textLineToDevice($x, $y)
127              
128             Convert text coordinates (C) to device coordinates.
129             Returns the converted X and Y.
130              
131             =cut
132              
133             sub textLineToDevice
134             {
135 0     0 1 0 my $self = shift;
136 0         0 my $x = shift;
137 0         0 my $y = shift;
138              
139 0         0 return $self->userToDevice($self->textLineToUser($x, $y));
140             }
141              
142             =item $self->renderText($string, $width)
143              
144             A general method for rendering strings, from C or C. This is a
145             no-op, but subclasses may override.
146              
147             =cut
148              
149             sub renderText
150             {
151 795     795 1 1141 my $self = shift;
152 795         1536 my $string = shift;
153 795         1110 my $width = shift;
154              
155             # noop, override in subclasses
156 795         1317 return;
157             }
158              
159             =item $self->Tadvance($width)
160              
161             Move the text cursor.
162              
163             =cut
164              
165             sub Tadvance
166             {
167 795     795 1 891 my $self = shift;
168 795         1093 my $width = shift;
169              
170 795         1045 my $tx = 0;
171 795         968 my $ty = 0;
172 795 50       1942 if ($self->{wm} == 0)
173             {
174 795         2599 $tx = ($width * $self->{Tfs} + $self->{Tc} + $self->{Tw}) * $self->{Tz};
175             }
176             else
177             {
178 0         0 $ty = $width * $self->{Tfs} + $self->{Tc} + $self->{Tw};
179             }
180 795         1629 $self->{moved}->[0] += $tx;
181 795         1224 $self->{moved}->[1] += $ty;
182              
183 795         4517 $self->applyMatrix([1,0,0,1,$tx,$ty], $self->{Tm});
184 795         3340 return;
185             }
186              
187             =back
188              
189             =head1 DATA FUNCTIONS
190              
191             =over
192              
193             =item $self->BT()
194              
195             =cut
196              
197             sub BT
198             {
199 164     164 1 482 my $self = shift;
200              
201 164         407 @{$self->{Tm}} = (1, 0, 0, 1, 0, 0);
  164         630  
202 164         372 @{$self->{Tlm}} = (1, 0, 0, 1, 0, 0);
  164         532  
203 164         476 return;
204             }
205              
206             =item $self->Tf($fontname, $fontsize)
207              
208             =cut
209              
210             sub Tf
211             {
212 164     164 1 366 my $self = shift;
213 164         384 my $fontname = shift;
214 164         301 my $fontsize = shift;
215              
216 164         414 $self->{Tf} = $fontname;
217 164         371 $self->{Tfs} = $fontsize;
218 164         1236 $self->{refs}->{fm} = $self->{refs}->{doc}->getFontMetrics($self->{refs}->{properties}, $fontname);
219              
220             # TODO: support vertical text mode (wm = 1)
221 164         318 $self->{wm} = 0;
222 164         512 return;
223             }
224              
225             =item $self->Tstar()
226              
227             =cut
228              
229             sub Tstar
230             {
231 0     0 1 0 my $self = shift;
232              
233 0         0 $self->Td(0, -$self->{TL});
234 0         0 return;
235             }
236              
237             =item $self->Tz($scale)
238              
239             =cut
240              
241             sub Tz
242             {
243 0     0 1 0 my $self = shift;
244 0         0 my $scale = shift;
245              
246 0         0 $self->{Tz} = $scale/100.0;
247 0         0 return;
248             }
249              
250             =item $self->Td($x, $y)
251              
252             =cut
253              
254             sub Td
255             {
256 0     0 1 0 my $self = shift;
257 0         0 my $x = shift;
258 0         0 my $y = shift;
259              
260 0         0 $self->applyMatrix([1,0,0,1,$x,$y], $self->{Tlm});
261 0         0 @{$self->{Tm}} = @{$self->{Tlm}};
  0         0  
  0         0  
262 0         0 return;
263             }
264              
265             =item $self->TD($x, $y)
266              
267             =cut
268              
269             sub TD
270             {
271 0     0 1 0 my $self = shift;
272 0         0 my $x = shift;
273 0         0 my $y = shift;
274              
275 0         0 $self->TL(-$y);
276 0         0 $self->Td($x,$y);
277 0         0 return;
278             }
279              
280             =item $self->Tj($string)
281              
282             =cut
283              
284             sub Tj
285             {
286 795     795 1 1254 my $self = shift;
287 795         1159 my $string = shift;
288              
289 795         2280 @{$self->{last}} = $self->textToUser(0,0);
  795         2668  
290 795         2372 $self->_Tj($string);
291 795         2045 @{$self->{current}} = $self->textToUser(0,0);
  795         2309  
292 795         2272 return;
293             }
294              
295             sub _Tj
296             {
297 795     795   1005 my $self = shift;
298 795         1244 my $string = shift;
299              
300 795 50       15707 if (!$self->{refs}->{fm})
301             {
302 0         0 die "No font metrics for font $self->{Tf}";
303             }
304              
305 795         1155 my @parts;
306 795 50 33     4720 if ($self->{mode} eq 'c' || $self->{wm} == 1)
307             {
308 0         0 @parts = split m//xms, $string;
309             }
310             else
311             {
312 795         1722 @parts = ($string);
313             }
314 795         1419 foreach my $substr (@parts)
315             {
316 795         4464 my $dw = $self->{refs}->{doc}->getStringWidth($self->{refs}->{fm}, $substr);
317 795         2316 $self->renderText($substr, $dw);
318 795         1852 $self->Tadvance($dw);
319             }
320 795         1762 return;
321             }
322              
323             =item $self->TJ($arrayref)
324              
325             =cut
326              
327             sub TJ
328             {
329 0     0 1 0 my $self = shift;
330 0         0 my $array = shift;
331              
332 0         0 @{$self->{last}} = $self->textToUser(0,0);
  0         0  
333 0         0 foreach my $node (@{$array})
  0         0  
334             {
335 0 0       0 if ($node->{type} eq 'number')
336             {
337 0         0 my $dw = -$node->{value} / 1000.0;
338 0         0 $self->Tadvance($dw);
339             }
340             else
341             {
342 0         0 $self->_Tj($node->{value});
343             }
344             }
345 0         0 @{$self->{current}} = $self->textToUser(0,0);
  0         0  
346 0         0 return;
347             }
348              
349             =item $self->quote($string)
350              
351             =cut
352              
353             sub quote
354             {
355 0     0 1 0 my $self = shift;
356 0         0 my $string = shift;
357              
358 0         0 @{$self->{last}} = $self->textToUser(0,0);
  0         0  
359 0         0 $self->Tstar();
360 0         0 $self->_Tj($string);
361 0         0 @{$self->{current}} = $self->textToUser(0,0);
  0         0  
362 0         0 return;
363             }
364              
365             =item $self->doublequote($tw, $tc, $string)
366              
367             =cut
368              
369             sub doublequote
370             {
371 0     0 1 0 my $self = shift;
372 0         0 $self->{Tw} = shift;
373 0         0 $self->{Tc} = shift;
374 0         0 my $string = shift;
375              
376 0         0 $self->quote($string);
377 0         0 return;
378             }
379              
380             =item $self->Tm($m1, $m2, $m3, $m4, $m5, $m6)
381              
382             =cut
383              
384             sub Tm
385             {
386 795     795 1 2907 my ($self, @tm) = @_;
387              
388 795         1390 @{$self->{Tm}} = @{$self->{Tlm}} = @tm;
  795         4387  
  795         3999  
389 795         3457 return;
390             }
391              
392             1;
393             __END__