 |
A tricky issue with java.awt.Font
Posted by mister__m on March 21, 2005 at 11:40 AM | Comments (30)
If your code or code you use relies on loading fonts by name, you may face severe limitations when trying to use your application in a different environment than the one you performed your tests. Although many of us are aware of the fact specific fonts may not be installed on a machine, trying to work around this problem may prove to be more difficult as it seems at first.
Most code that loads fonts by name use either the getFont(String name) or the getFont(String name, Font defaultFont) method from the java.awt.Font class. What happens when there is no font registered in the OS whose name is name? In the first case, null is returned; for the second method, the defaultFont parameter is returned. This will probably lead to unexpected results. Even when the font exists in the OS, it may not be the same font you were expecting. Yes, that is right: there are different font files for "common" fonts. So, how can you load a specific font and make sure the one you expect will be used to render text?
The Font API allows you to programatically load a font from a java.io.InputStream using the createFont(int fontFormat, InputStream fontStream) method. Although the only font format supported is Font.TRUETYPE_FONT, this should be enough for most situations, since if you are not using a TrueType font, there is no guarantee it will render the same in different platforms and/or devices. Unfortunately, there is a problem that prevents this solution from working most of the times: there is no way to associate a loaded font with a name. This is somewhat surprising, since the loaded instance even returns the correct name when its getName() method is called.
So, how to solve this problem? If you wrote the code or can modify its source, you simply need to rewrite the parts that load a font by name so that they delegate to a method that looks up the instance in a "registry", such as a Map. The problem gets worse, though, when you are working with third-party software. If you can modify the binaries in runtime, using AOP to work around this problem is a possible solution. However, sometimes the third-party license prohibits this kind of modification and then there isn't much the developer can do besides asking the vendor to rewrite the API.
The long term fix for this issue would be to add a register(String name, Font font) method to Font in Mustang. Should I propose an enhancement about this? I would like to know what you think.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
It sounds like you have a use case that isn't covered, in which case I think you should definitely submit an RFE.
I think you should have a think about the semantics of the border-cases, though:
1) Is there a required format for font names?
2) Can fonts be replaced using this method?
3) If 'no' to 2), what behaviour do you expect if an attempt is made replace a Font?
Personally, I get bad feelings whenever I see static methods (especially public ones) that change the state of "the application" (i.e. everything).
It's easy to imagine situations where either:
a) One component registers a font and then another replaces it with something different; or
b) Two components try to register a font with the same name and a race condition in the order code is loaded results in one Font "winning" sometimes and the other winning the other times.
These kinds of problems are very annoying and hard to work around. We recently experienced a problem where, seemingly for no reason, all our logging statements were being printed out using the GMT timezone. It turned out a library we were using thought it best that the default timezone be set to GMT!
In summary, I think maybe it's better to consider how often this kind of thing (i.e. loading and using a custom Font) needs to be done and whether it's actually a frequent enough occurence to introduce code into the core API when there's other, less trouble-prone methods of achieving the same outcome (e.g. send an RFE to the third-party software vendor to let you pass a Font object into their API?).
Posted by: grlea on March 21, 2005 at 04:38 PM
-
Hmmm... Salty problem we have here...
I think you should propose an enhancement, Michael...
Posted by: molusco on March 22, 2005 at 03:43 AM
-
I too dislike static state. I would prefer the addition of a FontFactory interface, and a method on Window (or perhaps Component) to get the FontFactory, delegating to its parent component if none has been set and ultimately to the platform factory.
The standard FontFactory would be equivalent to the existing Font.getFont methods and not support registering new fonts. However by changing a Frame's FontFactory you could alter the set of fonts for all components in its tree without interfering with other Frame's in the same process. Obviously this would also require developers to update their code to use the new mechanism.
Posted by: mthornton on March 22, 2005 at 05:42 AM
-
It is not a good idea to require people to use a new API for this. Thousands - if not millions - of lines of code currently use the Font API as it is and it makes no sense to require people to rewrite all these lines (and sometimes it is not even possible) to use a feature that should be there from the start.
Although I agree that there should be a way to avoid a global static mechanism, I think this should be the option that would require code to change. So, the current Font.getFont(..) methods should be deprecated and they could both delegate to a "default" FontFactory. Each framework/software could then use their own FontFactory if it was needed.
Posted by: mister__m on March 22, 2005 at 06:10 AM
-
Hi grlea,
Here are my answers to your questions:
1) Is there a required format for font names?
The same one used today
2) Can fonts be replaced using this method?
Yes. A permission should be required though.
I think maybe it's better to consider how often this kind of thing (i.e. loading and using a custom Font) needs to be done and whether it's actually a frequent enough occurence to introduce code into the core API when there's other, less trouble-prone methods of achieving the same outcome (e.g. send an RFE to the third-party software vendor to let you pass a Font object into their API?).
Almost all code dealing with fonts use the current mechanism, which is severely limited as I explained above. It is not possible to rewrite most code in the world because of this. The JDK code needs to be flexible instead.
Posted by: mister__m on March 22, 2005 at 06:22 AM
-
i propose that we try to learn from what css did for the web: define standard font families that are guaranteed to be available on every platform: serif, sans-serif, monospace ..
( http://www.w3.org/TR/CSS21/fonts.html#font-family-prop )
Posted by: eitan on March 22, 2005 at 08:28 AM
-
I hope this formats properly - the preview came out completely
wrong which will make this hard to read.
I think there were a couple of somewhat distinct issues raised here and
maybe they got blurred.
* How to tell if the font you got is the one you wanted
* How to use Font.createFont type mechanisms to install or register a
font.
How to tell if the font you got is the one you wanted
=====================================================
Font.getName() as mentioned in the blog will return whatever string
you use in the constructor. Its considered to be the logical name of
the
font. This does mean if you pass in garbage you'll get garbage out.
In practice getName() is of marginal use or interest.
If you want to know what font it resolved to you should use
Font.getFontname() or Font.getFamily() as they will look at the font.
I believe you overlooked these APIs since there is no mention of them.
They do what I believe you are requesting.
Also if you want to know what fonts are available there are APIs
to do it. See:
GraphicsEnvironment.getAllFonts and
GraphicsEnvironment.getAllFamilyNames
So you can see what's available before you start.
But if you want to let the system do an exhaustive "don't give up
try everything to load this font" its sufficient to do (eg)
new Font("name that I want", Font.PLAIN, 12);
and check the name of the returned font with getFontName()
>Most code that loads fonts by name use either the getFont(String name)
>or the getFont(String name, Font defaultFont) method from the
>java.awt.Font class.
The only justifiable reason I've seen for using these is that font
preferences were saved as a name-style-size string somewhere.
Now if that was how you were using it you too probably don't know what
font you are looking for, so you'd need to parse out the string to
figure that out and its going to be trickier than you think.
It would be better to store these separately and construct a new font.
So why are people using these APIs?
These APIS theoretically could help share fonts from a cache but a
java.awt.Font object is typically lightweight. All the real caching
that
matters happens at a lower level. In fact in getFont just does new Font
- and that's after lots of messing around parsing the String - so its
going to be slower than new Font(..). Its also less reliable because of
the parsing.
How to use Font.createFont type mechanisms to install or register a
font.
=======================================================================
> The long term fix for this issue would be to add a register(String
name, Font font)
If I correctly understand the point, adding a way to augment the set of
"registered" fonts via this API has been thought about and still is
but it is the (current) design that you need to capture the returned
reference from Font.createFont to derive new instances to avoid the
kind
of name clashing mentioned by the first commenter.
The first commenter was right on the money about state and clashes.
There's a reason its Font.createFont and returns you a Font rather than
being called something like Font.registerFont(). There are all sorts
of knotty problems with that which need careful thinking about.
Also if the reason for this is you want to supply a font that's not
available on some platform, then you need to be careful to follow the
terms of the font license. Don't expect to be able to grab "Tahoma"
from XP and ship it in your app to run on Linux.
Remember SansSerif, Serif and Monospaced.
Use these logical font names as much as possible, These get you great
advantages in terms of language/script support in 1.5 - you should
be able to display Chinese etc so long as the fonts are on your system
If you pick some other physical font loaded through createFont that's
not going to be possible.
> createFont(int fontFormat, InputStream fontStream) method. Although
the only font format supported is Font.TRUETYPE_FONT,
FYI: 1.5 - FCS last year - supports Type1 too
Posted by: philrace on March 22, 2005 at 10:04 AM
-
Yep it came out horribly formatted. No idea why
Posted by: philrace on March 22, 2005 at 10:05 AM
-
Hah I was supposed to hand type HTML into a horrible little
text widget?
Here's the post again formatted more legibly
I think there were a couple of somewhat distinct issues raised here and
maybe they got blurred.
* How to tell if the font you got is the one you wanted
* How to use Font.createFont type mechanisms to install or register a
font.
How to tell if the font you got is the one you wanted
=====================================================
Font.getName() as mentioned in the blog will return whatever string
you use in the constructor. Its considered to be the logical name of
the
font. This does mean if you pass in garbage you'll get garbage out.
In practice getName() is of marginal use or interest.
If you want to know what font it resolved to you should use
Font.getFontname() or Font.getFamily() as they will look at the font.
I believe you overlooked these APIs since there is no mention of them.
They do what I believe you are requesting.
Also if you want to know what fonts are available there are APIs
to do it. See:
GraphicsEnvironment.getAllFonts and
GraphicsEnvironment.getAllFamilyNames
So you can see what's available before you start.
But if you want to let the system do an exhaustive "don't give up
try everything to load this font" its sufficient to do (eg)
new Font("name that I want", Font.PLAIN, 12);
and check the name of the returned font with getFontName()
>Most code that loads fonts by name use either the getFont(String name)
>or the getFont(String name, Font defaultFont) method from the
>java.awt.Font class.
The only justifiable reason I've seen for using these is that font
preferences were saved as a name-style-size string somewhere.
Now if that was how you were using it you too probably don't know what
font you are looking for, so you'd need to parse out the string to
figure that out and its going to be trickier than you think.
It would be better to store these separately and construct a new font.
So why are people using these APIs?
These APIS theoretically could help share fonts from a cache but a
java.awt.Font object is typically lightweight. All the real caching
that
matters happens at a lower level. In fact in getFont just does new Font
- and that's after lots of messing around parsing the String - so its
going to be slower than new Font(..). Its also less reliable because of
the parsing.
How to use Font.createFont type mechanisms to install or register a
font.
=======================================================================
> The long term fix for this issue would be to add a register(String
name, Font font)
If I correctly understand the point, adding a way to augment the set of
"registered" fonts via this API has been thought about and still is
but it is the (current) design that you need to capture the returned
reference from Font.createFont to derive new instances to avoid the
kind
of name clashing mentioned by the first commenter.
The first commenter was right on the money about state and clashes.
There's a reason its Font.createFont and returns you a Font rather than
being called something like Font.registerFont(). There are all sorts
of knotty problems with that which need careful thinking about.
Also if the reason for this is you want to supply a font that's not
available on some platform, then you need to be careful to follow the
terms of the font license. Don't expect to be able to grab "Tahoma"
from XP and ship it in your app to run on Linux.
Remember SansSerif, Serif and Monospaced.
Use these logical font names as much as possible, These get you great
advantages in terms of language/script support in 1.5 - you should
be able to display Chinese etc so long as the fonts are on your system
If you pick some other physical font loaded through createFont that's
not going to be possible.
> createFont(int fontFormat, InputStream fontStream) method. Although
the only font format supported is Font.TRUETYPE_FONT,
FYI: 1.5 - FCS last year - supports Type1 too
Posted by: philrace on March 22, 2005 at 10:22 AM
-
I don't see why you would want to do this. Why not just load fonts manually in your program if you have these requirements? I think that's what I would do.
Posted by: keithkml on March 22, 2005 at 12:48 PM
-
mister__m wrote:
"Almost all code dealing with fonts use the current mechanism, which is severely limited as I explained above."
I'll admit, I've never seen much code that uses Fonts, though I'm sure there's lots around.
What I don't understand is why you're trying to create a custom font to begin with.
What's wrong with GraphicsEnvironment.getAllFonts()?
Can you give us a more concrete example of when this would be a problem?
I want to understand the problem, but I'm finding it hard to a imagine a situation where the Font used by something is important but where it's not appropriate to have the user select that font.
Posted by: grlea on March 22, 2005 at 03:10 PM
-
i propose that we try to learn from what css did for the web: define standard font families that are guaranteed to be available on every platform: serif, sans-serif, monospace .. ( http://www.w3.org/TR/CSS21/fonts.html#font-family-prop )
Hi eitan,
That's the problem. There is a way to make a font that is not available to the OS in HTML (afaik) and refer to it by name. There's nothing similar in Java :-(
Posted by: mister__m on March 22, 2005 at 04:01 PM
-
Hi philrace,
If you want to know what font it resolved to you should use
Font.getFontname() or Font.getFamily() as they will look at the font. I believe you overlooked these APIs since there is no mention of them. They do what I believe you are requesting.
Thanks for pointing out this. I really missed the diference between Font.getName() and Font.getFontname()
if you want to know what fonts are available there are APIs
to do it. See:
GraphicsEnvironment.getAllFonts and
GraphicsEnvironment.getAllFamilyNames
Ok, I was aware of these methods. ;-)
The only justifiable reason I've seen for using these is that font
preferences were saved as a name-style-size string somewhere.
Now if that was how you were using it you too probably don't know what font you are looking for, so you'd need to parse out the string to figure that out and its going to be trickier than you think.
It would be better to store these separately and construct a new font.
So why are people using these APIs?
There are many well-known frameworks using this very mechanism, such as JasperReports and Thinlet. So, people are forced to use this font loading scheme no matter how they feel about it.
If I correctly understand the point, adding a way to augment the set of "registered" fonts via this API has been thought about and still is but it is the (current) design that you need to capture the returned reference from Font.createFont to derive new instances to avoid the kind of name clashing mentioned by the first commenter.
As I mentioned in my post, the problem is not when you authored the code, but rather when it was produced by a third-party. Then, what you said - and I said before - is sometimes not possible.
FYI: 1.5 - FCS last year - supports Type1 too
Yes, you are right about this one. I thought I had looked at Tiger docs, but it was 1.4 docs instead.
Posted by: mister__m on March 22, 2005 at 04:26 PM
-
Hi keithkml,
I don't see why you would want to do this. Why not just load fonts manually in your program if you have these requirements?
Because most code dealing with fonts is in third-party frameworks and that's the way most of them load fonts.
Posted by: mister__m on March 22, 2005 at 04:28 PM
-
What I don't understand is why you're trying to create a custom font to begin with. What's wrong with GraphicsEnvironment.getAllFonts()?
Can you give us a more concrete example of when this would be a problem?
I want to understand the problem, but I'm finding it hard to a imagine a situation where the Font used by something is important but where it's not appropriate to have the user select that font.
Ok, an example: reports. Usually the layout of reports that are supposed to be sent to customers is designed by marketing or specialized people and approved by managers. It has to look the same, no matter whether the machine used to generate the report has the font or not. So, there must be a way to make sure the font you are using is the same you were expecting to use.
Posted by: mister__m on March 22, 2005 at 04:33 PM
-
As I think someone else has pointed out, the ability to register custom fonts wouldn't solve your problem here (with the 3rd party products), because you don't necessarily know or have the fonts that the product is going to lookup anyway!
I'm getting an increasing feeling that the problem you're describing is a flaw in the design of the products being used rather than Java.
There are many other solutions to the problem than the one you've suggested:
The product could serialize the font into the file format
The product could accept a setFont(Font) method
The product could use some form of callback, e.g. a 'FontProvider' interface
The user of the product could install the font?
The last suggestion isn't as ridiculous as it may seem:
Your original suggestion is essentially to "install" the font into Java, rather than into the OS. The font has to be available on the machine and in a known location to do this anyway, so why not just install it on the OS?
I guess we could come up with a scenario where 3rdPartyProduct, a library, accepts any fonts, and writes font names out in its file format, then OurProduct, a fully-fledged product that uses 3rdPartyProduct, uses a particular font, and always uses that font, so we distribute it with OurProduct and want to install it at runtime for 3rdPartyProduct to use.
Firstly, I think this would be a pretty contrived example.
Secondly, in this case I don't think it's unreasonable to ask the user to install the Font or to do it for them at installation time (MANY applications do this!).
In all other cases, my feeling is that the user is in a position to install any fonts they need and the Java APIs are sufficient at present for the application to be able to inform the user that they need to "Install font 'X' for this document to be formatted correctly.", or whatever.
Have I missed something?
Posted by: grlea on March 22, 2005 at 05:04 PM
-
Hi grlea,
As I think someone else has pointed out, the ability to register custom fonts wouldn't solve your problem here (with the 3rd party products), because you don't necessarily know or have the fonts that the product is going to lookup anyway!
Sorry if I still wasn't clear enough. What I meant is: if you are using JasperReports, Thinlet or several other frameworks, you specify a font name, style and size in xml/text/whatever format. It then gets loaded in runtime by these frameworks using Font.createFont(...). And it leads to unexpected behaviour since you cannot interfere with the way Font.createFont(...) works.
There are many other solutions to the problem than the one you've suggested:
- The product could serialize the font into the file format
Having a font file is not a problem. The problem is there is no way to make Font.createFont(..) "understand" it.
The product could accept a setFont(Font) method
When using XUL or a report, I surely don't want to navigate the entire widget tree for that or even do it programatically just because Java is limited in this sense. It could take a lot of time and there are several problems you'd have to deal with, for example, two widgets that are of the same type that should be displayed using different fonts. It simply does not feel right.
The product could use some form of callback, e.g. a 'FontProvider' interface
Why not adding something like this to the platform? It is not such a big change. Besides that, it would help in situations where the product cannot be changed.
Your original suggestion is essentially to "install" the font into Java, rather than into the OS. The font has to be available on the machine and in a known location to do this anyway, so why not just install it on the OS?
The font does not have to be available in the hard disk. You just need a InputStream. I loaded the font from a specific jar file in the original webstart application that got me thinking about this issue. Installing a font in the OS requires security permissions sometimes.
I don't think it's unreasonable to ask the user to install the Font or to do it for them at installation time
If it is a webstart application, it is :-) The user is only supposed to run it.
Posted by: mister__m on March 22, 2005 at 05:29 PM
-
Michael,
This is indeed a very interesting problem. : )
I've got quotes from you below in italics.
if you are using JasperReports, Thinlet or several other frameworks, you specify a font name, style and size in xml/text/whatever format. It then gets loaded in runtime by these frameworks using Font.createFont(...).
This doesn't make sense. They can't be using createFont() if they only have a name? I assume you mean they are using new Font(String,int,int)?
Having a font file is not a problem. The problem is there is no way to make Font.createFont(..) "understand" it.
I don't believe that's your real problem.
That's a way of stating the problem with a bias toward a particular solution. : )
The actual problem is that there's no way to get a "created" font into your library.
If you had a way to do this, not having a registerFont() method would not be a
"problem".
The product could accept a setFont(Font) method
It simply does not feel right.
It was a list of other options, not a list of good options. ; )
That was one of the poorer ones.
The product could use some form of callback, e.g. a 'FontProvider' interface
Why not adding something like this to the platform? It is not such a big change.
I believe adding state to the JVM (in the form of static methods that "remember" stuff, e.g. Locale.setDefault()) is a big change.
The consequences of methods like this are far-reaching and, if implemented, could cause more problems than they solve.
The font does not have to be available in the hard disk. You just need a InputStream. I loaded the font from a specific jar file in the original webstart application that got me thinking about this issue.
Ahhhhh...... this is a great point and I think I finally see where you're coming from / why you're having these problems. :)
I don't think it's unreasonable to ask the user to install the Font or to do it for them at installation time
If it is a webstart application, it is :-) The user is only supposed to run it.
I do now see exactly where you're coming from.
Unfortunately (for you), I still don't agree that it's Java that needs to be "fixed".
If the 3rd party product you're using is meant to be able to use documents that are portable (i.e. used on more than one machine), then it is making an incorrect assumption by storing your fonts as name/style/size, because the product is essentially assuming, on your behalf, that the font is installed on the OS.
After all, that is the semantics of new Font().
I assume the library authors didn't do it this way because they've foreseen the implementation of a Font.registerFont() methods. : )
Java provides other methods of loading Fonts, as you yourself pointed out just before.
The fact that the 3rd party product doesn't use those methods is not the fault of Java, and does not mean that Java is broken.
I'll stop short of saying the product is broken, because I've been antagonistic enough already, but if you did request this registerFont() feature in Java, it would really be so that you could use it to "fix" the 3rd party product. ; )
In essence, I'm saying that you don't need a change to the Java API for your problem to be solved.
There are other solutions, it's just that the 3rd party product you're using isn't taking advantage of them.
And when there's other solutions than adding something to the Java API, I think changing the Java API should be a low-percentage option.
However, I'm sure there are other situations where there may not be other solutions.
In fact, one of my colleagues just rang me (after reading this blog) to tell me about a problem he had where he wanted to refer to a custom font from within HTML being used in a JEditorPane.
Getting HTML changed to include a facility for auto-loading unknown fonts probably wouldn't be as easy asking the writer of your 3rd party product to support such a feature.
If you do go ahead and log an RFE for this, can I suggest that you request the semantics be as such:
If an attempt is made to register a Font under the name of an
existing font, a FontAlreadyRegisteredException (or
DuplicateFontNameException or whatever) is thrown.
Yep, this will disallow people from "overwriting" fonts that have already been registered (in particular, those installed in the OS), but I think having it implemented like that would save a lot of people a lot of time that they would otherwise spend trying to figure out why the font they registered isn't being rendered correctly.
Thanks for persisting until I understood what you're doing.
I hope my Devil's advocacy has been of some use to you, or at least someone.
Posted by: grlea on March 22, 2005 at 06:47 PM
-
Gee this blog software is funny.
All you have to do is accidentally insert a <pre> section with a really long line and you ruin the whole page for everyone.
Of course, it doesn't help that you can't edit your posts.
Sorry about that, everyone.
Posted by: grlea on March 22, 2005 at 06:49 PM
-
I fully agree with submitting an RFE. I have experience this exact problem. In the end had to use images in my JEditorPane (ouch).
I'm not to keen on the FontFactory stuff, as it won't fix existing classes (such as JEditorPane) unless they are updated to use the factory instead of "new Font(..)". While the factory approach is a nice idea in principal, i can't see Sun commiting to it.
I was also wondering if Font.register(Font f) would be adequate instead of having to explicitly supply the name. I presume it could be registered under f.getFontName() or what ever is appropriate.
Cheers Andrew
Posted by: pietschy on March 22, 2005 at 08:04 PM
-
Yes, please file an RFE.
I had to go a looong way to work around the same problems. I even wrote my own TrueType file reader, so that I could retrieve font names quickly (without actually loading the whole font).
Another point is that StyleContext doesn't use custom fonts, so one has to override StyleContext.getFont(), too...
What I would also like to have is support for device idependent sizing, so that a "12 Point" font is displayed as "12 / 72 inches" on any screen, instead of "12 Pixels".
-- Peter
Posted by: nightrider on March 23, 2005 at 01:35 AM
-
Sounds like it's something people really need. : )
Michael, maybe you could submit the RFE, then implement it yourself against the Mustang sources, contribute it back to Sun and then blog about how the whole process goes?
I'd be interested to know how long it takes to get everything compiling, make a fix, 'contribute' it and then see it appear in the real Mustang.
Posted by: grlea on March 23, 2005 at 04:21 PM
-
I just filed what I think is the right RFE
6245665 : RFE: Font's created with createFont to be available to new Font(..) etc.
After some delay to push it from the bugs db to the web (tomorrow maybe?)
it can be viewed at http://bugs.sun.com by typing the bug id into the search
field.
I included a very long discussion of the issues in the evaluation section.
So for anyone interested in this I'd suggest to add to the comments
section there as they can be tied to the RFE. You can also "vote" for
the RFE assuming you are a registered JDC member (its free).
Posted by: philrace on March 24, 2005 at 11:21 AM
-
I've made my comments to the bug you've submitted, Phil. I disagree on three things: first, yes, there is a need to override a system font; since this need exists, a permission should be required for this operation to succeed. The third point is that new fonts should be treated as system fonts, i.e., they should be "visible" for methods that list them.
Posted by: mister__m on March 28, 2005 at 06:41 AM
-
Michael,
What is your use case for overwriting an existing font?
Posted by: grlea on March 28, 2005 at 04:11 PM
-
grlea, the use case is based on a (sad) real world fact: font files are very different. I mean, if you have X.ttf in one machine and X.ttf in another, virtually all glyphs could be different. Yes, that's scary, it seems broken, but that's how things work on the real world.
So, if I am using a free font a user could have downloaded and installed, I want to be sure a specific version is being used. Otherwise, we're back to the original problem in a worse way: you can't tell whether the font you got is the one you expected because nearly all data about it would match unless you serialize the metrics for your "intended" font.
Posted by: mister__m on March 28, 2005 at 05:29 PM
-
What about being able to control the name of the font when you register it? i.e. :
Font.registerFont(String fontName, Font newFont)
Then you can name your font something like org_misterm_myapp_tableFont or whatever.
This would solve that use case, would it not?
I think I'm concerned about changing the fonts from what the user expects them to be.
Fair enough if you want to have a specific font, and you want other components to be able to look up custom created fonts, but is there a reason it has to overwrite an existing one?
Posted by: grlea on March 29, 2005 at 04:45 PM
-
Hi grlea,
Then you can name your font something like org_misterm_myapp_tableFont or whatever. This would solve that use case, would it not?
Then you are assuming I can actually manipulate the name of the font. This might be true or not, so it's only a partial solution.
I think I'm concerned about changing the fonts from what the user expects them to be.
I agree. And that's why a specific SecurityPermission should exist in order to control this.
Posted by: mister__m on March 30, 2005 at 01:40 PM
-
"Then you are assuming I can actually manipulate the name of the font."
Actually, I'm saying you should be able to manipulate the name of the font. : )
I'm saying it should be part of the RFE!
Being able to replace a font and not have an exception thrown is totally error-prone.
Here's a scenario for you:
I have a GUI, which has an Options... dialog.
The dialog uses a custom component.
The component loads and registers a custom font.
The font is called 'Tahoma'.
I load my GUI and it looks really good.
I then option the Options dialog, which creates the custom component, which registers the new Font.
Suddenly, the Font of absolutely everything in my application changes and the whole thing now looks crap.
Solution?
There is none.
Maybe you could change the font straight back again, which will probably show up as a visual glitch and will also mean that the custom component no longer has the font it intended to have.
Although, you can't just put that font back, because it was a system font, and you have no way to "create" it again.
If you let components replace existing fonts, this is what will happen.
Or, you could do what you've suggested, and just stop the custom component from being able to override fonts.
Again, this means the component doesn't have the font it intended to have, because it failed to register it and just gave up.
I don't believe being able to override fonts is a workable solution.
Being able to register fonts with a specified name, however, would facilitate every requirement you've been talking about.
Posted by: grlea on March 30, 2005 at 08:17 PM
-
Hi grlea, here we ago again :-)
I think my previous response did not conveyed the idea I had in mind. Of course you could register the font with any name you wanted, but what I meant is: "Then you are assuming I can actually manipulate the name of the font " in the place that uses the font, not defines it.
You seem worried about the fact that replacing a system font gives no warning. There are two solutions for that: the one I had already proposed is to require a permission for this kind of operation. If people grant all permission to code, they should be expecting anything from code.
The other one is to have two methods for that or maybe an extra boolean parameter indicating whether it should override the font if it exists. Then, these "bad things" would only happen by design, not by accident.
Posted by: mister__m on April 05, 2005 at 07:28 PM
|