package PDF::API2::Resource::UniFont;
use strict;
use warnings;
our $VERSION = '2.043'; # VERSION
use Carp;
use Encode qw(:all);
sub new {
my $class = shift();
$class = ref($class) if ref($class);
my $self = {
fonts => [],
block => {},
code => {},
pdf => shift(),
};
bless $self, $class;
my @fonts;
push @fonts, shift() while ref($_[0]);
my %options = @_;
$self->{'encode'} = $options{'-encode'} if defined $options{'-encode'};
my $font_number = 0;
foreach my $font (@fonts) {
if (ref($font) eq 'ARRAY') {
push @{$self->{'fonts'}}, shift(@$font);
while (defined $font->[0]) {
my $blockspec = shift @$font;
if (ref($blockspec)) {
foreach my $block ($blockspec->[0] .. $blockspec->[-1]) {
$self->{'block'}->{$block} = $font_number;
}
}
else {
$self->{'block'}->{$blockspec} = $font_number;
}
}
}
elsif (ref($font) eq 'HASH') {
push @{$self->{'fonts'}}, $font->{'font'};
if (defined($font->{'blocks'}) and ref($font->{'blocks'}) eq 'ARRAY') {
foreach my $blockspec (@{$font->{'blocks'}}) {
if (ref($blockspec)) {
foreach my $block ($blockspec->[0] .. $blockspec->[-1]) {
$self->{'block'}->{$block} = $font_number;
}
}
else {
$self->{'block'}->{$blockspec} = $font_number;
}
}
}
if (defined($font->{'codes'}) and ref($font->{'codes'}) eq 'ARRAY') {
foreach my $codespec (@{$font->{'codes'}}) {
if (ref($codespec)) {
foreach my $code ($codespec->[0] .. $codespec->[-1]) {
$self->{'code'}->{$code} = $font_number;
}
}
else {
$self->{'code'}->{$codespec} = $font_number;
}
}
}
}
else {
push @{$self->{'fonts'}}, $font;
foreach my $block (0 .. 255) {
$self->{'block'}->{$block} = $font_number;
}
}
$font_number++;
}
return $self;
}
sub isvirtual { return 1; }
sub fontlist {
my $self = shift();
return [@{$self->{'fonts'}}];
}
sub width {
my ($self, $text) = @_;
$text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
my $width = 0;
my @blocks = ();
foreach my $u (unpack('U*', $text)) {
my $font_number = 0;
if (defined $self->{'code'}->{$u}) {
$font_number = $self->{'code'}->{$u};
}
elsif (defined $self->{'block'}->{$u >> 8}) {
$font_number = $self->{'block'}->{$u >> 8};
}
else {
$font_number = 0;
}
if (scalar @blocks == 0 or $blocks[-1]->[0] != $font_number) {
push @blocks, [$font_number, pack('U', $u)];
}
else {
$blocks[-1]->[1] .= pack('U', $u);
}
}
foreach my $block (@blocks) {
my ($font_number, $string) = @$block;
$width += $self->fontlist->[$font_number]->width($string);
}
return $width;
}
sub text {
my ($self, $text, $size, $indent) = @_;
$text = decode($self->{'encode'}, $text) unless utf8::is_utf8($text);
croak 'Font size not specified' unless defined $size;
my $value = '';
my $last_font_number;
my @codes;
foreach my $u (unpack('U*', $text)) {
my $font_number = 0;
if (defined $self->{'code'}->{$u}) {
$font_number = $self->{'code'}->{$u};
}
elsif (defined $self->{'block'}->{$u >> 8}) {
$font_number = $self->{'block'}->{$u >> 8};
}
if (defined $last_font_number and $font_number != $last_font_number) {
my $font = $self->fontlist->[$last_font_number];
$value .= '/' . $font->name() . ' ' . $size . ' Tf ';
$value .= $font->text(pack('U*', @codes), $size, $indent) . ' ';
$indent = undef;
@codes = ();
}
push @codes, $u;
$last_font_number = $font_number;
}
if (scalar @codes > 0) {
my $font = $self->fontlist->[$last_font_number];
$value .= '/' . $font->name() . ' ' . $size . ' Tf ';
$value .= $font->text(pack('U*', @codes), $size, $indent);
}
return $value;
}
1;