dk / Prima

prima.eu.org
Other
106 stars 27 forks source link

GUI font ratio doesn't work right for large fonts #21

Closed run4flat closed 10 years ago

run4flat commented 10 years ago

Summary

There appears to be an error in the calculation of gui font scaling for GUI -> Postscript font that manifests itself for larger fonts. Basically, the postscript font with is far, far too small for big fonts. Even when using a Postscript font (Helvetica), there are also subtle discrepancies in the placement of individual characters. The spacing between the two o characters is wider on the Postscript than it is on the Window.

Additionally, it seems that a canvas size scaling factor of 65.25 / 100 gives identical postscript dimensions, not 72.27 / 100. This may simply be over-tweaking on my part, or it may have to do with what my screen thinks an inch is. Is there a way in Prima for me to query the number of pixels in an inch so that I can correctly set the canvas size?

Usage

The following script demonstrates the problem. You can modify the behavior of the script by calling it with various arguments.

For example, to call the script with a 500x500 window that uses gui fonts and subcanvas, you would say perl postscript-subcanvas-test.pl 500 subcanvas.

Script

use strict;
use warnings;
use Prima qw(Application);
use Prima::PS::Drawable;
use Prima::Drawable::Subcanvas;

################
# Process Args #
################
# Make subcanvas drawing contingent on an argument 'subcanvas'
my $subcanvas = grep /subcanvas/i, @ARGV;
# Let the user specify a window size
my ($size) = grep /^\d+$/, @ARGV;
$size ||= 50;
# Let the user specify to use Helvetica or the default
my $use_helvetica = grep /helvetica/i, @ARGV;

###################
# File management #
###################
# Build a file name and remove an pre-existing file by the same name
my $base_filename = 'font-dimensions';
$base_filename .= '-helvetica' if $use_helvetica;
$base_filename .= '-subcanvas' if $subcanvas;
$base_filename .= '.eps';
unlink $base_filename;

###############
# Diagnostics #
###############
# Monkey patch text_out to get an idea of the factors effecting font drawing
my $old_text_out = \&Prima::PS::Drawable::text_out;
*Prima::PS::Drawable::text_out = sub {
    my $self = $_[0];
    print "Just before text out operation, font width is $self->{font}{width}, and font width divisor is $self->{fontWidthDivisor}\n";
    goto &$old_text_out;
};

########################
# Build the GUI window #
########################
my $window = Prima::MainWindow->new(
    size => [$size, $size],
    onPaint => sub {
        my ($self, $canvas) = @_;
        $canvas->text_out('foo', $size/5, $size/5);
    },
    font => {
        ($use_helvetica ? (name => 'Helvetica') : ()),
        size => $size/3,
    },
);

########################
# Build the eps canvas #
########################
my $scaling_ratio = 65.25 / 100;
my $width = $window->width * $scaling_ratio;
my $height = $window->height * $scaling_ratio;
my $ps = Prima::PS::Drawable-> create( onSpool => sub {
        open my $fh, ">>", $base_filename;
        print $fh $_[1];
        close $fh;
    },
    pageSize => [$width, $height],
    pageMargins => [0, 0, 0, 0],
    isEPS => 1,
    useDeviceFontsOnly => 1,
);
$ps->resolution($window->resolution);
$ps->font(height => $window->font->height);
$ps->begin_doc or die "Error generating Postscript output: $@";

########################
# Paint the postscript #
########################
if ($subcanvas) {
    $window->paint_with_widgets($ps);
}
else {
    $window->push_event;
    $window->begin_paint_info;
    $window->notify('Paint', $ps);
    $window->end_paint_info;
    $window->pop_event;

}

$ps->end_doc;

##################################
# Show the window for comparison #
##################################
run Prima;
dk commented 10 years ago

Hi David,

Sorry but I can't see (or understand, even) what is the error you're referring to.

As for the character placement, this is a generic problem not specific to PS or even Prima that manifests itself when you try to render text using another font - all character placements become shifted according to the other font's kerning. One can fight it by forcing the kerning of the original font, but Prima's PS code doesn't do it. Probably having such an option can make some sense, I don't know.

I also don't quite get the trouble with the scaling factor .. suppose we have window height 500px, multipled by your constant that gets 326pt, or 4.5in and that is written verbatim in the .eps file. The rest is up to the postscript interpreter, and you can always check the real display PPI with a ruler :)

/dk

dk commented 10 years ago

PS - also, re-kerning the text is not a guarantee that it will look right, the PS interpreter may substitute the font or have another version of the same font.

run4flat commented 10 years ago

On Mac

When I run perl ps-subcanvas-font-dimensions.pl 500, I get this printed to the screen:

Subroutine Prima::PS::Drawable::text_out redefined at ps-subcanvas-font-dimensions.pl line 37.
Just before text out operation, font width is 261, and font width divisor is 260.664961636829

and I get this postscript output: font-dimensions

When I run perl ps-subcanvas-font-dimensions.pl 500 subcanvas, I get this printed to the screen:

Subroutine Prima::PS::Drawable::text_out redefined at ps-subcanvas-font-dimensions.pl line 37.
Just before text out operation, font width is 21.1664451744237, and font width divisor is 212.848588537211

and I get this postscript output: font-dimensions-subcanvas

The key difference is indicated in the printout: the font width divisors differ slightly (261 vs 213) but the font widths themselves differ substantially (261 vs 21.1).

run4flat commented 10 years ago

On Debian

When I run perl postscript-subcanvas-test.pl 500, I get this printed to the screen:

Subroutine Prima::PS::Drawable::text_out redefined at postscript-subcanvas-test.pl line 37.
Just before text out operation, font width is 258, and font width divisor is 257.657289002558

and this postscript output: font-dimensions

When I run perl postscript-subcanvas-test.pl 500 subcanvas, I get this printed to the screen:

Subroutine Prima::PS::Drawable::text_out redefined at postscript-subcanvas-test.pl line 37.
Just before text out operation, font width is 25.7114090220402, and font width divisor is 257.657289002558

and this postscript figure: font-dimensions-subcanvas

dk commented 10 years ago

thank you!

run4flat commented 10 years ago

Yes!! That fixes it! Thanks!