Java - How to tell which fonts don't render? - java

I have:
Font[] fonts =
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
which I then want to render in a JComboBox with a custom renderer however I'm finding that some fonts don't render at all, or just look beyond terrible. Some also take like 100-200 pixels of height in the JComboBox, some weird fonts that I'm not at all familiar with. So for example the 4th item is unreadable and the 5th (the selected one in blue) is huge and displays no characters even if you scroll down.
I looked at trying to remove the offending fonts but I can't find a way to do it other than whitelisting which is not ideal.
The best articles I found are:
https://weblogs.java.net/blog/javaben/archive/2008/01/of_fonts_and_ja.html
Determining in Java whether a particular font can render a particular character
but the second is really just how to check for a particular character and not terrible rendering overall.
I've also tried getAvailableFontFamilyNames(), and although this reduces the list, several badly rendered fonts still appear in the JComboBox. By badly rendered I mean invisible with tons of height. So trying canDisplay('a') or something like that also doesn't work because it still returns true;

there's no metric for "looking horrible", but you could draw the string you want into some off-screen buffer and see the rectangle size the string "occupies" under each font.
see here for how to do it.
this way you could render the same string with all fonts and thow out the ones that produce too small or too-large "rectangles" - that should do away with all those fonts that currently mess up your ui.

The solution I ended up using incorporates what radai did but also adds canDisplay('a') so that I ended up with:
private boolean isAcceptableFont(Font font)
{
int fontHeight = getFontMetrics(font).getHeight();
if(fontHeight > MAX_FONT_HEIGHT || fontHeight < MIN_FONT_HEIGHT)
return false;
if(getFontMetrics(font).stringWidth(TEST_STRING_FOR_FONT_WIDTH) <= MIN_FONT_WIDTH)
return false;
if(!font.canDisplay('a'))
return false;
return true;
}
Checking the size of the rendered fonts removed a lot of bad fonts, but there were still a few that rendered really poorly. Adding a check to see if they could display at least the character 'a' seems to have filtered the remaining bad fonts.
It's not ideal, but it filtered 99+% of fonts that didn't make sense.

Related

PDFBox 2.0: Get color information in TextStripper

I'm using PDFBox PDFTextStripper for text extraction. I also need to get color information for each character, ideally in writeString method.
What I found, is this solution for PDFBox 1.8 (actually can be easy converted to 2.0 version), and what else i'm looking for is background color for each character (as in that answer there is only character color).
I added all handlers for Fill operators - CloseFillNonZeroAndStrokePath, CloseFillEvenOddAndStrokePath FillNonZeroAndStrokePath, FillEvenOddAndStrokePath, LegacyFillNonZeroRule, FillNonZeroRule, FillEvenOddRule (like suggested in this topic), and inside those operators get nonStrokingColor:
public final class FillEvenOddRule extends OperatorProcessor {
#Override
public void process(Operator operator, List<COSBase> operands) throws IOException {
linePath.setWindingRule(GeneralPath.WIND_EVEN_ODD);
deleteCharsInPath();
linePath.reset();
PDGraphicsState gs = getGraphicsState();
PDColor nonStrokingColor = gs.getNonStrokingColor();
fillColor = nonStrokingColor.toRGB();
}
#Override
public String getName() {
return "f*";
}
}
Then in processTextPosition I tried to get this fillColor and put it to map for each character (assuming content stream work consecutive way - after Fill operator completes, all next coming to processTextPosition characters should have this fillColor. However this is not truth and all characters have wrong color. There is file I'm trying to process, each second row has blue filling, and I would like to get that blue color for each character in such row, and white color for each character in white row. Is it possible with PDFBox?
The problem in context with the sample document
Then in processTextPosition I tried to get this fillColor and put it to map for each character (assuming content stream work consecutive way - after Fill operator completes, all next coming to processTextPosition characters should have this fillColor. However this is not truth and all characters have wrong color.
As you found out, your assumption is wrong for the PDF at hand. The strategy in this document is to first draw all background material and then draw all text. Thus, your approach for this document should always return the color of the last bit of background material.
As mentioned in my comment to the second question here you referenced, you have to collect all rectangles (or more generically: paths) filled in parallel to the actual text extraction and check whether the font rendering color(s) (depending on the text rendering mode it may also be the StrokingColor!) of the currently inspected text coincide with that of the currently top filled path at the location of the text.
In a comment you wonder
does this mean this approach will work for all documents?
Does this approach work for all documents
For many it does but not for all.
The following issues immediately come to mind:
Not all color spaces support the toRGB method you use. (I just checked, I'm positively surprised for how many PDFBox does have an implementation.)
In particular in case of pattern colors you have to do a lot of digging into the pattern and its usage in your case to find the actual background color(s).
There are other ways to paint a background form, too, in particular:
The approach only considers filled paths, but if you use a larger value for the graphics state line width or a stretching transformation matrix, a stroked line can also paint rectangular forms. Thus, for this case you also have to consider stroked paths.
The background might be a bitmap image. In this case you'll have to analyze the image to get the background color(s)
Another alternative to consider is a shading fill. This usually will also result in a range of colors in the background.
Forms drawn over the glyph afterwards instead of covering it may change foreground and background considerably. There e.g. are blend modes that take the hue from the backdrop and the saturation from the foreground...
Soft masks active when drawing background or foreground may also be of interest.
...

What if the preferredSize of my component is taller than Integer.MAX_VALUE?

I have written a hex viewer.
However, I found a limitation in Swing. If you have a 3GB file and you're rendering at 20 pixels per row, the total height of the component is:
(3GB / 16 bytes per row) * 20 pixels per row = 3.75GB
At this point, Swing fails to render anything because the value overflows Integer.MAX_VALUE.
This is my best idea so far:
Clone enough of Java2D and JComponent to make an alternative to JComponent which does all rendering in long coordinates.
Clone JViewport so that you have a way to render the view of the component/
Put that alternative JViewport into a JScrollPane like you would normally do.
This seems like a lot of work, but such a component might be useful for things like large diagrams or large text documents.
I considered just paging it, but it seems like it would be awkward when you're using the Find feature and it matches text crossing a page boundary.
The (non-Java) hex viewer I normally use (Hex Fiend) doesn't use paging either. It just scrolls the whole height of the document as if it's not a problem.
Does anyone know a good way to get around this sort of thing?
You don't need to draw your hex viewer in long coordinates because you only need to draw the part of the file that you want to be visible at the moment. JScrollPane is a very useful tool for scrolling around large components, but you don't need it. If you want to scroll through so much stuff that it's troublesome to have a component big enough to hold it all, then you can simply do the scrolling by making a JScrollBar and painting your component according to the position of the scroll bar.

Getting font character spacing in Android

I'm trying to get the spacing between characters for any font in Android when painting to a Canvas, and I searched in Google but couldn't find anything.
Is there a way to get the font character spacing?
I am prepared to make a WAG that what this use-case really needs is methods more along the lines of:
Paint.getTextBounds()
Paint.getTextWidths()
Both those methods are overloaded. The link is to the one that appears first in the docs.
Possibly the reason you have not found the information on the distance between characters is that for most purposes it is irrelevant. What is relevant is the final width of the rendered text, or it's bounds.
does this work with canvas ?
I was looking through the methods for Canvas1 when I saw it! To underline that, I am new to Android, but experienced at using standard desktop Java (J2SE). In J2SE, I've never once heard a question in relation to the spacing between characters. Many, many questions about the width or the bounds.
But definitely examine the same docs I have been looking at, do a search on 'paint' and find the ways in which it can be used when rendering text.
The Developer Guides link at the top of that document would also be very helpful to you at this moment. They tend to cover these sorts of things.

Android fuzzy / faded fonts possible?

So I am developing a very simple app, mostly for personal use, am am looking for a simple solution to a simple problem.
In its simplest form I am looking for a way to have a line of text with just one or two words blurred out. Basically I am looking to blur text beyond readability but still hinting at what is hidden. Kind of a knowledge / memory app to help memorize some definitions by prompting with a few key words.
I am having issues finding a simple way to accomplish this. Am I just missing an attribute to blur text?
I have thought about:
overriding say the textview onDraw but that seems overkill and I am unsure if there are any methods available to easily blur text.
using the toHtml and trying out the new CSS3 blur effects but I don't think that that is a reasonable solution and I am not sure that the Android platform supports all the CSS3 format, if any.
the simplest and most desirable solution in my book was to find a font (ttf, off, etc) file, derived from a common font, that is already blurred as I described, and use that alternating with the non blurred version of that font to achieve the desired effect.
make the described font but that just plain requires too much time on my part and the outcome is not necessarily good :)
I have thought about some alternative ways to simulate this effect but they all result in fading the text, which is undesirable, since I want to have some visual prompts to indicate the obscured texts length.
Any ideas? It's been years since I have developed in Java and I am unsure what is available and what the Android OS supports.
I haven't looked into using these properties for only part of the text, but TextView has some possibly useful properties related to text shadows. Using something like the following XML attributes, you could hide the actual text and just show a blurred shadow.
android:textColor - #0000 (fully transparent so that the crisp text is not shown)
android:shadowColor - #FFFF (or whatever color you want to appear)
android:shadowDx - 0 (the shadow is in the same horizontal position as the text)
android:shadowDy - 0 (the shadow is in the same vertical position as the text)
android:shadowRadius - Depends on how much you want to blur. A very small non-zero value, such as 0.001, will be sharp. Larger values blur more, and at some point the shadow becomes illegible.

Calculation of required display space for different subclasses of JComponent

For my current project i am writing a JTable based GUI. One of the main features is the ability to adjust the sizes of all cells at runtime, depending on the contents (which change over time). Currently all cells have the same height and width, when the application is started. I would like to change that to a more sophisticated approach. I was wondering if it would be somehow possible to determine the space needed by "the content" to be displayed properly. That is without to much empty space or cutting something of.
"The content" is a string for starters. It is loaded from a database and i can't make any assumptions whatsoever about it. It may be null. In this case there should be any kind of default size for the corresponding cell.
In the long run there will be all different kinds of content to be displayed, like pictures, video and so on.
I tried working with FontMetrics to calculate the length of the strings. But since i'm using JTextPanes to display them, i can't get it to work exactly. I think this has to do with JTextPanes automatic word wrapping because sometimes the lines aren't filled up. This screws up my calculations.
Well long story short: I need some kind of design guideline to achieve the feature descriped above. I'm sure one of you clever guys knows just how to do it.
Thanks in advance,
DeKay
Maybe the text pane size calculation in this How can I measure/calculate the size a Document needs to render itself? will help you out.
As you are using JTextPane for rendering, you may find this Q&A helpful.
The conversion textPane.modelToView() always comes out to null.
Note that modelToView "Returns: the coordinates as a rectangle ... or null if the component does not yet have a positive size."
I have still no idea, how to calculate the amount of space needed in general.
IIUC, the key to understanding #camickr's example is the use of setPreferredSize() to include the text pane's changed boundary, followed by validate() which "is used to cause a container to lay out its subcomponents again."
To set the height of a row in a JTable, look at here:
public void setRowHeight(int row, int rowHeight)
To set a column width, you have to look at the TableCOlumn API here:
public void setWidth(int width)
Hope this can help

Categories

Resources