JEditorPane which is limited to HTML 3.2 with some extensions, and simply beeps when it can’t parse something, meaning it’s useless for third-party content.
You could of course instead embed an actual web browser such as the JavaFX
WebView. However, such libraries are massive – tens of megabytes – and also platform-dependent since browser engines contain native code. CSSBox with all its required libraries is only 3 MB and cross-platform. So when I started porting MIME Browser from JavaFX to Swing and discovered the limitations of
JEditorPane, CSSBox turned out to be an ideal solution.
High DPI Scaling Issue
There is however one defect that only becomes apparent on high DPI screens with Java SE 9 or later. In that version AWT/Swing finally got automatic high DPI scaling, just like JavaFX or WPF. The problem? CSSBox renders to a
BufferedImage for display output – and this particular class does not distinguish between layout coordinates and screen pixels, which is the basis for automatic DPI scaling.
When drawing to a high DPI screen, layout coordinates are scaled so everything is the proper size, but actual drawing is performed with screen pixel precision so everything looks nice and sharp. When drawing to a
BufferedImage, layout and drawing coordinates are scaled, meaning you get a pixelated mess.
The screenshot below gives a sample at scaling factor 200% on Windows 10 – try reading the fine print in the last line. (Choose “View Image” or the like in your browser to get a full-size version that makes the defective scaling easier to see.)
To my knowledge there is no easy solution for this image scaling issue. One would need to do manual DPI scaling: enlarge the image by the current DPI scaling factor, multiply all drawing coordinates accordingly, and then scale the image back down for screen output. This is quite cumbersome, as well as memory-intensive and slow.
For my purposes a much simpler solution was to rip out the
BufferedImage rendering in class
BrowserCanvas and instead render directly to the screen by overriding
paintComponent as usual. The remaining code only needed a few supporting changes. You can download my creatively titled BrowserCanvas2 – it’s a bit too large to show here. The second screenshot shows the greatly improved rendering results.
I’ll send a bug report to the CSSBox project. My code is no general substitute for the existing
BrowserCanvas because rendering to image files is one of the project’s advertised features, and my changed code can no longer do that. So the engine would need two paths: rendering to the screen by default, and rendering to an image on demand. I’d rather leave the task of doing this properly to the project maintainer.