Hi Scott,

sorry for the late reply. I spent a few days in Bulgaria with my family and needed some time to catch up to recent events (I did not expect the ComboBox bug to generate that much noise, but it looks like you guys found the best solution possible).

Other than Chris, after thinking again about my initial idea, I do not think that CompoundComposite will ever work the way I thought it would, and I think we should simply forget about this idea. I conducted some tests and found that this is the wrong approach (but I still may be wrong). On the other hand, the setAlpha() method with having the RepaintManager handle the this through intermediate images seems to be a great idea, since this is probably what people will be need in most of the cases (you can expect a bunch of people trying to mimic some of the Vista effects with Java at the beginning of 2007).

One important question that should be asked is in what way people will use Composites in future, and if the setAlpha() method will in some way comflict with these usages. For example, what if the developer decides to set an alpha composite inside a paintComponent() method to paint an icon translucently. Will this work as expected? If so (and I understood from Chris' explanation that it will), the setAlpha() method is just what I (and I suspect others as well) need.


Cheers

 Jan

P.S.: Chris, thanks for the extensive information, very interesting read.




Scott Violet wrote:
Hi Jan,

I wanted to get feedback from you on JComponent.setAlpha. Does Chris's explanation of how JComponent.setAlpha would work make sense? Is it what you are after?

Thanks,

    -Scott



Subject:
Re: [JAVA2D] Proposal for compound Composites
From:
Chris Campbell <[EMAIL PROTECTED]>
Date:
Thu, 12 Oct 2006 00:01:30 -0700
To:
Jan Bösenberg (INCORS GmbH) <[EMAIL PROTECTED]>
To:
Jan Bösenberg (INCORS GmbH) <[EMAIL PROTECTED]>
CC:
[EMAIL PROTECTED], Scott Violet <[EMAIL PROTECTED]>, Romain GUY <[EMAIL PROTECTED]>, Richard Bair - Sun Microsystems - Santa Clara United States <[EMAIL PROTECTED]>

Hi Jan,

This is an interesting proposal.  It's also timely in that we've  recently been discussing the possibility of adding a  JComponent.setAlpha() (or similarly named method), and you touch upon  some issues that came up in that discussion.

Swing and Java2D developers have certainly run into this issue  before, and our advice has typically been to use "intermediate  images" [1] to achieve your effect.  Using this approach, you can  isolate parts of your rendering routine that might use a different  composite or alpha value than other parts of your routine.  Taking  your example, you could make this work by doing the following:
    Composite myComposite = createMyComposite();
    Composite originalComposite = g2D.getComposite();
    BufferedImage img = ...;
    Graphics2D gimg = img.createGraphics();
    paintALot(gimg);
    gimg.dispose();
    g2D.setComposite(myComposite);
    g2D.drawImage(img, ...);
    g2D.setComposite(originalComposite);

This works well most obviously in the SrcOver case (which I'd say is  the 95% scenario), but it can work for other types of compositing as  well.  The downside of course is that it requires a lot of manual  intervention on the part of the developer, and what if paintALot() is  in some library that isn't under the developer's control?  Before you  know it, tin-hat paranoia takes hold and you're applying this  technique all over your code, even when it's not necessary :)

The SVG spec has something called "group opacity" [2], which is very  similar to what I describe above, and probably very similar to the  functionality that (I think) you're looking for.  Here's a quote from  section 14.5 of the SVG spec:

   "Object/group opacity can be thought of conceptually as a  postprocessing
   operation. Conceptually, after the object/group is rendered into  an RGBA
   offscreen image, the object/group opacity setting specifies how  to blend
   the offscreen image into the current background."

The SVG authors were going for that 95% scenario that I described  earlier, in that the blending used is essentially SrcOver with a  varying "opacity" value.  Again, the nice thing here is that you can  have lots of subelements within a group that each have different  (individual) opacity settings, and then the "group opacity" setting  is applied to that entire group (the conceptual image).  This is the  combination effect that (I believe) you are seeking.

This also happens to be the approach that we're leaning towards if/ when we implement JComponent.setAlpha().  The benefit here is that  Swing's RepaintManager will essentially be doing all that dirty work  that I showed earlier (with intermediate images behind the scenes as  necessary).  Going back to your original example, it should be as  simple as calling label.setAlpha(0.5f), which will work equally well  whether the content of the label is painted full opaque, or with  translucent elements, as in your example.  Either way, you'll get the  results you're looking for, with minimal fuss.  We'll need to specify  this method, hopefully with pictures, so that developers understand  what it really means to "set the opacity/alpha of a component", but  right now we're aiming in this direction since it seems to solve the  95% case.

As an aside, JXPanel today uses the naïve approach, and basically  calls g.setComposite(SrcOver(alpha) at the top of its paint()  method.  This of course will work for the most simple scenarios, but  it won't work for anything more complicated, like your example.  You  can achieve some "interesting" effects using JXPanel, most of which  are incorrect, but anyway... :)

Okay, so I'm rambling, and I haven't even gotten to your  CompoundComposite proposal yet.  I think that CompoundComposite could  probably work as you describe, where the compose() methods are  chained together, and you'd probably end up with the desired effect.   My main concern with this approach is performance: we almost never  use Composite.createContext() directly, but instead bypass it  altogether with accelerated loops.  If we had to fall back on  createContext() and compose() for each operation, performance would  suffer.  I suppose we could find a way around this, maybe analyze the  individual Composites within a CompoundComposite, and maybe collapse  them if they're simple (like if you're trying to chain two SrcOver's  together).  Regardless, even if you could get all of this working and  spec'd out properly, the conceptual model may be difficult for  developers to understand.  At least, it's not quite as  straightforward as comp.setAlpha().

Anyway, I hope that somewhere in here I've answered your questions  sufficiently.  I also hope that the setAlpha() method that's on the  table for JDK 7 will solve the most common cases.  Going forward, if  we decide to add SVG and/or a "layers" API (for which Romain pines),  it seems that both would fit in well conceptually with the "group  opacity" and setAlpha() approaches.  Thoughts?

Thanks,
Chris

[1] Chet doesn't necessarily talk about the compositing issues here,  but he does describe the general intermediate image approach:
http://java.sun.com/developer/technicalArticles/Media/intimages/

[2] http://www.w3.org/TR/SVG/ masking.html#ObjectAndGroupOpacityProperties


On Oct 6, 2006, at 6:19 AM, Jan Bösenberg (INCORS GmbH) wrote:
This is just a thought that I had yesterday when I used the
AlphaComposite class, but I thought it may be worth sharing with you:

Setting a composite when painting on java.awt.Graphics2D object is
usually done like this:

Composite myComposite = createMyComposite();
Composite originalComposite = g2D.getComposite();
g2D.setComposite(myComposite);
paintALot(g2D);
g2D.setComposite(originalComposite);

Just yesterday I decided that this will not work in some cases.  Imagine
you want to create a fancy effect by making a translucent panel. To
achieve this you set an AlphaComposite.SrcOver with 0.5f alpha  parameter
in the panel's paintComponent() method . On that panel you have a  bunch
of labels with html text. You decided that if a label is disabled, it
should be translucent, using an AlphaComposite.SrcOver with 0.5f  alpha.
This works well on a normal panel, but with our fancy translucent  panel
the disabled text will suddenly look exactly the same as the enabled
text (both will be translucent with alpha 0.5). The reason is simply
that the composites are replaced, while they should be combined to get
the desired effect.

If you look at Romain Guy's recent blog entries, you will see that  using
Composites will be used more frequently, and sooner or later someone
will run into a problem similar to the one I described. The solution
would be to have a class CompoundComposite, that simply takes two
Composite objects in the constructor. The code from the beginning  would
then look like this:

Composite myComposite = createMyComposite();
Composite originalComposite = g2D.getComposite();
if (originalComposite != null) {
 CompoundComposite compoundComposite = new
CompoundComposite(originalComposite, myComposite);
 g2D.setComposite(compoundComposite);
} else {
 g2D.setComposite(myComposite);
}
paintALot(g2D);
g2D.setComposite(originalComposite);

Since I do not know too much about the inner workings of Java2D, but I
would like to know if it is possible at all to create a class that can
combine two arbitrary Composites. Maybe it is very simple. What if its
createContext() method creates a CompundCompositeContext with a
CompositeContext from each of the simple Composites (created by  calling
the simple Composites' createContext() method). The
CompundCompositeContext's compose() method would then call the  compose()
method of each of the simple CompositeContexts.

What do you think? Am I on the right track? And if so, should this
always be used when working with Composites? And if so, should
CompoundComposite maybe be added to the java.awt package?

Just for the record, a similar problem exists for the AffineTransform,
but here the concatenate() method in the AffineTransform does what my
proposed CompoundComposite class would do.


Cheers,
Jan

====================================================================== =====
To unsubscribe, send email to [EMAIL PROTECTED] and include in  the body
of the message "signoff JAVA2D-INTEREST".  For general help, send  email to
[EMAIL PROTECTED] and include in the body of the message "help".



=========================================================================== To unsubscribe, send email to [EMAIL PROTECTED] and include in the body of the message "signoff JAVA2D-INTEREST". For general help, send email to [EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to