<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Chris Campbell&apos;s Blog</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/" />
<modified>2008-02-01T10:35:43Z</modified>
<tagline></tagline>
<id>tag:weblogs.java.net,2008:/blog/campbell/55</id>
<generator url="http://www.movabletype.org/" version="3.01D">Movable Type</generator>
<copyright>Copyright (c) 2008, campbell</copyright>
<entry>
<title>Effectuation: The Intro</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2008/02/effectuation_th.html" />
<modified>2008-02-01T10:35:43Z</modified>
<issued>2008-02-01T10:32:42Z</issued>
<id>tag:weblogs.java.net,2008:/blog/campbell/55.9107</id>
<created>2008-02-01T10:32:42Z</created>
<summary type="text/plain">Introducing a new framework for GPU-accelerated effects... Web Start demo included...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
For the past few months, I've been involved with various aspects of <a href="https://scenegraph.dev.java.net">Project Scene Graph</a> and the <a href="https://openjfx.dev.java.net/">JavaFX Script</a> runtime libraries.  <a href="http://weblogs.java.net/blog/hansmuller/">Hans</a> has already <a href="http://weblogs.java.net/blog/hansmuller/archive/2008/01/introducing_the.html">introduced the core elements</a> of the scenegraph package, and <a href="http://weblogs.java.net/blog/chet/">Chet</a> has donned his Groucho mask to <a href="http://weblogs.java.net/blog/chet/archive/2008/01/been_there_scen.html">explain the animation package</a> in great detail (<a href="http://www.youtube.com/watch?v=RbyzTI0M8eo">three chairs</a> for that!).
</p>
<p>
Today I'm finally going to talk about the third major component of the overall Scene Graph project, and that is the <a href="https://scenegraph-effects.dev.java.net">Effects Framework</a>.  If you've been wondering why I've been quiet lately, this is the reason.
</p>
<p>
Our team has already had <a href="http://weblogs.java.net/blog/campbell/archive/2007/04/faster_java_2d.html">plenty of experience</a> in delivering GPU-accelerated imaging operations.  Now we've taken it to the next level, by offering a long list of effects commonly used by designers, packaging them up into an easy-to-use API, and providing a sophisticated implementation that can take advantage of GPU acceleration (and later, SIMD instructions on the CPU) for blazingly fast performance.
</p>
<p>
All of this integrates seamlessly with the scenegraph and animation packages, and soon will be exposed just as pleasantly through the JavaFX Script runtime APIs.  You can even take advantage of the Effects Framework in existing Swing and Java 2D applications.
</p>
<p>
Anyway, enough yapping; let's move on to the introductory demo... This application demonstrates just a few of the effects available in the new API.  I'll let it speak for itself.  (Requires <a href="http://java.com">Java SE 6</a> or above.)
</p>
<br>
<p>
<center>
<img alt="intro.png" src="http://weblogs.java.net/blog/campbell/archive/images/intro.png" width="548" height="453" border="0"/>
</center>
<br>
<p>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="http://download.java.net/javadesktop/scenario/effects/demos/Intro.jnlp">
<img alt="webstart.small2.gif" src="http://weblogs.java.net/blog/campbell/archive/images/webstart.small2.gif" width="88" height="34" border="0" align="top"/>
</a>
    &nbsp;&nbsp;
  With default options -- will take advantage of the
  Direct3D-based backend (if possible*) on Windows...
<br><br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="http://download.java.net/javadesktop/scenario/effects/demos/Intro-OGL.jnlp">
<img alt="webstart.small2.gif" src="http://weblogs.java.net/blog/campbell/archive/images/webstart.small2.gif" width="88" height="34" border="0" align="top"/>
</a>
    &nbsp;&nbsp;
  With OpenGL backend enabled -- for Windows, Linux, and Solaris (if possible*);
  Mac OS X coming soon...
<br><br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="http://download.java.net/javadesktop/scenario/effects/demos/Intro-NoGPU.jnlp">
 <img alt="webstart.small2.gif" src="http://weblogs.java.net/blog/campbell/archive/images/webstart.small2.gif" width="88" height="34" border="0" align="top"/>
</a>
    &nbsp;&nbsp;
  With all GPU-acceleration disabled -- try this if you have problems with
  one of the above.
</p>
<p>
<i>
    (*) GPU acceleration requires the latest build of
    <a href="https://jdk6.dev.java.net/6uNea.html">JDK 6uN</a>, a
    compatible graphics card, and up-to-date graphics drivers.  If
    GPU acceleration cannot be enabled for any reason, the framework
    will automatically fall back on the software-based implementation.
    Yes, the software-based backend is much slower than it should be;
    we're working on that.
</i>
</p>
<br>
<p>
These projects are still in the early stages, but over the next few weeks, I'll have much more to say about (and more demos to share from) the Effects Framework and the Scene Graph project at large, so stay tuned.  In the meantime, take a gander at the <a href="http://download.java.net/javadesktop/scenario/releases/0.4.9/javadoc/">JavaDocs</a> and let us know what you think.  Hans should have news shortly of an 0.5 release that includes all of this and more.
</p>
<br>
<br>
<p>
In my ears: Enon, "High Society"
<br>
In my eyes: Found Magazine #3
</p>]]>

</content>
</entry>
<entry>
<title>Faster Java 2D Via Shaders</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/04/faster_java_2d.html" />
<modified>2007-04-08T18:48:47Z</modified>
<issued>2007-04-08T03:58:18Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6775</id>
<created>2007-04-08T03:58:18Z</created>
<summary type="text/plain">More performance improvements in Java 2D&apos;s OpenGL backend... Lots of pretty bar charts included...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
We've been doing a lot of work over the past couple years to accelerate many complex Java 2D operations on the GPU via OpenGL fragment shaders.  (Fragment shaders are little programs that operate on each pixel being rendered on the screen; they're infinitely more flexible than the fixed functionality that's historically been available in OpenGL.)  The sky's the limit when it comes to the kind of effects one can achieve by writing shader programs.
</p>
<p>
The first GPUs with fully programmable shader support were made available from Nvidia and ATI in 2002.  It took a couple years for the new hardware to penetrate into the consumer market, but now shader-capable GPUs are extremely prevalent (thanks in part to the hefty graphical requirements of Mac OS X and Windows Vista), so much so that we can reliably take advantage of shaders to accelerate complex Java 2D operations.  Even those first-generation boards are capable of providing huge performance gains, and each new generation of hardware seems to give an order of magnitude improvement over the last.  This should be quite evident from the charts that follow.  While CPU speeds seem to be nearing an asymptote, GPU performance continues to rocket, and now Java 2D is able to benefit from that power.  Not only does this mean improved performance for your Swing or Java 2D application, but also reduced CPU consumption, thus freeing up your CPU to crunch on application logic rather than getting bogged down with rendering tasks.
</p>
<p>
<i>
[This is one of those blog entries that could be novel length, but no one would actually read the words, because there are too many pretty bar charts to distract the reader.  Blah blah blah, words words words.  See?  No one's reading.  So let's skip the prose and get on with it... Oh, but first, I have to tell you how to read these charts.  I generated these numbers on a couple different machines, using J2DBench on Windows XP with the latest graphics drivers (ATI Catalyst 7.3 and Nvidia 93.71).  Since the machines vary slightly in processor performance and bus speed (the GeForce 7800 is a PCI-E board, the rest are AGP), I decided to use our software pipeline as a baseline, and then compare the OGL pipeline numbers to that baseline.  For example, if you see a result that lines up with the number 2000, it means that test is 2000% of baseline, or in other words, it is about 20 times faster on the GPU than on the CPU.  Your mileage may vary, but the big takeaway is that most operations are many times faster when executed on the GPU...]
</i>
</p>
<br>

<font size="+1">Text Rendering</font>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6274813">6274813</a>: Available in JDK 6)
<br>

<p>
<b>LCD-Optimized Text</b><br>
I already discussed this a bit in a <a href="http://weblogs.java.net/blog/campbell/archive/2006/04/five_easy_piece.html">blog entry</a> from about a year ago.  Since then, we've enabled this by default in JDK 7 (and soon in a JDK 6 update) when the OGL pipeline is enabled.  It's cool to see how software performance improves little over time, but each new generation of GPUs brings big performance improvements.
<center>
<img alt="lcdtext.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/lcdtext.png" width="513" height="386" />
</center>
</p>
<br>

<font size="+1">BufferedImageOps</font>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id= 6514990">6514990</a>: Available in JDK 7 b08)
<br>

<p>
<b>ConvolveOp</b><br>
<code>ConvolveOp</code> is commonly used for modern UI effects such as blurs and drop shadows.  Due to limitations in first-generation shader-level hardware, we are currently only accelerating <code>ConvolveOp</code> for 3x3 and 5x5 sized <code>Kernels</code>.  These are fairly common kernel sizes, but most drop shadow and glow effects require larger kernels, so we are working to loosen these restrictions and accelerate a wider range of kernel sizes.
<center>
<img alt="convolve.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/convolve.png" width="557" height="380" />
</center>
</p>

<p>
<b>LookupOp</b><br>
<code>LookupOp</code> is often used to perform simple brightness and contrast adjustments on images.  To simplify our code, we are currently only accelerating <code>LookupOp</code> for <code>ByteLookupTables</code> and <code>ShortLookupTables</code> with a maximum length of 256 elements, and for 1-, 3-, and 4-band sRGB images only.
<center>
<img alt="lookup.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/lookup.png" width="522" height="361" />
</center>
</p>

<p>
<b>RescaleOp</b><br>
<code>RescaleOp</code> is basically a degenerate case of <code>LookupOp</code> that can be accelerated very efficiently in shaders; after all, it's just a multiply and an add.  We are currently accelerating <code>RescaleOp</code> for 1-, 3-, and 4-band sRGB images only.
<center>
<img alt="rescale.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/rescale.png" width="537" height="393" />
</center>
</p>
<br>

<font size="+1">Multi-stop Gradient Paints</font>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6521533">6521533</a>: Available in JDK 7 b10)
<br>

<p>
<b>LinearGradientPaint</b><br>
For 2-stop linear gradients (<code>NO_CYCLE</code> or <code>REFLECT</code>), we can delegate to our existing <code>GradientPaint</code> codepath, which is already ridiculously fast via OpenGL's fixed functionality.  For all other linear gradients (for all <code>CycleMethods</code> and <code>ColorSpaceTypes</code>, up to a maximum of 12 color stops), we can accelerate the operation using shaders, for both antialiased and non-antialiased rendering.
<center>
<img alt="linear.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/linear.png" width="527" height="372" />
</center>
</p>

<p>
<b>RadialGradientPaint</b><br>
The same restrictions for linear gradients also apply to radial gradients (maximum of 12 color stops, etc).  For gradients with more than 12 stops, we simply fall back on our existing software routines.
<center>
<img alt="radial.png" src="http://weblogs.java.net/blog/campbell/archive/images/shaders/radial.png" width="519" height="365" />
</center>
</p>
<br>

<font size="+1">Extended Composite Modes</font>
(Bugs <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6531647">6531647</a>, <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5094232">5094232</a>: On the way)
<br>

<p>
<b>Antialiased Painting (with Non-SrcOver AlphaComposite)</b><br>
Historically the OGL pipeline has been able to accelerate the compositing step of an antialiased painting operation only when <code>AlphaComposite.SrcOver</code> (or <code>AlphaComposite.Src</code>, if the paint is opaque) due to the math involved.  (This is described in the quasi-official <a href="http://today.java.net/pub/a/today/2004/11/12/graphics2d.html">guide to the OpenGL-based Java 2D pipeline</a>, but that document could use a refresh for JDK 6 and beyond.)  But now with shaders we're able to accelerate antialiased rendering for any arbitrary AlphaComposite mode.
</p>

<p>
<b>Coming Soon: PhotoComposite</b><br>
It's not officially approved (or integrated) yet, but I've been working on adding more blending modes to Java 2D, in addition to those already provided by <code>AlphaComposite</code>.  Many of these modes come from traditional photography techniques, thus the name <code>"PhotoComposite"</code>.  Some modes are simple (Add, Multiply) and can be accelerated easily using OpenGL's built-in blending rules, others are more involved (ColorBurn, SoftLight) and benefit greatly from the use of shaders for efficient rendering.
</p>
<br>

<font size="+1">What's Next?</font>
<p>
There are plenty more optimizations that can be made to common Java 2D operations by leveraging shader technology; we'll keep working on this.  Also, there have been <a href="http://forums.java.net/jive/thread.jspa?threadID=23376&tstart=0">some discussion</a> on the interest list recently about the use of shaders in Java 2D.  Some folks would like to be able to write arbitrary shaders and have them work on Java 2D content.  I think it would be hard to come up with a general solution (in the public API) to make this work everywhere, and would shift an unreasonable burden to Java 2D (which is designed with WORA in mind).
</p>
<p>
However, I do recognize that it would be great if it were easy for developers to make use of shaders in their applications (as Romain <a href="http://www.curious-creature.org/2007/02/20/fast-image-processing-with-jogl">has demonstrated</a>) without getting bogged down in the OpenGL/GLSL learning curve.  To that extent, I've been working on a few utility classes for JOGL in the vein of <a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/TextureIO.html">TextureIO</a> and related classes.  This is another way to make the transition easier for existing Swing developers to leverage JOGL in their applications.  More on that in a future blog entry.
</p>
<p>
Finally, it's worth mentioning that all the shader-based optimizations I've described above are currently only available for the OpenGL-based Java 2D pipeline, but that will soon change.  For JDK 7 (maybe sooner?), we have a newly redesigned Direct3D-9-based pipeline in the works that will share much of the architecture (and code) of the OpenGL-based pipeline.  We fully expect that all of these shader-based optimizations will be available for most Windows users in the near future.  Stay tuned.
</p>
<br>
<br>
<p>
In my ears: Panda Bear, "Person Pitch"
<br>
In my eyes: JPG, Issue 9
</p>]]>

</content>
</entry>
<entry>
<title>Java 2D Trickery: Antialiased Image Transforms</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/03/java_2d_tricker_1.html" />
<modified>2007-03-11T00:31:35Z</modified>
<issued>2007-03-11T00:31:30Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6786</id>
<created>2007-03-11T00:31:30Z</created>
<summary type="text/plain">The third installment in a series of Java 2D tips-and-tricks.</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<i>
Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty <a href="http://weblogs.java.net/blog/zixle/archive/2006/07/beanshell_2d_in.html">Interactive Graphics Editor</a>.  Just cut and paste the code into that application, et voila: instant gratification.  This allows you to tinker with the code and immediately see how your changes affect the rendering.
</i>
</p>
<p>
It's been a while since I posted a "Trickery" blog (previous installments in this series include <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html">"Soft Clipping"</a> and <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker_2.html">"Light and Shadow"</a>).  This week at the <a href="http://www.desktopmatters.com/">Desktop Matters</a> conference (which was great, by the way) someone asked if there was a way to antialias the edges of an image when rotating it in Java 2D.  The kind gentleman noted that on Mac OS X with Apple's JDK, they do see antialiased edges if they enable <code>RenderingHints.VALUE_ANTIALIAS_ON</code>, but they don't see the same behavior on Sun's JDK.  The reason for that is Quartz: as I mentioned in the "Soft Clipping" entry, Apple's Java 2D implementation uses Quartz under the hood, which does antialias image edges in this particular case.  (But as I mentioned there as well, Apple is moving away from their Quartz renderer by default in their JDK 6 implementation, so it would be nice if there was a solution for all platforms.)
</p>
<p>
It is true that Sun's Java 2D implementation does not automatically antialias image edges when rendering with <code>Graphics.drawImage()</code>.  However, there is a simple workaround: use <code>TexturePaint</code> and render a transformed/antialiased <code>fillRect()</code>.  The following code demonstrates this technique:
</p>
<pre>
<code>
import java.awt.geom.*;
import java.awt.image.*;

// Clear the background to black
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);

// Create the source image
BufferedImage srcImage =
    new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = srcImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, 50, 50);
g2.setColor(Color.YELLOW);
g2.fillOval(5, 5, 40, 40);
g2.setColor(Color.BLACK);
g2.fillOval(15, 15, 5, 5);
g2.fillOval(30, 15, 5, 5);
g2.drawOval(20, 30, 10, 7);
g2.dispose();

// Render the image untransformed
g.drawImage(srcImage, 15, 7, null);
g.setColor(Color.WHITE);
g.drawString("Untransformed", 80, 25);

// Render the image rotated (with NEAREST_NEIGHBOR)
AffineTransform xform = new AffineTransform();
xform.setToIdentity();
xform.translate(15, 70);
xform.rotate(Math.PI/8, 25, 25);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                   RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g.drawImage(srcImage, xform, null);
g.setColor(Color.WHITE);
g.drawString("Nearest Neighbor", 80, 85);

// Render the image rotated (with BILINEAR)
xform.setToIdentity();
xform.translate(15, 130);
xform.rotate(Math.PI/8, 25, 25);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                   RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(srcImage, xform, null);
g.setColor(Color.WHITE);
g.drawString("Bilinear", 80, 145);

// Render the image rotated (with BILINEAR and antialiased edges)
g.setColor(Color.WHITE);
g.drawString("Bilinear, Antialiased", 80, 205);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                   RenderingHints.VALUE_ANTIALIAS_ON);
g.setPaint(new TexturePaint(srcImage,
    new Rectangle2D.Float(0, 0, srcImage.getWidth(), srcImage.getHeight())));
xform.setToIdentity();
xform.translate(15, 190);
xform.rotate(Math.PI/8, srcImage.getWidth()/2, srcImage.getHeight()/2);
g.transform(xform);
g.fillRect(0, 0, srcImage.getWidth(), srcImage.getHeight());
</code>
</pre>
<p>
Here's the resulting screenshot showing the different options:
<br>
<center>
<img alt="xformaa.png" src="http://weblogs.java.net/blog/campbell/archive/images/xformaa.png" width="226" height="257" />
</center>
</p>
<p>
Note that there will likely be some performance hit from transforming the image in this manner, but if quality is of utmost importance (as it was in this developer's case), then the cost is probably acceptable.  Hope this helps!
</p>
<br>
<br>
<p>
In my ears: The Fall, "Perverted By Language"
<br>
In my eyes: Yoshio Tsuchiya, "The Fine Art Of Japanese Food Arrangement"
</p>]]>

</content>
</entry>
<entry>
<title>Swing and GTK: What a LAF!</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/02/swing_and_gtk_w_1.html" />
<modified>2007-02-23T04:18:08Z</modified>
<issued>2007-02-23T04:17:47Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6663</id>
<created>2007-02-23T04:17:47Z</created>
<summary type="text/plain">On improvements to Swing&apos;s GTK L&amp;F in JDK 6uX and JDK 7... Screenshots included...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<i>
[If it's not readily apparent, I wrote this blog entry months ago because I was waiting around for the bug fixes described here to make it into JDK 7.  So just as a brief diversion from your day, pretend for a few moments that you've traveled back to the distant past, specifically the trail end of the year 2006...]
</i>
</p>

<br>
<p>
<b>How I Spent My Summer</b>
<br>
The big problem with my job at Sun is that I often simultaneously have ten different toes dipped into ten different puddles.  This past spring I made one final splash in my primary puddle, the OpenGL-based Java 2D pipeline, to fix the remaining big ticket items and make it as solid as possible for the JDK 6 release.  By and large those goals were met (for more info, go <a href="http://weblogs.java.net/blog/campbell/archive/2005/03/strcrazy_improv_1.html">crazy</a>, go <a href="http://weblogs.java.net/blog/campbell/archive/2005/07/strcrazier_perf.html">crazier</a>, or um, go <a href="http://weblogs.java.net/blog/campbell/archive/2007/01/java_2d_and_jog.html">more crazier</a>), but along the way I experienced a bit of burnout.  After all, I'd been hacking on the OGL pipeline since late 2001 (and pondering it as early as 1999 as evidenced in this <a href="http://archives.java.sun.com/cgi-bin/wa?A2=ind9912&L=java2d-interest&F=&S=&P=967">posting</a> by some clever, dare I say dashing, intern) so it's surprising that the burnout didn't happen sooner.
</p>
<p>
Anyway, with JDK 6 in a frozen state and summer rapidly approaching, I figured that it would be a good time for a change, but (oh!), what to work on?  I started with a blank slate, but quickly found my toes overdipped.  Here's a partial list of my non-OGL dabblings over the last six or so months:
<ul>
<li>Finished implementing the new Java Plugin <a href="http://weblogs.java.net/blog/campbell/archive/2007/02/orange_box_new.html">startup animation</a> (check it out soon in <a href="http://jdk6.dev.java.net">JDK 6u1</a> and <a href="http://jdk7.dev.java.net">JDK 7</a>, with more tweaks to follow)
<li>Kicked off my "Trickery" blog series (<a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html">here</a> and <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker_2.html">here</a>) with some techniques used in the aforementioned animation work
<li>Toyed around with the idea of reimplementing our native rendering loops in pure Java code (yes, believe it or not there are advantages; definitely worth revisiting)
<li>Played with the SwingX <a href="http://swingx.dev.java.net">Painters API</a> and <a href="http://jogl.dev.java.net>JOGL</a>, trying to find tie-in opportunities with Chet's <a href="http://timingframework.dev.java.net">Timing Framework</a> (partial success documented in my <a href="http://weblogs.java.net/blog/campbell/archive/2006/10/easy_2d3d_mixin.html">PhotoCube blog</a>)
<li>Started investigating new icon-related APIs in Swing (for L&F provided icons and multi-res icons)
<li>Installed Ubuntu and quickly found that, yes indeed, Swing's GTK L&F could use some work (despite the big improvements already seen in JDK 6 in that area)
</ul>
</p>
<p>
This list serves dual purposes.  First, it's a pathetic attempt to prove to my manager that I did accomplish something this summer besides, um, building an Adirondack chair and paddling around <a href="http://www.flickr.com/photos/chrispcampbell/350061392/">Shook's Pond</a>.  More relevantly, it demonstrates that I have issues with focusing on one concrete project.  However, the one item that showed the most potential (and had well-defined constraints) was the set of GTK L&F deficiencies.  Ubuntu wasn't a tier-one testing platform for us in JDK 6 (something I hope will change for JDK 7), and it turns out that Ubuntu's 6.06 release introduced a new GTK engine (ubuntulooks) and theme (Human).  The ubuntulooks engine is different enough from the clearlooks engine (from which it was derived) to warrant a close look, and it would require a number of special fixes to make Swing's GTK L&F look great on that distro.
</p>
<p>
Another reason to focus on a concrete project like the GTK L&F is that there's been an effort underway for some time by the NetBeans team to enable the GTK L&F by default on Linux and Solaris, just as Mac OS X and Windows use the platform L&F by default.  After all, if Sun doesn't set an example by enabling the platform L&F in all of our desktop-focused software, how can we expect developers to do the same in their apps?  Again, despite all the major improvements to Swing's GTK L&F in JDK 6, there were a few issues that slipped through the cracks, and we wanted to make sure those are addressed soon (ideally in the upcoming JDK 6 update releases).  Expect to see NetBeans make this switch in their 6.0 release (or thereabouts) in Spring 2007.
</p>
<p>
<i>
[Update: The NetBeans folks just this week flipped the switch in NetBeans 6.0 M7 so that the GTK L&F is now enabled by default on Solaris and Linux (on JDK 6u1 and above).  Check out the <a href="http://wiki.netbeans.org/wiki/view/NewAndNoteWorthyMilestone7#section-NewAndNoteWorthyMilestone7-NativeGTKLFEnabledByDefault">"new and noteworthy"</a> page for a few sample screenshots and more information.  To get things looking good in time for the NetBeans 6.0 release, a lot of energy was invested by the NetBeans, Solaris, and Swing teams.  Thanks guys!]
</i>
</p>

<br>
<p>
<b>Before and After Science</b>
<br>
All right, all right, enough words already.  As the saying (rarely) goes, a screenshot's worth a thousand words, so it's time for some before-and-after shots (click to enlarge):
</p>
<center>
<a href="http://weblogs.java.net/blog/campbell/archive/images/twf_native.png">
<img alt="twf_native.png" src="http://weblogs.java.net/blog/campbell/archive/images/twf_native.png" width="432" height="314" /></a>
<br>
<i>Fig. 1 -- Native "twf" demo application.</i>
<br><br>
<a href="http://weblogs.java.net/blog/campbell/archive/images/twf_java_6.png">
<img alt="twf_java_6.png" src="http://weblogs.java.net/blog/campbell/archive/images/twf_java_6.png" width="432" height="280" /></a>
<br>
<i>Fig. 2 -- Java/Swing mockup of "twf", courtesy of <a href="http://elliotth.blogspot.com/2006/04/gtk-laf-in-java-6.html">Elliott Hughes</a>, running on JDK 6.</i>
<br><br>
<a href="http://weblogs.java.net/blog/campbell/archive/images/twf_java_7.png">
<img alt="twf_java_7.png" src="http://weblogs.java.net/blog/campbell/archive/images/twf_java_7.png" width="413" height="274" /></a>
<br>
<i>Fig. 3 -- Same as above, but running on JDK 7-b08; can you spot the 6 (or 25) differences?</i>
</center>
<p>
These particular screenshots were taken on an Ubuntu 6.06 system with the default Human theme, but similar improvements can be seen on many other GTK themes such as Nimbus (the new default on Solaris), Clearlooks (the most popular on various Linux distros), and so on.  In total, over 30 GTK-specific bugs have been fixed so far in JDK 7, and there are plenty more fixes on the way.  For more details on these bug fixes, refer to <a href="http://weblogs.java.net/blog/campbell/archive/gtk/gtkfixes.html">this list</a>.  As you can probably see from Figure 3, there's still a bit more work to be done (e.g. table headers, non-editable comboboxes, tabs), but we're getting closer.
</p>

<br>
<p>
<b>Help Wanted</b>
<br>
Here's the thing about the GTK L&F... It's not rocket science.  Granted, some of the issues are tricky to fix, which is why it's taken quite a while to get it to where it is today.  It's not for lack of smarts, but rather a lack of time.  It can take a number of hours just to track down exactly why something is broken in the GTK L&F, and it can take up to a couple days to devise a robust and well-understood fix.
</p>
<p>
I hope these statements don't come across as whining.  The fact of the matter is that at Sun we have anywhere from 1.33 to 2.117 persons available to work on the GTK L&F at any given time.  Since time is the limiting factor, there's only so many fixes we can get in within a given year, maybe 50 tops.  But what if we took a page from the book of CMT and increased the number of threads crunching on these issues in parallel?  I think we could see some quick progress.
</p>
<p>
There are a number of people (you know who you are, <a href="http://elliotth.blogspot.com/">Elliott Hughes</a>; nudge nudge, Brian Harry; wink wink <a href="http://kennke.org/blog/">Roman Kennke</a>) who are actively interested in the success of the GTK L&F.  That's great, but I'd like to see more activity in this area, perhaps in addition to the aforementioned/illustrious names.  And not just in the form of an independent project.  We'd be happy to work closely with 1 or 2 (or 3) developers out there in the <a href="http://openjdk.dev.java.net">OpenJDK community</a>, collaborating on fixes, and so on.  Eventually it would be nice to see a couple folks in the community with the same level of expertise as we have in Kirill K. and Peter Z. (our resident GTK experts on the Swing team at Sun).
</p>
<p>
At the very least it would be a fun experiment as we move towards completely opening up the JDK library source code in the next few months.  As has been stated elsewhere, we still have a lot of work to do w.r.t. opening up our internal processes (bug evaluations, code reviews, etc) to the outside world, but I think it would help the transition if we had a few external folks get more involved with this process <b>now</b>.  Send me email if you'd like to get involved.  I can't promise you fame or fortune, but I can promise you a beer or two (*, **, ***, ****, *****) in return for your hard work.
</p>
<p>
* Valid only in the Bay Area, California, unless you want to fly me to your location.  (I'd gladly oblige, especially if you're located outside the U.S.)
<br>
** Under 21 receives <a href="http://www.flickr.com/photos/chrispcampbell/346356762/">R.C. Cola</a> or equivalent.
<br>
*** Pabst Blue Ribbon or equivalent only.
<br>
**** Must be happy hour or half-off equivalent.
<br>
***** You must buy me a beer in return, because that's the way the system works.
</p>

<br>
<br>
<p>
In my ears: Deerhoof, "Reveille" [digging through old favorites...]
<br>
In my eyes: Woody Allen, "Without Feathers"
</p>]]>

</content>
</entry>
<entry>
<title>Orange Box: New Java Plugin Animation</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/02/orange_box_new.html" />
<modified>2007-02-02T18:57:14Z</modified>
<issued>2007-02-02T18:54:51Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6463</id>
<created>2007-02-02T18:54:51Z</created>
<summary type="text/plain">On the snazzy new plugin sequence... Screenshots and a live demo included...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<i>
[Concision is often a difficult thing for me.  Everytime I write a blog entry I tell myself, "This one's a-gonna be a short 'un."  But it just never seems to work out that way.  Perhaps I'll succeed today.]
</i>
</p>
<p>
For the dozen or so folks that attended the User Experience BOF at JavaOne 2006, this is probably not news.  But if you're one of my (14 million) readers who did not attend that BOF, you may be interested to learn that we've revamped the quick little animation that users see when the Java Plugin is being initialized in the browser.  In the years prior to JDK 5, users saw little more than a gray box and a tiny coffee cup logo.  Besides being dull, there was no indication of applet startup progress; not exactly a brilliant user experience!
</p>
<p>
Fast forward to 2004 when a certain high-level-exec-turned-CEO decided it was time to improve that experience.  A short startup animation (with progress indicator) was proposed, and the general design was (somewhat unfortunately) handed down from above.  Our multi-talented visual designer, <a href="http://teef.org">Coleen Baik</a> <b>*</b>, and I were given only a couple weeks to churn out the final design and implementation (written purely in Java 2D, of course) in time for the impending JDK 5 release.  Thus was born the original "gray box animation," called as such despite the fact that it was now much more white than gray:
<center>
<img alt="graybox.png" src="http://weblogs.java.net/blog/campbell/archive/images/graybox.png" width="422" height="400" />
</center>
</p>
<p>
About a year later we were again asked to update the look of the animation, this time for the JDK 6 release.  Our initial reaction was one or more of:
<ul>
<li>"Are they bloody crazy?"
<li>"Didn't we just get finished with the first one?"
<li>"Has anyone even noticed the first one yet?"
</ul>
On the other hand, the old animation was already beginning to look a bit dated, so I think we were happy to give the design (and implementation) a much needed makeover.  Coleen's new designs were much more sleek and modern looking than the old gray box.  And this time they were predominantly bright orange.  (Hooray for Sun branding!)  The design we settled on looked fantastic, but it was also a bit of a fun challenge for me trying to convert her Photoshop blueprints into Java 2D-isms.  Fortunately around that time I had pushed to get <a href="http://weblogs.java.net/blog/campbell/archive/2006/04/five_easy_piece.html">LinearGradientPaint (and RadialGradientPaint)</a> included in the JDK, which turned out to be a lifesaver.  I also had to figure out how to achieve cheap, efficient drop shadows, glow effects, and soft clipping in Java 2D.  (The first two entries in my "Trickery" series on <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html">"Soft Clipping"</a> and <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker_2.html">"Light and Shadow"</a> might make a bit more sense now that you're clued into their origins.)  The sequencing of the progress bar and the subsequent fade-out implementation were also thankfully improved by Rita Fisher, resident Java Plugin expert.
</p>
<p>
<i>
[Concision, man, concision!  Enough yapping!  Show them some pictures, already!]
</i>
</p>
<p>
So without further ado, I present the new "orange box" Java Plugin startup animation...
<center>
<img alt="orangebox.png" src="http://weblogs.java.net/blog/campbell/archive/images/orangebox.png" width="363" height="299" />
<br>
<a href="http://download.java.net/javadesktop/blogs/campbell/2007.02.02/GrayBox2006.jnlp" style="border: 0px none #000000;">
<img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png">
</a>
</center>
</p>
<p>
The screenshot doesn't really do it justice, so I'd recommend trying the live demo (sandboxed; requires JDK 6) to see the fancy page flips, fades, and so on.  You can resize the window to see how the animation behaves at different sizes.  Note that the demo is derived from one of the final prototypes (before it was integrated into the JDK), so the behavior might differ slightly in the actual deployment scenario.  And before anyone asks, as always you can override this animation (instructions <a href="http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/special_attributes.html">here</a>)
with a static image of your choosing, such as a company logo, if desired.  Also, despite the fact that this animation looks significantly more complex than the old one, I'm happy to say that the new animation requires less CPU cycles than the old one; in both cases, we promise we're not slowing the applet startup process by displaying this animation (applet startup is usually I/O bound, and the animation requires very few compute cycles).
</p>
<p>
The new animation unfortunately missed the original JDK 6 release due to time constraints, but I'm glad to report that it's now available in early builds of <a href="http://jdk6.dev.java.net">JDK 6u1</a> and <a href="http://jdk7.dev.java.net">JDK 7</a>.  If you have either of those installed, try loading a large applet (the animation is usually only visible for larger applets that take a while to download) and let us know your thoughts.  Hope you enjoy the new look!
</p>
<p>
<b>*</b> ... who unfortunately is leaving Sun as of today... Why, Coleen, why?
</p>
<br>
<br>
<p>
In my ears: King Geedorah, "Take Me To Your Leader"
<br>
In my eyes: Woody Allen, "Side Effects" [a nice diversion from my ongoing battle with Faulkner...]
</p>]]>

</content>
</entry>
<entry>
<title>Java 2D and JOGL: The Flip Side</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/01/java_2d_and_jog.html" />
<modified>2007-01-23T20:30:52Z</modified>
<issued>2007-01-23T20:25:49Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6390</id>
<created>2007-01-23T20:25:49Z</created>
<summary type="text/plain">New convenience classes that help developers use Java 2D from within a JOGL application... Demo included: source code, webstart links, and all...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<b>The Hemingway Version</b>
<br>
<p>
In my last blog entry,
<a href="http://weblogs.java.net/blog/campbell/archive/2006/10/easy_2d3d_mixin.html">
Easy 2D/3D Mixing in Swing</a>, my goal was to show Swing developers how easy
it can be to include 3D content in a desktop application via <a href="http://jogl.dev.java.net">JOGL</a> and <a href="http://opengl.org">OpenGL</a>.
I think we've done a decent job of making things easier for that class of
developers, but what if we look at the problem from the other end of the
barrel?  There are lots of JOGL/OpenGL developers that want to include Java 2D
elements in their applications.  Historically it has been possible to include
Java 2D content in a JOGL application, but there haven't been any good
standard APIs to make this sort of integration convenient for developers.
Until now.
</p>
<p>
Let's get the demo out of the way before getting into any of the details.
Here's a screenshot (click to enlarge), for the truly impatient reader:
<center>
<a href="http://weblogs.java.net/blog/campbell/archive/images/ba3d.png" style="border: 0px none #000000;">
<img alt="ba3d.small.png" src="http://weblogs.java.net/blog/campbell/archive/images/ba3d.small.png" width="400" height="300" />
</a>
</center>
</p>
<p>
Better yet, run the demo yourself (the app itself is sandboxed and only
requires JDK 5; here's the <a href="http://download.java.net/javadesktop/blogs/campbell/2007.01.23/BezierAnim3D.zip">source code</a>, with NetBeans project included):
<center>
<a href="http://www.java.net/download/javadesktop/blogs/campbell/2007.01.23/BezierAnim3D.jnlp" style="border: 0px none #000000;">
<img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png">
</a>
</center>
</p>
<br>
<b>The Faulkner Version</b>
<br>
<p>
Ken Russell (the mastermind behind JOGL) promises me that he'll soon have a
blog of his own, which means I'll have to stop stealing all of his thunder.
In the meantime, let's look at some of the new convenience classes that
he's cooked up in the past few weeks (with some prodding from
<a href="http://blogs.sun.com/jag/">James Gosling</a>, and inspired by some
of the <a href="http://weblogs.java.net/blog/campbell/archive/2006/10/easy_2d3d_mixin.html#comments">
reader comments</a> from my last blog).
</p>

<p>
<b>
<a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/Texture.html">
Texture</a> and
<a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/TextureIO.html">
TextureIO</a>
</b>
<br>
These aren't new (they were added to Sun's JOGL implementation over 18
months ago), but it helps to mention them in the context of the newer
convenience classes.  The <code>Texture</code> class is a really nice
abstraction layer around an OpenGL texture object.  It makes it very easy
for developers to use non-power-of-two sized images in OpenGL (historically
this has been tricky for OpenGL developers) and provides simple methods
for enabling and binding texture state.  The <code>TextureIO</code> class
offers an extremely convenient API for loading image data from disk, the
network, or any other source into OpenGL texture memory.
(If you're into SAT-style analogies: <code>TextureIO</code> is to
<code>Texture</code> as <code>ImageIO</code>
is to <code>BufferedImage</code>.)  It even supports special
compressed texture formats, mipmapping, and other complex things that are
usually a nightmare for OpenGL developers.
</p>

<p>
<b><a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/j2d/TextureRenderer.html">
TextureRenderer</a></b>
<br>
The first of the three new convenience APIs found in the
<code>com.sun.opengl.util.j2d</code> package.  This class builds on top
of the <code>Texture</code> class described above and provides a convenient
way for developers to dynamically render into an OpenGL texture using
Java 2D.  From the following code snippet, it should be clear that you can
use a <code>TextureRenderer</code> instance just as you would a
<code>BufferedImage</code>:
<code>
<pre>
    // Create the TextureRenderer and render into it using Java 2D
    TextureRenderer renderer = TextureRenderer(w, h, true);
    Graphics2D g2 = renderer.createGraphics();
    g2.setColor(...);
    g2.fill(...);
    // and so on...
    g2.dispose();
    renderer.sync(0, 0, w, h);

    // Now use it as you would any other OpenGL texture
    Texture tex = renderer.getTexture();
    ...
</pre>
</code>
</p>
<p>
Note that currently the <code>TextureRenderer</code> class uses a
<code>BufferedImage</code> behind the scenes as backing store (but
that's just an implementation detail).  This means
that when you're rendering into a <code>TextureRenderer</code>, it
currently all goes through software routines.  However, Ken and
I have some tricks up our sleeves: if all goes well in the next few weeks,
we may have an alternate codepath that leverages the JOGL/Java 2D bridge,
which will mean that all rendering <i>into</i> the <code>TextureRenderer</code>
will be accelerated in hardware via the OpenGL-based Java 2D pipeline,
with no costly <code>BufferedImage-Texture</code> copy steps required.
This could be an exciting development, so stay tuned.
</p>

<p>
<b><a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/j2d/TextRenderer.html">
TextRenderer</a>
</b>
<br>
Since the beginning of time, rendering text in OpenGL applications has been a
huge hassle for developers.  There were some really hokey GLUT routines
that used ugly bitmap fonts with no support for antialiasing or non-Latin
text.  In the Java world, crafty developers using
<a href="http://jogl.dev.java.net">JOGL</a>
and <a href="http://lwjgl.org">LWJGL</a> have figured out custom ways to
leverage Java 2D's high-quality font rendering in their applications.  But
until this new <code>TextRenderer</code> class came along, (as far as I know)
there was no easy/standard way to get access to the high quality,
antialiased text offered by Java 2D.  It includes full Unicode support,
a really smart string/glyph caching algorithm, and clean APIs that allow
for both 2D and 3D rendering of text in a JOGL application (as you saw in
my demo above).  Under the hood, it takes advantage of the aforementioned
<code>TextureRenderer</code> and <code>Texture</code> classes.  Ken has
been <a href="http://www.javagaming.org/forums/index.php?topic=15634.0">bold
enough to declare</a> it "the last word in text rendering" for JOGL apps,
and I think he's right.  I can even imagine existing C-based OpenGL apps
being ported to Java and JOGL for this feature alone...
</p>

<p>
<b><a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/j2d/Overlay.html">
Overlay</a></b>
<br>
I didn't actually use this one in the above demo, but it's a really useful
and simple way to add a "heads-up display" to your JOGL application.
Imagine a flight simulator application: you could render the terrain and
all of your 3D content using JOGL, then you could use the new Overlay class
as a way to render the airplane's control panel using the high-quality
Java 2D APIs.  It's really just an even more convenient wrapper around
the already convenient <code>TextureRenderer</code> APIs.
</p>

<p>
To help explain how these new APIs fit together and how they layer on top
of OpenGL, I put together a pancake diagram showing how it all comes
together.
(I don't have my charting software handy, so the following,
might I add beautiful, ASCII art diagram will have to suffice.)
</p>
<p>
<pre>
       +----------------------------+
       | TextRenderer  |   Overlay  |
       |----------------------------|
       |      TextureRenderer   - - | - - ->  BufferedImage, Graphics2D
       |----------------------------|
       |          Texture       - - | - - ->  TextureIO, ImageIO
       |============================|
       |      OpenGL textures       |
       +----------------------------+
</pre>
</p>
<p>
That's all for now.  In my next entry I'll have some exciting performance numbers to share in the context of the OpenGL-based Java 2D pipeline (hint: hardware accelerated BufferedImageOps).
</p>
<br>
<br>
<p>
In my ears: Sloan, "Never Hear The End Of It" <code>*</code><br>
In my eyes: William Faulkner, "Absalom, Absalom!" <code>**</code>
</p>
<p>
<code>*</code> It's a bit long and wordy,
but I'm still just as much of a slobbering fan of theirs as I was in
high school...
<br>
<code>**</code>... But sometimes
"long and wordy" can be a virtue.
</p>]]>

</content>
</entry>
<entry>
<title>Is This Game Of Tag Over Yet?</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2007/01/is_this_game_of.html" />
<modified>2007-01-06T19:04:23Z</modified>
<issued>2007-01-05T22:32:07Z</issued>
<id>tag:weblogs.java.net,2007:/blog/campbell/55.6270</id>
<created>2007-01-05T22:32:07Z</created>
<summary type="text/plain">Unable to avoid the game of tag...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
Well, <a href="http://weblogs.java.net/blog/rbair/">Richard Bair</a> was kind enough to tag me, but I'm not sure if it was out of pity, or simply out of convenience (we work about 3.5 feet from each other).  I've been shocked by how prevalent this whole tag thing has been recently; I mean, doesn't it remind you of those lame chain emails circa 1996?  I told myself, "Self, if this tagging thing ever reaches you, you'd better not play along!  Those other bloggers are being so vain!  Remember your principles!"
</p>
<p>
But it's a new year (a time for resolutions), and I should probably resolve to stop resisting social phenomena just for the sake of resistance.  Then again, I usually resist making new year's resolutions as well, for all the same reasons.  (Late last year, <a href="http://weblogs.java.net/blog/chet/">Chet</a> and I summed up this philosophy as: "I'm sticking it to the man, but the man ain't listening.")
</p>
<p>
Anyway, that's it.  I give in.  Here are five things you may not know about me:
<ul>
<li><p>My two favorite things in the whole wide world: sheep that wear coats, and inverted umbrellas on windy/rainy day in Manhattan.</p></li>
<li><p>I'm the sole member (a <a href="http://music.hyperreal.org/artists/brian_eno/interviews/musn79.html#musician">
"non-musician"</a> of sorts [but to compare myself to Eno would be ludicrous]) of a number of bands, some real (<a href="http://labonnesoupe.org">La Bonne Soupe</a>), some less real (Shimmy, Burt Rido and the Texas Nachos).  The second  La Bonne Soupe album, "Literary Gentlemen," was released in November 2006 to worldwide accla... fanfa... umm, something.  You can listen to it in full <a href="http://www.bebo.com/grp/MusicAlbum.jsp?GrpAlbumId=2602925146">here</a> (not gapless, unfortunately) on the not-so-great-but-at-least-it-aint-myspace bebo.com...
</p></li>
<li><p>When I was 5, I wrote my first BASIC program on our Commodore 64.  It was something like a New York State information guide (yes, that was my patriotic year), with lots of menus and very little content.  When I was 14, I led a group of random folks in building a virtual reality amusement park (anyone remember REND386?).  Yes, that was one of many dorky years, but as you can see graphics programming is in my blood.  More on "dzzyland" <a href="http://www.ibiblio.org/pub/academic/computer-science/virtual-reality/rend386/worlds/wlds.txt">here</a>; it still runs, if you can track down all the pieces.
</p></li>
<li> <p>I'm afflicted by some really silly, non-debilitating medical conditions; for example:
<ul>
<li><a href="http://en.wikipedia.org/wiki/Raynaud's_phenomenon">Reynaud's syndrome</a> -- my left middle finger goes white when the temperature drops below 55 F; my right ring finger will follow suit below 50 F
<li><a href="http://en.wikipedia.org/wiki/Sleep_paralysis">Sleep paralysis</a> -- it comes and goes, but is most common when my sleep schedule is confused; this condition has been an endless source of amusement for my close friends
</ul> 
</p></li>
<li><p> If I could have lunch with anyone, it would probably be <a href="http://en.wikipedia.org/wiki/Woody_Allen">Woody Allen</a>.  If I could choose our waiter: <a href="http://en.wikipedia.org/wiki/Ricky_Gervais">Ricky Gervais</a>.
</p></li>
</ul>
</p>
<p>
Okay, that's that.  I still feel dirty about keeping this phenomenon alive, but I hope these colleagues of mine have more willpower than I do: <a href="http://weblogs.java.net/blog/shan_man/">Shannon</a>, <a href="http://weblogs.java.net/blog/alexfromsun/">Alex</a>, <a href="http://weblogs.java.net/blog/ixmal/">Artem</a>, and <a href="http://www.jroller.com/page/jazzy">Jasper</a>.
</p>
<br>
<p>
In my ears: Cluster, "Cluster '71"
<br>
In my eyes: William Faulkner, "Absalom, Absalom"
</p>]]>

</content>
</entry>
<entry>
<title>Easy 2D/3D Mixing in Swing</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/10/easy_2d3d_mixin.html" />
<modified>2006-10-12T20:47:32Z</modified>
<issued>2006-10-12T20:47:22Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.5716</id>
<created>2006-10-12T20:47:22Z</created>
<summary type="text/plain">How to use Swing, Java2D, JOGL, and Timing Framework together in your applications... Silly demo included: source code, webstart links, and all...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<b>When You're A Jet...</b>
</p>
<p>
A couple weeks back, I had the privilege of speaking to the Java Programming Club at Monta Vista High School in Cupertino, CA.  I'm still amazed at the turnout: about 25 students showed up, all with varying levels of experience with Java, and all apparently willing to endure my so-so demos on their lunch hour.  The thing that grabs me though is, if they have a <b>Java</b> club, does that imply that they have other similarly specialized programming clubs too?  Do the Ruby, Haskell, Java, and Lisp clubs all confront each other just outside school grounds when they have a score to settle, á la Sharks v. Jets?
</p>
<p>
Anyway, I'd like to thank their president, Anshul Bhagi, for inviting me.  It was fun!  I promised to post the (rather scattershot) <a href="http://weblogs.java.net/blog/campbell/archive/20060928_Monta_Vista.pdf">slides</a> from my talk, which mainly revolved around JDK 6 (the new SplashScreen API, 2D/3D mixing in Swing apps, how to get involved, etc).  I asked the students if anyone had tried out JDK 6 snapshots, and was surprised to find that none of them had.  All the more reason to pose a challenge to the students... By the end of this school year, I'd like to see at least two of them contribute fixes to the JDK 7 project.  I know we've had a number of contributions for JDK 6 from the university level, but none that I'm aware of at the high school level, so I think that would be pretty cool.
</p>
<br>
<b>It's A Bit Of A Pain</b>
<p>
To get the students interested in doing some basic 2D and 3D graphics programming, I showed a couple of existing 2D/3D mixing demos, like <a href="http://aerith.dev.java.net">Aerith</a>.  The great thing about demos like Aerith and its precursor <a href="http://www.jroller.com/page/gfx/?anchor=a_swing_opengl_photo_viewer">Twinkle</a> is that they're polished and they even behave like "real apps" (bells and whistles included), so ooh/aah factor is never an issue.  But of course, we all know that the road to real-app-hood often involves thousands of lines of code, so if you're trying to learn from their source code, it's often difficult to locate the essence of the demo.  Twinkle's cool and all, but the source code can be daunting to a newcomer (no fault of Romain's).
</p>
<p>
Quite frequently I hear from developers who are familiar with Swing and Java2D, but haven't the foggiest idea where to begin when it comes to using <a href="http://jogl.dev.java.net">JOGL</a> in their application.  It's especially difficult for developers who have no 3D graphics programming experience to be thrown into the world of OpenGL so abruptly.  This time around, I decided to develop my own demo from scratch (with only a few, sparse, documented classes) to help show how to use some complementary technologies in the same application:
<ul>
<li> <a href="http://weblogs.java.net/blog/campbell/archive/2005/09/java2djogl_inte_1.html">Mixing</a> Java2D and JOGL in a Swing application
<li> Using <a href="http://timingframework.dev.java.net">Chet's Timing Framework</a> (can we just start calling this CTF?) to control 2D and 3D elements
<li> Leveraging the <a href="http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/splashscreen/">new SplashScreen API</a> in JDK 6
</ul>
</p>
<p>
<a href="http://weblogs.java.net/blog/hansmuller/">Hans</a> thinks we're incapable of writing a 2D/3D demo that goes outside the realm of photo viewers, and you know what, he's probably right (at least for this week).  So, mea culpa, I wrote yet another photo-centric demo, but this time I stripped out all that pesky application logic.  All that's left is a minimal demo that I hope is easy to understand for beginners.  Here's a screenshot of "PhotoCube" (click to enlarge):
<center>
<a href="http://weblogs.java.net/blog/campbell/archive/images/photocube.large.png" style="border: 0px none #000000;">
<img alt="photocube.small.jpg" src="http://weblogs.java.net/blog/campbell/archive/images/photocube.small.jpg" width="500" height="405" />
</a>
</center>
</p>

<p>
Or, why not run it yourself (the app itself is unsigned and requires <a href="http://download.java.net/jdk6/binaries/">JDK 6</a>):
<center>
<table width="100%" border="0">
<tr>
<td width="50%">
<center>
<a href="http://www.java.net/download/javadesktop/blogs/campbell/2006.10.12/PhotoCube-OGL.jnlp" style="border: 0px none #000000;"><img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png"></a>
</center>
</td>
<td width="50%">
<center>
<a href="http://www.java.net/download/javadesktop/blogs/campbell/2006.10.12/PhotoCube-NoOGL.jnlp" style="border: 0px none #000000;"><img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png"></a>
</center>
</td>
</tr>
<tr>
<td width="50%">
<center>
With OpenGL-based Java2D pipeline <b>enabled</b>
<br>(should be faster than the other option)
</center>
</td>
<td width="50%">
<center>
With OpenGL-based Java2D pipeline <b>disabled</b>
<br> (useful for comparing performance between the two,
<br>or if you have trouble with the first link)
</center>
</td>
</tr>
</table>
</center>
</p>

<p>
And finally, here's the <a href="http://weblogs.java.net/blog/campbell/archive/PhotoCube.zip">source code</a> (NetBeans project included).
</p>
<p>
The core functionality can be found in the DemoPanel class.  The timingframework-specific code is isolated to the <code>DemoPanel.initTimers()</code> method.  You'll note that I've demonstrated a couple different ways to use the timingframework API to animate various rendering elements, some simple and some complex.  It's unfortunate that the code is so verbose; it's certainly better than doing it by hand, but there's still plenty of room for simplifying the API.  Chet and others are looking into ways to reduce the amount of code needed to write common animations, and some tools support is possible, so I would expect this to become much simpler in the near future.
</p>
<p>
(As an aside, one thing I'd like to see is something like a RepaintingObjectModifier, because so often in Swing applications all you want to say is, for example, "animate the location property of this JComponent from here to there, and call repaint() upon each timing event".  Right now you have to override ObjectModifier or TimingTarget to get this common behavior, which just adds to the verbosity.)
</p>
<p>
The 2D/3D mixing code is also in that class, look for the <code>render2DBackground()</code>, <code>render3DScene</code>, and <code>render2DForeground()</code> methods.  This code is illustrating how you can override those 3 or 4 methods provided by the CompositeGLJPanel class (also included in the source code) to easily include both Java2D and JOGL rendering elements in your user interface.  I'd really like to see something like CompositeGLJPanel included as a convenience class in one of the JOGL utility packages; GLJPanel itself can be really scary beast to someone just learning this stuff for the first time.  CompositeGLJPanel lowers the barrier a bit and handles a lot of the common boilerplate code needed by simple applications.  Let me know if you have any suggestions or ideas for improvement.
</p>
<p>
Finally, check out the PhotoCube class, where I demonstrate the nifty <a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/TextureIO.html">TextureIO</a> utility classes.  (They're not part of the official JSR-231 spec, but rather are part of the com.sun.opengl.* packages that ship with the JOGL 1.0.0 distribution.)  These classes work just like my other favorite API, Image I/O, and really make it easy to load an image from disk (or any other location) into an OpenGL texture.  From there, you can use the <a href="http://download.java.net/media/jogl/builds/nightly/javadoc_public/com/sun/opengl/util/texture/Texture.html">Texture</a> class, a simple wrapper object for OpenGL textures, which again provides an easier and slightly more object-oriented approach to dealing with OpenGL (a decidedly non-OO library).  Enjoy...
</p>

<p>
Okay, I swear, I'm really done now, once again proving that I'm incapable of short-and-sweet...
</p>

<br><br>
<p>
In my ears: Faust, "IV"
<br>
In my eyes: Kenzaburo Oe, "The Silent Cry"
</p>]]>

</content>
</entry>
<entry>
<title>Java 2D Trickery: Light and Shadow</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker_2.html" />
<modified>2006-07-28T00:21:46Z</modified>
<issued>2006-07-28T00:20:44Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.5263</id>
<created>2006-07-28T00:20:44Z</created>
<summary type="text/plain">The second installment in a series of Java 2D tips-and-tricks demonstrating an approach to adding light (and shadow) to your shapes.</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<i>
Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty <a href="http://weblogs.java.net/blog/zixle/archive/2006/07/beanshell_2d_in.html">Interactive Graphics Editor</a>.  Just cut and paste the code into that application, et voila: instant gratification.  This allows you to tinker with the code and immediately see how your changes affect the rendering.
</i>
</p>
<p>
In the <a href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html">first installment</a> of my "Trickery" series, I demonstrated a technique for achieving a soft clipping effect.  Now let's put it to good use.  In this installment I'll show how to add a lighting effect to give your otherwise flat shapes a 3D-ish appearance.
</p>
<p>
If you like your literature illustrated, perhaps a picture will help.  I'll show you how to go from the boring, flat shape on the left to the slightly less boring, glossy shape on the right:
</p>

<center>
<img alt="Flat Shape" src="http://weblogs.java.net/blog/campbell/archive/images/flat.png" width="195" height="175" />
<img alt="Glowing Shape" src="http://weblogs.java.net/blog/campbell/archive/images/glow.png" width="194" height="173" />
</center>

<p>
With the right colors, you can use this technique to simulate a colored light shining across your shape, producing a subtle glow.  How do we achieve this effect?  Check out the code below; the comments above the <code>drawBorderGlow()</code> method explain the core approach in a bit more detail:
</p>

<pre>
<code>
import java.awt.geom.*;
import java.awt.image.*;

private static final Color clrHi = new Color(255, 229, 63);
private static final Color clrLo = new Color(255, 105, 0);

private static final Color clrGlowInnerHi = new Color(253, 239, 175, 148);
private static final Color clrGlowInnerLo = new Color(255, 209, 0);
private static final Color clrGlowOuterHi = new Color(253, 239, 175, 124);
private static final Color clrGlowOuterLo = new Color(255, 179, 0);

private Shape createClipShape() {
    float border = 20.0f;

    float x1 = border;
    float y1 = border;
    float x2 = width - border;
    float y2 = height - border;

    float adj = 3.0f; // helps round out the sharp corners
    float arc = 8.0f;
    float dcx = 0.18f * width;
    float cx1 = x1-dcx;
    float cy1 = 0.40f * height;
    float cx2 = x1+dcx;
    float cy2 = 0.50f * height;

    GeneralPath gp = new GeneralPath();
    gp.moveTo(x1-adj, y1+adj);
    gp.quadTo(x1, y1, x1+adj, y1);
    gp.lineTo(x2-arc, y1);
    gp.quadTo(x2, y1, x2, y1+arc);
    gp.lineTo(x2, y2-arc);
    gp.quadTo(x2, y2, x2-arc, y2);
    gp.lineTo(x1+adj, y2);
    gp.quadTo(x1, y2, x1, y2-adj);
    gp.curveTo(cx2, cy2, cx1, cy1, x1-adj, y1+adj);
    gp.closePath();
    return gp;
}

private BufferedImage createClipImage(Shape s) {
    // Create a translucent intermediate image in which we can perform
    // the soft clipping
    GraphicsConfiguration gc = g.getDeviceConfiguration();
    BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
    Graphics2D g2 = img.createGraphics();

    // Clear the image so all pixels have zero alpha
    g2.setComposite(AlphaComposite.Clear);
    g2.fillRect(0, 0, width, height);

    // Render our clip shape into the image.  Note that we enable
    // antialiasing to achieve the soft clipping effect.  Try
    // commenting out the line that enables antialiasing, and
    // you will see that you end up with the usual hard clipping.
    g2.setComposite(AlphaComposite.Src);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(Color.WHITE);
    g2.fill(s);
    g2.dispose();

    return img;
}

private static Color getMixedColor(Color c1, float pct1, Color c2, float pct2) {
    float[] clr1 = c1.getComponents(null);
    float[] clr2 = c2.getComponents(null);
    for (int i = 0; i < clr1.length; i++) {
        clr1[i] = (clr1[i] * pct1) + (clr2[i] * pct2);
    }
    return new Color(clr1[0], clr1[1], clr1[2], clr1[3]);
}

// Here's the trick... To render the glow, we start with a thick pen
// of the "inner" color and stroke the desired shape.  Then we repeat
// with increasingly thinner pens, moving closer to the "outer" color
// and increasing the opacity of the color so that it appears to
// fade towards the interior of the shape.  We rely on the "clip shape"
// having been rendered into our destination image already so that
// the SRC_ATOP rule will take care of clipping out the part of the
// stroke that lies outside our shape.
private void paintBorderGlow(Graphics2D g2, int glowWidth) {
    int gw = glowWidth*2;
    for (int i=gw; i >= 2; i-=2) {
        float pct = (float)(gw - i) / (gw - 1);

        Color mixHi = getMixedColor(clrGlowInnerHi, pct,
                                    clrGlowOuterHi, 1.0f - pct);
        Color mixLo = getMixedColor(clrGlowInnerLo, pct,
                                    clrGlowOuterLo, 1.0f - pct);
        g2.setPaint(new GradientPaint(0.0f, height*0.25f,  mixHi,
                                      0.0f, height, mixLo));
        //g2.setColor(Color.WHITE);

        // See my "Java 2D Trickery: Soft Clipping" entry for more
        // on why we use SRC_ATOP here
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, pct));
        g2.setStroke(new BasicStroke(i));
        g2.draw(clipShape);
    }
}

Shape clipShape = createClipShape();
//Shape clipShape = new Ellipse2D.Float(width/4, height/4, width/2, height/2);

// Clear the background to white
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);

// Set the clip shape
BufferedImage clipImage = createClipImage(clipShape);
Graphics2D g2 = clipImage.createGraphics();

// Fill the shape with a gradient
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setComposite(AlphaComposite.SrcAtop);
g2.setPaint(new GradientPaint(0, 0, clrHi, 0, height, clrLo));
g2.fill(clipShape);

// Apply the border glow effect
paintBorderGlow(g2, 8);

g2.dispose();

g.drawImage(clipImage, 0, 0, null);
</code>
</pre>

<p>
Note that I've left a few "alternate" lines of code commented out in the example above.  Feel free to try uncommenting those lines in IGE and see how they affect the rendering.
</p>

<p>
Bonus: Astute readers may notice that the same technique used in the <code>paintBorderGlow()</code> method above could be used to add a drop shadow around the shape.  Care to guess how this would work?  Okay, time's up.  Instead of rendering the border on top of our shape (remember that the clip ensures that the stroke only touches the inside of the shape), we can render a varying gray border around our shape beforehand.  This means the shadow stroke will appear outside of our shape; the inner part of the shadow stroke will be effectively rendered over by our shape.
</p>
<p>
Here's some more code you can insert into the above example to add a shadow border to that same shape:
</p>

<pre>
<code>
private void paintBorderShadow(Graphics2D g2, int shadowWidth) {
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    int sw = shadowWidth*2;
    for (int i=sw; i >= 2; i-=2) {
        float pct = (float)(sw - i) / (sw - 1);
        g2.setColor(getMixedColor(Color.LIGHT_GRAY, pct,
                                  Color.WHITE, 1.0f-pct));
        g2.setStroke(new BasicStroke(i));
        g2.draw(clipShape);
    }
}

// Apply the border shadow before we paint the rest of the shape
paintBorderShadow(g, 6);
</code>
</pre>

<p>
And here's the resulting image:
</p>

<center>
<img alt="Shadow" src="http://weblogs.java.net/blog/campbell/archive/images/shadow.png" width="190" height="175" />
</center>

<p>
Note that this is just a quick attempt at adding a drop shadow for demonstration purposes.  If I wasn't so lazy, I'd probably use a lighter gray color and a non-linear ramp to achieve a more realistic effect.  Also note that this is just one of many ways to add a drop shadow using Java 2D.  Romain has discussed different drop shadow implementations in his blog <a href="http://jroller.com/page/gfx?entry=non_rectangular_shadow">here</a> and <a href="http://jroller.com/page/gfx?entry=fast_or_good_drop_shadows">here</a>.  The <a href="http://swinglabs.org">SwingLabs</a> folks have a <code>DropShadowBorder</code> in the <a href="https://swingx.dev.java.net/">SwingX</a> project, and <code>DropShadowPanel</code> is currently in the Incubator.
</p>

<p>
In the next installment of my "Trickery" series, I'll move away from low-level Java 2D effects and show you how to add animations to your applications using the SwingX Painters API and Chet's Timing Framework [tm].  In the meantime, let's see if <a href="http://weblogs.java.net/blog/joshy/">Josh</a> and <a href="http://weblogs.java.net/blog/rbair/">Richard</a> pick up the slack and turn some of the above code into stock painters (nudge nudge).
</p>

<br>
<br>
<p>
In my ears: <a href="http://en.wikipedia.org/wiki/Wire_%28band%29">Wire</a>, "Chairs Missing" [for about the 3 billionth time in my life]
<br>
In my eyes: "Idiot's Guide To Buying A Home" [I really hate growing up...]
</p>]]>

</content>
</entry>
<entry>
<title>Five More Easy Pieces</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/07/five_more_easy.html" />
<modified>2006-07-21T21:52:53Z</modified>
<issued>2006-07-21T21:52:38Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.5228</id>
<created>2006-07-21T21:52:38Z</created>
<summary type="text/plain">More improvements in the OpenGL-based Java 2D pipeline in Mustang b92... Also, an update on recent driver bug fixes...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
I'm sure you're all sick of reading my blogs at this point, because each time I state definitively that the OpenGL-based Java 2D pipeline is "now better than ever," only to follow it up a couple months later with a blog that says, "no really, this time it's even better," and so on.  It reminds me of a nearby store called "Cheaper Then Cheaper Cigarettes" [sic]; can you really improve on "cheaper" like that?
</p>
<p>
Anyway, at the risk of sounding like the boy who cried wolf, as of <a href="http://download.java.net/jdk6/binaries/">Mustang b92</a>, the OGL pipeline is now "better than better", one might even say it's superfantastic.  In the spirit of my recent <a href="http://weblogs.java.net/blog/campbell/archive/2006/04/five_easy_piece.html">"Five Easy Pieces"</a> entry, here are five more reasons why the OGL pipeline is better than ever...
</p>

<br>
<p>
<b>OGL: scrolling is extremely slow on Nvidia boards</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6298243">6298243</a>)
</p>

<p>
This bug frustrated me for a number of months, but I was confident that the Nvidia driver engineers would be able to come up with a solution as they've done with so many other issues.  Unfortunately, the problem is specific to the way data is laid out in texture memory on certain Nvidia hardware, so a simple driver fix wasn't possible.  However, they were kind enough to offer a (somewhat odd) workaround of using the GL_ARB_texture_rectangle extension, since rectangular textures are laid out more efficiently on said hardware and therefore do not exhibit the performance issues reported in this bug.
</p>
<p>
It took quite a bit of work, but the good news is that we were able to get support for the GL_ARB_texture_rectangle extension implemented for b92, so scrolling/dragging performance is back to normal on Nvidia hardware, for both pbuffers and framebuffer objects (FBOs).  As an added bonus, the use of that extension allows us to use less texture memory since we no longer have to pad up to power-of-two sized textures on older hardware.  (This is what <a href="http://en.wikipedia.org/wiki/Michael_Scott_%28The_Office%29">Michael Scott</a> would call a "win win win" situation.)
</p>

<br>
<p>
<b>OGL: enable sun.java2d.opengl.fbobject by default</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6439320">6439320</a>)
</p>

<p>
Another big benefit in fixing the previous scrolling performance bug is that it removed the last big barrier that prevented us from enabling the FBO codepath by default.  (I mentioned the FBO codepath in a <a href="http://weblogs.java.net/blog/campbell/archive/2005/09/java2djogl_inte_1.html">blog entry</a> from last autumn.  Note that since then, Ken Russell and I managed to get JOGL's GLJPanel working with the FBO codepath, so that is no longer a barrier.)  So as of b92, we've enabled the FBO codepath by default, which has many benefits when compared to the existing pbuffer-based codepath:
<ul>
<li>Reduces costly context-switching overhead.  This has helped to improve SwingMark (an internal Swing benchmark) scores by 15-20% on both ATI and Nvidia hardware, when compared to <code>fbobject=false</code>.
<li>Greatly improves performance when rendering VolatileImages (especially when applying an AffineTransform).
<li>Decreases the amount of VRAM consumed by VolatileImages, due to the fact that we have more control over which buffers are/aren't created.
<li>Improves maintainability, since the extension is cross-platform and not tied to any windowing system-isms.
<li>Works around a number of pbuffer-specific bugs in ATI's drivers, most notably the one that causes a HotSpot crash when exiting an application.
</ul>
</p>
<p>
If you've been been bitten by the OGL pipeline in the past (especially those folks with ATI hardware), I'd highly recommend installing b92 for this change alone.
</p>

<br>
<p>
<b>OGL: use new AffineTransform methods in enableGradientPaint()</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6434670">6434670</a>)
</p>

<p>
This one's not terribly exciting... Just a three-line change, but I wanted to mention it in case folks are not aware of some new convenience methods added to the AffineTransform class in Mustang.  The first is <a href="http://java.sun.com/javase/6/docs/api/java/awt/geom/AffineTransform.html#invert()">AffineTransform.invert()</a>, which is useful in those cases where you want to invert the transform matrix in place (hence no need to create a new AffineTransform object).  The second is <a href="http://java.sun.com/javase/6/docs/api/java/awt/geom/AffineTransform.html#rotate(double,%20double)">AffineTransform.rotate(vecx, vecy)</a>, which is helpful when you want to rotate about a vector (instead of using a relative angle value).
</p>
<p>
In this particular case, the old code was not a major bottleneck in the gradient/texture acceleration path, so there wasn't a huge performance benefit.  However, if you have some code that exercises AffineTransform heavily, you might want to check to see if these new methods give you a boost.
</p>


<br>
<p>
<b>OGL: accelerate Gradient/TexturePaint when antialiasing is enabled</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6436942">6436942</a>)
</p>

<p>
This one <i>is</i> terribly exciting, to me at least.  We've had some nifty acceleration for GradientPaint and TexturePaint since the OGL pipeline was introduced in JDK 5, but it always came with the caveat that <a href="http://today.java.net/cs/user/print/a/147#Non-antialiased_Rendering">only non-antialiased primitives</a> were accelerated.  But as of Mustang b92, we've figured out a way to use multitexturing to combine the gradient/texture acceleration code with our existing antialiased rendering code, which means GradientPaint and TexturePaint are now fully accelerated by the OGL pipeline, regardless of whether antialiasing is enabled.  The bug report has more details, but I'll include the executive summary here, because the numbers speak for themselves:
<ul>
<li>Up to 25x improvement for antialiased TexturePaint operations
<li>At least 2-7x improvement for antialiased GradientPaint operations
<li>No significant impact on existing accelerated operations
</ul>
</p>

<br>
<p>
<b>OGL: overlapping LCD glyphs not rendered properly</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6439274">6439274</a>)
</p>

<p>
This was a visible problem caused by an obscure bug, but fortunately the fix was easy.  It was the last known problem with the LCD text acceleration code mentioned in my <a href="http://weblogs.java.net/blog/campbell/archive/2006/04/five_easy_piece.html">last blog</a> on the subject, and the driver bugs mentioned there have since been fixed as well.
</p>
<p>
So if you're a fan of LCD text (meaning everyone but <a href="http://weblogs.java.net/blog/zixle/">Scott</a>, wink wink) and you have shader level hardware (Nvidia GeForce FX/6/7 series, ATI Radeon 9500 and up, etc), please try <code>-Dsun.java2d.opengl.lcdshader=true</code> and let us know if you see any problems.  I'm fairly confident that things are working well, but it hasn't received quite enough testing yet, so we're not planning to enable OpenGL acceleration of LCD text by default in Mustang.  Assuming all looks good in the next few months, we can consider turning it on by default in a Mustang update release.
</p>

<br>
<p>
<b>Bonus: The Driver Report</b>
</p>

<p>
As I've mentioned in past blogs, we've been working with driver teams from Nvidia, ATI, and Sun to ensure that any remaining driver issues are resolved by the time Mustang ships.  We have updated our basic acceptance test (BAT) suite with over 50 tests that said driver teams can use to prevent the introduction of new regressions and to test that their existing drivers work well with our OpenGL-based pipeline.
</p>
<p>
For the past couple years, ATI's drivers have been in a sad state of affairs w.r.t. our OGL pipeline (lots of crashes and rendering artifacts).  However, I'm now happy to report that ATI has fixed the remaining Linux-specific OpenGL driver bugs that affect our OGL pipeline, so our BAT suite now runs without failure on their forthcoming 8.27 series release.  If you're a Linux user with ATI hardware, I'd suggest upgrading to 8.27 when it becomes available in the next couple weeks.
</p>
<p>
As for ATI's OpenGL drivers for Windows, some bugs remain and we are continuing to push those with ATI.  But as I mentioned above, the change in b92 that makes the FBO codepath the default means that most of those bugs are no longer reproducible for most newer boards.
</p>
<p>
On the Nvidia and Sun fronts, things are looking really good.  There were a <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6447099">couple driver bugs</a> found recently on certain Nvidia laptop GPUs that have since been fixed.  If your laptop has an Nvidia GPU and you've been seeing weird artifacts when enabling the OGL pipeline, please install Nvidia's 95.xx series driver when it becomes available in the near future.
</p>

<br>
<br>
<p>
In my ears: <a href="http://en.wikipedia.org/wiki/Viktor_Vaughn">Viktor Vaughn</a>, "Vaudeville Villain"
<br>
In my eyes: <a href="http://en.wikipedia.org/wiki/Edward_P._Jones">Edward P. Jones</a>, "The Known World"
</p>]]>

</content>
</entry>
<entry>
<title>Java 2D Trickery: Soft Clipping</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/07/java_2d_tricker.html" />
<modified>2006-07-20T07:00:04Z</modified>
<issued>2006-07-20T06:59:57Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.5217</id>
<created>2006-07-20T06:59:57Z</created>
<summary type="text/plain">The first installment in a series of Java 2D tips-and-tricks.</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<i>
Note: The code snippets in this blog entry are intended to be used with Scott Violet's nifty <a href="http://weblogs.java.net/blog/zixle/archive/2006/07/beanshell_2d_in.html">Interactive Graphics Editor</a>.  Just cut and paste the code into that application, et voila: instant gratification.  This allows you to tinker with the code and immediately see how your changes affect the rendering.
</i>
</p>
<p>
If you're familiar with Java 2D, you probably already know that you can clip out a portion of your rendering with any arbitrary shape.  (If not, go check out the <a href="http://java.sun.com/docs/books/tutorial/2d/display/clipping.html">Java Tutorial</a>.)  For example, you can give the illusion of someone shining a flashlight on your application by setting a circular clip and then rendering your scene normally.  
</p>
<p>
When you clip using a complex shape, you will typically see jaggies around the edges of the region being clipped, which can uglify your app.  To illustrate the effect that I'll call "hard clipping", try the following example:
</p>

<code><pre>
// Clear the background to black
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);

// Set the clip shape
g.clip(new java.awt.geom.Ellipse2D.Float(width/4, height/4, width/2, height/2));

// Fill the area with a gradient; this will be clipped by our ellipse, but
// note the ugly jaggies
g.setPaint(new GradientPaint(0, 0, Color.RED, 0, height, Color.YELLOW));
g.fillRect(0, 0, width, height);
</pre></code>

<p>
Here's the resulting image:
</p>
<center><img alt="hard.png" src="http://weblogs.java.net/blog/campbell/archive/images/hard.png" width="196" height="198" />
</center>

<p>
Wouldn't it be nice if you could antialias those hard edges to remove the jaggies caused by clipping?  Well, unfortunately Java 2D (or at least Sun's current implementation) <a href="http://archives.java.sun.com/cgi-bin/wa?A2=ind0502&L=java2d-interest&F=&S=&P=1671">does not support</a> "soft clipping."
</p>
<p>
<i>
Sidebar: I add the caveat about Sun's implementation because I was surprised to find that when I tried the above code on my Mac, there were no jaggies!  What's going on here?  Well, it turns out that Apple's Java 2D implementation uses Quartz under the hood, which appears to do soft clipping by default.  In Mustang, Apple is planning to use Sun's software renderer instead of their Quartz renderer by default, so the tips in this blog entry should be relevant for Macs as well.
</i>
</p>
<p>
You'd think there would be a RenderingHint to control this behavior, but sorry, no such luck.  A few developers have asked for soft clipping in the past, but it doesn't seem to be common enough to warrant adding support for it in our implementation.  (I was going to say that it's too much work, and it probably would be, but then my esteemed readers would probably say "well if Apple could implement it in Quartz, why can't you?"  Damn those show-offs at Apple.  But I digress...)
</p>
<p>
Fortunately, we've found a fairly simple way to achieve a soft clipping effect using an intermediate image (see Chet's <a href="http://java.sun.com/developer/technicalArticles/Media/intimages/">article</a> on that subject) and a little known <code>AlphaComposite</code> rule known as <a href="http://java.sun.com/javase/6/docs/api/java/awt/AlphaComposite.html#SRC_ATOP"><code>SrcAtop</code></a>.  (Note that <code>SrcIn</code> would work equally well in this example, but <code>SrcAtop</code> has the added benefit that it blends the source with the destination, as opposed to simply replacing it, which will come in handy in the next installment.)  Try out the following code snippet:
</p>

<code><pre>
import java.awt.image.*;

// Clear the background to black
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);

// Create a translucent intermediate image in which we can perform
// the soft clipping
GraphicsConfiguration gc = g.getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();

// Clear the image so all pixels have zero alpha
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, width, height);

// Render our clip shape into the image.  Note that we enable
// antialiasing to achieve the soft clipping effect.  Try
// commenting out the line that enables antialiasing, and
// you will see that you end up with the usual hard clipping.
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fillOval(width/4, height/4, width/2, height/2);

// Here's the trick... We use SrcAtop, which effectively uses the
// alpha value as a coverage value for each pixel stored in the
// destination.  For the areas outside our clip shape, the destination
// alpha will be zero, so nothing is rendered in those areas.  For
// the areas inside our clip shape, the destination alpha will be fully
// opaque, so the full color is rendered.  At the edges, the original
// antialiasing is carried over to give us the desired soft clipping
// effect.
g2.setComposite(AlphaComposite.SrcAtop);
g2.setPaint(new GradientPaint(0, 0, Color.RED, 0, height, Color.YELLOW));
g2.fillRect(0, 0, width, height);
g2.dispose();

// Copy our intermediate image to the screen
g.drawImage(img, 0, 0, null);
</pre></code>

<p>
Compare the resulting image to the jaggy one above:
</p>
<center><img alt="soft.png" src="http://weblogs.java.net/blog/campbell/archive/images/soft.png" width="195" height="197" />
</center>

<p>
Looks better, no?  I'll admit that this example is a bit contrived, and it might be hard to see the real world applicability.  In the next installment of my "Trickery" series, I'll show you how to apply this technique when creating a lighting effect for arbitrary shapes.
</p>

<br>
<br>
<p>
In my ears: <a href="http://en.wikipedia.org/wiki/Asobi_Seksu">Asobi Seksu</a>, "Citrus" [just got back from their show at the Bowery Ballroom no less]
<br>
In my eyes: <a href="http://en.wikipedia.org/wiki/Edward_P._Jones">Edward P. Jones</a>, "The Known World"
</p>]]>

</content>
</entry>
<entry>
<title>The World&apos;s Slowest Web Service</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/04/the_worlds_slow.html" />
<modified>2006-04-27T01:07:00Z</modified>
<issued>2006-04-27T01:03:29Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.4587</id>
<created>2006-04-27T01:03:29Z</created>
<summary type="text/plain">What happens when a client-side guy dips his toes in the river of web services (JAX-WS)?  Come for the absurdity, stay for the tutorial.</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
<b>The Set Up</b>
<br>
Every so often a bug will creep into Java 2D that causes a particular rendering operation to be so ridiculously slow that it is almost comical.  (Only graphics geeks would find humor in something so mundane, but I digress.)  Back in the day, like 7 years ago, we would joke in our staff meetings along the lines of:
</p>
<pre>
   Person:   This rendering op is so slow...
   Audience: How slow is it?
   Person:   It's so slow that it would be faster to air mail each
             individual pixel to Timbuktu and back.
</pre>

<p>
A few years ago when the phrase "web services" became all the rage we had to update the punchline:
</p>

<pre>
   Person:   It's so slow that it would be faster to implement this
             op as a web service and host the server in Timbuktu.
</pre>

<p>
Okay, so you're not laughing, but I warned you earlier, I did.  Plus, it doesn't help that our collective senses of humor have all been addled recently by Chet and his <a href="http://weblogs.java.net/blog/chet/archive/2006/04/be_deployed_the.html">killer puns</a> (Minneapplet anyone?)...
</p>

<p>
<a href="http://en.wikipedia.org/wiki/Gary_Larson">But seriously forks</a>, all the web service yumminess being integrated into Mustang has peaked my interest, especially from the desktop Java standpoint.  I've seen a few JAX-WS 2.0 tutorials recently (see "Useful Resources" section below), but most are written from the server-side perspective, and therefore start out with "download the latest GlassFish build" or "grab the latest JWSDP release" or something similar.  Already that's one too many steps for my lazy self.  I'm a minimalist at heart, so what I really wanted to know was how quickly one could get up and running with JAX-WS using only the latest Mustang binaries.  And what better way to learn than to bring that old "joke" to life, so I now present to a truly contrived example: a pixel blender service (and client).
</p>
<br>

<p>
<b>Step 1: Write and compile the endpoint</b>
<br>
First we'll create our Blender endpoint.  JAX-WS 2.0 makes this a breeze.  All we need to do is define our Blender class and annotate it with <code>@WebService</code>, and then implement a single method (the one that does all the work) annotated with <code>@WebMethod</code>:
</p>

<pre>
package blend.endpoint;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;

@WebService(serviceName="BlenderService")
public class Blender {

    @WebMethod
    public int blend(int src, int dst) {
        int srcA = src >>> 24;
        int srcR = (src >> 16) & 0xff;
        int srcG = (src >>  8) & 0xff;
        int srcB = (src      ) & 0xff;
        int dstA = dst >>> 24;
        int dstR = (dst >> 16) & 0xff;
        int dstG = (dst >>  8) & 0xff;
        int dstB = (dst      ) & 0xff;
        int resA = (int)((srcA * 0.5) + (dstA * 0.5));
        int resR = (int)((srcR * 0.5) + (dstR * 0.5));
        int resG = (int)((srcG * 0.5) + (dstG * 0.5));
        int resB = (int)((srcB * 0.5) + (dstB * 0.5));
        return (resA << 24) | (resR << 16) | (resG << 8) | resB;
    }
}
</pre>

<p>
The "serviceName" parameter on <code>@WebService</code> is optional, as are many of the web service related annotation parameters, but here I just wanted to be a bit more explicit about the name of the service being generated.  (And again, this isn't meant to be an all-encompassing tutorial; I'm just trying to show the minimal number of steps to get "something" up and running.)
</p>

<p>
As the final part of this step, we will simply compile this source file:
<br>
<code>
% javac -d build src/blend/endpoint/Blender.java
</code>
</p>
<br>

<p>
<b>Step 2: Generate the endpoint "portable artifacts"</b>
<br>
Now that we have the source code and class file for our web service endpoint, we can use the <code>wsgen</code> tool (part of the JDK) to generate "portable artifacts", or behind-the-scenes implementation, for our web service:
<br>
<code>
% wsgen -cp build -d build -wsdl blend.endpoint.Blender
</code>
</p>

<p>
We pass the <code>-wsdl</code> argument to indicate that we want <code>wsgen</code> to generate the WSDL descriptor file, which we will need later.  In addition to the WSDL file, <code>wsgen</code> will generate a bunch of class files under the build directory.  Optionally you can pass the <code>-keep</code> argument indicating that you'd like it to generate the source files as well for those generated classes, but again, we're not concerned with what <code>wsgen</code> generates.  That's the benefit of the annotations here; as long as the tool conforms to the specifications of the various annotation types, we shouldn't need to worry too much about what gets generated under the hood.
</p>
<br>

<p>
<b>Step 3: Generate the client "portable artifacts"</b>
<br>
In Step 2 we used <code>wsgen</code> to generate a WSDL file from our Java endpoint class.  In this step, we will essentially reverse the process and use that WSDL file and the <code>wsimport</code> tool to generate our Java client class:
<br>
<code>
% wsimport -p blend.client -d build -wsdllocation http://127.0.0.1:8084/blend?WSDL build/BlenderService.wsdl
</code>
</p>

<p>
The <code>-p blend.client</code> argument indicates that we'd like <code>wsimport</code> to generate the class files in the <code>blend.client</code> package to keep them separate from our endpoint artifacts.  The <code>-wsdllocation</code> argument is not strictly necessary, but it is important if we want our client to pull the WSDL descriptor directly from the web service endpoint (otherwise our client would try to pull the descriptor at runtime from the location on disk, which is not what we want; this was tricky, it took me a while to figure out why this was needed).
</p>
<br>

<p>
<b>Step 4: Write and compile the client application</b>
<br>
Now that we have our automagically-generated Blender client classes that know how to communicate with the Blender endpoint, we just need to write an "interesting" client application to consume our even more "interesting" web service.  I've written a small Swing client application called BlendClient (source code included in the zip file mentioned later), but it would be easier to illustrate how to use the client code with a simple testcase:
</p>

<pre>
package blend.client;

public class Test {
    public static void main(String[] args) throws Exception {
        BlenderService service = new BlenderService();
        Blender blender = service.getBlenderPort();
        int src = 0xff00ff00;
        int dst = 0xff0000ff;
        int res = blender.blend(src, dst);
        System.out.printf("src=%08x dst=%08x result=%08x\n",
                          src, dst, res);
    }
}
</pre>

<p>
Note that by default this testcase will talk to the web service endpoint running at <code>http://127.0.0.1/blend</code> by virtue of the <code>-wsdllocation</code> parameter specified in Step 3.  If we wanted this testcase to communicate with an endpoint published on a different server, we could specify that with some additional parameters to the BlenderService constructor, but for the purposes of this demonstration, the default values will be sufficient.
</p>
<br>

<p>
<b>Step 5: Publish the endpoint</b>
<br>
Now it's time to publish our endpoint, which is a fancy way of saying that we'll start our "server".  Again, I've written a Swing client to start/stop the endpoint, but it would be easier to demonstrate how easy it is to publish an endpoint with a simple code example:
</p>

<pre>
package blend.endpoint;

import javax.xml.ws.Endpoint;

public class Test {
    public static void main(String[] args) throws Exception {
        Endpoint e = Endpoint.create(new Blender());
        e.publish("http://127.0.0.1:8084/blend");
        System.out.println("Endpoint running");
        try {
            Thread.sleep(300000);
        } catch (InterruptedException ex) {
        }
        e.stop();
        System.out.println("Endpoint stopped");
    }
}
</pre>

<p>
This code will publish the web service endpoint on the local machine on port 8084, and will keep it running for 5 minutes.  You can run compile and run this testcase easily:
<br>
<code>
% java -cp build blend.endpoint.Test
</code>
</p>

<p>
Note that the Endpoint API in Mustang is mainly useful for testing purposes.  If you were to publish this for real, you'd probably want to deploy it on one of them application server things the server-side folks like to talk about these days.
</p>
<br>

<p>
<b>Step 6: Run the client application</b>
<br>
This would be a good time to unveil my ludicrous attempt at a Swing application to demonstrate this stuff.  You'll need the <a href="http://download.java.net/jdk6/binaries/">latest version of Mustang</a> installed to run these WebStarted apps.  Note that I've had to sign my jar and give the application all permissions since it needs to talk to the network, even though it is running entirely locally on your machine.  (A real web service client won't necessarily have such a restriction; it should be possible to deploy a sandboxed WebStart application as long as it talks back to the server from which it was deployed, at least in theory.)
</p>

<p>
First fire up the endpoint (Blender Endpoint) using this link (thanks to Romain for hosting the binaries):
<br>
<center>
<a href="http://jext.free.fr/BlendEndpoint.jnlp" style="border: 0px none #000000;"><img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png"></a>
</center>
</p>

<p>
Then once the endpoint is running, try running the client app (Blender Client):
<br>
<center>
<a href="http://jext.free.fr/BlendClient.jnlp" style="border: 0px none #000000;"><img src="http://weblogs.java.net/blog/campbell/archive/webstart/webstart.png"></a>
</center>
</p>

<p>
Click the button and behold, it should look something like this:
<br>
<center>
<img src="http://weblogs.java.net/blog/campbell/archive/images/blender.png" width="608" height="270">
</center>
</p>

<p>
If all goes well, you should see the blended image filling in very, very slowly in the middle of the window.  Basically, the app is consulting the Blender web service running on your machine, one pixel and one scanline at a time.  Scary, and useless!  (By the way, the source code for this application demonstrates a couple other Mustang features, namely SwingWorker and the Desktop integration API, in case you're curious.)
</p>
<br>

<p>
<b>Conclusion</b>
<br>
Whew!  This turned out to be a much longer exercise than I was expecting, but I hope this information will be useful to those getting started with JAX-WS in Mustang, especially from the client side.  The minimalist within me winces when I realize how much prose and code it took to explain all this stuff.  I'm sure this process is much easier than it would have been in earlier JAX-RPC releases, so I can appreciate the simplicity of the new annotations.  However, there seem to be plenty of ways to shoot yourself in the foot when using these annotations, and the current documentation for many of these classes is not entirely clear in my opinion.  (Fortunately, I think that once there is more tools support for developing web services, developers will have less opportunity to screw up, and I would hope that the devlopment/deployment experience in those tools will improve things as well.)
</p>
<p>
At some point I'd like to go into more detail about my issues with JAX-WS, but I've got a plane to catch!  I'll be away for a couple weeks, so hopefully you'll understand if I don't respond to any comments right away.
</p>
<br>

<p>
<b>Useful Resources</b>
<ul>
<li><a href="http://weblogs.java.net/blog/campbell/archive/webstart/blender-src.zip">Source code</a> for the above examples
<li><a href="http://java.sun.com/developer/EJTechTips/2005/tt1220.html#1">SDN Tech Tip</a> on developing web services using JAX-WS
<li>Various blog entries from the JAX-WS gurus: <a href="http://weblogs.java.net/blog/mhadley/">Marc Hadley</a>, <a href="http://weblogs.java.net/blog/kohlert/">Doug Kohlert</a>, and <a href="http://weblogs.java.net/blog/jitu/">Jitendra Kotamraju</a>
<li>A recent <a href="http://www.devx.com/Java/Article/30459">DevX article</a> on JAX-WS
<li>Richard Monson-Haeful shares <a href="http://rmh.blogs.com/weblog/2006/03/jaxws_is_bad_ba.html">his criticism</a> of the latest JAX-WS spec
</ul>
</p>

<br>
<br>
<p>
In my ears: Destroyer, "Destroyer's Rubies"
<br>
In my eyes: Lots of blurriness at the moment
</p>]]>

</content>
</entry>
<entry>
<title>Five Easy Pieces</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/04/five_easy_piece.html" />
<modified>2006-04-24T09:04:19Z</modified>
<issued>2006-04-24T09:04:08Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.4566</id>
<created>2006-04-24T09:04:08Z</created>
<summary type="text/plain">A few short tidbits on some recent/nifty Mustang putbacks, documented here before my brain washes away on vacation.</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
I'm looking forward to a 2-week vacation in Greece that begins this week, so my mind is prone to wandering these days.  Therefore, I wanted to share with you a few short tidbits about some recent/nifty Mustang (Java SE 6) putbacks before they are indefinitely purged from my brain.  These fixes and features are small compared to most others in Mustang, but sometimes it's the little things that help round out a release, even for one that already contains so much desktop goodness.  And away we go, in no particular order...
</p>

<br>

<p>
<b>AlphaComposite.derive(float alpha)</b>
<br>
(RFE <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5095630">5095630</a>)
</p>

<p>
It's super easy to code up a fade effect in Java 2D using the AlphaComposite class, but eventually your fingers will tire of writing the following verbose code:
</p>
<pre>
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                                                alpha));
</pre>
<p>
Carpal Tunnel?  Suffer no more!  Mustang will save you a few keystrokes:
</p>
<pre>
    g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
</pre>

<p>
Clear, concise, nice!  This new method saves Romain so much time that he can invent twice as many ridiculous office weapons as before.  I recently had to work on a project that needed to run on JDK 5, and if there was one thing I wish I had from Mustang, it was AlphaComposite.derive()!
</p>

<br>

<p>
<b>GTK L&F Default Font</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6378474">6378474</a>)
</p>

<p>
In Tiger and earlier builds of Mustang, Swing's GTK L&F would simply use the default "Dialog" font.  In most cases, the chosen font would not be the same as the one used by native GTK applications, and as a result Java applications would look woefully out of place.  However, as of Mustang b77, the GTK L&F now consults the fontconfig library, so Swing applications will pick up the same desktop font used by native GTK applications.  Clearly this fix is long overdue; it required quite a bit of work, so I'm grateful that Phil fixed this for Mustang (and now I don't have to pester him anymore)!  Native fidelity of the GTK L&F has improved considerably in Mustang, and this fix played no small part, but in my opinion we still have a ways to go, so keep those contributions coming...
</p>

<br>

<p>
<b>Double Precision for GeneralPath</b>
<br>
(RFE <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4172661">4172661</a>)
</p>

<p>
This issue has come up at every Java 2D BOF at JavaOne for as long as I can remember, and I'm glad to say that this year we'll finally be able to say that it's available in Mustang.  The GeneralPath class has always looked a bit strange without a "double" counterpart, and beyond the obvious symmetry issue, GeneralPath has not been sufficient from a technical standpoint for many advanced users, especially those in the GIS and mapping industries (see the bug report for one such justification).
</p>

<p>
This is another long overdue enhancement, but it required a surprising amount of investigation to come up with a solution that fits in well with the existing java.awt.geom.* class hierarchy, performs well, and is easy to use.  The solution that Jim devised, with help from our community friend "leouser", required lots of thought, but it was worth the wait.  There is now a Path2D class (with Float and Double variants) in the java.awt.geom package, which will look familiar to longtime Java 2D users.  The GeneralPath class is now a trivial subclass of the Path2D.Float class, so your code will continue to work as always with single point precision, but now you have the option to migrate to the new Path2D.Float/Double classes to make the choice of storage a bit more explicit in your code.
</p>

<br>

<p>
<b>OpenGL Acceleration of LCD Text</b>
<br>
(Bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6274813">6274813</a>)
</p>

<p>
If you've read Chet's <a href="http://weblogs.java.net/blog/chet/archive/2005/06/phils_font_fixe.html">blog</a> or <a href="http://today.java.net/pub/a/today/2005/07/26/lcdtext.html">article</a> on the subject, you'll know that it takes quite a bit more computation to get LCD-optimized text onto the screen (when compared to grayscale or monochrome text).  As of Mustang b77, the text rendering codepath in the OpenGL-based Java 2D pipeline has been revamped to allow for acceleration of LCD text, in addition to the existing (and very fast) grayscale/monochrome codepath.
</p>

<p>
This is especially noteworthy because it is the first time we have leveraged programmable fragment shader technology in Java 2D.  We spent a number of weeks experimenting with a number of approaches in order to achieve maximum performance, and that work has mostly paid off.  The performance benefits aren't so noticeable on first and second generation shader-level hardware, but advancements are happening so fast in the graphics hardware space that I think this work will really pay off on today's hardware and beyond (think Nvidia GeForce 7800, ATI Radeon x1800, etc).
</p>

<p>
Unfortunately when this work was putback last month, there were a couple unresolved driver bugs that prevented us from enabling this support by default (see the above bug report for more details on performance as well as the magic incantation to enable this new codepath).  Since then, I'm happy to say that both Nvidia and ATI have addressed those issues, but the fixes are not yet in publically available drivers.  Once we're satisfied with those driver fixes, we should be able to turn this codepath on by default, when the OGL pipeline is enabled of course.
</p>

<p>
While we're on the subject of driver fixes, I'd like to quickly say thanks to Andy Ritger and team at Nvidia, and Matthew Tippett and Balaji Calidas at ATI, for all their help the past couple years in resolving the remaining driver kinks affecting Java 2D and our OGL pipeline.  It's been a lot of work, but the collaboration has paid off and I'm hoping that by the time Mustang ships the last couple outstanding driver issues will be resolved.
</p>

<br>

<p>
<b>Multi-stop Linear/RadialGradientPaints</b>
<br>
(RFE <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296064">6296064</a>)
</p>

<p>
If you're familiar with the Batik SVG library, you may have used the multi-stop gradient paint classes that are included with it.  Those classes were originally written by an intern on the Java 2D team, Nico Talian, way back in the year 2000 (when I was just a lowly intern myself!).  The code was donated to the Batik project at that time and the classes have served their purpose well, but in recent years there have been quite a few requests to include these classes with the core JDK.  Well, mostly it's been Josh, Richard, and Romain who have been doing the requesting on behalf of SwingLabs (check out their <a href="http://jroller.com/page/gfx/?anchor=advanced_swingx_painters_demo">recent work</a> on "painters"), and eventually they wore me down enough so that I'd take on this project.  So, we cleaned up the original API and got it into Mustang just in time for b81.
</p>

<p>
The JavaDocs for these new classes include a few basic (yet pretty) images to illustrate the various options:
<ul>
<li><a href="http://download.java.net/jdk6/docs/api/java/awt/LinearGradientPaint.html">LinearGradientPaint</a>
<li><a href="http://download.java.net/jdk6/docs/api/java/awt/RadialGradientPaint.html">RadialGradientPaint</a>
</ul>
</p>

<p>
You can also <a href="http://download.java.net/jdk6/binaries/">download the latest Mustang snapshot</a> and try the updated "GradAnim" pane in Java2Demo, which demonstrates these new multi-stop gradient classes.  (Oh, and before anyone yells at me for not mentioning this, the standard disclaimer applies that these new classes are not officially "in" until the Mustang JSR community -- and the proverbial fat lady -- say so.)
</p>

<p>
The biggest benefit of having these classes in the core JDK, other than the convenience factor, is that we are now able to provide hardware acceleration for these operations, which has been impossible up until this point.  As you may know, the OpenGL pipeline <a href="http://today.java.net/cs/user/print/a/147">already accelerates</a> the basic GradientPaint and TexturePaint operations in hardware for ridiculously good performance (GradientPaint for example is as much as 25x faster via OpenGL than in software!)... When I get back from vacation, I hope to provide similar acceleration for LinearGradientPaint and RadialGradientPaint when the OpenGL pipeline is enabled.  More fun with fragment shaders awaits!
</p>

<br>

<p>
<b>More to come...</b>
<br>
Man, I really thought this was going to be a short entry, but I guess even the smallest of features deserve their fifteen minutes in the spotlight.  Stay tuned for an upcoming blog entry containing a minimalist's tutorial of the new JAX-WS support in Mustang, from a client-side guy's perspective of course.  I was hoping to get that one out this week, but then again, it would be so much easier to just glide into vacation mode...
</p>

<br>

<p>
In my ears: Neu!, "Neu! 2"
<br>
In my eyes: Joseph Campbell, "The Hero with a Thousand Faces"
</p>]]>

</content>
</entry>
<entry>
<title>Wild Horses: Mustang Beta Is Out</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/02/wild_horses_mus_1.html" />
<modified>2006-02-15T16:56:19Z</modified>
<issued>2006-02-15T16:55:58Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.4122</id>
<created>2006-02-15T16:55:58Z</created>
<summary type="text/plain">A look back at some accomplishments in Mustang...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<p>
I'm an engineer, and if there's one thing that engineers suck at, it's taking stock of recent accomplishments.  As soon as one project is "completed" (no matter how significant or gratifying), we're already looking forward to the next big task into which to sink our collective teeth.  Who has time to sit around chatting about that old project when there's something new and shiny to tinker with?
</p>
<p>
Such is the case with <a href="http://java.sun.com/javase/6">Mustang (Java SE 6) Beta</a>.  No doubt by now you've already <a href="http://java.sun.com/javase/6/download.jsp">downloaded JDK 6 Beta</a> (and if you haven't, then stop reading this drivel and go download it).  But when I heard that Mustang Beta hit the streets this morning, my first reaction was something like: "Ho hum, b59g?  That's so passe!"...  After all, most of my concentration these days is directed on bug fixes and last minute enhancements for Mustang Beta 2, and I'm even spending some time looking into the hazy future that is Dolphin (Java SE 7).
</p>
<p>
Well, Mustang Beta may be passe to me (and to a few thousand eager early adopters who have been downloading the weekly snapshots), but it's new to the other N million Java developers out there.  And if you're one of those N million, you can rest assured that the JDK 6 Beta bits you've just gotten your hands on have been much more polished and well-tested than any of those weekly snapshots.  Almost all the major features of Mustang are in there, so there's no better time to kick the tires and see how well your application performs on the latest and greatest JDK.
</p>
<p>
At this point, I think I've convinced myself that Mustang Beta isn't passe at all, actually it's quite rad.  So maybe it is worth taking a quick look back at my favorite personal accomplishments in Mustang:
</p>
<p>
<b>5.</b> <a href="http://weblogs.java.net/blog/campbell/archive/2006/01/400_horsepower.html">I assisted</a> with my first externally contributed fix for Mustang.  Can't wait to see more of these in the near future.<br>
<b>4.</b> <a href="http://weblogs.java.net/blog/campbell/archive/2006/01/400_horsepower.html">Faster Image I/O</a>!<br>
<b>3.</b> Fullscreen exclusive mode for Linux and Solaris.  Admittedly, this one's a couple releases overdue, but it's pretty cool that you can now write a fullscreen application and have it work on all platforms.<br>
<b>2.</b> Single-threaded OpenGL pipeline.  I think I've said enough about this one already (see <a href="http://weblogs.java.net/blog/campbell/archive/2005/03/strcrazy_improv_1.html">this</a> and <a href="http://weblogs.java.net/blog/campbell/archive/2005/07/strcrazier_perf.html">that</a>), but it's still really fast, stable, and it opens the doors to a whole new breed of applications (see Romain's <a href="http://www.jroller.com/page/gfx?entry=a_swing_opengl_photo_viewer">"Twinkle" demo</a>) that mix Java 2D, Swing, and JOGL to provide a compelling user interface.<br>
<b>1.</b> <a href="http://weblogs.java.net/blog/zixle/archive/2005/04/no_more_gray_re_1.html">No more gray rect</a>!  I played a small part in this one (it took a whole dedicated team with people like <a href="http://weblogs.java.net/blog/zixle/">Scott</a>, Alexander, Denis, Dmitri, and <a href="http://weblogs.java.net/blog/chet/">Chet</a>), but we pulled it off and now Swing applications appear more responsive than ever.
</p>

<p>
And those of my colleagues:
</p>
<p>
<b>6.</b> <a href="http://weblogs.java.net/blog/stanleyh/archive/2005/04/deployment_good_1.html">No more scary WebStart dialogs</a> (and the new splashscreens and icons are pretty slick as well).<br>
<b>5.</b> JAXB and JAX-WS finally part of the JDK.  No more extra downloads required to write compelling rich clients that interact with those nifty up-and-coming web services (e.g. Flickr).<br>
<b>4.</b> SplashScreen API.<br>
<b>3.</b> A more complete Direct3D pipeline for Java 2D.  Going forward the D3D and OGL pipelines will have very similar architectures, which will help bring robust, hardware accelerated rendering to more platforms and hardware configurations.<br>
<b>2.</b> Vastly improved Windows and GTK L&Fs.  They're both now using platform APIs for even better native fidelity and performance.<br>
<b>1.</b> LCD-optimized text!
</p>
<br><br>
<p>
In my ears: The Buzzcocks, "Singles Going Steady"
<br>
In my eyes: Nothing, for once!
</p>]]>

</content>
</entry>
<entry>
<title>400 Horsepower: Image I/O Improvements in Mustang</title>
<link rel="alternate" type="text/html" href="http://weblogs.java.net/blog/campbell/archive/2006/01/400_horsepower.html" />
<modified>2006-01-13T09:06:00Z</modified>
<issued>2006-01-13T09:04:49Z</issued>
<id>tag:weblogs.java.net,2006:/blog/campbell/55.3937</id>
<created>2006-01-13T09:04:49Z</created>
<summary type="text/plain">Image I/O performance enhancements in Mustang... (In)action shots of the Java Client team... And my first external Mustang fix submission...</summary>
<author>
<name>campbell</name>

<email>christopher.campbell@sun.com</email>
</author>
<dc:subject>Community: JavaDesktop</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://weblogs.java.net/blog/campbell/">
<![CDATA[<b>Happy New Year!</b>
<p>
It's been a while since my last post, but I wanted to kick off 2006 by reporting some nice performance improvements in Image I/O.  As you may know, we're constantly finding ways to boost performance in various parts of the JDK.  In JDK 5 we did some performance work in Image I/O, specifically to avoid finalization in the JPEGImageReader, which made for huge gains in scalability and performance of reading JPEG images.  We heard some great feedback about those changes, but we knew there was more work to be done.
</p>
<p>
So a couple months ago, I spent a few solid weeks digging deep into the Image I/O framework and the core plugins trying to find ways to improve performance.  I've identified a few long term things we can do to optimize certain plugins even more, perhaps in the Dolphin timeframe.  But along the way, I uncovered (and picked off) some low hanging fruit and fixed them in <a href="https://mustang.dev.java.net/">Mustang</a> b63.  I won't bore you with all the details, but if you're interested, you can read the evaluations of the following bug reports, all of which were fixed in b63:
</p>
<p>
<ul>
<li><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6347575">6347575</a>: FileImageInputStream.readInt() and similar methods are inefficient
<li><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348744">6348744</a>: PNGImageReader should skip metadata if
ignoreMetadata=true
<li><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6348744">6354056</a>: JPEGImageReader could be optimized
<li><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6299405">6299405</a>: ImageInputStreamImpl still uses a finalize() which causes java.lang.OutOfMemoryError
<li><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6354112">6354112</a>: increase compiler optimization level for libjpeg to improve runtime performance
</ul>
</p>
<p>
Also in those evaluations you'll find lots of raw J2DBench numbers and analysis, but ASCII can be so boring.  What blog entry would be complete without a Ross Perot-style chart?  [Did I really just make a Ross Perot reference?  How pathetic...  Maybe next time I'll make a clever remark about Dan Quayle's potatoe?]  Feast yr eyes:
</p>
<center><img alt="mustang.png" src="http://weblogs.java.net/blog/campbell/archive/images/mustang.png" width="530" height="368" /></center>
<p>
That 20x20 JPEG score for JDK 1.4.2 isn't a glitch; it really was that bad (yet another demonstration of the evils of finalizers and explicit System.gc() calls)... Note that this chart only shows results for small images just because I'm tired and lazy, but similar improvements can be seen for larger images as well.  For example, I've measured a 53% improvement in reading 4000x4000 pixel JPEG images between Mustang b62 and b63.
</p>
<p>
And yet somehow I'm still not satisfied... We'll continue to work on this stuff as time goes on.  In the meantime, please <a href="http://download.java.net/jdk6/binaries/">download the latest Mustang snapshot</a> and let us know if these Image I/O enhancements are helping your application.
</p>
<br>
<b>Are You Ready To Testify?  I Give You... A Testimonial!</b>
<p>
While we're on the subject, just yesterday I received some exciting feedback from Jeffrey Moore and <a href="http://weblogs.java.net/blog/gonzo/">James Todd</a> from the JXTA project.  You may have <a href=http://weblogs.java.net/blog/gonzo/archive/2005/12/myjxta_video.html">read recently</a> that MyJXTA now has a video conferencing feature, which uses MJPEG as the video protocol.  It's not the most efficient video format out there, but it was easy for them to use the JPEGImageReader in Image I/O to assist in decoding the JPEG frames.  They were asking about JPEG decoding performance and I suggested that they try the latest Mustang builds because of the fixes I mentioned above.  It turns out that with the latest Mustang snapshots they are seeing CPU usage cut in half when decoding an MJPEG stream at 30 fps (compared to JDK 5)!  The fixes above had a lot to do with it, but I know there have been other performance improvements across the stack (in HotSpot and elsewhere) that are probably contributing as well.  This chart tells all:
</p>
<center><img alt="myjxta.png" src="http://weblogs.java.net/blog/campbell/archive/images/myjxta.png" width="528" height="387" />
</center>
<br>
<b>Meet the Java Client Team</b>
<p>
When he's not working on one of his <a href="http://jroller.com/page/gfx/?anchor=a_swing_opengl_photo_viewer">cool JOGL/Java2D demos</a>, you can find <a href="http://weblogs.java.net/blog/chet/">Romain</a> snapping some photos of the <a href="http://jroller.com/page/gfx/?anchor=meet_the_swing_team_part">desktop Java geeks</a> that work here on <a href="http://jroller.com/page/gfx/?anchor=meet_the_swing_team_part1">Sun's Santa Clara campus</a>.  If you've ever wondered about the faces behind the names, now's your chance to satisfy your curiosity.  Or maybe you have a favorite Java2D or Swing bug that still isn't fixed?  Here's what you do: print out the responsible engineer's photo, tape it to your office dartboard, and then play a little game of cricket... It may not get that bug fixed any sooner, but what better way is there to relieve the frustration of waiting?
</p>
<br>
<b>Get Involved with Mustang!</b>
<p>
Well, perhaps that was a tad sinister.  I would never condone violence against my fellow Sun engineers (except maybe <a href="http://weblogs.java.net/blog/chet/">Chet</a>, but I kid, I kid).  If you really do want to see a languishing JDK bug fixed, let me once again recommend the <a href="https://jdk-collaboration.dev.java.net/">JDK Collaboration</a> project (aka Project Peabody).  We've had lots of external developers digging into the JDK source code and submitting complete bug fixes, but we'd love to see more, so why not <a href="https://mustang.dev.java.net/collaborate.html">get involved</a>?  There are plenty of open bugs on the <a href="http://download.java.net/jdk/JDK-Starter.html">"starter list"</a> that you can hack on to get your feet wet.
</p>
<p>
On that note, I recently had the pleasure of working with one such external developer, Rémi Forax, who submitted a <a href="https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=10399">really nice patch</a> for <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4703112">this Image I/O RFE</a>.  This was a model submission: it wasn't just a cut-and-paste job, but instead included a more complete fix (using JDK 5 features, no less) to make the existing code even better, and to top it off it included the requisite testcase.  Thanks for the great fix, Rémi!  I hope to see more submissions just like that in the near future...
</p>
<br>
<p>
In my ears-uh: <a href="http://en.wikipedia.org/wiki/The_Fall_%28band%29">The Fall</a>, "Bend Sinister"
<br>
In my eyes-uh: <a href="http://en.wikipedia.org/wiki/Peter_Hoeg">Peter Høeg</a>, "Smilla's Sense of Snow"
</p>]]>

</content>
</entry>

</feed>