001: /*
002: * $RCSfile: RenderableImageAdapter.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:57:20 $
010: * $State: Exp $
011: */
012: package javax.media.jai;
013:
014: import java.awt.RenderingHints;
015: import java.awt.image.RenderedImage;
016: import java.awt.image.renderable.RenderableImage;
017: import java.awt.image.renderable.RenderContext;
018: import java.beans.PropertyChangeListener;
019: import java.util.Hashtable;
020: import java.util.Vector;
021: import com.sun.media.jai.util.PropertyUtil;
022:
023: /**
024: * An adapter class for externally-generated RenderableImages. All
025: * methods are simply forwarded to the image being adapted. The
026: * purpose of this class is simply to ensure that the PropertySource
027: * interface is available for all JAI RenderableImages.
028: *
029: * <p> The set of properties available on the image will be a combination of
030: * those defined locally via <code>setProperty()</code> and those defined
031: * on the source image with the local properties taking precedence. No
032: * <code>PropertySourceChangeEvent</code> will be generated as a result of
033: * changes to the property set of the source image.
034: */
035: public final class RenderableImageAdapter implements RenderableImage,
036: WritablePropertySource {
037:
038: /** A reference to the external RenderableImage. */
039: private RenderableImage im;
040:
041: /** A helper object to manage firing events. */
042: private PropertyChangeSupportJAI eventManager = null;
043:
044: /** A helper object to manage the image properties. */
045: private WritablePropertySourceImpl properties = null;
046:
047: /**
048: * Adapts a RenderableImage into a RenderableImageAdapter.
049: * If the image is already an instance of RenderableImageAdapter,
050: * it is returned unchanged.
051: *
052: * @param im a RenderableImage.
053: *
054: * @return a RenderableImageAdapter.
055: *
056: * @throws IllegalArgumentException if <code>im</code> is <code>null</code>.
057: */
058: public static RenderableImageAdapter wrapRenderableImage(
059: RenderableImage im) {
060: if (im == null) {
061: throw new IllegalArgumentException(JaiI18N
062: .getString("Generic0"));
063: } else if (im instanceof RenderableImageAdapter) {
064: return (RenderableImageAdapter) im;
065: } else {
066: return new RenderableImageAdapter(im);
067: }
068: }
069:
070: /**
071: * Constructs a RenderableImageAdapter from a RenderableImage.
072: *
073: * @throws IllegalArgumentException if <code>im</code> is <code>null</code>.
074: */
075: public RenderableImageAdapter(RenderableImage im) {
076: if (im == null) {
077: throw new IllegalArgumentException(JaiI18N
078: .getString("Generic0"));
079: }
080:
081: this .im = im;
082: eventManager = new PropertyChangeSupportJAI(this );
083: properties = new WritablePropertySourceImpl(null, null,
084: eventManager);
085: }
086:
087: /**
088: * Returns the reference to the external <code>RenderableImage</code>
089: * originally supplied to the constructor.
090: *
091: * @since JAI 1.1.2
092: */
093: public final RenderableImage getWrappedImage() {
094: return im;
095: }
096:
097: /*
098: * Returns a vector of RenderableImages that are the sources of
099: * image data for this RenderableImage. Note that this method may
100: * return an empty vector, to indicate that the image has no sources,
101: * or null, to indicate that no information is available.
102: *
103: * @return a (possibly empty) Vector of RenderableImages, or null.
104: */
105: public final Vector getSources() {
106: return im.getSources();
107: }
108:
109: /**
110: * Gets a property from the property set of this image.
111: * If the property name is not recognized, java.awt.Image.UndefinedProperty
112: * will be returned.
113: *
114: * @param name the name of the property to get, as a String.
115: * @throws IllegalArgumentException if <code>name</code> is
116: * <code>null</code>.
117: * @return a reference to the property Object, or the value
118: * java.awt.Image.UndefinedProperty.
119: */
120: public final Object getProperty(String name) {
121: // Retrieve the property from the local cache.
122: Object property = properties.getProperty(name);
123:
124: // If it is still undefined, forward the call.
125: if (property == java.awt.Image.UndefinedProperty) {
126: property = im.getProperty(name);
127: }
128:
129: return property;
130: }
131:
132: /**
133: * Returns the class expected to be returned by a request for
134: * the property with the specified name. If this information
135: * is unavailable, <code>null</code> will be returned.
136: *
137: * @return The <code>Class</code> expected to be return by a
138: * request for the value of this property or <code>null</code>.
139: * @throws IllegalArgumentException if <code>name</code> is
140: * <code>null</code>.
141: *
142: * @since JAI 1.1
143: */
144: public Class getPropertyClass(String name) {
145: // Get the class if the property is local.
146: Class propClass = properties.getPropertyClass(name);
147:
148: // If not local ...
149: if (propClass == null) {
150: // Get the property value.
151: Object propValue = getProperty(name);
152:
153: if (propValue != java.awt.Image.UndefinedProperty) {
154: // If the property is defined, get the class.
155: propClass = propValue.getClass();
156: }
157: }
158:
159: return propClass;
160: }
161:
162: /**
163: * Returns a list of the properties recognized by this image. If
164: * no properties are available, <code>null</code> will be
165: * returned.
166: *
167: * @return an array of <code>String</code>s representing valid
168: * property names.
169: */
170: public final String[] getPropertyNames() {
171: return RenderedImageAdapter.mergePropertyNames(properties
172: .getPropertyNames(), im.getPropertyNames());
173: }
174:
175: /**
176: * Returns an array of <code>String</code>s recognized as names by
177: * this property source that begin with the supplied prefix. If
178: * no property names match, <code>null</code> will be returned.
179: * The comparison is done in a case-independent manner.
180: *
181: * @throws IllegalArgumentException if <code>prefix</code> is
182: * <code>null</code>.
183: * @return an array of <code>String</code>s giving the valid
184: * property names.
185: */
186: public String[] getPropertyNames(String prefix) {
187: return PropertyUtil
188: .getPropertyNames(getPropertyNames(), prefix);
189: }
190:
191: /**
192: * Sets a property on a <code>RenderableImageAdapter</code>.
193: *
194: * @param name a <code>String</code> containing the property's name.
195: * @param value the property, as a general <code>Object</code>.
196: *
197: * @throws IllegalArgumentException If <code>name</code> or
198: * <code>value</code> is <code>null</code>.
199: *
200: * @since JAI 1.1
201: */
202: public void setProperty(String name, Object value) {
203: properties.setProperty(name, value);
204: }
205:
206: /**
207: * Removes the named property from the <code>RenderableImageAdapter</code>.
208: *
209: * @throws IllegalArgumentException if <code>name</code> is
210: * <code>null</code>.
211: *
212: * @since JAI 1.1
213: */
214: public void removeProperty(String name) {
215: properties.removeProperty(name);
216: }
217:
218: /**
219: * Add a PropertyChangeListener to the listener list. The
220: * listener is registered for all properties.
221: *
222: * @since JAI 1.1
223: */
224: public void addPropertyChangeListener(
225: PropertyChangeListener listener) {
226: eventManager.addPropertyChangeListener(listener);
227: }
228:
229: /**
230: * Add a PropertyChangeListener for a specific property. The case of
231: * the name is ignored.
232: *
233: * @since JAI 1.1
234: */
235: public void addPropertyChangeListener(String propertyName,
236: PropertyChangeListener listener) {
237: eventManager.addPropertyChangeListener(propertyName, listener);
238: }
239:
240: /**
241: * Remove a PropertyChangeListener from the listener list. This
242: * removes a PropertyChangeListener that was registered for all
243: * properties.
244: *
245: * @since JAI 1.1
246: */
247: public void removePropertyChangeListener(
248: PropertyChangeListener listener) {
249: eventManager.removePropertyChangeListener(listener);
250: }
251:
252: /**
253: * Remove a PropertyChangeListener for a specific property. The case
254: * of the name is ignored.
255: *
256: * @since JAI 1.1
257: */
258: public void removePropertyChangeListener(String propertyName,
259: PropertyChangeListener listener) {
260: eventManager.removePropertyChangeListener(propertyName,
261: listener);
262: }
263:
264: /**
265: * Gets the width in user coordinate space. By convention, the
266: * usual width of a RenderableImage is equal to the image's aspect
267: * ratio (width divided by height).
268: *
269: * @return the width of the image in user coordinates.
270: */
271: public final float getWidth() {
272: return im.getWidth();
273: }
274:
275: /**
276: * Gets the height in user coordinate space. By convention, the
277: * usual height of a RenderedImage is equal to 1.0F.
278: *
279: * @return the height of the image in user coordinates.
280: */
281: public final float getHeight() {
282: return im.getHeight();
283: }
284:
285: /**
286: * Gets the minimum X coordinate of the rendering-independent image.
287: */
288: public final float getMinX() {
289: return im.getMinX();
290: }
291:
292: /**
293: * Gets the minimum Y coordinate of the rendering-independent image.
294: */
295: public final float getMinY() {
296: return im.getMinY();
297: }
298:
299: /**
300: * Returns true if successive renderings (that is, calls to
301: * createRendering() or createScaledRendering()) with the same arguments
302: * may produce different results. This method may be used to
303: * determine whether an existing rendering may be cached and
304: * reused.
305: */
306: public final boolean isDynamic() {
307: return im.isDynamic();
308: }
309:
310: /**
311: * Gets a RenderedImage instance of this image with width w, and
312: * height h in pixels. The RenderContext is built automatically
313: * with an appropriate usr2dev transform and an area of interest
314: * of the full image. All the rendering hints come from hints
315: * passed in.
316: *
317: * @param w the width of rendered image in pixels.
318: * @param h the height of rendered image in pixels.
319: * @param hints a RenderingHints object containing rendering hints.
320: * @return a RenderedImage containing the rendered data.
321: */
322: public final RenderedImage createScaledRendering(int w, int h,
323: RenderingHints hints) {
324: return im.createScaledRendering(w, h, hints);
325: }
326:
327: /**
328: * Gets a RenderedImage instance of this image with a default
329: * width and height in pixels. The RenderContext is built
330: * automatically with an appropriate usr2dev transform and an area
331: * of interest of the full image. All the rendering hints come
332: * from hints passed in. Implementors of this interface must be
333: * sure that there is a defined default width and height.
334: *
335: * @return a RenderedImage containing the rendered data.
336: */
337: public final RenderedImage createDefaultRendering() {
338: return im.createDefaultRendering();
339: }
340:
341: /**
342: * Gets a RenderedImage instance of this image from a
343: * RenderContext. This is the most general way to obtain a
344: * rendering of a RenderableImage.
345: *
346: * @param renderContext the RenderContext to use to produce the rendering.
347: * @return a RenderedImage containing the rendered data.
348: */
349: public final RenderedImage createRendering(
350: RenderContext renderContext) {
351: return im.createRendering(renderContext);
352: }
353: }
|