This commit is contained in:
Xiomara Jayasena 2008-06-12 11:46:57 -07:00
commit cd6060aace
114 changed files with 17770 additions and 404 deletions

View File

@ -1,3 +1,4 @@
1cc8dd79fd1cd13d36b385196271a29632c67c3b jdk7-b24
bf2517e15f0c0f950e5b3143c4ca11e2df73dcc1 jdk7-b25
5ae7db536e3fcf6be78e45b240a9058095e0ed38 jdk7-b26
67052ac87fc927d048e62ec54ff42adb230d3f7c jdk7-b27

View File

@ -1,3 +1,4 @@
cfeea66a3fa8ca3686a7cfa2d0ce8ab0169f168d jdk7-b24
cbc8ad9dd0e085a607427ea35411990982f19a36 jdk7-b25
9410f77cc30c604d1caf7c9fe3a57fa19e1acbe8 jdk7-b26
11b4dc9f2be3523ef989a0db8459eb56b3045c3a jdk7-b27

View File

@ -1,3 +1,4 @@
55540e827aef970ecc010b7e06b912d991c8e3ce jdk7-b24
5e61d5df62586474414d1058e9186441aa908f51 jdk7-b25
0043eb3d4e628f049ff80a8c223b5657136085e7 jdk7-b26
e84e9018bebbf3e5bafc5706e7882a15cb1c7d99 jdk7-b27

View File

@ -1,3 +1,4 @@
a61af66fc99eb5ec9d50c05b0c599757b1289ceb jdk7-b24
7836be3e92d0a4f9ee7566f602c91f5609534e66 jdk7-b25
ad0b851458ff9d1d490ed2d79bb84f75a9fdb753 jdk7-b26
e3d2692f8442e2d951166dc9bd9a330684754438 jdk7-b27

View File

@ -1,3 +1,4 @@
6ce5f4757bde08f7470cbb9f0b46da8f2f3d4f56 jdk7-b24
a3b3ba7d6034dc754b51ddc3d281399ac1cae5f1 jdk7-b25
da43cb85fac1646d6f97e4a35e510bbfdff97bdb jdk7-b26
bafed478d67c3acf7744aaad88b9404261ea6739 jdk7-b27

View File

@ -1,3 +1,4 @@
0961a4a211765fea071b8dac419003ee0c3d5973 jdk7-b24
59fd8224ba2da5c2d8d4c68e33cf33ab41ce8de0 jdk7-b25
debd37e1a422e580edb086c95d6e89199133a39c jdk7-b26
27d8f42862c11b4ddc4af2dd2d2a3cd86cda04c2 jdk7-b27

View File

@ -2,3 +2,4 @@
75fca0b0ab83ab1392e615910cea020f66535390 jdk7-b25
fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26
3e599d98875ddf919c8ea11cff9b3a99ba631a9b jdk7-b27
02e4c5348592a8d7fc2cba28bc5f8e35c0e17277 jdk7-b28

View File

@ -126,44 +126,10 @@ com/sun/media/sound/SimpleInputDeviceProvider\$$1.class \
com/sun/media/sound/SimpleInputDeviceProvider\$$InputDeviceInfo.class \
com/sun/media/sound/SimpleInputDeviceProvider.class
PLUG_AWT_CLASS_NAMES = \
java/awt/color/CMMException.class \
java/awt/color/ColorSpace.class \
java/awt/color/ICC_ColorSpace.class \
java/awt/color/ICC_Profile\$$1.class \
java/awt/color/ICC_Profile\$$2.class \
java/awt/color/ICC_Profile\$$3.class \
java/awt/color/ICC_Profile.class \
java/awt/color/ICC_ProfileGray.class \
java/awt/color/ICC_ProfileRGB.class \
java/awt/image/BandedSampleModel.class \
java/awt/image/ColorConvertOp.class \
java/awt/image/ComponentSampleModel.class \
java/awt/image/DataBuffer\$$1.class \
java/awt/image/DataBuffer.class \
java/awt/image/DataBufferByte.class \
java/awt/image/DataBufferInt.class \
java/awt/image/DataBufferShort.class \
java/awt/image/DataBufferUShort.class \
java/awt/image/MultiPixelPackedSampleModel.class \
java/awt/image/Raster.class \
java/awt/image/RenderedImage.class \
java/awt/image/SampleModel.class \
java/awt/image/SinglePixelPackedSampleModel.class \
java/awt/image/WritableRaster.class \
java/awt/image/WritableRenderedImage.class \
java/awt/image/renderable/ContextualRenderedImageFactory.class \
java/awt/image/renderable/ParameterBlock.class \
java/awt/image/renderable/RenderContext.class \
java/awt/image/renderable/RenderableImage.class \
java/awt/image/renderable/RenderableImageOp.class \
java/awt/image/renderable/RenderableImageProducer.class \
java/awt/image/renderable/RenderedImageFactory.class
# Class list temp files (used by both import and export of plugs)
PLUG_TEMPDIR=$(ABS_TEMPDIR)/plugs
PLUG_CLASS_AREAS = jmf sound awt
PLUG_CLASS_AREAS = jmf sound
PLUG_CLISTS = $(PLUG_CLASS_AREAS:%=$(PLUG_TEMPDIR)/%.clist)
# Create jargs file command
@ -186,11 +152,6 @@ $(PLUG_TEMPDIR)/sound.clist:
@for i in $(PLUG_SOUND_CLASS_NAMES) ; do \
$(ECHO) "$$i" >> $@ ; \
done
$(PLUG_TEMPDIR)/awt.clist:
@$(prep-target)
@for i in $(PLUG_AWT_CLASS_NAMES) ; do \
$(ECHO) "$$i" >> $@ ; \
done
$(PLUG_TEMPDIR)/all.clist: $(PLUG_CLISTS)
@$(prep-target)
$(CAT) $(PLUG_CLISTS) > $@
@ -198,8 +159,6 @@ $(PLUG_TEMPDIR)/jmf.jargs: $(PLUG_TEMPDIR)/jmf.clist
$(plug-create-jargs)
$(PLUG_TEMPDIR)/sound.jargs: $(PLUG_TEMPDIR)/sound.clist
$(plug-create-jargs)
$(PLUG_TEMPDIR)/awt.jargs: $(PLUG_TEMPDIR)/awt.clist
$(plug-create-jargs)
$(PLUG_TEMPDIR)/all.jargs: $(PLUG_TEMPDIR)/all.clist
$(plug-create-jargs)
@ -235,15 +194,12 @@ import-binary-plug-jmf-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/jmf.clist
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/jmf.clist)
import-binary-plug-sound-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/sound.clist
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/sound.clist)
import-binary-plug-awt-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/awt.clist
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/awt.clist)
# Import all classes from the jar file
import-binary-plug-jar: \
import-binary-plug-jmf-classes \
import-binary-plug-sound-classes \
import-binary-plug-awt-classes
import-binary-plug-sound-classes
# Import native libraries
@ -286,7 +242,6 @@ import-binary-plugs: \
import-binary-plug-jar \
import-binary-plug-jmf-classes \
import-binary-plug-sound-classes \
import-binary-plug-awt-classes \
import-binary-plug-jsound-library
else # !OPENJDK

View File

@ -28,24 +28,12 @@ PACKAGE = java.awt
PRODUCT = sun
include $(BUILDDIR)/common/Defs.gmk
# WARNING: Make sure the OPENJDK plugs are up-to-date, see make/common/internal/BinaryPlugs.gmk
#
# Files
#
AUTO_FILES_JAVA_DIRS = java/awt sun/awt/geom
#
# Specific to OPENJDK
#
ifdef OPENJDK
build: import-binary-plug-awt-classes
include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
endif
build: properties cursors
#

View File

@ -41,12 +41,8 @@ endif # OPENJDK
ICCPROFILE_DEST_DIR = $(LIBDIR)/cmm
iccprofiles: $(ICCPROFILE_DEST_DIR)/sRGB.pf $(ICCPROFILE_DEST_DIR)/GRAY.pf \
$(ICCPROFILE_DEST_DIR)/CIEXYZ.pf
ifndef OPENJDK
iccprofiles: $(ICCPROFILE_DEST_DIR)/PYCC.pf \
$(ICCPROFILE_DEST_DIR)/LINEAR_RGB.pf
endif
$(ICCPROFILE_DEST_DIR)/CIEXYZ.pf $(ICCPROFILE_DEST_DIR)/PYCC.pf \
$(ICCPROFILE_DEST_DIR)/LINEAR_RGB.pf
$(ICCPROFILE_DEST_DIR)/sRGB.pf: $(ICCPROFILE_SRC_DIR)/sRGB.pf
$(RM) $(ICCPROFILE_DEST_DIR)/sRGB.pf

View File

@ -113,7 +113,9 @@ FILES_cpp_shared = \
ifeq ($(PLATFORM),windows)
FILES_c_platform = fontpath.c
FILES_c_platform = fontpath.c \
lcdglyph.c
FILES_cpp_platform = D3DTextRenderer.cpp
else
FILES_c_platform = X11FontScaler.c \

View File

@ -63,6 +63,7 @@ FILES_export = \
java/awt/Font.java \
java/text/Bidi.java \
sun/font/FileFont.java \
sun/font/FileFontStrike.java \
sun/font/FontManager.java \
sun/font/GlyphList.java \
sun/font/NativeFont.java \

View File

@ -3057,10 +3057,24 @@ public abstract class Component implements ImageObserver, MenuContainer,
// services. Additionally, the request is restricted to
// the bounds of the component.
if (parent != null) {
int px = this.x + ((x < 0) ? 0 : x);
int py = this.y + ((y < 0) ? 0 : y);
if (x < 0) {
width += x;
x = 0;
}
if (y < 0) {
height += y;
y = 0;
}
int pwidth = (width > this.width) ? this.width : width;
int pheight = (height > this.height) ? this.height : height;
if (pwidth <= 0 || pheight <= 0) {
return;
}
int px = this.x + x;
int py = this.y + y;
parent.repaint(tm, px, py, pwidth, pheight);
}
} else {

View File

@ -711,7 +711,7 @@ public class Font implements java.io.Serializable
EBIDI_EMBEDDING, EJUSTIFICATION,
EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE,
ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING,
ELIGATURES, ETRACKING);
ELIGATURES, ETRACKING, ESUPERSCRIPT);
private static final int EXTRA_MASK =
AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH);
@ -1970,7 +1970,6 @@ public class Font implements java.io.Serializable
* in the JDK - and the only likely caller - is in this same class.
*/
private float getItalicAngle(FontRenderContext frc) {
AffineTransform at = (isTransformed()) ? getTransform() : identityTx;
Object aa, fm;
if (frc == null) {
aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;
@ -1979,7 +1978,7 @@ public class Font implements java.io.Serializable
aa = frc.getAntiAliasingHint();
fm = frc.getFractionalMetricsHint();
}
return getFont2D().getItalicAngle(this, at, aa, fm);
return getFont2D().getItalicAngle(this, identityTx, aa, fm);
}
/**

View File

@ -0,0 +1,57 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
Created by gbp, October 25, 1997
*
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.color;
/**
* This exception is thrown if the native CMM returns an error.
*/
public class CMMException extends java.lang.RuntimeException {
/**
* Constructs a CMMException with the specified detail message.
* @param s the specified detail message
*/
public CMMException (String s) {
super (s);
}
}

View File

@ -0,0 +1,611 @@
/*
* Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.color;
import sun.java2d.cmm.PCMM;
import sun.java2d.cmm.CMSManager;
/**
* This abstract class is used to serve as a color space tag to identify the
* specific color space of a Color object or, via a ColorModel object,
* of an Image, a BufferedImage, or a GraphicsDevice. It contains
* methods that transform colors in a specific color space to/from sRGB
* and to/from a well-defined CIEXYZ color space.
* <p>
* For purposes of the methods in this class, colors are represented as
* arrays of color components represented as floats in a normalized range
* defined by each ColorSpace. For many ColorSpaces (e.g. sRGB), this
* range is 0.0 to 1.0. However, some ColorSpaces have components whose
* values have a different range. Methods are provided to inquire per
* component minimum and maximum normalized values.
* <p>
* Several variables are defined for purposes of referring to color
* space types (e.g. TYPE_RGB, TYPE_XYZ, etc.) and to refer to specific
* color spaces (e.g. CS_sRGB and CS_CIEXYZ).
* sRGB is a proposed standard RGB color space. For more information,
* see <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
* http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
* </A>.
* <p>
* The purpose of the methods to transform to/from the well-defined
* CIEXYZ color space is to support conversions between any two color
* spaces at a reasonably high degree of accuracy. It is expected that
* particular implementations of subclasses of ColorSpace (e.g.
* ICC_ColorSpace) will support high performance conversion based on
* underlying platform color management systems.
* <p>
* The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be
* described as follows:
<pre>
&nbsp; CIEXYZ
&nbsp; viewing illuminance: 200 lux
&nbsp; viewing white point: CIE D50
&nbsp; media white point: "that of a perfectly reflecting diffuser" -- D50
&nbsp; media black point: 0 lux or 0 Reflectance
&nbsp; flare: 1 percent
&nbsp; surround: 20percent of the media white point
&nbsp; media description: reflection print (i.e., RLAB, Hunt viewing media)
&nbsp; note: For developers creating an ICC profile for this conversion
&nbsp; space, the following is applicable. Use a simple Von Kries
&nbsp; white point adaptation folded into the 3X3 matrix parameters
&nbsp; and fold the flare and surround effects into the three
&nbsp; one-dimensional lookup tables (assuming one uses the minimal
&nbsp; model for monitors).
</pre>
*
* <p>
* @see ICC_ColorSpace
*/
public abstract class ColorSpace implements java.io.Serializable {
static final long serialVersionUID = -409452704308689724L;
private int type;
private int numComponents;
private transient String [] compName = null;
// Cache of singletons for the predefined color spaces.
private static ColorSpace sRGBspace;
private static ColorSpace XYZspace;
private static ColorSpace PYCCspace;
private static ColorSpace GRAYspace;
private static ColorSpace LINEAR_RGBspace;
/**
* Any of the family of XYZ color spaces.
*/
public static final int TYPE_XYZ = 0;
/**
* Any of the family of Lab color spaces.
*/
public static final int TYPE_Lab = 1;
/**
* Any of the family of Luv color spaces.
*/
public static final int TYPE_Luv = 2;
/**
* Any of the family of YCbCr color spaces.
*/
public static final int TYPE_YCbCr = 3;
/**
* Any of the family of Yxy color spaces.
*/
public static final int TYPE_Yxy = 4;
/**
* Any of the family of RGB color spaces.
*/
public static final int TYPE_RGB = 5;
/**
* Any of the family of GRAY color spaces.
*/
public static final int TYPE_GRAY = 6;
/**
* Any of the family of HSV color spaces.
*/
public static final int TYPE_HSV = 7;
/**
* Any of the family of HLS color spaces.
*/
public static final int TYPE_HLS = 8;
/**
* Any of the family of CMYK color spaces.
*/
public static final int TYPE_CMYK = 9;
/**
* Any of the family of CMY color spaces.
*/
public static final int TYPE_CMY = 11;
/**
* Generic 2 component color spaces.
*/
public static final int TYPE_2CLR = 12;
/**
* Generic 3 component color spaces.
*/
public static final int TYPE_3CLR = 13;
/**
* Generic 4 component color spaces.
*/
public static final int TYPE_4CLR = 14;
/**
* Generic 5 component color spaces.
*/
public static final int TYPE_5CLR = 15;
/**
* Generic 6 component color spaces.
*/
public static final int TYPE_6CLR = 16;
/**
* Generic 7 component color spaces.
*/
public static final int TYPE_7CLR = 17;
/**
* Generic 8 component color spaces.
*/
public static final int TYPE_8CLR = 18;
/**
* Generic 9 component color spaces.
*/
public static final int TYPE_9CLR = 19;
/**
* Generic 10 component color spaces.
*/
public static final int TYPE_ACLR = 20;
/**
* Generic 11 component color spaces.
*/
public static final int TYPE_BCLR = 21;
/**
* Generic 12 component color spaces.
*/
public static final int TYPE_CCLR = 22;
/**
* Generic 13 component color spaces.
*/
public static final int TYPE_DCLR = 23;
/**
* Generic 14 component color spaces.
*/
public static final int TYPE_ECLR = 24;
/**
* Generic 15 component color spaces.
*/
public static final int TYPE_FCLR = 25;
/**
* The sRGB color space defined at
* <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
* http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
* </A>.
*/
public static final int CS_sRGB = 1000;
/**
* A built-in linear RGB color space. This space is based on the
* same RGB primaries as CS_sRGB, but has a linear tone reproduction curve.
*/
public static final int CS_LINEAR_RGB = 1004;
/**
* The CIEXYZ conversion color space defined above.
*/
public static final int CS_CIEXYZ = 1001;
/**
* The Photo YCC conversion color space.
*/
public static final int CS_PYCC = 1002;
/**
* The built-in linear gray scale color space.
*/
public static final int CS_GRAY = 1003;
/**
* Constructs a ColorSpace object given a color space type
* and the number of components.
* @param type one of the <CODE>ColorSpace</CODE> type constants
* @param numcomponents the number of components in the color space
*/
protected ColorSpace (int type, int numcomponents) {
this.type = type;
this.numComponents = numcomponents;
}
/**
* Returns a ColorSpace representing one of the specific
* predefined color spaces.
* @param colorspace a specific color space identified by one of
* the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB,
* CS_CIEXYZ, CS_GRAY, or CS_PYCC)
* @return the requested <CODE>ColorSpace</CODE> object
*/
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public static ColorSpace getInstance (int colorspace)
{
ColorSpace theColorSpace;
switch (colorspace) {
case CS_sRGB:
synchronized(ColorSpace.class) {
if (sRGBspace == null) {
ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB);
sRGBspace = new ICC_ColorSpace (theProfile);
}
theColorSpace = sRGBspace;
}
break;
case CS_CIEXYZ:
synchronized(ColorSpace.class) {
if (XYZspace == null) {
ICC_Profile theProfile =
ICC_Profile.getInstance (CS_CIEXYZ);
XYZspace = new ICC_ColorSpace (theProfile);
}
theColorSpace = XYZspace;
}
break;
case CS_PYCC:
synchronized(ColorSpace.class) {
if (PYCCspace == null) {
ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC);
PYCCspace = new ICC_ColorSpace (theProfile);
}
theColorSpace = PYCCspace;
}
break;
case CS_GRAY:
synchronized(ColorSpace.class) {
if (GRAYspace == null) {
ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY);
GRAYspace = new ICC_ColorSpace (theProfile);
/* to allow access from java.awt.ColorModel */
CMSManager.GRAYspace = GRAYspace;
}
theColorSpace = GRAYspace;
}
break;
case CS_LINEAR_RGB:
synchronized(ColorSpace.class) {
if (LINEAR_RGBspace == null) {
ICC_Profile theProfile =
ICC_Profile.getInstance(CS_LINEAR_RGB);
LINEAR_RGBspace = new ICC_ColorSpace (theProfile);
/* to allow access from java.awt.ColorModel */
CMSManager.LINEAR_RGBspace = LINEAR_RGBspace;
}
theColorSpace = LINEAR_RGBspace;
}
break;
default:
throw new IllegalArgumentException ("Unknown color space");
}
return theColorSpace;
}
/**
* Returns true if the ColorSpace is CS_sRGB.
* @return <CODE>true</CODE> if this is a <CODE>CS_sRGB</CODE> color
* space, <code>false</code> if it is not
*/
public boolean isCS_sRGB () {
/* REMIND - make sure we know sRGBspace exists already */
return (this == sRGBspace);
}
/**
* Transforms a color value assumed to be in this ColorSpace
* into a value in the default CS_sRGB color space.
* <p>
* This method transforms color values using algorithms designed
* to produce the best perceptual match between input and output
* colors. In order to do colorimetric conversion of color values,
* you should use the <code>toCIEXYZ</code>
* method of this color space to first convert from the input
* color space to the CS_CIEXYZ color space, and then use the
* <code>fromCIEXYZ</code> method of the CS_sRGB color space to
* convert from CS_CIEXYZ to the output color space.
* See {@link #toCIEXYZ(float[]) toCIEXYZ} and
* {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
* <p>
* @param colorvalue a float array with length of at least the number
* of components in this ColorSpace
* @return a float array of length 3
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least the number of components in this ColorSpace
*/
public abstract float[] toRGB(float[] colorvalue);
/**
* Transforms a color value assumed to be in the default CS_sRGB
* color space into this ColorSpace.
* <p>
* This method transforms color values using algorithms designed
* to produce the best perceptual match between input and output
* colors. In order to do colorimetric conversion of color values,
* you should use the <code>toCIEXYZ</code>
* method of the CS_sRGB color space to first convert from the input
* color space to the CS_CIEXYZ color space, and then use the
* <code>fromCIEXYZ</code> method of this color space to
* convert from CS_CIEXYZ to the output color space.
* See {@link #toCIEXYZ(float[]) toCIEXYZ} and
* {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
* <p>
* @param rgbvalue a float array with length of at least 3
* @return a float array with length equal to the number of
* components in this ColorSpace
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least 3
*/
public abstract float[] fromRGB(float[] rgbvalue);
/**
* Transforms a color value assumed to be in this ColorSpace
* into the CS_CIEXYZ conversion color space.
* <p>
* This method transforms color values using relative colorimetry,
* as defined by the International Color Consortium standard. This
* means that the XYZ values returned by this method are represented
* relative to the D50 white point of the CS_CIEXYZ color space.
* This representation is useful in a two-step color conversion
* process in which colors are transformed from an input color
* space to CS_CIEXYZ and then to an output color space. This
* representation is not the same as the XYZ values that would
* be measured from the given color value by a colorimeter.
* A further transformation is necessary to compute the XYZ values
* that would be measured using current CIE recommended practices.
* See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of
* <code>ICC_ColorSpace</code> for further information.
* <p>
* @param colorvalue a float array with length of at least the number
* of components in this ColorSpace
* @return a float array of length 3
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least the number of components in this ColorSpace.
*/
public abstract float[] toCIEXYZ(float[] colorvalue);
/**
* Transforms a color value assumed to be in the CS_CIEXYZ conversion
* color space into this ColorSpace.
* <p>
* This method transforms color values using relative colorimetry,
* as defined by the International Color Consortium standard. This
* means that the XYZ argument values taken by this method are represented
* relative to the D50 white point of the CS_CIEXYZ color space.
* This representation is useful in a two-step color conversion
* process in which colors are transformed from an input color
* space to CS_CIEXYZ and then to an output color space. The color
* values returned by this method are not those that would produce
* the XYZ value passed to the method when measured by a colorimeter.
* If you have XYZ values corresponding to measurements made using
* current CIE recommended practices, they must be converted to D50
* relative values before being passed to this method.
* See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of
* <code>ICC_ColorSpace</code> for further information.
* <p>
* @param colorvalue a float array with length of at least 3
* @return a float array with length equal to the number of
* components in this ColorSpace
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least 3
*/
public abstract float[] fromCIEXYZ(float[] colorvalue);
/**
* Returns the color space type of this ColorSpace (for example
* TYPE_RGB, TYPE_XYZ, ...). The type defines the
* number of components of the color space and the interpretation,
* e.g. TYPE_RGB identifies a color space with three components - red,
* green, and blue. It does not define the particular color
* characteristics of the space, e.g. the chromaticities of the
* primaries.
*
* @return the type constant that represents the type of this
* <CODE>ColorSpace</CODE>
*/
public int getType() {
return type;
}
/**
* Returns the number of components of this ColorSpace.
* @return The number of components in this <CODE>ColorSpace</CODE>.
*/
public int getNumComponents() {
return numComponents;
}
/**
* Returns the name of the component given the component index.
*
* @param idx the component index
* @return the name of the component at the specified index
* @throws IllegalArgumentException if <code>idx</code> is
* less than 0 or greater than numComponents - 1
*/
public String getName (int idx) {
/* REMIND - handle common cases here */
if ((idx < 0) || (idx > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + idx);
}
if (compName == null) {
switch (type) {
case ColorSpace.TYPE_XYZ:
compName = new String[] {"X", "Y", "Z"};
break;
case ColorSpace.TYPE_Lab:
compName = new String[] {"L", "a", "b"};
break;
case ColorSpace.TYPE_Luv:
compName = new String[] {"L", "u", "v"};
break;
case ColorSpace.TYPE_YCbCr:
compName = new String[] {"Y", "Cb", "Cr"};
break;
case ColorSpace.TYPE_Yxy:
compName = new String[] {"Y", "x", "y"};
break;
case ColorSpace.TYPE_RGB:
compName = new String[] {"Red", "Green", "Blue"};
break;
case ColorSpace.TYPE_GRAY:
compName = new String[] {"Gray"};
break;
case ColorSpace.TYPE_HSV:
compName = new String[] {"Hue", "Saturation", "Value"};
break;
case ColorSpace.TYPE_HLS:
compName = new String[] {"Hue", "Lightness",
"Saturation"};
break;
case ColorSpace.TYPE_CMYK:
compName = new String[] {"Cyan", "Magenta", "Yellow",
"Black"};
break;
case ColorSpace.TYPE_CMY:
compName = new String[] {"Cyan", "Magenta", "Yellow"};
break;
default:
String [] tmp = new String[numComponents];
for (int i = 0; i < tmp.length; i++) {
tmp[i] = "Unnamed color component(" + i + ")";
}
compName = tmp;
}
}
return compName[idx];
}
/**
* Returns the minimum normalized color component value for the
* specified component. The default implementation in this abstract
* class returns 0.0 for all components. Subclasses should override
* this method if necessary.
*
* @param component the component index
* @return the minimum normalized component value
* @throws IllegalArgumentException if component is less than 0 or
* greater than numComponents - 1
* @since 1.4
*/
public float getMinValue(int component) {
if ((component < 0) || (component > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
return 0.0f;
}
/**
* Returns the maximum normalized color component value for the
* specified component. The default implementation in this abstract
* class returns 1.0 for all components. Subclasses should override
* this method if necessary.
*
* @param component the component index
* @return the maximum normalized component value
* @throws IllegalArgumentException if component is less than 0 or
* greater than numComponents - 1
* @since 1.4
*/
public float getMaxValue(int component) {
if ((component < 0) || (component > numComponents - 1)) {
throw new IllegalArgumentException(
"Component index out of range: " + component);
}
return 1.0f;
}
/* Returns true if cspace is the XYZspace.
*/
static boolean isCS_CIEXYZ(ColorSpace cspace) {
return (cspace == XYZspace);
}
}

View File

@ -0,0 +1,616 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.color;
import sun.java2d.cmm.ColorTransform;
import sun.java2d.cmm.CMSManager;
import sun.java2d.cmm.PCMM;
/**
*
* The ICC_ColorSpace class is an implementation of the abstract
* ColorSpace class. This representation of
* device independent and device dependent color spaces is based on the
* International Color Consortium Specification ICC.1:2001-12, File Format for
* Color Profiles (see <A href="http://www.color.org">http://www.color.org</A>).
* <p>
* Typically, a Color or ColorModel would be associated with an ICC
* Profile which is either an input, display, or output profile (see
* the ICC specification). There are other types of ICC Profiles, e.g.
* abstract profiles, device link profiles, and named color profiles,
* which do not contain information appropriate for representing the color
* space of a color, image, or device (see ICC_Profile).
* Attempting to create an ICC_ColorSpace object from an inappropriate ICC
* Profile is an error.
* <p>
* ICC Profiles represent transformations from the color space of
* the profile (e.g. a monitor) to a Profile Connection Space (PCS).
* Profiles of interest for tagging images or colors have a
* PCS which is one of the device independent
* spaces (one CIEXYZ space and two CIELab spaces) defined in the
* ICC Profile Format Specification. Most profiles of interest
* either have invertible transformations or explicitly specify
* transformations going both directions. Should an ICC_ColorSpace
* object be used in a way requiring a conversion from PCS to
* the profile's native space and there is inadequate data to
* correctly perform the conversion, the ICC_ColorSpace object will
* produce output in the specified type of color space (e.g. TYPE_RGB,
* TYPE_CMYK, etc.), but the specific color values of the output data
* will be undefined.
* <p>
* The details of this class are not important for simple applets,
* which draw in a default color space or manipulate and display
* imported images with a known color space. At most, such applets
* would need to get one of the default color spaces via
* ColorSpace.getInstance().
* <p>
* @see ColorSpace
* @see ICC_Profile
*/
public class ICC_ColorSpace extends ColorSpace {
static final long serialVersionUID = 3455889114070431483L;
private ICC_Profile thisProfile;
private float[] minVal;
private float[] maxVal;
private float[] diffMinMax;
private float[] invDiffMinMax;
private boolean needScaleInit = true;
// {to,from}{RGB,CIEXYZ} methods create and cache these when needed
private transient ColorTransform this2srgb;
private transient ColorTransform srgb2this;
private transient ColorTransform this2xyz;
private transient ColorTransform xyz2this;
/**
* Constructs a new ICC_ColorSpace from an ICC_Profile object.
* @param profile the specified ICC_Profile object
* @exception IllegalArgumentException if profile is inappropriate for
* representing a ColorSpace.
*/
public ICC_ColorSpace (ICC_Profile profile) {
super (profile.getColorSpaceType(), profile.getNumComponents());
int profileClass = profile.getProfileClass();
/* REMIND - is NAMEDCOLOR OK? */
if ((profileClass != ICC_Profile.CLASS_INPUT) &&
(profileClass != ICC_Profile.CLASS_DISPLAY) &&
(profileClass != ICC_Profile.CLASS_OUTPUT) &&
(profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
(profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
(profileClass != ICC_Profile.CLASS_ABSTRACT)) {
throw new IllegalArgumentException("Invalid profile type");
}
thisProfile = profile;
setMinMax();
}
/**
* Returns the ICC_Profile for this ICC_ColorSpace.
* @return the ICC_Profile for this ICC_ColorSpace.
*/
public ICC_Profile getProfile() {
return thisProfile;
}
/**
* Transforms a color value assumed to be in this ColorSpace
* into a value in the default CS_sRGB color space.
* <p>
* This method transforms color values using algorithms designed
* to produce the best perceptual match between input and output
* colors. In order to do colorimetric conversion of color values,
* you should use the <code>toCIEXYZ</code>
* method of this color space to first convert from the input
* color space to the CS_CIEXYZ color space, and then use the
* <code>fromCIEXYZ</code> method of the CS_sRGB color space to
* convert from CS_CIEXYZ to the output color space.
* See {@link #toCIEXYZ(float[]) toCIEXYZ} and
* {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
* <p>
* @param colorvalue a float array with length of at least the number
* of components in this ColorSpace.
* @return a float array of length 3.
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least the number of components in this ColorSpace.
*/
public float[] toRGB (float[] colorvalue) {
if (this2srgb == null) {
ColorTransform[] transformList = new ColorTransform [2];
ICC_ColorSpace srgbCS =
(ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
PCMM mdl = CMSManager.getModule();
transformList[0] = mdl.createTransform(
thisProfile, ColorTransform.Any, ColorTransform.In);
transformList[1] = mdl.createTransform(
srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
this2srgb = mdl.createTransform(transformList);
if (needScaleInit) {
setComponentScaling();
}
}
int nc = this.getNumComponents();
short tmp[] = new short[nc];
for (int i = 0; i < nc; i++) {
tmp[i] = (short)
((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
}
tmp = this2srgb.colorConvert(tmp, null);
float[] result = new float [3];
for (int i = 0; i < 3; i++) {
result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f;
}
return result;
}
/**
* Transforms a color value assumed to be in the default CS_sRGB
* color space into this ColorSpace.
* <p>
* This method transforms color values using algorithms designed
* to produce the best perceptual match between input and output
* colors. In order to do colorimetric conversion of color values,
* you should use the <code>toCIEXYZ</code>
* method of the CS_sRGB color space to first convert from the input
* color space to the CS_CIEXYZ color space, and then use the
* <code>fromCIEXYZ</code> method of this color space to
* convert from CS_CIEXYZ to the output color space.
* See {@link #toCIEXYZ(float[]) toCIEXYZ} and
* {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
* <p>
* @param rgbvalue a float array with length of at least 3.
* @return a float array with length equal to the number of
* components in this ColorSpace.
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least 3.
*/
public float[] fromRGB(float[] rgbvalue) {
if (srgb2this == null) {
ColorTransform[] transformList = new ColorTransform [2];
ICC_ColorSpace srgbCS =
(ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
PCMM mdl = CMSManager.getModule();
transformList[0] = mdl.createTransform(
srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In);
transformList[1] = mdl.createTransform(
thisProfile, ColorTransform.Any, ColorTransform.Out);
srgb2this = mdl.createTransform(transformList);
if (needScaleInit) {
setComponentScaling();
}
}
short tmp[] = new short[3];
for (int i = 0; i < 3; i++) {
tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f);
}
tmp = srgb2this.colorConvert(tmp, null);
int nc = this.getNumComponents();
float[] result = new float [nc];
for (int i = 0; i < nc; i++) {
result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
diffMinMax[i] + minVal[i];
}
return result;
}
/**
* Transforms a color value assumed to be in this ColorSpace
* into the CS_CIEXYZ conversion color space.
* <p>
* This method transforms color values using relative colorimetry,
* as defined by the ICC Specification. This
* means that the XYZ values returned by this method are represented
* relative to the D50 white point of the CS_CIEXYZ color space.
* This representation is useful in a two-step color conversion
* process in which colors are transformed from an input color
* space to CS_CIEXYZ and then to an output color space. This
* representation is not the same as the XYZ values that would
* be measured from the given color value by a colorimeter.
* A further transformation is necessary to compute the XYZ values
* that would be measured using current CIE recommended practices.
* The paragraphs below explain this in more detail.
* <p>
* The ICC standard uses a device independent color space (DICS) as the
* mechanism for converting color from one device to another device. In
* this architecture, colors are converted from the source device's color
* space to the ICC DICS and then from the ICC DICS to the destination
* device's color space. The ICC standard defines device profiles which
* contain transforms which will convert between a device's color space
* and the ICC DICS. The overall conversion of colors from a source
* device to colors of a destination device is done by connecting the
* device-to-DICS transform of the profile for the source device to the
* DICS-to-device transform of the profile for the destination device.
* For this reason, the ICC DICS is commonly referred to as the profile
* connection space (PCS). The color space used in the methods
* toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
* Specification. This is also the color space represented by
* ColorSpace.CS_CIEXYZ.
* <p>
* The XYZ values of a color are often represented as relative to some
* white point, so the actual meaning of the XYZ values cannot be known
* without knowing the white point of those values. This is known as
* relative colorimetry. The PCS uses a white point of D50, so the XYZ
* values of the PCS are relative to D50. For example, white in the PCS
* will have the XYZ values of D50, which is defined to be X=.9642,
* Y=1.000, and Z=0.8249. This white point is commonly used for graphic
* arts applications, but others are often used in other applications.
* <p>
* To quantify the color characteristics of a device such as a printer
* or monitor, measurements of XYZ values for particular device colors
* are typically made. For purposes of this discussion, the term
* device XYZ values is used to mean the XYZ values that would be
* measured from device colors using current CIE recommended practices.
* <p>
* Converting between device XYZ values and the PCS XYZ values returned
* by this method corresponds to converting between the device's color
* space, as represented by CIE colorimetric values, and the PCS. There
* are many factors involved in this process, some of which are quite
* subtle. The most important, however, is the adjustment made to account
* for differences between the device's white point and the white point of
* the PCS. There are many techniques for doing this and it is the
* subject of much current research and controversy. Some commonly used
* methods are XYZ scaling, the von Kries transform, and the Bradford
* transform. The proper method to use depends upon each particular
* application.
* <p>
* The simplest method is XYZ scaling. In this method each device XYZ
* value is converted to a PCS XYZ value by multiplying it by the ratio
* of the PCS white point (D50) to the device white point.
* <pre>
*
* Xd, Yd, Zd are the device XYZ values
* Xdw, Ydw, Zdw are the device XYZ white point values
* Xp, Yp, Zp are the PCS XYZ values
* Xd50, Yd50, Zd50 are the PCS XYZ white point values
*
* Xp = Xd * (Xd50 / Xdw)
* Yp = Yd * (Yd50 / Ydw)
* Zp = Zd * (Zd50 / Zdw)
*
* </pre>
* <p>
* Conversion from the PCS to the device would be done by inverting these
* equations:
* <pre>
*
* Xd = Xp * (Xdw / Xd50)
* Yd = Yp * (Ydw / Yd50)
* Zd = Zp * (Zdw / Zd50)
*
* </pre>
* <p>
* Note that the media white point tag in an ICC profile is not the same
* as the device white point. The media white point tag is expressed in
* PCS values and is used to represent the difference between the XYZ of
* device illuminant and the XYZ of the device media when measured under
* that illuminant. The device white point is expressed as the device
* XYZ values corresponding to white displayed on the device. For
* example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
* will result in a measured device XYZ value of D65. This will not
* be the same as the media white point tag XYZ value in the ICC
* profile for an sRGB device.
* <p>
* @param colorvalue a float array with length of at least the number
* of components in this ColorSpace.
* @return a float array of length 3.
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least the number of components in this ColorSpace.
*/
public float[] toCIEXYZ(float[] colorvalue) {
if (this2xyz == null) {
ColorTransform[] transformList = new ColorTransform [2];
ICC_ColorSpace xyzCS =
(ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
PCMM mdl = CMSManager.getModule();
try {
transformList[0] = mdl.createTransform(
thisProfile, ICC_Profile.icRelativeColorimetric,
ColorTransform.In);
} catch (CMMException e) {
transformList[0] = mdl.createTransform(
thisProfile, ColorTransform.Any, ColorTransform.In);
}
transformList[1] = mdl.createTransform(
xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
this2xyz = mdl.createTransform (transformList);
if (needScaleInit) {
setComponentScaling();
}
}
int nc = this.getNumComponents();
short tmp[] = new short[nc];
for (int i = 0; i < nc; i++) {
tmp[i] = (short)
((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
}
tmp = this2xyz.colorConvert(tmp, null);
float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
// For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
float[] result = new float [3];
for (int i = 0; i < 3; i++) {
result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO;
}
return result;
}
/**
* Transforms a color value assumed to be in the CS_CIEXYZ conversion
* color space into this ColorSpace.
* <p>
* This method transforms color values using relative colorimetry,
* as defined by the ICC Specification. This
* means that the XYZ argument values taken by this method are represented
* relative to the D50 white point of the CS_CIEXYZ color space.
* This representation is useful in a two-step color conversion
* process in which colors are transformed from an input color
* space to CS_CIEXYZ and then to an output color space. The color
* values returned by this method are not those that would produce
* the XYZ value passed to the method when measured by a colorimeter.
* If you have XYZ values corresponding to measurements made using
* current CIE recommended practices, they must be converted to D50
* relative values before being passed to this method.
* The paragraphs below explain this in more detail.
* <p>
* The ICC standard uses a device independent color space (DICS) as the
* mechanism for converting color from one device to another device. In
* this architecture, colors are converted from the source device's color
* space to the ICC DICS and then from the ICC DICS to the destination
* device's color space. The ICC standard defines device profiles which
* contain transforms which will convert between a device's color space
* and the ICC DICS. The overall conversion of colors from a source
* device to colors of a destination device is done by connecting the
* device-to-DICS transform of the profile for the source device to the
* DICS-to-device transform of the profile for the destination device.
* For this reason, the ICC DICS is commonly referred to as the profile
* connection space (PCS). The color space used in the methods
* toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
* Specification. This is also the color space represented by
* ColorSpace.CS_CIEXYZ.
* <p>
* The XYZ values of a color are often represented as relative to some
* white point, so the actual meaning of the XYZ values cannot be known
* without knowing the white point of those values. This is known as
* relative colorimetry. The PCS uses a white point of D50, so the XYZ
* values of the PCS are relative to D50. For example, white in the PCS
* will have the XYZ values of D50, which is defined to be X=.9642,
* Y=1.000, and Z=0.8249. This white point is commonly used for graphic
* arts applications, but others are often used in other applications.
* <p>
* To quantify the color characteristics of a device such as a printer
* or monitor, measurements of XYZ values for particular device colors
* are typically made. For purposes of this discussion, the term
* device XYZ values is used to mean the XYZ values that would be
* measured from device colors using current CIE recommended practices.
* <p>
* Converting between device XYZ values and the PCS XYZ values taken as
* arguments by this method corresponds to converting between the device's
* color space, as represented by CIE colorimetric values, and the PCS.
* There are many factors involved in this process, some of which are quite
* subtle. The most important, however, is the adjustment made to account
* for differences between the device's white point and the white point of
* the PCS. There are many techniques for doing this and it is the
* subject of much current research and controversy. Some commonly used
* methods are XYZ scaling, the von Kries transform, and the Bradford
* transform. The proper method to use depends upon each particular
* application.
* <p>
* The simplest method is XYZ scaling. In this method each device XYZ
* value is converted to a PCS XYZ value by multiplying it by the ratio
* of the PCS white point (D50) to the device white point.
* <pre>
*
* Xd, Yd, Zd are the device XYZ values
* Xdw, Ydw, Zdw are the device XYZ white point values
* Xp, Yp, Zp are the PCS XYZ values
* Xd50, Yd50, Zd50 are the PCS XYZ white point values
*
* Xp = Xd * (Xd50 / Xdw)
* Yp = Yd * (Yd50 / Ydw)
* Zp = Zd * (Zd50 / Zdw)
*
* </pre>
* <p>
* Conversion from the PCS to the device would be done by inverting these
* equations:
* <pre>
*
* Xd = Xp * (Xdw / Xd50)
* Yd = Yp * (Ydw / Yd50)
* Zd = Zp * (Zdw / Zd50)
*
* </pre>
* <p>
* Note that the media white point tag in an ICC profile is not the same
* as the device white point. The media white point tag is expressed in
* PCS values and is used to represent the difference between the XYZ of
* device illuminant and the XYZ of the device media when measured under
* that illuminant. The device white point is expressed as the device
* XYZ values corresponding to white displayed on the device. For
* example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
* will result in a measured device XYZ value of D65. This will not
* be the same as the media white point tag XYZ value in the ICC
* profile for an sRGB device.
* <p>
* <p>
* @param colorvalue a float array with length of at least 3.
* @return a float array with length equal to the number of
* components in this ColorSpace.
* @throws ArrayIndexOutOfBoundsException if array length is not
* at least 3.
*/
public float[] fromCIEXYZ(float[] colorvalue) {
if (xyz2this == null) {
ColorTransform[] transformList = new ColorTransform [2];
ICC_ColorSpace xyzCS =
(ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
PCMM mdl = CMSManager.getModule();
transformList[0] = mdl.createTransform (
xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
try {
transformList[1] = mdl.createTransform(
thisProfile, ICC_Profile.icRelativeColorimetric,
ColorTransform.Out);
} catch (CMMException e) {
transformList[1] = CMSManager.getModule().createTransform(
thisProfile, ColorTransform.Any, ColorTransform.Out);
}
xyz2this = mdl.createTransform(transformList);
if (needScaleInit) {
setComponentScaling();
}
}
short tmp[] = new short[3];
float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
float factor = 65535.0f / ALMOST_TWO;
// For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
for (int i = 0; i < 3; i++) {
tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
}
tmp = xyz2this.colorConvert(tmp, null);
int nc = this.getNumComponents();
float[] result = new float [nc];
for (int i = 0; i < nc; i++) {
result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
diffMinMax[i] + minVal[i];
}
return result;
}
/**
* Returns the minimum normalized color component value for the
* specified component. For TYPE_XYZ spaces, this method returns
* minimum values of 0.0 for all components. For TYPE_Lab spaces,
* this method returns 0.0 for L and -128.0 for a and b components.
* This is consistent with the encoding of the XYZ and Lab Profile
* Connection Spaces in the ICC specification. For all other types, this
* method returns 0.0 for all components. When using an ICC_ColorSpace
* with a profile that requires different minimum component values,
* it is necessary to subclass this class and override this method.
* @param component The component index.
* @return The minimum normalized component value.
* @throws IllegalArgumentException if component is less than 0 or
* greater than numComponents - 1.
* @since 1.4
*/
public float getMinValue(int component) {
if ((component < 0) || (component > this.getNumComponents() - 1)) {
throw new IllegalArgumentException(
"Component index out of range: + component");
}
return minVal[component];
}
/**
* Returns the maximum normalized color component value for the
* specified component. For TYPE_XYZ spaces, this method returns
* maximum values of 1.0 + (32767.0 / 32768.0) for all components.
* For TYPE_Lab spaces,
* this method returns 100.0 for L and 127.0 for a and b components.
* This is consistent with the encoding of the XYZ and Lab Profile
* Connection Spaces in the ICC specification. For all other types, this
* method returns 1.0 for all components. When using an ICC_ColorSpace
* with a profile that requires different maximum component values,
* it is necessary to subclass this class and override this method.
* @param component The component index.
* @return The maximum normalized component value.
* @throws IllegalArgumentException if component is less than 0 or
* greater than numComponents - 1.
* @since 1.4
*/
public float getMaxValue(int component) {
if ((component < 0) || (component > this.getNumComponents() - 1)) {
throw new IllegalArgumentException(
"Component index out of range: + component");
}
return maxVal[component];
}
private void setMinMax() {
int nc = this.getNumComponents();
int type = this.getType();
minVal = new float[nc];
maxVal = new float[nc];
if (type == ColorSpace.TYPE_Lab) {
minVal[0] = 0.0f; // L
maxVal[0] = 100.0f;
minVal[1] = -128.0f; // a
maxVal[1] = 127.0f;
minVal[2] = -128.0f; // b
maxVal[2] = 127.0f;
} else if (type == ColorSpace.TYPE_XYZ) {
minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z
maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f);
} else {
for (int i = 0; i < nc; i++) {
minVal[i] = 0.0f;
maxVal[i] = 1.0f;
}
}
}
private void setComponentScaling() {
int nc = this.getNumComponents();
diffMinMax = new float[nc];
invDiffMinMax = new float[nc];
for (int i = 0; i < nc; i++) {
minVal[i] = this.getMinValue(i); // in case getMinVal is overridden
maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden
diffMinMax[i] = maxVal[i] - minVal[i];
invDiffMinMax[i] = 65535.0f / diffMinMax[i];
}
needScaleInit = false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.color;
import java.awt.image.LookupTable;
import sun.java2d.cmm.ProfileDeferralInfo;
/**
*
* A subclass of the ICC_Profile class which represents profiles
* which meet the following criteria: the color space type of the
* profile is TYPE_GRAY and the profile includes the grayTRCTag and
* mediaWhitePointTag tags. Examples of this kind of profile are
* monochrome input profiles, monochrome display profiles, and
* monochrome output profiles. The getInstance methods in the
* ICC_Profile class will
* return an ICC_ProfileGray object when the above conditions are
* met. The advantage of this class is that it provides a lookup
* table that Java or native methods may be able to use directly to
* optimize color conversion in some cases.
* <p>
* To transform from a GRAY device profile color space to the CIEXYZ Profile
* Connection Space, the device gray component is transformed by
* a lookup through the tone reproduction curve (TRC). The result is
* treated as the achromatic component of the PCS.
<pre>
&nbsp; PCSY = grayTRC[deviceGray]
</pre>
* The inverse transform is done by converting the PCS Y components to
* device Gray via the inverse of the grayTRC.
* <p>
*/
public class ICC_ProfileGray
extends ICC_Profile {
static final long serialVersionUID = -1124721290732002649L;
/**
* Constructs a new ICC_ProfileGray from a CMM ID.
*/
ICC_ProfileGray(long ID) {
super(ID);
}
/**
* Constructs a new ICC_ProfileGray from a ProfileDeferralInfo object.
*/
ICC_ProfileGray(ProfileDeferralInfo pdi) {
super(pdi);
}
/**
* Returns a float array of length 3 containing the X, Y, and Z
* components of the mediaWhitePointTag in the ICC profile.
* @return an array containing the components of the
* mediaWhitePointTag in the ICC profile.
*/
public float[] getMediaWhitePoint() {
return super.getMediaWhitePoint();
}
/**
* Returns a gamma value representing the tone reproduction
* curve (TRC). If the profile represents the TRC as a table rather
* than a single gamma value, then an exception is thrown. In this
* case the actual table can be obtained via getTRC(). When
* using a gamma value, the PCS Y component is computed as follows:
<pre>
&nbsp; gamma
&nbsp; PCSY = deviceGray
</pre>
* @return the gamma value as a float.
* @exception ProfileDataException if the profile does not specify
* the TRC as a single gamma value.
*/
public float getGamma() {
float theGamma;
theGamma = super.getGamma(ICC_Profile.icSigGrayTRCTag);
return theGamma;
}
/**
* Returns the TRC as an array of shorts. If the profile has
* specified the TRC as linear (gamma = 1.0) or as a simple gamma
* value, this method throws an exception, and the getGamma() method
* should be used to get the gamma value. Otherwise the short array
* returned here represents a lookup table where the input Gray value
* is conceptually in the range [0.0, 1.0]. Value 0.0 maps
* to array index 0 and value 1.0 maps to array index length-1.
* Interpolation may be used to generate output values for
* input values which do not map exactly to an index in the
* array. Output values also map linearly to the range [0.0, 1.0].
* Value 0.0 is represented by an array value of 0x0000 and
* value 1.0 by 0xFFFF, i.e. the values are really unsigned
* short values, although they are returned in a short array.
* @return a short array representing the TRC.
* @exception ProfileDataException if the profile does not specify
* the TRC as a table.
*/
public short[] getTRC() {
short[] theTRC;
theTRC = super.getTRC(ICC_Profile.icSigGrayTRCTag);
return theTRC;
}
}

View File

@ -0,0 +1,282 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.color;
import java.awt.image.LookupTable;
import sun.java2d.cmm.ProfileDeferralInfo;
/**
*
* The ICC_ProfileRGB class is a subclass of the ICC_Profile class
* that represents profiles which meet the following criteria:
* <ul>
* <li>The profile's color space type is RGB.</li>
* <li>The profile includes the <code>redColorantTag</code>,
* <code>greenColorantTag</code>, <code>blueColorantTag</code>,
* <code>redTRCTag</code>, <code>greenTRCTag</code>,
* <code>blueTRCTag</code>, and <code>mediaWhitePointTag</code> tags.</li>
* </ul>
* The <code>ICC_Profile</code> <code>getInstance</code> method will
* return an <code>ICC_ProfileRGB</code> object when these conditions are met.
* Three-component, matrix-based input profiles and RGB display profiles are
* examples of this type of profile.
* <p>
* This profile class provides color transform matrices and lookup tables
* that Java or native methods can use directly to
* optimize color conversion in some cases.
* <p>
* To transform from a device profile color space to the CIEXYZ Profile
* Connection Space, each device color component is first linearized by
* a lookup through the corresponding tone reproduction curve (TRC).
* The resulting linear RGB components are converted to the CIEXYZ PCS
* using a a 3x3 matrix constructed from the RGB colorants.
* <pre>
*
* &nbsp; linearR = redTRC[deviceR]
*
* &nbsp; linearG = greenTRC[deviceG]
*
* &nbsp; linearB = blueTRC[deviceB]
*
* &nbsp; _ _ _ _ _ _
* &nbsp;[ PCSX ] [ redColorantX greenColorantX blueColorantX ] [ linearR ]
* &nbsp;[ ] [ ] [ ]
* &nbsp;[ PCSY ] = [ redColorantY greenColorantY blueColorantY ] [ linearG ]
* &nbsp;[ ] [ ] [ ]
* &nbsp;[_ PCSZ _] [_ redColorantZ greenColorantZ blueColorantZ _] [_ linearB _]
*
* </pre>
* The inverse transform is performed by converting PCS XYZ components to linear
* RGB components through the inverse of the above 3x3 matrix, and then converting
* linear RGB to device RGB through inverses of the TRCs.
* <p>
*/
public class ICC_ProfileRGB
extends ICC_Profile {
static final long serialVersionUID = 8505067385152579334L;
/**
* Used to get a gamma value or TRC for the red component.
*/
public static final int REDCOMPONENT = 0;
/**
* Used to get a gamma value or TRC for the green component.
*/
public static final int GREENCOMPONENT = 1;
/**
* Used to get a gamma value or TRC for the blue component.
*/
public static final int BLUECOMPONENT = 2;
/**
* Constructs an new <code>ICC_ProfileRGB</code> from a CMM ID.
*
* @param ID The CMM ID for the profile.
*
*/
ICC_ProfileRGB(long ID) {
super(ID);
}
/**
* Constructs a new <code>ICC_ProfileRGB</code> from a
* ProfileDeferralInfo object.
*
* @param pdi
*/
ICC_ProfileRGB(ProfileDeferralInfo pdi) {
super(pdi);
}
/**
* Returns an array that contains the components of the profile's
* <CODE>mediaWhitePointTag</CODE>.
*
* @return A 3-element <CODE>float</CODE> array containing the x, y,
* and z components of the profile's <CODE>mediaWhitePointTag</CODE>.
*/
public float[] getMediaWhitePoint() {
return super.getMediaWhitePoint();
}
/**
* Returns a 3x3 <CODE>float</CODE> matrix constructed from the
* X, Y, and Z components of the profile's <CODE>redColorantTag</CODE>,
* <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
* <p>
* This matrix can be used for color transforms in the forward
* direction of the profile--from the profile color space
* to the CIEXYZ PCS.
*
* @return A 3x3 <CODE>float</CODE> array that contains the x, y, and z
* components of the profile's <CODE>redColorantTag</CODE>,
* <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
*/
public float[][] getMatrix() {
float[][] theMatrix = new float[3][3];
float[] tmpMatrix;
tmpMatrix = getXYZTag(ICC_Profile.icSigRedColorantTag);
theMatrix[0][0] = tmpMatrix[0];
theMatrix[1][0] = tmpMatrix[1];
theMatrix[2][0] = tmpMatrix[2];
tmpMatrix = getXYZTag(ICC_Profile.icSigGreenColorantTag);
theMatrix[0][1] = tmpMatrix[0];
theMatrix[1][1] = tmpMatrix[1];
theMatrix[2][1] = tmpMatrix[2];
tmpMatrix = getXYZTag(ICC_Profile.icSigBlueColorantTag);
theMatrix[0][2] = tmpMatrix[0];
theMatrix[1][2] = tmpMatrix[1];
theMatrix[2][2] = tmpMatrix[2];
return theMatrix;
}
/**
* Returns a gamma value representing the tone reproduction curve
* (TRC) for a particular component. The component parameter
* must be one of REDCOMPONENT, GREENCOMPONENT, or BLUECOMPONENT.
* <p>
* If the profile
* represents the TRC for the corresponding component
* as a table rather than a single gamma value, an
* exception is thrown. In this case the actual table
* can be obtained through the {@link #getTRC(int)} method.
* When using a gamma value,
* the linear component (R, G, or B) is computed as follows:
* <pre>
*
* &nbsp; gamma
* &nbsp; linearComponent = deviceComponent
*
*</pre>
* @param component The <CODE>ICC_ProfileRGB</CODE> constant that
* represents the component whose TRC you want to retrieve
* @return the gamma value as a float.
* @exception ProfileDataException if the profile does not specify
* the corresponding TRC as a single gamma value.
*/
public float getGamma(int component) {
float theGamma;
int theSignature;
switch (component) {
case REDCOMPONENT:
theSignature = ICC_Profile.icSigRedTRCTag;
break;
case GREENCOMPONENT:
theSignature = ICC_Profile.icSigGreenTRCTag;
break;
case BLUECOMPONENT:
theSignature = ICC_Profile.icSigBlueTRCTag;
break;
default:
throw new IllegalArgumentException("Must be Red, Green, or Blue");
}
theGamma = super.getGamma(theSignature);
return theGamma;
}
/**
* Returns the TRC for a particular component as an array.
* Component must be <code>REDCOMPONENT</code>,
* <code>GREENCOMPONENT</code>, or <code>BLUECOMPONENT</code>.
* Otherwise the returned array
* represents a lookup table where the input component value
* is conceptually in the range [0.0, 1.0]. Value 0.0 maps
* to array index 0 and value 1.0 maps to array index length-1.
* Interpolation might be used to generate output values for
* input values that do not map exactly to an index in the
* array. Output values also map linearly to the range [0.0, 1.0].
* Value 0.0 is represented by an array value of 0x0000 and
* value 1.0 by 0xFFFF. In other words, the values are really unsigned
* <code>short</code> values even though they are returned in a
* <code>short</code> array.
*
* If the profile has specified the corresponding TRC
* as linear (gamma = 1.0) or as a simple gamma value, this method
* throws an exception. In this case, the {@link #getGamma(int)}
* method should be used to get the gamma value.
*
* @param component The <CODE>ICC_ProfileRGB</CODE> constant that
* represents the component whose TRC you want to retrieve:
* <CODE>REDCOMPONENT</CODE>, <CODE>GREENCOMPONENT</CODE>, or
* <CODE>BLUECOMPONENT</CODE>.
*
* @return a short array representing the TRC.
* @exception ProfileDataException if the profile does not specify
* the corresponding TRC as a table.
*/
public short[] getTRC(int component) {
short[] theTRC;
int theSignature;
switch (component) {
case REDCOMPONENT:
theSignature = ICC_Profile.icSigRedTRCTag;
break;
case GREENCOMPONENT:
theSignature = ICC_Profile.icSigGreenTRCTag;
break;
case BLUECOMPONENT:
theSignature = ICC_Profile.icSigBlueTRCTag;
break;
default:
throw new IllegalArgumentException("Must be Red, Green, or Blue");
}
theTRC = super.getTRC(theSignature);
return theTRC;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -485,7 +485,6 @@ public class DragSourceContext
Cursor c = null;
targetAct = DnDConstants.ACTION_NONE;
switch (status) {
case ENTER:
case OVER:
@ -507,6 +506,10 @@ public class DragSourceContext
else
c = DragSource.DefaultCopyDrop;
}
break;
default:
targetAct = DnDConstants.ACTION_NONE;
}
setCursorImpl(c);

View File

@ -31,9 +31,9 @@ package java.awt.font;
* <i>sfnt</i> tables from the font. A particular
* <code>Font</code> object can implement this interface.
* <p>
* For more information on TrueType fonts, see the
* Apple TrueType Reference Manual
* ( <a href="http://fonts.apple.com/TTRefMan/index.html">http://fonts.apple.com/TTRefMan/index.html</a> ).
* For more information on TrueType and OpenType fonts, see the
* OpenType specification.
* ( <a href=http://www.microsoft.com/typography/otspec/">http://www.microsoft.com/typography/otspec/l</a> ).
*/
public interface OpenType {

View File

@ -0,0 +1,839 @@
/*
* Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
/**
* This class represents image data which is stored in a band interleaved
* fashion and for
* which each sample of a pixel occupies one data element of the DataBuffer.
* It subclasses ComponentSampleModel but provides a more efficent
* implementation for accessing band interleaved image data than is provided
* by ComponentSampleModel. This class should typically be used when working
* with images which store sample data for each band in a different bank of the
* DataBuffer. Accessor methods are provided so that image data can be
* manipulated directly. Pixel stride is the number of
* data array elements between two samples for the same band on the same
* scanline. The pixel stride for a BandedSampleModel is one.
* Scanline stride is the number of data array elements between
* a given sample and the corresponding sample in the same column of the next
* scanline. Band offsets denote the number
* of data array elements from the first data array element of the bank
* of the DataBuffer holding each band to the first sample of the band.
* The bands are numbered from 0 to N-1.
* Bank indices denote the correspondence between a bank of the data buffer
* and a band of image data. This class supports
* {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
* {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
* {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
* {@link DataBuffer#TYPE_INT TYPE_INT},
* {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and
* {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes
*/
public final class BandedSampleModel extends ComponentSampleModel
{
/**
* Constructs a BandedSampleModel with the specified parameters.
* The pixel stride will be one data element. The scanline stride
* will be the same as the width. Each band will be stored in
* a separate bank and all band offsets will be zero.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of image
* data described.
* @param numBands The number of bands for the image data.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public BandedSampleModel(int dataType, int w, int h, int numBands) {
super(dataType, w, h, 1, w,
BandedSampleModel.createIndicesArray(numBands),
BandedSampleModel.createOffsetArray(numBands));
}
/**
* Constructs a BandedSampleModel with the specified parameters.
* The number of bands will be inferred from the lengths of the
* bandOffsets bankIndices arrays, which must be equal. The pixel
* stride will be one data element.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param scanlineStride The line stride of the of the image data.
* @param bankIndices The bank index for each band.
* @param bandOffsets The band offset for each band.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public BandedSampleModel(int dataType,
int w, int h,
int scanlineStride,
int bankIndices[],
int bandOffsets[]) {
super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets);
}
/**
* Creates a new BandedSampleModel with the specified
* width and height. The new BandedSampleModel will have the same
* number of bands, storage data type, and bank indices
* as this BandedSampleModel. The band offsets will be compressed
* such that the offset between bands will be w*pixelStride and
* the minimum of all of the band offsets is zero.
* @param w the width of the resulting <code>BandedSampleModel</code>
* @param h the height of the resulting <code>BandedSampleModel</code>
* @return a new <code>BandedSampleModel</code> with the specified
* width and height.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> equals either
* <code>Integer.MAX_VALUE</code> or
* <code>Integer.MIN_VALUE</code>
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
int[] bandOffs;
if (numBanks == 1) {
bandOffs = orderBands(bandOffsets, w*h);
}
else {
bandOffs = new int[bandOffsets.length];
}
SampleModel sampleModel =
new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs);
return sampleModel;
}
/**
* Creates a new BandedSampleModel with a subset of the bands of this
* BandedSampleModel. The new BandedSampleModel can be
* used with any DataBuffer that the existing BandedSampleModel
* can be used with. The new BandedSampleModel/DataBuffer
* combination will represent an image with a subset of the bands
* of the original BandedSampleModel/DataBuffer combination.
* @throws RasterFormatException if the number of bands is greater than
* the number of banks in this sample model.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands.length > bankIndices.length)
throw new RasterFormatException("There are only " +
bankIndices.length +
" bands");
int newBankIndices[] = new int[bands.length];
int newBandOffsets[] = new int[bands.length];
for (int i=0; i<bands.length; i++) {
newBankIndices[i] = bankIndices[bands[i]];
newBandOffsets[i] = bandOffsets[bands[i]];
}
return new BandedSampleModel(this.dataType, width, height,
this.scanlineStride,
newBankIndices, newBandOffsets);
}
/**
* Creates a DataBuffer that corresponds to this BandedSampleModel,
* The DataBuffer's data type, number of banks, and size
* will be consistent with this BandedSampleModel.
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported types.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = scanlineStride * height;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size, numBanks);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size, numBanks);
break;
case DataBuffer.TYPE_SHORT:
dataBuffer = new DataBufferShort(size, numBanks);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size, numBanks);
break;
case DataBuffer.TYPE_FLOAT:
dataBuffer = new DataBufferFloat(size, numBanks);
break;
case DataBuffer.TYPE_DOUBLE:
dataBuffer = new DataBufferDouble(size, numBanks);
break;
default:
throw new IllegalArgumentException("dataType is not one " +
"of the supported types.");
}
return dataBuffer;
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a BandedSampleModel, this will be the same
* as the data type, and samples will be returned one per array
* element. Generally, obj
* should be passed in as null, so that the Object will be created
* automatically and will be of the right primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
* whose storage layout is described by
* BandedSampleModel <code>bsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* BandedSampleModel bsm1, bsm2;
* DataBufferInt db1, db2;
* bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
* db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If obj is non-null, it should be a primitive array of type TransferType.
* Otherwise, a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is non-null and is not large enough to hold
* the pixel data.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The DataBuffer containing the image data.
* @return the data for the specified pixel.
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null) {
bdata = new byte[numDataElems];
} else {
bdata = (byte[])obj;
}
for (int i=0; i<numDataElems; i++) {
bdata[i] = (byte)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
short[] sdata;
if (obj == null) {
sdata = new short[numDataElems];
} else {
sdata = (short[])obj;
}
for (int i=0; i<numDataElems; i++) {
sdata[i] = (short)data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null) {
idata = new int[numDataElems];
} else {
idata = (int[])obj;
}
for (int i=0; i<numDataElems; i++) {
idata[i] = data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)idata;
break;
case DataBuffer.TYPE_FLOAT:
float[] fdata;
if (obj == null) {
fdata = new float[numDataElems];
} else {
fdata = (float[])obj;
}
for (int i=0; i<numDataElems; i++) {
fdata[i] = data.getElemFloat(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)fdata;
break;
case DataBuffer.TYPE_DOUBLE:
double[] ddata;
if (obj == null) {
ddata = new double[numDataElems];
} else {
ddata = (double[])obj;
}
for (int i=0; i<numDataElems; i++) {
ddata[i] = data.getElemDouble(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
obj = (Object)ddata;
break;
}
return obj;
}
/**
* Returns all samples for the specified pixel in an int array.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples for the specified pixel.
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int[] pixels;
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [numBands];
}
int pixelOffset = y*scanlineStride + x;
for (int i=0; i<numBands; i++) {
pixels[i] = data.getElem(bankIndices[i],
pixelOffset + bandOffsets[i]);
}
return pixels;
}
/**
* Returns all samples for the specified rectangle of pixels in
* an int array, one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples for the pixels within the specified region.
* @see #setPixels(int, int, int, int, int[], DataBuffer)
*/
public int[] getPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int[] pixels;
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int[w*h*numBands];
}
for (int k = 0; k < numBands; k++) {
int lineOffset = y*scanlineStride + x + bandOffsets[k];
int srcOffset = k;
int bank = bankIndices[k];
for (int i = 0; i < h; i++) {
int pixelOffset = lineOffset;
for (int j = 0; j < w; j++) {
pixels[srcOffset] = data.getElem(bank, pixelOffset++);
srcOffset += numBands;
}
lineOffset += scanlineStride;
}
}
return pixels;
}
/**
* Returns as int the sample in a specified band for the pixel
* located at (x,y).
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return the sample in the specified band for the specified pixel.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int sample =
data.getElem(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the sample in a specified band
* for the pixel located at (x,y) as a float.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return a float value that represents the sample in the specified
* band for the specified pixel.
*/
public float getSampleFloat(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
float sample = data.getElemFloat(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the sample in a specified band
* for a pixel located at (x,y) as a double.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to return
* @param data The DataBuffer containing the image data
* @return a double value that represents the sample in the specified
* band for the specified pixel.
*/
public double getSampleDouble(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
double sample = data.getElemDouble(bankIndices[b],
y*scanlineStride + x + bandOffsets[b]);
return sample;
}
/**
* Returns the samples in a specified band for the specified rectangle
* of pixels in an int array, one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param b The band to return
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data
* @return the samples in the specified band for the pixels within
* the specified region.
* @see #setSamples(int, int, int, int, int, int[], DataBuffer)
*/
public int[] getSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int samples[];
if (iArray != null) {
samples = iArray;
} else {
samples = new int [w*h];
}
int lineOffset = y*scanlineStride + x + bandOffsets[b];
int srcOffset = 0;
int bank = bankIndices[b];
for (int i = 0; i < h; i++) {
int sampleOffset = lineOffset;
for (int j = 0; j < w; j++) {
samples[srcOffset++] = data.getElem(bank, sampleOffset++);
}
lineOffset += scanlineStride;
}
return samples;
}
/**
* Sets the data for a single pixel in the specified DataBuffer from a
* primitive array of type TransferType. For a BandedSampleModel,
* this will be the same as the data type, and samples are transferred
* one per array element.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
* whose storage layout is described by
* BandedSampleModel <code>bsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* BandedSampleModel bsm1, bsm2;
* DataBufferInt db1, db2;
* bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
* db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* obj must be a primitive array of type TransferType. Otherwise,
* a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is not large enough to hold the pixel data.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param obj If non-null, returns the primitive array in this
* object
* @param data The DataBuffer containing the image data
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int numDataElems = getNumDataElements();
int pixelOffset = y*scanlineStride + x;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
barray[i] & 0xff);
}
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
short[] sarray = (short[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
sarray[i] & 0xffff);
}
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
iarray[i]);
}
break;
case DataBuffer.TYPE_FLOAT:
float[] farray = (float[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i],
farray[i]);
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] darray = (double[])obj;
for (int i=0; i<numDataElems; i++) {
data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i],
darray[i]);
}
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param iArray The input samples in an int array
* @param data The DataBuffer containing the image data
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixelOffset = y*scanlineStride + x;
for (int i=0; i<numBands; i++) {
data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
iArray[i]);
}
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param iArray The input samples in an int array
* @param data The DataBuffer containing the image data
* @see #getPixels(int, int, int, int, int[], DataBuffer)
*/
public void setPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
for (int k = 0; k < numBands; k++) {
int lineOffset = y*scanlineStride + x + bandOffsets[k];
int srcOffset = k;
int bank = bankIndices[k];
for (int i = 0; i < h; i++) {
int pixelOffset = lineOffset;
for (int j = 0; j < w; j++) {
data.setElem(bank, pixelOffset++, iArray[srcOffset]);
srcOffset += numBands;
}
lineOffset += scanlineStride;
}
}
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as an int
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElem(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a float for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as a float
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b,
float s ,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElemFloat(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a double for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location
* @param y The Y coordinate of the pixel location
* @param b The band to set
* @param s The input sample as a double
* @param data The DataBuffer containing the image data
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b,
double s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
data.setElemDouble(bankIndices[b],
y*scanlineStride + x + bandOffsets[b], s);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per data array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location
* @param y The Y coordinate of the upper left pixel location
* @param w The width of the pixel rectangle
* @param h The height of the pixel rectangle
* @param b The band to set
* @param iArray The input sample array
* @param data The DataBuffer containing the image data
* @see #getSamples(int, int, int, int, int, int[], DataBuffer)
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x + bandOffsets[b];
int srcOffset = 0;
int bank = bankIndices[b];
for (int i = 0; i < h; i++) {
int sampleOffset = lineOffset;
for (int j = 0; j < w; j++) {
data.setElem(bank, sampleOffset++, iArray[srcOffset++]);
}
lineOffset += scanlineStride;
}
}
private static int[] createOffsetArray(int numBands) {
int[] bandOffsets = new int[numBands];
for (int i=0; i < numBands; i++) {
bandOffsets[i] = 0;
}
return bandOffsets;
}
private static int[] createIndicesArray(int numBands) {
int[] bankIndices = new int[numBands];
for (int i=0; i < numBands; i++) {
bankIndices[i] = i;
}
return bankIndices;
}
// Differentiate hash code from other ComponentSampleModel subclasses
public int hashCode() {
return super.hashCode() ^ 0x2;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,535 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import sun.java2d.StateTrackable.State;
import static sun.java2d.StateTrackable.State.*;
import sun.java2d.StateTrackableDelegate;
import sun.awt.image.SunWritableRaster;
/**
* This class exists to wrap one or more data arrays. Each data array in
* the DataBuffer is referred to as a bank. Accessor methods for getting
* and setting elements of the DataBuffer's banks exist with and without
* a bank specifier. The methods without a bank specifier use the default 0th
* bank. The DataBuffer can optionally take an offset per bank, so that
* data in an existing array can be used even if the interesting data
* doesn't start at array location zero. Getting or setting the 0th
* element of a bank, uses the (0+offset)th element of the array. The
* size field specifies how much of the data array is available for
* use. Size + offset for a given bank should never be greater
* than the length of the associated data array. The data type of
* a data buffer indicates the type of the data array(s) and may also
* indicate additional semantics, e.g. storing unsigned 8-bit data
* in elements of a byte array. The data type may be TYPE_UNDEFINED
* or one of the types defined below. Other types may be added in
* the future. Generally, an object of class DataBuffer will be cast down
* to one of its data type specific subclasses to access data type specific
* methods for improved performance. Currently, the Java 2D(tm) API
* image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT,
* TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data.
* @see java.awt.image.Raster
* @see java.awt.image.SampleModel
*/
public abstract class DataBuffer {
/** Tag for unsigned byte data. */
public static final int TYPE_BYTE = 0;
/** Tag for unsigned short data. */
public static final int TYPE_USHORT = 1;
/** Tag for signed short data. Placeholder for future use. */
public static final int TYPE_SHORT = 2;
/** Tag for int data. */
public static final int TYPE_INT = 3;
/** Tag for float data. Placeholder for future use. */
public static final int TYPE_FLOAT = 4;
/** Tag for double data. Placeholder for future use. */
public static final int TYPE_DOUBLE = 5;
/** Tag for undefined data. */
public static final int TYPE_UNDEFINED = 32;
/** The data type of this DataBuffer. */
protected int dataType;
/** The number of banks in this DataBuffer. */
protected int banks;
/** Offset into default (first) bank from which to get the first element. */
protected int offset;
/** Usable size of all banks. */
protected int size;
/** Offsets into all banks. */
protected int offsets[];
/* The current StateTrackable state. */
StateTrackableDelegate theTrackable;
/** Size of the data types indexed by DataType tags defined above. */
private static final int dataTypeSize[] = {8,16,16,32,32,64};
/** Returns the size (in bits) of the data type, given a datatype tag.
* @param type the value of one of the defined datatype tags
* @return the size of the data type
* @throws IllegalArgumentException if <code>type</code> is less than
* zero or greater than {@link #TYPE_DOUBLE}
*/
public static int getDataTypeSize(int type) {
if (type < TYPE_BYTE || type > TYPE_DOUBLE) {
throw new IllegalArgumentException("Unknown data type "+type);
}
return dataTypeSize[type];
}
/**
* Constructs a DataBuffer containing one bank of the specified
* data type and size.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
*/
protected DataBuffer(int dataType, int size) {
this(UNTRACKABLE, dataType, size);
}
/**
* Constructs a DataBuffer containing one bank of the specified
* data type and size with the indicated initial {@link State State}.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = 1;
this.size = size;
this.offset = 0;
this.offsets = new int[1]; // init to 0 by new
}
/**
* Constructs a DataBuffer containing the specified number of
* banks. Each bank has the specified size and an offset of 0.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
*/
protected DataBuffer(int dataType, int size, int numBanks) {
this(UNTRACKABLE, dataType, size, numBanks);
}
/**
* Constructs a DataBuffer containing the specified number of
* banks with the indicated initial {@link State State}.
* Each bank has the specified size and an offset of 0.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = 0;
this.offsets = new int[banks]; // init to 0 by new
}
/**
* Constructs a DataBuffer that contains the specified number
* of banks. Each bank has the specified datatype, size and offset.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offset the offset for each bank
*/
protected DataBuffer(int dataType, int size, int numBanks, int offset) {
this(UNTRACKABLE, dataType, size, numBanks, offset);
}
/**
* Constructs a DataBuffer that contains the specified number
* of banks with the indicated initial {@link State State}.
* Each bank has the specified datatype, size and offset.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offset the offset for each bank
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks, int offset)
{
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = offset;
this.offsets = new int[numBanks];
for (int i = 0; i < numBanks; i++) {
this.offsets[i] = offset;
}
}
/**
* Constructs a DataBuffer which contains the specified number
* of banks. Each bank has the specified datatype and size. The
* offset for each bank is specified by its respective entry in
* the offsets array.
*
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offsets an array containing an offset for each bank.
* @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
* does not equal the length of <code>offsets</code>
*/
protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) {
this(UNTRACKABLE, dataType, size, numBanks, offsets);
}
/**
* Constructs a DataBuffer which contains the specified number
* of banks with the indicated initial {@link State State}.
* Each bank has the specified datatype and size. The
* offset for each bank is specified by its respective entry in
* the offsets array.
*
* @param initialState the initial {@link State State} state of the data
* @param dataType the data type of this <code>DataBuffer</code>
* @param size the size of the banks
* @param numBanks the number of banks in this
* <code>DataBuffer</code>
* @param offsets an array containing an offset for each bank.
* @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
* does not equal the length of <code>offsets</code>
* @since 1.7
*/
DataBuffer(State initialState,
int dataType, int size, int numBanks, int offsets[])
{
if (numBanks != offsets.length) {
throw new ArrayIndexOutOfBoundsException("Number of banks" +
" does not match number of bank offsets");
}
this.theTrackable = StateTrackableDelegate.createInstance(initialState);
this.dataType = dataType;
this.banks = numBanks;
this.size = size;
this.offset = offsets[0];
this.offsets = (int[])offsets.clone();
}
/** Returns the data type of this DataBuffer.
* @return the data type of this <code>DataBuffer</code>.
*/
public int getDataType() {
return dataType;
}
/** Returns the size (in array elements) of all banks.
* @return the size of all banks.
*/
public int getSize() {
return size;
}
/** Returns the offset of the default bank in array elements.
* @return the offset of the default bank.
*/
public int getOffset() {
return offset;
}
/** Returns the offsets (in array elements) of all the banks.
* @return the offsets of all banks.
*/
public int[] getOffsets() {
return (int[])offsets.clone();
}
/** Returns the number of banks in this DataBuffer.
* @return the number of banks.
*/
public int getNumBanks() {
return banks;
}
/**
* Returns the requested data array element from the first (default) bank
* as an integer.
* @param i the index of the requested data array element
* @return the data array element at the specified index.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return getElem(0,i);
}
/**
* Returns the requested data array element from the specified bank
* as an integer.
* @param bank the specified bank
* @param i the index of the requested data array element
* @return the data array element at the specified index from the
* specified bank at the specified index.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public abstract int getElem(int bank, int i);
/**
* Sets the requested data array element in the first (default) bank
* from the given integer.
* @param i the specified index into the data array
* @param val the data to set the element at the specified index in
* the data array
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
setElem(0,i,val);
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank the specified bank
* @param i the specified index into the data array
* @param val the data to set the element in the specified bank
* at the specified index in the data array
* @see #getElem(int)
* @see #getElem(int, int)
*/
public abstract void setElem(int bank, int i, int val);
/**
* Returns the requested data array element from the first (default) bank
* as a float. The implementation in this class is to cast getElem(i)
* to a float. Subclasses may override this method if another
* implementation is needed.
* @param i the index of the requested data array element
* @return a float value representing the data array element at the
* specified index.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int i) {
return (float)getElem(i);
}
/**
* Returns the requested data array element from the specified bank
* as a float. The implementation in this class is to cast
* {@link #getElem(int, int)}
* to a float. Subclasses can override this method if another
* implementation is needed.
* @param bank the specified bank
* @param i the index of the requested data array element
* @return a float value representing the data array element from the
* specified bank at the specified index.
* @see #setElemFloat(int, float)
* @see #setElemFloat(int, int, float)
*/
public float getElemFloat(int bank, int i) {
return (float)getElem(bank,i);
}
/**
* Sets the requested data array element in the first (default) bank
* from the given float. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses
* can override this method if another implementation is needed.
* @param i the specified index
* @param val the value to set the element at the specified index in
* the data array
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int i, float val) {
setElem(i,(int)val);
}
/**
* Sets the requested data array element in the specified bank
* from the given float. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @param val the value to set the element in the specified bank at
* the specified index in the data array
* @see #getElemFloat(int)
* @see #getElemFloat(int, int)
*/
public void setElemFloat(int bank, int i, float val) {
setElem(bank,i,(int)val);
}
/**
* Returns the requested data array element from the first (default) bank
* as a double. The implementation in this class is to cast
* {@link #getElem(int)}
* to a double. Subclasses can override this method if another
* implementation is needed.
* @param i the specified index
* @return a double value representing the element at the specified
* index in the data array.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int i) {
return (double)getElem(i);
}
/**
* Returns the requested data array element from the specified bank as
* a double. The implementation in this class is to cast getElem(bank, i)
* to a double. Subclasses may override this method if another
* implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @return a double value representing the element from the specified
* bank at the specified index in the data array.
* @see #setElemDouble(int, double)
* @see #setElemDouble(int, int, double)
*/
public double getElemDouble(int bank, int i) {
return (double)getElem(bank,i);
}
/**
* Sets the requested data array element in the first (default) bank
* from the given double. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param i the specified index
* @param val the value to set the element at the specified index
* in the data array
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int i, double val) {
setElem(i,(int)val);
}
/**
* Sets the requested data array element in the specified bank
* from the given double. The implementation in this class is to cast
* val to an int and call {@link #setElem(int, int)}. Subclasses can
* override this method if another implementation is needed.
* @param bank the specified bank
* @param i the specified index
* @param val the value to set the element in the specified bank
* at the specified index of the data array
* @see #getElemDouble(int)
* @see #getElemDouble(int, int)
*/
public void setElemDouble(int bank, int i, double val) {
setElem(bank,i,(int)val);
}
static int[] toIntArray(Object obj) {
if (obj instanceof int[]) {
return (int[])obj;
} else if (obj == null) {
return null;
} else if (obj instanceof short[]) {
short sdata[] = (short[])obj;
int idata[] = new int[sdata.length];
for (int i = 0; i < sdata.length; i++) {
idata[i] = (int)sdata[i] & 0xffff;
}
return idata;
} else if (obj instanceof byte[]) {
byte bdata[] = (byte[])obj;
int idata[] = new int[bdata.length];
for (int i = 0; i < bdata.length; i++) {
idata[i] = 0xff & (int)bdata[i];
}
return idata;
}
return null;
}
static {
SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() {
public byte[] getData(DataBufferByte dbb, int bank) {
return dbb.bankdata[bank];
}
public short[] getData(DataBufferUShort dbus, int bank) {
return dbus.bankdata[bank];
}
public int[] getData(DataBufferInt dbi, int bank) {
return dbi.bankdata[bank];
}
public StateTrackableDelegate getTrackable(DataBuffer db) {
return db.theTrackable;
}
});
}
}

View File

@ -0,0 +1,286 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as bytes.
* Values stored in the byte array(s) of this <CODE>DataBuffer</CODE> are treated as
* unsigned values.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array, as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferByte extends DataBuffer
{
/** The default data bank. */
byte data[];
/** All data banks */
byte bankdata[][];
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferByte(int size) {
super(STABLE, TYPE_BYTE, size);
data = new byte[size];
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte based <CODE>DataBuffer</CODE> with the specified number of
* banks all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferByte(int size, int numBanks) {
super(STABLE, TYPE_BYTE, size, numBanks);
bankdata = new byte[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new byte[size];
}
data = bankdata[0];
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferByte(byte dataArray[], int size) {
super(UNTRACKABLE, TYPE_BYTE, size);
data = dataArray;
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>. <CODE>dataArray</CODE>
* must have at least <CODE>offset</CODE> + <CODE>size</CODE> elements.
*/
public DataBufferByte(byte dataArray[], int size, int offset){
super(UNTRACKABLE, TYPE_BYTE, size, 1, offset);
data = dataArray;
bankdata = new byte[1][];
bankdata[0] = data;
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks is equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferByte(byte dataArray[][], int size) {
super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length);
bankdata = (byte[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding <CODE>offset</CODE>.
* There must be an entry in the <CODE>offset</CODE> array for each <CODE>dataArray</CODE>
* entry. For each bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be used by accessors of this
* <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferByte(byte dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets);
bankdata = (byte[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) byte data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first byte data array.
*/
public byte[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public byte[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public byte[][] getBankData() {
theTrackable.setUntrackable();
return (byte[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]) & 0xff;
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]) & 0xff;
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (byte)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (byte)val;
theTrackable.markDirty();
}
}

View File

@ -0,0 +1,284 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally
* as integers.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferInt extends DataBuffer
{
/** The default data bank. */
int data[];
/** All data banks */
int bankdata[][];
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank
* and the specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int size) {
super(STABLE, TYPE_INT, size);
data = new int[size];
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified number of
* banks, all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int size, int numBanks) {
super(STABLE, TYPE_INT, size, numBanks);
bankdata = new int[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new int[size];
}
data = bankdata[0];
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferInt(int dataArray[], int size) {
super(UNTRACKABLE, TYPE_INT, size);
data = dataArray;
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferInt(int dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_INT, size, 1, offset);
data = dataArray;
bankdata = new int[1][];
bankdata[0] = data;
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int dataArray[][], int size) {
super(UNTRACKABLE, TYPE_INT, size, dataArray.length);
bankdata = (int [][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferInt(int dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets);
bankdata = (int [][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) int data array in <CODE>DataBuffer</CODE>.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first integer data array.
*/
public int[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public int[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public int[][] getBankData() {
theTrackable.setUntrackable();
return (int [][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return data[i+offset];
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return bankdata[bank][i+offsets[bank]];
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* to the integer value <CODE>i</CODE>.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (int)val;
theTrackable.markDirty();
}
}

View File

@ -0,0 +1,283 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as shorts.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferShort extends DataBuffer
{
/** The default data bank. */
short data[];
/** All data banks */
short bankdata[][];
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferShort(int size) {
super(STABLE, TYPE_SHORT,size);
data = new short[size];
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified number of
* banks all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferShort(int size, int numBanks) {
super(STABLE, TYPE_SHORT,size,numBanks);
bankdata = new short[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new short[size];
}
data = bankdata[0];
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferShort(short dataArray[], int size) {
super(UNTRACKABLE, TYPE_SHORT, size);
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
* specified array, size, and offset. <CODE>dataArray</CODE> must have at least
* <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
* through <CODE>offset</CODE> + <CODE>size</CODE> - 1
* should be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferShort(short dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_SHORT, size, 1, offset);
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferShort(short dataArray[][], int size) {
super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length);
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays, size,
* and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferShort(short dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets);
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) byte data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first short data array.
*/
public short[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public short[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public short[][] getBankData() {
theTrackable.setUntrackable();
return (short[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]);
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]);
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (short)val;
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (short)val;
theTrackable.markDirty();
}
}

View File

@ -0,0 +1,318 @@
/*
* Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import static sun.java2d.StateTrackable.State.*;
/**
* This class extends <CODE>DataBuffer</CODE> and stores data internally as
* shorts. Values stored in the short array(s) of this <CODE>DataBuffer</CODE>
* are treated as unsigned values.
* <p>
* <a name="optimizations">
* Note that some implementations may function more efficiently
* if they can maintain control over how the data for an image is
* stored.
* For example, optimizations such as caching an image in video
* memory require that the implementation track all modifications
* to that data.
* Other implementations may operate better if they can store the
* data in locations other than a Java array.
* To maintain optimum compatibility with various optimizations
* it is best to avoid constructors and methods which expose the
* underlying storage as a Java array as noted below in the
* documentation for those methods.
* </a>
*/
public final class DataBufferUShort extends DataBuffer
{
/** The default data bank. */
short data[];
/** All data banks */
short bankdata[][];
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank and the
* specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(int size) {
super(STABLE, TYPE_USHORT, size);
data = new short[size];
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified number of
* banks, all of which are the specified size.
*
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(int size, int numBanks) {
super(STABLE, TYPE_USHORT, size, numBanks);
bankdata = new short[numBanks][];
for (int i= 0; i < numBanks; i++) {
bankdata[i] = new short[size];
}
data = bankdata[0];
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
* using the specified array.
* Only the first <CODE>size</CODE> elements should be used by accessors of
* this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
* hold <CODE>size</CODE> elements.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
*/
public DataBufferUShort(short dataArray[], int size) {
super(UNTRACKABLE, TYPE_USHORT, size);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
* using the specified array, size, and offset. <CODE>dataArray</CODE> must have at
* least <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements
* <CODE>offset</CODE> through <CODE>offset</CODE> + <CODE>size</CODE> - 1 should
* be used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
* @param size The size of the <CODE>DataBuffer</CODE> bank.
* @param offset The offset into the <CODE>dataArray</CODE>.
*/
public DataBufferUShort(short dataArray[], int size, int offset) {
super(UNTRACKABLE, TYPE_USHORT, size, 1, offset);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
if ((size+offset) > dataArray.length) {
throw new IllegalArgumentException("Length of dataArray is less "+
" than size+offset.");
}
data = dataArray;
bankdata = new short[1][];
bankdata[0] = data;
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified arrays.
* The number of banks will be equal to <CODE>dataArray.length</CODE>.
* Only the first <CODE>size</CODE> elements of each array should be used by
* accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
*/
public DataBufferUShort(short dataArray[][], int size) {
super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
for (int i=0; i < dataArray.length; i++) {
if (dataArray[i] == null) {
throw new NullPointerException("dataArray["+i+"] is null");
}
}
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Constructs an unsigned-short based <CODE>DataBuffer</CODE> with specified arrays,
* size, and offsets.
* The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
* be at least as large as <CODE>size</CODE> + the corresponding offset. There must
* be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
* bank, only elements <CODE>offset</CODE> through
* <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
* used by accessors of this <CODE>DataBuffer</CODE>.
* <p>
* Note that {@code DataBuffer} objects created by this constructor
* may be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
* @param size The size of the banks in the <CODE>DataBuffer</CODE>.
* @param offsets The offsets into each array.
*/
public DataBufferUShort(short dataArray[][], int size, int offsets[]) {
super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets);
if (dataArray == null) {
throw new NullPointerException("dataArray is null");
}
for (int i=0; i < dataArray.length; i++) {
if (dataArray[i] == null) {
throw new NullPointerException("dataArray["+i+"] is null");
}
if ((size+offsets[i]) > dataArray[i].length) {
throw new IllegalArgumentException("Length of dataArray["+i+
"] is less than size+"+
"offsets["+i+"].");
}
}
bankdata = (short[][]) dataArray.clone();
data = bankdata[0];
}
/**
* Returns the default (first) unsigned-short data array.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return The first unsigned-short data array.
*/
public short[] getData() {
theTrackable.setUntrackable();
return data;
}
/**
* Returns the data array for the specified bank.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @param bank The bank whose data array you want to get.
* @return The data array for the specified bank.
*/
public short[] getData(int bank) {
theTrackable.setUntrackable();
return bankdata[bank];
}
/**
* Returns the data arrays for all banks.
* <p>
* Note that calling this method may cause this {@code DataBuffer}
* object to be incompatible with <a href="#optimizations">performance
* optimizations</a> used by some implementations (such as caching
* an associated image in video memory).
*
* @return All of the data arrays.
*/
public short[][] getBankData() {
theTrackable.setUntrackable();
return (short[][]) bankdata.clone();
}
/**
* Returns the requested data array element from the first (default) bank.
*
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int i) {
return (int)(data[i+offset]&0xffff);
}
/**
* Returns the requested data array element from the specified bank.
*
* @param bank The bank from which you want to get a data array element.
* @param i The data array element you want to get.
* @return The requested data array element as an integer.
* @see #setElem(int, int)
* @see #setElem(int, int, int)
*/
public int getElem(int bank, int i) {
return (int)(bankdata[bank][i+offsets[bank]]&0xffff);
}
/**
* Sets the requested data array element in the first (default) bank
* to the specified value.
*
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int i, int val) {
data[i+offset] = (short)(val&0xffff);
theTrackable.markDirty();
}
/**
* Sets the requested data array element in the specified bank
* from the given integer.
* @param bank The bank in which you want to set the data array element.
* @param i The data array element you want to set.
* @param val The integer value to which you want to set the specified data array element.
* @see #getElem(int)
* @see #getElem(int, int)
*/
public void setElem(int bank, int i, int val) {
bankdata[bank][i+offsets[bank]] = (short)(val&0xffff);
theTrackable.markDirty();
}
}

View File

@ -0,0 +1,699 @@
/*
* Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
/**
* The <code>MultiPixelPackedSampleModel</code> class represents
* one-banded images and can pack multiple one-sample
* pixels into one data element. Pixels are not allowed to span data elements.
* The data type can be DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
* or DataBuffer.TYPE_INT. Each pixel must be a power of 2 number of bits
* and a power of 2 number of pixels must fit exactly in one data element.
* Pixel bit stride is equal to the number of bits per pixel. Scanline
* stride is in data elements and the last several data elements might be
* padded with unused pixels. Data bit offset is the offset in bits from
* the beginning of the {@link DataBuffer} to the first pixel and must be
* a multiple of pixel bit stride.
* <p>
* The following code illustrates extracting the bits for pixel
* <code>x,&nbsp;y</code> from <code>DataBuffer</code> <code>data</code>
* and storing the pixel data in data elements of type
* <code>dataType</code>:
* <pre>
* int dataElementSize = DataBuffer.getDataTypeSize(dataType);
* int bitnum = dataBitOffset + x*pixelBitStride;
* int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
* int shift = dataElementSize - (bitnum & (dataElementSize-1))
* - pixelBitStride;
* int pixel = (element >> shift) & ((1 << pixelBitStride) - 1);
* </pre>
*/
public class MultiPixelPackedSampleModel extends SampleModel
{
/** The number of bits from one pixel to the next. */
int pixelBitStride;
/** Bitmask that extracts the rightmost pixel of a data element. */
int bitMask;
/**
* The number of pixels that fit in a data element. Also used
* as the number of bits per pixel.
*/
int pixelsPerDataElement;
/** The size of a data element in bits. */
int dataElementSize;
/** The bit offset into the data array where the first pixel begins.
*/
int dataBitOffset;
/** ScanlineStride of the data buffer described in data array elements. */
int scanlineStride;
/**
* Constructs a <code>MultiPixelPackedSampleModel</code> with the
* specified data type, width, height and number of bits per pixel.
* @param dataType the data type for storing samples
* @param w the width, in pixels, of the region of
* image data described
* @param h the height, in pixels, of the region of
* image data described
* @param numberOfBits the number of bits per pixel
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public MultiPixelPackedSampleModel(int dataType,
int w,
int h,
int numberOfBits) {
this(dataType,w,h,
numberOfBits,
(w*numberOfBits+DataBuffer.getDataTypeSize(dataType)-1)/
DataBuffer.getDataTypeSize(dataType),
0);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
}
/**
* Constructs a <code>MultiPixelPackedSampleModel</code> with
* specified data type, width, height, number of bits per pixel,
* scanline stride and data bit offset.
* @param dataType the data type for storing samples
* @param w the width, in pixels, of the region of
* image data described
* @param h the height, in pixels, of the region of
* image data described
* @param numberOfBits the number of bits per pixel
* @param scanlineStride the line stride of the image data
* @param dataBitOffset the data bit offset for the region of image
* data described
* @exception RasterFormatException if the number of bits per pixel
* is not a power of 2 or if a power of 2 number of
* pixels do not fit in one data element.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits,
int scanlineStride,
int dataBitOffset) {
super(dataType, w, h, 1);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
this.dataType = dataType;
this.pixelBitStride = numberOfBits;
this.scanlineStride = scanlineStride;
this.dataBitOffset = dataBitOffset;
this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
this.pixelsPerDataElement = dataElementSize/numberOfBits;
if (pixelsPerDataElement*numberOfBits != dataElementSize) {
throw new RasterFormatException("MultiPixelPackedSampleModel " +
"does not allow pixels to " +
"span data element boundaries");
}
this.bitMask = (1 << numberOfBits) - 1;
}
/**
* Creates a new <code>MultiPixelPackedSampleModel</code> with the
* specified width and height. The new
* <code>MultiPixelPackedSampleModel</code> has the
* same storage data type and number of bits per pixel as this
* <code>MultiPixelPackedSampleModel</code>.
* @param w the specified width
* @param h the specified height
* @return a {@link SampleModel} with the specified width and height
* and with the same storage data type and number of bits per pixel
* as this <code>MultiPixelPackedSampleModel</code>.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
SampleModel sampleModel =
new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
return sampleModel;
}
/**
* Creates a <code>DataBuffer</code> that corresponds to this
* <code>MultiPixelPackedSampleModel</code>. The
* <code>DataBuffer</code> object's data type and size
* is consistent with this <code>MultiPixelPackedSampleModel</code>.
* The <code>DataBuffer</code> has a single bank.
* @return a <code>DataBuffer</code> with the same data type and
* size as this <code>MultiPixelPackedSampleModel</code>.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = (int)scanlineStride*height;
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32);
break;
}
return dataBuffer;
}
/**
* Returns the number of data elements needed to transfer one pixel
* via the {@link #getDataElements} and {@link #setDataElements}
* methods. For a <code>MultiPixelPackedSampleModel</code>, this is
* one.
* @return the number of data elements.
*/
public int getNumDataElements() {
return 1;
}
/**
* Returns the number of bits per sample for all bands.
* @return the number of bits per sample.
*/
public int[] getSampleSize() {
int sampleSize[] = {pixelBitStride};
return sampleSize;
}
/**
* Returns the number of bits per sample for the specified band.
* @param band the specified band
* @return the number of bits per sample for the specified band.
*/
public int getSampleSize(int band) {
return pixelBitStride;
}
/**
* Returns the offset of pixel (x,&nbsp;y) in data array elements.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @return the offset of the specified pixel.
*/
public int getOffset(int x, int y) {
int offset = y * scanlineStride;
offset += (x*pixelBitStride+dataBitOffset)/dataElementSize;
return offset;
}
/**
* Returns the offset, in bits, into the data element in which it is
* stored for the <code>x</code>th pixel of a scanline.
* This offset is the same for all scanlines.
* @param x the specified pixel
* @return the bit offset of the specified pixel.
*/
public int getBitOffset(int x){
return (x*pixelBitStride+dataBitOffset)%dataElementSize;
}
/**
* Returns the scanline stride.
* @return the scanline stride of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getScanlineStride() {
return scanlineStride;
}
/**
* Returns the pixel bit stride in bits. This value is the same as
* the number of bits per pixel.
* @return the <code>pixelBitStride</code> of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getPixelBitStride() {
return pixelBitStride;
}
/**
* Returns the data bit offset in bits.
* @return the <code>dataBitOffset</code> of this
* <code>MultiPixelPackedSampleModel</code>.
*/
public int getDataBitOffset() {
return dataBitOffset;
}
/**
* Returns the TransferType used to transfer pixels by way of the
* <code>getDataElements</code> and <code>setDataElements</code>
* methods. The TransferType might or might not be the same as the
* storage DataType. The TransferType is one of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
* or DataBuffer.TYPE_INT.
* @return the transfertype.
*/
public int getTransferType() {
if (pixelBitStride > 16)
return DataBuffer.TYPE_INT;
else if (pixelBitStride > 8)
return DataBuffer.TYPE_USHORT;
else
return DataBuffer.TYPE_BYTE;
}
/**
* Creates a new <code>MultiPixelPackedSampleModel</code> with a
* subset of the bands of this
* <code>MultiPixelPackedSampleModel</code>. Since a
* <code>MultiPixelPackedSampleModel</code> only has one band, the
* bands argument must have a length of one and indicate the zeroth
* band.
* @param bands the specified bands
* @return a new <code>SampleModel</code> with a subset of bands of
* this <code>MultiPixelPackedSampleModel</code>.
* @exception RasterFormatException if the number of bands requested
* is not one.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands != null) {
if (bands.length != 1)
throw new RasterFormatException("MultiPixelPackedSampleModel has "
+ "only one band.");
}
SampleModel sm = createCompatibleSampleModel(width, height);
return sm;
}
/**
* Returns as <code>int</code> the sample in a specified band for the
* pixel located at (x,&nbsp;y). An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param b the band to return, which is assumed to be 0
* @param data the <code>DataBuffer</code> containing the image
* data
* @return the specified band containing the sample of the specified
* pixel.
* @exception ArrayIndexOutOfBoundException if the specified
* coordinates are not in bounds.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// 'b' must be 0
if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
(b != 0)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x*pixelBitStride;
int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
return (element >> shift) & bitMask;
}
/**
* Sets a sample in the specified band for the pixel located at
* (x,&nbsp;y) in the <code>DataBuffer</code> using an
* <code>int</code> for input.
* An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param b the band to return, which is assumed to be 0
* @param s the input sample as an <code>int</code>
* @param data the <code>DataBuffer</code> where image data is stored
* @exception ArrayIndexOutOfBoundsException if the coordinates are
* not in bounds.
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// 'b' must be 0
if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
(b != 0)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
element |= (s & bitMask) << shift;
data.setElem(index,element);
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a <code>MultiPixelPackedSampleModel</code>,
* the array has one element, and the type is the smallest of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
* that can hold a single pixel. Generally, <code>obj</code>
* should be passed in as <code>null</code>, so that the
* <code>Object</code> is created automatically and is the
* correct primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is
* described by <code>MultiPixelPackedSampleModel</code>
* <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
* The transfer is generally more efficient than using
* <code>getPixel</code> or <code>setPixel</code>.
* <pre>
* MultiPixelPackedSampleModel mppsm1, mppsm2;
* DataBufferInt db1, db2;
* mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using <code>getDataElements</code> or <code>setDataElements</code>
* to transfer between two <code>DataBuffer/SampleModel</code> pairs
* is legitimate if the <code>SampleModels</code> have the same number
* of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If <code>obj</code> is not <code>null</code>, it should be a
* primitive array of type TransferType. Otherwise, a
* <code>ClassCastException</code> is thrown. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds, or if <code>obj</code> is not
* <code>null</code> and is not large enough to hold the pixel data.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param obj a primitive array in which to return the pixel data or
* <code>null</code>.
* @param data the <code>DataBuffer</code> containing the image data.
* @return an <code>Object</code> containing data for the specified
* pixel.
* @exception ClassCastException if <code>obj</code> is not a
* primitive array of type TransferType or is not <code>null</code>
* @exception ArrayIndexOutOfBoundsException if the coordinates are
* not in bounds, or if <code>obj</code> is not <code>null</code> or
* not large enough to hold the pixel data
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int bitnum = dataBitOffset + x*pixelBitStride;
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = 0;
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null)
bdata = new byte[1];
else
bdata = (byte[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
bdata[0] = (byte)((element >> shift) & bitMask);
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
short[] sdata;
if (obj == null)
sdata = new short[1];
else
sdata = (short[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
sdata[0] = (short)((element >> shift) & bitMask);
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null)
idata = new int[1];
else
idata = (int[])obj;
element = data.getElem(y*scanlineStride +
bitnum/dataElementSize);
idata[0] = (element >> shift) & bitMask;
obj = (Object)idata;
break;
}
return obj;
}
/**
* Returns the specified single band pixel in the first element
* of an <code>int</code> array.
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds.
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @param iArray the array containing the pixel to be returned or
* <code>null</code>
* @param data the <code>DataBuffer</code> where image data is stored
* @return an array containing the specified pixel.
* @exception ArrayIndexOutOfBoundsException if the coordinates
* are not in bounds
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [numBands];
}
int bitnum = dataBitOffset + x*pixelBitStride;
int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
pixels[0] = (element >> shift) & bitMask;
return pixels;
}
/**
* Sets the data for a single pixel in the specified
* <code>DataBuffer</code> from a primitive array of type
* TransferType. For a <code>MultiPixelPackedSampleModel</code>,
* only the first element of the array holds valid data,
* and the type must be the smallest of
* DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
* that can hold a single pixel.
* <p>
* The following code illustrates transferring data for one pixel from
* <code>DataBuffer</code> <code>db1</code>, whose storage layout is
* described by <code>MultiPixelPackedSampleModel</code>
* <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
* whose storage layout is described by
* <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
* The transfer is generally more efficient than using
* <code>getPixel</code> or <code>setPixel</code>.
* <pre>
* MultiPixelPackedSampleModel mppsm1, mppsm2;
* DataBufferInt db1, db2;
* mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using <code>getDataElements</code> or <code>setDataElements</code> to
* transfer between two <code>DataBuffer/SampleModel</code> pairs is
* legitimate if the <code>SampleModel</code> objects have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* <code>obj</code> must be a primitive array of type TransferType.
* Otherwise, a <code>ClassCastException</code> is thrown. An
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the
* coordinates are not in bounds, or if <code>obj</code> is not large
* enough to hold the pixel data.
* @param x the X coordinate of the pixel location
* @param y the Y coordinate of the pixel location
* @param obj a primitive array containing pixel data
* @param data the <code>DataBuffer</code> containing the image data
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
element |= ( ((int)(barray[0])&0xff) & bitMask) << shift;
data.setElem(index, element);
break;
case DataBuffer.TYPE_USHORT:
short[] sarray = (short[])obj;
element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift;
data.setElem(index, element);
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
element |= (iarray[0] & bitMask) << shift;
data.setElem(index, element);
break;
}
}
/**
* Sets a pixel in the <code>DataBuffer</code> using an
* <code>int</code> array for input.
* <code>ArrayIndexOutOfBoundsException</code> is thrown if
* the coordinates are not in bounds.
* @param x the X coordinate of the pixel location
* @param y the Y coordinate of the pixel location
* @param iArray the input pixel in an <code>int</code> array
* @param data the <code>DataBuffer</code> containing the image data
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int bitnum = dataBitOffset + x * pixelBitStride;
int index = y * scanlineStride + (bitnum / dataElementSize);
int shift = dataElementSize - (bitnum & (dataElementSize-1))
- pixelBitStride;
int element = data.getElem(index);
element &= ~(bitMask << shift);
element |= (iArray[0] & bitMask) << shift;
data.setElem(index,element);
}
public boolean equals(Object o) {
if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
return false;
}
MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o;
return this.width == that.width &&
this.height == that.height &&
this.numBands == that.numBands &&
this.dataType == that.dataType &&
this.pixelBitStride == that.pixelBitStride &&
this.bitMask == that.bitMask &&
this.pixelsPerDataElement == that.pixelsPerDataElement &&
this.dataElementSize == that.dataElementSize &&
this.dataBitOffset == that.dataBitOffset &&
this.scanlineStride == that.scanlineStride;
}
// If we implement equals() we must also implement hashCode
public int hashCode() {
int hash = 0;
hash = width;
hash <<= 8;
hash ^= height;
hash <<= 8;
hash ^= numBands;
hash <<= 8;
hash ^= dataType;
hash <<= 8;
hash ^= pixelBitStride;
hash <<= 8;
hash ^= bitMask;
hash <<= 8;
hash ^= pixelsPerDataElement;
hash <<= 8;
hash ^= dataElementSize;
hash <<= 8;
hash ^= dataBitOffset;
hash <<= 8;
hash ^= scanlineStride;
return hash;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,217 @@
/*
* Portions Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Rectangle;
import java.util.Dictionary;
import java.util.Vector;
/**
* RenderedImage is a common interface for objects which contain
* or can produce image data in the form of Rasters. The image
* data may be stored/produced as a single tile or a regular array
* of tiles.
*/
public interface RenderedImage {
/**
* Returns a vector of RenderedImages that are the immediate sources of
* image data for this RenderedImage. This method returns null if
* the RenderedImage object has no information about its immediate
* sources. It returns an empty Vector if the RenderedImage object has
* no immediate sources.
* @return a Vector of <code>RenderedImage</code> objects.
*/
Vector<RenderedImage> getSources();
/**
* Gets a property from the property set of this image. The set of
* properties and whether it is immutable is determined by the
* implementing class. This method returns
* java.awt.Image.UndefinedProperty if the specified property is
* not defined for this RenderedImage.
* @param name the name of the property
* @return the property indicated by the specified name.
* @see java.awt.Image#UndefinedProperty
*/
Object getProperty(String name);
/**
* Returns an array of names recognized by
* {@link #getProperty(String) getProperty(String)}
* or <code>null</code>, if no property names are recognized.
* @return a <code>String</code> array containing all of the
* property names that <code>getProperty(String)</code> recognizes;
* or <code>null</code> if no property names are recognized.
*/
String[] getPropertyNames();
/**
* Returns the ColorModel associated with this image. All Rasters
* returned from this image will have this as their ColorModel. This
* can return null.
* @return the <code>ColorModel</code> of this image.
*/
ColorModel getColorModel();
/**
* Returns the SampleModel associated with this image. All Rasters
* returned from this image will have this as their SampleModel.
* @return the <code>SampleModel</code> of this image.
*/
SampleModel getSampleModel();
/**
* Returns the width of the RenderedImage.
* @return the width of this <code>RenderedImage</code>.
*/
int getWidth();
/**
* Returns the height of the RenderedImage.
* @return the height of this <code>RenderedImage</code>.
*/
int getHeight();
/**
* Returns the minimum X coordinate (inclusive) of the RenderedImage.
* @return the X coordinate of this <code>RenderedImage</code>.
*/
int getMinX();
/**
* Returns the minimum Y coordinate (inclusive) of the RenderedImage.
* @return the Y coordinate of this <code>RenderedImage</code>.
*/
int getMinY();
/**
* Returns the number of tiles in the X direction.
* @return the number of tiles in the X direction.
*/
int getNumXTiles();
/**
* Returns the number of tiles in the Y direction.
* @return the number of tiles in the Y direction.
*/
int getNumYTiles();
/**
* Returns the minimum tile index in the X direction.
* @return the minimum tile index in the X direction.
*/
int getMinTileX();
/**
* Returns the minimum tile index in the Y direction.
* @return the minimum tile index in the X direction.
*/
int getMinTileY();
/**
* Returns the tile width in pixels. All tiles must have the same
* width.
* @return the tile width in pixels.
*/
int getTileWidth();
/**
* Returns the tile height in pixels. All tiles must have the same
* height.
* @return the tile height in pixels.
*/
int getTileHeight();
/**
* Returns the X offset of the tile grid relative to the origin,
* i.e., the X coordinate of the upper-left pixel of tile (0, 0).
* (Note that tile (0, 0) may not actually exist.)
* @return the X offset of the tile grid relative to the origin.
*/
int getTileGridXOffset();
/**
* Returns the Y offset of the tile grid relative to the origin,
* i.e., the Y coordinate of the upper-left pixel of tile (0, 0).
* (Note that tile (0, 0) may not actually exist.)
* @return the Y offset of the tile grid relative to the origin.
*/
int getTileGridYOffset();
/**
* Returns tile (tileX, tileY). Note that tileX and tileY are indices
* into the tile array, not pixel locations. The Raster that is returned
* is live and will be updated if the image is changed.
* @param tileX the X index of the requested tile in the tile array
* @param tileY the Y index of the requested tile in the tile array
* @return the tile given the specified indices.
*/
Raster getTile(int tileX, int tileY);
/**
* Returns the image as one large tile (for tile based
* images this will require fetching the whole image
* and copying the image data over). The Raster returned is
* a copy of the image data and will not be updated if the image
* is changed.
* @return the image as one large tile.
*/
Raster getData();
/**
* Computes and returns an arbitrary region of the RenderedImage.
* The Raster returned is a copy of the image data and will not
* be updated if the image is changed.
* @param rect the region of the RenderedImage to be returned.
* @return the region of the <code>RenderedImage</code>
* indicated by the specified <code>Rectangle</code>.
*/
Raster getData(Rectangle rect);
/**
* Computes an arbitrary rectangular region of the RenderedImage
* and copies it into a caller-supplied WritableRaster. The region
* to be computed is determined from the bounds of the supplied
* WritableRaster. The supplied WritableRaster must have a
* SampleModel that is compatible with this image. If raster is null,
* an appropriate WritableRaster is created.
* @param raster a WritableRaster to hold the returned portion of the
* image, or null.
* @return a reference to the supplied or created WritableRaster.
*/
WritableRaster copyData(WritableRaster raster);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,805 @@
/*
* Portions Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.util.Arrays;
/**
* This class represents pixel data packed such that the N samples which make
* up a single pixel are stored in a single data array element, and each data
* data array element holds samples for only one pixel.
* This class supports
* {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
* {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
* {@link DataBuffer#TYPE_INT TYPE_INT} data types.
* All data array elements reside
* in the first bank of a DataBuffer. Accessor methods are provided so
* that the image data can be manipulated directly. Scanline stride is the
* number of data array elements between a given sample and the corresponding
* sample in the same column of the next scanline. Bit masks are the masks
* required to extract the samples representing the bands of the pixel.
* Bit offsets are the offsets in bits into the data array
* element of the samples representing the bands of the pixel.
* <p>
* The following code illustrates extracting the bits of the sample
* representing band <code>b</code> for pixel <code>x,y</code>
* from DataBuffer <code>data</code>:
* <pre>
* int sample = data.getElem(y * scanlineStride + x);
* sample = (sample & bitMasks[b]) >>> bitOffsets[b];
* </pre>
*/
public class SinglePixelPackedSampleModel extends SampleModel
{
/** Bit masks for all bands of the image data. */
private int bitMasks[];
/** Bit Offsets for all bands of the image data. */
private int bitOffsets[];
/** Bit sizes for all the bands of the image data. */
private int bitSizes[];
/** Maximum bit size. */
private int maxBitSize;
/** Line stride of the region of image data described by this
* SinglePixelPackedSampleModel.
*/
private int scanlineStride;
private static native void initIDs();
static {
ColorModel.loadLibraries();
initIDs();
}
/**
* Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
* Each sample is stored in a data array element in the position of
* its corresponding bit mask. Each bit mask must be contiguous and
* masks must not overlap.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of the
* image data described.
* @param h The height (in pixels) of the region of the
* image data described.
* @param bitMasks The bit masks for all bands.
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int bitMasks[]) {
this(dataType, w, h, w, bitMasks);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
}
/**
* Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
* and a scanline stride equal to scanlineStride data array elements.
* Each sample is stored in a data array element in the position of
* its corresponding bit mask. Each bit mask must be contiguous and
* masks must not overlap.
* @param dataType The data type for storing samples.
* @param w The width (in pixels) of the region of
* image data described.
* @param h The height (in pixels) of the region of
* image data described.
* @param scanlineStride The line stride of the image data.
* @param bitMasks The bit masks for all bands.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
* @throws IllegalArgumentException if any mask in
* <code>bitMask</code> is not contiguous
* @throws IllegalArgumentException if <code>dataType</code> is not
* either <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>
*/
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int scanlineStride, int bitMasks[]) {
super(dataType, w, h, bitMasks.length);
if (dataType != DataBuffer.TYPE_BYTE &&
dataType != DataBuffer.TYPE_USHORT &&
dataType != DataBuffer.TYPE_INT) {
throw new IllegalArgumentException("Unsupported data type "+
dataType);
}
this.dataType = dataType;
this.bitMasks = (int[]) bitMasks.clone();
this.scanlineStride = scanlineStride;
this.bitOffsets = new int[numBands];
this.bitSizes = new int[numBands];
this.maxBitSize = 0;
for (int i=0; i<numBands; i++) {
int bitOffset = 0, bitSize = 0, mask;
mask = bitMasks[i];
if (mask != 0) {
while ((mask & 1) == 0) {
mask = mask >>> 1;
bitOffset++;
}
while ((mask & 1) == 1) {
mask = mask >>> 1;
bitSize++;
}
if (mask != 0) {
throw new IllegalArgumentException("Mask "+bitMasks[i]+
" must be contiguous");
}
}
bitOffsets[i] = bitOffset;
bitSizes[i] = bitSize;
if (bitSize > maxBitSize) {
maxBitSize = bitSize;
}
}
}
/**
* Returns the number of data elements needed to transfer one pixel
* via the getDataElements and setDataElements methods.
* For a SinglePixelPackedSampleModel, this is one.
*/
public int getNumDataElements() {
return 1;
}
/**
* Returns the size of the buffer (in data array elements)
* needed for a data buffer that matches this
* SinglePixelPackedSampleModel.
*/
private long getBufferSize() {
long size = scanlineStride * (height-1) + width;
return size;
}
/**
* Creates a new SinglePixelPackedSampleModel with the specified
* width and height. The new SinglePixelPackedSampleModel will have the
* same storage data type and bit masks as this
* SinglePixelPackedSampleModel.
* @param w the width of the resulting <code>SampleModel</code>
* @param h the height of the resulting <code>SampleModel</code>
* @return a <code>SinglePixelPackedSampleModel</code> with the
* specified width and height.
* @throws IllegalArgumentException if <code>w</code> or
* <code>h</code> is not greater than 0
*/
public SampleModel createCompatibleSampleModel(int w, int h) {
SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
bitMasks);
return sampleModel;
}
/**
* Creates a DataBuffer that corresponds to this
* SinglePixelPackedSampleModel. The DataBuffer's data type and size
* will be consistent with this SinglePixelPackedSampleModel. The
* DataBuffer will have a single bank.
*/
public DataBuffer createDataBuffer() {
DataBuffer dataBuffer = null;
int size = (int)getBufferSize();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
dataBuffer = new DataBufferByte(size);
break;
case DataBuffer.TYPE_USHORT:
dataBuffer = new DataBufferUShort(size);
break;
case DataBuffer.TYPE_INT:
dataBuffer = new DataBufferInt(size);
break;
}
return dataBuffer;
}
/** Returns the number of bits per sample for all bands. */
public int[] getSampleSize() {
int mask;
int sampleSize[] = new int [numBands];
for (int i=0; i<numBands; i++) {
sampleSize[i] = 0;
mask = bitMasks[i] >>> bitOffsets[i];
while ((mask & 1) != 0) {
sampleSize[i] ++;
mask = mask >>> 1;
}
}
return sampleSize;
}
/** Returns the number of bits per sample for the specified band. */
public int getSampleSize(int band) {
int sampleSize = 0;
int mask = bitMasks[band] >>> bitOffsets[band];
while ((mask & 1) != 0) {
sampleSize ++;
mask = mask >>> 1;
}
return sampleSize;
}
/** Returns the offset (in data array elements) of pixel (x,y).
* The data element containing pixel <code>x,y</code>
* can be retrieved from a DataBuffer <code>data</code> with a
* SinglePixelPackedSampleModel <code>sppsm</code> as:
* <pre>
* data.getElem(sppsm.getOffset(x, y));
* </pre>
* @param x the X coordinate of the specified pixel
* @param y the Y coordinate of the specified pixel
* @return the offset of the specified pixel.
*/
public int getOffset(int x, int y) {
int offset = y * scanlineStride + x;
return offset;
}
/** Returns the bit offsets into the data array element representing
* a pixel for all bands.
* @return the bit offsets representing a pixel for all bands.
*/
public int [] getBitOffsets() {
return (int[])bitOffsets.clone();
}
/** Returns the bit masks for all bands.
* @return the bit masks for all bands.
*/
public int [] getBitMasks() {
return (int[])bitMasks.clone();
}
/** Returns the scanline stride of this SinglePixelPackedSampleModel.
* @return the scanline stride of this
* <code>SinglePixelPackedSampleModel</code>.
*/
public int getScanlineStride() {
return scanlineStride;
}
/**
* This creates a new SinglePixelPackedSampleModel with a subset of the
* bands of this SinglePixelPackedSampleModel. The new
* SinglePixelPackedSampleModel can be used with any DataBuffer that the
* existing SinglePixelPackedSampleModel can be used with. The new
* SinglePixelPackedSampleModel/DataBuffer combination will represent
* an image with a subset of the bands of the original
* SinglePixelPackedSampleModel/DataBuffer combination.
* @exception RasterFormatException if the length of the bands argument is
* greater than the number of bands in
* the sample model.
*/
public SampleModel createSubsetSampleModel(int bands[]) {
if (bands.length > numBands)
throw new RasterFormatException("There are only " +
numBands +
" bands");
int newBitMasks[] = new int[bands.length];
for (int i=0; i<bands.length; i++)
newBitMasks[i] = bitMasks[bands[i]];
return new SinglePixelPackedSampleModel(this.dataType, width, height,
this.scanlineStride, newBitMasks);
}
/**
* Returns data for a single pixel in a primitive array of type
* TransferType. For a SinglePixelPackedSampleModel, the array will
* have one element, and the type will be the same as the storage
* data type. Generally, obj
* should be passed in as null, so that the Object will be created
* automatically and will be of the right primitive data type.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm1</code>, to
* DataBuffer <code>db2</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* SinglePixelPackedSampleModel sppsm1, sppsm2;
* DataBufferInt db1, db2;
* sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* If obj is non-null, it should be a primitive array of type TransferType.
* Otherwise, a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is non-null and is not large enough to hold
* the pixel data.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj If non-null, a primitive array in which to return
* the pixel data.
* @param data The DataBuffer containing the image data.
* @return the data for the specified pixel.
* @see #setDataElements(int, int, Object, DataBuffer)
*/
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] bdata;
if (obj == null)
bdata = new byte[1];
else
bdata = (byte[])obj;
bdata[0] = (byte)data.getElem(y * scanlineStride + x);
obj = (Object)bdata;
break;
case DataBuffer.TYPE_USHORT:
short[] sdata;
if (obj == null)
sdata = new short[1];
else
sdata = (short[])obj;
sdata[0] = (short)data.getElem(y * scanlineStride + x);
obj = (Object)sdata;
break;
case DataBuffer.TYPE_INT:
int[] idata;
if (obj == null)
idata = new int[1];
else
idata = (int[])obj;
idata[0] = data.getElem(y * scanlineStride + x);
obj = (Object)idata;
break;
}
return obj;
}
/**
* Returns all samples in for the specified pixel in an int array.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray If non-null, returns the samples in this array
* @param data The DataBuffer containing the image data.
* @return all samples for the specified pixel.
* @see #setPixel(int, int, int[], DataBuffer)
*/
public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray == null) {
pixels = new int [numBands];
} else {
pixels = iArray;
}
int value = data.getElem(y * scanlineStride + x);
for (int i=0; i<numBands; i++) {
pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
}
return pixels;
}
/**
* Returns all samples for the specified rectangle of pixels in
* an int array, one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param iArray If non-null, returns the samples in this array.
* @param data The DataBuffer containing the image data.
* @return all samples for the specified region of pixels.
* @see #setPixels(int, int, int, int, int[], DataBuffer)
*/
public int[] getPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int pixels[];
if (iArray != null) {
pixels = iArray;
} else {
pixels = new int [w*h*numBands];
}
int lineOffset = y*scanlineStride + x;
int dstOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
for (int k=0; k < numBands; k++) {
pixels[dstOffset++] =
((value & bitMasks[k]) >>> bitOffsets[k]);
}
}
lineOffset += scanlineStride;
}
return pixels;
}
/**
* Returns as int the sample in a specified band for the pixel
* located at (x,y).
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to return.
* @param data The DataBuffer containing the image data.
* @return the sample in a specified band for the specified
* pixel.
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int sample = data.getElem(y * scanlineStride + x);
return ((sample & bitMasks[b]) >>> bitOffsets[b]);
}
/**
* Returns the samples for a specified band for the specified rectangle
* of pixels in an int array, one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param b The band to return.
* @param iArray If non-null, returns the samples in this array.
* @param data The DataBuffer containing the image data.
* @return the samples for the specified band for the specified
* region of pixels.
* @see #setSamples(int, int, int, int, int, int[], DataBuffer)
*/
public int[] getSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int samples[];
if (iArray != null) {
samples = iArray;
} else {
samples = new int [w*h];
}
int lineOffset = y*scanlineStride + x;
int dstOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
samples[dstOffset++] =
((value & bitMasks[b]) >>> bitOffsets[b]);
}
lineOffset += scanlineStride;
}
return samples;
}
/**
* Sets the data for a single pixel in the specified DataBuffer from a
* primitive array of type TransferType. For a
* SinglePixelPackedSampleModel, only the first element of the array
* will hold valid data, and the type of the array must be the same as
* the storage data type of the SinglePixelPackedSampleModel.
* <p>
* The following code illustrates transferring data for one pixel from
* DataBuffer <code>db1</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm1</code>,
* to DataBuffer <code>db2</code>, whose storage layout is described by
* SinglePixelPackedSampleModel <code>sppsm2</code>.
* The transfer will generally be more efficient than using
* getPixel/setPixel.
* <pre>
* SinglePixelPackedSampleModel sppsm1, sppsm2;
* DataBufferInt db1, db2;
* sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
* db1), db2);
* </pre>
* Using getDataElements/setDataElements to transfer between two
* DataBuffer/SampleModel pairs is legitimate if the SampleModels have
* the same number of bands, corresponding bands have the same number of
* bits per sample, and the TransferTypes are the same.
* <p>
* obj must be a primitive array of type TransferType. Otherwise,
* a ClassCastException is thrown. An
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if obj is not large enough to hold the pixel data.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param obj A primitive array containing pixel data.
* @param data The DataBuffer containing the image data.
* @see #getDataElements(int, int, Object, DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int type = getTransferType();
switch(type) {
case DataBuffer.TYPE_BYTE:
byte[] barray = (byte[])obj;
data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
break;
case DataBuffer.TYPE_USHORT:
short[] sarray = (short[])obj;
data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
break;
case DataBuffer.TYPE_INT:
int[] iarray = (int[])obj;
data.setElem(y*scanlineStride+x, iarray[0]);
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getPixel(int, int, int[], DataBuffer)
*/
public void setPixel(int x, int y,
int iArray[],
DataBuffer data) {
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y * scanlineStride + x;
int value = data.getElem(lineOffset);
for (int i=0; i < numBands; i++) {
value &= ~bitMasks[i];
value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
}
data.setElem(lineOffset, value);
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getPixels(int, int, int, int, int[], DataBuffer)
*/
public void setPixels(int x, int y, int w, int h,
int iArray[], DataBuffer data) {
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x;
int srcOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
for (int k=0; k < numBands; k++) {
value &= ~bitMasks[k];
int srcValue = iArray[srcOffset++];
value |= ((srcValue << bitOffsets[k])
& bitMasks[k]);
}
data.setElem(lineOffset+j, value);
}
lineOffset += scanlineStride;
}
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as an int.
* @param data The DataBuffer containing the image data.
* @see #getSample(int, int, int, DataBuffer)
*/
public void setSample(int x, int y, int b, int s,
DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int value = data.getElem(y*scanlineStride + x);
value &= ~bitMasks[b];
value |= (s << bitOffsets[b]) & bitMasks[b];
data.setElem(y*scanlineStride + x,value);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per array element.
* ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w The width of the pixel rectangle.
* @param h The height of the pixel rectangle.
* @param b The band to set.
* @param iArray The input samples in an int array.
* @param data The DataBuffer containing the image data.
* @see #getSamples(int, int, int, int, int, int[], DataBuffer)
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[], DataBuffer data) {
// Bounds check for 'b' will be performed automatically
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int lineOffset = y*scanlineStride + x;
int srcOffset = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
int value = data.getElem(lineOffset+j);
value &= ~bitMasks[b];
int sample = iArray[srcOffset++];
value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
data.setElem(lineOffset+j,value);
}
lineOffset += scanlineStride;
}
}
public boolean equals(Object o) {
if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
return false;
}
SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o;
return this.width == that.width &&
this.height == that.height &&
this.numBands == that.numBands &&
this.dataType == that.dataType &&
Arrays.equals(this.bitMasks, that.bitMasks) &&
Arrays.equals(this.bitOffsets, that.bitOffsets) &&
Arrays.equals(this.bitSizes, that.bitSizes) &&
this.maxBitSize == that.maxBitSize &&
this.scanlineStride == that.scanlineStride;
}
// If we implement equals() we must also implement hashCode
public int hashCode() {
int hash = 0;
hash = width;
hash <<= 8;
hash ^= height;
hash <<= 8;
hash ^= numBands;
hash <<= 8;
hash ^= dataType;
hash <<= 8;
for (int i = 0; i < bitMasks.length; i++) {
hash ^= bitMasks[i];
hash <<= 8;
}
for (int i = 0; i < bitOffsets.length; i++) {
hash ^= bitOffsets[i];
hash <<= 8;
}
for (int i = 0; i < bitSizes.length; i++) {
hash ^= bitSizes[i];
hash <<= 8;
}
hash ^= maxBitSize;
hash <<= 8;
hash ^= scanlineStride;
return hash;
}
}

View File

@ -0,0 +1,741 @@
/*
* Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Rectangle;
import java.awt.Point;
/**
* This class extends Raster to provide pixel writing capabilities.
* Refer to the class comment for Raster for descriptions of how
* a Raster stores pixels.
*
* <p> The constructors of this class are protected. To instantiate
* a WritableRaster, use one of the createWritableRaster factory methods
* in the Raster class.
*/
public class WritableRaster extends Raster {
/**
* Constructs a WritableRaster with the given SampleModel. The
* WritableRaster's upper left corner is origin and it is the
* same size as the SampleModel. A DataBuffer large enough to
* describe the WritableRaster is automatically created.
* @param sampleModel The SampleModel that specifies the layout.
* @param origin The Point that specifies the origin.
* @throws RasterFormatException if computing either
* <code>origin.x + sampleModel.getWidth()</code> or
* <code>origin.y + sampleModel.getHeight()</code> results
* in integer overflow
*/
protected WritableRaster(SampleModel sampleModel,
Point origin) {
this(sampleModel,
sampleModel.createDataBuffer(),
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
sampleModel.getHeight()),
origin,
null);
}
/**
* Constructs a WritableRaster with the given SampleModel and DataBuffer.
* The WritableRaster's upper left corner is origin and it is the same
* size as the SampleModel. The DataBuffer is not initialized and must
* be compatible with SampleModel.
* @param sampleModel The SampleModel that specifies the layout.
* @param dataBuffer The DataBuffer that contains the image data.
* @param origin The Point that specifies the origin.
* @throws RasterFormatException if computing either
* <code>origin.x + sampleModel.getWidth()</code> or
* <code>origin.y + sampleModel.getHeight()</code> results
* in integer overflow
*/
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer,
Point origin) {
this(sampleModel,
dataBuffer,
new Rectangle(origin.x,
origin.y,
sampleModel.getWidth(),
sampleModel.getHeight()),
origin,
null);
}
/**
* Constructs a WritableRaster with the given SampleModel, DataBuffer,
* and parent. aRegion specifies the bounding rectangle of the new
* Raster. When translated into the base Raster's coordinate
* system, aRegion must be contained by the base Raster.
* (The base Raster is the Raster's ancestor which has no parent.)
* sampleModelTranslate specifies the sampleModelTranslateX and
* sampleModelTranslateY values of the new Raster.
*
* Note that this constructor should generally be called by other
* constructors or create methods, it should not be used directly.
* @param sampleModel The SampleModel that specifies the layout.
* @param dataBuffer The DataBuffer that contains the image data.
* @param aRegion The Rectangle that specifies the image area.
* @param sampleModelTranslate The Point that specifies the translation
* from SampleModel to Raster coordinates.
* @param parent The parent (if any) of this raster.
* @throws RasterFormatException if <code>aRegion</code> has width
* or height less than or equal to zero, or computing either
* <code>aRegion.x + aRegion.width</code> or
* <code>aRegion.y + aRegion.height</code> results in integer
* overflow
*/
protected WritableRaster(SampleModel sampleModel,
DataBuffer dataBuffer,
Rectangle aRegion,
Point sampleModelTranslate,
WritableRaster parent){
super(sampleModel,dataBuffer,aRegion,sampleModelTranslate,parent);
}
/** Returns the parent WritableRaster (if any) of this WritableRaster,
* or else null.
* @return the parent of this <code>WritableRaster</code>, or
* <code>null</code>.
*/
public WritableRaster getWritableParent() {
return (WritableRaster)parent;
}
/**
* Create a WritableRaster with the same size, SampleModel and DataBuffer
* as this one, but with a different location. The new WritableRaster
* will possess a reference to the current WritableRaster, accessible
* through its getParent() and getWritableParent() methods.
*
* @param childMinX X coord of the upper left corner of the new Raster.
* @param childMinY Y coord of the upper left corner of the new Raster.
* @return a <code>WritableRaster</code> the same as this one except
* for the specified location.
* @throws RasterFormatException if computing either
* <code>childMinX + this.getWidth()</code> or
* <code>childMinY + this.getHeight()</code> results in integer
* overflow
*/
public WritableRaster createWritableTranslatedChild(int childMinX,
int childMinY) {
return createWritableChild(minX,minY,width,height,
childMinX,childMinY,null);
}
/**
* Returns a new WritableRaster which shares all or part of this
* WritableRaster's DataBuffer. The new WritableRaster will
* possess a reference to the current WritableRaster, accessible
* through its getParent() and getWritableParent() methods.
*
* <p> The parentX, parentY, width and height parameters form a
* Rectangle in this WritableRaster's coordinate space, indicating
* the area of pixels to be shared. An error will be thrown if
* this Rectangle is not contained with the bounds of the current
* WritableRaster.
*
* <p> The new WritableRaster may additionally be translated to a
* different coordinate system for the plane than that used by the current
* WritableRaster. The childMinX and childMinY parameters give
* the new (x, y) coordinate of the upper-left pixel of the
* returned WritableRaster; the coordinate (childMinX, childMinY)
* in the new WritableRaster will map to the same pixel as the
* coordinate (parentX, parentY) in the current WritableRaster.
*
* <p> The new WritableRaster may be defined to contain only a
* subset of the bands of the current WritableRaster, possibly
* reordered, by means of the bandList parameter. If bandList is
* null, it is taken to include all of the bands of the current
* WritableRaster in their current order.
*
* <p> To create a new WritableRaster that contains a subregion of
* the current WritableRaster, but shares its coordinate system
* and bands, this method should be called with childMinX equal to
* parentX, childMinY equal to parentY, and bandList equal to
* null.
*
* @param parentX X coordinate of the upper left corner in this
* WritableRaster's coordinates.
* @param parentY Y coordinate of the upper left corner in this
* WritableRaster's coordinates.
* @param w Width of the region starting at (parentX, parentY).
* @param h Height of the region starting at (parentX, parentY).
* @param childMinX X coordinate of the upper left corner of
* the returned WritableRaster.
* @param childMinY Y coordinate of the upper left corner of
* the returned WritableRaster.
* @param bandList Array of band indices, or null to use all bands.
* @return a <code>WritableRaster</code> sharing all or part of the
* <code>DataBuffer</code> of this <code>WritableRaster</code>.
* @exception RasterFormatException if the subregion is outside of the
* raster bounds.
* @throws RasterFormatException if <code>w</code> or
* <code>h</code>
* is less than or equal to zero, or computing any of
* <code>parentX + w</code>, <code>parentY + h</code>,
* <code>childMinX + w</code>, or
* <code>childMinY + h</code> results in integer
* overflow
*/
public WritableRaster createWritableChild(int parentX, int parentY,
int w, int h,
int childMinX, int childMinY,
int bandList[]) {
if (parentX < this.minX) {
throw new RasterFormatException("parentX lies outside raster");
}
if (parentY < this.minY) {
throw new RasterFormatException("parentY lies outside raster");
}
if ((parentX+w < parentX) || (parentX+w > this.width + this.minX)) {
throw new RasterFormatException("(parentX + width) is outside raster");
}
if ((parentY+h < parentY) || (parentY+h > this.height + this.minY)) {
throw new RasterFormatException("(parentY + height) is outside raster");
}
SampleModel sm;
// Note: the SampleModel for the child Raster should have the same
// width and height as that for the parent, since it represents
// the physical layout of the pixel data. The child Raster's width
// and height represent a "virtual" view of the pixel data, so
// they may be different than those of the SampleModel.
if (bandList != null) {
sm = sampleModel.createSubsetSampleModel(bandList);
}
else {
sm = sampleModel;
}
int deltaX = childMinX - parentX;
int deltaY = childMinY - parentY;
return new WritableRaster(sm,
getDataBuffer(),
new Rectangle(childMinX,childMinY,
w, h),
new Point(sampleModelTranslateX+deltaX,
sampleModelTranslateY+deltaY),
this);
}
/**
* Sets the data for a single pixel from a
* primitive array of type TransferType. For image data supported by
* the Java 2D(tm) API, this will be one of DataBuffer.TYPE_BYTE,
* DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
* DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
* may be in a packed format, thus increasing efficiency for data
* transfers.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if inData is not large enough to hold the pixel data.
* However, explicit bounds checking is not guaranteed.
* A ClassCastException will be thrown if the input object is not null
* and references anything other than an array of TransferType.
* @see java.awt.image.SampleModel#setDataElements(int, int, Object, DataBuffer)
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param inData An object reference to an array of type defined by
* getTransferType() and length getNumDataElements()
* containing the pixel data to place at x,y.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if inData is too small to hold the input.
*/
public void setDataElements(int x, int y, Object inData) {
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
inData, dataBuffer);
}
/**
* Sets the data for a rectangle of pixels from an input Raster.
* The input Raster must be compatible with this WritableRaster
* in that they must have the same number of bands, corresponding bands
* must have the same number of bits per sample, the TransferTypes
* and NumDataElements must be the same, and the packing used by
* the getDataElements/setDataElements must be identical.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param inRaster Raster containing data to place at x,y.
*
* @throws NullPointerException if inRaster is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds.
*/
public void setDataElements(int x, int y, Raster inRaster) {
int dstOffX = x+inRaster.getMinX();
int dstOffY = y+inRaster.getMinY();
int width = inRaster.getWidth();
int height = inRaster.getHeight();
if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
(dstOffX + width > this.minX + this.width) ||
(dstOffY + height > this.minY + this.height)) {
throw new ArrayIndexOutOfBoundsException
("Coordinate out of bounds!");
}
int srcOffX = inRaster.getMinX();
int srcOffY = inRaster.getMinY();
Object tdata = null;
for (int startY=0; startY < height; startY++) {
tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
width, 1, tdata);
setDataElements(dstOffX, dstOffY+startY,
width, 1, tdata);
}
}
/**
* Sets the data for a rectangle of pixels from a
* primitive array of type TransferType. For image data supported by
* the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
* DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
* DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
* may be in a packed format, thus increasing efficiency for data
* transfers.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds, or if inData is not large enough to hold the pixel data.
* However, explicit bounds checking is not guaranteed.
* A ClassCastException will be thrown if the input object is not null
* and references anything other than an array of TransferType.
* @see java.awt.image.SampleModel#setDataElements(int, int, int, int, Object, DataBuffer)
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param inData An object reference to an array of type defined by
* getTransferType() and length w*h*getNumDataElements()
* containing the pixel data to place between x,y and
* x+w-1, y+h-1.
*
* @throws NullPointerException if inData is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if inData is too small to hold the input.
*/
public void setDataElements(int x, int y, int w, int h, Object inData) {
sampleModel.setDataElements(x-sampleModelTranslateX,
y-sampleModelTranslateY,
w,h,inData,dataBuffer);
}
/**
* Copies pixels from Raster srcRaster to this WritableRaster. Each pixel
* in srcRaster is copied to the same x,y address in this raster, unless
* the address falls outside the bounds of this raster. srcRaster
* must have the same number of bands as this WritableRaster. The
* copy is a simple copy of source samples to the corresponding destination
* samples.
* <p>
* If all samples of both source and destination Rasters are of
* integral type and less than or equal to 32 bits in size, then calling
* this method is equivalent to executing the following code for all
* <code>x,y</code> addresses valid in both Rasters.
* <pre>
* Raster srcRaster;
* WritableRaster dstRaster;
* for (int b = 0; b < srcRaster.getNumBands(); b++) {
* dstRaster.setSample(x, y, b, srcRaster.getSample(x, y, b));
* }
* </pre>
* Thus, when copying an integral type source to an integral type
* destination, if the source sample size is greater than the destination
* sample size for a particular band, the high order bits of the source
* sample are truncated. If the source sample size is less than the
* destination size for a particular band, the high order bits of the
* destination are zero-extended or sign-extended depending on whether
* srcRaster's SampleModel treats the sample as a signed or unsigned
* quantity.
* <p>
* When copying a float or double source to an integral type destination,
* each source sample is cast to the destination type. When copying an
* integral type source to a float or double destination, the source
* is first converted to a 32-bit int (if necessary), using the above
* rules for integral types, and then the int is cast to float or
* double.
* <p>
* @param srcRaster The Raster from which to copy pixels.
*
* @throws NullPointerException if srcRaster is null.
*/
public void setRect(Raster srcRaster) {
setRect(0,0,srcRaster);
}
/**
* Copies pixels from Raster srcRaster to this WritableRaster.
* For each (x, y) address in srcRaster, the corresponding pixel
* is copied to address (x+dx, y+dy) in this WritableRaster,
* unless (x+dx, y+dy) falls outside the bounds of this raster.
* srcRaster must have the same number of bands as this WritableRaster.
* The copy is a simple copy of source samples to the corresponding
* destination samples. For details, see
* {@link WritableRaster#setRect(Raster)}.
*
* @param dx The X translation factor from src space to dst space
* of the copy.
* @param dy The Y translation factor from src space to dst space
* of the copy.
* @param srcRaster The Raster from which to copy pixels.
*
* @throws NullPointerException if srcRaster is null.
*/
public void setRect(int dx, int dy, Raster srcRaster) {
int width = srcRaster.getWidth();
int height = srcRaster.getHeight();
int srcOffX = srcRaster.getMinX();
int srcOffY = srcRaster.getMinY();
int dstOffX = dx+srcOffX;
int dstOffY = dy+srcOffY;
// Clip to this raster
if (dstOffX < this.minX) {
int skipX = this.minX - dstOffX;
width -= skipX;
srcOffX += skipX;
dstOffX = this.minX;
}
if (dstOffY < this.minY) {
int skipY = this.minY - dstOffY;
height -= skipY;
srcOffY += skipY;
dstOffY = this.minY;
}
if (dstOffX+width > this.minX+this.width) {
width = this.minX + this.width - dstOffX;
}
if (dstOffY+height > this.minY+this.height) {
height = this.minY + this.height - dstOffY;
}
if (width <= 0 || height <= 0) {
return;
}
switch (srcRaster.getSampleModel().getDataType()) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
int[] iData = null;
for (int startY=0; startY < height; startY++) {
// Grab one scanline at a time
iData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
iData);
setPixels(dstOffX, dstOffY+startY, width, 1, iData);
}
break;
case DataBuffer.TYPE_FLOAT:
float[] fData = null;
for (int startY=0; startY < height; startY++) {
fData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
fData);
setPixels(dstOffX, dstOffY+startY, width, 1, fData);
}
break;
case DataBuffer.TYPE_DOUBLE:
double[] dData = null;
for (int startY=0; startY < height; startY++) {
// Grab one scanline at a time
dData =
srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
dData);
setPixels(dstOffX, dstOffY+startY, width, 1, dData);
}
break;
}
}
/**
* Sets a pixel in the DataBuffer using an int array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param iArray The input samples in a int array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if iArray is too small to hold the input.
*/
public void setPixel(int x, int y, int iArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
iArray,dataBuffer);
}
/**
* Sets a pixel in the DataBuffer using a float array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param fArray The input samples in a float array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if fArray is too small to hold the input.
*/
public void setPixel(int x, int y, float fArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
fArray,dataBuffer);
}
/**
* Sets a pixel in the DataBuffer using a double array of samples for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param dArray The input samples in a double array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if dArray is too small to hold the input.
*/
public void setPixel(int x, int y, double dArray[]) {
sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
dArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from an int array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param iArray The input int pixel array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if iArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, int iArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,iArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from a float array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param fArray The input float pixel array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if fArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, float fArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,fArray,dataBuffer);
}
/**
* Sets all samples for a rectangle of pixels from a double array containing
* one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param dArray The input double pixel array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates are not
* in bounds, or if dArray is too small to hold the input.
*/
public void setPixels(int x, int y, int w, int h, double dArray[]) {
sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,dArray,dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using an int for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, int s) {
sampleModel.setSample(x-sampleModelTranslateX,
y-sampleModelTranslateY, b, s,
dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a float for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a float.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, float s){
sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
b,s,dataBuffer);
}
/**
* Sets a sample in the specified band for the pixel located at (x,y)
* in the DataBuffer using a double for input.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the pixel location.
* @param y The Y coordinate of the pixel location.
* @param b The band to set.
* @param s The input sample as a double.
*
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds.
*/
public void setSample(int x, int y, int b, double s){
sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
b,s,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from an int array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param iArray The input int sample array.
*
* @throws NullPointerException if iArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if iArray is too small to
* hold the input.
*/
public void setSamples(int x, int y, int w, int h, int b,
int iArray[]) {
sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,b,iArray,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from a float array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param fArray The input float sample array.
*
* @throws NullPointerException if fArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if fArray is too small to
* hold the input.
*/
public void setSamples(int x, int y, int w, int h, int b,
float fArray[]) {
sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,b,fArray,dataBuffer);
}
/**
* Sets the samples in the specified band for the specified rectangle
* of pixels from a double array containing one sample per array element.
* An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
* not in bounds.
* However, explicit bounds checking is not guaranteed.
* @param x The X coordinate of the upper left pixel location.
* @param y The Y coordinate of the upper left pixel location.
* @param w Width of the pixel rectangle.
* @param h Height of the pixel rectangle.
* @param b The band to set.
* @param dArray The input double sample array.
*
* @throws NullPointerException if dArray is null.
* @throws ArrayIndexOutOfBoundsException if the coordinates or
* the band index are not in bounds, or if dArray is too small to
* hold the input.
*/
public void setSamples(int x, int y, int w, int h, int b,
double dArray[]) {
sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
w,h,b,dArray,dataBuffer);
}
}

View File

@ -0,0 +1,151 @@
/*
* Portions Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ****************************************************************
******************************************************************
******************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997
*** As an unpublished work pursuant to Title 17 of the United
*** States Code. All rights reserved.
******************************************************************
******************************************************************
******************************************************************/
package java.awt.image;
import java.awt.Point;
/**
* WriteableRenderedImage is a common interface for objects which
* contain or can produce image data in the form of Rasters and
* which can be modified and/or written over. The image
* data may be stored/produced as a single tile or a regular array
* of tiles.
* <p>
* WritableRenderedImage provides notification to other interested
* objects when a tile is checked out for writing (via the
* getWritableTile method) and when the last writer of a particular
* tile relinquishes its access (via a call to releaseWritableTile).
* Additionally, it allows any caller to determine whether any tiles
* are currently checked out (via hasTileWriters), and to obtain a
* list of such tiles (via getWritableTileIndices, in the form of a Vector
* of Point objects).
* <p>
* Objects wishing to be notified of changes in tile writability must
* implement the TileObserver interface, and are added by a
* call to addTileObserver. Multiple calls to
* addTileObserver for the same object will result in multiple
* notifications. An existing observer may reduce its notifications
* by calling removeTileObserver; if the observer had no
* notifications the operation is a no-op.
* <p>
* It is necessary for a WritableRenderedImage to ensure that
* notifications occur only when the first writer acquires a tile and
* the last writer releases it.
*
*/
public interface WritableRenderedImage extends RenderedImage
{
/**
* Adds an observer. If the observer is already present,
* it will receive multiple notifications.
* @param to the specified <code>TileObserver</code>
*/
public void addTileObserver(TileObserver to);
/**
* Removes an observer. If the observer was not registered,
* nothing happens. If the observer was registered for multiple
* notifications, it will now be registered for one fewer.
* @param to the specified <code>TileObserver</code>
*/
public void removeTileObserver(TileObserver to);
/**
* Checks out a tile for writing.
*
* The WritableRenderedImage is responsible for notifying all
* of its TileObservers when a tile goes from having
* no writers to having one writer.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
* @return a writable tile.
*/
public WritableRaster getWritableTile(int tileX, int tileY);
/**
* Relinquishes the right to write to a tile. If the caller
* continues to write to the tile, the results are undefined.
* Calls to this method should only appear in matching pairs
* with calls to getWritableTile; any other use will lead
* to undefined results.
*
* The WritableRenderedImage is responsible for notifying all of
* its TileObservers when a tile goes from having one writer
* to having no writers.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
*/
public void releaseWritableTile(int tileX, int tileY);
/**
* Returns whether a tile is currently checked out for writing.
*
* @param tileX the X index of the tile.
* @param tileY the Y index of the tile.
* @return <code>true</code> if specified tile is checked out
* for writing; <code>false</code> otherwise.
*/
public boolean isTileWritable(int tileX, int tileY);
/**
* Returns an array of Point objects indicating which tiles
* are checked out for writing. Returns null if none are
* checked out.
* @return an array containing the locations of tiles that are
* checked out for writing.
*/
public Point[] getWritableTileIndices();
/**
* Returns whether any tile is checked out for writing.
* Semantically equivalent to (getWritableTileIndices() != null).
* @return <code>true</code> if any tiles are checked out for
* writing; <code>false</code> otherwise.
*/
public boolean hasTileWriters();
/**
* Sets a rect of the image to the contents of the Raster r, which is
* assumed to be in the same coordinate space as the WritableRenderedImage.
* The operation is clipped to the bounds of the WritableRenderedImage.
* @param r the specified <code>Raster</code>
*/
public void setData(Raster r);
}

View File

@ -0,0 +1,143 @@
/*
* Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
/**
* ContextualRenderedImageFactory provides an interface for the
* functionality that may differ between instances of
* RenderableImageOp. Thus different operations on RenderableImages
* may be performed by a single class such as RenderedImageOp through
* the use of multiple instances of ContextualRenderedImageFactory.
* The name ContextualRenderedImageFactory is commonly shortened to
* "CRIF."
*
* <p> All operations that are to be used in a rendering-independent
* chain must implement ContextualRenderedImageFactory.
*
* <p> Classes that implement this interface must provide a
* constructor with no arguments.
*/
public interface ContextualRenderedImageFactory extends RenderedImageFactory {
/**
* Maps the operation's output RenderContext into a RenderContext
* for each of the operation's sources. This is useful for
* operations that can be expressed in whole or in part simply as
* alterations in the RenderContext, such as an affine mapping, or
* operations that wish to obtain lower quality renderings of
* their sources in order to save processing effort or
* transmission bandwith. Some operations, such as blur, can also
* use this mechanism to avoid obtaining sources of higher quality
* than necessary.
*
* @param i the index of the source image.
* @param renderContext the RenderContext being applied to the operation.
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @param image the RenderableImage being rendered.
* @return a <code>RenderContext</code> for
* the source at the specified index of the parameters
* Vector contained in the specified ParameterBlock.
*/
RenderContext mapRenderContext(int i,
RenderContext renderContext,
ParameterBlock paramBlock,
RenderableImage image);
/**
* Creates a rendering, given a RenderContext and a ParameterBlock
* containing the operation's sources and parameters. The output
* is a RenderedImage that takes the RenderContext into account to
* determine its dimensions and placement on the image plane.
* This method houses the "intelligence" that allows a
* rendering-independent operation to adapt to a specific
* RenderContext.
*
* @param renderContext The RenderContext specifying the rendering
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters
* @return a <code>RenderedImage</code> from the sources and parameters
* in the specified ParameterBlock and according to the
* rendering instructions in the specified RenderContext.
*/
RenderedImage create(RenderContext renderContext,
ParameterBlock paramBlock);
/**
* Returns the bounding box for the output of the operation,
* performed on a given set of sources, in rendering-independent
* space. The bounds are returned as a Rectangle2D, that is, an
* axis-aligned rectangle with floating-point corner coordinates.
*
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @return a Rectangle2D specifying the rendering-independent
* bounding box of the output.
*/
Rectangle2D getBounds2D(ParameterBlock paramBlock);
/**
* Gets the appropriate instance of the property specified by the name
* parameter. This method must determine which instance of a property to
* return when there are multiple sources that each specify the property.
*
* @param paramBlock a ParameterBlock containing the operation's
* sources and parameters.
* @param name a String naming the desired property.
* @return an object reference to the value of the property requested.
*/
Object getProperty(ParameterBlock paramBlock, String name);
/**
* Returns a list of names recognized by getProperty.
* @return the list of property names.
*/
String[] getPropertyNames();
/**
* Returns true if successive renderings (that is, calls to
* create(RenderContext, ParameterBlock)) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. It is always safe to return true.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
boolean isDynamic();
}

View File

@ -0,0 +1,272 @@
/*
* Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.util.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.image.*;
/**
* A RenderContext encapsulates the information needed to produce a
* specific rendering from a RenderableImage. It contains the area to
* be rendered specified in rendering-independent terms, the
* resolution at which the rendering is to be performed, and hints
* used to control the rendering process.
*
* <p> Users create RenderContexts and pass them to the
* RenderableImage via the createRendering method. Most of the methods of
* RenderContexts are not meant to be used directly by applications,
* but by the RenderableImage and operator classes to which it is
* passed.
*
* <p> The AffineTransform parameter passed into and out of this class
* are cloned. The RenderingHints and Shape parameters are not
* necessarily cloneable and are therefore only reference copied.
* Altering RenderingHints or Shape instances that are in use by
* instances of RenderContext may have undesired side effects.
*/
public class RenderContext implements Cloneable {
/** Table of hints. May be null. */
RenderingHints hints;
/** Transform to convert user coordinates to device coordinates. */
AffineTransform usr2dev;
/** The area of interest. May be null. */
Shape aoi;
// Various constructors that allow different levels of
// specificity. If the Shape is missing the whole renderable area
// is assumed. If hints is missing no hints are assumed.
/**
* Constructs a RenderContext with a given transform.
* The area of interest is supplied as a Shape,
* and the rendering hints are supplied as a RenderingHints object.
*
* @param usr2dev an AffineTransform.
* @param aoi a Shape representing the area of interest.
* @param hints a RenderingHints object containing rendering hints.
*/
public RenderContext(AffineTransform usr2dev,
Shape aoi,
RenderingHints hints) {
this.hints = hints;
this.aoi = aoi;
this.usr2dev = (AffineTransform)usr2dev.clone();
}
/**
* Constructs a RenderContext with a given transform.
* The area of interest is taken to be the entire renderable area.
* No rendering hints are used.
*
* @param usr2dev an AffineTransform.
*/
public RenderContext(AffineTransform usr2dev) {
this(usr2dev, null, null);
}
/**
* Constructs a RenderContext with a given transform and rendering hints.
* The area of interest is taken to be the entire renderable area.
*
* @param usr2dev an AffineTransform.
* @param hints a RenderingHints object containing rendering hints.
*/
public RenderContext(AffineTransform usr2dev, RenderingHints hints) {
this(usr2dev, null, hints);
}
/**
* Constructs a RenderContext with a given transform and area of interest.
* The area of interest is supplied as a Shape.
* No rendering hints are used.
*
* @param usr2dev an AffineTransform.
* @param aoi a Shape representing the area of interest.
*/
public RenderContext(AffineTransform usr2dev, Shape aoi) {
this(usr2dev, aoi, null);
}
/**
* Gets the rendering hints of this <code>RenderContext</code>.
* @return a <code>RenderingHints</code> object that represents
* the rendering hints of this <code>RenderContext</code>.
* @see #setRenderingHints(RenderingHints)
*/
public RenderingHints getRenderingHints() {
return hints;
}
/**
* Sets the rendering hints of this <code>RenderContext</code>.
* @param hints a <code>RenderingHints</code> object that represents
* the rendering hints to assign to this <code>RenderContext</code>.
* @see #getRenderingHints
*/
public void setRenderingHints(RenderingHints hints) {
this.hints = hints;
}
/**
* Sets the current user-to-device AffineTransform contained
* in the RenderContext to a given transform.
*
* @param newTransform the new AffineTransform.
* @see #getTransform
*/
public void setTransform(AffineTransform newTransform) {
usr2dev = (AffineTransform)newTransform.clone();
}
/**
* Modifies the current user-to-device transform by prepending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [modTransform] x [this]
* </pre>
*
* @param modTransform the AffineTransform to prepend to the
* current usr2dev transform.
* @since 1.3
*/
public void preConcatenateTransform(AffineTransform modTransform) {
this.preConcetenateTransform(modTransform);
}
/**
* Modifies the current user-to-device transform by prepending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [modTransform] x [this]
* </pre>
* This method does the same thing as the preConcatenateTransform
* method. It is here for backward compatibility with previous releases
* which misspelled the method name.
*
* @param modTransform the AffineTransform to prepend to the
* current usr2dev transform.
* @deprecated replaced by
* <code>preConcatenateTransform(AffineTransform)</code>.
*/
@Deprecated
public void preConcetenateTransform(AffineTransform modTransform) {
usr2dev.preConcatenate(modTransform);
}
/**
* Modifies the current user-to-device transform by appending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [this] x [modTransform]
* </pre>
*
* @param modTransform the AffineTransform to append to the
* current usr2dev transform.
* @since 1.3
*/
public void concatenateTransform(AffineTransform modTransform) {
this.concetenateTransform(modTransform);
}
/**
* Modifies the current user-to-device transform by appending another
* transform. In matrix notation the operation is:
* <pre>
* [this] = [this] x [modTransform]
* </pre>
* This method does the same thing as the concatenateTransform
* method. It is here for backward compatibility with previous releases
* which misspelled the method name.
*
* @param modTransform the AffineTransform to append to the
* current usr2dev transform.
* @deprecated replaced by
* <code>concatenateTransform(AffineTransform)</code>.
*/
@Deprecated
public void concetenateTransform(AffineTransform modTransform) {
usr2dev.concatenate(modTransform);
}
/**
* Gets the current user-to-device AffineTransform.
*
* @return a reference to the current AffineTransform.
* @see #setTransform(AffineTransform)
*/
public AffineTransform getTransform() {
return (AffineTransform)usr2dev.clone();
}
/**
* Sets the current area of interest. The old area is discarded.
*
* @param newAoi The new area of interest.
* @see #getAreaOfInterest
*/
public void setAreaOfInterest(Shape newAoi) {
aoi = newAoi;
}
/**
* Gets the ares of interest currently contained in the
* RenderContext.
*
* @return a reference to the area of interest of the RenderContext,
* or null if none is specified.
* @see #setAreaOfInterest(Shape)
*/
public Shape getAreaOfInterest() {
return aoi;
}
/**
* Makes a copy of a RenderContext. The area of interest is copied
* by reference. The usr2dev AffineTransform and hints are cloned,
* while the area of interest is copied by reference.
*
* @return the new cloned RenderContext.
*/
public Object clone() {
RenderContext newRenderContext = new RenderContext(usr2dev,
aoi, hints);
return newRenderContext;
}
}

View File

@ -0,0 +1,198 @@
/*
* Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.util.Vector;
import java.awt.RenderingHints;
import java.awt.image.*;
/**
* A RenderableImage is a common interface for rendering-independent
* images (a notion which subsumes resolution independence). That is,
* images which are described and have operations applied to them
* independent of any specific rendering of the image. For example, a
* RenderableImage can be rotated and cropped in
* resolution-independent terms. Then, it can be rendered for various
* specific contexts, such as a draft preview, a high-quality screen
* display, or a printer, each in an optimal fashion.
*
* <p> A RenderedImage is returned from a RenderableImage via the
* createRendering() method, which takes a RenderContext. The
* RenderContext specifies how the RenderedImage should be
* constructed. Note that it is not possible to extract pixels
* directly from a RenderableImage.
*
* <p> The createDefaultRendering() and createScaledRendering() methods are
* convenience methods that construct an appropriate RenderContext
* internally. All of the rendering methods may return a reference to a
* previously produced rendering.
*/
public interface RenderableImage {
/**
* String constant that can be used to identify a property on
* a RenderedImage obtained via the createRendering or
* createScaledRendering methods. If such a property exists,
* the value of the propoery will be a RenderingHints object
* specifying which hints were observed in creating the rendering.
*/
static final String HINTS_OBSERVED = "HINTS_OBSERVED";
/**
* Returns a vector of RenderableImages that are the sources of
* image data for this RenderableImage. Note that this method may
* return an empty vector, to indicate that the image has no sources,
* or null, to indicate that no information is available.
*
* @return a (possibly empty) Vector of RenderableImages, or null.
*/
Vector<RenderableImage> getSources();
/**
* Gets a property from the property set of this image.
* If the property name is not recognized, java.awt.Image.UndefinedProperty
* will be returned.
*
* @param name the name of the property to get, as a String.
* @return a reference to the property Object, or the value
* java.awt.Image.UndefinedProperty.
*/
Object getProperty(String name);
/**
* Returns a list of names recognized by getProperty.
* @return a list of property names.
*/
String[] getPropertyNames();
/**
* Returns true if successive renderings (that is, calls to
* createRendering() or createScaledRendering()) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. It is always safe to return true.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
boolean isDynamic();
/**
* Gets the width in user coordinate space. By convention, the
* usual width of a RenderableImage is equal to the image's aspect
* ratio (width divided by height).
*
* @return the width of the image in user coordinates.
*/
float getWidth();
/**
* Gets the height in user coordinate space. By convention, the
* usual height of a RenderedImage is equal to 1.0F.
*
* @return the height of the image in user coordinates.
*/
float getHeight();
/**
* Gets the minimum X coordinate of the rendering-independent image data.
* @return the minimum X coordinate of the rendering-independent image
* data.
*/
float getMinX();
/**
* Gets the minimum Y coordinate of the rendering-independent image data.
* @return the minimum Y coordinate of the rendering-independent image
* data.
*/
float getMinY();
/**
* Creates a RenderedImage instance of this image with width w, and
* height h in pixels. The RenderContext is built automatically
* with an appropriate usr2dev transform and an area of interest
* of the full image. All the rendering hints come from hints
* passed in.
*
* <p> If w == 0, it will be taken to equal
* Math.round(h*(getWidth()/getHeight())).
* Similarly, if h == 0, it will be taken to equal
* Math.round(w*(getHeight()/getWidth())). One of
* w or h must be non-zero or else an IllegalArgumentException
* will be thrown.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param w the width of rendered image in pixels, or 0.
* @param h the height of rendered image in pixels, or 0.
* @param hints a RenderingHints object containg hints.
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
/**
* Returnd a RenderedImage instance of this image with a default
* width and height in pixels. The RenderContext is built
* automatically with an appropriate usr2dev transform and an area
* of interest of the full image. The rendering hints are
* empty. createDefaultRendering may make use of a stored
* rendering for speed.
*
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createDefaultRendering();
/**
* Creates a RenderedImage that represented a rendering of this image
* using a given RenderContext. This is the most general way to obtain a
* rendering of a RenderableImage.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* (from the RenderContext) were used to create the image.
* In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param renderContext the RenderContext to use to produce the rendering.
* @return a RenderedImage containing the rendered data.
*/
RenderedImage createRendering(RenderContext renderContext);
}

View File

@ -0,0 +1,350 @@
/*
* Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.awt.RenderingHints;
import java.util.Hashtable;
import java.util.Vector;
/**
* This class handles the renderable aspects of an operation with help
* from its associated instance of a ContextualRenderedImageFactory.
*/
public class RenderableImageOp implements RenderableImage {
/** A ParameterBlock containing source and parameters. */
ParameterBlock paramBlock;
/** The associated ContextualRenderedImageFactory. */
ContextualRenderedImageFactory myCRIF;
/** The bounding box of the results of this RenderableImageOp. */
Rectangle2D boundingBox;
/**
* Constructs a RenderedImageOp given a
* ContextualRenderedImageFactory object, and
* a ParameterBlock containing RenderableImage sources and other
* parameters. Any RenderedImage sources referenced by the
* ParameterBlock will be ignored.
*
* @param CRIF a ContextualRenderedImageFactory object
* @param paramBlock a ParameterBlock containing this operation's source
* images and other parameters necessary for the operation
* to run.
*/
public RenderableImageOp(ContextualRenderedImageFactory CRIF,
ParameterBlock paramBlock) {
this.myCRIF = CRIF;
this.paramBlock = (ParameterBlock) paramBlock.clone();
}
/**
* Returns a vector of RenderableImages that are the sources of
* image data for this RenderableImage. Note that this method may
* return an empty vector, to indicate that the image has no sources,
* or null, to indicate that no information is available.
*
* @return a (possibly empty) Vector of RenderableImages, or null.
*/
public Vector<RenderableImage> getSources() {
return getRenderableSources();
}
private Vector getRenderableSources() {
Vector sources = null;
if (paramBlock.getNumSources() > 0) {
sources = new Vector();
int i = 0;
while (i < paramBlock.getNumSources()) {
Object o = paramBlock.getSource(i);
if (o instanceof RenderableImage) {
sources.add((RenderableImage)o);
i++;
} else {
break;
}
}
}
return sources;
}
/**
* Gets a property from the property set of this image.
* If the property name is not recognized, java.awt.Image.UndefinedProperty
* will be returned.
*
* @param name the name of the property to get, as a String.
* @return a reference to the property Object, or the value
* java.awt.Image.UndefinedProperty.
*/
public Object getProperty(String name) {
return myCRIF.getProperty(paramBlock, name);
}
/**
* Return a list of names recognized by getProperty.
* @return a list of property names.
*/
public String[] getPropertyNames() {
return myCRIF.getPropertyNames();
}
/**
* Returns true if successive renderings (that is, calls to
* createRendering() or createScaledRendering()) with the same arguments
* may produce different results. This method may be used to
* determine whether an existing rendering may be cached and
* reused. The CRIF's isDynamic method will be called.
* @return <code>true</code> if successive renderings with the
* same arguments might produce different results;
* <code>false</code> otherwise.
*/
public boolean isDynamic() {
return myCRIF.isDynamic();
}
/**
* Gets the width in user coordinate space. By convention, the
* usual width of a RenderableImage is equal to the image's aspect
* ratio (width divided by height).
*
* @return the width of the image in user coordinates.
*/
public float getWidth() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getWidth();
}
/**
* Gets the height in user coordinate space. By convention, the
* usual height of a RenderedImage is equal to 1.0F.
*
* @return the height of the image in user coordinates.
*/
public float getHeight() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getHeight();
}
/**
* Gets the minimum X coordinate of the rendering-independent image data.
*/
public float getMinX() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getMinX();
}
/**
* Gets the minimum Y coordinate of the rendering-independent image data.
*/
public float getMinY() {
if (boundingBox == null) {
boundingBox = myCRIF.getBounds2D(paramBlock);
}
return (float)boundingBox.getMinY();
}
/**
* Change the current ParameterBlock of the operation, allowing
* editing of image rendering chains. The effects of such a
* change will be visible when a new rendering is created from
* this RenderableImageOp or any dependent RenderableImageOp.
*
* @param paramBlock the new ParameterBlock.
* @return the old ParameterBlock.
* @see #getParameterBlock
*/
public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
ParameterBlock oldParamBlock = this.paramBlock;
this.paramBlock = (ParameterBlock)paramBlock.clone();
return oldParamBlock;
}
/**
* Returns a reference to the current parameter block.
* @return the <code>ParameterBlock</code> of this
* <code>RenderableImageOp</code>.
* @see #setParameterBlock(ParameterBlock)
*/
public ParameterBlock getParameterBlock() {
return paramBlock;
}
/**
* Creates a RenderedImage instance of this image with width w, and
* height h in pixels. The RenderContext is built automatically
* with an appropriate usr2dev transform and an area of interest
* of the full image. All the rendering hints come from hints
* passed in.
*
* <p> If w == 0, it will be taken to equal
* Math.round(h*(getWidth()/getHeight())).
* Similarly, if h == 0, it will be taken to equal
* Math.round(w*(getHeight()/getWidth())). One of
* w or h must be non-zero or else an IllegalArgumentException
* will be thrown.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param w the width of rendered image in pixels, or 0.
* @param h the height of rendered image in pixels, or 0.
* @param hints a RenderingHints object containg hints.
* @return a RenderedImage containing the rendered data.
*/
public RenderedImage createScaledRendering(int w, int h,
RenderingHints hints) {
// DSR -- code to try to get a unit scale
double sx = (double)w/getWidth();
double sy = (double)h/getHeight();
if (Math.abs(sx/sy - 1.0) < 0.01) {
sx = sy;
}
AffineTransform usr2dev = AffineTransform.getScaleInstance(sx, sy);
RenderContext newRC = new RenderContext(usr2dev, hints);
return createRendering(newRC);
}
/**
* Gets a RenderedImage instance of this image with a default
* width and height in pixels. The RenderContext is built
* automatically with an appropriate usr2dev transform and an area
* of interest of the full image. All the rendering hints come
* from hints passed in. Implementors of this interface must be
* sure that there is a defined default width and height.
*
* @return a RenderedImage containing the rendered data.
*/
public RenderedImage createDefaultRendering() {
AffineTransform usr2dev = new AffineTransform(); // Identity
RenderContext newRC = new RenderContext(usr2dev);
return createRendering(newRC);
}
/**
* Creates a RenderedImage which represents this
* RenderableImageOp (including its Renderable sources) rendered
* according to the given RenderContext.
*
* <p> This method supports chaining of either Renderable or
* RenderedImage operations. If sources in
* the ParameterBlock used to construct the RenderableImageOp are
* RenderableImages, then a three step process is followed:
*
* <ol>
* <li> mapRenderContext() is called on the associated CRIF for
* each RenderableImage source;
* <li> createRendering() is called on each of the RenderableImage sources
* using the backwards-mapped RenderContexts obtained in step 1,
* resulting in a rendering of each source;
* <li> ContextualRenderedImageFactory.create() is called
* with a new ParameterBlock containing the parameters of
* the RenderableImageOp and the RenderedImages that were created by the
* createRendering() calls.
* </ol>
*
* <p> If the elements of the source Vector of
* the ParameterBlock used to construct the RenderableImageOp are
* instances of RenderedImage, then the CRIF.create() method is
* called immediately using the original ParameterBlock.
* This provides a basis case for the recursion.
*
* <p> The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* (from the RenderContext) were used to create the image.
* In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param renderContext The RenderContext to use to perform the rendering.
* @return a RenderedImage containing the desired output image.
*/
public RenderedImage createRendering(RenderContext renderContext) {
RenderedImage image = null;
RenderContext rcOut = null;
// Clone the original ParameterBlock; if the ParameterBlock
// contains RenderableImage sources, they will be replaced by
// RenderedImages.
ParameterBlock renderedParamBlock = (ParameterBlock)paramBlock.clone();
Vector sources = getRenderableSources();
try {
// This assumes that if there is no renderable source, that there
// is a rendered source in paramBlock
if (sources != null) {
Vector renderedSources = new Vector();
for (int i = 0; i < sources.size(); i++) {
rcOut = myCRIF.mapRenderContext(i, renderContext,
paramBlock, this);
RenderedImage rdrdImage =
((RenderableImage)sources.elementAt(i)).createRendering(rcOut);
if (rdrdImage == null) {
return null;
}
// Add this rendered image to the ParameterBlock's
// list of RenderedImages.
renderedSources.addElement(rdrdImage);
}
if (renderedSources.size() > 0) {
renderedParamBlock.setSources(renderedSources);
}
}
return myCRIF.create(renderContext, renderedParamBlock);
} catch (ArrayIndexOutOfBoundsException e) {
// This should never happen
return null;
}
}
}

View File

@ -0,0 +1,219 @@
/*
* Portions Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.util.Enumeration;
import java.util.Vector;
/**
* An adapter class that implements ImageProducer to allow the
* asynchronous production of a RenderableImage. The size of the
* ImageConsumer is determined by the scale factor of the usr2dev
* transform in the RenderContext. If the RenderContext is null, the
* default rendering of the RenderableImage is used. This class
* implements an asynchronous production that produces the image in
* one thread at one resolution. This class may be subclassed to
* implement versions that will render the image using several
* threads. These threads could render either the same image at
* progressively better quality, or different sections of the image at
* a single resolution.
*/
public class RenderableImageProducer implements ImageProducer, Runnable {
/** The RenderableImage source for the producer. */
RenderableImage rdblImage;
/** The RenderContext to use for producing the image. */
RenderContext rc;
/** A Vector of image consumers. */
Vector ics = new Vector();
/**
* Constructs a new RenderableImageProducer from a RenderableImage
* and a RenderContext.
*
* @param rdblImage the RenderableImage to be rendered.
* @param rc the RenderContext to use for producing the pixels.
*/
public RenderableImageProducer(RenderableImage rdblImage,
RenderContext rc) {
this.rdblImage = rdblImage;
this.rc = rc;
}
/**
* Sets a new RenderContext to use for the next startProduction() call.
*
* @param rc the new RenderContext.
*/
public synchronized void setRenderContext(RenderContext rc) {
this.rc = rc;
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image.
*
* @param ic an ImageConsumer to be added to the interest list.
*/
public synchronized void addConsumer(ImageConsumer ic) {
if (!ics.contains(ic)) {
ics.addElement(ic);
}
}
/**
* Determine if an ImageConsumer is on the list of consumers
* currently interested in data for this image.
*
* @param ic the ImageConsumer to be checked.
* @return true if the ImageConsumer is on the list; false otherwise.
*/
public synchronized boolean isConsumer(ImageConsumer ic) {
return ics.contains(ic);
}
/**
* Remove an ImageConsumer from the list of consumers interested in
* data for this image.
*
* @param ic the ImageConsumer to be removed.
*/
public synchronized void removeConsumer(ImageConsumer ic) {
ics.removeElement(ic);
}
/**
* Adds an ImageConsumer to the list of consumers interested in
* data for this image, and immediately starts delivery of the
* image data through the ImageConsumer interface.
*
* @param ic the ImageConsumer to be added to the list of consumers.
*/
public synchronized void startProduction(ImageConsumer ic) {
addConsumer(ic);
// Need to build a runnable object for the Thread.
Thread thread = new Thread(this, "RenderableImageProducer Thread");
thread.start();
}
/**
* Requests that a given ImageConsumer have the image data delivered
* one more time in top-down, left-right order.
*
* @param ic the ImageConsumer requesting the resend.
*/
public void requestTopDownLeftRightResend(ImageConsumer ic) {
// So far, all pixels are already sent in TDLR order
}
/**
* The runnable method for this class. This will produce an image using
* the current RenderableImage and RenderContext and send it to all the
* ImageConsumer currently registered with this class.
*/
public void run() {
// First get the rendered image
RenderedImage rdrdImage;
if (rc != null) {
rdrdImage = rdblImage.createRendering(rc);
} else {
rdrdImage = rdblImage.createDefaultRendering();
}
// And its ColorModel
ColorModel colorModel = rdrdImage.getColorModel();
Raster raster = rdrdImage.getData();
SampleModel sampleModel = raster.getSampleModel();
DataBuffer dataBuffer = raster.getDataBuffer();
if (colorModel == null) {
colorModel = ColorModel.getRGBdefault();
}
int minX = raster.getMinX();
int minY = raster.getMinY();
int width = raster.getWidth();
int height = raster.getHeight();
Enumeration icList;
ImageConsumer ic;
// Set up the ImageConsumers
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.setDimensions(width,height);
ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
ImageConsumer.COMPLETESCANLINES |
ImageConsumer.SINGLEPASS |
ImageConsumer.SINGLEFRAME);
}
// Get RGB pixels from the raster scanline by scanline and
// send to consumers.
int pix[] = new int[width];
int i,j;
int numBands = sampleModel.getNumBands();
int tmpPixel[] = new int[numBands];
for (j = 0; j < height; j++) {
for(i = 0; i < width; i++) {
sampleModel.getPixel(i, j, tmpPixel, dataBuffer);
pix[i] = colorModel.getDataElement(tmpPixel, 0);
}
// Now send the scanline to the Consumers
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.setPixels(0, j, width, 1, colorModel, pix, 0, width);
}
}
// Now tell the consumers we're done.
icList = ics.elements();
while (icList.hasMoreElements()) {
ic = (ImageConsumer)icList.nextElement();
ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
}
}
}

View File

@ -0,0 +1,78 @@
/*
* Portions Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/* ********************************************************************
**********************************************************************
**********************************************************************
*** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
*** As an unpublished work pursuant to Title 17 of the United ***
*** States Code. All rights reserved. ***
**********************************************************************
**********************************************************************
**********************************************************************/
package java.awt.image.renderable;
import java.awt.image.RenderedImage;
import java.awt.RenderingHints;
/**
* The RenderedImageFactory interface (often abbreviated RIF) is
* intended to be implemented by classes that wish to act as factories
* to produce different renderings, for example by executing a series
* of BufferedImageOps on a set of sources, depending on a specific
* set of parameters, properties, and rendering hints.
*/
public interface RenderedImageFactory {
/**
* Creates a RenderedImage representing the results of an imaging
* operation (or chain of operations) for a given ParameterBlock and
* RenderingHints. The RIF may also query any source images
* referenced by the ParameterBlock for their dimensions,
* SampleModels, properties, etc., as necessary.
*
* <p> The create() method can return null if the
* RenderedImageFactory is not capable of producing output for the
* given set of source images and parameters. For example, if a
* RenderedImageFactory is only capable of performing a 3x3
* convolution on single-banded image data, and the source image has
* multiple bands or the convolution Kernel is 5x5, null should be
* returned.
*
* <p> Hints should be taken into account, but can be ignored.
* The created RenderedImage may have a property identified
* by the String HINTS_OBSERVED to indicate which RenderingHints
* were used to create the image. In addition any RenderedImages
* that are obtained via the getSources() method on the created
* RenderedImage may have such a property.
*
* @param paramBlock a ParameterBlock containing sources and parameters
* for the RenderedImage to be created.
* @param hints a RenderingHints object containing hints.
* @return A RenderedImage containing the desired output.
*/
RenderedImage create(ParameterBlock paramBlock,
RenderingHints hints);
}

View File

@ -1696,8 +1696,8 @@ public class RequiredModelMBean
} catch (Exception e) {
// eat exceptions because interface doesn't have an
// exception on it
if (MODELMBEAN_LOGGER.isLoggable(Level.WARNING)) {
MODELMBEAN_LOGGER.logp(Level.WARNING,
if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),
"getAttributes(String[])",
"Failed to get \"" + attrNames[i] + "\": ", e);
@ -1857,8 +1857,8 @@ public class RequiredModelMBean
attrValue.getClass().getName() +
" received.");
} catch (ClassNotFoundException x) {
if (MODELMBEAN_LOGGER.isLoggable(Level.WARNING)) {
MODELMBEAN_LOGGER.logp(Level.WARNING,
if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),
"setAttribute(Attribute)","Class " +
attrType + " for attribute "
@ -2224,8 +2224,8 @@ public class RequiredModelMBean
ntfyObj.getMessage() + " Severity = " +
(String)ntfyDesc.getFieldValue("severity"));
} catch (Exception e) {
if (MODELMBEAN_LOGGER.isLoggable(Level.WARNING)) {
MODELMBEAN_LOGGER.logp(Level.WARNING,
if (MODELMBEAN_LOGGER.isLoggable(Level.FINE)) {
MODELMBEAN_LOGGER.logp(Level.FINE,
RequiredModelMBean.class.getName(),
"sendNotification(Notification)",
"Failed to log " +
@ -2618,8 +2618,8 @@ public class RequiredModelMBean
" Old value = " + oldv +
" New value = " + newv);
} catch (Exception e) {
if (MODELMBEAN_LOGGER.isLoggable(Level.WARNING)) {
MODELMBEAN_LOGGER.logp(Level.WARNING,
if (MODELMBEAN_LOGGER.isLoggable(Level.FINE)) {
MODELMBEAN_LOGGER.logp(Level.FINE,
RequiredModelMBean.class.getName(),mth,
"Failed to log " + ntfyObj.getType() +
" notification: ", e);
@ -2644,8 +2644,8 @@ public class RequiredModelMBean
" Old value = " + oldv +
" New value = " + newv);
} catch (Exception e) {
if (MODELMBEAN_LOGGER.isLoggable(Level.WARNING)) {
MODELMBEAN_LOGGER.logp(Level.WARNING,
if (MODELMBEAN_LOGGER.isLoggable(Level.FINE)) {
MODELMBEAN_LOGGER.logp(Level.FINE,
RequiredModelMBean.class.getName(),mth,
"Failed to log " + ntfyObj.getType() +
" notification: ", e);

View File

@ -44,7 +44,7 @@ import javax.print.attribute.Attribute;
* print request's, print job's, or print service's attribute set.
* <P>
* The Internet Assigned Numbers Authority maintains the
* <A HREF="http://www.isi.edu/in-notes/iana/assignments/url-schemes">official
* <A HREF="http://www.iana.org/assignments/uri-schemes.html">official
* list of URI schemes</A>.
* <p>
* Class ReferenceUriSchemesSupported defines enumeration values for widely

View File

@ -165,7 +165,8 @@ public class SunVolatileImage extends VolatileImage {
{
return new BufImgVolatileSurfaceManager(this, context);
}
return SurfaceManagerFactory.createVolatileManager(this, context);
SurfaceManagerFactory smf = SurfaceManagerFactory.getInstance();
return smf.createVolatileManager(this, context);
}
private Color getForeground() {

View File

@ -887,10 +887,10 @@ public final class AttributeValues implements Cloneable {
try {
AffineTransform rtxi = rtx.createInverse();
double dx = tx.getTranslateX();
double dy = tx.getTranslateY();
tx.preConcatenate(rtxi);
if (andTranslation) {
double dx = tx.getTranslateX();
double dy = tx.getTranslateY();
if (dx != 0 || dy != 0) {
tx.setTransform(tx.getScaleX(), tx.getShearY(),
tx.getShearX(), tx.getScaleY(), 0, 0);

View File

@ -27,6 +27,7 @@ package sun.font;
import java.lang.ref.SoftReference;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
@ -105,6 +106,19 @@ public class FileFontStrike extends PhysicalStrike {
boolean useNatives;
NativeStrike[] nativeStrikes;
/* Used only for communication to native layer */
private int intPtSize;
/* Perform global initialisation needed for Windows native rasterizer */
private static native boolean initNative();
private static boolean isXPorLater = false;
static {
if (FontManager.isWindows && !FontManager.useT2K &&
!GraphicsEnvironment.isHeadless()) {
isXPorLater = initNative();
}
}
FileFontStrike(FileFont fileFont, FontStrikeDesc desc) {
super(fileFont, desc);
this.fileFont = fileFont;
@ -165,7 +179,7 @@ public class FileFontStrike extends PhysicalStrike {
* should not segment unless there's another reason to do so.
*/
float ptSize = (float)matrix[3]; // interpreted only when meaningful.
int iSize = (int)ptSize;
int iSize = intPtSize = (int)ptSize;
boolean isSimpleTx = (at.getType() & complexTX) == 0;
segmentedCache =
(numGlyphs > SEGSIZE << 3) ||
@ -189,8 +203,26 @@ public class FileFontStrike extends PhysicalStrike {
FontManager.deRegisterBadFont(fileFont);
return;
}
if (fileFont.checkUseNatives() && desc.aaHint==0 && !algoStyle) {
/* First, see if native code should be used to create the glyph.
* GDI will return the integer metrics, not fractional metrics, which
* may be requested for this strike, so we would require here that :
* desc.fmHint != INTVAL_FRACTIONALMETRICS_ON
* except that the advance returned by GDI is always overwritten by
* the JDK rasteriser supplied one (see getGlyphImageFromWindows()).
*/
if (FontManager.isWindows && isXPorLater &&
!FontManager.useT2K &&
!GraphicsEnvironment.isHeadless() &&
!fileFont.useJavaRasterizer &&
(desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HRGB ||
desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HBGR) &&
(matrix[1] == 0.0 && matrix[2] == 0.0 &&
matrix[0] == matrix[3] &&
matrix[0] >= 3.0 && matrix[0] <= 100.0) &&
!((TrueTypeFont)fileFont).useEmbeddedBitmapsForSize(intPtSize)) {
useNatives = true;
}
else if (fileFont.checkUseNatives() && desc.aaHint==0 && !algoStyle) {
/* Check its a simple scale of a pt size in the range
* where native bitmaps typically exist (6-36 pts) */
if (matrix[1] == 0.0 && matrix[2] == 0.0 &&
@ -208,7 +240,16 @@ public class FileFontStrike extends PhysicalStrike {
}
}
}
if (FontManager.logging && FontManager.isWindows) {
FontManager.logger.info
("Strike for " + fileFont + " at size = " + intPtSize +
" use natives = " + useNatives +
" useJavaRasteriser = " + fileFont.useJavaRasterizer +
" AAHint = " + desc.aaHint +
" Has Embedded bitmaps = " +
((TrueTypeFont)fileFont).
useEmbeddedBitmapsForSize(intPtSize));
}
this.disposer = new FontStrikeDisposer(fileFont, desc, pScalerContext);
/* Always get the image and the advance together for smaller sizes
@ -217,7 +258,12 @@ public class FileFontStrike extends PhysicalStrike {
* "maximumSizeForGetImageWithAdvance".
* This should be no greater than OutlineTextRender.THRESHOLD.
*/
getImageWithAdvance = at.getScaleY() <= 48.0;
double maxSz = 48.0;
getImageWithAdvance =
Math.abs(at.getScaleX()) <= maxSz &&
Math.abs(at.getScaleY()) <= maxSz &&
Math.abs(at.getShearX()) <= maxSz &&
Math.abs(at.getShearY()) <= maxSz;
/* Some applications request advance frequently during layout.
* If we are not getting and caching the image with the advance,
@ -250,8 +296,50 @@ public class FileFontStrike extends PhysicalStrike {
return fileFont.getNumGlyphs();
}
/* Try the native strikes first, then try the fileFont strike */
long getGlyphImageFromNative(int glyphCode) {
if (FontManager.isWindows) {
return getGlyphImageFromWindows(glyphCode);
} else {
return getGlyphImageFromX11(glyphCode);
}
}
/* There's no global state conflicts, so this method is not
* presently synchronized.
*/
private native long _getGlyphImageFromWindows(String family,
int style,
int size,
int glyphCode,
boolean fracMetrics);
long getGlyphImageFromWindows(int glyphCode) {
String family = fileFont.getFamilyName(null);
int style = desc.style & Font.BOLD | desc.style & Font.ITALIC
| fileFont.getStyle();
int size = intPtSize;
long ptr = _getGlyphImageFromWindows
(family, style, size, glyphCode,
desc.fmHint == INTVAL_FRACTIONALMETRICS_ON);
if (ptr != 0) {
/* Get the advance from the JDK rasterizer. This is mostly
* necessary for the fractional metrics case, but there are
* also some very small number (<0.25%) of marginal cases where
* there is some rounding difference between windows and JDK.
* After these are resolved, we can restrict this extra
* work to the FM case.
*/
float advance = getGlyphAdvance(glyphCode, false);
StrikeCache.unsafe.putFloat(ptr + StrikeCache.xAdvanceOffset,
advance);
return ptr;
} else {
return fileFont.getGlyphImage(pScalerContext, glyphCode);
}
}
/* Try the native strikes first, then try the fileFont strike */
long getGlyphImageFromX11(int glyphCode) {
long glyphPtr;
char charCode = fileFont.glyphToCharMap[glyphCode];
for (int i=0;i<nativeStrikes.length;i++) {
@ -271,13 +359,19 @@ public class FileFontStrike extends PhysicalStrike {
if (glyphCode >= INVISIBLE_GLYPHS) {
return StrikeCache.invisibleGlyphPtr;
}
long glyphPtr;
long glyphPtr = 0L;
if ((glyphPtr = getCachedGlyphPtr(glyphCode)) != 0L) {
return glyphPtr;
} else {
if (useNatives) {
glyphPtr = getGlyphImageFromNative(glyphCode);
} else {
if (glyphPtr == 0L && FontManager.logging) {
FontManager.logger.info
("Strike for " + fileFont +
" at size = " + intPtSize +
" couldn't get native glyph for code = " + glyphCode);
}
} if (glyphPtr == 0L) {
glyphPtr = fileFont.getGlyphImage(pScalerContext,
glyphCode);
}
@ -295,10 +389,10 @@ public class FileFontStrike extends PhysicalStrike {
} else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) {
continue;
} else {
long glyphPtr;
long glyphPtr = 0L;
if (useNatives) {
glyphPtr = getGlyphImageFromNative(glyphCode);
} else {
} if (glyphPtr == 0L) {
glyphPtr = fileFont.getGlyphImage(pScalerContext,
glyphCode);
}
@ -327,10 +421,11 @@ public class FileFontStrike extends PhysicalStrike {
} else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) {
continue;
} else {
long glyphPtr;
long glyphPtr = 0L;
if (useNatives) {
glyphPtr = getGlyphImageFromNative(glyphCode);
} else {
}
if (glyphPtr == 0L) {
glyphPtr = fileFont.getGlyphImage(pScalerContext,
glyphCode);
}
@ -454,11 +549,16 @@ public class FileFontStrike extends PhysicalStrike {
}
}
float getGlyphAdvance(int glyphCode) {
return getGlyphAdvance(glyphCode, true);
}
/* Metrics info is always retrieved. If the GlyphInfo address is non-zero
* then metrics info there is valid and can just be copied.
* This is in user space coordinates.
* This is in user space coordinates unless getUserAdv == false.
* Device space advance should not be propagated out of this class.
*/
float getGlyphAdvance(int glyphCode) {
private float getGlyphAdvance(int glyphCode, boolean getUserAdv) {
float advance;
if (glyphCode >= INVISIBLE_GLYPHS) {
@ -480,11 +580,11 @@ public class FileFontStrike extends PhysicalStrike {
}
}
if (invertDevTx != null) {
if (invertDevTx != null || !getUserAdv) {
/* If there is a device transform need x & y advance to
* transform back into user space.
*/
advance = getGlyphMetrics(glyphCode).x;
advance = getGlyphMetrics(glyphCode, getUserAdv).x;
} else {
long glyphPtr;
if (getImageWithAdvance) {
@ -620,6 +720,10 @@ public class FileFontStrike extends PhysicalStrike {
}
Point2D.Float getGlyphMetrics(int glyphCode) {
return getGlyphMetrics(glyphCode, true);
}
private Point2D.Float getGlyphMetrics(int glyphCode, boolean getUserAdv) {
Point2D.Float metrics = new Point2D.Float();
// !!! or do we force sgv user glyphs?
@ -627,7 +731,7 @@ public class FileFontStrike extends PhysicalStrike {
return metrics;
}
long glyphPtr;
if (getImageWithAdvance) {
if (getImageWithAdvance && getUserAdv) {
/* A heuristic optimisation says that for most cases its
* worthwhile retrieving the image at the same time as the
* metrics. So here we get the image data even if its not
@ -644,9 +748,9 @@ public class FileFontStrike extends PhysicalStrike {
metrics.y = StrikeCache.unsafe.getFloat
(glyphPtr + StrikeCache.yAdvanceOffset);
/* advance is currently in device space, need to convert back
* into user space.
* into user space, unless getUserAdv == false.
* This must not include the translation component. */
if (invertDevTx != null) {
if (invertDevTx != null && getUserAdv) {
invertDevTx.deltaTransform(metrics, metrics);
}
} else {
@ -675,9 +779,9 @@ public class FileFontStrike extends PhysicalStrike {
if (value == null) {
fileFont.getGlyphMetrics(pScalerContext, glyphCode, metrics);
/* advance is currently in device space, need to convert back
* into user space.
* into user space, unless getUserAdv == false.
*/
if (invertDevTx != null) {
if (invertDevTx != null && getUserAdv) {
invertDevTx.deltaTransform(metrics, metrics);
}
value = new Point2D.Float(metrics.x, metrics.y);

View File

@ -241,6 +241,13 @@ public abstract class Font2D {
if (font.isTransformed()) {
glyphTx.concatenate(font.getTransform());
}
if (glyphTx.getTranslateX() != 0 || glyphTx.getTranslateY() != 0) {
glyphTx.setTransform(glyphTx.getScaleX(),
glyphTx.getShearY(),
glyphTx.getShearX(),
glyphTx.getScaleY(),
0.0, 0.0);
}
FontStrikeDesc desc = new FontStrikeDesc(devTx, glyphTx,
font.getStyle(), aa, fm);
return getStrike(desc, false);
@ -266,6 +273,13 @@ public abstract class Font2D {
at.scale(ptSize, ptSize);
if (font.isTransformed()) {
at.concatenate(font.getTransform());
if (at.getTranslateX() != 0 || at.getTranslateY() != 0) {
at.setTransform(at.getScaleX(),
at.getShearY(),
at.getShearX(),
at.getScaleY(),
0.0, 0.0);
}
}
int aa = FontStrikeDesc.getAAHintIntVal(this, font, frc);
int fm = FontStrikeDesc.getFMHintIntVal(frc.getFractionalMetricsHint());

View File

@ -93,7 +93,6 @@ public final class FontManager {
*/
private static final int CHANNELPOOLSIZE = 20;
private static int lastPoolIndex = 0;
private static int poolSize = 0;
private static FileFont fontFileCache[] = new FileFont[CHANNELPOOLSIZE];
/* Need to implement a simple linked list scheme for fast
@ -245,9 +244,11 @@ public final class FontManager {
osName = System.getProperty("os.name", "unknownOS");
isSolaris = osName.startsWith("SunOS");
if (isSolaris) {
String t2kStr= System.getProperty("sun.java2d.font.scaler");
String t2kStr = System.getProperty("sun.java2d.font.scaler");
if (t2kStr != null) {
useT2K = "t2k".equals(t2kStr);
}
if (isSolaris) {
String version = System.getProperty("os.version", "unk");
isSolaris8 = version.equals("5.8");
isSolaris9 = version.equals("5.9");
@ -283,29 +284,32 @@ public final class FontManager {
private static native void initIDs();
public static void addToPool(FileFont font) {
boolean added = false;
FileFont fontFileToClose = null;
int freeSlot = -1;
synchronized (fontFileCache) {
/* use poolSize to quickly detect if there's any free slots.
* This is a performance tweak based on the assumption that
* if this is executed at all often, its because there are many
* fonts being used and the pool will be full, and we will save
* a fruitless iteration
/* Avoid duplicate entries in the pool, and don't close() it,
* since this method is called only from within open().
* Seeing a duplicate is most likely to happen if the thread
* was interrupted during a read, forcing perhaps repeated
* close and open calls and it eventually it ends up pointing
* at the same slot.
*/
if (poolSize < CHANNELPOOLSIZE) {
for (int i=0; i<CHANNELPOOLSIZE; i++) {
if (fontFileCache[i] == null) {
fontFileCache[i] = font;
poolSize++;
added = true;
break;
}
for (int i=0;i<CHANNELPOOLSIZE;i++) {
if (fontFileCache[i] == font) {
return;
}
assert added;
if (fontFileCache[i] == null && freeSlot < 0) {
freeSlot = i;
}
}
if (freeSlot >= 0) {
fontFileCache[freeSlot] = font;
return;
} else {
// is it possible for this to be the same font?
assert fontFileCache[lastPoolIndex] != font;
/* replace with new font, poolSize is unchanged. */
fontFileCache[lastPoolIndex].close();
/* replace with new font. */
fontFileToClose = fontFileCache[lastPoolIndex];
fontFileCache[lastPoolIndex] = font;
/* lastPoolIndex is updated so that the least recently opened
* file will be closed next.
@ -313,6 +317,19 @@ public final class FontManager {
lastPoolIndex = (lastPoolIndex+1) % CHANNELPOOLSIZE;
}
}
/* Need to close the font file outside of the synchronized block,
* since its possible some other thread is in an open() call on
* this font file, and could be holding its lock and the pool lock.
* Releasing the pool lock allows that thread to continue, so it can
* then release the lock on this font, allowing the close() call
* below to proceed.
* Also, calling close() is safe because any other thread using
* the font we are closing() synchronizes all reading, so we
* will not close the file while its in use.
*/
if (fontFileToClose != null) {
fontFileToClose.close();
}
}
/*
@ -334,7 +351,6 @@ public final class FontManager {
for (int i=0; i<CHANNELPOOLSIZE; i++) {
if (fontFileCache[i] == font) {
fontFileCache[i] = null;
poolSize--;
}
}
}

View File

@ -85,7 +85,7 @@ public final class GlyphLayout {
private GVData _gvdata;
// cached glyph layout data for reuse
private static GlyphLayout cache; // reusable
private static volatile GlyphLayout cache; // reusable
private LayoutEngineFactory _lef; // set when get is called, unset when done is called
private TextRecord _textRecord; // the text we're working on, used by iterators

View File

@ -893,6 +893,31 @@ public class TrueTypeFont extends FileFont {
return null;
}
/* Used to determine if this size has embedded bitmaps, which
* for CJK fonts should be used in preference to LCD glyphs.
*/
boolean useEmbeddedBitmapsForSize(int ptSize) {
if (!supportsCJK) {
return false;
}
if (getDirectoryEntry(EBLCTag) == null) {
return false;
}
ByteBuffer eblcTable = getTableBuffer(EBLCTag);
int numSizes = eblcTable.getInt(4);
/* The bitmapSizeTable's start at offset of 8.
* Each bitmapSizeTable entry is 48 bytes.
* The offset of ppemY in the entry is 45.
*/
for (int i=0;i<numSizes;i++) {
int ppemY = eblcTable.get(8+(i*48)+45) &0xff;
if (ppemY == ptSize) {
return true;
}
}
return false;
}
public String getFullName() {
return fullName;
}

View File

@ -589,7 +589,7 @@ public class Type1Font extends FileFont {
protected synchronized FontScaler getScaler() {
if (scaler == null) {
return FontManager.getScaler(this, 0, false, fileSize);
scaler = FontManager.getScaler(this, 0, false, fileSize);
}
return scaler;

View File

@ -2805,6 +2805,9 @@ public final class SunGraphics2D
}
if (font.hasLayoutAttributes()) {
if (str.length() == 0) {
return;
}
new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);
return;
}
@ -2831,6 +2834,9 @@ public final class SunGraphics2D
}
if (font.hasLayoutAttributes()) {
if (str.length() == 0) {
return;
}
new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);
return;
}
@ -2856,6 +2862,9 @@ public final class SunGraphics2D
if (iterator == null) {
throw new NullPointerException("AttributedCharacterIterator is null");
}
if (iterator.getBeginIndex() == iterator.getEndIndex()) {
return; /* nothing to draw */
}
TextLayout tl = new TextLayout(iterator, getFontRenderContext());
tl.draw(this, (float) x, (float) y);
}
@ -2865,6 +2874,9 @@ public final class SunGraphics2D
if (iterator == null) {
throw new NullPointerException("AttributedCharacterIterator is null");
}
if (iterator.getBeginIndex() == iterator.getEndIndex()) {
return; /* nothing to draw */
}
TextLayout tl = new TextLayout(iterator, getFontRenderContext());
tl.draw(this, x, y);
}
@ -2900,6 +2912,9 @@ public final class SunGraphics2D
throw new ArrayIndexOutOfBoundsException("bad offset/length");
}
if (font.hasLayoutAttributes()) {
if (data.length == 0) {
return;
}
new TextLayout(new String(data, offset, length),
font, getFontRenderContext()).draw(this, x, y);
return;
@ -2934,6 +2949,9 @@ public final class SunGraphics2D
chData[i] = (char)(data[i+offset] & 0xff);
}
if (font.hasLayoutAttributes()) {
if (data.length == 0) {
return;
}
new TextLayout(new String(chData),
font, getFontRenderContext()).draw(this, x, y);
return;

View File

@ -0,0 +1,91 @@
/*
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.VolatileSurfaceManager;
/**
* This factory creates platform specific VolatileSurfaceManager
* implementations.
*
* There are two platform specific SurfaceManagerFactories in OpenJDK,
* UnixSurfaceManagerFactory and WindowsSurfaceManagerFactory.
* The actually used SurfaceManagerFactory is set by the respective platform
* GraphicsEnvironment implementations in the static initializer.
*/
public abstract class SurfaceManagerFactory {
/**
* The single shared instance.
*/
private static SurfaceManagerFactory instance;
/**
* Returns the surface manager factory instance. This returns a factory
* that has been set by {@link #setInstance(SurfaceManagerFactory)}.
*
* @return the surface manager factory
*/
public synchronized static SurfaceManagerFactory getInstance() {
if (instance == null) {
throw new IllegalStateException("No SurfaceManagerFactory set.");
}
return instance;
}
/**
* Sets the surface manager factory. This may only be called once, and it
* may not be set back to {@code null} when the factory is already
* instantiated.
*
* @param factory the factory to set
*/
public synchronized static void setInstance(SurfaceManagerFactory factory) {
if (factory == null) {
// We don't want to allow setting this to null at any time.
throw new IllegalArgumentException("factory must be non-null");
}
if (instance != null) {
// We don't want to re-set the instance at any time.
throw new IllegalStateException("The surface manager factory is already initialized");
}
instance = factory;
}
/**
* Creates a new instance of a VolatileSurfaceManager given any
* arbitrary SunVolatileImage. An optional context Object can be supplied
* as a way for the caller to pass pipeline-specific context data to
* the VolatileSurfaceManager (such as a backbuffer handle, for example).
*/
public abstract VolatileSurfaceManager
createVolatileManager(SunVolatileImage image, Object context);
}

View File

@ -344,8 +344,15 @@ class PSPathGraphics extends PathGraphics {
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
if (scaleX > devScaleX) scaleX = devScaleX;
if (scaleY > devScaleY) scaleY = devScaleY;
/* check if rotated or sheared */
int transformType = fullTransform.getType();
boolean clampScale = ((transformType &
(AffineTransform.TYPE_GENERAL_ROTATION |
AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0);
if (clampScale) {
if (scaleX > devScaleX) scaleX = devScaleX;
if (scaleY > devScaleY) scaleY = devScaleY;
}
/* We do not need to draw anything if either scaling
* factor is zero.

View File

@ -2149,48 +2149,55 @@ public class ServiceDialog extends JDialog implements ActionListener {
}
}
}
}
rbPortrait.setEnabled(pSupported);
rbLandscape.setEnabled(lSupported);
rbRevPortrait.setEnabled(rpSupported);
rbRevLandscape.setEnabled(rlSupported);
OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
if (or == null ||
!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
rbPortrait.setEnabled(pSupported);
rbLandscape.setEnabled(lSupported);
rbRevPortrait.setEnabled(rpSupported);
rbRevLandscape.setEnabled(rlSupported);
or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
// need to validate if default is not supported
if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
or = null;
Object values =
psCurrent.getSupportedAttributeValues(orCategory,
docFlavor,
asCurrent);
if (values instanceof OrientationRequested[]) {
OrientationRequested[] orValues =
OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory);
if (or == null ||
!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
// need to validate if default is not supported
if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
or = null;
values =
psCurrent.getSupportedAttributeValues(orCategory,
docFlavor,
asCurrent);
if (values instanceof OrientationRequested[]) {
OrientationRequested[] orValues =
(OrientationRequested[])values;
if (orValues.length > 1) {
// get the first in the list
or = orValues[0];
if (orValues.length > 1) {
// get the first in the list
or = orValues[0];
}
}
}
if (or == null) {
or = OrientationRequested.PORTRAIT;
}
asCurrent.add(or);
}
if (or == null) {
or = OrientationRequested.PORTRAIT;
if (or == OrientationRequested.PORTRAIT) {
rbPortrait.setSelected(true);
} else if (or == OrientationRequested.LANDSCAPE) {
rbLandscape.setSelected(true);
} else if (or == OrientationRequested.REVERSE_PORTRAIT) {
rbRevPortrait.setSelected(true);
} else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
rbRevLandscape.setSelected(true);
}
asCurrent.add(or);
}
} else {
rbPortrait.setEnabled(pSupported);
rbLandscape.setEnabled(lSupported);
rbRevPortrait.setEnabled(rpSupported);
rbRevLandscape.setEnabled(rlSupported);
if (or == OrientationRequested.PORTRAIT) {
rbPortrait.setSelected(true);
} else if (or == OrientationRequested.LANDSCAPE) {
rbLandscape.setSelected(true);
} else if (or == OrientationRequested.REVERSE_PORTRAIT) {
rbRevPortrait.setSelected(true);
} else { // if (or == OrientationRequested.REVERSE_LANDSCAPE)
rbRevLandscape.setSelected(true);
}
}
}

View File

@ -102,7 +102,7 @@ class OCSPChecker extends PKIXCertPathChecker {
*/
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
remainingCerts = certs.length;
remainingCerts = certs.length + 1;
} else {
throw new CertPathValidatorException(
"Forward checking not supported");
@ -131,14 +131,22 @@ class OCSPChecker extends PKIXCertPathChecker {
InputStream in = null;
OutputStream out = null;
// Decrement the certificate counter
remainingCerts--;
try {
// Examine OCSP properties
X509Certificate responderCert = null;
boolean seekResponderCert = false;
X500Principal responderSubjectName = null;
X500Principal responderIssuerName = null;
BigInteger responderSerialNumber = null;
boolean seekIssuerCert = true;
X509CertImpl issuerCertImpl = null;
X509CertImpl currCertImpl =
X509CertImpl.toImpl((X509Certificate)cert);
/*
* OCSP security property values, in the following order:
* 1. ocsp.responderURL
@ -148,6 +156,9 @@ class OCSPChecker extends PKIXCertPathChecker {
*/
String[] properties = getOCSPProperties();
// Check whether OCSP is feasible before seeking cert information
URL url = getOCSPServerURL(currCertImpl, properties);
// When responder's subject name is set then the issuer/serial
// properties are ignored
if (properties[1] != null) {
@ -172,14 +183,9 @@ class OCSPChecker extends PKIXCertPathChecker {
seekResponderCert = true;
}
boolean seekIssuerCert = true;
X509CertImpl issuerCertImpl = null;
X509CertImpl currCertImpl =
X509CertImpl.toImpl((X509Certificate)cert);
remainingCerts--;
// Set the issuer certificate
if (remainingCerts != 0) {
// Set the issuer certificate to the next cert in the chain
// (unless we're processing the final cert).
if (remainingCerts < certs.length) {
issuerCertImpl = X509CertImpl.toImpl(certs[remainingCerts]);
seekIssuerCert = false; // done
@ -312,7 +318,8 @@ class OCSPChecker extends PKIXCertPathChecker {
// Construct an OCSP Request
OCSPRequest ocspRequest =
new OCSPRequest(currCertImpl, issuerCertImpl);
URL url = getOCSPServerURL(currCertImpl, properties);
// Use the URL to the OCSP service that was created earlier
HttpURLConnection con = (HttpURLConnection)url.openConnection();
if (DEBUG != null) {
DEBUG.println("connecting to OCSP service at: " + url);

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -368,7 +368,7 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
//text can not be smaller than 1 point
ptsz = 1.0;
}
context->ptsz = (((int) ptsz) << 6);
context->ptsz = (int)(ptsz * 64);
context->transform.xx = FloatToFTFixed((float)dmat[0]/ptsz);
context->transform.yx = -FloatToFTFixed((float)dmat[1]/ptsz);
context->transform.xy = -FloatToFTFixed((float)dmat[2]/ptsz);
@ -779,13 +779,24 @@ Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
}
if (context->fmType == TEXT_FM_ON) {
glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x);
glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y);
} else {
double advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
glyphInfo->advanceX =
(float) ROUND(FT26Dot6ToFloat(ftglyph->advance.x));
(float) (advh * FTFixedToFloat(context->transform.xx));
glyphInfo->advanceY =
(float) ROUND(FT26Dot6ToFloat(-ftglyph->advance.y));
(float) (advh * FTFixedToFloat(context->transform.xy));
} else {
if (!ftglyph->advance.y) {
glyphInfo->advanceX =
(float) ROUND(FT26Dot6ToFloat(ftglyph->advance.x));
glyphInfo->advanceY = 0;
} else if (!ftglyph->advance.x) {
glyphInfo->advanceX = 0;
glyphInfo->advanceY =
(float) ROUND(FT26Dot6ToFloat(-ftglyph->advance.y));
} else {
glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x);
glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y);
}
}
if (imageSize == 0) {
@ -974,7 +985,7 @@ static FT_Outline* getFTOutline(JNIEnv* env, jobject font2D,
FT_Outline_Translate(&ftglyph->outline,
FloatToF26Dot6(xpos),
FloatToF26Dot6(ypos));
-FloatToF26Dot6(ypos));
return &ftglyph->outline;
}

View File

@ -416,7 +416,8 @@ void NAME_SRCOVER_MASKBLIT(SRC, DST) \
MultiplyAndStore ## STRATEGY ## Comps(res, \
srcF, res);\
} \
if (!(DST ## IsPremultiplied) && resA && \
if (!(DST ## IsOpaque) && \
!(DST ## IsPremultiplied) && resA && \
resA < MaxValFor ## STRATEGY) \
{ \
DivideAndStore ## STRATEGY ## Comps(res, \
@ -475,7 +476,8 @@ void NAME_SRCOVER_MASKBLIT(SRC, DST) \
MultiplyAndStore ## STRATEGY ## Comps(res, \
srcF, res); \
} \
if (!(DST ## IsPremultiplied) && resA && \
if (!(DST ## IsOpaque) && \
!(DST ## IsPremultiplied) && resA && \
resA < MaxValFor ## STRATEGY) \
{ \
DivideAndStore ## STRATEGY ## Comps(res, res, resA); \
@ -797,7 +799,8 @@ void NAME_SRCOVER_MASKFILL(TYPE) \
Store ## STRATEGY ## CompsUsingOp(res, +=, tmp); \
} \
} \
if (!(TYPE ## IsPremultiplied) && resA && \
if (!(TYPE ## IsOpaque) && \
!(TYPE ## IsPremultiplied) && resA && \
resA < MaxValFor ## STRATEGY) \
{ \
DivideAndStore ## STRATEGY ## Comps(res, res, resA); \
@ -831,7 +834,8 @@ void NAME_SRCOVER_MASKFILL(TYPE) \
Postload ## STRATEGY ## From ## TYPE(pRas, DstPix, res); \
MultiplyAddAndStore ## STRATEGY ## Comps(res, \
dstF, res, src); \
if (!(TYPE ## IsPremultiplied) && resA && \
if (!(TYPE ## IsOpaque) && \
!(TYPE ## IsPremultiplied) && resA && \
resA < MaxValFor ## STRATEGY) \
{ \
DivideAndStore ## STRATEGY ## Comps(res, res, resA); \

View File

@ -36,6 +36,8 @@
typedef jubyte ByteGrayPixelType;
typedef jubyte ByteGrayDataType;
#define ByteGrayIsOpaque 1
#define ByteGrayPixelStride 1
#define ByteGrayBitsPerPixel 8

View File

@ -34,6 +34,8 @@
typedef jint FourByteAbgrPixelType;
typedef jubyte FourByteAbgrDataType;
#define FourByteAbgrIsOpaque 0
#define FourByteAbgrPixelStride 4
#define DeclareFourByteAbgrLoadVars(PREFIX)

View File

@ -34,6 +34,8 @@
typedef jint FourByteAbgrPrePixelType;
typedef jubyte FourByteAbgrPreDataType;
#define FourByteAbgrPreIsOpaque 0
#define FourByteAbgrPrePixelStride 4
#define DeclareFourByteAbgrPreLoadVars(PREFIX)

View File

@ -37,6 +37,8 @@
typedef jushort Index12GrayPixelType;
typedef jushort Index12GrayDataType;
#define Index12GrayIsOpaque 1
#define Index12GrayPixelStride 2
#define Index12GrayBitsPerPixel 12

View File

@ -37,6 +37,8 @@
typedef jubyte Index8GrayPixelType;
typedef jubyte Index8GrayDataType;
#define Index8GrayIsOpaque 1
#define Index8GrayPixelStride 1
#define Index8GrayBitsPerPixel 8

View File

@ -38,6 +38,8 @@
typedef jint IntArgbPixelType;
typedef jint IntArgbDataType;
#define IntArgbIsOpaque 0
#define IntArgbPixelStride 4
#define DeclareIntArgbLoadVars(PREFIX)

View File

@ -38,6 +38,8 @@
typedef jint IntArgbBmPixelType;
typedef jint IntArgbBmDataType;
#define IntArgbBmIsOpaque 0
#define IntArgbBmPixelStride 4
#define DeclareIntArgbBmLoadVars(PREFIX)

View File

@ -36,6 +36,8 @@
typedef jint IntArgbPrePixelType;
typedef jint IntArgbPreDataType;
#define IntArgbPreIsOpaque 0
#define IntArgbPrePixelStride 4
#define DeclareIntArgbPreLoadVars(PREFIX)

View File

@ -38,6 +38,8 @@
typedef jint IntBgrPixelType;
typedef jint IntBgrDataType;
#define IntBgrIsOpaque 1
#define IntBgrPixelStride 4
#define DeclareIntBgrLoadVars(PREFIX)

View File

@ -38,6 +38,8 @@
typedef jint IntRgbPixelType;
typedef jint IntRgbDataType;
#define IntRgbIsOpaque 1
#define IntRgbPixelStride 4
#define DeclareIntRgbLoadVars(PREFIX)

View File

@ -36,6 +36,8 @@
typedef jint IntRgbxPixelType;
typedef jint IntRgbxDataType;
#define IntRgbxIsOpaque 1
#define IntRgbxPixelStride 4
#define DeclareIntRgbxLoadVars(PREFIX)

View File

@ -1610,8 +1610,12 @@ void NAME_SOLID_DRAWGLYPHLIST(DST)(SurfaceDataRasInfo *pRasInfo, \
MUL8(SRC_PREFIX ## A, mixValSrc); \
MultMultAddAndStore4ByteArgbComps(dst, mixValDst, dst, \
mixValSrc, SRC_PREFIX); \
Store ## DST ## From4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \
dstA, dstR, dstG, dstB); \
if (!(DST ## IsOpaque) && \
!(DST ## IsPremultiplied) && dstA && dstA < 255) { \
DivideAndStore4ByteArgbComps(dst, dst, dstA); \
} \
Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
PIXEL_INDEX, dst); \
} else { \
Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
FG_PIXEL, PREFIX); \
@ -1793,8 +1797,12 @@ void NAME_SOLID_DRAWGLYPHLISTAA(DST)(SurfaceDataRasInfo *pRasInfo, \
dstR = gammaLut[dstR]; \
dstG = gammaLut[dstG]; \
dstB = gammaLut[dstB]; \
Store ## DST ## From4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \
dstA, dstR, dstG, dstB); \
if (!(DST ## IsOpaque) && \
!(DST ## IsPremultiplied) && dstA && dstA < 255) { \
DivideAndStore4ByteArgbComps(dst, dst, dstA); \
} \
Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
PIXEL_INDEX, dst); \
} else { \
Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
FG_PIXEL, PREFIX); \

View File

@ -34,6 +34,8 @@
typedef jint ThreeByteBgrPixelType;
typedef jubyte ThreeByteBgrDataType;
#define ThreeByteBgrIsOpaque 1
#define ThreeByteBgrPixelStride 3
#define DeclareThreeByteBgrLoadVars(PREFIX)

View File

@ -34,6 +34,8 @@
typedef jushort Ushort4444ArgbPixelType;
typedef jushort Ushort4444ArgbDataType;
#define Ushort4444ArgbIsOpaque 0
#define Ushort4444ArgbPixelStride 2
#define DeclareUshort4444ArgbLoadVars(PREFIX)

View File

@ -34,6 +34,8 @@
typedef jushort Ushort555RgbPixelType;
typedef jushort Ushort555RgbDataType;
#define Ushort555RgbIsOpaque 1
#define Ushort555RgbPixelStride 2
#define DeclareUshort555RgbLoadVars(PREFIX)

View File

@ -34,6 +34,8 @@
typedef jushort Ushort555RgbxPixelType;
typedef jushort Ushort555RgbxDataType;
#define Ushort555RgbxIsOpaque 1
#define Ushort555RgbxPixelStride 2
#define DeclareUshort555RgbxLoadVars(PREFIX)

View File

@ -34,6 +34,8 @@
typedef jushort Ushort565RgbPixelType;
typedef jushort Ushort565RgbDataType;
#define Ushort565RgbIsOpaque 1
#define Ushort565RgbPixelStride 2
#define DeclareUshort565RgbLoadVars(PREFIX)

View File

@ -36,6 +36,8 @@
typedef jushort UshortGrayPixelType;
typedef jushort UshortGrayDataType;
#define UshortGrayIsOpaque 1
#define UshortGrayPixelStride 2
#define UshortGrayBitsPerPixel 16

View File

@ -48,6 +48,8 @@ import sun.font.Font2D;
import sun.font.FontManager;
import sun.font.NativeFont;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.UnixSurfaceManagerFactory;
/**
* This is an implementation of a GraphicsEnvironment object for the
@ -177,6 +179,10 @@ public class X11GraphicsEnvironment
return null;
}
});
// Install the correct surface manager factory.
SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());
}
private static boolean glxAvailable;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,24 +23,23 @@
* have any questions.
*/
package sun.java2d;
import java.awt.GraphicsConfiguration;
import java.awt.image.BufferedImage;
import sun.awt.X11GraphicsConfig;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.SurfaceManager;
import sun.awt.image.VolatileSurfaceManager;
import sun.java2d.opengl.GLXGraphicsConfig;
import sun.java2d.opengl.GLXVolatileSurfaceManager;
import sun.java2d.x11.X11VolatileSurfaceManager;
/**
* This is a factory class with static methods for creating a
* platform-specific instance of a particular SurfaceManager. Each platform
* (Windows, Unix, etc.) has its own specialized SurfaceManagerFactory.
* The SurfaceManagerFactory that creates VolatileSurfaceManager
* implementations for the Unix volatile images.
*/
public class SurfaceManagerFactory {
public class UnixSurfaceManagerFactory extends SurfaceManagerFactory {
/**
* Creates a new instance of a VolatileSurfaceManager given any
* arbitrary SunVolatileImage. An optional context Object can be supplied
@ -51,9 +50,8 @@ public class SurfaceManagerFactory {
* specific VolatileSurfaceManager based on the GraphicsConfiguration
* under which the SunVolatileImage was created.
*/
public static VolatileSurfaceManager
createVolatileManager(SunVolatileImage vImg,
Object context)
public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
Object context)
{
GraphicsConfiguration gc = vImg.getGraphicsConfig();
if (gc instanceof GLXGraphicsConfig) {
@ -62,4 +60,5 @@ public class SurfaceManagerFactory {
return new X11VolatileSurfaceManager(vImg, context);
}
}
}

View File

@ -32,6 +32,7 @@ public class AttributeClass {
private int nameLen;
private Object myValue;
public static final int TAG_UNSUPPORTED_VALUE = 0x10;
public static final int TAG_INT = 0x21;
public static final int TAG_BOOL = 0x22;
public static final int TAG_ENUM = 0x23;

View File

@ -333,7 +333,7 @@ public class CUPSPrinter {
AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
new AttributeClass("requested-attributes",
AttributeClass.TAG_KEYWORD,
"printer-name")
"printer-uri-supported")
};
if (IPPPrintService.writeIPPRequest(os,
@ -354,7 +354,7 @@ public class CUPSPrinter {
ArrayList printerNames = new ArrayList();
for (int i=0; i< responseMap.length; i++) {
AttributeClass attribClass = (AttributeClass)
responseMap[i].get("printer-name");
responseMap[i].get("printer-uri-supported");
if (attribClass != null) {
String nameStr = attribClass.getStringValue();

View File

@ -335,6 +335,38 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
}
IPPPrintService(String name, String uriStr, boolean isCups) {
if ((name == null) || (uriStr == null)){
throw new IllegalArgumentException("null uri or printer name");
}
printer = name;
supportedDocFlavors = null;
supportedCats = null;
mediaSizeNames = null;
customMediaSizeNames = null;
mediaTrays = null;
cps = null;
init = false;
defaultMediaIndex = -1;
try {
myURL =
new URL(uriStr.replaceFirst("ipp", "http"));
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" IPPPrintService, myURL="+
myURL+" Exception= "+
e);
}
isCupsPrinter = isCups;
try {
myURI = new URI(uriStr);
debug_println(debugPrefix+"IPPPrintService myURI : "+myURI);
} catch (java.net.URISyntaxException e) {
throw new IllegalArgumentException("invalid uri");
}
}
/*
* Initialize mediaSizeNames, mediaTrays and other attributes.
@ -375,7 +407,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
return;
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" error creating CUPSPrinter");
" error creating CUPSPrinter e="+e);
}
}
@ -621,17 +653,8 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
}
}
} else if (category == OrientationRequested.class) {
if (flavor == null ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
// Orientation is emulated in Pageable/Printable flavors
// so we report the 3 orientations as supported.
OrientationRequested []orientSup = new OrientationRequested[3];
orientSup[0] = OrientationRequested.PORTRAIT;
orientSup[1] = OrientationRequested.LANDSCAPE;
orientSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
return orientSup;
}
boolean revPort = false;
OrientationRequested[] orientSup = null;
AttributeClass attribClass = (getAttMap != null) ?
(AttributeClass)getAttMap.get("orientation-requested-supported")
@ -639,7 +662,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
if (attribClass != null) {
int[] orientArray = attribClass.getArrayOfIntValues();
if ((orientArray != null) && (orientArray.length > 0)) {
OrientationRequested[] orientSup =
orientSup =
new OrientationRequested[orientArray.length];
for (int i=0; i<orientArray.length; i++) {
switch (orientArray[i]) {
@ -657,12 +680,33 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
case 6:
orientSup[i] =
OrientationRequested.REVERSE_PORTRAIT;
revPort = true;
break;
}
}
return orientSup;
}
}
if (flavor == null ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
if (revPort && flavor == null) {
OrientationRequested []orSup = new OrientationRequested[4];
orSup[0] = OrientationRequested.PORTRAIT;
orSup[1] = OrientationRequested.LANDSCAPE;
orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
orSup[3] = OrientationRequested.REVERSE_PORTRAIT;
return orSup;
} else {
OrientationRequested []orSup = new OrientationRequested[3];
orSup[0] = OrientationRequested.PORTRAIT;
orSup[1] = OrientationRequested.LANDSCAPE;
orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
return orSup;
}
} else {
return orientSup;
}
} else if (category == PageRanges.class) {
if (flavor == null ||
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
@ -795,6 +839,18 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
docList.addAll(Arrays.asList(flavors));
if (isCupsPrinter) {
/*
Always add Pageable and Printable for CUPS
since it uses Filters to convert from Postscript
to device printer language.
*/
docList.add(
DocFlavor.SERVICE_FORMATTED.PAGEABLE);
docList.add(
DocFlavor.SERVICE_FORMATTED.PRINTABLE);
}
if (mimeType.equals("text/plain") &&
addHostEncoding) {
docList.add(Arrays.asList(textPlainHost));
@ -808,11 +864,6 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
} else if (mimeType.equals("image/jpeg")) {
jpgImagesAdded = true;
} else if (mimeType.indexOf("postscript") != -1) {
docList.add(
DocFlavor.SERVICE_FORMATTED.PAGEABLE);
docList.add(
DocFlavor.SERVICE_FORMATTED.PRINTABLE);
psSupported = true;
}
break;
@ -829,7 +880,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
}
// check if we need to add image DocFlavors
if (psSupported) {
if (psSupported || isCupsPrinter) {
if (!jpgImagesAdded) {
docList.addAll(Arrays.asList(imageJPG));
}
@ -991,6 +1042,14 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
getSupportedAttributeCategories();
}
// It is safe to assume that Orientation is always supported
// and even if CUPS or an IPP device reports it as not,
// our renderer can do portrait, landscape and
// reverse landscape.
if (category == OrientationRequested.class) {
return true;
}
for (int i=0;i<supportedCats.length;i++) {
if (category == supportedCats[i]) {
return true;
@ -1520,10 +1579,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
if (isCupsPrinter) {
try {
urlConnection = getIPPConnection(
new URL("http://"+
CUPSPrinter.getServer()+":"+
CUPSPrinter.getPort()+
"/printers/"+printer+".ppd"));
new URL(myURL+".ppd"));
InputStream is = urlConnection.getInputStream();
if (is != null) {
@ -1539,6 +1595,11 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
}
}
} catch (java.io.IOException e) {
debug_println(" isPostscript, e= "+e);
/* if PPD is not found, this may be a raw printer
and in this case it is assumed that it is a
Postscript printer */
// do nothing
}
}
}
@ -1602,7 +1663,13 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
public static boolean writeIPPRequest(OutputStream os,
String operCode,
AttributeClass[] attCl) {
OutputStreamWriter osw = new OutputStreamWriter(os);
OutputStreamWriter osw;
try {
osw = new OutputStreamWriter(os, "UTF-8");
} catch (java.io.UnsupportedEncodingException exc) {
debug_println("UTF-8 not supported? Exception: "+exc);
return false;
}
char[] opCode = new char[2];
opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16);
opCode[1] = (char)Byte.parseByte(operCode.substring(2,4), 16);
@ -1690,7 +1757,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
// read value tag
response[0] = ois.readByte();
while (response[0] >= AttributeClass.TAG_INT &&
while (response[0] >= AttributeClass.TAG_UNSUPPORTED_VALUE &&
response[0] <= AttributeClass.TAG_MEMBER_ATTRNAME) {
// read name length
len = ois.readShort();
@ -1710,12 +1777,16 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
respList.add(responseMap);
responseMap = new HashMap();
}
AttributeClass ac =
new AttributeClass(attribStr,
valTagByte,
outArray);
responseMap.put(ac.getName(), ac);
// exclude those that are unknown
if (valTagByte >= AttributeClass.TAG_INT) {
AttributeClass ac =
new AttributeClass(attribStr,
valTagByte,
outArray);
responseMap.put(ac.getName(), ac);
}
outObj = new ByteArrayOutputStream();
counter = 0; //reset counter

View File

@ -196,11 +196,20 @@ public class UnixPrintServiceLookup extends PrintServiceLookup
// refreshes "printServices"
public synchronized void refreshServices() {
String[] printers; /* excludes the default printer */
/* excludes the default printer */
String[] printers = null; // array of printer names
String[] printerURIs = null; //array of printer URIs
getDefaultPrintService();
if (CUPSPrinter.isCupsRunning()) {
printers = CUPSPrinter.getAllPrinters();
printerURIs = CUPSPrinter.getAllPrinters();
if ((printerURIs != null) && (printerURIs.length > 0)) {
printers = new String[printerURIs.length];
for (int i=0; i<printerURIs.length; i++) {
int lastIndex = printerURIs[i].lastIndexOf("/");
printers[i] = printerURIs[i].substring(lastIndex+1);
}
}
} else {
if (isSysV()) {
printers = getAllPrinterNamesSysV();
@ -236,12 +245,9 @@ public class UnixPrintServiceLookup extends PrintServiceLookup
if (CUPSPrinter.isCupsRunning()) {
try {
URL serviceURL =
new URL("http://"+
CUPSPrinter.getServer()+":"+
CUPSPrinter.getPort()+"/"+printers[p]);
printerList.add(new IPPPrintService( printers[p],
serviceURL));
printerList.add(new IPPPrintService(printers[p],
printerURIs[p],
true));
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" getAllPrinters Exception "+
@ -265,12 +271,10 @@ public class UnixPrintServiceLookup extends PrintServiceLookup
if (j == printServices.length) { // not found?
if (CUPSPrinter.isCupsRunning()) {
try {
URL serviceURL =
new URL("http://"+
CUPSPrinter.getServer()+":"+
CUPSPrinter.getPort()+"/"+printers[p]);
printerList.add(new IPPPrintService( printers[p],
serviceURL));
printerList.add(new IPPPrintService(
printers[p],
printerURIs[p],
true));
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" getAllPrinters Exception "+

View File

@ -358,15 +358,28 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
* See 6343810.
*/
while (1) {
fd_set wr, ex;
#ifndef USE_SELECT
{
fprintf(stdout,"\nNATIVE: fd = %d] ", fd);
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT;
FD_ZERO(&wr);
FD_SET(fd, &wr);
FD_ZERO(&ex);
FD_SET(fd, &ex);
connect_rv = NET_Poll(&pfd, 1, -1);
}
#else
{
fd_set wr, ex;
FD_ZERO(&wr);
FD_SET(fd, &wr);
FD_ZERO(&ex);
FD_SET(fd, &ex);
connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0);
}
#endif
errno = 0;
connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0);
if (connect_rv == JVM_IO_ERR) {
if (errno == EINTR) {
continue;

View File

@ -650,7 +650,7 @@ static void xinerama_init_linux()
if (XineramaQueryScreens != NULL) {
DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
if (xinInfo != NULL) {
if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
int32_t idx;
DTRACE_PRINTLN("Enabling Xinerama support");
usingXinerama = True;
@ -701,7 +701,8 @@ static void xinerama_init_solaris()
if (XineramaSolarisFunc != NULL) {
DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
&fbhints[0], &locNumScr) != 0)
&fbhints[0], &locNumScr) != 0 &&
locNumScr > XScreenCount(awt_display))
{
DTRACE_PRINTLN("Enabling Xinerama support");
usingXinerama = True;
@ -1626,6 +1627,8 @@ Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env,
#define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI
typedef Status
(*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);
typedef XRRScreenConfiguration*
(*XRRGetScreenInfoType)(Display *dpy, Drawable root);
typedef void
@ -1650,6 +1653,7 @@ typedef Status
short rate,
Time timestamp);
static XRRQueryVersionType awt_XRRQueryVersion;
static XRRGetScreenInfoType awt_XRRGetScreenInfo;
static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
static XRRConfigRatesType awt_XRRConfigRates;
@ -1672,6 +1676,8 @@ static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;
static jboolean
X11GD_InitXrandrFuncs(JNIEnv *env)
{
int rr_maj_ver = 0, rr_min_ver = 0;
void *pLibRandR = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_LOCAL);
if (pLibRandR == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR,
@ -1679,6 +1685,41 @@ X11GD_InitXrandrFuncs(JNIEnv *env)
return JNI_FALSE;
}
LOAD_XRANDR_FUNC(XRRQueryVersion);
if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {
J2dRlsTraceLn(J2D_TRACE_ERROR,
"X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");
dlclose(pLibRandR);
return JNI_FALSE;
}
if (usingXinerama) {
/*
* We can proceed as long as this is RANDR 1.2 or above.
* As of Xorg server 1.3 onwards the Xinerama backend may actually be
* a fake one provided by RANDR itself. See Java bug 6636469 for info.
*/
if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {
J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
"Xinerama is active and Xrandr version is %d.%d",
rr_maj_ver, rr_min_ver);
dlclose(pLibRandR);
return JNI_FALSE;
}
/*
* REMIND: Fullscreen mode doesn't work quite right with multi-monitor
* setups and RANDR 1.2. So for now we also require a single screen.
*/
if (awt_numScreens > 1 ) {
J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
"Multiple screens in use");
dlclose(pLibRandR);
return JNI_FALSE;
}
}
LOAD_XRANDR_FUNC(XRRGetScreenInfo);
LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);
LOAD_XRANDR_FUNC(XRRConfigRates);
@ -1814,15 +1855,6 @@ Java_sun_awt_X11GraphicsDevice_initXrandrExtension
int opcode = 0, firstEvent = 0, firstError = 0;
jboolean ret;
if (usingXinerama) {
/*
* REMIND: we'll just punt if Xinerama is enabled; we can remove this
* restriction in the future if we find Xinerama and XRandR playing
* well together...
*/
return JNI_FALSE;
}
AWT_LOCK();
ret = (jboolean)XQueryExtension(awt_display, "RANDR",
&opcode, &firstEvent, &firstError);

View File

@ -1936,6 +1936,7 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
for (j = 0; j < height; j++) {
mlib_u8 *src = (void*)pixels;
mlib_s32 *dst, *dst_end;
mlib_u8 *dst_start;
if ((mlib_s32)dstBase & 3) {
COPY_NA(dstBase, pbuff, width*sizeof(mlib_s32));
@ -1943,8 +1944,14 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
} else {
dst = (void*)dstBase;
}
dst_start = (void*)dst;
dst_end = dst + width;
/* Need to reset the GSR from the values set by the
* convert call near the end of this loop.
*/
vis_write_gsr(7 << 0);
if ((mlib_s32)dst & 7) {
pix = *src++;
dd = vis_fpadd16(MUL8_VIS(srcG_f, pix), d_half);
@ -1984,8 +1991,13 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
dst++;
}
ADD_SUFF(IntArgbPreToIntArgbConvert)(dst_start, dst_start,
width, 1,
pRasInfo, pRasInfo,
pPrim, pCompInfo);
if ((mlib_s32)dstBase & 3) {
COPY_NA(pbuff, dstBase, width*sizeof(mlib_s32));
COPY_NA(dst_start, dstBase, width*sizeof(mlib_s32));
}
PTR_ADD(dstBase, scan);

View File

@ -181,6 +181,7 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
d_half = vis_to_double_dup((1 << (16 + 6)) | (1 << 6));
srcG_f = vis_to_float(argbcolor);
ARGB2ABGR_FL(srcG_f);
for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) {
const jubyte *pixels;
@ -238,8 +239,33 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
mlib_u8 *src = (void*)pixels;
mlib_s32 *dst, *dst_end;
mlib_u8 *dst8;
mlib_u8* dst_start = dstBase;
ADD_SUFF(FourByteAbgrPreToIntArgbConvert)(dstBase, pbuff, width, 1,
/*
* Typically the inner loop here works on Argb input data, an
* Argb color, and produces ArgbPre output data. To use that
* standard approach we would need a FourByteAbgrPre to IntArgb
* converter for the front end and an IntArgbPre to FourByteAbgrPre
* converter for the back end. The converter exists for the
* front end, but it is a workaround implementation that uses a 2
* stage conversion and an intermediate buffer that is allocated
* on every call. The converter for the back end doesn't really
* exist, but we could reuse the IntArgb to FourByteAbgr converter
* to do the same work - at the cost of swapping the components as
* we copy the data back. All of this is more work than we really
* need so we use an alternate procedure:
* - Copy the data into an int-aligned temporary buffer (if needed)
* - Convert the data from FourByteAbgrPre to IntAbgr by using the
* IntArgbPre to IntArgb converter in the int-aligned buffer.
* - Swap the color data to Abgr so that the inner loop goes from
* IntAbgr data to IntAbgrPre data
* - Simply copy the IntAbgrPre data back into place.
*/
if (((mlib_s32)dstBase) & 3) {
COPY_NA(dstBase, pbuff, width*sizeof(mlib_s32));
dst_start = pbuff;
}
ADD_SUFF(IntArgbPreToIntArgbConvert)(dst_start, pbuff, width, 1,
pRasInfo, pRasInfo,
pPrim, pCompInfo);
@ -283,9 +309,7 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
dst++;
}
ADD_SUFF(IntArgbToFourByteAbgrPreConvert)(pbuff, dstBase, width, 1,
pRasInfo, pRasInfo,
pPrim, pCompInfo);
COPY_NA(pbuff, dstBase, width*sizeof(mlib_s32));
src = (void*)pixels;
dst8 = (void*)dstBase;

View File

@ -428,6 +428,11 @@ void ADD_SUFF(IntArgbDrawGlyphListAA)(GLYPH_LIST_PARAMS)
dst = (void*)dstBase;
dst_end = dst + width;
/* Clearing the Graphics Status Register is necessary otherwise
* left over scale settings affect the pack instructions.
*/
vis_write_gsr(0 << 3);
if ((mlib_s32)dst & 7) {
pix = *src++;
dd = vis_fpadd16(MUL8_VIS(srcG_f, pix), d_half);
@ -467,6 +472,9 @@ void ADD_SUFF(IntArgbDrawGlyphListAA)(GLYPH_LIST_PARAMS)
dst++;
}
ADD_SUFF(IntArgbPreToIntArgbConvert)(dstBase, dstBase, width, 1,
pRasInfo, pRasInfo,
pPrim, pCompInfo);
PTR_ADD(dstBase, scan);
pixels += rowBytes;
}

View File

@ -1193,10 +1193,6 @@ void ADD_SUFF(IntArgbPreDrawGlyphListAA)(SurfaceDataRasInfo * pRasInfo,
dst++;
}
ADD_SUFF(IntArgbToIntArgbPreConvert)(dstBase, dstBase, width, 1,
pRasInfo, pRasInfo,
pPrim, pCompInfo);
PTR_ADD(dstBase, scan);
pixels += rowBytes;
}

View File

@ -42,6 +42,8 @@ import sun.awt.windows.WPrinterJob;
import sun.awt.windows.WToolkit;
import sun.font.FontManager;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.WindowsSurfaceManagerFactory;
import sun.java2d.windows.WindowsFlags;
/**
@ -64,6 +66,9 @@ public class Win32GraphicsEnvironment
WindowsFlags.initFlags();
initDisplayWrapper();
eudcFontFileName = getEUDCFontFile();
// Install correct surface manager factory.
SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory());
}
/**
@ -260,6 +265,7 @@ public class Win32GraphicsEnvironment
try {
while (!found && parser.hasMoreTokens()) {
String newPath = parser.nextToken();
boolean ujr = newPath.equals(jreFontDirName);
File theFile = new File(newPath, fontFileName);
if (theFile.canRead()) {
found = true;
@ -267,11 +273,11 @@ public class Win32GraphicsEnvironment
if (defer) {
FontManager.registerDeferredFont(fontFileName, path,
nativeNames,
fontFormat, true,
fontFormat, ujr,
fontRank);
} else {
FontManager.registerFontFile(path, nativeNames,
fontFormat, true,
fontFormat, ujr,
fontRank);
}
break;
@ -296,7 +302,7 @@ public class Win32GraphicsEnvironment
}
public static void registerJREFontsForPrinting() {
String pathName = null;
final String pathName;
synchronized (Win32GraphicsEnvironment.class) {
GraphicsEnvironment.getLocalGraphicsEnvironment();
if (fontsForPrinting == null) {
@ -305,15 +311,21 @@ public class Win32GraphicsEnvironment
pathName = fontsForPrinting;
fontsForPrinting = null;
}
File f1 = new File(pathName);
String[] ls = f1.list(new TTFilter());
if (ls == null) {
return;
}
for (int i=0; i <ls.length; i++ ) {
File fontFile = new File(f1, ls[i]);
registerFontWithPlatform(fontFile.getAbsolutePath());
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
File f1 = new File(pathName);
String[] ls = f1.list(new TTFilter());
if (ls == null) {
return null;
}
for (int i=0; i <ls.length; i++ ) {
File fontFile = new File(f1, ls[i]);
registerFontWithPlatform(fontFile.getAbsolutePath());
}
return null;
}
});
}
protected static native void registerFontWithPlatform(String fontName);

View File

@ -943,8 +943,16 @@ class WPathGraphics extends PathGraphics {
double devResY = wPrinterJob.getYRes();
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
if (scaleX > devScaleX) scaleX = devScaleX;
if (scaleY > devScaleY) scaleY = devScaleY;
/* check if rotated or sheared */
int transformType = fullTransform.getType();
boolean clampScale = ((transformType &
(AffineTransform.TYPE_GENERAL_ROTATION |
AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0);
if (clampScale) {
if (scaleX > devScaleX) scaleX = devScaleX;
if (scaleY > devScaleY) scaleY = devScaleY;
}
/* We do not need to draw anything if either scaling
* factor is zero.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,11 +36,11 @@ import sun.java2d.windows.WindowsFlags;
import sun.java2d.windows.WinVolatileSurfaceManager;
/**
* This is a factory class with static methods for creating a
* platform-specific instance of a particular SurfaceManager. Each platform
* (Windows, Unix, etc.) has its own specialized SurfaceManagerFactory.
* The SurfaceManagerFactory that creates VolatileSurfaceManager
* implementations for the Windows volatile images.
*/
public class SurfaceManagerFactory {
public class WindowsSurfaceManagerFactory extends SurfaceManagerFactory {
/**
* Creates a new instance of a VolatileSurfaceManager given any
* arbitrary SunVolatileImage. An optional context Object can be supplied
@ -50,9 +50,8 @@ public class SurfaceManagerFactory {
* For Windows platforms, this method returns a Windows-specific
* VolatileSurfaceManager.
*/
public static VolatileSurfaceManager
createVolatileManager(SunVolatileImage vImg,
Object context)
public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
Object context)
{
GraphicsConfiguration gc = vImg.getGraphicsConfig();
if (gc instanceof WGLGraphicsConfig) {
@ -61,4 +60,5 @@ public class SurfaceManagerFactory {
return new WinVolatileSurfaceManager(vImg, context);
}
}
}

View File

@ -0,0 +1,481 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* The function here is used to get a GDI rasterized LCD glyph and place it
* into the JDK glyph cache. The benefit is rendering fidelity for the
* most common cases, with no impact on the 2D rendering pipelines.
*
* Requires that the font and graphics are unrotated, and the scale is
* a simple one, and the font is a TT font registered with windows.
* Those conditions are established by the calling code.
*
* This code
* - Receives the family name, style, and size of the font
* and creates a Font object.
* - Create a surface from which we can get a DC : must be 16 bit or more.
* Ideally we'd be able to specify the depth of this, but in practice we
* have to accept it will be the same as the default screen.
* - Selects the GDI font on to the device
* - Uses GetGlyphOutline to estimate the bounds.
* - Creates a DIB on to which to blit the image.
* - Creates a GlyphInfo structure and copies the GDI glyph and offsets
* into the glyph which is returned.
*/
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <windows.h>
#include <winuser.h>
#include <jni.h>
#include <jni_util.h>
#include <jlong_md.h>
#include <sun_font_FileFontStrike.h>
#include "fontscalerdefs.h"
/* Some of these are also defined in awtmsg.h but I don't want a dependency
* on that here. They are needed here - and in awtmsg.h - until we
* move up our build to define WIN32_WINNT >= 0x501 (ie XP), since MS
* headers will not define them otherwise.
*/
#ifndef SPI_GETFONTSMOOTHINGTYPE
#define SPI_GETFONTSMOOTHINGTYPE 0x200A
#endif //SPI_GETFONTSMOOTHINGTYPE
#ifndef SPI_GETFONTSMOOTHINGCONTRAST
#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
#endif //SPI_GETFONTSMOOTHINGCONTRAST
#ifndef SPI_GETFONTSMOOTHINGORIENTATION
#define SPI_GETFONTSMOOTHINGORIENTATION 0x2012
#endif //SPI_GETFONTSMOOTHINGORIENTATION
#ifndef FE_FONTSMOOTHINGORIENTATIONBGR
#define FE_FONTSMOOTHINGORIENTATIONBGR 0x0000
#endif //FE_FONTSMOOTHINGORIENTATIONBGR
#ifndef FE_FONTSMOOTHINGORIENTATIONRGB
#define FE_FONTSMOOTHINGORIENTATIONRGB 0x0001
#endif //FE_FONTSMOOTHINGORIENTATIONRGB
#define MIN_GAMMA 100
#define MAX_GAMMA 220
#define LCDLUTCOUNT (MAX_GAMMA-MIN_GAMMA+1)
static unsigned char* igLUTable[LCDLUTCOUNT];
static unsigned char* getIGTable(int gamma) {
int i, index;
double ig;
char *igTable;
if (gamma < MIN_GAMMA) {
gamma = MIN_GAMMA;
} else if (gamma > MAX_GAMMA) {
gamma = MAX_GAMMA;
}
index = gamma - MIN_GAMMA;
if (igLUTable[index] != NULL) {
return igLUTable[index];
}
igTable = (unsigned char*)malloc(256);
if (igTable == NULL) {
return NULL;
}
igTable[0] = 0;
igTable[255] = 255;
ig = ((double)gamma)/100.0;
for (i=1;i<255;i++) {
igTable[i] = (unsigned char)(pow(((double)i)/255.0, ig)*255);
}
igLUTable[index] = igTable;
return igTable;
}
JNIEXPORT jboolean JNICALL
Java_sun_font_FileFontStrike_initNative(JNIEnv *env, jclass unused) {
DWORD osVersion = GetVersion();
DWORD majorVersion = (DWORD)(LOBYTE(LOWORD(osVersion)));
DWORD minorVersion = (DWORD)(HIBYTE(LOWORD(osVersion)));
/* Need at least XP which is 5.1 */
if (majorVersion < 5 || (majorVersion == 5 && minorVersion < 1)) {
return JNI_FALSE;
}
memset(igLUTable, 0, LCDLUTCOUNT);
return JNI_TRUE;
}
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
#ifndef CLEARTYPE_NATURAL_QUALITY
#define CLEARTYPE_NATURAL_QUALITY 6
#endif
#define FREE_AND_RETURN \
if (hDesktopDC != 0 && hWnd != 0) { \
ReleaseDC(hWnd, hDesktopDC); \
}\
if (hMemoryDC != 0) { \
DeleteObject(hMemoryDC); \
} \
if (hBitmap != 0) { \
DeleteObject(hBitmap); \
} \
if (dibImage != NULL) { \
free(dibImage); \
} \
if (glyphInfo != NULL) { \
free(glyphInfo); \
} \
return (jlong)0;
/* end define */
JNIEXPORT jlong JNICALL
Java_sun_font_FileFontStrike__1getGlyphImageFromWindows
(JNIEnv *env, jobject unused,
jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm) {
GLYPHMETRICS glyphMetrics;
LOGFONTW lf;
BITMAPINFO bmi;
TEXTMETRIC textMetric;
RECT rect;
int bytesWidth, dibBytesWidth, extra, imageSize, dibImageSize;
unsigned char* dibImage = NULL, *rowPtr, *pixelPtr, *dibPixPtr, *dibRowPtr;
unsigned char r,g,b;
unsigned char* igTable;
GlyphInfo* glyphInfo = NULL;
int nameLen;
LPWSTR name;
HFONT oldFont, hFont;
MAT2 mat2;
unsigned short width;
unsigned short height;
short advanceX;
short advanceY;
int topLeftX;
int topLeftY;
int err;
int bmWidth, bmHeight;
int x, y;
HBITMAP hBitmap = NULL, hOrigBM;
int gamma, orient;
HWND hWnd = NULL;
HDC hDesktopDC = NULL;
HDC hMemoryDC = NULL;
hWnd = GetDesktopWindow();
hDesktopDC = GetWindowDC(hWnd);
if (hDesktopDC == NULL) {
return (jlong)0;
}
if (GetDeviceCaps(hDesktopDC, BITSPIXEL) < 15) {
FREE_AND_RETURN;
}
hMemoryDC = CreateCompatibleDC(hDesktopDC);
if (hMemoryDC == NULL || fontFamily == NULL) {
FREE_AND_RETURN;
}
err = SetMapMode(hMemoryDC, MM_TEXT);
if (err == 0) {
FREE_AND_RETURN;
}
memset(&lf, 0, sizeof(LOGFONTW));
lf.lfHeight = -size;
lf.lfWeight = (style & 1) ? FW_BOLD : FW_NORMAL;
lf.lfItalic = (style & 2) ? 0xff : 0;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfQuality = CLEARTYPE_QUALITY;
lf.lfOutPrecision = OUT_TT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfPitchAndFamily = DEFAULT_PITCH;
nameLen = (*env)->GetStringLength(env, fontFamily);
name = (LPWSTR)alloca((nameLen+1)*2);
if (name == NULL) {
FREE_AND_RETURN;
}
(*env)->GetStringRegion(env, fontFamily, 0, nameLen, name);
name[nameLen] = '\0';
if (nameLen < (sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0]))) {
wcscpy(lf.lfFaceName, name);
} else {
FREE_AND_RETURN;
}
hFont = CreateFontIndirectW(&lf);
if (hFont == NULL) {
FREE_AND_RETURN;
}
oldFont = SelectObject(hMemoryDC, hFont);
memset(&textMetric, 0, sizeof(TEXTMETRIC));
err = GetTextMetrics(hMemoryDC, &textMetric);
if (err == 0) {
FREE_AND_RETURN;
}
memset(&glyphMetrics, 0, sizeof(GLYPHMETRICS));
memset(&mat2, 0, sizeof(MAT2));
mat2.eM11.value = 1; mat2.eM22.value = 1;
err = GetGlyphOutline(hMemoryDC, glyphCode,
GGO_METRICS|GGO_GLYPH_INDEX,
&glyphMetrics,
0, NULL, &mat2);
if (err == GDI_ERROR) {
/* Probably no such glyph - ie the font wasn't the one we expected. */
FREE_AND_RETURN;
}
width = (unsigned short)glyphMetrics.gmBlackBoxX;
height = (unsigned short)glyphMetrics.gmBlackBoxY;
/* Don't handle "invisible" glyphs in this code */
if (width <= 0 || height == 0) {
FREE_AND_RETURN;
}
advanceX = glyphMetrics.gmCellIncX;
advanceY = glyphMetrics.gmCellIncY;
topLeftX = glyphMetrics.gmptGlyphOrigin.x;
topLeftY = glyphMetrics.gmptGlyphOrigin.y;
/* GetGlyphOutline pre-dates cleartype and I'm not sure that it will
* account for all pixels touched by the rendering. Need to widen,
* and also adjust by one the x position at which it is rendered.
* The extra pixels of width are used as follows :
* One extra pixel at the left and the right will be needed to absorb
* the pixels that will be touched by filtering by GDI to compensate
* for colour fringing.
* However there seem to be some cases where GDI renders two extra
* pixels to the right, so we add one additional pixel to the right,
* and in the code that copies this to the image cache we test for
* the (rare) cases when this is touched, and if its not reduce the
* stated image width for the blitting loops.
* For fractional metrics :
* One extra pixel at each end to account for sub-pixel positioning used
* when fractional metrics is on in LCD mode.
* The pixel at the left is needed so the blitting loop can index into
* that a byte at a time to more accurately position the glyph.
* The pixel at the right is needed so that when such indexing happens,
* the blitting still can use the same width.
* Consequently the width that is specified for the glyph is one less
* than that of the actual image.
* Note that in the FM case as a consequence we need to adjust the
* position at which GDI renders, and the declared width of the glyph
* See the if (fm) {} cases in the code.
* For the non-FM case, we not only save 3 bytes per row, but this
* prevents apparent glyph overlapping which affects the rendering
* performance of accelerated pipelines since it adds additional
* read-back requirements.
*/
width+=3;
if (fm) {
width+=1;
}
/* DIB scanline must end on a DWORD boundary. We specify 3 bytes per pixel,
* so must round up as needed to a multiple of 4 bytes.
*/
dibBytesWidth = bytesWidth = width*3;
extra = dibBytesWidth % 4;
if (extra != 0) {
dibBytesWidth += (4-extra);
}
/* The glyph cache image must be a multiple of 3 bytes wide. */
extra = bytesWidth % 3;
if (extra != 0) {
bytesWidth += (3-extra);
}
bmWidth = width;
bmHeight = height;
/* Must use desktop DC to create a bitmap of that depth */
hBitmap = CreateCompatibleBitmap(hDesktopDC, bmWidth, bmHeight);
if (hBitmap == NULL) {
FREE_AND_RETURN;
}
hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
/* Fill in black */
rect.left = 0;
rect.top = 0;
rect.right = bmWidth;
rect.bottom = bmHeight;
FillRect(hMemoryDC, (LPRECT)&rect, GetStockObject(BLACK_BRUSH));
/* Set text color to white, background to black. */
SetBkColor(hMemoryDC, RGB(0,0,0));
SetTextColor(hMemoryDC, RGB(255,255,255));
/* adjust rendering position */
x = -topLeftX+1;
if (fm) {
x += 1;
}
y = topLeftY - textMetric.tmAscent;
err = ExtTextOutW(hMemoryDC, x, y, ETO_GLYPH_INDEX|ETO_OPAQUE,
(LPRECT)&rect, (LPCWSTR)&glyphCode, 1, NULL);
if (err == 0) {
FREE_AND_RETURN;
}
/* Now get the image into a DIB.
* MS docs for GetDIBits says the compatible bitmap must not be
* selected into a DC, so restore the original first.
*/
SelectObject(hMemoryDC, hOrigBM);
SelectObject(hMemoryDC, oldFont);
DeleteObject(hFont);
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
dibImageSize = dibBytesWidth*height;
dibImage = malloc(dibImageSize);
if (dibImage == NULL) {
FREE_AND_RETURN;
}
memset(dibImage, 0, dibImageSize);
err = GetDIBits(hMemoryDC, hBitmap, 0, height, dibImage,
&bmi, DIB_RGB_COLORS);
if (err == 0) { /* GetDIBits failed. */
FREE_AND_RETURN;
}
err = SystemParametersInfo(SPI_GETFONTSMOOTHINGORIENTATION, 0, &orient, 0);
if (err == 0) {
FREE_AND_RETURN;
}
err = SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &gamma, 0);
if (err == 0) {
FREE_AND_RETURN;
}
igTable = getIGTable(gamma/10);
if (igTable == NULL) {
FREE_AND_RETURN;
}
/* Now copy glyph image into a GlyphInfo structure and return it.
* NB the xadvance calculated here may be overwritten by the caller.
* 1 is subtracted from the bitmap width to get the glyph width, since
* that extra "1" was added as padding, so the sub-pixel positioning of
* fractional metrics could index into it.
*/
imageSize = bytesWidth*height;
glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize);
if (malloc == NULL) {
FREE_AND_RETURN;
}
glyphInfo->cellInfo = NULL;
glyphInfo->rowBytes = bytesWidth;
glyphInfo->width = width;
if (fm) {
glyphInfo->width -= 1; // must subtract 1
}
glyphInfo->height = height;
glyphInfo->advanceX = advanceX;
glyphInfo->advanceY = advanceY;
glyphInfo->topLeftX = (float)(topLeftX-1);
if (fm) {
glyphInfo->topLeftX -= 1;
}
glyphInfo->topLeftY = (float)-topLeftY;
glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo);
memset(glyphInfo->image, 0, imageSize);
/* DIB 24bpp data is always stored in BGR order, but we usually
* need this in RGB, so we can't just memcpy and need to swap B and R.
* Also need to apply inverse gamma adjustment here.
* We re-use the variable "extra" to see if the last pixel is touched
* at all. If its not we can reduce the glyph image width. This comes
* into play in some cases where GDI touches more pixels than accounted
* for by increasing width by two pixels over the B&W image. Whilst
* the bytes are in the cache, it doesn't affect rendering performance
* of the hardware pipelines.
*/
extra = 0;
if (fm) {
extra = 1; // always need it.
}
dibRowPtr = dibImage;
rowPtr = glyphInfo->image;
for (y=0;y<height;y++) {
pixelPtr = rowPtr;
dibPixPtr = dibRowPtr;
for (x=0;x<width;x++) {
if (orient == FE_FONTSMOOTHINGORIENTATIONRGB) {
b = *dibPixPtr++;
g = *dibPixPtr++;
r = *dibPixPtr++;
} else {
r = *dibPixPtr++;
g = *dibPixPtr++;
b = *dibPixPtr++;
}
*pixelPtr++ = igTable[r];
*pixelPtr++ = igTable[g];
*pixelPtr++ = igTable[b];
if (!fm && (x==(width-1)) && (r|g|b)) {
extra = 1;
}
}
dibRowPtr += dibBytesWidth;
rowPtr += bytesWidth;
}
if (!extra) {
glyphInfo->width -= 1;
}
free(dibImage);
ReleaseDC(hWnd, hDesktopDC);
DeleteObject(hMemoryDC);
DeleteObject(hBitmap);
return ptr_to_jlong(glyphInfo);
}

View File

@ -3464,6 +3464,21 @@ UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
return java_awt_event_KeyEvent_VK_UNDEFINED;
}
BOOL AwtComponent::IsNavigationKey(UINT wkey) {
switch (wkey) {
case VK_END:
case VK_PRIOR: // PageUp
case VK_NEXT: // PageDown
case VK_HOME:
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
return TRUE;
}
return FALSE;
}
// determine if a key is a numpad key (distinguishes the numpad
// arrow keys from the non-numpad arrow keys, for example).
BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended)
@ -3563,7 +3578,10 @@ UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops)
// fix for 4623376,4737679,4501485,4740906,4708221 (4173679/4122715)
// Here we try to resolve a conflict with ::ToAsciiEx's translating
// ALT+number key combinations. kdm@sarc.spb.su
keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
// yan: Do it for navigation keys only, otherwise some AltGr deadkeys fail.
if( IsNavigationKey(wkey) ) {
keyboardState[VK_MENU] &= ~KEY_STATE_DOWN;
}
if (ctrlIsDown)
{

View File

@ -823,6 +823,7 @@ public:
private:
AwtComponent* SearchChild(UINT id);
void RemoveChild(UINT id) ;
static BOOL IsNavigationKey(UINT wkey);
ChildListItem* m_childList;

View File

@ -0,0 +1,106 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6679308
* @summary test drawing to Alpha surfaces
*/
import java.awt.*;
import java.awt.image.*;
public class AlphaSurfaceText {
int wid=400, hgt=200;
public AlphaSurfaceText(int biType, Color c) {
BufferedImage opaquebi0 =
new BufferedImage(wid, hgt, BufferedImage.TYPE_INT_RGB);
drawText(opaquebi0, c);
BufferedImage alphabi = new BufferedImage(wid, hgt, biType);
drawText(alphabi, c);
BufferedImage opaquebi1 =
new BufferedImage(wid, hgt, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = opaquebi1.createGraphics();
g2d.drawImage(alphabi, 0, 0, null);
compare(opaquebi0, opaquebi1, biType, c);
}
private void drawText(BufferedImage bi, Color c) {
Graphics2D g = bi.createGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(c);
g.setFont(new Font("sansserif", Font.PLAIN, 70));
g.drawString("Hello!", 20, 100);
g.setFont(new Font("sansserif", Font.PLAIN, 12));
g.drawString("Hello!", 20, 130);
g.setFont(new Font("sansserif", Font.PLAIN, 10));
g.drawString("Hello!", 20, 150);
}
// Need to allow for minimal rounding error, so allow each component
// to differ by 1.
void compare(BufferedImage bi0, BufferedImage bi1, int biType, Color c) {
for (int x=0; x<wid; x++) {
for (int y=0; y<hgt; y++) {
int rgb0 = bi0.getRGB(x, y);
int rgb1 = bi1.getRGB(x, y);
if (rgb0 == rgb1) continue;
int r0 = (rgb0 & 0xff0000) >> 16;
int r1 = (rgb1 & 0xff0000) >> 16;
int rdiff = r0-r1; if (rdiff<0) rdiff = -rdiff;
int g0 = (rgb0 & 0x00ff00) >> 8;
int g1 = (rgb1 & 0x00ff00) >> 8;
int gdiff = g0-g1; if (gdiff<0) gdiff = -gdiff;
int b0 = (rgb0 & 0x0000ff);
int b1 = (rgb1 & 0x0000ff);
int bdiff = b0-b1; if (bdiff<0) bdiff = -bdiff;
if (rdiff > 1 || gdiff > 1 || bdiff > 1) {
throw new RuntimeException(
"Images differ for type "+biType + " col="+c +
" at x=" + x + " y="+ y + " " +
Integer.toHexString(rgb0) + " vs " +
Integer.toHexString(rgb1));
}
}
}
}
public static void main(String[] args) {
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.white);
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.red);
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.blue);
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.white);
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.red);
new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.blue);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.white);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.red);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.blue);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.white);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.red);
new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.blue);
}
}

Some files were not shown because too many files have changed in this diff Show More