Re: patch -- fix resolution in pango (win32 backend)



Sorry for the late reply.  I'm not having much free time lately...

On Tue, 2002-04-30 at 06:03, Owen Taylor wrote:
> 
> Joaquín Cuenca Abela <cuenca pacaterie u-psud fr> writes:
> 
> > This patch fixes the resolution calculation in pango
> > (for the win32 backend).
> > 
> > With the old resolution, when you ask for a font of
> > size 12, pango used a font of ~7.5 points.
> 
> [ Note that the best thing to do with patches is to attach
>   them to a bug report on bugzilla.gnome.org so they don't
>   get lost. ]
> 
> I'm afraid something happened to your attachment and it is no longer
> well-formed, and a bit hard to make it out.

I will redo it when I will be logged back in Windows.  I will then open
a bug in bugzilla and attach the patch.

> Maybe Tor can figure figure it out though, since he's more familiar
> with the Win32 API.
> 
> Can you also explain the change a bit more?

of course.  The changes are two lines, from:

1a. fontmap->resolution = (PANGO_SCALE * 72.27 / 25.4) * ((double) GetDeviceCaps (pango_win32_hdc, HORZSIZE) / (rect.right - rect.left));
2a. out->lfHeight = (int)((double)size / win32fontmap->resolution +
0.5);

to

1b. fontmap->resolution = PANGO_SCALE / GetDeviceCaps(pango_win32_hdc,
LOGPIXELSY) * 72.0;
2b. out->lfHeight = -(int)((double)size / win32fontmap->resolution +
0.5);

First, the simple differences.  2b is the same thing as 2a, but putting
the value negative.

That's because negative and positive values for lfHeight have different
meanings.  A positive value for lfHeight means that you're specifying
the "height of the font + internal leading" (in short, the line
spacing).  A negative value means that you're specifying the "height of
the font" (once you take the absolute value, of course).

Here we're specifying the size of the font, so we should use the
negative value.

Now, the differences between 1a and 1b are not so easy to understand. 
The only little difference here is the factor points/inch.  1a uses
72.27 points per inch, and 1b uses 72.0 points per inch.

72.27 points per inch is the conversion factor to convert ATA
typographical points to inches (ie, from american points to inches).  In
europe the conversion factor is something as 68.0.  In TeX the
conversion factor is something like the ATA point (but not exactly, if I
remember right), and postscript points are exactly 72 points per inch.

AFAIK Windows uses all around in the GDI 72 as the conversion factor.

The "resolution" value is used by 2[ab] to transform from points[*] to
pixels, so I try to explain here the differences in the calculation of
this value between 1a and 1b.

The interesting part of 1a is that: GetDeviceCaps (pango_win32_hdc, HORZSIZE) / (rect.right - rect.left);

That means more or less:

physical width of the screen in inches / width of the screen in pixels

[(rect.right - rect.left) may give a fake value for the width of the
screen in pixels, and GetDeviceCaps(...) gives only a "standard" size of
the screen in inches (windows has no way to know the real size of your
screen), but that doesn't matters too much here]

When you do that, you will get the more accurate way to draw a text in
screen that you can get.  That means that when you print a text and when
you display it using this conversion factor, you will get roughly the
same size in screen and in the paper (if your screen has the same size
that GetDeviceCaps (...) returns).

The problem here is that in the screen you usually don't have enough
pixels to draw the text at the same size as in the printer, so your text
will have the right physical size in the screen, but it will be
unreadable.

To solve this problem, windows invented the "logical resolution". 
Basically, the user says somewhere that he wants to draw its fonts using
a resolution of 96dpi (by default, people with high resolutions usually
use 120dpi), and windows should not care about the real "inches /
pixels" of the screen (in fact the "i" in 96 dpi is for "logical inch"
instead of a real inch).

That way, you get readable text at low resolutions, and your font
doesn't changes its size as you change your resolution.

To get the logical resolution, you should use
GetDeviceCaps(pango_win32_hdc, LOGPIXELSY).

There is here one more thing to do (not fixed by my patch).

The "resolution" value will convert the size variable in pixels, but
lfHeight is not expecting pixels, but a value in "logical units"
(nothing to do with the "logical resolution" or "logical inches").

The default mapping mode (MM_TEXT) uses 1 logical pixel = 1 pixel, so
(with my patch) you will get the right size for the font for hdcs using
MM_TEXT (and any mapping that keeps the 1 log. pixel = 1 real pixel),
but in the general case it will still be wrong.

To fix that, the piece of code that calculates lfHeight should have
access to the hdc where the user is going to draw the text, and do a:

Point pt;
pt.x = 0; /* doesn't matters */
pt.y = (LONG) ((double)size / win32fontmap->resolution + 0.5);
DPtoLP(hdc, &pt, 1);
lfHeight = -pt.y;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]