File Coverage

blib/lib/CAM/PDF/GS/NoText.pm
Criterion Covered Total %
statement 112 198 56.5
branch 2 14 14.2
condition 2 5 40.0
subroutine 18 30 60.0
pod 23 23 100.0
total 157 270 58.1


line stmt bran cond sub pod time code
1             package CAM::PDF::GS::NoText;
2              
3 1     1   23 use 5.006;
  1         4  
  1         60  
4 1     1   7 use warnings;
  1         2  
  1         30  
5 1     1   7 use strict;
  1         2  
  1         38  
6 1     1   7 use Carp;
  1         2  
  1         81  
7 1     1   7 use English qw(-no_match_vars);
  1         2  
  1         9  
8              
9             our $VERSION = '1.60';
10              
11             ##no critic (Bangs::ProhibitNumberedNames)
12              
13             =for stopwords fallback
14              
15             =head1 NAME
16              
17             CAM::PDF::GS::NoText - PDF graphic state
18              
19             =head1 LICENSE
20              
21             See CAM::PDF.
22              
23             =head1 SYNOPSIS
24              
25             use CAM::PDF;
26             my $pdf = CAM::PDF->new($filename);
27             my $contentTree = $pdf->getPageContentTree(4);
28             my $gs = $contentTree->computeGS(1);
29              
30             =head1 DESCRIPTION
31              
32             This class is used to represent the graphic state at a point in the
33             rendering flow of a PDF page. This does not include the graphics
34             state for text blocks. That functionality is in the subclass,
35             CAM::PDF::GS.
36              
37             =head1 FUNCTIONS
38              
39             =over
40              
41             =item $pkg->new($hashref)
42              
43             Create a new instance, setting all state values to their defaults.
44             Stores a reference to C<$hashref> and sets the property
45             C<$hashref->{fm}> to C.
46              
47             =cut
48              
49             sub new
50             {
51 6     6 1 15 my $pkg = shift;
52 6         14 my $refs = shift;
53              
54 6   50     274 my $self = bless {
55              
56             mode => 'n', # 'c'har, 's'tring, 'n'oop
57              
58             refs => $refs || {},
59              
60             c => undef, # color
61             cm => [1, 0, 0, 1, 0, 0], # current transformation matrix
62             w => 1.0, # line width
63             J => 0, # line cap
64             j => 0, # line join
65             M => 0, # miter limit
66             da => [], # dash pattern array
67             dp => 0, # dash phase
68             ri => undef, # rendering intent
69             i => 0, # flatness
70              
71             # Others, see PDF Ref page 149
72              
73             Tm => [1, 0, 0, 1, 0, 0], # text matrix
74             Tlm => [1, 0, 0, 1, 0, 0], # text matrix
75             Tc => 0, # character spacing
76             Tw => 0, # word spacing
77             Tz => 1, # horizontal scaling
78             TL => 0, # leading
79             Tf => undef, # font
80             Tfs => undef, # font size
81             Tr => 0, # render mode
82             Ts => 0, # rise
83             wm => 0, # writing mode (0=horiz, 1=vert)
84              
85             Device => undef,
86             device => undef,
87             G => undef,
88             g => undef,
89             RG => undef,
90             rg => undef,
91             K => undef,
92             k => undef,
93              
94             moved => [0,0],
95              
96             start => [0,0],
97             last => [0,0],
98             current => [0,0],
99              
100             }, $pkg;
101              
102 6         34 $self->{refs}->{fm} = undef;
103              
104 6         23 return $self;
105             }
106              
107             =item $self->clone()
108              
109             Duplicate the instance.
110              
111             =cut
112              
113             sub clone
114             {
115 2646     2646 1 3496 my $self = shift;
116              
117 2646         14034 require Data::Dumper;
118 2646         3179 my $newself;
119              
120             # don't clone references, just point to them
121 2646         4900 my $refs = delete $self->{refs};
122              
123 2646 50       12834 if (!eval Data::Dumper->Dump([$self], ['newself'])) ## no critic (StringyEval)
124             {
125 0         0 die 'Error in '.__PACKAGE__."::clone() - $EVAL_ERROR";
126             }
127 2646         94019 $self->{refs} = $newself->{refs} = $refs; # restore references
128 2646         3911 @{$newself->{moved}} = (0,0);
  2646         7609  
129 2646         9242 return $newself;
130             }
131              
132             =back
133              
134             =head1 CONVERSION FUNCTIONS
135              
136             =over
137              
138             =item $self->applyMatrix($m1, $m2)
139              
140             Apply C<$m1> to C<$m2>, save in C<$m2>.
141              
142             =cut
143              
144             sub applyMatrix
145             {
146 976     976 1 1395 my $self = shift;
147 976         1120 my $m1 = shift;
148 976         1184 my $m2 = shift;
149              
150 976 50 33     5611 if (ref $m1 ne 'ARRAY' || ref $m2 ne 'ARRAY')
151             {
152 0         0 require Data::Dumper;
153 0         0 croak "Bad arrays:\n".Dumper($m1,$m2);
154             }
155              
156 976         1122 my @m3;
157              
158 976         3061 $m3[0] = $m2->[0]*$m1->[0] + $m2->[2]*$m1->[1];
159 976         2018 $m3[1] = $m2->[1]*$m1->[0] + $m2->[3]*$m1->[1];
160 976         2144 $m3[2] = $m2->[0]*$m1->[2] + $m2->[2]*$m1->[3];
161 976         2044 $m3[3] = $m2->[1]*$m1->[2] + $m2->[3]*$m1->[3];
162 976         2900 $m3[4] = $m2->[0]*$m1->[4] + $m2->[2]*$m1->[5] + $m2->[4];
163 976         2392 $m3[5] = $m2->[1]*$m1->[4] + $m2->[3]*$m1->[5] + $m2->[5];
164              
165 976         1366 @{$m2} = @m3;
  976         4254  
166 976         3259 return;
167             }
168              
169             =item $self->dot($matrix, $x, $y)
170              
171             Compute the dot product of a position against the coordinate matrix.
172              
173             =cut
174              
175             sub dot
176             {
177 1590     1590 1 2009 my $self = shift;
178 1590         1930 my $cm = shift;
179 1590         2015 my $x = shift;
180 1590         1866 my $y = shift;
181              
182 1590         9016 return ($cm->[0]*$x + $cm->[2]*$y + $cm->[4],
183             $cm->[1]*$x + $cm->[3]*$y + $cm->[5]);
184             }
185              
186             =item $self->userToDevice($x, $y)
187              
188             Convert user coordinates to device coordinates.
189              
190             =cut
191              
192             sub userToDevice
193             {
194 0     0 1 0 my $self = shift;
195 0         0 my $x = shift;
196 0         0 my $y = shift;
197              
198 0         0 ($x,$y) = $self->dot($self->{cm}, $x, $y);
199 0         0 $x -= $self->{refs}->{mediabox}->[0];
200 0         0 $y -= $self->{refs}->{mediabox}->[1];
201 0         0 return ($x, $y);
202             }
203              
204             =item $self->getCoords($node)
205              
206             Computes device coordinates for the specified node. This implementation
207             handles line-drawing nodes.
208              
209             =cut
210              
211             my %path_cmds = map {$_ => 1} qw(m l h c v y re);
212             my %paint_cmds = map {$_ => 1} qw(S s F f f* B B* b b* n);
213              
214             sub getCoords
215             {
216 0     0 1 0 my $self = shift;
217 0         0 my $node = shift;
218              
219 0         0 my ($x1,$y1,$x2,$y2);
220 0 0       0 if ($path_cmds{$node->{name}})
221             {
222 0         0 ($x1,$y1) = $self->userToDevice(@{$self->{last}});
  0         0  
223 0         0 ($x2,$y2) = $self->userToDevice(@{$self->{current}});
  0         0  
224             }
225 0         0 return ($x1,$y1,$x2,$y2);
226             }
227              
228             =item $self->nodeType($node)
229              
230             Returns one of C, C, C, C or (the fallback
231             case) C for the type of the specified node.
232              
233             =cut
234              
235             sub nodeType
236             {
237 0     0 1 0 my $self = shift;
238 0         0 my $node = shift;
239              
240 0 0       0 return $node->{type} eq 'block' ? 'block'
    0          
    0          
    0          
241             : $path_cmds{$node->{name}} ? 'path'
242             : $paint_cmds{$node->{name}} ? 'paint'
243             : $node->{name} =~ / \A T /xms ? 'text'
244             : 'op';
245             }
246              
247             =back
248              
249             =head1 DATA FUNCTIONS
250              
251             =over
252              
253             =item $self->i($flatness)
254              
255             =item $self->j($linejoin)
256              
257             =item $self->J($linecap)
258              
259             =item $self->ri($rendering_intent)
260              
261             =item $self->Tc($charspace)
262              
263             =item $self->TL($leading)
264              
265             =item $self->Tr($rendering_mode)
266              
267             =item $self->Ts($rise)
268              
269             =item $self->Tw($wordspace)
270              
271             =item $self->w($linewidth)
272              
273             =cut
274              
275             # default setters
276             {
277 1     1   2272 no strict 'refs'; ## no critic(ProhibitNoStrict)
  1         3  
  1         1525  
278             foreach my $name (qw(i j J ri Tc TL Tr Ts Tw w))
279             {
280 16     16   45 *{$name} = sub { $_[0]->{$name} = $_[1]; return; };
  16         45  
281             }
282             }
283              
284             =item $self->g($gray)
285              
286             =cut
287              
288             sub g
289             {
290 0     0 1 0 my $self = shift;
291 0         0 my $g = shift;
292              
293 0         0 $self->{g} = [$g];
294 0         0 $self->{device} = 'DeviceGray';
295 0         0 return;
296             }
297              
298             =item $self->G($gray)
299              
300             =cut
301              
302             sub G
303             {
304 0     0 1 0 my $self = shift;
305 0         0 my $g = shift;
306              
307 0         0 $self->{G} = [$g];
308 0         0 $self->{Device} = 'DeviceGray';
309 0         0 return;
310             }
311              
312             =item $self->rg($red, $green, $blue)
313              
314             =cut
315              
316             sub rg
317             {
318 0     0 1 0 my $self = shift;
319 0         0 my $rd = shift;
320 0         0 my $gr = shift;
321 0         0 my $bl = shift;
322              
323 0         0 $self->{rg} = [$rd, $gr, $bl];
324 0         0 $self->{device} = 'DeviceRGB';
325 0         0 return;
326             }
327              
328             =item $self->RG($red, $green, $blue)
329              
330             =cut
331              
332             sub RG
333             {
334 0     0 1 0 my $self = shift;
335 0         0 my $rd = shift;
336 0         0 my $gr = shift;
337 0         0 my $bl = shift;
338              
339 0         0 $self->{RG} = [$rd, $gr, $bl];
340 0         0 $self->{Device} = 'DeviceRGB';
341 0         0 return;
342             }
343              
344             =item $self->k($cyan, $magenta, $yellow, $black)
345              
346             =cut
347              
348             sub k
349             {
350 0     0 1 0 my $self = shift;
351 0         0 my $c = shift;
352 0         0 my $m = shift;
353 0         0 my $y = shift;
354 0         0 my $k = shift;
355              
356 0         0 $self->{k} = [$c, $m, $y, $k];
357 0         0 $self->{device} = 'DeviceCMYK';
358 0         0 return;
359             }
360              
361             =item $self->K($cyan, $magenta, $yellow, $black)
362              
363             =cut
364              
365             sub K
366             {
367 0     0 1 0 my $self = shift;
368 0         0 my $c = shift;
369 0         0 my $m = shift;
370 0         0 my $y = shift;
371 0         0 my $k = shift;
372              
373 0         0 $self->{K} = [$c, $m, $y, $k];
374 0         0 $self->{Device} = 'DeviceCMYK';
375 0         0 return;
376             }
377              
378             =item $self->gs()
379              
380             (Not implemented...)
381              
382             =cut
383              
384             sub gs
385             {
386 0     0 1 0 my $self = shift;
387              
388             # See PDF Ref page 157
389             #warn 'gs operator not yet implemented';
390 0         0 return;
391             }
392              
393             =item $self->cm M1, M2, M3, M4, M5, M6
394              
395             =cut
396              
397             sub cm
398             {
399 181     181 1 732 my ($self, @mtx) = @_;
400              
401 181         1000 $self->applyMatrix([@mtx], $self->{cm});
402 181         779 return;
403             }
404              
405             =item $self->d($arrayref, $scalar)
406              
407             =cut
408              
409             sub d
410             {
411 2     2 1 7 my $self = shift;
412 2         5 my $da = shift;
413 2         5 my $dp = shift;
414              
415 2         7 @{$self->{da}} = @{$da};
  2         7  
  2         5  
416 2         7 $self->{dp} = $dp;
417 2         7 return;
418             }
419              
420             =item $self->m($x, $y)
421              
422             Move path.
423              
424             =cut
425              
426             sub m ##no critic (Homonym)
427             {
428 75     75 1 139 my $self = shift;
429 75         121 my $x = shift;
430 75         115 my $y = shift;
431              
432 75         128 @{$self->{start}} = @{$self->{last}} = @{$self->{current}} = ($x,$y);
  75         218  
  75         269  
  75         295  
433 75         244 return;
434             }
435              
436             =item $self->l($x, $y)
437              
438             Line path.
439              
440             =cut
441              
442             sub l
443             {
444 232     232 1 360 my $self = shift;
445 232         348 my $x = shift;
446 232         298 my $y = shift;
447              
448 232         323 @{$self->{last}} = @{$self->{current}};
  232         668  
  232         412  
449 232         374 @{$self->{current}} = ($x,$y);
  232         690  
450 232         632 return;
451             }
452              
453             =item $self->h()
454              
455             =cut
456              
457             sub h
458             {
459 73     73 1 129 my $self = shift;
460              
461 73         128 @{$self->{last}} = @{$self->{current}};
  73         240  
  73         178  
462 73         162 @{$self->{current}} = @{$self->{start}};
  73         187  
  73         157  
463 73         210 return;
464             }
465              
466             =item $self->c($x1, $y1, $x2, $y2, $x3, $y3)
467              
468             =cut
469              
470             sub c ## no critic (ProhibitManyArgs)
471             {
472 5     5 1 11 my $self = shift;
473 5         7 my $x1 = shift;
474 5         8 my $y1 = shift;
475 5         8 my $x2 = shift;
476 5         7 my $y2 = shift;
477 5         7 my $x3 = shift;
478 5         5 my $y3 = shift;
479              
480 5         7 @{$self->{last}} = @{$self->{current}};
  5         17  
  5         10  
481 5         8 @{$self->{current}} = ($x3,$y3);
  5         14  
482 5         16 return;
483             }
484              
485             =item $self->v($x1, $y1, $x2, $y2)
486              
487             =cut
488              
489             sub v
490             {
491 0     0 1 0 my $self = shift;
492 0         0 my $x1 = shift;
493 0         0 my $y1 = shift;
494 0         0 my $x2 = shift;
495 0         0 my $y2 = shift;
496              
497 0         0 @{$self->{last}} = @{$self->{current}};
  0         0  
  0         0  
498 0         0 @{$self->{current}} = ($x2,$y2);
  0         0  
499 0         0 return;
500             }
501              
502             =item $self->y($x1, $y1, $x2, $y2)
503              
504             =cut
505              
506             sub y ##no critic (Homonym)
507             {
508 0     0 1 0 my $self = shift;
509 0         0 my $x1 = shift;
510 0         0 my $y1 = shift;
511 0         0 my $x2 = shift;
512 0         0 my $y2 = shift;
513              
514 0         0 @{$self->{last}} = @{$self->{current}};
  0         0  
  0         0  
515 0         0 @{$self->{current}} = ($x2,$y2);
  0         0  
516 0         0 return;
517             }
518              
519             =item $self->re($x, $y, $width, $height)
520              
521             Rectangle path.
522              
523             =cut
524              
525             sub re
526             {
527 144     144 1 270 my $self = shift;
528 144         238 my $x = shift;
529 144         282 my $y = shift;
530 144         237 my $w = shift;
531 144         218 my $h = shift;
532              
533 144         269 @{$self->{start}} = @{$self->{last}} = @{$self->{current}} = ($x,$y);
  144         425  
  144         497  
  144         588  
534 144         503 return;
535             }
536              
537             1;
538             __END__