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   1983 use strict;
  2         4  
  2         72  
4 2     2   11 use warnings;
  2         5  
  2         123  
5              
6             our $VERSION = '2.044'; # VERSION
7              
8 2     2   15 use Carp;
  2         6  
  2         170  
9 2     2   15 use Encode qw(:all);
  2         4  
  2         2702  
10              
11             sub new {
12 1     1 0 2 my $class = shift();
13 1 50       4 $class = ref($class) if ref($class);
14 1         5 my $self = {
15             fonts => [],
16             block => {},
17             code => {},
18             pdf => shift(),
19             };
20 1         3 bless $self, $class;
21              
22 1         2 my @fonts;
23 1         8 push @fonts, shift() while ref($_[0]);
24              
25 1         6 my %options = @_;
26 1 50       11 $self->{'encode'} = $options{'-encode'} if defined $options{'-encode'};
27              
28 1         3 my $font_number = 0;
29 1         2 foreach my $font (@fonts) {
30 2 100       15 if (ref($font) eq 'ARRAY') {
    50          
31 1         2 push @{$self->{'fonts'}}, shift(@$font);
  1         3  
32              
33 1         7 while (defined $font->[0]) {
34 1         5 my $blockspec = shift @$font;
35 1 50       4 if (ref($blockspec)) {
36 1         3 foreach my $block ($blockspec->[0] .. $blockspec->[-1]) {
37 1         7 $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         6  
76 1         4 foreach my $block (0 .. 255) {
77 256         450 $self->{'block'}->{$block} = $font_number;
78             }
79             }
80 2         5 $font_number++;
81             }
82              
83 1         4 return $self;
84             }
85              
86 2     2 0 7 sub isvirtual { return 1; }
87              
88             sub fontlist {
89 11     11 0 20 my $self = shift();
90 11         16 return [@{$self->{'fonts'}}];
  11         66  
91             }
92              
93             sub width {
94 4     4 0 15 my ($self, $text) = @_;
95 4 100       19 $text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
96 4         279 my $width = 0;
97              
98 4         7 my @blocks = ();
99 4         15 foreach my $u (unpack('U*', $text)) {
100 18         26 my $font_number = 0;
101 18 50       54 if (defined $self->{'code'}->{$u}) {
    50          
102 0         0 $font_number = $self->{'code'}->{$u};
103             }
104             elsif (defined $self->{'block'}->{$u >> 8}) {
105 18         26 $font_number = $self->{'block'}->{$u >> 8};
106             }
107             else {
108 0         0 $font_number = 0;
109             }
110              
111 18 100 100     56 if (scalar @blocks == 0 or $blocks[-1]->[0] != $font_number) {
112 6         23 push @blocks, [$font_number, pack('U', $u)];
113             }
114             else {
115 12         26 $blocks[-1]->[1] .= pack('U', $u);
116             }
117             }
118              
119 4         9 foreach my $block (@blocks) {
120 6         13 my ($font_number, $string) = @$block;
121 6         12 $width += $self->fontlist->[$font_number]->width($string);
122             }
123              
124 4         15 return $width;
125             }
126              
127             sub text {
128 2     2 0 5 my ($self, $text, $size, $indent) = @_;
129 2 100       8 $text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
130 2 50       53 croak 'Font size not specified' unless defined $size;
131              
132 2         3 my $value = '';
133 2         4 my $last_font_number;
134             my @codes;
135              
136 2         6 foreach my $u (unpack('U*', $text)) {
137 9         15 my $font_number = 0;
138 9 50       26 if (defined $self->{'code'}->{$u}) {
    50          
139 0         0 $font_number = $self->{'code'}->{$u};
140             }
141             elsif (defined $self->{'block'}->{$u >> 8}) {
142 9         15 $font_number = $self->{'block'}->{$u >> 8};
143             }
144              
145 9 100 100     26 if (defined $last_font_number and $font_number != $last_font_number) {
146 1         3 my $font = $self->fontlist->[$last_font_number];
147 1         5 $value .= '/' . $font->name() . ' ' . $size . ' Tf ';
148 1         5 $value .= $font->text(pack('U*', @codes), $size, $indent) . ' ';
149 1         3 $indent = undef;
150 1         2 @codes = ();
151             }
152              
153 9         18 push @codes, $u;
154 9         12 $last_font_number = $font_number;
155             }
156              
157 2 50       7 if (scalar @codes > 0) {
158 2         13 my $font = $self->fontlist->[$last_font_number];
159 2         7 $value .= '/' . $font->name() . ' ' . $size . ' Tf ';
160 2         16 $value .= $font->text(pack('U*', @codes), $size, $indent);
161             }
162              
163 2         10 return $value;
164             }
165              
166             1;