ssimms / pdfapi2

Create, modify, and examine PDF files in Perl
Other
15 stars 20 forks source link

paragraph justified text does not work with embedded fonts because word spacing only applies to x20 ascii char #81

Open mcitterio opened 2 months ago

mcitterio commented 2 months ago

according to PDF32000-1:2008 specifications for PDF1.7 point 9.3.3 at pages 244-245 and point 9.4.3 at pages 250-251 I suggest to change or overclass function text_fill_justified as follows for a better management of justified text.

*PDF::API2::Content::text_fill_justified =
sub {
    my ($self, $text, $width, %opts) = @_;
    my ($line, $ret) = $self->_text_fill_line($text, $width);
    my $ws = $self->wordspace();
    my $w = $self->advancewidth($line);
    my $space_count = (split /\s/, $line) - 1;

    # Normal Line
    if ($ret) {
        #$self->wordspace(($width - $w) / $space_count) if $space_count;
        #$width = $self->text($line, %opts, align => 'left');
        #$self->wordspace($ws);
        my $s = $self->advancewidth(' ') + (($width - $w) / $space_count) if $space_count;
        my @words = split /\s/, $line;
        $width =0;
        foreach my $word (@words){
            $width += $self->text($word, %opts, align => 'left');
            $opts{indent} = $s if $space_count;
        }
        return $width, $ret;
    }

    # Last Line
    if ($opts{'align-last'}) {
        unless ($opts{'align-last'} =~ /^(left|center|right|justified)$/) {
            croak 'Invalid align-last (must be left, center, right, or justified)';
        }
    }
    my $align_last = $opts{'align-last'} // 'left';
    if ($align_last eq 'left') {
        $width = $self->text($line, %opts, align => 'left');
    }
    elsif ($align_last eq 'center') {
        $width = $self->text($line, %opts, align => 'center');
    }
    elsif ($align_last eq 'right') {
        $width = $self->text($line, %opts, align => 'right');
    }
    else { 
        #$self->wordspace(($width - $w) / $space_count) if $space_count;
        #$width = $self->text($line, %opts, align => 'left');
        #$self->wordspace($ws);
        my $s = $self->advancewidth(' ') + (($width - $w) / $space_count) if $space_count;
        my @words = split /\s/, $line;
        $width =0;
        foreach my $word (@words){
            $width += $self->text($word, %opts, align => 'left');
            $opts{indent} = $s if $space_count;
        }
    }
    return $width, $ret;
};
mcitterio commented 2 months ago

Also found into pdf reference version 1.4 point 5.3.2 page 311-312

so the change is compatible with PDF 1.4 too

https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.4.pdf https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf