File Coverage

blib/lib/PDF/API2/Resource/UniFont.pm
Criterion Covered Total %
statement 77 97 79.3
branch 20 38 52.6
condition 6 12 50.0
subroutine 9 9 100.0
pod 0 5 0.0
total 112 161 69.5


line stmt bran cond sub pod time code
1             package PDF::API2::Resource::UniFont;
2              
3 2     2   2269 use strict;
  2         4  
  2         70  
4 2     2   11 use warnings;
  2         4  
  2         111  
5              
6             our $VERSION = '2.043'; # VERSION
7              
8 2     2   16 use Carp;
  2         5  
  2         168  
9 2     2   14 use Encode qw(:all);
  2         14  
  2         2838  
10              
11             sub new {
12 1     1 0 3 my $class = shift();
13 1 50       4 $class = ref($class) if ref($class);
14 1         4 my $self = {
15             fonts => [],
16             block => {},
17             code => {},
18             pdf => shift(),
19             };
20 1         2 bless $self, $class;
21              
22 1         3 my @fonts;
23 1         6 push @fonts, shift() while ref($_[0]);
24              
25 1         4 my %options = @_;
26 1 50       8 $self->{'encode'} = $options{'-encode'} if defined $options{'-encode'};
27              
28 1         2 my $font_number = 0;
29 1         2 foreach my $font (@fonts) {
30 2 100       12 if (ref($font) eq 'ARRAY') {
    50          
31 1         2 push @{$self->{'fonts'}}, shift(@$font);
  1         27  
32              
33 1         5 while (defined $font->[0]) {
34 1         5 my $blockspec = shift @$font;
35 1 50       3 if (ref($blockspec)) {
36 1         3 foreach my $block ($blockspec->[0] .. $blockspec->[-1]) {
37 1         5 $self->{'block'}->{$block} = $font_number;
38             }
39             }
40             else {
41 0         0 $self->{'block'}->{$blockspec} = $font_number;
42             }
43             }
44             }
45             elsif (ref($font) eq 'HASH') {
46 0         0 push @{$self->{'fonts'}}, $font->{'font'};
  0         0  
47              
48 0 0 0     0 if (defined($font->{'blocks'}) and ref($font->{'blocks'}) eq 'ARRAY') {
49 0         0 foreach my $blockspec (@{$font->{'blocks'}}) {
  0         0  
50 0 0       0 if (ref($blockspec)) {
51 0         0 foreach my $block ($blockspec->[0] .. $blockspec->[-1]) {
52 0         0 $self->{'block'}->{$block} = $font_number;
53             }
54             }
55             else {
56 0         0 $self->{'block'}->{$blockspec} = $font_number;
57             }
58             }
59             }
60              
61 0 0 0     0 if (defined($font->{'codes'}) and ref($font->{'codes'}) eq 'ARRAY') {
62 0         0 foreach my $codespec (@{$font->{'codes'}}) {
  0         0  
63 0 0       0 if (ref($codespec)) {
64 0         0 foreach my $code ($codespec->[0] .. $codespec->[-1]) {
65 0         0 $self->{'code'}->{$code} = $font_number;
66             }
67             }
68             else {
69 0         0 $self->{'code'}->{$codespec} = $font_number;
70             }
71             }
72             }
73             }
74             else {
75 1         2 push @{$self->{'fonts'}}, $font;
  1         3  
76 1         3 foreach my $block (0 .. 255) {
77 256         402 $self->{'block'}->{$block} = $font_number;
78             }
79             }
80 2         4 $font_number++;
81             }
82              
83 1         6 return $self;
84             }
85              
86 2     2 0 8 sub isvirtual { return 1; }
87              
88             sub fontlist {
89 11     11 0 22 my $self = shift();
90 11         26 return [@{$self->{'fonts'}}];
  11         78  
91             }
92              
93             sub width {
94 4     4 0 14 my ($self, $text) = @_;
95 4 100       35 $text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
96 4         322 my $width = 0;
97              
98 4         12 my @blocks = ();
99 4         25 foreach my $u (unpack('U*', $text)) {
100 18         39 my $font_number = 0;
101 18 50       83 if (defined $self->{'code'}->{$u}) {
    50          
102 0         0 $font_number = $self->{'code'}->{$u};
103             }
104             elsif (defined $self->{'block'}->{$u >> 8}) {
105 18         45 $font_number = $self->{'block'}->{$u >> 8};
106             }
107             else {
108 0         0 $font_number = 0;
109             }
110              
111 18 100 100     80 if (scalar @blocks == 0 or $blocks[-1]->[0] != $font_number) {
112 6         42 push @blocks, [$font_number, pack('U', $u)];
113             }
114             else {
115 12         39 $blocks[-1]->[1] .= pack('U', $u);
116             }
117             }
118              
119 4         13 foreach my $block (@blocks) {
120 6         19 my ($font_number, $string) = @$block;
121 6         23 $width += $self->fontlist->[$font_number]->width($string);
122             }
123              
124 4         20 return $width;
125             }
126              
127             sub text {
128 2     2 0 9 my ($self, $text, $size, $indent) = @_;
129 2 100       12 $text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
130 2 50       64 croak 'Font size not specified' unless defined $size;
131              
132 2         7 my $value = '';
133 2         7 my $last_font_number;
134             my @codes;
135              
136 2         11 foreach my $u (unpack('U*', $text)) {
137 9         19 my $font_number = 0;
138 9 50       41 if (defined $self->{'code'}->{$u}) {
    50          
139 0         0 $font_number = $self->{'code'}->{$u};
140             }
141             elsif (defined $self->{'block'}->{$u >> 8}) {
142 9         25 $font_number = $self->{'block'}->{$u >> 8};
143             }
144              
145 9 100 100     48 if (defined $last_font_number and $font_number != $last_font_number) {
146 1         10 my $font = $self->fontlist->[$last_font_number];
147 1         23 $value .= '/' . $font->name() . ' ' . $size . ' Tf ';
148 1         20 $value .= $font->text(pack('U*', @codes), $size, $indent) . ' ';
149 1         5 $indent = undef;
150 1         8 @codes = ();
151             }
152              
153 9         32 push @codes, $u;
154 9         23 $last_font_number = $font_number;
155             }
156              
157 2 50       11 if (scalar @codes > 0) {
158 2         10 my $font = $self->fontlist->[$last_font_number];
159 2         13 $value .= '/' . $font->name() . ' ' . $size . ' Tf ';
160 2         19 $value .= $font->text(pack('U*', @codes), $size, $indent);
161             }
162              
163 2         26 return $value;
164             }
165              
166             1;