001/* RenderableImageProducer.java --
002   Copyright (C) 2002, 2006 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt.image.renderable;
040
041import java.awt.image.ColorModel;
042import java.awt.image.DataBuffer;
043import java.awt.image.ImageConsumer;
044import java.awt.image.ImageProducer;
045import java.awt.image.Raster;
046import java.awt.image.RenderedImage;
047import java.awt.image.SampleModel;
048import java.util.ArrayList;
049import java.util.Iterator;
050
051public class RenderableImageProducer implements ImageProducer, Runnable
052{
053  private RenderableImage image;
054  private RenderContext context;
055  private ArrayList consumers = new ArrayList();
056
057  public RenderableImageProducer(RenderableImage image, RenderContext context)
058  {
059    this.image = image;
060    this.context = context;
061  }
062
063  public void setRenderContext(RenderContext context)
064  {
065    this.context = context;
066  }
067
068  public void addConsumer(ImageConsumer consumer)
069  {
070    synchronized (consumers)
071      {
072        if (! consumers.contains(consumer))
073          consumers.add(consumer);
074      }
075  }
076
077  public boolean isConsumer(ImageConsumer consumer)
078  {
079    synchronized (consumers)
080      {
081        return consumers.contains(consumer);
082      }
083  }
084
085  public void removeConsumer(ImageConsumer consumer)
086  {
087    synchronized (consumers)
088      {
089        consumers.remove(consumer);
090      }
091  }
092
093  public void startProduction(ImageConsumer consumer)
094  {
095    addConsumer(consumer);
096    Thread t = new Thread(this, "RenderableImageProducerWorker");
097    t.start();
098  }
099
100  public void requestTopDownLeftRightResend(ImageConsumer consumer)
101  {
102    // Do nothing.  The contract says we can ignore this call, so we do.
103  }
104
105  public void run()
106  {
107    // This isn't ideal but it avoids fail-fast problems.
108    // Alternatively, we could clone 'consumers' here.
109    synchronized (consumers)
110      {
111        RenderedImage newImage;
112        if (context == null)
113          newImage = image.createDefaultRendering();
114        else
115          newImage = image.createRendering(context);
116        Raster newData = newImage.getData();
117        ColorModel colorModel = newImage.getColorModel();
118        if (colorModel == null)
119          colorModel = ColorModel.getRGBdefault();
120        SampleModel sampleModel = newData.getSampleModel();
121        DataBuffer dataBuffer = newData.getDataBuffer();
122        int width = newData.getWidth();
123        int height = newData.getHeight();
124
125        // Initialize the consumers.
126        Iterator it = consumers.iterator();
127        while (it.hasNext())
128          {
129            ImageConsumer target = (ImageConsumer) it.next();
130            target.setHints(ImageConsumer.COMPLETESCANLINES
131                            | ImageConsumer.SINGLEFRAME
132                            | ImageConsumer.SINGLEPASS
133                            | ImageConsumer.TOPDOWNLEFTRIGHT);
134            target.setDimensions(width, height);
135          }
136
137        // Work in scan-line order.
138        int[] newLine = new int[width];
139        int[] bands = new int[sampleModel.getNumBands()];
140        for (int y = 0; y < height; ++y)
141          {
142            for (int x = 0; x < width; ++x)
143              {
144                sampleModel.getPixel(x, y, bands, dataBuffer);
145                newLine[x] = colorModel.getDataElement(bands, 0);
146              }
147
148            // Tell the consumers about the new scan line.
149            it = consumers.iterator();
150            while (it.hasNext())
151              {
152                ImageConsumer target = (ImageConsumer) it.next();
153                target.setPixels(0, y, width, 1, colorModel, newLine, 0, width);
154              }
155          }
156
157        // Tell the consumers that we're done.
158        it = consumers.iterator();
159        while (it.hasNext())
160          {
161            ImageConsumer target = (ImageConsumer) it.next();
162            target.imageComplete(ImageConsumer.STATICIMAGEDONE);
163          }
164      }
165  }
166} // class RenderableImageProducer