PhilterPaper / Perl-PDF-Builder

Extended version of the popular PDF::API2 Perl-based PDF library for creating, reading, and modifying PDF documents
https://www.catskilltech.com/FreeSW/product/PDF%2DBuilder/title/PDF%3A%3ABuilder/freeSW_full
Other
6 stars 7 forks source link

ttfont uninitialized value in hash warning message #205

Closed PhilterPaper closed 9 months ago

PhilterPaper commented 9 months ago

In PDF::API2 ticket ssimms/pdfapi2/issues/71, @svenoe reports receiving warning messages that 3 out of 256 entries are uninitialized in a specific font:


When calling ttfont() on a PDF::API2 object with -encoding => 'utf-8', I receive a warning three times. Unfortunately I understand neither the aim of the code here, nor pack and decode well enough, to say much more.

use PDF::API2;
print "Version: $PDF::API2::VERSION\n";

my $pdf = PDF::API2->new();
$pdf->addFontDirs('var/fonts'); # some font containing directory

my $font = $pdf->ttfont('DejaVuSansMono.ttf', '-encode', 'utf-8');

Version: 2.045 Use of uninitialized value in hash element at /usr/local/share/perl/5.26.1/PDF/API2/Resource/CIDFont.pm line 290. Use of uninitialized value in hash element at /usr/local/share/perl/5.26.1/PDF/API2/Resource/CIDFont.pm line 290. Use of uninitialized value in hash element at /usr/local/share/perl/5.26.1/PDF/API2/Resource/CIDFont.pm line 290.

This comes from

pdfapi2/lib/PDF/API2/Resource/CIDFont.pm

Line 276 in 1b99877 unpack('U*', decode($enc, pack('C*', 0 .. 255))) only returning 253 instead of 256 strings, and thus the line above mapping (253..255) onto undef.

Old versions (at least 2.033-old) had a no warnings qw[ deprecated recursion uninitialized ]; in the code, so I assume that this is maybe no error. And map { unpack( 'U', decode( $enc, pack( 'C', $_ ) ) ) } (0..255) would do something which looks similar in outcome (to me^^), but doesn't have the gaps, but that is, as said before, just guess work...

Thanks in any case and best regards, Sven


I was unable to replicate this problem on PDF::Builder, and was hoping that Sven might have tried it in PDF::Builder, or at least have more information to share. I am not permitted to post to PDF::API2, so I can't talk to you there. I have been waiting to see if there has been any progress on this, but there doesn't appear to have been any.

In the path to the font, is var/fonts a directory relative to either the current directory (your program is running in), or to some fixed base directory? I was wondering if it should be /var/fonts (absolute, not relative, path). Following the instructions above, I have not had any error messages, but I'm also running under Windows. I do have that font, under \Windows\fonts. Is there any way for you to verify that your copy of the font file has not been corrupted?

svenoe commented 9 months ago

Hi @PhilterPaper,

thanks for replying - I can replicate it for PDF::Builder, but while writing this and trying to boil things down, I noticed that it only happens in one of my environments, so maybe it's the perl version. First quickly, it's not the fonts directory, you can even leave that out, I noticed:

#!/usr/bin/perl
use warnings;

use PDF::Builder;
print "perl $^V\nBuilder: $PDF::Builder::VERSION\n";

my $pdf = PDF::Builder->new();

my $font = $pdf->ttfont('DejaVuSansMono.ttf', '-encode', 'utf-8');

returns

perl v5.26.1
Builder: 3.026
Use of uninitialized value in hash element at pdfbuilder/lib/perl5/PDF/Builder/Resource/CIDFont.pm line 358.
Use of uninitialized value in hash element at pdfbuilder/lib/perl5/PDF/Builder/Resource/CIDFont.pm line 358.
Use of uninitialized value in hash element at pdfbuilder/lib/perl5/PDF/Builder/Resource/CIDFont.pm line 358.

And now more specifically:

#!/usr/bin/perl
use warnings;
use Encode qw(:all);

print "perl $^V\n";

my $enc = 'utf-8';

my $e2u = [
    map { ($_ and $_>0x7f and $_<0xA0)? uniByName(nameByUni($_)): $_ }
    unpack('U*', decode($enc, pack('C*', 0..255)))
];

my %u2e;
foreach my $n (reverse 0..255) {
    $u2e{$e2u->[$n]} //= $n;
}

print "done\n";

returns on an older server:

perl v5.26.1
Use of uninitialized value in hash element at x line 16.
Use of uninitialized value in hash element at x line 16.
Use of uninitialized value in hash element at x line 16.
done

but no warning on my laptop:

perl v5.30.3
done

This can, as written in the other thread be tracked down to the following:

#!/usr/bin/perl
use warnings;
use Encode qw(:all);

print "perl $^V\n";

my $enc = 'utf-8';

my @pdu = unpack('U*', decode($enc, pack('C*', 0..255)));
for ( reverse 0..255 ) { printf "%3d - %s\n", $_, ( $pdu[$_] // 'undef' ) };

Resulting in (and only differing in the first three entries):

perl v5.26.1
255 - undef
254 - undef
253 - undef
252 - 65533
251 - 65533
250 - 65533
249 - 65533
248 - 65533
247 - 65533
[...]
129 - 65533
128 - 65533
127 - 127
126 - 126
125 - 125
124 - 124
[...]
  4 - 4
  3 - 3
  2 - 2
  1 - 1
  0 - 0

Or, the working variant:

perl v5.30.3
255 - 65533
254 - 65533
253 - 65533
252 - 65533
251 - 65533
250 - 65533
249 - 65533
248 - 65533
247 - 65533
[...]
129 - 65533
128 - 65533
127 - 127
126 - 126
125 - 125
124 - 124
[...]
  6 - 6
  5 - 5
  4 - 4
  3 - 3
  2 - 2
  1 - 1
  0 - 0

Not sure what really happens under the hood, but I guess this is not a PDF::API2 or PDF::Builder problem then, so sorry for the false alarm, I guess.

Best regards, Sven

PhilterPaper commented 9 months ago

Hi Sven,

All I get out of running your test code (Windows 10, Perl 5.32) is

C:\Users\Phil\Desktop>test205.pl
perl v5.32.1
Builder: 3.026

C:\Users\Phil\Desktop>

No warnings. I suspect that you either have a corrupted font file on this particular machine, or something strange going on in the overall environment. If you think it's something local, and not either PDF::API2 or PDF::Builder code, I'll go ahead and close this ticket.

By the way, concerning the line

my $font = $pdf->ttfont('DejaVuSansMono.ttf', '-encode', 'utf-8');

while that is allowable, the intent is for "encode" (you can give it with or without the leading - hyphen) to be a hash element. Thus, the convention would be to write

my $font = $pdf->ttfont('DejaVuSansMono.ttf', 'encode' => 'utf-8');

It's easier to understand the code that way. Quotes around "encode" are generally optional, but often a good idea.

PhilterPaper commented 9 months ago

It sounds like you're satisfied with the results, so I'll go ahead and close this ticket.

svenoe commented 9 months ago

Yes, thanks for replying to me here, in the first place. :)

(Just for completeness though - no, it's not related to any of my fonts at all, it is, as written in my lengthy post, that unpack('U*', decode('utf-8', pack('C*', 0..255))) has a different (potentially wrong) result on my old testing server running a standard Ubuntu 18.04 with its perl 5.26.1, compared to newer systems. It's definitely not a problem of PDF::API2 or ::Builder, and as it only seems to affect some old version, at least for me I don't see any todo anymore.)