The unavoidable issue is that in Java when you request size "12", the
default
transform for that is 72dpi and that is actually specified here:-
http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html
Adjusting how this maps to pixels requires applying a transform, which
would apply to all rendering .. and I'm not sure that is what you want and
certainly can't be handled in the selective way you are trying.
Put another way, in the absence of any transform visible on the Graphics,
if "new Font("Serif", Font.PLAIN, 12)" doesn't result in a 12 pixel
font, and
instead results in a (96/72*12) pixel font you are contravening the spec.
So what the GTK L&F currently does is explicitly request a size of
(96/72*12) = 16.
Assuming rounding is handled properly through the chain, then the *pixel*
size that comes out ought to be correct and what matters, and as hinting
should be done
in pixel space. that ought to hint equivalently to telling freetype 12
px @ 96 DPI.
I can't say offhand if that is in fact all correct in implementation but
that is the intent.
And FWIW Windows default DPI isn't 72 DPI either .. but we manage to
hint 100%
(or at least 99.99%) compatibly with GDI at the same pixel sizes,
although those
results are for the proprietary JDK rasteriser not freetype. So again
maybe there's
a freetype thing we aren't doing right if you see differences *at the
same pixel size*
that are rectified purely by adjusting the DPI and pt size.
Apps that want to use the same size as the GTK L&F probably should query
the font size on a GTK L&F Label and that should tell you the standard size.
BTW I notice that one of your patches has SunToolkit dragging in and
querying
the Swing L&F. That's not desirable.
-phil.
On 10/3/2011 7:15 AM, Johnson Lau wrote:
Hi all,
I was working on the same issue as Aekold Helbrass,
to improve Java2D's font rendering.
I agree that instead of handling the size in L&F,
it would be better when the DPI setting is passed to the scaler.
I implemented this by introducing a new method in SunToolkit.
The font scaler will ask SunToolkit for the DPI setting,
which is either retrieved from the system by the platform-specific
SunToolkit implementations, or an overrided value set by the L&F.
For those who're interested in this,
please refer to my patches on Java2D.
https://bitbucket.org/johnsonlau/openjdk-java2d-enhanced-mq
It contains several bug fixes and RFEs to Java2D
which I haven't been ready to publish yet
since some of them are not available on Windows currently,
and focus on the reflect-fc-config.patch and
font-scaler-dpi-handling.patch for the moment please.
The attachment is a screenshot to my work.
Johnson
11-9-30 3:33, Aekold Helbrass:
On Thu, Sep 29, 2011 at 9:40 PM, Phil Race<[email protected]>
wrote:
On 9/29/2011 11:33 AM, Aekold Helbrass wrote:
So... You really mean that swing may not respect desktop font
rendering settings and must keep rendering fonts with the same
uglyness forever, even in native look and feels? No wonder swing is so
dead...
I don't think you are reading what I wrote. The native GTK L&F
*does* do
that ..
I even pointed you to the source code that handles it.
I am reading, also I checked PangoFonts class. It is just changing
size of font instead of setting up proper freetype rendering. Because
of this freetype first of all will not be able to apply proper
subpixel rendering, because it has to know real number of pixels,
calculated from DPI and pt size of font, not just 72 dpi and increased
size. Second, hinting algorythms of freetype will not work either,
because hinting depends on pixel grid so needs exact pixel sizes too.
Please see screenshot in attachment, showing that even GTK look and
feel rendering is different from real GTK app (gedit in the
background).
And "size difference" != "ugliness"
With that I can fully agree, but I have few points here too. First of
all, swing fonts are still ugly as you can see on screenshots I've
sent. Also, swing is not respecting desktop properties, so in any
modern linux desktop environment all apps will look similar (they
respect fontconfig settings, written by user himself or distribution
developers) but swing will be different, and not in a good way.
Being fan of netbeans and swing architecture I wanted to see pretty
fonts and to get rid of those "wow your netbeans is ugly, why don't
you switch to eclipse?", and with my dirty hack I almost did, with few
problems when components are requesting fonts with greyscale or mono
rendering. So as you can see I am not very happy that swing is doomed
because it has to render fonts in some strange manner instead of
respecting system and user settings and getting 100% similar glyphs.
It's a pity swing is so powerful and with really great design, but
nothing is written in swing but few developer tools and maybe few
corporate apps based on netbeans platform. And as for me this visual
difference between swing and native apps is not the last reason for
this.
-phil.
On Thu, Sep 29, 2011 at 8:56 PM, Phil
Race<[email protected]> wrote:
On 9/28/2011 11:10 PM, Aekold Helbrass wrote:
Hi! Thanx for your answer.
On Wed, Sep 28, 2011 at 8:50 PM, Phil Race<[email protected]>
wrote:
I can't see exactly what you are proposing since you aren't
providing
a diff against openjdk master.
Well, before providing diffs against openjdk master - I want to make
it as good as possible. So for now those are just experiments with
what I can and what I can't do.
In so far as I could traverse your git repository and find anything
I'm concerned by seeing references to "x11Display" in the
freetypeScaler.c
file which is actually used on Windows too ..
Exactly. That's why I called it "a dirty hack", "a proof of
concept",
and that's the reason I am asking my questions now - to implement it
properly. To do that I want to see ideas behind font rendering
layer.
OpenJDK does not belong to me, so I am the one who should be
compliant
with original developer's ideas and styles.
And I think you misunderstand how Java defines point sizes.
The point size specified to the Font constructor should be scaled
from pixels only according to the transform on the Java Graphics2D
instance.
NOT in response to any desktop DPI setting.
But freetype2 needs DPI setting to render font properly. That's the
reason why swing apps are always ugly on linux - swing does not
respect DPI nor fontconfig proeprties. Every other UI toolkit on
linux
does, including Qt and GTK. And the more DPI screen has - the uglier
swing looks there. I want to use the same font in kwrite and in
netbeans, but in kwrite its size 9 and in netbeans I have to set
size
12-13 to make it the same, but it still looks different. Not to be
unfounded - please see comparison in attachment, to the left - Qt
rendering, the same as KDE has, Consolas, from size 16 to size 9 top
to bottom. To the right - the same but in swing (jdk6u24). And
that's
on the screen with only 96 DPI, on the screens with 130 and more -
it's even worse. Additionaly, freetype2 has to know exact pixel
size,
calculated from pt size and DPI or set up directly, to render
subpixel
structure properly and make hinter do its job properly. Otherwise
subpixel structure will be wrong and you'll probably get rendering
artefacts, plus hinting will be broken.
Just got another thought... Do you mean that Java have to work that
way because of backward compatibility or compatibility with
T2KFontScaler or for any other reason? I mean, that java does not
need
to respect desktop settings but has to work in predefined manner?
I mean that this is how Java is specified. So its not something
you can
change.
The GTKLookAndFeel code accounts for the desktop DPI used by the
desktop
and scales the font size appropriately. Take a look at
src/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java
In your application, not in JDK code, you could try what it does
there
and getDeskProperty("gnome.Xft/DPI"); and scale your font size
appropriately.
-phil.
-phil.
On 9/28/2011 6:35 AM, Aekold Helbrass wrote:
Hi All!
I am working on fixing openjdk font rendering on linux (because
currently it's just horrible!), and I've done working
proof-of-concept: https://github.com/Helbrass/openjdk-fontfix
So now I would like to move from dirty workaround to proper
clean and
working implementation. And I have some questions about code that
surrounds font rendering and ideas behind that code.
First question is: FreetypeFontScaler.createScalerContext() is not
doing anything, just acting as bridge, and all logic is in
FileFontStrike constructor. And I have to pass DPI to
createScalerContext(). Should I change FileFontStrike and pass
DPI to
any scaler implementation or make
FreetypeFontScaler.createScalerContext() read DPI itself because
T2KFontScaler doesn't need DPI or can read it itself?
Thanx!