mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			317 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			317 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* AlphaCompositeContext.java -- CompositeContext impl for AlphaComposite
 | |
|    Copyright (C) 2006 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package gnu.java.awt.java2d;
 | |
| 
 | |
| import java.awt.AWTError;
 | |
| import java.awt.AlphaComposite;
 | |
| import java.awt.CompositeContext;
 | |
| import java.awt.image.ColorModel;
 | |
| import java.awt.image.Raster;
 | |
| import java.awt.image.WritableRaster;
 | |
| 
 | |
| /**
 | |
|  * A CompositeContext implementation for {@link AlphaComposite}.
 | |
|  *
 | |
|  * @author Roman Kennke (kennke@aicas.com)
 | |
|  */
 | |
| public class AlphaCompositeContext
 | |
|   implements CompositeContext
 | |
| {
 | |
| 
 | |
|   /**
 | |
|    * The Composite object for which we perform compositing.
 | |
|    */
 | |
|   private AlphaComposite composite;
 | |
| 
 | |
|   /**
 | |
|    * The source color model.
 | |
|    */
 | |
|   private ColorModel srcColorModel;
 | |
| 
 | |
|   /**
 | |
|    * The destination color model.
 | |
|    */
 | |
|   private ColorModel dstColorModel;
 | |
| 
 | |
|   /**
 | |
|    * The blending factor for the source.
 | |
|    */
 | |
|   private float fs;
 | |
| 
 | |
|   /**
 | |
|    * The blending factor for the destination.
 | |
|    */
 | |
|   private float fd;
 | |
| 
 | |
|   /**
 | |
|    * Creates a new AlphaCompositeContext.
 | |
|    *
 | |
|    * @param aComp the AlphaComposite object
 | |
|    * @param srcCM the source color model
 | |
|    * @param dstCM the destination color model
 | |
|    */
 | |
|   public AlphaCompositeContext(AlphaComposite aComp, ColorModel srcCM,
 | |
|                                ColorModel dstCM)
 | |
|   {
 | |
|     composite = aComp;
 | |
|     srcColorModel = srcCM;
 | |
|     dstColorModel = dstCM;
 | |
| 
 | |
| 
 | |
|     // Determine the blending factors according to the rule in the
 | |
|     // AlphaComposite. For some rules the factors must be determined
 | |
|     // dynamically because they depend on the actual pixel value.
 | |
|     switch (composite.getRule())
 | |
|     {
 | |
|       case AlphaComposite.CLEAR:
 | |
|         fs = 0.F;
 | |
|         fd= 0.F;
 | |
|         break;
 | |
|       case AlphaComposite.DST:
 | |
|         fs = 0.F;
 | |
|         fd= 1.F;
 | |
|         break;
 | |
|       case AlphaComposite.DST_ATOP:
 | |
|         fs = 1.F; // Determined later as 1 - alpha_dst;
 | |
|         fd = 1.F; // Determined later as alpha_src;
 | |
|         break;
 | |
|       case AlphaComposite.DST_IN:
 | |
|         fs = 0.F;
 | |
|         fd = 0.F; // Determined later as alpha_src;
 | |
|         break;
 | |
|       case AlphaComposite.DST_OUT:
 | |
|         fs = 0.F;
 | |
|         fd = 0.F; // Determined later as 1 - alpha_src;
 | |
|         break;
 | |
|       case AlphaComposite.DST_OVER:
 | |
|         fs = 1.F; // Determined later as 1 - alpha_dst.
 | |
|         fd= 1.F;
 | |
|         break;
 | |
|       case AlphaComposite.SRC:
 | |
|         fs = 1.F;
 | |
|         fd= 0.F;
 | |
|         break;
 | |
|       case AlphaComposite.SRC_ATOP:
 | |
|         fs = 1.F; // Determined later as alpha_dst;
 | |
|         fd = 1.F; // Determined later as 1 - alpha_src;
 | |
|         break;
 | |
|       case AlphaComposite.SRC_IN:
 | |
|         fs = 0.F; // Determined later as alpha_dst;
 | |
|         fd = 0.F;
 | |
|         break;
 | |
|       case AlphaComposite.SRC_OUT:
 | |
|         fs = 0.F; // Determined later as 1 - alpha_dst;
 | |
|         fd = 0.F;
 | |
|         break;
 | |
|       case AlphaComposite.SRC_OVER:
 | |
|         fs = 1.F;
 | |
|         fd= 1.F; // Determined later as 1 - alpha_src.
 | |
|         break;
 | |
|       case AlphaComposite.XOR:
 | |
|         fs = 1.F; // Determined later as 1 - alpha_dst.
 | |
|         fd= 1.F; // Determined later as 1 - alpha_src.
 | |
|         break;
 | |
|       default:
 | |
|         throw new AWTError("Illegal AlphaComposite rule");
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Releases all resources held by this composite object.
 | |
|    */
 | |
|   public void dispose()
 | |
|   {
 | |
|     // Nothing to do here yet.
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Performs compositing according to the rules specified in the
 | |
|    * AlphaComposite from the constructor.
 | |
|    */
 | |
|   public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
 | |
|   {
 | |
| 
 | |
|     // TODO: This implementation is very general and highly inefficient. There
 | |
|     // are two possible ways to optimize this:
 | |
|     // 1. Special cased implementations for common ColorModels and transfer
 | |
|     //    types.
 | |
|     // 2. Native implementation.
 | |
| 
 | |
|     int x0 = src.getMinX();
 | |
|     int y0 = src.getMinY();
 | |
|     int width = src.getWidth();
 | |
|     int height = src.getHeight();
 | |
|     int x1 = x0 + width;
 | |
|     int y1 = y0 + height;
 | |
| 
 | |
|     Object srcPixel = null;
 | |
|     Object dstPixel = null;
 | |
| 
 | |
|     // Prepare the array that holds the color and alpha components of the
 | |
|     // source pixels.
 | |
|     float[] srcComponents;
 | |
|     int srcComponentsLength = srcColorModel.getNumComponents();
 | |
|     if (! srcColorModel.hasAlpha())
 | |
|       srcComponentsLength += 1;
 | |
|     srcComponents = new float[srcComponentsLength];
 | |
| 
 | |
|     // Prepare the array that holds the color and alpha components of the
 | |
|     // destination pixels.
 | |
|     float[] dstComponents;
 | |
|     int dstComponentsLength = dstColorModel.getNumComponents();
 | |
|     if (! dstColorModel.hasAlpha())
 | |
|       dstComponentsLength += 1;
 | |
|     dstComponents = new float[dstComponentsLength];
 | |
| 
 | |
|     if (srcComponentsLength != dstComponentsLength)
 | |
|       throw new AWTError("The color models of the source and destination have"
 | |
|                          + "incompatible number of color components");
 | |
| 
 | |
|     int srcTransferType = srcColorModel.getTransferType();
 | |
|     int dstTransferType = dstColorModel.getTransferType();
 | |
| 
 | |
|     for (int y = y0; y < y1; y++)
 | |
|       {
 | |
|         for (int x = x0; x < x1; x++)
 | |
|           {
 | |
|             // Fetch source pixel.
 | |
|             srcPixel = src.getDataElements(x, y, (int[]) srcPixel);
 | |
|             // Fetch destination pixel.
 | |
|             dstPixel = dstIn.getDataElements(x, y, dstPixel);
 | |
|             // Get normalized components. This is the only type that is
 | |
|             // guaranteed to be supported by all ColorModels.
 | |
|             srcComponents =
 | |
|               srcColorModel.getNormalizedComponents(srcPixel, srcComponents, 0);
 | |
|             if (! srcColorModel.hasAlpha())
 | |
|               srcComponents[srcComponentsLength - 1] = 1.0F;
 | |
|             dstComponents =
 | |
|               dstColorModel.getNormalizedComponents(dstPixel, dstComponents, 0);
 | |
|             if (! dstColorModel.hasAlpha())
 | |
|               dstComponents[dstComponentsLength - 1] = 1.0F;
 | |
| 
 | |
|             // Prepare the input.
 | |
|             float compositeAlpha = composite.getAlpha();
 | |
|             srcComponents[srcComponentsLength - 1] *= compositeAlpha;
 | |
|             if (srcColorModel.isAlphaPremultiplied())
 | |
|               {
 | |
|                 for (int i = srcComponentsLength - 2; i >= 0; i--)
 | |
|                   srcComponents[i] *= compositeAlpha;
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 for (int i = srcComponentsLength - 2; i >= 0; i--)
 | |
|                   srcComponents[i] *= srcComponents[srcComponentsLength - 1];
 | |
|               }
 | |
|             if (! dstColorModel.isAlphaPremultiplied())
 | |
|               {
 | |
|                 for (int i = dstComponentsLength - 2; i >= 0; i--)
 | |
|                   dstComponents[i] *= dstComponents[dstComponents.length - 1];
 | |
|               }
 | |
| 
 | |
|             // Determine the blending factors according to the rule in the
 | |
|             // AlphaComposite. For some rules the factors must be determined
 | |
|             // dynamically because they depend on the actual pixel value.
 | |
|             float srcAlpha = srcComponents[srcComponentsLength - 1];
 | |
|             float dstAlpha = dstComponents[dstComponentsLength - 1];
 | |
|             switch (composite.getRule())
 | |
|             {
 | |
|               case AlphaComposite.DST_ATOP:
 | |
|                 fs = 1.F - dstAlpha;
 | |
|                 fd = srcAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.DST_IN:
 | |
|                 fd = srcAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.DST_OUT:
 | |
|                 fd = 1.F - srcAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.DST_OVER:
 | |
|                 fs = 1.F - dstAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.SRC_ATOP:
 | |
|                 fs = srcAlpha;
 | |
|                 fd = 1.F - srcAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.SRC_IN:
 | |
|                 fs = dstAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.SRC_OUT:
 | |
|                 fs = 1.F - dstAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.SRC_OVER:
 | |
|                 fd= 1.F - srcAlpha;
 | |
|                 break;
 | |
|               case AlphaComposite.XOR:
 | |
|                 fs = 1.F - dstAlpha;
 | |
|                 fd= 1.F - srcAlpha;
 | |
|                 break;
 | |
|               default:
 | |
|                 // For the other cases the factors have already been determined
 | |
|                 // in the constructor.
 | |
|             }
 | |
| 
 | |
|             // Apply the blending equation to the pixels.
 | |
|             for (int i = 0; i < srcComponentsLength; i++)
 | |
|               {
 | |
|                 dstComponents[i] = srcComponents[i] * fs
 | |
|                                    + dstComponents[i] * fd;
 | |
|               }
 | |
| 
 | |
|             // Convert the result back when the destination is not
 | |
|             // alpha-premultiplied.
 | |
|             dstAlpha = dstComponents[dstComponentsLength - 1];
 | |
|             if (!dstColorModel.isAlphaPremultiplied() && dstAlpha != 0.F)
 | |
|               {
 | |
|                 for (int i = 0; i < dstComponentsLength - 1; i++)
 | |
|                   {
 | |
|                     dstComponents[i] = dstComponents[i] / dstAlpha;
 | |
|                   }
 | |
|               }
 | |
| 
 | |
|             // Store the result in the destination raster.
 | |
|             dstPixel = dstColorModel.getDataElements(dstComponents, 0,
 | |
|                                                      dstPixel);
 | |
|             dstOut.setDataElements(x, y, dstPixel);
 | |
|           } // End X loop.
 | |
|       } // End Y loop.
 | |
|   }
 | |
| 
 | |
| }
 |