A considerable part of the new skinning layer of Substance is geared towards enabling writing Swing applications that have UI capabilities of this WPF application designed by frog studio (mentioned a few months ago on this blog):

The required changes have slowly sipped into releases 4.2 and 4.3 of Substance, but were limited due to maintaining as much backwards compatibility as possible. However, the old skinning / theming layer was not up to the challenge, especially considering its deficiencies in handling mixed light / dark skins. This layer has been completely rewritten in version 5.0 (currently under development) and it is now possible to use different skins for different top-level windows (such as frames and dialogs).

To specify a custom skin for the specific top-level window, use the SubstanceLookAndFeel.SKIN_PROPERTY client property and set it on the root pane of that window. To get the skin of the specific control (to provide custom painting that is consistent with how Substance paints core and third-party Swing components), use the SubstanceLookAndFeel.getCurrentSkin(Component) API.

Here is a screenshot that shows an application with twelve top-level frames, each using its own skin (click for the fullsize version):

Note that applications using a single global skin do not incur performance overhead. Applications that use per-window skins do not incur performance overhead as well, but the memory consumption will be higher due to a larger number of cached images.

You’re more than welcome to test the latest development drop of Substance 5 and report any bugs (visual or exceptions) to the project mailing lists, forums on in a private e-mail.

Effective Java2D

June 6th, 2008

This post summarizes the changes that were made in Substance 5 to address the performance issues raised by the users. As mentioned before (part 1 and part 2), Substance 5 is 2.5-3.5 times faster than Substance 4.3 on various static and dynamic scenarios. Many thanks go to Dmitri Trembovetski from Java2D team for his help and tips.

  1. Use multi-stop gradients (LinearGradientPaint) with REPEAT cycle method (as mentioned in the comments on Romain’s blog entry).
  2. Rendering translucent texts is slow and does not use the new native font rasterizer in 6u10. Solution – instead of installing a translucent composite, interpolate the text foreground color and the background fill color based on your alpha value, and use full opacity text rendering.
  3. BufferedImage.setRGB and BufferedImage.getRGB are really slow. A custom BufferedImageOp might be more difficult to learn, but is much more performant if done correctly.
  4. Set RenderingHints.KEY_ANTIALIASING to OFF before calling any Graphics.fill operation that results in aliased fill in any case. This is especially relevant for Graphics.fillRect that gets integer parameters. Java2D is not smart enough (yet) to choose the non-antialiased path when the end result is non-antialiased.
  5. Intermediate non-cached BufferedImages are slow. Whenever possible, either draw directly on the Graphics context, or collect the final result into one BufferedImage that goes into the cache, even if the cache key is more complex.
  6. Filling with translucent color or filling under translucent composite is very expensive. In fact, the single largest performance gain (20% of the final result) in Substance 5 was removing watermarks from most core skins.
  7. Use AffineTransform for rotating painting instead of doing it manually. As with BufferedImageOp, it takes some time to understand how to do it (and i’m still terrible at it), but the performance is much better.
  8. Use EnumSet and EnumMap whenever possible. This is not Java2D-specific, and the tip goes to Joshua Bloch. These are quite faster than Hash* counterparts.
  9. Do not do multiplt rendering of the same surfaces. This is especially relevant for tables thatcan have potentially thousands of visible cells on the screen. Try to draw background fills and gradients once per table.
  10. Last, and not specific to Java2D – profile every scenario, question every method and every line of code.

More tips on Java2D performance right here.

Update: hitting “Submit” too fast, i forgot another Swing-specific optimization. Since everything UI-relates has to run on EDT, you can use non-synchronized non-thread safe code and collections. This comes in quite handy coupled with caching images and additional otherwise guarded blocks.

As i was looking at the directions to a store on Google maps, i noticed that they’ve added a new functionality to click on each route turn point and see the “street view” shots. Here is how one of the exits off highway 87 looks on Google:

CA 87 exit C1

and if you manage to find your way through the parking lot, you’ll just need to drive through another house to get to Santa Teresa:

CA 87 exit C1

Reminds me of an episode in “The Office” where the boss drove the car into the lake a couple of yards before the bridge, just because the GPS lady told him to :)

Update: deciding to go a little bit further to Santa Teresa, Google would like you to go against the traffic:

Santa Teresa fast and furious

and once you make it to the intersection, turn on red:

Santa Teresa fast and furious

Here are some Swing links that you might have missed during this week:

  • Chrigel dives into SwingBuilder and MigLayout to create a GUI application for testing JCR query functionality.
  • On a related subject, Jacek Furmankiewicz has an article on using MigLayout for building Swing and SWT applications. There’s definitely a lot of interesting MigLayout recently, and Mikael is pushing hardto get it into the core JDK. I’m not really sure that it’s a good idea, especially given the mismatch in the pace of development and backwards compatibility. Perhaps it would be better to concentrate on tight integration with visual builders such as JFormDesigner, Matisse and Instantiations.
  • Thomas Kunneth compares the two Swing binding frameworks, JGoodies Binding and Beans Binding (dormant RI of JSR 295).
  • ???????? ????? ????????Artem Ananiev kicks off the series of posts on JWebPane component, WebKit-based lightweight Swing component for displaying and interacting with”street” HTML content. There is an unexpected twist – it is going to use the current look-and-feel to render the HTML form elements.
  • Maxim Zakharenkov summarizes his JavaOne BoF session on the SwingExplorer project and has a link to the presentation slides (PDF warning).
  • Jacek Furmankiewicz is busy at work augmenting the Java SwingBuilder with support for scroll panes, borders and icons.
  • And finally, Christophe Le Besnerais shows how to use a custom popup factory, some Java2D code and HTML to display richer multiline tooltips inspired by the Office 2007 Super Tooltips.