提交 3ed02fab 编写于 作者: L lana

Merge

......@@ -339,8 +339,7 @@ ifeq ($(PLATFORM), windows)
FONTCONFIGS_SRC = $(PLATFORM_SRC)/classes/sun/awt/windows
_FONTCONFIGS = \
fontconfig.properties \
fontconfig.98.properties
fontconfig.properties
FONTCONFIGS_SRC_PREFIX =
......
......@@ -304,12 +304,14 @@ SUNWprivate_1.1 {
Java_java_awt_FileDialog_initIDs;
Java_sun_awt_X11_XWindow_initIDs;
Java_sun_java2d_opengl_OGLContext_getOGLIdString;
Java_sun_java2d_opengl_OGLMaskFill_maskFill;
Java_sun_java2d_opengl_OGLRenderer_drawPoly;
Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer;
Java_sun_java2d_opengl_OGLSurfaceData_initTexture;
Java_sun_java2d_opengl_OGLSurfaceData_initFBObject;
Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer;
Java_sun_java2d_opengl_OGLSurfaceData_getTextureID;
Java_sun_java2d_opengl_OGLSurfaceData_getTextureTarget;
Java_sun_java2d_opengl_OGLTextRenderer_drawGlyphList;
Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo;
......
......@@ -153,7 +153,7 @@ public class GIFImageMetadata extends GIFMetadata {
node.setAttribute("imageWidth", Integer.toString(imageWidth));
node.setAttribute("imageHeight", Integer.toString(imageHeight));
node.setAttribute("interlaceFlag",
interlaceFlag ? "true" : "false");
interlaceFlag ? "TRUE" : "FALSE");
root.appendChild(node);
// Local color table
......@@ -185,9 +185,9 @@ public class GIFImageMetadata extends GIFMetadata {
node.setAttribute("disposalMethod",
disposalMethodNames[disposalMethod]);
node.setAttribute("userInputFlag",
userInputFlag ? "true" : "false");
userInputFlag ? "TRUE" : "FALSE");
node.setAttribute("transparentColorFlag",
transparentColorFlag ? "true" : "false");
transparentColorFlag ? "TRUE" : "FALSE");
node.setAttribute("delayTime",
Integer.toString(delayTime));
node.setAttribute("transparentColorIndex",
......
......@@ -55,6 +55,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.imageio.plugins.common.LZWCompressor;
import com.sun.imageio.plugins.common.PaletteBuilder;
import sun.awt.image.ByteComponentRaster;
public class GIFImageWriter extends ImageWriter {
private static final boolean DEBUG = false; // XXX false for release!
......@@ -905,10 +906,18 @@ public class GIFImageWriter extends ImageWriter {
LZWCompressor compressor =
new LZWCompressor(stream, initCodeSize, false);
/* At this moment we know that input image is indexed image.
* We can directly copy data iff:
* - no subsampling required (periodX = 1, periodY = 0)
* - we can access data directly (image is non-tiled,
* i.e. image data are in single block)
* - we can calculate offset in data buffer (next 3 lines)
*/
boolean isOptimizedCase =
periodX == 1 && periodY == 1 &&
sampleModel instanceof ComponentSampleModel &&
image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
sampleModel instanceof ComponentSampleModel &&
image.getTile(0, 0) instanceof ByteComponentRaster &&
image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte;
int numRowsWritten = 0;
......@@ -921,11 +930,14 @@ public class GIFImageWriter extends ImageWriter {
if (DEBUG) System.out.println("Writing interlaced");
if (isOptimizedCase) {
Raster tile = image.getTile(0, 0);
ByteComponentRaster tile =
(ByteComponentRaster)image.getTile(0, 0);
byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
ComponentSampleModel csm =
(ComponentSampleModel)tile.getSampleModel();
int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
// take into account the raster data offset
offset += tile.getDataOffset(0);
int lineStride = csm.getScanlineStride();
writeRowsOpt(data, offset, lineStride, compressor,
......
......@@ -158,13 +158,10 @@ abstract class GIFMetadata extends IIOMetadata {
}
}
String value = attr.getNodeValue();
// XXX Should be able to use equals() here instead of
// equalsIgnoreCase() but some boolean attributes are incorrectly
// set to "true" or "false" by the J2SE core metadata classes
// getAsTree() method (which are duplicated above). See bug 5082756.
if (value.equalsIgnoreCase("TRUE")) {
// Allow lower case booleans for backward compatibility, #5082756
if (value.equals("TRUE") || value.equals("true")) {
return true;
} else if (value.equalsIgnoreCase("FALSE")) {
} else if (value.equals("FALSE") || value.equals("false")) {
return false;
} else {
fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
......
......@@ -202,7 +202,7 @@ public class GIFStreamMetadata extends GIFMetadata {
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", "true");
node.setAttribute("value", "TRUE");
compression_node.appendChild(node);
// NumProgressiveScans not in stream
......
......@@ -1003,7 +1003,7 @@ class JFIFMarkerSegment extends MarkerSegment {
3,
new int [] {0, 1, 2},
null);
ColorModel cm = new ComponentColorModel(JPEG.sRGB,
ColorModel cm = new ComponentColorModel(JPEG.JCS.sRGB,
false,
false,
ColorModel.OPAQUE,
......
......@@ -208,15 +208,24 @@ public class JPEG {
public static final int [] bOffsRGB = { 2, 1, 0 };
protected static final ColorSpace sRGB =
ColorSpace.getInstance(ColorSpace.CS_sRGB);
protected static ColorSpace YCC = null; // Can't be final
static {
try {
YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
} catch (IllegalArgumentException e) {
// PYCC.pf may not always be installed
/* These are kept in the inner class to avoid static initialization
* of the CMM class until someone actually needs it.
* (e.g. do not init CMM on the request for jpeg mime types)
*/
public static class JCS {
public static final ColorSpace sRGB =
ColorSpace.getInstance(ColorSpace.CS_sRGB);
public static final ColorSpace YCC;
static {
ColorSpace cs = null;
try {
cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
} catch (IllegalArgumentException e) {
// PYCC.pf may not always be installed
} finally {
YCC = cs;
}
}
}
......
......@@ -228,31 +228,31 @@ public class JPEGImageReader extends ImageReader {
(BufferedImage.TYPE_BYTE_GRAY);
defaultTypes[JPEG.JCS_RGB] =
ImageTypeSpecifier.createInterleaved
(JPEG.sRGB,
(JPEG.JCS.sRGB,
JPEG.bOffsRGB,
DataBuffer.TYPE_BYTE,
false,
false);
defaultTypes[JPEG.JCS_RGBA] =
ImageTypeSpecifier.createPacked
(JPEG.sRGB,
(JPEG.JCS.sRGB,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff,
DataBuffer.TYPE_INT,
false);
if (JPEG.YCC != null) {
if (JPEG.JCS.YCC != null) {
defaultTypes[JPEG.JCS_YCC] =
ImageTypeSpecifier.createInterleaved
(JPEG.YCC,
(JPEG.JCS.YCC,
JPEG.bandOffsets[2],
DataBuffer.TYPE_BYTE,
false,
false);
defaultTypes[JPEG.JCS_YCCA] =
ImageTypeSpecifier.createInterleaved
(JPEG.YCC,
(JPEG.JCS.YCC,
JPEG.bandOffsets[3],
DataBuffer.TYPE_BYTE,
true,
......@@ -774,7 +774,7 @@ public class JPEGImageReader extends ImageReader {
case JPEG.JCS_RGB:
list.add(raw);
list.add(getImageType(JPEG.JCS_GRAYSCALE));
if (JPEG.YCC != null) {
if (JPEG.JCS.YCC != null) {
list.add(getImageType(JPEG.JCS_YCC));
}
break;
......@@ -811,7 +811,7 @@ public class JPEGImageReader extends ImageReader {
}
list.add(getImageType(JPEG.JCS_GRAYSCALE));
if (JPEG.YCC != null) { // Might be null if PYCC.pf not installed
if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed
list.add(getImageType(JPEG.JCS_YCC));
}
break;
......@@ -893,7 +893,7 @@ public class JPEGImageReader extends ImageReader {
(!cs.isCS_sRGB()) &&
(cm.getNumComponents() == numComponents)) {
// Target isn't sRGB, so convert from sRGB to the target
convert = new ColorConvertOp(JPEG.sRGB, cs, null);
convert = new ColorConvertOp(JPEG.JCS.sRGB, cs, null);
} else if (csType != ColorSpace.TYPE_RGB) {
throw new IIOException("Incompatible color conversion");
}
......@@ -906,18 +906,18 @@ public class JPEGImageReader extends ImageReader {
}
break;
case JPEG.JCS_YCC:
if (JPEG.YCC == null) { // We can't do YCC at all
if (JPEG.JCS.YCC == null) { // We can't do YCC at all
throw new IIOException("Incompatible color conversion");
}
if ((cs != JPEG.YCC) &&
if ((cs != JPEG.JCS.YCC) &&
(cm.getNumComponents() == numComponents)) {
convert = new ColorConvertOp(JPEG.YCC, cs, null);
convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null);
}
break;
case JPEG.JCS_YCCA:
// No conversions available; image must be YCCA
if ((JPEG.YCC == null) || // We can't do YCC at all
(cs != JPEG.YCC) ||
if ((JPEG.JCS.YCC == null) || // We can't do YCC at all
(cs != JPEG.JCS.YCC) ||
(cm.getNumComponents() != numComponents)) {
throw new IIOException("Incompatible color conversion");
}
......
......@@ -39,8 +39,6 @@ public class JPEGImageReaderSpi extends ImageReaderSpi {
private static String [] writerSpiNames =
{"com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi"};
private boolean registered = false;
public JPEGImageReaderSpi() {
super(JPEG.vendor,
JPEG.version,
......@@ -61,26 +59,6 @@ public class JPEGImageReaderSpi extends ImageReaderSpi {
);
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
try {
java.security.AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("jpeg"));
// Stuff it all into one lib for first pass
//java.security.AccessController.doPrivileged(
//new sun.security.action.LoadLibraryAction("imageioIJG"));
} catch (Throwable e) { // Fail on any Throwable
// if it can't be loaded, deregister and return
registry.deregisterServiceProvider(this);
return;
}
registered = true;
}
public String getDescription(Locale locale) {
return "Standard JPEG Image Reader";
}
......
......@@ -812,13 +812,13 @@ public class JPEGImageWriter extends ImageWriter {
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.YCC) {
if (cs == JPEG.JCS.YCC) {
if (!alpha) {
if (jfif != null) {
convertTosRGB = true;
convertOp =
new ColorConvertOp(cs,
JPEG.sRGB,
JPEG.JCS.sRGB,
null);
outCsType = JPEG.JCS_YCbCr;
} else if (adobe != null) {
......@@ -1494,7 +1494,7 @@ public class JPEGImageWriter extends ImageWriter {
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.YCC) {
if (cs == JPEG.JCS.YCC) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
......@@ -1533,7 +1533,7 @@ public class JPEGImageWriter extends ImageWriter {
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.YCC) {
if (cs == JPEG.JCS.YCC) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
......@@ -1579,7 +1579,7 @@ public class JPEGImageWriter extends ImageWriter {
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.YCC) {
if (cs == JPEG.JCS.YCC) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
......
......@@ -42,8 +42,6 @@ public class JPEGImageWriterSpi extends ImageWriterSpi {
private static String [] readerSpiNames =
{"com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi"};
private boolean registered = false;
public JPEGImageWriterSpi() {
super(JPEG.vendor,
JPEG.version,
......@@ -68,23 +66,6 @@ public class JPEGImageWriterSpi extends ImageWriterSpi {
return "Standard JPEG Image Writer";
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
try {
java.security.AccessController.doPrivileged(
new sun.security.action.LoadLibraryAction("jpeg"));
} catch (Throwable e) { // Fail on any Throwable
// if it can't be loaded, deregister and return
registry.deregisterServiceProvider(this);
return;
}
registered = true;
}
public boolean isFormatLossless() {
return false;
}
......
......@@ -490,7 +490,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable {
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.YCC) {
if (cs == JPEG.JCS.YCC) {
wantJFIF = false;
componentIDs[0] = (byte) 'Y';
componentIDs[1] = (byte) 'C';
......@@ -955,7 +955,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable {
// Lossless - false
IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
lossless.setAttribute("value", "false");
lossless.setAttribute("value", "FALSE");
compression.appendChild(lossless);
// NumProgressiveScans - count sos segments
......
......@@ -37,6 +37,7 @@ import java.awt.image.WritableRaster;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.InputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
......@@ -59,7 +60,7 @@ import com.sun.imageio.plugins.common.SubImageInputStream;
import java.io.ByteArrayOutputStream;
import sun.awt.image.ByteInterleavedRaster;
class PNGImageDataEnumeration implements Enumeration {
class PNGImageDataEnumeration implements Enumeration<InputStream> {
boolean firstTime = true;
ImageInputStream stream;
......@@ -72,7 +73,7 @@ class PNGImageDataEnumeration implements Enumeration {
int type = stream.readInt(); // skip chunk type
}
public Object nextElement() {
public InputStream nextElement() {
try {
firstTime = false;
ImageInputStream iis = new SubImageInputStream(stream, length);
......@@ -207,25 +208,17 @@ public class PNGImageReader extends ImageReader {
resetStreamSettings();
}
private String readNullTerminatedString(String charset) throws IOException {
private String readNullTerminatedString(String charset, int maxLen) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b;
while ((b = stream.read()) != 0) {
int count = 0;
while ((maxLen > count++) && ((b = stream.read()) != 0)) {
if (b == -1) throw new EOFException();
baos.write(b);
}
return new String(baos.toByteArray(), charset);
}
private String readNullTerminatedString() throws IOException {
StringBuilder b = new StringBuilder();
int c;
while ((c = stream.read()) != 0) {
b.append((char)c);
}
return b.toString();
}
private void readHeader() throws IIOException {
if (gotHeader) {
return;
......@@ -434,7 +427,7 @@ public class PNGImageReader extends ImageReader {
}
private void parse_iCCP_chunk(int chunkLength) throws IOException {
String keyword = readNullTerminatedString();
String keyword = readNullTerminatedString("ISO-8859-1", 80);
metadata.iCCP_profileName = keyword;
metadata.iCCP_compressionMethod = stream.readUnsignedByte();
......@@ -450,7 +443,7 @@ public class PNGImageReader extends ImageReader {
private void parse_iTXt_chunk(int chunkLength) throws IOException {
long chunkStart = stream.getStreamPosition();
String keyword = readNullTerminatedString();
String keyword = readNullTerminatedString("ISO-8859-1", 80);
metadata.iTXt_keyword.add(keyword);
int compressionFlag = stream.readUnsignedByte();
......@@ -459,15 +452,17 @@ public class PNGImageReader extends ImageReader {
int compressionMethod = stream.readUnsignedByte();
metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
String languageTag = readNullTerminatedString("UTF8");
String languageTag = readNullTerminatedString("UTF8", 80);
metadata.iTXt_languageTag.add(languageTag);
long pos = stream.getStreamPosition();
int maxLen = (int)(chunkStart + chunkLength - pos);
String translatedKeyword =
readNullTerminatedString("UTF8");
readNullTerminatedString("UTF8", maxLen);
metadata.iTXt_translatedKeyword.add(translatedKeyword);
String text;
long pos = stream.getStreamPosition();
pos = stream.getStreamPosition();
byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
stream.readFully(b);
......@@ -511,7 +506,7 @@ public class PNGImageReader extends ImageReader {
private void parse_sPLT_chunk(int chunkLength)
throws IOException, IIOException {
metadata.sPLT_paletteName = readNullTerminatedString();
metadata.sPLT_paletteName = readNullTerminatedString("ISO-8859-1", 80);
chunkLength -= metadata.sPLT_paletteName.length() + 1;
int sampleDepth = stream.readUnsignedByte();
......@@ -554,12 +549,12 @@ public class PNGImageReader extends ImageReader {
}
private void parse_tEXt_chunk(int chunkLength) throws IOException {
String keyword = readNullTerminatedString();
String keyword = readNullTerminatedString("ISO-8859-1", 80);
metadata.tEXt_keyword.add(keyword);
byte[] b = new byte[chunkLength - keyword.length() - 1];
stream.readFully(b);
metadata.tEXt_text.add(new String(b));
metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
}
private void parse_tIME_chunk() throws IOException {
......@@ -640,7 +635,7 @@ public class PNGImageReader extends ImageReader {
}
private void parse_zTXt_chunk(int chunkLength) throws IOException {
String keyword = readNullTerminatedString();
String keyword = readNullTerminatedString("ISO-8859-1", 80);
metadata.zTXt_keyword.add(keyword);
int method = stream.readUnsignedByte();
......@@ -648,7 +643,7 @@ public class PNGImageReader extends ImageReader {
byte[] b = new byte[chunkLength - keyword.length() - 2];
stream.readFully(b);
metadata.zTXt_text.add(new String(inflate(b)));
metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
}
private void readMetadata() throws IIOException {
......@@ -1263,7 +1258,7 @@ public class PNGImageReader extends ImageReader {
try {
stream.seek(imageStartPosition);
Enumeration e = new PNGImageDataEnumeration(stream);
Enumeration<InputStream> e = new PNGImageDataEnumeration(stream);
InputStream is = new SequenceInputStream(e);
/* InflaterInputStream uses an Inflater instance which consumes
......
......@@ -674,13 +674,8 @@ public class PNGImageWriter extends ImageWriter {
private byte[] deflate(byte[] b) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeflaterOutputStream dos = new DeflaterOutputStream(baos);
int len = b.length;
for (int i = 0; i < len; i++) {
dos.write((int)(0xff & b[i]));
}
dos.write(b);
dos.close();
return baos.toByteArray();
}
......@@ -736,7 +731,7 @@ public class PNGImageWriter extends ImageWriter {
cs.writeByte(compressionMethod);
String text = (String)textIter.next();
cs.write(deflate(text.getBytes()));
cs.write(deflate(text.getBytes("ISO-8859-1")));
cs.finish();
}
}
......
......@@ -211,8 +211,8 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
public int sRGB_renderingIntent;
// tEXt chunk
public ArrayList tEXt_keyword = new ArrayList(); // 1-79 char Strings
public ArrayList tEXt_text = new ArrayList(); // Strings
public ArrayList<String> tEXt_keyword = new ArrayList<String>(); // 1-79 characters
public ArrayList<String> tEXt_text = new ArrayList<String>();
// tIME chunk
public boolean tIME_present;
......@@ -235,13 +235,13 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
public int tRNS_blue;
// zTXt chunk
public ArrayList zTXt_keyword = new ArrayList(); // Strings
public ArrayList zTXt_compressionMethod = new ArrayList(); // Integers
public ArrayList zTXt_text = new ArrayList(); // Strings
public ArrayList<String> zTXt_keyword = new ArrayList<String>();
public ArrayList<Integer> zTXt_compressionMethod = new ArrayList<Integer>();
public ArrayList<String> zTXt_text = new ArrayList<String>();
// Unknown chunks
public ArrayList unknownChunkType = new ArrayList(); // Strings
public ArrayList unknownChunkData = new ArrayList(); // byte arrays
public ArrayList<String> unknownChunkType = new ArrayList<String>();
public ArrayList<byte[]> unknownChunkData = new ArrayList<byte[]>();
public PNGMetadata() {
super(true,
......@@ -426,21 +426,14 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
return false;
}
private ArrayList cloneBytesArrayList(ArrayList in) {
private ArrayList<byte[]> cloneBytesArrayList(ArrayList<byte[]> in) {
if (in == null) {
return null;
} else {
ArrayList list = new ArrayList(in.size());
Iterator iter = in.iterator();
while (iter.hasNext()) {
Object o = iter.next();
if (o == null) {
list.add(null);
} else {
list.add(((byte[])o).clone());
}
ArrayList<byte[]> list = new ArrayList<byte[]>(in.size());
for (byte[] b: in) {
list.add((b == null) ? null : (byte[])b.clone());
}
return list;
}
}
......@@ -600,7 +593,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
iTXt_node.setAttribute("keyword", iTXt_keyword.get(i));
iTXt_node.setAttribute("compressionFlag",
iTXt_compressionFlag.get(i) ? "1" : "0");
iTXt_compressionFlag.get(i) ? "TRUE" : "FALSE");
iTXt_node.setAttribute("compressionMethod",
iTXt_compressionMethod.get(i).toString());
iTXt_node.setAttribute("languageTag",
......@@ -832,7 +825,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
}
node = new IIOMetadataNode("BlackIsZero");
node.setAttribute("value", "true");
node.setAttribute("value", "TRUE");
chroma_node.appendChild(node);
if (PLTE_present) {
......@@ -894,7 +887,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", "true");
node.setAttribute("value", "TRUE");
compression_node.appendChild(node);
node = new IIOMetadataNode("NumProgressiveScans");
......@@ -1040,7 +1033,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
node.setAttribute("language",
iTXt_languageTag.get(i));
if (iTXt_compressionFlag.get(i)) {
node.setAttribute("compression", "deflate");
node.setAttribute("compression", "zip");
} else {
node.setAttribute("compression", "none");
}
......@@ -1052,7 +1045,7 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
node = new IIOMetadataNode("TextEntry");
node.setAttribute("keyword", (String)zTXt_keyword.get(i));
node.setAttribute("value", (String)zTXt_text.get(i));
node.setAttribute("compression", "deflate");
node.setAttribute("compression", "zip");
text_node.appendChild(node);
}
......@@ -1162,12 +1155,13 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
}
}
String value = attr.getNodeValue();
if (value.equals("true")) {
// Allow lower case booleans for backward compatibility, #5082756
if (value.equals("TRUE") || value.equals("true")) {
return true;
} else if (value.equals("false")) {
} else if (value.equals("FALSE") || value.equals("false")) {
return false;
} else {
fatal(node, "Attribute " + name + " must be 'true' or 'false'!");
fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
return false;
}
}
......@@ -1421,26 +1415,30 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
}
String keyword = getAttribute(iTXt_node, "keyword");
iTXt_keyword.add(keyword);
if (isValidKeyword(keyword)) {
iTXt_keyword.add(keyword);
boolean compressionFlag =
getBooleanAttribute(iTXt_node, "compressionFlag");
iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
boolean compressionFlag =
getBooleanAttribute(iTXt_node, "compressionFlag");
iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag));
String compressionMethod =
getAttribute(iTXt_node, "compressionMethod");
iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
String compressionMethod =
getAttribute(iTXt_node, "compressionMethod");
iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
String languageTag =
getAttribute(iTXt_node, "languageTag");
iTXt_languageTag.add(languageTag);
String languageTag =
getAttribute(iTXt_node, "languageTag");
iTXt_languageTag.add(languageTag);
String translatedKeyword =
getAttribute(iTXt_node, "translatedKeyword");
iTXt_translatedKeyword.add(translatedKeyword);
String translatedKeyword =
getAttribute(iTXt_node, "translatedKeyword");
iTXt_translatedKeyword.add(translatedKeyword);
String text = getAttribute(iTXt_node, "text");
iTXt_text.add(text);
String text = getAttribute(iTXt_node, "text");
iTXt_text.add(text);
}
// silently skip invalid text entry
iTXt_node = iTXt_node.getNextSibling();
}
......@@ -1692,11 +1690,45 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
}
}
private boolean isISOLatin(String s) {
/*
* Accrding to PNG spec, keywords are restricted to 1 to 79 bytes
* in length. Keywords shall contain only printable Latin-1 characters
* and spaces; To reduce the chances for human misreading of a keyword,
* leading spaces, trailing spaces, and consecutive spaces are not
* permitted in keywords.
*
* See: http://www.w3.org/TR/PNG/#11keywords
*/
private boolean isValidKeyword(String s) {
int len = s.length();
if (len < 1 || len >= 80) {
return false;
}
if (s.startsWith(" ") || s.endsWith(" ") || s.contains(" ")) {
return false;
}
return isISOLatin(s, false);
}
/*
* According to PNG spec, keyword shall contain only printable
* Latin-1 [ISO-8859-1] characters and spaces; that is, only
* character codes 32-126 and 161-255 decimal are allowed.
* For Latin-1 value fields the 0x10 (linefeed) control
* character is aloowed too.
*
* See: http://www.w3.org/TR/PNG/#11keywords
*/
private boolean isISOLatin(String s, boolean isLineFeedAllowed) {
int len = s.length();
for (int i = 0; i < len; i++) {
if (s.charAt(i) > 255) {
return false;
char c = s.charAt(i);
if (c < 32 || c > 255 || (c > 126 && c < 161)) {
// not printable. Check whether this is an allowed
// control char
if (!isLineFeedAllowed || c != 0x10) {
return false;
}
}
}
return true;
......@@ -1929,19 +1961,22 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("TextEntry")) {
String keyword = getAttribute(child, "keyword");
String keyword =
getAttribute(child, "keyword", "", false);
String value = getAttribute(child, "value");
String encoding = getAttribute(child, "encoding");
String language = getAttribute(child, "language");
String language =
getAttribute(child, "language", "", false);
String compression =
getAttribute(child, "compression");
getAttribute(child, "compression", "none", false);
if (isISOLatin(value)) {
if (!isValidKeyword(keyword)) {
// Just ignore this node, PNG requires keywords
} else if (isISOLatin(value, true)) {
if (compression.equals("zip")) {
// Use a zTXt node
zTXt_keyword.add(keyword);
zTXt_text.add(value);
zTXt_compressionMethod.add(new Integer(0));
zTXt_compressionMethod.add(Integer.valueOf(0));
} else {
// Use a tEXt node
tEXt_keyword.add(keyword);
......@@ -1998,14 +2033,14 @@ public class PNGMetadata extends IIOMetadata implements Cloneable {
sBIT_present = false;
sPLT_present = false;
sRGB_present = false;
tEXt_keyword = new ArrayList();
tEXt_text = new ArrayList();
tEXt_keyword = new ArrayList<String>();
tEXt_text = new ArrayList<String>();
tIME_present = false;
tRNS_present = false;
zTXt_keyword = new ArrayList();
zTXt_compressionMethod = new ArrayList();
zTXt_text = new ArrayList();
unknownChunkType = new ArrayList();
unknownChunkData = new ArrayList();
zTXt_keyword = new ArrayList<String>();
zTXt_compressionMethod = new ArrayList<Integer>();
zTXt_text = new ArrayList<String>();
unknownChunkType = new ArrayList<String>();
unknownChunkData = new ArrayList<byte[]>();
}
}
......@@ -94,6 +94,10 @@ public class StreamCloser {
tgn != null;
tg = tgn, tgn = tg.getParent());
streamCloser = new Thread(tg, streamCloserRunnable);
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
streamCloser.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(streamCloser);
return null;
}
......
......@@ -356,6 +356,9 @@ public abstract class GraphicsEnvironment {
* @since 1.5
*/
public void preferLocaleFonts() {
if (!(this instanceof SunGraphicsEnvironment)) {
return;
}
sun.font.FontManager.preferLocaleFonts();
}
......@@ -376,6 +379,9 @@ public abstract class GraphicsEnvironment {
* @since 1.5
*/
public void preferProportionalFonts() {
if (!(this instanceof SunGraphicsEnvironment)) {
return;
}
sun.font.FontManager.preferProportionalFonts();
}
......
......@@ -737,7 +737,7 @@ public class ICC_Profile implements Serializable {
ICC_Profile(ProfileDeferralInfo pdi) {
this.deferralInfo = pdi;
this.profileActivator = new ProfileActivator() {
public void activate() {
public void activate() throws ProfileDataException {
activateDeferredProfile();
}
};
......@@ -830,20 +830,16 @@ public class ICC_Profile implements Serializable {
case ColorSpace.CS_sRGB:
synchronized(ICC_Profile.class) {
if (sRGBprofile == null) {
try {
/*
* Deferral is only used for standard profiles.
* Enabling the appropriate access privileges is handled
* at a lower level.
*/
sRGBprofile = getDeferredInstance(
new ProfileDeferralInfo("sRGB.pf",
ColorSpace.TYPE_RGB,
3, CLASS_DISPLAY));
} catch (IOException e) {
throw new IllegalArgumentException(
"Can't load standard profile: sRGB.pf");
}
/*
* Deferral is only used for standard profiles.
* Enabling the appropriate access privileges is handled
* at a lower level.
*/
ProfileDeferralInfo pInfo =
new ProfileDeferralInfo("sRGB.pf",
ColorSpace.TYPE_RGB, 3,
CLASS_DISPLAY);
sRGBprofile = getDeferredInstance(pInfo);
}
thisProfile = sRGBprofile;
}
......@@ -853,7 +849,11 @@ public class ICC_Profile implements Serializable {
case ColorSpace.CS_CIEXYZ:
synchronized(ICC_Profile.class) {
if (XYZprofile == null) {
XYZprofile = getStandardProfile("CIEXYZ.pf");
ProfileDeferralInfo pInfo =
new ProfileDeferralInfo("CIEXYZ.pf",
ColorSpace.TYPE_XYZ, 3,
CLASS_DISPLAY);
XYZprofile = getDeferredInstance(pInfo);
}
thisProfile = XYZprofile;
}
......@@ -863,7 +863,11 @@ public class ICC_Profile implements Serializable {
case ColorSpace.CS_PYCC:
synchronized(ICC_Profile.class) {
if (PYCCprofile == null) {
PYCCprofile = getStandardProfile("PYCC.pf");
ProfileDeferralInfo pInfo =
new ProfileDeferralInfo("PYCC.pf",
ColorSpace.TYPE_3CLR, 3,
CLASS_DISPLAY);
PYCCprofile = getDeferredInstance(pInfo);
}
thisProfile = PYCCprofile;
}
......@@ -873,7 +877,11 @@ public class ICC_Profile implements Serializable {
case ColorSpace.CS_GRAY:
synchronized(ICC_Profile.class) {
if (GRAYprofile == null) {
GRAYprofile = getStandardProfile("GRAY.pf");
ProfileDeferralInfo pInfo =
new ProfileDeferralInfo("GRAY.pf",
ColorSpace.TYPE_GRAY, 1,
CLASS_DISPLAY);
GRAYprofile = getDeferredInstance(pInfo);
}
thisProfile = GRAYprofile;
}
......@@ -883,7 +891,11 @@ public class ICC_Profile implements Serializable {
case ColorSpace.CS_LINEAR_RGB:
synchronized(ICC_Profile.class) {
if (LINEAR_RGBprofile == null) {
LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf");
ProfileDeferralInfo pInfo =
new ProfileDeferralInfo("LINEAR_RGB.pf",
ColorSpace.TYPE_RGB, 3,
CLASS_DISPLAY);
LINEAR_RGBprofile = getDeferredInstance(pInfo);
}
thisProfile = LINEAR_RGBprofile;
}
......@@ -1047,9 +1059,7 @@ public class ICC_Profile implements Serializable {
* code will take care of access privileges.
* @see activateDeferredProfile()
*/
static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi)
throws IOException {
static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
if (!ProfileDeferralMgr.deferring) {
return getStandardProfile(pdi.filename);
}
......@@ -1063,33 +1073,37 @@ public class ICC_Profile implements Serializable {
}
void activateDeferredProfile() {
byte profileData[];
FileInputStream fis;
String fileName = deferralInfo.filename;
void activateDeferredProfile() throws ProfileDataException {
byte profileData[];
FileInputStream fis;
String fileName = deferralInfo.filename;
profileActivator = null;
deferralInfo = null;
if ((fis = openProfile(fileName)) == null) {
throw new IllegalArgumentException("Cannot open file " + fileName);
throw new ProfileDataException("Cannot open file " + fileName);
}
try {
profileData = getProfileDataFromStream(fis);
fis.close(); /* close the file */
}
catch (IOException e) {
throw new IllegalArgumentException("Invalid ICC Profile Data" +
fileName);
ProfileDataException pde = new
ProfileDataException("Invalid ICC Profile Data" + fileName);
pde.initCause(e);
throw pde;
}
if (profileData == null) {
throw new IllegalArgumentException("Invalid ICC Profile Data" +
throw new ProfileDataException("Invalid ICC Profile Data" +
fileName);
}
try {
ID = CMSManager.getModule().loadProfile(profileData);
} catch (CMMException c) {
throw new IllegalArgumentException("Invalid ICC Profile Data" +
fileName);
ProfileDataException pde = new
ProfileDataException("Invalid ICC Profile Data" + fileName);
pde.initCause(c);
throw pde;
}
}
......
......@@ -215,6 +215,14 @@ public class LogManager {
// This private class is used as a shutdown hook.
// It does a "reset" to close all open handlers.
private class Cleaner extends Thread {
private Cleaner() {
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
this.setContextClassLoader(null);
}
public void run() {
// This is to ensure the LogManager.<clinit> is completed
// before synchronized block. Otherwise deadlocks are possible.
......
......@@ -67,126 +67,13 @@ public class ImageTypeSpecifier {
* <code>BufferedImage</code> types.
*/
private static ImageTypeSpecifier[] BISpecifier;
private static ColorSpace sRGB;
// Initialize the standard specifiers
static {
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
BISpecifier =
new ImageTypeSpecifier[BufferedImage.TYPE_BYTE_INDEXED + 1];
BISpecifier[BufferedImage.TYPE_CUSTOM] = null;
BISpecifier[BufferedImage.TYPE_INT_RGB] =
createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0x0,
DataBuffer.TYPE_INT,
false);
BISpecifier[BufferedImage.TYPE_INT_ARGB] =
createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
false);
BISpecifier[BufferedImage.TYPE_INT_ARGB_PRE] =
createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
true);
BISpecifier[BufferedImage.TYPE_INT_BGR] =
createPacked(sRGB,
0x000000ff,
0x0000ff00,
0x00ff0000,
0x0,
DataBuffer.TYPE_INT,
false);
int[] bOffsRGB = { 2, 1, 0 };
BISpecifier[BufferedImage.TYPE_3BYTE_BGR] =
createInterleaved(sRGB,
bOffsRGB,
DataBuffer.TYPE_BYTE,
false,
false);
int[] bOffsABGR = { 3, 2, 1, 0 };
BISpecifier[BufferedImage.TYPE_4BYTE_ABGR] =
createInterleaved(sRGB,
bOffsABGR,
DataBuffer.TYPE_BYTE,
true,
false);
BISpecifier[BufferedImage.TYPE_4BYTE_ABGR_PRE] =
createInterleaved(sRGB,
bOffsABGR,
DataBuffer.TYPE_BYTE,
true,
true);
BISpecifier[BufferedImage.TYPE_USHORT_565_RGB] =
createPacked(sRGB,
0xF800,
0x07E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
BISpecifier[BufferedImage.TYPE_USHORT_555_RGB] =
createPacked(sRGB,
0x7C00,
0x03E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
BISpecifier[BufferedImage.TYPE_BYTE_GRAY] =
createGrayscale(8,
DataBuffer.TYPE_BYTE,
false);
BISpecifier[BufferedImage.TYPE_USHORT_GRAY] =
createGrayscale(16,
DataBuffer.TYPE_USHORT,
false);
BISpecifier[BufferedImage.TYPE_BYTE_BINARY] =
createGrayscale(1,
DataBuffer.TYPE_BYTE,
false);
BufferedImage bi =
new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
IndexColorModel icm = (IndexColorModel)bi.getColorModel();
int mapSize = icm.getMapSize();
byte[] redLUT = new byte[mapSize];
byte[] greenLUT = new byte[mapSize];
byte[] blueLUT = new byte[mapSize];
byte[] alphaLUT = new byte[mapSize];
icm.getReds(redLUT);
icm.getGreens(greenLUT);
icm.getBlues(blueLUT);
icm.getAlphas(alphaLUT);
BISpecifier[BufferedImage.TYPE_BYTE_INDEXED] =
createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
8,
DataBuffer.TYPE_BYTE);
}
/**
......@@ -1011,7 +898,7 @@ public class ImageTypeSpecifier {
ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
if (bufferedImageType >= BufferedImage.TYPE_INT_RGB &&
bufferedImageType <= BufferedImage.TYPE_BYTE_INDEXED) {
return BISpecifier[bufferedImageType];
return getSpecifier(bufferedImageType);
} else if (bufferedImageType == BufferedImage.TYPE_CUSTOM) {
throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
} else {
......@@ -1041,7 +928,7 @@ public class ImageTypeSpecifier {
if (image instanceof BufferedImage) {
int bufferedImageType = ((BufferedImage)image).getType();
if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
return BISpecifier[bufferedImageType];
return getSpecifier(bufferedImageType);
}
}
......@@ -1225,4 +1112,130 @@ public class ImageTypeSpecifier {
public int hashCode() {
return (9 * colorModel.hashCode()) + (14 * sampleModel.hashCode());
}
private static ImageTypeSpecifier getSpecifier(int type) {
if (BISpecifier[type] == null) {
BISpecifier[type] = createSpecifier(type);
}
return BISpecifier[type];
}
private static ImageTypeSpecifier createSpecifier(int type) {
switch(type) {
case BufferedImage.TYPE_INT_RGB:
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0x0,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_INT_ARGB:
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_INT_ARGB_PRE:
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
DataBuffer.TYPE_INT,
true);
case BufferedImage.TYPE_INT_BGR:
return createPacked(sRGB,
0x000000ff,
0x0000ff00,
0x00ff0000,
0x0,
DataBuffer.TYPE_INT,
false);
case BufferedImage.TYPE_3BYTE_BGR:
return createInterleaved(sRGB,
new int[] { 2, 1, 0 },
DataBuffer.TYPE_BYTE,
false,
false);
case BufferedImage.TYPE_4BYTE_ABGR:
return createInterleaved(sRGB,
new int[] { 3, 2, 1, 0 },
DataBuffer.TYPE_BYTE,
true,
false);
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
return createInterleaved(sRGB,
new int[] { 3, 2, 1, 0 },
DataBuffer.TYPE_BYTE,
true,
true);
case BufferedImage.TYPE_USHORT_565_RGB:
return createPacked(sRGB,
0xF800,
0x07E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_USHORT_555_RGB:
return createPacked(sRGB,
0x7C00,
0x03E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_BYTE_GRAY:
return createGrayscale(8,
DataBuffer.TYPE_BYTE,
false);
case BufferedImage.TYPE_USHORT_GRAY:
return createGrayscale(16,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_BYTE_BINARY:
return createGrayscale(1,
DataBuffer.TYPE_BYTE,
false);
case BufferedImage.TYPE_BYTE_INDEXED:
{
BufferedImage bi =
new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
IndexColorModel icm = (IndexColorModel)bi.getColorModel();
int mapSize = icm.getMapSize();
byte[] redLUT = new byte[mapSize];
byte[] greenLUT = new byte[mapSize];
byte[] blueLUT = new byte[mapSize];
byte[] alphaLUT = new byte[mapSize];
icm.getReds(redLUT);
icm.getGreens(greenLUT);
icm.getBlues(blueLUT);
icm.getAlphas(alphaLUT);
return createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
8,
DataBuffer.TYPE_BYTE);
}
default:
throw new IllegalArgumentException("Invalid BufferedImage type!");
}
}
}
......@@ -242,8 +242,12 @@ public interface IIOMetadataFormat {
/**
* A constant returned by <code>getAttributeDataType</code>
* indicating that the value of an attribute is one of 'true' or
* 'false'.
* indicating that the value of an attribute is one of the boolean
* values 'true' or 'false'.
* Attribute values of type DATATYPE_BOOLEAN should be marked as
* enumerations, and the permitted values should be the string
* literal values "TRUE" or "FALSE", although a plugin may also
* recognise lower or mixed case equivalents.
*/
int DATATYPE_BOOLEAN = 1;
......
......@@ -98,7 +98,7 @@ public abstract class FontConfiguration {
if (!inited) {
this.preferLocaleFonts = false;
this.preferPropFonts = false;
fontConfig = this; /* static initialization */
setFontConfiguration();
readFontConfigFile(fontConfigFile);
initFontConfig();
inited = true;
......@@ -1244,6 +1244,10 @@ public abstract class FontConfiguration {
return fontConfig;
}
protected void setFontConfiguration() {
fontConfig = this; /* static initialization */
}
//////////////////////////////////////////////////////////////////////
// FontConfig data tables and the index constants in binary file //
//////////////////////////////////////////////////////////////////////
......
......@@ -26,6 +26,7 @@
package sun.font;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
......@@ -842,8 +843,36 @@ public class FileFontStrike extends PhysicalStrike {
return fileFont.getGlyphOutlineBounds(pScalerContext, glyphCode);
}
private
WeakReference<ConcurrentHashMap<Integer,GeneralPath>> outlineMapRef;
GeneralPath getGlyphOutline(int glyphCode, float x, float y) {
return fileFont.getGlyphOutline(pScalerContext, glyphCode, x, y);
GeneralPath gp = null;
ConcurrentHashMap<Integer, GeneralPath> outlineMap = null;
if (outlineMapRef != null) {
outlineMap = outlineMapRef.get();
if (outlineMap != null) {
gp = (GeneralPath)outlineMap.get(glyphCode);
}
}
if (gp == null) {
gp = fileFont.getGlyphOutline(pScalerContext, glyphCode, 0, 0);
if (outlineMap == null) {
outlineMap = new ConcurrentHashMap<Integer, GeneralPath>();
outlineMapRef =
new WeakReference
<ConcurrentHashMap<Integer,GeneralPath>>(outlineMap);
}
outlineMap.put(glyphCode, gp);
}
gp = (GeneralPath)gp.clone(); // mutable!
if (x != 0f || y != 0f) {
gp.transform(AffineTransform.getTranslateInstance(x, y));
}
return gp;
}
GeneralPath getGlyphVectorOutline(int[] glyphs, float x, float y) {
......
......@@ -1601,18 +1601,27 @@ public final class FontManager {
/* Path may be absolute or a base file name relative to one of
* the platform font directories
*/
private static String getPathName(String s) {
private static String getPathName(final String s) {
File f = new File(s);
if (f.isAbsolute()) {
return s;
} else if (pathDirs.length==1) {
return pathDirs[0] + File.separator + s;
} else {
for (int p=0; p<pathDirs.length; p++) {
f = new File(pathDirs[p] + File.separator + s);
if (f.exists()) {
return f.getAbsolutePath();
}
String path = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<String>() {
public String run() {
for (int p=0; p<pathDirs.length; p++) {
File f = new File(pathDirs[p] +File.separator+ s);
if (f.exists()) {
return f.getAbsolutePath();
}
}
return null;
}
});
if (path != null) {
return path;
}
}
return s; // shouldn't happen, but harmless
......
......@@ -338,6 +338,8 @@ public final class GlyphLayout {
cache = new ConcurrentHashMap<SDKey, SDCache>(10);
cacheRef = new
SoftReference<ConcurrentHashMap<SDKey, SDCache>>(cache);
} else if (cache.size() >= 512) {
cache.clear();
}
cache.put(key, res);
}
......
......@@ -232,6 +232,16 @@ public final class StrikeCache {
if (disposer.pScalerContext != 0L) {
freeLongMemory(new long[0], disposer.pScalerContext);
}
} else if (disposer.pScalerContext != 0L) {
/* Rarely a strike may have been created that never cached
* any glyphs. In this case we still want to free the scaler
* context.
*/
if (FontManager.longAddresses) {
freeLongMemory(new long[0], disposer.pScalerContext);
} else {
freeIntMemory(new int[0], disposer.pScalerContext);
}
}
}
......
......@@ -25,6 +25,7 @@
package sun.java2d.cmm;
import java.awt.color.ProfileDataException;
/**
* An interface to allow the ProfileDeferralMgr to activate a
......@@ -35,6 +36,6 @@ public interface ProfileActivator {
/**
* Activate a previously deferred ICC_Profile object.
*/
public void activate();
public void activate() throws ProfileDataException;
}
......@@ -25,6 +25,7 @@
package sun.java2d.cmm;
import java.awt.color.ProfileDataException;
import java.util.Vector;
......@@ -39,7 +40,7 @@ import java.util.Vector;
public class ProfileDeferralMgr {
public static boolean deferring = true;
private static Vector aVector;
private static Vector<ProfileActivator> aVector;
/**
* Records a ProfileActivator object whose activate method will
......@@ -51,7 +52,7 @@ public class ProfileDeferralMgr {
return;
}
if (aVector == null) {
aVector = new Vector(3, 3);
aVector = new Vector<ProfileActivator>(3, 3);
}
aVector.addElement(pa);
return;
......@@ -89,8 +90,26 @@ public class ProfileDeferralMgr {
return;
}
n = aVector.size();
for (i = 0; i < n; i++) {
((ProfileActivator) aVector.get(i)).activate();
for (ProfileActivator pa : aVector) {
try {
pa.activate();
} catch (ProfileDataException e) {
/*
* Ignore profile activation error for now:
* such exception is pssible due to absence
* or corruption of standard color profile.
* As for now we expect all profiles should
* be shiped with jre and presence of this
* exception is indication of some configuration
* problem in jre installation.
*
* NB: we still are greedy loading deferred profiles
* and load them all if any of them is needed.
* Therefore broken profile (if any) might be never used.
* If there will be attempt to use broken profile then
* it will result in CMMException.
*/
}
}
aVector.removeAllElements();
aVector = null;
......
......@@ -120,7 +120,7 @@ public class Dasher extends LineSink {
// Normalize so 0 <= phase < dash[0]
int idx = 0;
dashOn = false;
dashOn = true;
int d;
while (phase >= (d = dash[idx])) {
phase -= d;
......
......@@ -245,6 +245,7 @@ public class PiscesRenderingEngine extends RenderingEngine {
FloatToS15_16(coords[1]));
break;
case PathIterator.SEG_CLOSE:
lsink.lineJoin();
lsink.close();
break;
default:
......
......@@ -2149,55 +2149,51 @@ 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)) {
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 (or == null) {
or = OrientationRequested.PORTRAIT;
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)) {
or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory);
// need to validate if default is not supported
if ((or != null) &&
!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) {
or = null;
Object 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];
}
}
asCurrent.add(or);
}
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);
if (or == null) {
or = OrientationRequested.PORTRAIT;
}
} else {
rbPortrait.setEnabled(pSupported);
rbLandscape.setEnabled(lSupported);
rbRevPortrait.setEnabled(rpSupported);
rbRevLandscape.setEnabled(rlSupported);
asCurrent.add(or);
}
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);
}
}
}
......
......@@ -169,6 +169,7 @@ initCubemap(int* cmap,
int cubesize = cube_dim * cube_dim * cube_dim;
unsigned char *useFlags;
unsigned char *newILut = (unsigned char*)malloc(cubesize);
int cmap_mid = (cmap_len >> 1) + (cmap_len & 0x1);
if (newILut) {
useFlags = (unsigned char *)calloc(cubesize, 1);
......@@ -188,7 +189,7 @@ initCubemap(int* cmap,
currentState.iLUT = newILut;
currentState.rgb = (unsigned short *)
malloc(256 * sizeof(unsigned short));
malloc(cmap_len * sizeof(unsigned short));
if (currentState.rgb == NULL) {
free(newILut);
free(useFlags);
......@@ -199,7 +200,7 @@ initCubemap(int* cmap,
}
currentState.indices = (unsigned char *)
malloc(256 * sizeof(unsigned char));
malloc(cmap_len * sizeof(unsigned char));
if (currentState.indices == NULL) {
free(currentState.rgb);
free(newILut);
......@@ -210,18 +211,18 @@ initCubemap(int* cmap,
return NULL;
}
for (i = 0; i < 128; i++) {
for (i = 0; i < cmap_mid; i++) {
unsigned short rgb;
int pixel = cmap[i];
rgb = (pixel & 0x00f80000) >> 9;
rgb |= (pixel & 0x0000f800) >> 6;
rgb |= (pixel & 0xf8) >> 3;
INSERTNEW(currentState, rgb, i);
pixel = cmap[255-i];
pixel = cmap[cmap_len - i - 1];
rgb = (pixel & 0x00f80000) >> 9;
rgb |= (pixel & 0x0000f800) >> 6;
rgb |= (pixel & 0xf8) >> 3;
INSERTNEW(currentState, rgb, 255-i);
INSERTNEW(currentState, rgb, cmap_len - i - 1);
}
if (!recurseLevel(&currentState)) {
......
......@@ -396,7 +396,7 @@ static imageIODataPtr initImageioData (JNIEnv *env,
data->jpegObj = cinfo;
cinfo->client_data = data;
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("new structures: data is %p, cinfo is %p\n", data, cinfo);
#endif
......@@ -673,7 +673,7 @@ static int setQTables(JNIEnv *env,
j_decompress_ptr decomp;
qlen = (*env)->GetArrayLength(env, qtables);
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
#endif
for (i = 0; i < qlen; i++) {
......@@ -876,7 +876,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo)
return FALSE;
}
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("Filling input buffer, remaining skip is %ld, ",
sb->remaining_skip);
printf("Buffer length is %d\n", sb->bufferLength);
......@@ -906,7 +906,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo)
cinfo->err->error_exit((j_common_ptr) cinfo);
}
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("Buffer filled. ret = %d\n", ret);
#endif
/*
......@@ -917,7 +917,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo)
*/
if (ret <= 0) {
jobject reader = data->imageIOobj;
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("YO! Early EOI! ret = %d\n", ret);
#endif
RELEASE_ARRAYS(env, data, src->next_input_byte);
......@@ -1216,21 +1216,24 @@ read_icc_profile (JNIEnv *env, j_decompress_ptr cinfo)
{
jpeg_saved_marker_ptr marker;
int num_markers = 0;
int num_found_markers = 0;
int seq_no;
JOCTET *icc_data;
JOCTET *dst_ptr;
unsigned int total_length;
#define MAX_SEQ_NO 255 // sufficient since marker numbers are bytes
char marker_present[MAX_SEQ_NO+1]; // 1 if marker found
unsigned int data_length[MAX_SEQ_NO+1]; // size of profile data in marker
unsigned int data_offset[MAX_SEQ_NO+1]; // offset for data in marker
jpeg_saved_marker_ptr icc_markers[MAX_SEQ_NO + 1];
int first; // index of the first marker in the icc_markers array
int last; // index of the last marker in the icc_markers array
jbyteArray data = NULL;
/* This first pass over the saved markers discovers whether there are
* any ICC markers and verifies the consistency of the marker numbering.
*/
for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
marker_present[seq_no] = 0;
for (seq_no = 0; seq_no <= MAX_SEQ_NO; seq_no++)
icc_markers[seq_no] = NULL;
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
if (marker_is_icc(marker)) {
......@@ -1242,37 +1245,58 @@ read_icc_profile (JNIEnv *env, j_decompress_ptr cinfo)
return NULL;
}
seq_no = GETJOCTET(marker->data[12]);
if (seq_no <= 0 || seq_no > num_markers) {
/* Some third-party tools produce images with profile chunk
* numeration started from zero. It is inconsistent with ICC
* spec, but seems to be recognized by majority of image
* processing tools, so we should be more tolerant to this
* departure from the spec.
*/
if (seq_no < 0 || seq_no > num_markers) {
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid icc profile: bad sequence number");
return NULL;
}
if (marker_present[seq_no]) {
if (icc_markers[seq_no] != NULL) {
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid icc profile: duplicate sequence numbers");
return NULL;
}
marker_present[seq_no] = 1;
data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
icc_markers[seq_no] = marker;
num_found_markers ++;
}
}
if (num_markers == 0)
return NULL; // There is no profile
/* Check for missing markers, count total space needed,
* compute offset of each marker's part of the data.
*/
if (num_markers != num_found_markers) {
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid icc profile: invalid number of icc markers");
return NULL;
}
first = icc_markers[0] ? 0 : 1;
last = num_found_markers + first;
/* Check for missing markers, count total space needed.
*/
total_length = 0;
for (seq_no = 1; seq_no <= num_markers; seq_no++) {
if (marker_present[seq_no] == 0) {
for (seq_no = first; seq_no < last; seq_no++) {
unsigned int length;
if (icc_markers[seq_no] == NULL) {
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid icc profile: missing sequence number");
return NULL;
}
data_offset[seq_no] = total_length;
total_length += data_length[seq_no];
/* check the data length correctness */
length = icc_markers[seq_no]->data_length;
if (ICC_OVERHEAD_LEN > length || length > MAX_BYTES_IN_MARKER) {
JNU_ThrowByName(env, "javax/imageio/IIOException",
"Invalid icc profile: invalid data length");
return NULL;
}
total_length += (length - ICC_OVERHEAD_LEN);
}
if (total_length <= 0) {
......@@ -1301,19 +1325,14 @@ read_icc_profile (JNIEnv *env, j_decompress_ptr cinfo)
}
/* and fill it in */
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
if (marker_is_icc(marker)) {
JOCTET FAR *src_ptr;
JOCTET *dst_ptr;
unsigned int length;
seq_no = GETJOCTET(marker->data[12]);
dst_ptr = icc_data + data_offset[seq_no];
src_ptr = marker->data + ICC_OVERHEAD_LEN;
length = data_length[seq_no];
while (length--) {
*dst_ptr++ = *src_ptr++;
}
}
dst_ptr = icc_data;
for (seq_no = first; seq_no < last; seq_no++) {
JOCTET FAR *src_ptr = icc_markers[seq_no]->data + ICC_OVERHEAD_LEN;
unsigned int length =
icc_markers[seq_no]->data_length - ICC_OVERHEAD_LEN;
memcpy(dst_ptr, src_ptr, length);
dst_ptr += length;
}
/* finally, unpin the array */
......@@ -1530,6 +1549,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
j_decompress_ptr cinfo;
struct jpeg_source_mgr *src;
sun_jpeg_error_ptr jerr;
jbyteArray profileData = NULL;
if (data == NULL) {
JNU_ThrowByName(env,
......@@ -1557,7 +1577,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
return retval;
}
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("In readImageHeader, data is %p cinfo is %p\n", data, cinfo);
printf("clearFirst is %d\n", clearFirst);
#endif
......@@ -1584,7 +1604,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
if (ret == JPEG_HEADER_TABLES_ONLY) {
retval = JNI_TRUE;
imageio_term_source(cinfo); // Pushback remaining buffer contents
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("just read tables-only image; q table 0 at %p\n",
cinfo->quant_tbl_ptrs[0]);
#endif
......@@ -1691,6 +1711,14 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
}
}
RELEASE_ARRAYS(env, data, src->next_input_byte);
/* read icc profile data */
profileData = read_icc_profile(env, cinfo);
if ((*env)->ExceptionCheck(env)) {
return retval;
}
(*env)->CallVoidMethod(env, this,
JPEGImageReader_setImageDataID,
cinfo->image_width,
......@@ -1698,7 +1726,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
cinfo->jpeg_color_space,
cinfo->out_color_space,
cinfo->num_components,
read_icc_profile(env, cinfo));
profileData);
if (reset) {
jpeg_abort_decompress(cinfo);
}
......@@ -1827,7 +1855,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
(*env)->ReleaseIntArrayElements(env, srcBands, body, JNI_ABORT);
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("---- in reader.read ----\n");
printf("numBands is %d\n", numBands);
printf("bands array: ");
......@@ -2487,7 +2515,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeTables
data->streamBuf.suspendable = FALSE;
if (qtables != NULL) {
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("in writeTables: qtables not NULL\n");
#endif
setQTables(env, (j_common_ptr) cinfo, qtables, TRUE);
......@@ -2763,7 +2791,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage
cinfo->restart_interval = restartInterval;
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
printf("writer setup complete, starting compressor\n");
#endif
......@@ -2812,13 +2840,13 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage
for (i = 0; i < numBands; i++) {
if (scale !=NULL && scale[i] != NULL) {
*out++ = scale[i][*(in+i)];
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
if (in == data->pixelBuf.buf.bp){ // Just the first pixel
printf("in %d -> out %d, ", *(in+i), *(out-i-1));
}
#endif
#ifdef DEBUG
#ifdef DEBUG_IIO_JPEG
if (in == data->pixelBuf.buf.bp){ // Just the first pixel
printf("\n");
}
......
......@@ -394,12 +394,14 @@ static int setupFTContext(JNIEnv *env,
scalerInfo->env = env;
scalerInfo->font2D = font2D;
FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
if (context != NULL) {
FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);
errCode = FT_Set_Char_Size(scalerInfo->face, 0, context->ptsz, 72, 72);
if (errCode == 0) {
errCode = FT_Activate_Size(scalerInfo->face->size);
if (errCode == 0) {
errCode = FT_Activate_Size(scalerInfo->face->size);
}
}
return errCode;
......@@ -885,6 +887,14 @@ Java_sun_font_FreetypeFontScaler_disposeNativeScaler(
JNIEnv *env, jobject scaler, jlong pScaler) {
FTScalerInfo* scalerInfo = (FTScalerInfo *) jlong_to_ptr(pScaler);
/* Freetype functions *may* cause callback to java
that can use cached values. Make sure our cache is up to date.
NB: scaler context is not important at this point, can use NULL. */
int errCode = setupFTContext(env, scaler, scalerInfo, NULL);
if (errCode) {
return;
}
freeNativeResources(env, scalerInfo);
}
......@@ -932,12 +942,21 @@ Java_sun_font_FreetypeFontScaler_getGlyphCodeNative(
JNIEnv *env, jobject scaler, jlong pScaler, jchar charCode) {
FTScalerInfo* scalerInfo = (FTScalerInfo *) jlong_to_ptr(pScaler);
int errCode;
if (scaler == NULL || scalerInfo->face == NULL) { /* bad/null scaler */
invalidateJavaScaler(env, scaler, scalerInfo);
return 0;
}
/* Freetype functions *may* cause callback to java
that can use cached values. Make sure our cache is up to date.
Scaler context is not important here, can use NULL. */
errCode = setupFTContext(env, scaler, scalerInfo, NULL);
if (errCode) {
return 0;
}
return FT_Get_Char_Index(scalerInfo->face, charCode);
}
......
......@@ -30,6 +30,41 @@
#include "Disposer.h"
#include "lcms.h"
#define ALIGNLONG(x) (((x)+3) & ~(3)) // Aligns to DWORD boundary
#ifdef USE_BIG_ENDIAN
#define AdjustEndianess32(a)
#else
static
void AdjustEndianess32(LPBYTE pByte)
{
BYTE temp1;
BYTE temp2;
temp1 = *pByte++;
temp2 = *pByte++;
*(pByte-1) = *pByte;
*pByte++ = temp2;
*(pByte-3) = *pByte;
*pByte = temp1;
}
#endif
// Transports to properly encoded values - note that icc profiles does use
// big endian notation.
static
icInt32Number TransportValue32(icInt32Number Value)
{
icInt32Number Temp = Value;
AdjustEndianess32((LPBYTE) &Temp);
return Temp;
}
#define SigMake(a,b,c,d) \
( ( ((int) ((unsigned char) (a))) << 24) | \
( ((int) ((unsigned char) (b))) << 16) | \
......@@ -182,6 +217,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile
sProf.pf = cmsOpenProfileFromMem((LPVOID)dataArray, (DWORD) dataSize);
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
if (sProf.pf == NULL) {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
}
......@@ -337,6 +374,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
return;
}
// Modify data for a tag in a profile
LCMSBOOL LCMSEXPORT _cmsModifyTagData(cmsHPROFILE hProfile,
icTagSignature sig, void *data, size_t size);
/*
* Class: sun_java2d_cmm_lcms_LCMS
* Method: setTagData
......@@ -345,7 +386,23 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
{
fprintf(stderr, "setTagData operation is not implemented");
cmsHPROFILE profile;
storeID_t sProf;
jbyte* dataArray;
int tagSize;
if (tagSig == SigHead) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_setTagData on icSigHead not "
"permitted");
return;
}
sProf.j = id;
profile = (cmsHPROFILE) sProf.pf;
dataArray = (*env)->GetByteArrayElements(env, data, 0);
tagSize =(*env)->GetArrayLength(env, data);
_cmsModifyTagData(profile, (icTagSignature) tagSig, dataArray, tagSize);
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
}
void* getILData (JNIEnv *env, jobject img, jint* pDataType,
......@@ -507,3 +564,174 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
}
LCMSBOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig,
void *data, size_t size)
{
LCMSBOOL isNew;
int i, idx, delta, count;
LPBYTE padChars[3] = {0, 0, 0};
LPBYTE beforeBuf, afterBuf, ptr;
size_t beforeSize, afterSize;
icUInt32Number profileSize, temp;
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
isNew = FALSE;
idx = _cmsSearchTag(Icc, sig, FALSE);
if (idx < 0) {
isNew = TRUE;
idx = Icc->TagCount++;
if (Icc->TagCount >= MAX_TABLE_TAG) {
J2dRlsTraceLn1(J2D_TRACE_ERROR, "_cmsModifyTagData: Too many tags "
"(%d)\n", Icc->TagCount);
Icc->TagCount = MAX_TABLE_TAG-1;
return FALSE;
}
}
/* Read in size from header */
Icc->Seek(Icc, 0);
Icc->Read(&profileSize, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &profileSize);
/* Compute the change in profile size */
if (isNew) {
delta = sizeof(icTag) + ALIGNLONG(size);
} else {
delta = ALIGNLONG(size) - ALIGNLONG(Icc->TagSizes[idx]);
}
/* Add tag to internal structures */
ptr = malloc(size);
if (ptr == NULL) {
if(isNew) {
Icc->TagCount--;
}
J2dRlsTraceLn(J2D_TRACE_ERROR, "_cmsModifyTagData: ptr == NULL");
return FALSE;
}
if (!Icc->Grow(Icc, delta)) {
free(ptr);
if(isNew) {
Icc->TagCount--;
}
J2dRlsTraceLn(J2D_TRACE_ERROR,
"_cmsModifyTagData: Icc->Grow() == FALSE");
return FALSE;
}
/* Compute size of tag data before/after the modified tag */
beforeSize = ((isNew)?profileSize:Icc->TagOffsets[idx]) -
Icc->TagOffsets[0];
if (Icc->TagCount == (idx + 1)) {
afterSize = 0;
} else {
afterSize = profileSize - Icc->TagOffsets[idx+1];
}
/* Make copies of the data before/after the modified tag */
if (beforeSize > 0) {
beforeBuf = malloc(beforeSize);
if (!beforeBuf) {
if(isNew) {
Icc->TagCount--;
}
free(ptr);
J2dRlsTraceLn(J2D_TRACE_ERROR,
"_cmsModifyTagData: beforeBuf == NULL");
return FALSE;
}
Icc->Seek(Icc, Icc->TagOffsets[0]);
Icc->Read(beforeBuf, beforeSize, 1, Icc);
}
if (afterSize > 0) {
afterBuf = malloc(afterSize);
if (!afterBuf) {
free(ptr);
if(isNew) {
Icc->TagCount--;
}
if (beforeSize > 0) {
free(beforeBuf);
}
J2dRlsTraceLn(J2D_TRACE_ERROR,
"_cmsModifyTagData: afterBuf == NULL");
return FALSE;
}
Icc->Seek(Icc, Icc->TagOffsets[idx+1]);
Icc->Read(afterBuf, afterSize, 1, Icc);
}
CopyMemory(ptr, data, size);
Icc->TagSizes[idx] = size;
Icc->TagNames[idx] = sig;
if (Icc->TagPtrs[idx]) {
free(Icc->TagPtrs[idx]);
}
Icc->TagPtrs[idx] = ptr;
if (isNew) {
Icc->TagOffsets[idx] = profileSize;
}
/* Update the profile size in the header */
profileSize += delta;
Icc->Seek(Icc, 0);
temp = TransportValue32(profileSize);
Icc->Write(Icc, sizeof(icUInt32Number), &temp);
/* Adjust tag offsets: if the tag is new, we must account
for the new tag table entry; otherwise, only those tags after
the modified tag are changed (by delta) */
if (isNew) {
for (i = 0; i < Icc->TagCount; ++i) {
Icc->TagOffsets[i] += sizeof(icTag);
}
} else {
for (i = idx+1; i < Icc->TagCount; ++i) {
Icc->TagOffsets[i] += delta;
}
}
/* Write out a new tag table */
count = 0;
for (i = 0; i < Icc->TagCount; ++i) {
if (Icc->TagNames[i] != 0) {
++count;
}
}
Icc->Seek(Icc, sizeof(icHeader));
temp = TransportValue32(count);
Icc->Write(Icc, sizeof(icUInt32Number), &temp);
for (i = 0; i < Icc->TagCount; ++i) {
if (Icc->TagNames[i] != 0) {
icTag tag;
tag.sig = TransportValue32(Icc->TagNames[i]);
tag.offset = TransportValue32((icInt32Number) Icc->TagOffsets[i]);
tag.size = TransportValue32((icInt32Number) Icc->TagSizes[i]);
Icc->Write(Icc, sizeof(icTag), &tag);
}
}
/* Write unchanged data before the modified tag */
if (beforeSize > 0) {
Icc->Write(Icc, beforeSize, beforeBuf);
free(beforeBuf);
}
/* Write modified tag data */
Icc->Write(Icc, size, data);
if (size % 4) {
Icc->Write(Icc, 4 - (size % 4), padChars);
}
/* Write unchanged data after the modified tag */
if (afterSize > 0) {
Icc->Write(Icc, afterSize, afterBuf);
free(afterBuf);
}
return TRUE;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -51,7 +51,7 @@
// CIECAM 02 appearance model
// CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging.
#include "lcms.h"
......@@ -196,6 +196,10 @@ CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod)
clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1;
}
}
clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
(clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
return clr;
}
......@@ -249,9 +253,6 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp);
}
clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] +
(clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb;
clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A),
(pMod->c * pMod->z));
......@@ -395,7 +396,7 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
LPcmsCIECAM02 lpMod;
if((lpMod = (LPcmsCIECAM02) malloc(sizeof(cmsCIECAM02))) == NULL) {
if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) {
return (LCMSHANDLE) NULL;
}
......@@ -449,14 +450,19 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
lpMod -> z = compute_z(lpMod);
lpMod -> Nbb = computeNbb(lpMod);
lpMod -> FL = computeFL(lpMod);
if (lpMod -> D == D_CALCULATE ||
lpMod -> D == D_CALCULATE_DISCOUNT) {
lpMod -> D = computeD(lpMod);
}
lpMod -> Ncb = lpMod -> Nbb;
lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod);
lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
lpMod -> adoptedWhite = ComputeCorrelates(lpMod -> adoptedWhite, lpMod);
return (LCMSHANDLE) lpMod;
......@@ -465,7 +471,7 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel)
{
LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
if (lpMod) free(lpMod);
if (lpMod) _cmsFree(lpMod);
}
......@@ -510,3 +516,4 @@ void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ
pOut ->Z = clr.XYZ[2];
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -174,7 +174,7 @@ typedef struct {
LCMSAPI void LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel)
{
LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel;
if (lpMod) free(lpMod);
if (lpMod) _cmsFree(lpMod);
}
// Partial discounting for adaptation degree computation
......@@ -331,7 +331,7 @@ LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM97sInit(LPcmsViewingConditions pVC)
LPcmsCIECAM97s lpMod;
VEC3 tmp;
if((lpMod = (LPcmsCIECAM97s) malloc(sizeof(cmsCIECAM97s))) == NULL) {
if((lpMod = (LPcmsCIECAM97s) _cmsMalloc(sizeof(cmsCIECAM97s))) == NULL) {
return (LCMSHANDLE) NULL;
}
......@@ -449,7 +449,7 @@ LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM97sInit(LPcmsViewingConditions pVC)
// RGB_subw = [MlamRigg][WP/YWp]
#ifdef USE_CIECAM97s2
MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, (LPVEC3) &lpMod -> WP);
MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &lpMod -> WP);
#else
VEC3divK(&tmp, (LPVEC3) &lpMod -> WP, lpMod->WP.Y);
MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &tmp);
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -65,22 +65,25 @@ LCMSAPI int LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable);
// Persistence
LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
// Properties
LCMSAPI const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
LCMSAPI const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
LCMSAPI double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames);
LCMSAPI const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames);
LCMSAPI int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
// Datasets
......@@ -89,10 +92,10 @@ LCMSAPI const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatc
LCMSAPI const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
LCMSAPI double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int col, int row);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
const char* Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
double Val);
LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
......@@ -100,15 +103,15 @@ LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPa
LCMSAPI double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
const char* cSample,
const char *Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
const char* cSample,
double Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
LCMSAPI int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
LCMSAPI void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
......@@ -126,7 +129,7 @@ LCMSAPI int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const
// #define STRICT_CGATS 1
#define MAXID 128 // Max lenght of identifier
#define MAXSTR 255 // Max lenght of string
#define MAXSTR 1024 // Max lenght of string
#define MAXTABLES 255 // Max Number of tables in a single stream
#define MAXINCLUDE 20 // Max number of nested includes
......@@ -137,6 +140,9 @@ LCMSAPI int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const
#ifndef NON_WINDOWS
#include <io.h>
#define DIR_CHAR '\\'
#else
#define DIR_CHAR '/'
#endif
// Symbols
......@@ -160,6 +166,7 @@ typedef enum {
SEND_DATA,
SEND_DATA_FORMAT,
SKEYWORD,
SDATA_FORMAT_ID,
SINCLUDE
} SYMBOL;
......@@ -171,7 +178,8 @@ typedef enum {
WRITE_UNCOOKED,
WRITE_STRINGIFY,
WRITE_HEXADECIMAL,
WRITE_BINARY
WRITE_BINARY,
WRITE_PAIR
} WRITEMODE;
......@@ -181,6 +189,8 @@ typedef struct _KeyVal {
struct _KeyVal* Next;
char* Keyword; // Name of variable
struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item
char* Subkey; // If key is a dictionary, points to the subkey name
char* Value; // Points to value
WRITEMODE WriteAs; // How to write the value
......@@ -220,7 +230,12 @@ typedef struct _Table {
} TABLE, *LPTABLE;
// File stream being parsed
typedef struct _FileContext {
char FileName[MAX_PATH]; // File name if being readed from file
FILE* Stream; // File stream or NULL if holded in memory
} FILECTX, *LPFILECTX;
// This struct hold all information about an openened
// IT8 handler. Only one dataset is allowed.
......@@ -257,9 +272,9 @@ typedef struct {
char* Source; // Points to loc. being parsed
int lineno; // line counter for error reporting
char FileName[MAX_PATH]; // File name if being readed from file
FILE* Stream[MAXINCLUDE]; // File stream or NULL if holded in memory
LPFILECTX FileStack[MAXINCLUDE]; // Stack of files being parsed
int IncludeSP; // Include Stack Pointer
char* MemoryBlock; // The stream if holded in memory
char DoubleFormatter[MAXID]; // Printf-like 'double' formatter
......@@ -270,14 +285,14 @@ typedef struct {
typedef struct {
FILE* stream; // For save-to-file behaviour
FILE* stream; // For save-to-file behaviour
LPBYTE Base;
LPBYTE Ptr; // For save-to-mem behaviour
size_t Used;
size_t Max;
LPBYTE Base;
LPBYTE Ptr; // For save-to-mem behaviour
size_t Used;
size_t Max;
} SAVESTREAM, FAR* LPSAVESTREAM;
} SAVESTREAM, FAR* LPSAVESTREAM;
// ------------------------------------------------------ IT8 parsing routines
......@@ -298,59 +313,104 @@ static const KEYWORD TabKeys[] = {
{".INCLUDE", SINCLUDE},
{"BEGIN_DATA", SBEGIN_DATA },
{"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT },
{"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID},
{"END_DATA", SEND_DATA},
{"END_DATA_FORMAT", SEND_DATA_FORMAT},
{"KEYWORD", SKEYWORD}
};
#define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
// Predefined properties
static const char* PredefinedProperties[] = {
"NUMBER_OF_FIELDS", // Required - NUMBER OF FIELDS
"NUMBER_OF_SETS", // Required - NUMBER OF SETS
"ORIGINATOR", // Required - Identifies the specific system, organization or individual that created the data file.
"FILE_DESCRIPTOR", // Required - Describes the purpose or contents of the data file.
"CREATED", // Required - Indicates date of creation of the data file.
"DESCRIPTOR", // Required - Describes the purpose or contents of the data file.
"DIFFUSE_GEOMETRY", // The diffuse geometry used. Allowed values are "sphere" or "opal".
"MANUFACTURER",
"MANUFACTURE", // Some broken Fuji targets does store this value
"PROD_DATE", // Identifies year and month of production of the target in the form yyyy:mm.
"SERIAL", // Uniquely identifies individual physical target.
"MATERIAL", // Identifies the material on which the target was produced using a code
// A property
typedef struct {
const char *id;
WRITEMODE as;
} PROPERTY;
static PROPERTY PredefinedProperties[] = {
{"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS
{"NUMBER_OF_SETS", WRITE_UNCOOKED}, // Required - NUMBER OF SETS
{"ORIGINATOR", WRITE_STRINGIFY}, // Required - Identifies the specific system, organization or individual that created the data file.
{"FILE_DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file.
{"CREATED", WRITE_STRINGIFY}, // Required - Indicates date of creation of the data file.
{"DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file.
{"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal".
{"MANUFACTURER", WRITE_STRINGIFY},
{"MANUFACTURE", WRITE_STRINGIFY}, // Some broken Fuji targets does store this value
{"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm.
{"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target.
{"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code
// uniquely identifying th e material. This is intend ed to be used for IT8.7
// physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
"INSTRUMENTATION", // Used to report the specific instrumentation used (manufacturer and
{"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and
// model number) to generate the data reported. This data will often
// provide more information about the particular data collected than an
// extensive list of specific details. This is particularly important for
// spectral data or data derived from spectrophotometry.
"MEASUREMENT_SOURCE", // Illumination used for spectral measurements. This data helps provide
{"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide
// a guide to the potential for issues of paper fluorescence, etc.
"PRINT_CONDITIONS", // Used to define the characteristics of the printed sheet being reported.
{"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported.
// Where standard conditions have been defined (e.g., SWOP at nominal)
// named conditions may suffice. Otherwise, detailed information is
// needed.
"SAMPLE_BACKING", // Identifies the backing material used behind the sample during
// measurement. Allowed values are black, white, or "na".
{"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during
// measurement. Allowed values are black, white, or {"na".
{"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic
// new in recent specs:
{"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
// along with details of the geometry and the aperture size and shape. For example,
// for transmission measurements it is important to identify 0/diffuse, diffuse/0,
// opal or integrating sphere, etc. For reflection it is important to identify 0/45,
// 45/0, sphere (specular included or excluded), etc.
{"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to
// denote the use of filters such as none, D65, Red, Green or Blue.
{"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed
// values are {"yes, white, none or na.
{"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the
// calculation of various data parameters (2 degree and 10 degree), CIE standard
// illuminant functions used in the calculation of various data parameters (e.g., D50,
// D65, etc.), density status response, etc. If used there shall be at least one
// name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
// in the set shall be {"name" and shall identify the particular parameter used.
// The second shall be {"value" and shall provide the value associated with that name.
// For ASCII data, a string containing the Name and Value attribute pairs shall follow
// the weighting function keyword. A semi-colon separates attribute pairs from each
// other and within the attribute the name and value are separated by a comma.
"CHISQ_DOF" // Degrees of freedom associated with the Chi squared statistic
{"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name
// of the calculation, parameter is the name of the parameter used in the calculation
// and value is the value of the parameter.
{"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
{"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target.
{"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table.
{"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table.
};
#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(char *))
#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY))
// Predefined sample types on dataset
static const char* PredefinedSampleID[] = {
"SAMPLE_ID", // Identifies sample that data represents
"STRING", // Identifies label, or other non-machine readable value.
// Value must begin and end with a " symbol
"CMYK_C", // Cyan component of CMYK data expressed as a percentage
"CMYK_M", // Magenta component of CMYK data expressed as a percentage
......@@ -378,7 +438,7 @@ static const char* PredefinedSampleID[] = {
"LAB_B", // b* component of Lab data
"LAB_C", // C*ab component of Lab data
"LAB_H", // hab component of Lab data
"LAB_DE" // CIE dE
"LAB_DE", // CIE dE
"LAB_DE_94", // CIE dE using CIE 94
"LAB_DE_CMC", // dE using CMC
"LAB_DE_2000", // CIE dE using CIE DE 2000
......@@ -388,7 +448,7 @@ static const char* PredefinedSampleID[] = {
"STDEV_Y", // Standard deviation of Y (tristimulus data)
"STDEV_Z", // Standard deviation of Z (tristimulus data)
"STDEV_L", // Standard deviation of L*
"STDEV_A" // Standard deviation of a*
"STDEV_A", // Standard deviation of a*
"STDEV_B", // Standard deviation of b*
"STDEV_DE", // Standard deviation of CIE dE
"CHI_SQD_PAR"}; // The average of the standard deviations of L*, a* and b*. It is
......@@ -397,57 +457,120 @@ static const char* PredefinedSampleID[] = {
#define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
//Forward declaration of some internal functions
static
void* AllocChunk(LPIT8 it8, size_t size);
// Checks if c is a separator
static
BOOL isseparator(int c)
LCMSBOOL isseparator(int c)
{
return (c == ' ') || (c == '\t') || (c == '\r');
}
// Checks whatever if c is a valid identifier char
static
BOOL ismiddle(int c)
LCMSBOOL ismiddle(int c)
{
return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
}
// Checks whatsever if c is a valid identifier middle char.
static
BOOL isidchar(int c)
LCMSBOOL isidchar(int c)
{
return isalnum(c) || ismiddle(c);
}
// Checks whatsever if c is a valid identifier first char.
static
BOOL isfirstidchar(int c)
LCMSBOOL isfirstidchar(int c)
{
return !isdigit(c) && ismiddle(c);
}
// checks whether the supplied path looks like an absolute path
// NOTE: this function doesn't checks if the path exists or even if it's legal
static
LCMSBOOL isabsolutepath(const char *path)
{
if(path == NULL)
return FALSE;
if(path[0] == DIR_CHAR)
return TRUE;
#ifndef NON_WINDOWS
if(isalpha(path[0]) && path[1] == ':')
return TRUE;
#endif
return FALSE;
}
// Makes a file path based on a given reference path
// NOTE: buffer is assumed to point to at least MAX_PATH bytes
// NOTE: both relPath and basePath are assumed to be no more than MAX_PATH characters long (including the null terminator!)
// NOTE: this function doesn't check if the path exists or even if it's legal
static
LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer)
{
if (!isabsolutepath(relPath)) {
char *tail;
strncpy(buffer, basePath, MAX_PATH-1);
tail = strrchr(buffer, DIR_CHAR);
if (tail != NULL) {
size_t len = tail - buffer;
strncpy(tail + 1, relPath, MAX_PATH - len -1);
// TODO: if combined path is longer than MAX_PATH, this should return FALSE!
return TRUE;
}
}
strncpy(buffer, relPath, MAX_PATH - 1);
buffer[MAX_PATH-1] = 0;
return TRUE;
}
// Make sure no exploit is being even tried
static
const char* NoMeta(const char* str)
{
if (strchr(str, '%') != NULL)
return "**** CORRUPTED FORMAT STRING ***";
return str;
}
// Syntax error
static
BOOL SynError(LPIT8 it8, const char *Txt, ...)
LCMSBOOL SynError(LPIT8 it8, const char *Txt, ...)
{
char Buffer[256], ErrMsg[1024];
va_list args;
va_start(args, Txt);
vsprintf(Buffer, Txt, args);
vsnprintf(Buffer, 255, Txt, args);
Buffer[255] = 0;
va_end(args);
sprintf(ErrMsg, "%s: Line %d, %s", it8->FileName, it8->lineno, Buffer);
snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer);
ErrMsg[1023] = 0;
it8->sy = SSYNERROR;
cmsSignalError(LCMS_ERRC_ABORTED, ErrMsg);
cmsSignalError(LCMS_ERRC_ABORTED, "%s", ErrMsg);
return FALSE;
}
// Check if current symbol is same as specified. issue an error else.
static
BOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
LCMSBOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
{
if (it8 -> sy != sy)
return SynError(it8, Err);
return SynError(it8, NoMeta(Err));
return TRUE;
}
......@@ -457,15 +580,15 @@ BOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
static
void NextCh(LPIT8 it8)
{
if (it8 -> Stream[it8 ->IncludeSP]) {
if (it8 -> FileStack[it8 ->IncludeSP]->Stream) {
it8 ->ch = fgetc(it8 ->Stream[it8 ->IncludeSP]);
it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream);
if (feof(it8 -> Stream[it8 ->IncludeSP])) {
if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream)) {
if (it8 ->IncludeSP > 0) {
fclose(it8 ->Stream[it8->IncludeSP--]);
fclose(it8 ->FileStack[it8->IncludeSP--]->Stream);
it8 -> ch = ' '; // Whitespace to be ignored
} else
......@@ -476,7 +599,6 @@ void NextCh(LPIT8 it8)
}
else {
it8->ch = *it8->Source;
if (it8->ch) it8->Source++;
}
......@@ -799,18 +921,39 @@ void InSymbol(LPIT8 it8)
if (it8 -> sy == SINCLUDE) {
FILE* IncludeFile;
LPFILECTX FileNest;
if(it8 -> IncludeSP >= (MAXINCLUDE-1))
{
SynError(it8, "Too many recursion levels");
return;
}
InSymbol(it8);
if (!Check(it8, SSTRING, "Filename expected")) return;
IncludeFile = fopen(it8 -> str, "rt");
if (IncludeFile == NULL) {
SynError(it8, "File %s not found", it8 ->str);
FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
if(FileNest == NULL)
{
FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
//if(FileNest == NULL)
// TODO: how to manage out-of-memory conditions?
}
if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE)
{
SynError(it8, "File path too long");
return;
}
FileNest->Stream = fopen(FileNest->FileName, "rt");
if (FileNest->Stream == NULL) {
SynError(it8, "File %s not found", FileNest->FileName);
return;
}
it8->IncludeSP++;
it8 -> Stream[++it8 -> IncludeSP] = IncludeFile;
it8 ->ch = ' ';
InSymbol(it8);
}
......@@ -819,7 +962,7 @@ void InSymbol(LPIT8 it8)
// Checks end of line separator
static
BOOL CheckEOLN(LPIT8 it8)
LCMSBOOL CheckEOLN(LPIT8 it8)
{
if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
while (it8 -> sy == SEOLN)
......@@ -850,21 +993,26 @@ void SkipEOLN(LPIT8 it8)
// Returns a string holding current value
static
BOOL GetVal(LPIT8 it8, char* Buffer, const char* ErrorTitle)
LCMSBOOL GetVal(LPIT8 it8, char* Buffer, size_t max, const char* ErrorTitle)
{
switch (it8->sy) {
case SIDENT: strncpy(Buffer, it8->id, MAXID-1); break;
case SINUM: sprintf(Buffer, "%d", it8 -> inum); break;
case SDNUM: sprintf(Buffer, it8->DoubleFormatter, it8 -> dnum); break;
case SSTRING: strncpy(Buffer, it8->str, MAXSTR-1); break;
case SIDENT: strncpy(Buffer, it8->id, max);
Buffer[max-1]=0;
break;
case SINUM: snprintf(Buffer, max, "%d", it8 -> inum); break;
case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break;
case SSTRING: strncpy(Buffer, it8->str, max);
Buffer[max-1] = 0;
break;
default:
return SynError(it8, ErrorTitle);
return SynError(it8, "%s", ErrorTitle);
}
return TRUE;
Buffer[max] = 0;
return TRUE;
}
// ---------------------------------------------------------- Table
......@@ -872,7 +1020,13 @@ BOOL GetVal(LPIT8 it8, char* Buffer, const char* ErrorTitle)
static
LPTABLE GetTable(LPIT8 it8)
{
return it8 ->Tab + it8 ->nTable;
if ((it8 -> nTable >= it8 ->TablesCount) || (it8 -> nTable < 0)) {
SynError(it8, "Table %d out of sequence", it8 -> nTable);
return it8 -> Tab;
}
return it8 ->Tab + it8 ->nTable;
}
// ---------------------------------------------------------- Memory management
......@@ -896,15 +1050,15 @@ void LCMSEXPORT cmsIT8Free(LCMSHANDLE hIT8)
for (p = it8->MemorySink; p != NULL; p = n) {
n = p->Next;
if (p->Ptr) free(p->Ptr);
free(p);
if (p->Ptr) _cmsFree(p->Ptr);
_cmsFree(p);
}
}
if (it8->MemoryBlock)
free(it8->MemoryBlock);
_cmsFree(it8->MemoryBlock);
free(it8);
_cmsFree(it8);
}
......@@ -913,16 +1067,16 @@ static
void* AllocBigBlock(LPIT8 it8, size_t size)
{
LPOWNEDMEM ptr1;
void* ptr = malloc(size);
void* ptr = _cmsMalloc(size);
if (ptr) {
ZeroMemory(ptr, size);
ptr1 = (LPOWNEDMEM) malloc(sizeof(OWNEDMEM));
ptr1 = (LPOWNEDMEM) _cmsMalloc(sizeof(OWNEDMEM));
if (ptr1 == NULL) {
free(ptr);
_cmsFree(ptr);
return NULL;
}
......@@ -986,8 +1140,9 @@ char *AllocString(LPIT8 it8, const char* str)
// Searches through linked list
static
BOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr)
LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr)
{
if (LastPtr) *LastPtr = p;
for (; p != NULL; p = p->Next) {
......@@ -996,8 +1151,22 @@ BOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr)
if (*Key != '#') { // Comments are ignored
if (stricmp(Key, p->Keyword) == 0)
return TRUE;
break;
}
}
if (p == NULL)
return FALSE;
if (Subkey == 0)
return TRUE;
for (; p != NULL; p = p->NextSubkey) {
if (LastPtr) *LastPtr = p;
if (stricmp(Subkey, p->Subkey) == 0)
return TRUE;
}
return FALSE;
......@@ -1007,35 +1176,55 @@ BOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr)
// Add a property into a linked list
static
BOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* xValue, WRITEMODE WriteAs)
LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
{
LPKEYVALUE p;
LPKEYVALUE last;
// Check if property is already in list (this is an error)
if (IsAvailableOnList(*Head, Key, &last)) {
// This may work for editing properties
if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
last->Value = AllocString(it8, xValue);
last->WriteAs = WriteAs;
return TRUE;
// This may work for editing properties
// return SynError(it8, "duplicate key <%s>", Key);
// return SynError(it8, "duplicate key <%s>", Key);
}
else {
LPKEYVALUE last = p;
// Allocate the container
// Allocate the container
p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE));
if (p == NULL)
{
return SynError(it8, "AddToList: out of memory");
SynError(it8, "AddToList: out of memory");
return NULL;
}
// Store name and value
p->Keyword = AllocString(it8, Key);
p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey);
// Keep the container in our list
if (*Head == NULL)
*Head = p;
else
{
if(Subkey != 0 && last != 0) {
last->NextSubkey = p;
// If Subkey is not null, then last is the last property with the same key,
// but not necessarily is the last property in the list, so we need to move
// to the actual list end
while(last->Next != 0)
last = last->Next;
}
last->Next = p;
}
p->Next = NULL;
p->NextSubkey = NULL;
}
p->WriteAs = WriteAs;
if (xValue != NULL) {
p->Value = AllocString(it8, xValue);
......@@ -1044,29 +1233,20 @@ BOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* xValue,
p->Value = NULL;
}
p->Next = NULL;
p->WriteAs = WriteAs;
// Keep the container in our list
if (*Head == NULL)
*Head = p;
else
last->Next = p;
return TRUE;
return p;
}
static
BOOL AddAvailableProperty(LPIT8 it8, const char* Key)
LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as)
{
return AddToList(it8, &it8->ValidKeywords, Key, NULL, WRITE_UNCOOKED);
return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
}
static
BOOL AddAvailableSampleID(LPIT8 it8, const char* Key)
LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key)
{
return AddToList(it8, &it8->ValidSampleID, Key, NULL, WRITE_UNCOOKED);
return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
}
......@@ -1122,8 +1302,6 @@ LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void)
AllocTable(it8);
it8->MemoryBlock = NULL;
it8->Stream[0] = NULL;
it8->IncludeSP = 0;
it8->MemorySink = NULL;
it8 ->nTable = 0;
......@@ -1141,6 +1319,8 @@ LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void)
it8 -> inum = 0;
it8 -> dnum = 0.0;
it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
it8->IncludeSP = 0;
it8 -> lineno = 1;
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
......@@ -1149,7 +1329,7 @@ LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void)
// Initialize predefined properties & data
for (i=0; i < NUMPREDEFINEDPROPS; i++)
AddAvailableProperty(it8, PredefinedProperties[i]);
AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
for (i=0; i < NUMPREDEFINEDSAMPLEID; i++)
AddAvailableSampleID(it8, PredefinedSampleID[i]);
......@@ -1167,65 +1347,72 @@ const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8)
}
BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type)
LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type)
{
LPIT8 it8 = (LPIT8) hIT8;
strncpy(it8 ->SheetType, Type, MAXSTR-1);
it8 ->SheetType[MAXSTR-1] = 0;
return TRUE;
}
BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val)
LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val)
{
LPIT8 it8 = (LPIT8) hIT8;
if (!Val) return FALSE;
if (!*Val) return FALSE;
return AddToList(it8, &GetTable(it8)->HeaderList, "# ", Val, WRITE_UNCOOKED);
return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL;
}
// Sets a property
BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val)
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val)
{
LPIT8 it8 = (LPIT8) hIT8;
if (!Val) return FALSE;
if (!*Val) return FALSE;
return AddToList(it8, &GetTable(it8)->HeaderList, Key, Val, WRITE_STRINGIFY);
return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL;
}
BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val)
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val)
{
LPIT8 it8 = (LPIT8) hIT8;
char Buffer[1024];
sprintf(Buffer, it8->DoubleFormatter, Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_UNCOOKED);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;
}
BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
{
LPIT8 it8 = (LPIT8) hIT8;
char Buffer[1024];
sprintf(Buffer, "%d", Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_HEXADECIMAL);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
}
BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
{
LPIT8 it8 = (LPIT8) hIT8;
return AddToList(it8, &GetTable(it8)->HeaderList, Key, Buffer, WRITE_UNCOOKED);
return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
}
LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
{
LPIT8 it8 = (LPIT8) hIT8;
return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL;
}
// Gets a property
const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key)
......@@ -1233,7 +1420,7 @@ const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key)
LPIT8 it8 = (LPIT8) hIT8;
LPKEYVALUE p;
if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, &p))
if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p))
{
return p -> Value;
}
......@@ -1249,6 +1436,18 @@ double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp)
else return 0.0;
}
const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey)
{
LPIT8 it8 = (LPIT8) hIT8;
LPKEYVALUE p;
if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p))
{
return p -> Value;
}
return NULL;
}
// ----------------------------------------------------------------- Datasets
......@@ -1287,10 +1486,17 @@ const char *GetDataFormat(LPIT8 it8, int n)
}
static
BOOL SetDataFormat(LPIT8 it8, int n, const char *label)
LCMSBOOL SetDataFormat(LPIT8 it8, int n, const char *label)
{
LPTABLE t = GetTable(it8);
#ifdef STRICT_CGATS
if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) {
SynError(it8, "Invalid data format '%s'.", label);
return FALSE;
}
#endif
if (!t->DataFormat)
AllocateDataFormat(it8);
......@@ -1308,7 +1514,7 @@ BOOL SetDataFormat(LPIT8 it8, int n, const char *label)
}
BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample)
LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample)
{
LPIT8 it8 = (LPIT8) h;
return SetDataFormat(it8, n, Sample);
......@@ -1348,7 +1554,7 @@ char* GetData(LPIT8 it8, int nSet, int nField)
}
static
BOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val)
LCMSBOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val)
{
LPTABLE t = GetTable(it8);
......@@ -1383,42 +1589,43 @@ static
void WriteStr(LPSAVESTREAM f, const char *str)
{
size_t len;
size_t len;
if (str == NULL)
str = " ";
if (str == NULL)
str = " ";
// Lenghth to write
len = strlen(str);
// Lenghth to write
len = strlen(str);
f ->Used += len;
if (f ->stream) { // Should I write it to a file?
fwrite(str, 1, len, f->stream);
if (f ->stream) { // Should I write it to a file?
}
else { // Or to a memory block?
fwrite(str, 1, len, f->stream);
}
else { // Or to a memory block?
if (f ->Base) { // Am I just counting the bytes?
if (f ->Used > f ->Max) {
if (f ->Base) { // Am I just counting the bytes?
cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
return;
}
if (f ->Used > f ->Max) {
CopyMemory(f ->Ptr, str, len);
f->Ptr += len;
cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
return;
}
}
CopyMemory(f ->Ptr, str, len);
f->Ptr += len;
}
}
}
//
// Write formatted
static
void Writef(LPSAVESTREAM f, const char* frm, ...)
{
......@@ -1426,7 +1633,8 @@ void Writef(LPSAVESTREAM f, const char* frm, ...)
va_list args;
va_start(args, frm);
vsprintf(Buffer, frm, args);
vsnprintf(Buffer, 4095, frm, args);
Buffer[4095] = 0;
WriteStr(f, Buffer);
va_end(args);
......@@ -1450,7 +1658,7 @@ void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
for (Pt = p ->Value; *Pt; Pt++) {
Writef(fp, "%c", *Pt);
Writef(fp, "%c", *Pt);
if (*Pt == '\n') {
WriteStr(fp, "# ");
......@@ -1462,7 +1670,7 @@ void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
}
if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL)) {
if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
#ifdef STRICT_CGATS
WriteStr(fp, "KEYWORD\t\"");
......@@ -1470,7 +1678,7 @@ void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
WriteStr(fp, "\"\n");
#endif
AddAvailableProperty(it8, p->Keyword);
AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
}
......@@ -1495,6 +1703,10 @@ void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
Writef(fp, "\t0x%B", atoi(p ->Value));
break;
case WRITE_PAIR:
Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value);
break;
default: SynError(it8, "Unknown write mode %d", p ->WriteAs);
return;
}
......@@ -1573,13 +1785,13 @@ void WriteData(LPSAVESTREAM fp, LPIT8 it8)
// Saves whole file
BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
{
SAVESTREAM sd;
int i;
LPIT8 it8 = (LPIT8) hIT8;
ZeroMemory(&sd, sizeof(SAVESTREAM));
ZeroMemory(&sd, sizeof(SAVESTREAM));
sd.stream = fopen(cFileName, "wt");
if (!sd.stream) return FALSE;
......@@ -1594,31 +1806,31 @@ BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
WriteData(&sd, it8);
}
fclose(sd.stream);
fclose(sd.stream);
return TRUE;
}
// Saves to memory
BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
{
SAVESTREAM sd;
int i;
LPIT8 it8 = (LPIT8) hIT8;
ZeroMemory(&sd, sizeof(SAVESTREAM));
ZeroMemory(&sd, sizeof(SAVESTREAM));
sd.stream = NULL;
sd.Base = (LPBYTE) MemPtr;
sd.Ptr = sd.Base;
sd.Base = (LPBYTE) MemPtr;
sd.Ptr = sd.Base;
sd.Used = 0;
sd.Used = 0;
if (sd.Base)
sd.Max = *BytesNeeded; // Write to memory?
else
sd.Max = 0; // Just counting the needed bytes
if (sd.Base)
sd.Max = *BytesNeeded; // Write to memory?
else
sd.Max = 0; // Just counting the needed bytes
WriteStr(&sd, it8->SheetType);
WriteStr(&sd, "\n");
......@@ -1630,12 +1842,12 @@ BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeed
WriteData(&sd, it8);
}
sd.Used++; // The \0 at the very end
sd.Used++; // The \0 at the very end
if (sd.Base)
sd.Ptr = 0;
if (sd.Base)
sd.Ptr = 0;
*BytesNeeded = sd.Used;
*BytesNeeded = sd.Used;
return TRUE;
}
......@@ -1644,7 +1856,7 @@ BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeed
// -------------------------------------------------------------- Higer level parsing
static
BOOL DataFormatSection(LPIT8 it8)
LCMSBOOL DataFormatSection(LPIT8 it8)
{
int iField = 0;
LPTABLE t = GetTable(it8);
......@@ -1685,16 +1897,19 @@ BOOL DataFormatSection(LPIT8 it8)
static
BOOL DataSection (LPIT8 it8)
LCMSBOOL DataSection (LPIT8 it8)
{
int iField = 0;
int iSet = 0;
char Buffer[256];
char Buffer[MAXSTR];
LPTABLE t = GetTable(it8);
InSymbol(it8); // Eats "BEGIN_DATA"
CheckEOLN(it8);
if (!t->Data)
AllocateDataSet(it8);
while (it8->sy != SEND_DATA && it8->sy != SEOF)
{
if (iField >= t -> nSamples) {
......@@ -1705,7 +1920,7 @@ BOOL DataSection (LPIT8 it8)
if (it8->sy != SEND_DATA && it8->sy != SEOF) {
if (!GetVal(it8, Buffer, "Sample data expected"))
if (!GetVal(it8, Buffer, 255, "Sample data expected"))
return FALSE;
if (!SetData(it8, iSet, iField, Buffer))
......@@ -1734,10 +1949,11 @@ BOOL DataSection (LPIT8 it8)
static
BOOL HeaderSection(LPIT8 it8)
LCMSBOOL HeaderSection(LPIT8 it8)
{
char VarName[MAXID];
char Buffer[MAXSTR];
LPKEYVALUE Key;
while (it8->sy != SEOF &&
it8->sy != SSYNERROR &&
......@@ -1749,30 +1965,79 @@ BOOL HeaderSection(LPIT8 it8)
case SKEYWORD:
InSymbol(it8);
if (!GetVal(it8, Buffer, "Keyword expected")) return FALSE;
if (!AddAvailableProperty(it8, Buffer)) return FALSE;
if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE;
InSymbol(it8);
break;
case SDATA_FORMAT_ID:
InSymbol(it8);
if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
if (!AddAvailableSampleID(it8, Buffer)) return FALSE;
InSymbol(it8);
break;
case SIDENT:
strncpy(VarName, it8->id, MAXID-1);
VarName[MAXID-1] = 0;
if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL)) {
if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
#ifdef STRICT_CGATS
return SynError(it8, "Undefined keyword '%s'", VarName);
#else
if (!AddAvailableProperty(it8, VarName)) return FALSE;
Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
if (Key == NULL) return FALSE;
#endif
}
InSymbol(it8);
if (!GetVal(it8, Buffer, "Property data expected")) return FALSE;
if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
AddToList(it8, &GetTable(it8)->HeaderList, VarName, Buffer,
(it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
if(Key->WriteAs != WRITE_PAIR) {
AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
(it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
}
else {
const char *Subkey;
char *Nextkey;
if (it8->sy != SSTRING)
return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
// chop the string as a list of "subkey, value" pairs, using ';' as a separator
for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
{
char *Value, *temp;
// identify token pair boundary
Nextkey = (char*) strchr(Subkey, ';');
if(Nextkey)
*Nextkey++ = '\0';
// for each pair, split the subkey and the value
Value = (char*) strrchr(Subkey, ',');
if(Value == NULL)
return SynError(it8, "Invalid value for property '%s'.", VarName);
// gobble the spaces before the coma, and the coma itself
temp = Value++;
do *temp-- = '\0'; while(temp >= Subkey && *temp == ' ');
// gobble any space at the right
temp = Value + strlen(Value) - 1;
while(*temp == ' ') *temp-- = '\0';
// trim the strings from the left
Subkey += strspn(Subkey, " ");
Value += strspn(Value, " ");
if(Subkey[0] == 0 || Value[0] == 0)
return SynError(it8, "Invalid value for property '%s'.", VarName);
AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
}
}
InSymbol(it8);
break;
......@@ -1793,22 +2058,23 @@ BOOL HeaderSection(LPIT8 it8)
static
BOOL ParseIT8(LPIT8 it8)
LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet)
{
char* SheetTypePtr;
char* SheetTypePtr = it8 ->SheetType;
if (nosheet == 0) {
// First line is a very special case.
while (isseparator(it8->ch))
NextCh(it8);
SheetTypePtr = it8 ->SheetType;
while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
*SheetTypePtr++= (char) it8 ->ch;
NextCh(it8);
}
}
*SheetTypePtr = 0;
InSymbol(it8);
......@@ -1869,6 +2135,12 @@ void CookPointers(LPIT8 it8)
for (idField = 0; idField < t -> nSamples; idField++)
{
if (t ->DataFormat == NULL) {
SynError(it8, "Undefined DATA_FORMAT");
return;
}
Fld = t->DataFormat[idField];
if (!Fld) continue;
......@@ -1884,6 +2156,7 @@ void CookPointers(LPIT8 it8)
char Buffer[256];
strncpy(Buffer, Data, 255);
Buffer[255] = 0;
if (strlen(Buffer) <= strlen(Data))
strcpy(Data, Buffer);
......@@ -1916,7 +2189,7 @@ void CookPointers(LPIT8 it8)
LPTABLE Table = it8 ->Tab + k;
LPKEYVALUE p;
if (IsAvailableOnList(Table->HeaderList, Label, &p)) {
if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
// Available, keep type and table
char Buffer[256];
......@@ -1924,7 +2197,7 @@ void CookPointers(LPIT8 it8)
char *Type = p ->Value;
int nTable = k;
sprintf(Buffer, "%s %d %s", Label, nTable, Type );
snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
SetData(it8, i, idField, Buffer);
}
......@@ -1948,8 +2221,9 @@ void CookPointers(LPIT8 it8)
// that should be something like some printable characters plus a \n
static
BOOL IsMyBlock(LPBYTE Buffer, size_t n)
int IsMyBlock(LPBYTE Buffer, size_t n)
{
int cols = 1, space = 0, quot = 0;
size_t i;
if (n < 10) return FALSE; // Too small
......@@ -1959,9 +2233,26 @@ BOOL IsMyBlock(LPBYTE Buffer, size_t n)
for (i = 1; i < n; i++) {
if (Buffer[i] == '\n' || Buffer[i] == '\r' || Buffer[i] == '\t') return TRUE;
if (Buffer[i] < 32) return FALSE;
switch(Buffer[i])
{
case '\n':
case '\r':
return quot == 1 || cols > 2 ? 0 : cols;
case '\t':
case ' ':
if(!quot && !space)
space = 1;
break;
case '\"':
quot = !quot;
break;
default:
if (Buffer[i] < 32) return 0;
if (Buffer[i] > 127) return 0;
cols += space;
space = 0;
break;
}
}
return FALSE;
......@@ -1970,7 +2261,7 @@ BOOL IsMyBlock(LPBYTE Buffer, size_t n)
static
BOOL IsMyFile(const char* FileName)
int IsMyFile(const char* FileName)
{
FILE *fp;
size_t Size;
......@@ -1998,21 +2289,22 @@ LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len)
LCMSHANDLE hIT8;
LPIT8 it8;
if (!IsMyBlock((LPBYTE) Ptr, len)) return NULL;
int type = IsMyBlock((LPBYTE) Ptr, len);
if (type == 0) return NULL;
hIT8 = cmsIT8Alloc();
if (!hIT8) return NULL;
it8 = (LPIT8) hIT8;
it8 ->MemoryBlock = (char*) malloc(len + 1);
it8 ->MemoryBlock = (char*) _cmsMalloc(len + 1);
strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
it8 ->MemoryBlock[len] = 0;
strncpy(it8->FileName, "", MAX_PATH-1);
strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1);
it8-> Source = it8 -> MemoryBlock;
if (!ParseIT8(it8)) {
if (!ParseIT8(it8, type-1)) {
cmsIT8Free(hIT8);
return FALSE;
......@@ -2021,7 +2313,7 @@ LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len)
CookPointers(it8);
it8 ->nTable = 0;
free(it8->MemoryBlock);
_cmsFree(it8->MemoryBlock);
it8 -> MemoryBlock = NULL;
return hIT8;
......@@ -2036,26 +2328,28 @@ LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName)
LCMSHANDLE hIT8;
LPIT8 it8;
if (!IsMyFile(cFileName)) return NULL;
int type = IsMyFile(cFileName);
if (type == 0) return NULL;
hIT8 = cmsIT8Alloc();
it8 = (LPIT8) hIT8;
if (!hIT8) return NULL;
it8 ->Stream[0] = fopen(cFileName, "rt");
it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
if (!it8 ->Stream[0]) {
if (!it8 ->FileStack[0]->Stream) {
cmsIT8Free(hIT8);
return NULL;
}
strncpy(it8->FileName, cFileName, MAX_PATH-1);
strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1);
it8->FileStack[0]->FileName[MAX_PATH-1] = 0;
if (!ParseIT8(it8)) {
if (!ParseIT8(it8, type-1)) {
fclose(it8 ->Stream[0]);
fclose(it8 ->FileStack[0]->Stream);
cmsIT8Free(hIT8);
return NULL;
}
......@@ -2063,7 +2357,7 @@ LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName)
CookPointers(it8);
it8 ->nTable = 0;
fclose(it8 ->Stream[0]);
fclose(it8 ->FileStack[0]->Stream);
return hIT8;
}
......@@ -2078,12 +2372,12 @@ int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE hIT8, char ***SampleNames)
}
int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames)
int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames)
{
LPIT8 it8 = (LPIT8) hIT8;
LPKEYVALUE p;
int n;
char **Props;
const char **Props;
LPTABLE t = GetTable(it8);
// Pass#1 - count properties
......@@ -2094,7 +2388,7 @@ int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames)
}
Props = (char **) AllocChunk(it8, sizeof(char *) * n);
Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
// Pass#2 - Fill pointers
n = 0;
......@@ -2106,6 +2400,41 @@ int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames)
return n;
}
int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
{
LPIT8 it8 = (LPIT8) hIT8;
LPKEYVALUE p, tmp;
int n;
const char **Props;
LPTABLE t = GetTable(it8);
if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
*SubpropertyNames = 0;
return 0;
}
// Pass#1 - count properties
n = 0;
for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) {
if(tmp->Subkey != NULL)
n++;
}
Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
// Pass#2 - Fill pointers
n = 0;
for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) {
if(tmp->Subkey != NULL)
Props[n++] = p ->Subkey;
}
*SubpropertyNames = Props;
return n;
}
static
int LocatePatch(LPIT8 it8, const char* cPatch)
{
......@@ -2201,7 +2530,7 @@ double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE hIT8, int row, int col)
}
BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val)
LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val)
{
LPIT8 it8 = (LPIT8) hIT8;
......@@ -2209,7 +2538,7 @@ BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const cha
}
BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val)
LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val)
{
LPIT8 it8 = (LPIT8) hIT8;
char Buff[256];
......@@ -2260,7 +2589,7 @@ double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE it8, const char* cPatch, const cha
BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
const char* cSample,
const char *Val)
{
......@@ -2305,18 +2634,19 @@ BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
}
BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
const char* cSample,
double Val)
{
LPIT8 it8 = (LPIT8) hIT8;
char Buff[256];
sprintf(Buff, it8->DoubleFormatter, Val);
snprintf(Buff, 255, it8->DoubleFormatter, Val);
return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
}
// Buffer should get MAXSTR at least
const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer)
{
......@@ -2327,10 +2657,16 @@ const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buf
if (!Data) return NULL;
if (!buffer) return Data;
strcpy(buffer, Data);
strncpy(buffer, Data, MAXSTR-1);
buffer[MAXSTR-1] = 0;
return buffer;
}
int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch)
{
return LocatePatch((LPIT8)hIT8, cPatch);
}
int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8)
{
LPIT8 it8 = (LPIT8) hIT8;
......@@ -2356,7 +2692,7 @@ int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const ch
cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
if (!cLabelFld) return -1;
if (sscanf(cLabelFld, "%s %d %s", Label, &nTable, Type) != 3)
if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3)
return -1;
if (ExpectedType != NULL && *ExpectedType == 0)
......@@ -2371,6 +2707,19 @@ int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const ch
}
LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample)
{
LPIT8 it8 = (LPIT8) hIT8;
int pos = LocateSample(it8, cSample);
if(pos == -1)
return FALSE;
it8->Tab[it8->nTable].SampleID = pos;
return TRUE;
}
void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter)
{
LPIT8 it8 = (LPIT8) hIT8;
......@@ -2380,3 +2729,4 @@ void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter)
else
strcpy(it8->DoubleFormatter, Formatter);
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -256,7 +256,7 @@ void ComputeBlackPointCompensationFactors(LPcmsCIEXYZ BlackPointIn,
// Return TRUE if both m and of are empy -- "m" being identity and "of" being 0
static
BOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of)
LCMSBOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of)
{
WVEC3 wv0;
......@@ -661,3 +661,6 @@ int cmsChooseCnvrt(int Absolute,
return rc;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -57,6 +57,7 @@
// errors.
void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...);
int LCMSEXPORT cmsErrorAction(int lAbort);
void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn);
......@@ -96,7 +97,7 @@ void cmsSignalError(int ErrorCode, const char *ErrorText, ...)
char Buffer[1024];
vsprintf(Buffer, ErrorText, args);
vsnprintf(Buffer, 1023, ErrorText, args);
va_end(args);
if (UserErrorHandler(ErrorCode, Buffer)) {
......@@ -118,8 +119,8 @@ void cmsSignalError(int ErrorCode, const char *ErrorText, ...)
char Buffer1[1024];
char Buffer2[256];
sprintf(Buffer1, "Error #%x; ", ErrorCode);
vsprintf(Buffer2, ErrorText, args);
snprintf(Buffer1, 767, "Error #%x; ", ErrorCode);
vsnprintf(Buffer2, 255, ErrorText, args);
strcat(Buffer1, Buffer2);
MessageBox(NULL, Buffer1, "Little cms",
MB_OK|MB_ICONSTOP|MB_TASKMODAL);
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -63,9 +63,9 @@ LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma
LPGAMMATABLE LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[]);
LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma);
LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints);
BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
BOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints);
LCMSBOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints);
// Sampled curves
......@@ -74,7 +74,7 @@ LPSAMPLEDCURVE cdecl cmsAllocSampledCurve(int nItems);
void cdecl cmsFreeSampledCurve(LPSAMPLEDCURVE p);
void cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
void cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
BOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
LCMSBOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
void cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
......@@ -84,7 +84,6 @@ double LCMSEXPORT cmsEstimateGammaEx(LPWORD GammaTable, int nEntries, double The
// ----------------------------------------------------------------------------------------
// #define DEBUG 1
#define MAX_KNOTS 4096
typedef float vec[MAX_KNOTS+1];
......@@ -144,14 +143,14 @@ LPGAMMATABLE LCMSEXPORT cmsAllocGamma(int nEntries)
LPGAMMATABLE p;
size_t size;
if (nEntries > 65530) {
cmsSignalError(LCMS_ERRC_WARNING, "Couldn't create gammatable of more than 65530 entries; 65530 assumed");
nEntries = 65530;
if (nEntries > 65530 || nEntries <= 0) {
cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't create gammatable of more than 65530 entries");
return NULL;
}
size = sizeof(GAMMATABLE) + (sizeof(WORD) * (nEntries-1));
p = (LPGAMMATABLE) malloc(size);
p = (LPGAMMATABLE) _cmsMalloc(size);
if (!p) return NULL;
ZeroMemory(p, size);
......@@ -164,7 +163,7 @@ LPGAMMATABLE LCMSEXPORT cmsAllocGamma(int nEntries)
void LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma)
{
if (Gamma) free(Gamma);
if (Gamma) _cmsFree(Gamma);
}
......@@ -278,6 +277,15 @@ LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma
LPWORD InPtr;
LPGAMMATABLE p;
// Try to reverse it analytically whatever possible
if (InGamma -> Seed.Type > 0 && InGamma -> Seed.Type <= 5 &&
_cmsCrc32OfGammaTable(InGamma) == InGamma -> Seed.Crc32) {
return cmsBuildParametricGamma(nResultSamples, -(InGamma -> Seed.Type), InGamma ->Seed.Params);
}
// Nope, reverse the table
p = cmsAllocGamma(nResultSamples);
if (!p) return NULL;
......@@ -528,7 +536,7 @@ void smooth2(vec w, vec y, vec z, float lambda, int m)
// Smooths a curve sampled at regular intervals
BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda)
LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda)
{
vec w, y, z;
......@@ -640,13 +648,13 @@ LPSAMPLEDCURVE cmsAllocSampledCurve(int nItems)
{
LPSAMPLEDCURVE pOut;
pOut = (LPSAMPLEDCURVE) malloc(sizeof(SAMPLEDCURVE));
pOut = (LPSAMPLEDCURVE) _cmsMalloc(sizeof(SAMPLEDCURVE));
if (pOut == NULL)
return NULL;
if((pOut->Values = (double *) malloc(nItems * sizeof(double))) == NULL)
if((pOut->Values = (double *) _cmsMalloc(nItems * sizeof(double))) == NULL)
{
free(pOut);
_cmsFree(pOut);
return NULL;
}
......@@ -659,8 +667,8 @@ LPSAMPLEDCURVE cmsAllocSampledCurve(int nItems)
void cmsFreeSampledCurve(LPSAMPLEDCURVE p)
{
free((LPVOID) p -> Values);
free((LPVOID) p);
_cmsFree((LPVOID) p -> Values);
_cmsFree((LPVOID) p);
}
......@@ -731,7 +739,7 @@ void cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max)
// Smooths a curve sampled at regular intervals
BOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda)
LCMSBOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda)
{
vec w, y, z;
int i, nItems;
......@@ -915,14 +923,11 @@ LPSAMPLEDCURVE cmsConvertGammaToSampledCurve(LPGAMMATABLE Gamma, int nPoints)
// Smooth endpoints (used in Black/White compensation)
BOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries)
LCMSBOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries)
{
vec w, y, z;
int i, Zeros, Poles;
#ifdef DEBUG
ASAVE(Table, nEntries, "nonsmt.txt");
#endif
if (cmsIsLinear(Table, nEntries)) return FALSE; // Nothing to do
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -66,7 +66,7 @@ to use highlights, then it will be lost.
*/
BOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black,
LCMSBOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black,
int *nOutputs)
{
// Only most common spaces
......@@ -376,7 +376,6 @@ double LCMSEXPORT cmsCIE2000DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2,
double bs = Lab2 ->b;
double Cs = sqrt( Sqr(as) + Sqr(bs) );
double G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) ));
double a_p = (1 + G ) * a1;
......@@ -390,15 +389,21 @@ double LCMSEXPORT cmsCIE2000DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2,
double C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
double h_ps = atan2deg(a_ps, b_ps);
double meanC_p =(C_p + C_ps) / 2;
double hps_plus_hp = h_ps + h_p;
double hps_minus_hp = h_ps - h_p;
double meanC_p =(C_p + C_ps) / 2;
double meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
(hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
(hps_plus_hp - 360)/2;
double meanh_p = fabs(h_ps-h_p) <= 180 ? (h_ps + h_p)/2 : (h_ps+h_p-360)/2;
double delta_h = (hps_minus_hp) <= -180.000001 ? (hps_minus_hp + 360) :
(hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
(hps_minus_hp);
double delta_L = (Ls - L1);
double delta_C = (C_ps - C_p );
double delta_h = fabs(h_p - h_ps) <= 180 ? fabs(h_p - h_ps) : 360 - fabs(h_p - h_ps);
double delta_L = fabs(L1 - Ls);
double delta_C = fabs(C_p - C_ps);
double delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANES(delta_h) / 2);
......@@ -1065,7 +1070,7 @@ void SlopeLimiting(WORD Table[], int nEntries)
// Check for monotonicity.
static
BOOL IsMonotonic(LPGAMMATABLE t)
LCMSBOOL IsMonotonic(LPGAMMATABLE t)
{
int n = t -> nEntries;
int i, last;
......@@ -1088,7 +1093,7 @@ BOOL IsMonotonic(LPGAMMATABLE t)
// Check for endpoints
static
BOOL HasProperEndpoints(LPGAMMATABLE t)
LCMSBOOL HasProperEndpoints(LPGAMMATABLE t)
{
if (t ->GammaTable[0] != 0) return FALSE;
if (t ->GammaTable[t ->nEntries-1] != 0xFFFF) return FALSE;
......@@ -1109,7 +1114,7 @@ void _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransfor
unsigned int t, i, v;
int j;
WORD In[MAXCHANNELS], Out[MAXCHANNELS];
BOOL lIsSuitable;
LCMSBOOL lIsSuitable;
_LPcmsTRANSFORM InputXForm = (_LPcmsTRANSFORM) h[0];
_LPcmsTRANSFORM OutputXForm = (_LPcmsTRANSFORM) h[nTransforms-1];
......@@ -1126,10 +1131,10 @@ void _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransfor
}
// Do nothing on all but RGB to RGB transforms
// Do nothing on all but Gray/RGB to Gray/RGB transforms
if ((InputXForm ->EntryColorSpace != icSigRgbData) ||
(OutputXForm->ExitColorSpace != icSigRgbData)) return;
if (((InputXForm ->EntryColorSpace != icSigRgbData) && (InputXForm ->EntryColorSpace != icSigGrayData)) ||
((OutputXForm->ExitColorSpace != icSigRgbData) && (OutputXForm->ExitColorSpace != icSigGrayData))) return;
for (t = 0; t < Grid -> InputChan; t++)
......@@ -1169,10 +1174,13 @@ void _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransfor
if (!HasProperEndpoints(Trans[t]))
lIsSuitable = FALSE;
/*
// Exclude if transfer function is not smooth enough
// to be modelled as a gamma function, or the gamma is reversed
if (cmsEstimateGamma(Trans[t]) < 1.0)
lIsSuitable = FALSE;
*/
}
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -282,7 +282,7 @@ void Eval8Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS
// Fills optimization parameters
void cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
BOOL lUseTetrahedral, LPL16PARAMS p)
LCMSBOOL lUseTetrahedral, LPL16PARAMS p)
{
int clutPoints;
......@@ -579,7 +579,7 @@ WORD cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p)
// Identify if value fall downto 0 or FFFF zone
if (Value == 0) return 0;
if (Value == 0xFFFF) return 0xFFFF;
// if (Value == 0xFFFF) return 0xFFFF;
// else restrict to valid zone
......@@ -631,7 +631,7 @@ WORD cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p)
a = (y1 - y0) / (x1 - x0);
b = y0 - a * x0;
if (a == 0) return (WORD) x;
if (fabs(a) < 0.01) return (WORD) x;
f = ((Value - b) / a);
......@@ -763,7 +763,7 @@ void cmsTrilinearInterp16(WORD Input[], WORD Output[],
X0 = p -> opta3 * x0;
X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
Y0 = p -> opta2 * y0;
Y0 = p -> opta2 * y0;
Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
Z0 = p -> opta1 * z0;
......@@ -942,7 +942,7 @@ void cmsTetrahedralInterp16(WORD Input[],
X0 = p -> opta3 * x0;
X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
Y0 = p -> opta2 * y0;
Y0 = p -> opta2 * y0;
Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
Z0 = p -> opta1 * z0;
......@@ -1009,11 +1009,11 @@ void cmsTetrahedralInterp16(WORD Input[],
Rest = c1 * rx + c2 * ry + c3 * rz;
// There is a lot of math hidden in this expression. The rest is in fixed domain
// and the result in 0..ffff domain. So the complete expression should be
// ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF
// There is a lot of math hidden in this expression. The rest is in fixed domain
// and the result in 0..ffff domain. So the complete expression should be
// ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF
Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF));
Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF));
}
......@@ -1131,3 +1131,4 @@ void cmsTetrahedralInterp8(WORD Input[],
}
#undef DENS
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -62,7 +62,7 @@
typedef struct {
LPBYTE Block; // Points to allocated memory
size_t Size; // Size of allocated memory
int Pointer; // Points to current location
size_t Pointer; // Points to current location
int FreeBlockOnClose; // As title
} FILEMEM;
......@@ -70,18 +70,19 @@ typedef struct {
static
LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode)
{
FILEMEM* fm = (FILEMEM*) malloc(sizeof(FILEMEM));
FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM));
if (fm == NULL) return NULL;
ZeroMemory(fm, sizeof(FILEMEM));
if (Mode == 'r') {
fm ->Block = (LPBYTE) malloc(Size);
fm ->Block = (LPBYTE) _cmsMalloc(Size);
if (fm ->Block == NULL) {
free(fm);
_cmsFree(fm);
return NULL;
}
CopyMemory(fm->Block, Block, Size);
fm ->FreeBlockOnClose = TRUE;
}
......@@ -103,13 +104,27 @@ size_t MemoryRead(LPVOID buffer, size_t size, size_t count, struct _lcms_iccprof
FILEMEM* ResData = (FILEMEM*) Icc ->stream;
LPBYTE Ptr;
size_t len = size * count;
size_t extent = ResData -> Pointer + len;
if (len == 0) {
return 0;
}
if (len / size != count) {
cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size.");
return 0;
}
if (ResData -> Pointer + len > ResData -> Size){
if (extent < len || extent < ResData -> Pointer) {
cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len.");
return 0;
}
len = (ResData -> Size - ResData -> Pointer);
cmsSignalError(LCMS_ERRC_WARNING, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
if (ResData -> Pointer + len > ResData -> Size) {
len = (ResData -> Size - ResData -> Pointer);
cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
return 0;
}
Ptr = ResData -> Block;
......@@ -123,7 +138,7 @@ size_t MemoryRead(LPVOID buffer, size_t size, size_t count, struct _lcms_iccprof
// SEEK_CUR is assumed
static
BOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
{
FILEMEM* ResData = (FILEMEM*) Icc ->stream;
......@@ -147,18 +162,19 @@ size_t MemoryTell(struct _lcms_iccprofile_struct* Icc)
}
// Writes data to memory, also keeps used space for further reference
// Writes data to memory, also keeps used space for further reference. NO CHECK IS PERFORMED
static
BOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
LCMSBOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
{
FILEMEM* ResData = (FILEMEM*) Icc ->stream;
if (size == 0) return TRUE;
if (ResData != NULL)
CopyMemory(ResData ->Block + Icc ->UsedSpace, Ptr, size);
CopyMemory(ResData ->Block + ResData ->Pointer, Ptr, size);
ResData->Pointer += size;
Icc->UsedSpace += size;
return TRUE;
......@@ -166,15 +182,37 @@ BOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
static
BOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
LCMSBOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
{
FILEMEM* ResData = (FILEMEM*) Icc->stream;
void* newBlock = NULL;
/* Follow same policies as functions in lcms.h */
if (ResData->Size + size < 0) return NULL;
if (ResData->Size + size > ((size_t)1024*1024*500)) return NULL;
newBlock = realloc(ResData->Block, ResData->Size + size);
if (!newBlock) {
return FALSE;
}
ResData->Block = newBlock;
ResData->Size += size;
return TRUE;
}
static
LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
{
FILEMEM* ResData = (FILEMEM*) Icc ->stream;
if (ResData ->FreeBlockOnClose) {
if (ResData ->Block) free(ResData ->Block);
if (ResData ->Block) _cmsFree(ResData ->Block);
}
free(ResData);
_cmsFree(ResData);
return 0;
}
......@@ -192,7 +230,7 @@ size_t FileRead(void *buffer, size_t size, size_t count, struct _lcms_iccprofile
{
size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream);
if (nReaded != count) {
cmsSignalError(LCMS_ERRC_WARNING, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
return 0;
}
......@@ -201,7 +239,7 @@ size_t FileRead(void *buffer, size_t size, size_t count, struct _lcms_iccprofile
static
BOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
{
if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) {
......@@ -223,7 +261,7 @@ size_t FileTell(struct _lcms_iccprofile_struct* Icc)
static
BOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
LCMSBOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
{
if (size == 0) return TRUE;
......@@ -239,7 +277,14 @@ BOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
static
BOOL FileClose(struct _lcms_iccprofile_struct* Icc)
LCMSBOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
{
return TRUE;
}
static
LCMSBOOL FileClose(struct _lcms_iccprofile_struct* Icc)
{
return fclose((FILE*) Icc ->stream);
}
......@@ -252,7 +297,7 @@ BOOL FileClose(struct _lcms_iccprofile_struct* Icc)
cmsHPROFILE _cmsCreateProfilePlaceholder(void)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) malloc(sizeof(LCMSICCPROFILE));
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE));
if (Icc == NULL) return NULL;
// Empty values
......@@ -290,7 +335,7 @@ icTagSignature LCMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, icInt32Number
// Search for a specific tag in tag dictionary
// Returns position or -1 if tag not found
icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError)
icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError)
{
icInt32Number i;
......@@ -311,7 +356,7 @@ icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL l
// Check existance
BOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
return _cmsSearchTag(Icc, sig, FALSE) >= 0;
......@@ -330,7 +375,7 @@ LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const
if (i >=0) {
if (Icc -> TagPtrs[i]) free(Icc -> TagPtrs[i]);
if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]);
}
else {
......@@ -341,11 +386,14 @@ LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const
cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG);
Icc ->TagCount = MAX_TABLE_TAG-1;
return NULL;
}
}
Ptr = malloc(size);
Ptr = _cmsMalloc(size);
if (Ptr == NULL) return NULL;
CopyMemory(Ptr, Init, size);
Icc ->TagNames[i] = sig;
......@@ -376,12 +424,15 @@ LPLCMSICCPROFILE _cmsCreateProfileFromFilePlaceholder(const char* FileName)
if (NewIcc == NULL) return NULL;
strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1);
NewIcc -> PhysicalFile[MAX_PATH-1] = 0;
NewIcc ->stream = ICCfile;
NewIcc ->Read = FileRead;
NewIcc ->Seek = FileSeek;
NewIcc ->Tell = FileTell;
NewIcc ->Close = FileClose;
NewIcc ->Grow = FileGrow;
NewIcc ->Write = NULL;
NewIcc ->IsWrite = FALSE;
......@@ -419,7 +470,8 @@ LPLCMSICCPROFILE _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize
NewIcc ->Seek = MemorySeek;
NewIcc ->Tell = MemoryTell;
NewIcc ->Close = MemoryClose;
NewIcc ->Write = NULL;
NewIcc ->Grow = MemoryGrow;
NewIcc ->Write = MemoryWrite;
NewIcc ->IsWrite = FALSE;
......@@ -476,7 +528,7 @@ void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize)
BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
*Dest = Icc -> MediaWhitePoint;
......@@ -484,14 +536,14 @@ BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
}
BOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
*Dest = Icc -> MediaBlackPoint;
return TRUE;
}
BOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
*Dest = Icc -> Illuminant;
......@@ -549,7 +601,7 @@ void LCMSEXPORT cmsSetProfileID(cmsHPROFILE hProfile, LPBYTE ProfileID)
}
BOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
CopyMemory(Dest, &Icc ->Created, sizeof(struct tm));
......@@ -570,23 +622,18 @@ void LCMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, icColorSpaceSignature pcs)
Icc -> PCS = pcs;
}
icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
return Icc -> ColorSpace;
}
void LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
Icc -> ColorSpace = sig;
}
icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
......@@ -599,7 +646,6 @@ DWORD LCMSEXPORT cmsGetProfileICCversion(cmsHPROFILE hProfile)
return (DWORD) Icc -> Version;
}
void LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
......@@ -638,7 +684,7 @@ LPVOID DupBlock(LPLCMSICCPROFILE Icc, LPVOID Block, size_t size)
// This is tricky, since LUT structs does have pointers
BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
LPLUT Orig, Stored;
......@@ -666,7 +712,7 @@ BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const vo
}
BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -675,7 +721,7 @@ BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cm
}
BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -683,7 +729,7 @@ BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const c
return TRUE;
}
BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -692,7 +738,7 @@ BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMM
}
BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -701,7 +747,7 @@ BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig,
}
BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -711,28 +757,40 @@ BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignatu
}
BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
_cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
return FALSE;
return TRUE;
}
BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
_cmsInitTag(Icc, sig, sizeof(struct tm), DateTime);
return FALSE;
return TRUE;
}
BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
_cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
return FALSE;
return TRUE;
}
LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
_cmsInitTag(Icc, sig, 3*sizeof(cmsCIEXYZ), mat);
return TRUE;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -149,6 +149,7 @@ void AdjustEndianessArray16(LPWORD p, size_t num_words)
#endif
// Transports to properly encoded values - note that icc profiles does use
// big endian notation.
......@@ -216,7 +217,8 @@ icTagTypeSignature ReadBase(LPLCMSICCPROFILE Icc)
{
icTagBase Base;
Icc -> Read(&Base, sizeof(icTagBase), 1, Icc);
if (Icc -> Read(&Base, sizeof(icTagBase), 1, Icc) != 1)
return (icTagTypeSignature) 0;
AdjustEndianess32((LPBYTE) &Base.sig);
return Base.sig;
......@@ -288,13 +290,15 @@ void EvalCHRM(LPcmsCIEXYZ Dest, LPMAT3 Chrm, LPcmsCIEXYZ Src)
// Read profile header and validate it
static
LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, LCMSBOOL lIsFromMemory)
{
icTag Tag;
icHeader Header;
icInt32Number TagCount, i;
icUInt32Number extent;
Icc -> Read(&Header, sizeof(icHeader), 1, Icc);
if (Icc -> Read(&Header, sizeof(icHeader), 1, Icc) != 1)
goto ErrorCleanup;
// Convert endian
......@@ -306,14 +310,13 @@ LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
AdjustEndianess32((LPBYTE) &Header.pcs);
AdjustEndianess32((LPBYTE) &Header.magic);
AdjustEndianess32((LPBYTE) &Header.flags);
AdjustEndianess32((LPBYTE) &Header.attributes[0]);
AdjustEndianess32((LPBYTE) &Header.attributes[0]);
AdjustEndianess32((LPBYTE) &Header.renderingIntent);
// Validate it
if (Header.magic != icMagicNumber) goto ErrorCleanup;
if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1)
goto ErrorCleanup;
......@@ -324,7 +327,7 @@ LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
Icc -> PCS = Header.pcs;
Icc -> RenderingIntent = (icRenderingIntent) Header.renderingIntent;
Icc -> flags = Header.flags;
Icc -> attributes = Header.attributes[0];
Icc -> attributes = Header.attributes[0];
Icc -> Illuminant.X = Convert15Fixed16(Header.illuminant.X);
Icc -> Illuminant.Y = Convert15Fixed16(Header.illuminant.Y);
Icc -> Illuminant.Z = Convert15Fixed16(Header.illuminant.Z);
......@@ -348,7 +351,7 @@ LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
// Read tag directory
if (TagCount > MAX_TABLE_TAG) {
if (TagCount > MAX_TABLE_TAG || TagCount < 0) {
cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount);
goto ErrorCleanup;
......@@ -357,12 +360,18 @@ LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory)
Icc -> TagCount = TagCount;
for (i=0; i < TagCount; i++) {
Icc ->Read(&Tag, sizeof(icTag), 1, Icc);
if (Icc ->Read(&Tag, sizeof(icTag), 1, Icc) != 1)
goto ErrorCleanup;
AdjustEndianess32((LPBYTE) &Tag.offset);
AdjustEndianess32((LPBYTE) &Tag.size);
AdjustEndianess32((LPBYTE) &Tag.sig); // Signature
// Perform some sanity check. Offset + size should fall inside file.
extent = Tag.offset + Tag.size;
if (extent > Header.size || extent < Tag.offset)
goto ErrorCleanup;
Icc -> TagNames[i] = Tag.sig;
Icc -> TagOffsets[i] = Tag.offset;
Icc -> TagSizes[i] = Tag.size;
......@@ -381,13 +390,10 @@ ErrorCleanup:
cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile);
free(Icc);
_cmsFree(Icc);
return NULL;
}
static
unsigned int uipow(unsigned int a, unsigned int b) {
unsigned int rv = 1;
......@@ -497,7 +503,7 @@ void FixLUT8bothSides(LPLUT Lut, size_t nTabSize)
// The infamous LUT 8
static
void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
{
icLut8 LUT8;
LPBYTE Temp;
......@@ -506,7 +512,7 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
unsigned int AllLinear;
LPWORD PtrW;
Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc);
if (Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return FALSE;
NewLUT -> wFlags = LUT_HASTL1|LUT_HASTL2|LUT_HAS3DGRID;
NewLUT -> cLutPoints = LUT8.clutPoints;
......@@ -515,6 +521,10 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
NewLUT -> InputEntries = 256;
NewLUT -> OutputEntries = 256;
// Do some checking
if (!_cmsValidateLUT(NewLUT)) {
return FALSE;
}
AdjustEndianess32((LPBYTE) &LUT8.e00);
AdjustEndianess32((LPBYTE) &LUT8.e01);
......@@ -550,13 +560,24 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
// Copy input tables
Temp = (LPBYTE) malloc(256);
Temp = (LPBYTE) _cmsMalloc(256);
if (Temp == NULL) return FALSE;
AllLinear = 0;
for (i=0; i < NewLUT -> InputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * 256);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
if (PtrW == NULL) {
_cmsFree(Temp);
return FALSE;
}
NewLUT -> L1[i] = PtrW;
Icc ->Read(Temp, 1, 256, Icc);
if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
_cmsFree(Temp);
return FALSE;
}
for (j=0; j < 256; j++)
PtrW[j] = TO16_TAB(Temp[j]);
AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
......@@ -569,7 +590,7 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
NewLUT -> wFlags &= ~LUT_HASTL1;
}
free(Temp);
_cmsFree(Temp);
// Copy 3D CLUT
......@@ -578,9 +599,20 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
if (nTabSize > 0) {
PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize);
Temp = (LPBYTE) malloc(nTabSize);
Icc ->Read(Temp, 1, nTabSize, Icc);
PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
if (PtrW == NULL) return FALSE;
Temp = (LPBYTE) _cmsMalloc(nTabSize);
if (Temp == NULL) {
_cmsFree(PtrW);
return FALSE;
}
if (Icc ->Read(Temp, 1, nTabSize, Icc) != nTabSize) {
_cmsFree(Temp);
_cmsFree(PtrW);
return FALSE;
}
NewLUT -> T = PtrW;
NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
......@@ -589,25 +621,37 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
*PtrW++ = TO16_TAB(Temp[i]);
}
free(Temp);
_cmsFree(Temp);
}
else {
NewLUT ->T = NULL;
NewLUT ->Tsize = 0;
NewLUT -> wFlags &= ~LUT_HAS3DGRID;
NewLUT ->wFlags &= ~LUT_HAS3DGRID;
}
// Copy output tables
Temp = (LPBYTE) malloc(256);
Temp = (LPBYTE) _cmsMalloc(256);
if (Temp == NULL) {
return FALSE;
}
AllLinear = 0;
for (i=0; i < NewLUT -> OutputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * 256);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
if (PtrW == NULL) {
_cmsFree(Temp);
return FALSE;
}
NewLUT -> L2[i] = PtrW;
Icc ->Read(Temp, 1, 256, Icc);
if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
_cmsFree(Temp);
return FALSE;
}
for (j=0; j < 256; j++)
PtrW[j] = TO16_TAB(Temp[j]);
AllLinear += cmsIsLinear(NewLUT -> L2[i], 256);
......@@ -621,7 +665,7 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
}
free(Temp);
_cmsFree(Temp);
cmsCalcL16Params(NewLUT -> InputEntries, &NewLUT -> In16params);
cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params);
......@@ -646,6 +690,15 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
// some profiles does claim to do that. Poor lcms will try
// to detect such condition and fix up "on the fly".
switch (sig) {
case icSigBToA0Tag:
case icSigBToA1Tag:
case icSigBToA2Tag:
case icSigGamutTag:
case icSigPreview0Tag:
case icSigPreview1Tag:
case icSigPreview2Tag:
{
LPWORD WhiteLab, ExpectedWhite;
WORD WhiteFixed[MAXCHANNELS], WhiteUnfixed[MAXCHANNELS];
......@@ -685,9 +738,13 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
}
}
break;
default:;
}
}
return TRUE;
}
......@@ -696,7 +753,7 @@ void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
// Case LUT 16
static
void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
LCMSBOOL ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
{
icLut16 LUT16;
size_t nTabSize;
......@@ -705,7 +762,8 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
LPWORD PtrW;
Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc);
if (Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc) != 1)
return FALSE;
NewLUT -> wFlags = LUT_HASTL1 | LUT_HASTL2 | LUT_HAS3DGRID;
NewLUT -> cLutPoints = LUT16.clutPoints;
......@@ -718,6 +776,9 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
NewLUT -> InputEntries = LUT16.inputEnt;
NewLUT -> OutputEntries = LUT16.outputEnt;
if (!_cmsValidateLUT(NewLUT)) {
return FALSE;
}
// Matrix handling
......@@ -754,9 +815,14 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
AllLinear = 0;
for (i=0; i < NewLUT -> InputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
if (PtrW == NULL) return FALSE;
NewLUT -> L1[i] = PtrW;
Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc);
if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc) != NewLUT -> InputEntries) {
return FALSE;
}
AdjustEndianessArray16(PtrW, NewLUT -> InputEntries);
AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
}
......@@ -775,12 +841,17 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
NewLUT->InputChan));
if (nTabSize > 0) {
PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize);
PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
if (PtrW == NULL)
return FALSE;
NewLUT -> T = PtrW;
NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc);
if (Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc) != nTabSize) {
return FALSE;
}
AdjustEndianessArray16(NewLUT -> T, nTabSize);
}
else {
......@@ -794,9 +865,16 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
AllLinear = 0;
for (i=0; i < NewLUT -> OutputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
if (PtrW == NULL) {
return FALSE;
}
NewLUT -> L2[i] = PtrW;
Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc);
if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc) != NewLUT -> OutputEntries) {
return FALSE;
}
AdjustEndianessArray16(PtrW, NewLUT -> OutputEntries);
AllLinear += cmsIsLinear(NewLUT -> L2[i], NewLUT -> OutputEntries);
}
......@@ -814,6 +892,8 @@ void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
cmsCalcCLUT16Params(NewLUT -> cLutPoints, NewLUT -> InputChan,
NewLUT -> OutputChan,
&NewLUT -> CLut16params);
return TRUE;
}
......@@ -830,17 +910,15 @@ LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE Icc)
BaseType = ReadBase(Icc);
switch (BaseType) {
case 0x9478ee00L: // Monaco 2 profiler is BROKEN!
case ((icTagTypeSignature) 0x9478ee00): // Monaco 2 profiler is BROKEN!
case icSigCurveType:
Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
AdjustEndianess32((LPBYTE) &Count);
switch (Count) {
case 0: // Linear.
......@@ -855,7 +933,7 @@ LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE Icc)
{
WORD SingleGammaFixed;
Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc);
if (Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
AdjustEndianess16((LPBYTE) &SingleGammaFixed);
return cmsBuildGamma(4096, Convert8Fixed8(SingleGammaFixed));
}
......@@ -865,10 +943,9 @@ LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE Icc)
NewGamma = cmsAllocGamma(Count);
if (!NewGamma) return NULL;
Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc);
if (Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
return NULL;
AdjustEndianessArray16(NewGamma -> GammaTable, Count);
return NewGamma;
}
}
......@@ -885,11 +962,11 @@ LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE Icc)
icUInt16Number Type;
int i;
Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc);
Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc);
if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
AdjustEndianess16((LPBYTE) &Type);
if (Type > 5) {
if (Type > 4) {
cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
return NULL;
......@@ -900,7 +977,7 @@ LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE Icc)
for (i=0; i < n; i++) {
Num = 0;
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
Params[i] = Convert15Fixed16(Num);
}
......@@ -938,7 +1015,7 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
case 0x9478ee00L: // Monaco 2 profiler is BROKEN!
case icSigCurveType:
Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc);
if (Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
AdjustEndianess32((LPBYTE) &Count);
......@@ -948,6 +1025,7 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
NewGamma = cmsAllocGamma(2);
if (!NewGamma) return NULL;
NewGamma -> GammaTable[0] = 0;
NewGamma -> GammaTable[1] = 0xFFFF;
return NewGamma;
......@@ -955,7 +1033,7 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
case 1: {
WORD SingleGammaFixed;
Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc);
if (Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
AdjustEndianess16((LPBYTE) &SingleGammaFixed);
return cmsBuildGamma(4096, 1./Convert8Fixed8(SingleGammaFixed));
}
......@@ -965,7 +1043,8 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
NewGamma = cmsAllocGamma(Count);
if (!NewGamma) return NULL;
Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc);
if (Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
return NULL;
AdjustEndianessArray16(NewGamma -> GammaTable, Count);
......@@ -992,11 +1071,11 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
int i;
Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc);
Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc);
if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
AdjustEndianess16((LPBYTE) &Type);
if (Type > 5) {
if (Type > 4) {
cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
return NULL;
......@@ -1006,7 +1085,7 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
n = ParamsByType[Type];
for (i=0; i < n; i++) {
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
Params[i] = Convert15Fixed16(Num);
}
......@@ -1028,7 +1107,7 @@ LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
// V4 stuff. Read matrix for LutAtoB and LutBtoA
static
BOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags)
LCMSBOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags)
{
icS15Fixed16Number All[12];
......@@ -1038,7 +1117,8 @@ BOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD d
if (Icc -> Seek(Icc, Offset)) return FALSE;
Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc);
if (Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc) != 12)
return FALSE;
for (i=0; i < 12; i++)
AdjustEndianess32((LPBYTE) &All[i]);
......@@ -1067,17 +1147,26 @@ BOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD d
// V4 stuff. Read CLUT part for LutAtoB and LutBtoA
static
BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
LCMSBOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
{
unsigned int j;
icCLutStruct CLUT;
if (Icc -> Seek(Icc, Offset)) return FALSE;
Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc);
if (Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc) != 1) return FALSE;
cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan,
NewLUT ->OutputChan);
for (j=1; j < NewLUT ->InputChan; j++) {
if (CLUT.gridPoints[0] != CLUT.gridPoints[j]) {
cmsSignalError(LCMS_ERRC_ABORTED, "CLUT with different granulatity is currently unsupported.");
return FALSE;
}
}
if (cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan,
NewLUT ->OutputChan) == NULL) return FALSE;
// Precission can be 1 or 2 bytes
......@@ -1087,7 +1176,7 @@ BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
unsigned int i;
for (i=0; i < NewLUT->Tsize / sizeof(WORD); i++) {
Icc ->Read(&v, sizeof(BYTE), 1, Icc);
if (Icc ->Read(&v, sizeof(BYTE), 1, Icc) != 1) return FALSE;
NewLUT->T[i] = TO16_TAB(v);
}
......@@ -1095,10 +1184,10 @@ BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
else
if (CLUT.prec == 2) {
Icc ->Read(NewLUT ->T, sizeof(WORD),
NewLUT->Tsize / sizeof(WORD), Icc);
size_t n = NewLUT->Tsize / sizeof(WORD);
AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD));
if (Icc ->Read(NewLUT ->T, sizeof(WORD), n, Icc) != n) return FALSE;
AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD));
}
else {
cmsSignalError(LCMS_ERRC_ABORTED, "Unknow precission of '%d'", CLUT.prec);
......@@ -1109,6 +1198,22 @@ BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
}
static
void ResampleCurves(LPGAMMATABLE Curves[], int nCurves)
{
int i;
LPSAMPLEDCURVE sc;
for (i=0; i < nCurves; i++) {
sc = cmsConvertGammaToSampledCurve(Curves[i], 4096);
cmsFreeGamma(Curves[i]);
Curves[i] = cmsConvertSampledCurveToGamma(sc, 0xFFFF);
cmsFreeSampledCurve(sc);
}
}
static
void SkipAlignment(LPLCMSICCPROFILE Icc)
{
......@@ -1121,7 +1226,7 @@ void SkipAlignment(LPLCMSICCPROFILE Icc)
// Read a set of curves from specific offset
static
BOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
LCMSBOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
{
LPGAMMATABLE Curves[MAXCHANNELS];
unsigned int i, nCurves;
......@@ -1134,20 +1239,41 @@ BOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLoc
else
nCurves = NewLUT ->OutputChan;
ZeroMemory(Curves, sizeof(Curves));
for (i=0; i < nCurves; i++) {
Curves[i] = ReadCurve(Icc);
if (Curves[i] == NULL) goto Error;
SkipAlignment(Icc);
}
// March-26'08: some V4 profiles may have different sampling
// rates, in this case resample all curves to maximum
for (i=1; i < nCurves; i++) {
if (Curves[i]->nEntries != Curves[0]->nEntries) {
ResampleCurves(Curves, nCurves);
break;
}
}
NewLUT = cmsAllocLinearTable(NewLUT, Curves, nLocation);
if (NewLUT == NULL) goto Error;
for (i=0; i < nCurves; i++)
cmsFreeGamma(Curves[i]);
return TRUE;
Error:
for (i=0; i < nCurves; i++)
if (Curves[i])
cmsFreeGamma(Curves[i]);
return FALSE;
}
// V4 stuff. LutAtoB type
......@@ -1160,22 +1286,28 @@ BOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLoc
// L2 = B curves
static
BOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
LCMSBOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
{
icLutAtoB LUT16;
Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc);
if (Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc) != 1) return FALSE;
NewLUT -> InputChan = LUT16.inputChan;
NewLUT -> OutputChan = LUT16.outputChan;
// Validate the NewLUT here to avoid excessive number of channels
// (leading to stack-based buffer overflow in ReadSetOfCurves).
// Needs revalidation after table size is filled in.
if (!_cmsValidateLUT(NewLUT)) {
return FALSE;
}
AdjustEndianess32((LPBYTE) &LUT16.offsetB);
AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
AdjustEndianess32((LPBYTE) &LUT16.offsetM);
AdjustEndianess32((LPBYTE) &LUT16.offsetC);
AdjustEndianess32((LPBYTE) &LUT16.offsetA);
if (LUT16.offsetB != 0)
ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetB, NewLUT, 2);
......@@ -1220,15 +1352,22 @@ BOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSig
// V4 stuff. LutBtoA type
static
BOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
LCMSBOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
{
icLutBtoA LUT16;
Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc);
if (Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc) != 1) return FALSE;
NewLUT -> InputChan = LUT16.inputChan;
NewLUT -> OutputChan = LUT16.outputChan;
// Validate the NewLUT here to avoid excessive number of channels
// (leading to stack-based buffer overflow in ReadSetOfCurves).
// Needs revalidation after table size is filled in.
if (!_cmsValidateLUT(NewLUT)) {
return FALSE;
}
AdjustEndianess32((LPBYTE) &LUT16.offsetB);
AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
AdjustEndianess32((LPBYTE) &LUT16.offsetM);
......@@ -1242,7 +1381,6 @@ BOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSi
if (LUT16.offsetMat != 0)
ReadMatrixOffset(Icc, BaseOffset + LUT16.offsetMat, NewLUT, LUT_HASMATRIX3);
if (LUT16.offsetM != 0)
ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetM, NewLUT, 3);
......@@ -1294,7 +1432,7 @@ LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig)
// If is in memory, the LUT is already there, so throw a copy
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
return cmsDupLUT((LPLUT) Icc ->TagPtrs[n]);
}
......@@ -1308,8 +1446,8 @@ LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig)
NewLUT = cmsAllocLUT();
if (!NewLUT)
{
if (!NewLUT) {
cmsSignalError(LCMS_ERRC_ABORTED, "cmsAllocLUT() failed");
return NULL;
}
......@@ -1317,11 +1455,29 @@ LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig)
switch (BaseType) {
case icSigLut8Type: ReadLUT8(Icc, NewLUT, sig); break;
case icSigLut16Type: ReadLUT16(Icc, NewLUT); break;
case icSiglutAtoBType: ReadLUT_A2B(Icc, NewLUT, offset, sig); break;
case icSiglutBtoAType: ReadLUT_B2A(Icc, NewLUT, offset, sig); break;
case icSigLut8Type: if (!ReadLUT8(Icc, NewLUT, sig)) {
cmsFreeLUT(NewLUT);
return NULL;
}
break;
case icSigLut16Type: if (!ReadLUT16(Icc, NewLUT)) {
cmsFreeLUT(NewLUT);
return NULL;
}
break;
case icSiglutAtoBType: if (!ReadLUT_A2B(Icc, NewLUT, offset, sig)) {
cmsFreeLUT(NewLUT);
return NULL;
}
break;
case icSiglutBtoAType: if (!ReadLUT_B2A(Icc, NewLUT, offset, sig)) {
cmsFreeLUT(NewLUT);
return NULL;
}
break;
default: cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
cmsFreeLUT(NewLUT);
......@@ -1335,16 +1491,23 @@ LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig)
// Sets the language & country preferences. Used only in ICC 4.0 profiles
void LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode)
void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4])
{
GlobalLanguageCode = LanguageCode;
GlobalCountryCode = CountryCode;
int LanguageCodeInt = *(int *) LanguageCode;
int CountryCodeInt = *(int *) CountryCode;
AdjustEndianess32((LPBYTE) &LanguageCodeInt);
AdjustEndianess32((LPBYTE) &CountryCodeInt);
GlobalLanguageCode = LanguageCodeInt;
GlobalCountryCode = CountryCodeInt;
}
// Some tags (e.g, 'pseq') can have text tags embedded. This function
// handles such special case.
// handles such special case. Returns -1 on error, or the number of bytes left on success.
static
int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t size_max)
......@@ -1353,7 +1516,6 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
BaseType = ReadBase(Icc);
size -= sizeof(icTagBase);
switch (BaseType) {
......@@ -1365,50 +1527,54 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
icUInt16Number ScriptCodeCode, Dummy;
icUInt8Number ScriptCodeCount;
Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
if (size < sizeof(icUInt32Number)) return (int) size;
if (size < sizeof(icUInt32Number)) return (int) size;
size -= sizeof(icUInt32Number);
AdjustEndianess32((LPBYTE) &AsciiCount);
Icc ->Read(Name, 1,
(AsciiCount >= size_max) ? (size_max-1) : AsciiCount, Icc);
if (size < AsciiCount) return (int) size;
if (size < AsciiCount) return (int) size;
size -= AsciiCount;
// Skip Unicode code
Icc ->Read(&UnicodeCode, sizeof(icUInt32Number), 1, Icc);
if (size < sizeof(icUInt32Number)) return (int) size;
if (Icc ->Read(&UnicodeCode, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
if (size < sizeof(icUInt32Number)) return (int) size;
size -= sizeof(icUInt32Number);
Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc);
if (size < sizeof(icUInt32Number)) return (int) size;
if (Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
if (size < sizeof(icUInt32Number)) return (int) size;
size -= sizeof(icUInt32Number);
AdjustEndianess32((LPBYTE) &UnicodeCount);
if (UnicodeCount > size) return (int) size;
for (i=0; i < UnicodeCount; i++)
Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc);
size -= UnicodeCount * sizeof(icUInt16Number);
for (i=0; i < UnicodeCount; i++) {
size_t nread = Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc);
if (nread != 1) return (int) size;
size -= sizeof(icUInt16Number);
}
// Skip ScriptCode code
Icc ->Read(&ScriptCodeCode, sizeof(icUInt16Number), 1, Icc);
if (Icc ->Read(&ScriptCodeCode, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
size -= sizeof(icUInt16Number);
Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc);
if (Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc) != 1) return -1;
size -= sizeof(icUInt8Number);
if (size < 67) return (int) size;
// Should remain 67 bytes as filler
for (i=0; i < 67; i++)
Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc);
if (size < 67) return (int) size;
size -= 67;
for (i=0; i < 67; i++) {
size_t nread = Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc);
if (nread != 1) return (int) size;
size --;
}
}
break;
......@@ -1425,7 +1591,7 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
size = size_max - 1;
}
Icc -> Read(Name, 1, size, Icc);
if (Icc -> Read(Name, 1, size, Icc) != size) return -1;
for (i=0; i < Missing; i++)
Icc -> Read(&Dummy, 1, 1, Icc);
......@@ -1445,9 +1611,9 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
wchar_t* wchar = L"";
Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
AdjustEndianess32((LPBYTE) &Count);
Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
AdjustEndianess32((LPBYTE) &RecLen);
if (RecLen != 12) {
......@@ -1458,15 +1624,15 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
for (i=0; i < Count; i++) {
Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc);
if (Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
AdjustEndianess16((LPBYTE) &Language);
Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc);
if (Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
AdjustEndianess16((LPBYTE) &Country);
Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
AdjustEndianess32((LPBYTE) &ThisLen);
Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
AdjustEndianess32((LPBYTE) &ThisOffset);
if (Language == GlobalLanguageCode || Offset == 0) {
......@@ -1492,14 +1658,18 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
for (i=0; i < Offset; i++) {
char Discard;
Icc ->Read(&Discard, 1, 1, Icc);
if (Icc ->Read(&Discard, 1, 1, Icc) != 1) return -1;
}
wchar = (wchar_t*) malloc(Len+2);
// Bound len
if (Len < 0) Len = 0;
if (Len > 20*1024) Len = 20 * 1024;
wchar = (wchar_t*) _cmsMalloc(Len*sizeof(wchar_t)+2);
if (!wchar) return -1;
Icc ->Read(wchar, 1, Len, Icc);
if (Icc ->Read(wchar, 1, Len, Icc) != Len) return -1;
AdjustEndianessArray16((LPWORD) wchar, Len / 2);
wchar[Len / 2] = L'\0';
......@@ -1509,7 +1679,7 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
Name[0] = 0; // Error
}
free((void*) wchar);
_cmsFree((void*) wchar);
}
break;
......@@ -1522,8 +1692,7 @@ int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t si
}
// Take an ASCII item. Takes at most LCMS_DESC_MAX
// Take an ASCII item. Takes at most size_max bytes
int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Name, size_t size_max)
{
......@@ -1535,19 +1704,27 @@ int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *
if (n < 0)
return -1;
if (!Icc -> stream) {
size = Icc -> TagSizes[n];
if (Icc -> TagPtrs[n]) {
if (size > size_max)
size = size_max;
CopyMemory(Name, Icc -> TagPtrs[n], size);
CopyMemory(Name, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
return (int) Icc -> TagSizes[n];
}
offset = Icc -> TagOffsets[n];
size = Icc -> TagSizes[n];
if (Icc -> Seek(Icc, offset))
return -1;
return ReadEmbeddedTextTag(Icc, size, Name, size_max);
if (ReadEmbeddedTextTag(Icc, size, Name, size_max) < 0) return -1;
return size;
}
// Keep compatibility with older versions
......@@ -1561,7 +1738,7 @@ int LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Te
// Take an XYZ item
static
int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, BOOL lIsFatal)
int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, LCMSBOOL lIsFatal)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
icTagTypeSignature BaseType;
......@@ -1573,7 +1750,7 @@ int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, BOOL
if (n < 0)
return -1;
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
CopyMemory(Value, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
return (int) Icc -> TagSizes[n];
......@@ -1628,7 +1805,7 @@ int ReadICCXYZArray(cmsHPROFILE hProfile, icTagSignature sig, LPMAT3 v)
if (n < 0)
return -1; // Not found
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
CopyMemory(v, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
return (int) Icc -> TagSizes[n];
......@@ -1677,7 +1854,7 @@ int ReadICCXYZArray(cmsHPROFILE hProfile, icTagSignature sig, LPMAT3 v)
// Primaries are to be in xyY notation
BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
{
if (ReadICCXYZ(hProfile, icSigRedColorantTag, &Dest -> Red, TRUE) < 0) return FALSE;
if (ReadICCXYZ(hProfile, icSigGreenColorantTag, &Dest -> Green, TRUE) < 0) return FALSE;
......@@ -1687,7 +1864,7 @@ BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
}
BOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
LCMSBOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
{
cmsCIEXYZTRIPLE Primaries;
......@@ -1704,7 +1881,7 @@ BOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
// Always return a suitable matrix
BOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile)
LCMSBOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile)
{
if (ReadICCXYZArray(hProfile, icSigChromaticAdaptationTag, r) < 0) {
......@@ -1741,7 +1918,7 @@ LPGAMMATABLE LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig
if (n < 0)
return NULL;
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
return cmsDupGamma((LPGAMMATABLE) Icc -> TagPtrs[n]);
}
......@@ -1769,7 +1946,7 @@ LPGAMMATABLE LCMSEXPORT cmsReadICCGammaReversed(cmsHPROFILE hProfile, icTagSigna
if (n < 0)
return NULL;
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
return cmsReverseGamma(256, (LPGAMMATABLE) Icc -> TagPtrs[n]);
}
......@@ -1785,7 +1962,7 @@ LPGAMMATABLE LCMSEXPORT cmsReadICCGammaReversed(cmsHPROFILE hProfile, icTagSigna
// Check Named color header
static
BOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2)
LCMSBOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2)
{
if (v ->Prefix[0] == 0 && v ->Suffix[0] == 0 && v ->ColorantCount == 0) return TRUE;
......@@ -1809,13 +1986,13 @@ int cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSig
if (n < 0)
return 0;
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
// This replaces actual named color list.
size_t size = Icc -> TagSizes[n];
if (v ->NamedColorList) cmsFreeNamedColorList(v ->NamedColorList);
v -> NamedColorList = (LPcmsNAMEDCOLORLIST) malloc(size);
v -> NamedColorList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
CopyMemory(v -> NamedColorList, Icc ->TagPtrs[n], size);
return v ->NamedColorList->nColors;
}
......@@ -1844,7 +2021,7 @@ int cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSig
icNamedColor2 nc2;
unsigned int i, j;
Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc);
if (Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return 0;
AdjustEndianess32((LPBYTE) &nc2.vendorFlag);
AdjustEndianess32((LPBYTE) &nc2.count);
AdjustEndianess32((LPBYTE) &nc2.nDeviceCoords);
......@@ -1854,6 +2031,11 @@ int cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSig
return 0;
}
if (nc2.nDeviceCoords > MAXCHANNELS) {
cmsSignalError(LCMS_ERRC_WARNING, "Too many device coordinates.");
return 0;
}
strncpy(v ->NamedColorList->Prefix, (const char*) nc2.prefix, 32);
strncpy(v ->NamedColorList->Suffix, (const char*) nc2.suffix, 32);
v ->NamedColorList->Prefix[32] = v->NamedColorList->Suffix[32] = 0;
......@@ -1900,7 +2082,8 @@ int cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSig
LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig)
{
icInt32Number n, Count, i;
icInt32Number n;
icUInt32Number Count, i;
size_t offset;
icTagTypeSignature BaseType;
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -1910,10 +2093,12 @@ LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagS
if (n < 0)
return NULL; // Not found
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
size_t size = Icc -> TagSizes[n];
void* v = malloc(size);
void* v = _cmsMalloc(size);
if (v == NULL) return NULL;
CopyMemory(v, Icc -> TagPtrs[n], size);
return (LPcmsNAMEDCOLORLIST) v;
}
......@@ -1932,13 +2117,17 @@ LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagS
}
Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
AdjustEndianess32((LPBYTE) &Count);
if (Count > MAXCHANNELS) {
cmsSignalError(LCMS_ERRC_ABORTED, "Too many colorants '%lx'", Count);
return NULL;
}
List = cmsAllocNamedColorList(Count);
for (i=0; i < Count; i++) {
if (!Icc ->Read(List->List[i].Name, 1, 32 , Icc)) goto Error;
if (!Icc ->Read(List->List[i].PCS, sizeof(icUInt16Number), 3, Icc)) goto Error;
AdjustEndianessArray16(List->List[i].PCS, 3);
......@@ -1965,7 +2154,7 @@ const char* LCMSEXPORT cmsTakeManufacturer(cmsHPROFILE hProfile)
if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer);
cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
}
return Manufacturer;
......@@ -1982,7 +2171,7 @@ const char* LCMSEXPORT cmsTakeModel(cmsHPROFILE hProfile)
if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model);
cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
}
return Model;
......@@ -1995,10 +2184,9 @@ const char* LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile)
static char Copyright[LCMS_DESC_MAX] = "";
Copyright[0] = 0;
if (cmsIsTag(hProfile, icSigCopyrightTag)) {
cmsReadICCText(hProfile, icSigCopyrightTag, Copyright);
cmsReadICCTextEx(hProfile, icSigCopyrightTag, Copyright, LCMS_DESC_MAX);
}
return Copyright;
......@@ -2009,7 +2197,7 @@ const char* LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile)
const char* LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile)
{
static char Name[2048];
static char Name[LCMS_DESC_MAX*2+4];
char Manufacturer[LCMS_DESC_MAX], Model[LCMS_DESC_MAX];
Name[0] = '\0';
......@@ -2017,19 +2205,19 @@ const char* LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile)
if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer);
cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
}
if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model);
cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
}
if (!Manufacturer[0] && !Model[0]) {
if (cmsIsTag(hProfile, icSigProfileDescriptionTag)) {
cmsReadICCText(hProfile, icSigProfileDescriptionTag, Name);
cmsReadICCTextEx(hProfile, icSigProfileDescriptionTag, Name, LCMS_DESC_MAX);
return Name;
}
else return "{no name}";
......@@ -2129,7 +2317,7 @@ const char* LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile)
// Extract the target data as a big string. Does not signal if tag is not present.
BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len)
LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
int n;
......@@ -2142,7 +2330,11 @@ BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t*
*len = Icc -> TagSizes[n];
*Data = (char*) malloc(*len + 1); // Plus zero marker
// Make sure that is reasonable (600K)
if (*len > 600*1024) *len = 600*1024;
*Data = (char*) _cmsMalloc(*len + 1); // Plus zero marker
if (!*Data) {
......@@ -2162,7 +2354,7 @@ BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t*
BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
int n;
......@@ -2170,8 +2362,8 @@ BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile
n = _cmsSearchTag(Icc, icSigCalibrationDateTimeTag, FALSE);
if (n < 0) return FALSE;
if (!Icc ->stream)
{
if (Icc ->TagPtrs[n]) {
CopyMemory(Dest, Icc ->TagPtrs[n], sizeof(struct tm));
}
else
......@@ -2212,9 +2404,10 @@ LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile)
size = Icc -> TagSizes[n];
if (size < 12) return NULL;
if (!Icc -> stream) {
if (Icc -> TagPtrs[n]) {
OutSeq = (LPcmsSEQ) malloc(size);
OutSeq = (LPcmsSEQ) _cmsMalloc(size);
if (OutSeq == NULL) return NULL;
CopyMemory(OutSeq, Icc ->TagPtrs[n], size);
return OutSeq;
}
......@@ -2231,8 +2424,13 @@ LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile)
Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &Count);
if (Count > 1000) {
return NULL;
}
size = sizeof(int) + Count * sizeof(cmsPSEQDESC);
OutSeq = (LPcmsSEQ) malloc(size);
OutSeq = (LPcmsSEQ) _cmsMalloc(size);
if (OutSeq == NULL) return NULL;
OutSeq ->n = Count;
......@@ -2268,181 +2466,11 @@ LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile)
void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq)
{
if (pseq)
free(pseq);
}
// Extended gamut -- an HP extension
LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
size_t size, offset;
icUInt32Number off_samp, off_desc, off_vc;
int n;
icTagTypeSignature BaseType;
icColorSpaceSignature CoordSig;
icUInt16Number Method, Usage;
icUInt32Number GamutCount, SamplesCount;
LPcmsGAMUTEX gex;
size_t Offsets[256];
size_t i, Actual, Loc;
icS15Fixed16Number Num;
icUInt16Number Surround;
n = _cmsSearchTag(Icc, icSigHPGamutDescTag, FALSE);
if (n < 0) return NULL;
if (!Icc ->stream) return NULL; // In memory is not supported
// Read the header
offset = Icc -> TagOffsets[n];
if (Icc -> Seek(Icc, offset))
return NULL;
// Here is the beginning of tag
Actual = Icc ->Tell(Icc);
BaseType = ReadBase(Icc);
if (BaseType != icSigHPGamutDescType) {
cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType);
return NULL;
}
// Read the gamut descriptors count
Icc ->Read(&GamutCount, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &GamutCount);
if (GamutCount >= 256) {
cmsSignalError(LCMS_ERRC_ABORTED, "Too many gamut structures '%d'.", GamutCount);
return NULL;
}
// Read the directory
for (i=0; i < GamutCount; i++) {
Icc ->Read(&Offsets[i], sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &Offsets[i]);
}
// Is there such element?
if (index >= (int) GamutCount) return NULL;
Loc = Actual + Offsets[index];
// Go to specified index
if (Icc -> Seek(Icc, Loc))
return NULL;
// Read all members
Icc ->Read(&CoordSig, sizeof(icColorSpaceSignature), 1, Icc);
AdjustEndianess32((LPBYTE) &CoordSig);
Icc ->Read(&Method, sizeof(icUInt16Number), 1, Icc);
AdjustEndianess16((LPBYTE) &Method);
Icc ->Read(&Usage, sizeof(icUInt16Number), 1, Icc);
AdjustEndianess16((LPBYTE) &Usage);
Icc ->Read(&SamplesCount, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &SamplesCount);
Icc ->Read(&off_samp, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &off_samp);
Icc ->Read(&off_desc, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &off_desc);
Icc ->Read(&off_vc, sizeof(icUInt32Number), 1, Icc);
AdjustEndianess32((LPBYTE) &off_vc);
size = sizeof(cmsGAMUTEX) + (SamplesCount - 1) * sizeof(double);
gex = (LPcmsGAMUTEX) malloc(size);
if (gex == NULL) return NULL;
gex ->CoordSig = CoordSig;
gex ->Method = Method;
gex ->Usage = Usage;
gex ->Count = SamplesCount;
// Read data
if (Icc -> Seek(Icc, Loc + off_samp))
return NULL;
for (i=0; i < SamplesCount; i++) {
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Data[i] = Convert15Fixed16(Num);
}
// Read mluc
if (Icc -> Seek(Icc, Loc + off_desc)) {
free(gex);
return NULL;
}
ReadEmbeddedTextTag(Icc, 256, gex ->Description, LCMS_DESC_MAX);
// Read viewing conditions
if (Icc -> Seek(Icc, Loc + off_vc)) {
free(gex);
return NULL;
}
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.whitePoint.X = Convert15Fixed16(Num);
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.whitePoint.Y = Convert15Fixed16(Num);
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.whitePoint.Z = Convert15Fixed16(Num);
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.La = Convert15Fixed16(Num);
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.Yb = Convert15Fixed16(Num);
Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc);
gex ->Vc.D_value = Convert15Fixed16(Num);
Icc -> Read(&Surround, sizeof(icUInt16Number), 1, Icc);
AdjustEndianess16((LPBYTE) &Surround);
gex ->Vc.surround = Surround;
// All OK
return gex;
_cmsFree(pseq);
}
void LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex)
{
if (gex)
free(gex);
}
// Read a few tags that are hardly required
......@@ -2564,6 +2592,7 @@ cmsHPROFILE LCMSEXPORT cmsOpenProfileFromFile(const char *lpFileName, const char
NewIcc = (LPLCMSICCPROFILE) (LPSTR) hEmpty;
NewIcc -> IsWrite = TRUE;
strncpy(NewIcc ->PhysicalFile, lpFileName, MAX_PATH-1);
NewIcc ->PhysicalFile[MAX_PATH-1] = 0;
// Save LUT as 8 bit
......@@ -2609,14 +2638,14 @@ cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize)
BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
BOOL rc = TRUE;
LCMSBOOL rc = TRUE;
icInt32Number i;
if (!Icc) return FALSE;
// Was open in write mode?
if (Icc ->IsWrite) {
......@@ -2624,21 +2653,15 @@ BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
rc = _cmsSaveProfile(hProfile, Icc ->PhysicalFile);
}
if (Icc -> stream == NULL) { // Was a memory (i.e. not serialized) profile?
icInt32Number i; // Yes, free tags
for (i=0; i < Icc -> TagCount; i++) {
for (i=0; i < Icc -> TagCount; i++) {
if (Icc -> TagPtrs[i])
free(Icc -> TagPtrs[i]);
}
}
else Icc -> Close(Icc); // No, close the stream
if (Icc -> stream != NULL) { // Was a memory (i.e. not serialized) profile?
Icc -> Close(Icc); // No, close the stream
}
free(Icc); // Free placeholder memory
......@@ -2652,11 +2675,11 @@ BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
static
BOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
{
size_t nTabSize = sizeof(WORD) * nEntries;
LPWORD PtrW = (LPWORD) malloc(nTabSize);
BOOL rc;
LPWORD PtrW = (LPWORD) _cmsMalloc(nTabSize);
LCMSBOOL rc;
if (!PtrW) return FALSE;
CopyMemory(PtrW, Tab, nTabSize);
......@@ -2672,7 +2695,7 @@ BOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
// Saves profile header
static
BOOL SaveHeader(LPLCMSICCPROFILE Icc)
LCMSBOOL SaveHeader(LPLCMSICCPROFILE Icc)
{
icHeader Header;
time_t now = time(NULL);
......@@ -2727,7 +2750,7 @@ BOOL SaveHeader(LPLCMSICCPROFILE Icc)
// Setup base marker
static
BOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
LCMSBOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
{
icTagBase Base;
......@@ -2737,10 +2760,10 @@ BOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
}
// Store an XYZ tag
// Store a XYZ tag
static
BOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
{
icXYZNumber XYZ;
......@@ -2756,72 +2779,97 @@ BOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
}
// Store a XYZ array.
static
LCMSBOOL SaveXYZArray(int n, LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
{
int i;
icXYZNumber XYZ;
if (!SetupBase(icSigS15Fixed16ArrayType, Icc)) return FALSE;
for (i=0; i < n; i++) {
XYZ.X = TransportValue32(DOUBLE_TO_FIXED(Value -> X));
XYZ.Y = TransportValue32(DOUBLE_TO_FIXED(Value -> Y));
XYZ.Z = TransportValue32(DOUBLE_TO_FIXED(Value -> Z));
if (!Icc -> Write(Icc, sizeof(icXYZNumber), &XYZ)) return FALSE;
Value++;
}
return TRUE;
}
// Save a gamma structure as a table
static
BOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
{
icInt32Number Count;
icInt32Number Count;
if (!SetupBase(icSigCurveType, Icc)) return FALSE;
if (!SetupBase(icSigCurveType, Icc)) return FALSE;
Count = TransportValue32(Gamma->nEntries);
Count = TransportValue32(Gamma->nEntries);
if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc);
return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc);
}
// Save a gamma structure as a one-value
static
BOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
{
icInt32Number Count;
Fixed32 GammaFixed32;
WORD GammaFixed8;
icInt32Number Count;
Fixed32 GammaFixed32;
WORD GammaFixed8;
if (!SetupBase(icSigCurveType, Icc)) return FALSE;
if (!SetupBase(icSigCurveType, Icc)) return FALSE;
Count = TransportValue32(1);
if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
Count = TransportValue32(1);
if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]);
GammaFixed8 = (WORD) ((GammaFixed32 >> 8) & 0xFFFF);
GammaFixed8 = TransportValue16(GammaFixed8);
GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]);
GammaFixed8 = (WORD) ((GammaFixed32 >> 8) & 0xFFFF);
GammaFixed8 = TransportValue16(GammaFixed8);
return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8);
return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8);
}
// Save a gamma structure as a parametric gamma
static
BOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
{
icUInt16Number Type, Reserved;
int i, nParams;
int ParamsByType[] = { 1, 3, 4, 5, 7 };
icUInt16Number Type, Reserved;
int i, nParams;
int ParamsByType[] = { 1, 3, 4, 5, 7 };
if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE;
if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE;
nParams = ParamsByType[Gamma -> Seed.Type];
nParams = ParamsByType[Gamma -> Seed.Type];
Type = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type);
Reserved = (icUInt16Number) TransportValue16((WORD) 0);
Type = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type);
Reserved = (icUInt16Number) TransportValue16((WORD) 0);
Icc -> Write(Icc, sizeof(icInt16Number), &Type);
Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved);
Icc -> Write(Icc, sizeof(icInt16Number), &Type);
Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved);
for (i=0; i < nParams; i++) {
for (i=0; i < nParams; i++) {
icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i]));
Icc ->Write(Icc, sizeof(icInt32Number), &val);
}
icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i]));
Icc ->Write(Icc, sizeof(icInt32Number), &val);
}
return TRUE;
return TRUE;
}
......@@ -2829,29 +2877,29 @@ BOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
// Save a gamma table
static
BOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
{
// Is the gamma curve type supported by ICC format?
// Is the gamma curve type supported by ICC format?
if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 ||
if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 ||
// has been modified by user?
// has been modified by user?
_cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) {
_cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) {
return SaveGammaTable(Gamma, Icc);
}
return SaveGammaTable(Gamma, Icc);
}
if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc);
if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc);
// Only v4 profiles are allowed to hold parametric curves
// Only v4 profiles are allowed to hold parametric curves
if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000)
return SaveGammaParametric(Gamma, Icc);
if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000)
return SaveGammaParametric(Gamma, Icc);
// Defaults to save as table
// Defaults to save as table
return SaveGammaTable(Gamma, Icc);
return SaveGammaTable(Gamma, Icc);
}
......@@ -2861,7 +2909,7 @@ BOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
// Save an DESC Tag
static
BOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
{
icUInt32Number len, Count, TotalSize, AlignedSize;
......@@ -2893,6 +2941,11 @@ BOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
if (!Icc ->Write(Icc, len, (LPVOID)Text)) return FALSE;
AlignedSize -= len;
if (AlignedSize < 0)
AlignedSize = 0;
if (AlignedSize > 255)
AlignedSize = 255;
ZeroMemory(Filler, AlignedSize);
if (!Icc ->Write(Icc, AlignedSize, Filler)) return FALSE;
......@@ -2902,7 +2955,7 @@ BOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
// Save an ASCII Tag
static
BOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
{
size_t len = strlen(Text) + 1;
......@@ -2915,7 +2968,7 @@ BOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
// Save one of these new chromaticity values
static
BOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
{
Fixed32 xf, yf;
......@@ -2932,7 +2985,7 @@ BOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
// New tag added in Addendum II of old spec.
static
BOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
{
WORD nChans, Table;
......@@ -2952,7 +3005,7 @@ BOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
static
BOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
{
icUInt32Number nSeqs;
icDescStruct DescStruct;
......@@ -2989,7 +3042,7 @@ BOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
// Saves a timestamp tag
static
BOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
{
icDateTimeNumber Dest;
......@@ -3003,14 +3056,14 @@ BOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
// Saves a named color list into a named color profile
static
BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
{
icUInt32Number vendorFlag; // Bottom 16 bits for IC use
icUInt32Number count; // Count of named colors
icUInt32Number nDeviceCoords; // Num of device coordinates
icInt8Number prefix[32]; // Prefix for each color name
icInt8Number suffix[32]; // Suffix for each color name
char prefix[32]; // Prefix for each color name
char suffix[32]; // Suffix for each color name
int i;
if (!SetupBase(icSigNamedColor2Type, Icc)) return FALSE;
......@@ -3019,8 +3072,10 @@ BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc
count = TransportValue32(NamedColorList ->nColors);
nDeviceCoords = TransportValue32(NamedColorList ->ColorantCount);
strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
strncpy(prefix, (const char*) NamedColorList->Prefix, 31);
strncpy(suffix, (const char*) NamedColorList->Suffix, 31);
suffix[31] = prefix[31] = 0;
if (!Icc ->Write(Icc, sizeof(icUInt32Number), &vendorFlag)) return FALSE;
if (!Icc ->Write(Icc, sizeof(icUInt32Number), &count)) return FALSE;
......@@ -3030,15 +3085,17 @@ BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc
for (i=0; i < NamedColorList ->nColors; i++) {
icUInt16Number PCS[3];
icUInt16Number Colorant[MAXCHANNELS];
icInt8Number root[32];
icUInt16Number PCS[3];
icUInt16Number Colorant[MAXCHANNELS];
char root[32];
LPcmsNAMEDCOLOR Color;
int j;
Color = NamedColorList ->List + i;
strncpy((char*) root, Color ->Name, 32);
strncpy(root, Color ->Name, 32);
Color ->Name[32] = 0;
if (!Icc ->Write(Icc, 32 , root)) return FALSE;
for (j=0; j < 3; j++)
......@@ -3062,7 +3119,7 @@ BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc
// Saves a colorant table. It is using the named color structure for simplicity sake
static
BOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
{
icUInt32Number count; // Count of named colors
int i;
......@@ -3076,13 +3133,15 @@ BOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
for (i=0; i < NamedColorList ->nColors; i++) {
icUInt16Number PCS[3];
icInt8Number root[32];
icInt8Number root[33];
LPcmsNAMEDCOLOR Color;
int j;
Color = NamedColorList ->List + i;
strncpy((char*) root, Color ->Name, 32);
root[32] = 0;
if (!Icc ->Write(Icc, 32 , root)) return FALSE;
for (j=0; j < 3; j++)
......@@ -3099,7 +3158,7 @@ BOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
// Does serialization of LUT16 and writes it.
static
BOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
{
icLut16 LUT16;
unsigned int i;
......@@ -3189,7 +3248,7 @@ BOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
// Does serialization of LUT8 and writes it
static
BOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
LCMSBOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
{
icLut8 LUT8;
unsigned int i, j;
......@@ -3323,7 +3382,7 @@ void LCMSEXPORT _cmsSetLUTdepth(cmsHPROFILE hProfile, int depth)
// Saves Tag directory
static
BOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
LCMSBOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
{
icInt32Number i;
icTag Tag;
......@@ -3356,7 +3415,7 @@ BOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
// Dump tag contents
static
BOOL SaveTags(LPLCMSICCPROFILE Icc)
LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc, LPLCMSICCPROFILE FileOrig)
{
LPBYTE Data;
......@@ -3384,8 +3443,31 @@ BOOL SaveTags(LPLCMSICCPROFILE Icc)
Icc -> TagOffsets[i] = Begin = Icc ->UsedSpace;
Data = (LPBYTE) Icc -> TagPtrs[i];
if (!Data)
if (!Data) {
// Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user.
// In this case a blind copy of the block data is performed
if (Icc -> TagOffsets[i]) {
size_t TagSize = FileOrig -> TagSizes[i];
size_t TagOffset = FileOrig -> TagOffsets[i];
void* Mem;
if (FileOrig ->Seek(FileOrig, TagOffset)) return FALSE;
Mem = _cmsMalloc(TagSize);
if (FileOrig ->Read(Mem, TagSize, 1, FileOrig) != 1) return FALSE;
if (!Icc ->Write(Icc, TagSize, Mem)) return FALSE;
Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin);
free(Mem);
}
continue;
}
switch (Icc -> TagNames[i]) {
......@@ -3464,6 +3546,10 @@ BOOL SaveTags(LPLCMSICCPROFILE Icc)
break;
case icSigChromaticAdaptationTag:
if (!SaveXYZArray(3, (LPcmsCIEXYZ) Data, Icc)) return FALSE;
break;
default:
return FALSE;
}
......@@ -3480,9 +3566,9 @@ BOOL SaveTags(LPLCMSICCPROFILE Icc)
// Add tags to profile structure
BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag)
LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag)
{
BOOL rc;
LCMSBOOL rc;
switch (sig) {
......@@ -3543,6 +3629,11 @@ BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void*
rc = _cmsAddColorantTableTag(hProfile, sig, (LPcmsNAMEDCOLORLIST) Tag);
break;
case icSigChromaticAdaptationTag:
rc = _cmsAddChromaticAdaptationTag(hProfile, sig, (const cmsCIEXYZ*) Tag);
break;
default:
cmsSignalError(LCMS_ERRC_ABORTED, "cmsAddTag: Tag '%x' is unsupported", sig);
return FALSE;
......@@ -3568,11 +3659,11 @@ BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void*
// Low-level save to disk. It closes the profile on exit
BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
LCMSICCPROFILE Keep;
BOOL rc;
LCMSBOOL rc;
CopyMemory(&Keep, Icc, sizeof(LCMSICCPROFILE));
_cmsSetSaveToDisk(Icc, NULL);
......@@ -3581,7 +3672,7 @@ BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
if (!SaveHeader(Icc)) return FALSE;
if (!SaveTagDirectory(Icc)) return FALSE;
if (!SaveTags(Icc)) return FALSE;
if (!SaveTags(Icc, &Keep)) return FALSE;
_cmsSetSaveToDisk(Icc, FileName);
......@@ -3591,7 +3682,7 @@ BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
if (!SaveHeader(Icc)) goto CleanUp;
if (!SaveTagDirectory(Icc)) goto CleanUp;
if (!SaveTags(Icc)) goto CleanUp;
if (!SaveTags(Icc, &Keep)) goto CleanUp;
rc = (Icc ->Close(Icc) == 0);
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
......@@ -3608,7 +3699,7 @@ BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
// Low-level save from open stream
BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
size_t* BytesNeeded)
{
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
......@@ -3623,20 +3714,20 @@ BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
if (!SaveHeader(Icc)) return FALSE;
if (!SaveTagDirectory(Icc)) return FALSE;
if (!SaveTags(Icc)) return FALSE;
if (!SaveTags(Icc, &Keep)) return FALSE;
if (!MemPtr) {
// update BytesSaved so caller knows how many bytes are needed for MemPtr
*BytesNeeded = Icc ->UsedSpace;
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
return TRUE;
}
if (*BytesNeeded < Icc ->UsedSpace) {
// need at least UsedSpace in MemPtr to continue
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
return FALSE;
}
......@@ -3646,7 +3737,7 @@ BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
// Pass #2 does save to file into supplied stream
if (!SaveHeader(Icc)) goto CleanUp;
if (!SaveTagDirectory(Icc)) goto CleanUp;
if (!SaveTags(Icc)) goto CleanUp;
if (!SaveTags(Icc, &Keep)) goto CleanUp;
// update BytesSaved so caller knows how many bytes put into stream
*BytesNeeded = Icc ->UsedSpace;
......@@ -3661,3 +3752,4 @@ CleanUp:
CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
return FALSE;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -118,7 +118,7 @@ LPLUT LCMSEXPORT cmsAllocLUT(void)
{
LPLUT NewLUT;
NewLUT = (LPLUT) malloc(sizeof(LUT));
NewLUT = (LPLUT) _cmsMalloc(sizeof(LUT));
if (NewLUT)
ZeroMemory(NewLUT, sizeof(LUT));
......@@ -171,9 +171,10 @@ void LCMSEXPORT cmsFreeLUT(LPLUT Lut)
static
LPVOID DupBlockTab(LPVOID Org, size_t size)
{
LPVOID mem = malloc(size);
LPVOID mem = _cmsMalloc(size);
if (mem != NULL)
CopyMemory(mem, Org, size);
CopyMemory(mem, Org, size);
return mem;
}
......@@ -211,6 +212,37 @@ unsigned int UIpow(unsigned int a, unsigned int b)
}
LCMSBOOL _cmsValidateLUT(LPLUT NewLUT)
{
unsigned int calc = 1;
unsigned int oldCalc;
unsigned int power = NewLUT -> InputChan;
if (NewLUT -> cLutPoints > 100) return FALSE;
if (NewLUT -> InputChan > MAXCHANNELS) return FALSE;
if (NewLUT -> OutputChan > MAXCHANNELS) return FALSE;
if (NewLUT -> cLutPoints == 0) return TRUE;
for (; power > 0; power--) {
oldCalc = calc;
calc *= NewLUT -> cLutPoints;
if (calc / NewLUT -> cLutPoints != oldCalc) {
return FALSE;
}
}
oldCalc = calc;
calc *= NewLUT -> OutputChan;
if (NewLUT -> OutputChan && calc / NewLUT -> OutputChan != oldCalc) {
return FALSE;
}
return TRUE;
}
LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan)
{
DWORD nTabSize;
......@@ -220,12 +252,17 @@ LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int
NewLUT -> InputChan = inputChan;
NewLUT -> OutputChan = outputChan;
if (!_cmsValidateLUT(NewLUT)) {
return NULL;
}
nTabSize = NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
NewLUT->InputChan);
nTabSize = (NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
NewLUT->InputChan)
* sizeof(WORD));
NewLUT -> T = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
nTabSize *= sizeof(WORD);
if (NewLUT -> T == NULL) return NULL;
NewLUT -> T = (LPWORD) malloc(nTabSize);
ZeroMemory(NewLUT -> T, nTabSize);
NewLUT ->Tsize = nTabSize;
......@@ -254,10 +291,12 @@ LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nT
for (i=0; i < NewLUT -> InputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
if (PtrW == NULL) return NULL;
NewLUT -> L1[i] = PtrW;
CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries);
CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
}
......@@ -268,10 +307,12 @@ LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nT
NewLUT -> OutputEntries = Tables[0] -> nEntries;
for (i=0; i < NewLUT -> OutputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
if (PtrW == NULL) return NULL;
NewLUT -> L2[i] = PtrW;
CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries);
CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
}
break;
......@@ -285,10 +326,12 @@ LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nT
for (i=0; i < NewLUT -> InputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L3Entries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L3Entries);
if (PtrW == NULL) return NULL;
NewLUT -> L3[i] = PtrW;
CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries);
CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
}
break;
......@@ -298,10 +341,12 @@ LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nT
NewLUT -> L4Entries = Tables[0] -> nEntries;
for (i=0; i < NewLUT -> OutputChan; i++) {
PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L4Entries);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L4Entries);
if (PtrW == NULL) return NULL;
NewLUT -> L4[i] = PtrW;
CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries);
CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
}
break;
......@@ -580,7 +625,7 @@ LPLUT _cmsBlessLUT8(LPLUT Lut)
LPL16PARAMS p = &Lut ->CLut16params;
p8 = (LPL8PARAMS) malloc(sizeof(L8PARAMS));
p8 = (LPL8PARAMS) _cmsMalloc(sizeof(L8PARAMS));
if (p8 == NULL) return NULL;
// values comes * 257, so we can safely take first byte (x << 8 + x)
......@@ -593,8 +638,8 @@ LPLUT _cmsBlessLUT8(LPLUT Lut)
if (Lut ->wFlags & LUT_HASTL1) {
for (j=0; j < 3; j++)
StageABC[i] = cmsLinearInterpLUT16(StageABC[i],
Lut -> L1[i],
StageABC[j] = cmsLinearInterpLUT16(StageABC[j],
Lut -> L1[j],
&Lut -> In16params);
Lut ->wFlags &= ~LUT_HASTL1;
}
......@@ -697,7 +742,7 @@ void EvalLUTdoubleKLab(LPLUT Lut, const VEC3* In, WORD FixedK, LPcmsCIELab Out)
wIn[3] = FixedK;
cmsEvalLUT(Lut, wIn, wOut);
cmsLabEncoded2Float(Out, wOut);
cmsLabEncoded2Float(Out, wOut);
}
// Builds a Jacobian CMY->Lab
......@@ -722,9 +767,9 @@ void ComputeJacobianLab(LPLUT Lut, LPMAT3 Jacobian, const VEC3* Colorant, WORD K
EvalLUTdoubleKLab(Lut, &ColorantD, K, &LabD);
Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON);
Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON);
Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON);
Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON);
Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON);
Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON);
}
}
......@@ -797,18 +842,18 @@ LCMSAPI double LCMSEXPORT cmsEvalLUTreverse(LPLUT Lut, WORD Target[], WORD Resul
// Obtain slope
ComputeJacobianLab(Lut, &Jacobian, &x, FixedK);
// Solve system
tmp2.n[0] = fx.L - Goal.L;
tmp2.n[1] = fx.a - Goal.a;
tmp2.n[2] = fx.b - Goal.b;
// Solve system
tmp2.n[0] = fx.L - Goal.L;
tmp2.n[1] = fx.a - Goal.a;
tmp2.n[2] = fx.b - Goal.b;
if (!MAT3solve(&tmp, &Jacobian, &tmp2))
break;
if (!MAT3solve(&tmp, &Jacobian, &tmp2))
break;
// Move our guess
x.n[0] -= tmp.n[0];
x.n[1] -= tmp.n[1];
x.n[2] -= tmp.n[2];
x.n[0] -= tmp.n[0];
x.n[1] -= tmp.n[1];
x.n[2] -= tmp.n[2];
// Some clipping....
VEC3saturate(&x);
......@@ -822,3 +867,6 @@ LCMSAPI double LCMSEXPORT cmsEvalLUTreverse(LPLUT Lut, WORD Target[], WORD Resul
return LastError;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -62,6 +62,7 @@
// data yet in fixed point, so no additional process is required.
// Then, we obtain data on 15.16, so we need to shift >> by 1 to
// obtain 1.15 PCS format.
// On OUTPUT profiles, things are inverse, we must first expand 1 bit
// by shifting left, and then convert result between 0 and 1.000 to
// RGB, so FromFixedDomain() must be called before pass values to
......@@ -71,6 +72,7 @@
// input is encoded from 0 to 0xffff, we must first use the shaper and
// then the matrix, an additional FromFixedDomain() must be used to
// accomodate output values.
// For a sake of simplicity, I will handle this three behaviours
// with different routines, so the flags MATSHAPER_INPUT and MATSHAPER_OUTPUT
// can be conbined to signal smelted matrix-shapers
......@@ -89,7 +91,7 @@ int ComputeTables(LPGAMMATABLE Table[3], LPWORD Out[3], LPL16PARAMS p16)
{
LPWORD PtrW;
PtrW = (LPWORD) malloc(sizeof(WORD) * p16 -> nSamples);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * p16 -> nSamples);
if (PtrW == NULL) return -1; // Signal error
......@@ -119,7 +121,7 @@ LPMATSHAPER cmsAllocMatShaper2(LPMAT3 Matrix, LPGAMMATABLE In[], LPGAMMATABLE Ou
LPMATSHAPER NewMatShaper;
int rc;
NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER));
NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
if (NewMatShaper)
ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
......@@ -171,7 +173,13 @@ LPMATSHAPER cmsAllocMatShaper(LPMAT3 Matrix, LPGAMMATABLE Tables[], DWORD Behavi
LPMATSHAPER NewMatShaper;
int i, AllLinear;
NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER));
if (Matrix == NULL) return NULL;
for (i=0; i < 3; i++) {
if (Tables[i] == NULL) return NULL;
}
NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
if (NewMatShaper)
ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
......@@ -187,17 +195,16 @@ LPMATSHAPER cmsAllocMatShaper(LPMAT3 Matrix, LPGAMMATABLE Tables[], DWORD Behavi
NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX;
// Now, on the table characteristics
cmsCalcL16Params(Tables[0] -> nEntries, &NewMatShaper -> p16);
// Copy tables
AllLinear = 0;
for (i=0; i < 3; i++)
{
for (i=0; i < 3; i++) {
LPWORD PtrW;
PtrW = (LPWORD) malloc(sizeof(WORD) * NewMatShaper -> p16.nSamples);
PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewMatShaper -> p16.nSamples);
if (PtrW == NULL) {
cmsFreeMatShaper(NewMatShaper);
......@@ -235,11 +242,11 @@ void cmsFreeMatShaper(LPMATSHAPER MatShaper)
for (i=0; i < 3; i++)
{
if (MatShaper -> L[i]) free(MatShaper ->L[i]);
if (MatShaper -> L2[i]) free(MatShaper ->L2[i]);
if (MatShaper -> L[i]) _cmsFree(MatShaper ->L[i]);
if (MatShaper -> L2[i]) _cmsFree(MatShaper ->L2[i]);
}
free(MatShaper);
_cmsFree(MatShaper);
}
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -71,16 +71,16 @@ double cdecl VEC3length(LPVEC3 a);
double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
void cdecl MAT3identity(LPMAT3 a);
void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
BOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
double cdecl MAT3det(LPMAT3 m);
void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
void cdecl MAT3identity(LPMAT3 a);
void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
LCMSBOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
double cdecl MAT3det(LPMAT3 m);
void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
// --------------------- Implementation ----------------------------
......@@ -345,13 +345,13 @@ void VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b)
// Check id two vectors are the same, allowing tolerance
static
BOOL RangeCheck(double l, double h, double v)
LCMSBOOL RangeCheck(double l, double h, double v)
{
return (v >= l && v <= h);
}
BOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
LCMSBOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
{
int i;
double c;
......@@ -367,7 +367,7 @@ BOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
return TRUE;
}
BOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance)
LCMSBOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance)
{
int i;
double c;
......@@ -462,7 +462,7 @@ void MAT3identity(LPMAT3 a)
// Check if matrix is Identity. Allow a tolerance as %
BOOL MAT3isIdentity(LPWMAT3 a, double Tolerance)
LCMSBOOL MAT3isIdentity(LPWMAT3 a, double Tolerance)
{
int i;
MAT3 Idd;
......@@ -545,16 +545,16 @@ int MAT3inverse(LPMAT3 a, LPMAT3 b)
// Solve a system in the form Ax = b
BOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b)
LCMSBOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b)
{
MAT3 m, a_1;
MAT3 m, a_1;
CopyMemory(&m, a, sizeof(MAT3));
CopyMemory(&m, a, sizeof(MAT3));
if (!MAT3inverse(&m, &a_1)) return FALSE; // Singular matrix
if (!MAT3inverse(&m, &a_1)) return FALSE; // Singular matrix
MAT3eval(x, &a_1, b);
return TRUE;
MAT3eval(x, &a_1, b);
return TRUE;
}
......@@ -839,3 +839,7 @@ void MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d)
VEC3scaleAndCut(&r -> v[1], &v -> v[1], d);
VEC3scaleAndCut(&r -> v[2], &v -> v[2], d);
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -74,7 +74,7 @@ LPcmsNAMEDCOLORLIST GrowNamedColorList(LPcmsNAMEDCOLORLIST v, int ByElements)
NewElements *= 2;
size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * NewElements);
TheNewList = (LPcmsNAMEDCOLORLIST) malloc(size);
TheNewList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
if (TheNewList == NULL) {
......@@ -86,7 +86,7 @@ LPcmsNAMEDCOLORLIST GrowNamedColorList(LPcmsNAMEDCOLORLIST v, int ByElements)
CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR));
TheNewList -> Allocated = NewElements;
free(v);
_cmsFree(v);
return TheNewList;
}
}
......@@ -99,7 +99,7 @@ LPcmsNAMEDCOLORLIST cmsAllocNamedColorList(int n)
{
size_t size = sizeof(cmsNAMEDCOLORLIST) + (n - 1) * sizeof(cmsNAMEDCOLOR);
LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) malloc(size);
LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
if (v == NULL) {
......@@ -124,10 +124,10 @@ void cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST v)
return;
}
free(v);
_cmsFree(v);
}
BOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS])
LCMSBOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS])
{
_LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
LPcmsNAMEDCOLORLIST List;
......@@ -146,6 +146,7 @@ BOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WOR
List ->List[List ->nColors].PCS[i] = PCS[i];
strncpy(List ->List[List ->nColors].Name, Name, MAX_PATH-1);
List ->List[List ->nColors].Name[MAX_PATH-1] = 0;
List ->nColors++;
return TRUE;
......@@ -164,18 +165,17 @@ int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform)
}
BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix)
LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix)
{
_LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
if (v ->NamedColorList == NULL) return FALSE;
if (nColor < 0 || nColor >= cmsNamedColorCount(xform)) return FALSE;
if (Name) strncpy(Name, v ->NamedColorList->List[nColor].Name, 31);
if (Prefix) strncpy(Prefix, v ->NamedColorList->Prefix, 31);
if (Suffix) strncpy(Suffix, v ->NamedColorList->Suffix, 31);
if (Name) { strncpy(Name, v ->NamedColorList->List[nColor].Name, 31); Name[31] = 0; }
if (Prefix) { strncpy(Prefix, v ->NamedColorList->Prefix, 31); Prefix[31] = 0; }
if (Suffix) { strncpy(Suffix, v ->NamedColorList->Suffix, 31); Suffix[31] = 0; }
return TRUE;
}
......@@ -196,3 +196,5 @@ int LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name)
return -1;
}
......@@ -28,7 +28,7 @@
// file:
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -639,9 +639,81 @@ LPBYTE UnrollDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register
static
LPBYTE UnrollDouble1Chan(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
{
double* Inks = (double*) accum;
double v;
v = floor(Inks[0] * 65535.0 + 0.5);
if (v > 65535.0) v = 65535.0;
if (v < 0) v = 0;
wIn[0] = wIn[1] = wIn[2] = (WORD) v;
return accum + sizeof(double);
}
// ----------------------------------------------------------- Packing routines
// Generic N-bytes plus dither 16-to-8 conversion. Currently is just a quick hack
static int err[MAXCHANNELS];
static
LPBYTE PackNBytesDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
{
int nChan = T_CHANNELS(info -> OutputFormat);
register int i;
unsigned int n, pe, pf;
for (i=0; i < nChan; i++) {
n = wOut[i] + err[i]; // Value
pe = (n / 257); // Whole part
pf = (n % 257); // Fractional part
err[i] = pf; // Store it for next pixel
*output++ = (BYTE) pe;
}
return output + T_EXTRA(info ->OutputFormat);
}
static
LPBYTE PackNBytesSwapDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
{
int nChan = T_CHANNELS(info -> OutputFormat);
register int i;
unsigned int n, pe, pf;
for (i=nChan-1; i >= 0; --i) {
n = wOut[i] + err[i]; // Value
pe = (n / 257); // Whole part
pf = (n % 257); // Fractional part
err[i] = pf; // Store it for next pixel
*output++ = (BYTE) pe;
}
return output + T_EXTRA(info ->OutputFormat);
}
// Generic chunky for byte
static
......@@ -1486,7 +1558,10 @@ _cmsFIXFN _cmsIdentifyInputFormat(_LPcmsTRANSFORM xform, DWORD dwInput)
case PT_HSV:
case PT_HLS:
case PT_Yxy:
FromInput = UnrollDouble;
if (T_CHANNELS(dwInput) == 1)
FromInput = UnrollDouble1Chan;
else
FromInput = UnrollDouble;
break;
// Inks (%) 0.0 .. 100.0
......@@ -1749,6 +1824,9 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
switch (T_CHANNELS(dwOutput))
{
case 1:
if (T_DITHER(dwOutput))
ToOutput = PackNBytesDither;
else
ToOutput = Pack1Byte;
if (T_EXTRA(dwOutput) == 1) {
if (T_SWAPFIRST(dwOutput))
......@@ -1766,8 +1844,12 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
else
if (T_COLORSPACE(dwOutput) == PT_Lab)
ToOutput = Pack3BytesLab;
else {
if (T_DITHER(dwOutput))
ToOutput = PackNBytesDither;
else
ToOutput = Pack3Bytes;
}
break;
case 1: // TODO: ALab8 should be handled here
......@@ -1793,12 +1875,22 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
case 4: if (T_EXTRA(dwOutput) == 0) {
if (T_DOSWAP(dwOutput)) {
if (T_SWAPFIRST(dwOutput))
if (T_SWAPFIRST(dwOutput)) {
ToOutput = Pack4BytesSwapSwapFirst;
else
}
else {
if (T_DITHER(dwOutput)) {
ToOutput = PackNBytesSwapDither;
}
else {
ToOutput = Pack4BytesSwap;
}
}
}
else {
if (T_SWAPFIRST(dwOutput))
......@@ -1807,11 +1899,15 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
if (T_FLAVOR(dwOutput))
ToOutput = Pack4BytesReverse;
else {
if (T_DITHER(dwOutput))
ToOutput = PackNBytesDither;
else
ToOutput = Pack4Bytes;
}
}
}
}
else {
if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
ToOutput = PackNBytes;
......@@ -1833,7 +1929,7 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
}
break;
case 2:
case 2:
case 5:
case 7:
case 8:
......@@ -1849,8 +1945,13 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
{
if (T_DOSWAP(dwOutput))
ToOutput = PackNBytesSwap;
else {
if (T_DITHER(dwOutput))
ToOutput = PackNBytesDither;
else
ToOutput = PackNBytes;
}
}
break;
......@@ -1984,7 +2085,7 @@ _cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
break;
case 2:
case 2:
case 5:
case 7:
case 8:
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -624,3 +624,7 @@ void LCMSEXPORT cmsXYZEncoded2Float(LPcmsCIEXYZ fXYZ, const WORD XYZ[3])
fXYZ -> Z = XYZ2float(XYZ[2]);
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -144,6 +144,8 @@ LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, int Intent,
/Table [ p p p [<...>]]
/RangeABC [ 0 1 0 1 0 1]
/DecodeABC[ <postlinearization> ]
/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]
% -128/500 1+127/500 0 1 -127/200 1+128/200
/MatrixABC [ 1 1 1 1 0 0 0 0 -1]
/WhitePoint [D50]
/BlackPoint [BP]
......@@ -347,7 +349,8 @@ typedef struct {
static
LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols)
{
LPMEMSTREAM m = (LPMEMSTREAM) malloc(sizeof(MEMSTREAM));
LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM));
if (m == NULL) return NULL;
ZeroMemory(m, sizeof(MEMSTREAM));
......@@ -376,9 +379,9 @@ BYTE Word2Byte(WORD w)
static
BYTE L2Byte(WORD w)
{
int ww = w + 0x0080;
int ww = w + 0x0080;
if (ww > 0xFFFF) return 0xFF;
if (ww > 0xFFFF) return 0xFF;
return (BYTE) ((WORD) (ww >> 8) & 0xFF);
}
......@@ -387,7 +390,6 @@ BYTE L2Byte(WORD w)
static
void WriteRawByte(LPMEMSTREAM m, BYTE b)
{
if (m -> dwUsed + 1 > m -> dwMax) {
m -> HasError = 1;
}
......@@ -422,7 +424,7 @@ void WriteByte(LPMEMSTREAM m, BYTE b)
}
// Does write a formatted string
// Does write a formatted string. Guaranteed to be 2048 bytes at most.
static
void Writef(LPMEMSTREAM m, const char *frm, ...)
{
......@@ -432,7 +434,7 @@ void Writef(LPMEMSTREAM m, const char *frm, ...)
va_start(args, frm);
vsprintf((char*) Buffer, frm, args);
vsnprintf((char*) Buffer, 2048, frm, args);
for (pt = Buffer; *pt; pt++) {
......@@ -562,7 +564,7 @@ void EmitLab2XYZ(LPMEMSTREAM m)
Writef(m, "{255 mul 128 sub 200 div } bind\n");
Writef(m, "]\n");
Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
Writef(m, "/DecodeLMN [\n");
Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
......@@ -584,7 +586,11 @@ void Emit1Gamma(LPMEMSTREAM m, LPWORD Table, int nEntries)
if (nEntries <= 0) return; // Empty table
// Suppress whole if identity
if (cmsIsLinear(Table, nEntries)) return;
if (cmsIsLinear(Table, nEntries)) {
Writef(m, "{} ");
return;
}
// Check if is really an exponential. If so, emit "exp"
gamma = cmsEstimateGammaEx(Table, nEntries, 0.001);
......@@ -646,7 +652,7 @@ void Emit1Gamma(LPMEMSTREAM m, LPWORD Table, int nEntries)
// Compare gamma table
static
BOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
{
return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;
}
......@@ -676,7 +682,7 @@ void EmitNGamma(LPMEMSTREAM m, int n, LPWORD g[], int nEntries)
// Check whatever a profile has CLUT tables (only on input)
static
BOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
{
icTagSignature Tag;
......@@ -718,10 +724,10 @@ int OutputValueSampler(register WORD In[], register WORD Out[], register LPVOID
if (sc -> FixWhite) {
if (In[0] == 0xFFFF) { // Only in L* = 100
if (In[0] == 0xFFFF) { // Only in L* = 100, ab = [-8..8]
if ((In[1] >= 0x8000 && In[1] <= 0x87FF) ||
(In[2] >= 0x8000 && In[2] <= 0x87FF)) {
if ((In[1] >= 0x7800 && In[1] <= 0x8800) &&
(In[2] >= 0x7800 && In[2] <= 0x8800)) {
WORD* Black;
WORD* White;
......@@ -829,8 +835,8 @@ void WriteCLUT(LPMEMSTREAM m, LPLUT Lut, int bps, const char* PreMaj,
sc.PreMaj = PreMaj;
sc.PostMaj= PostMaj;
sc.PreMin = PreMin;
sc.PostMin= PostMin;
sc.PreMin = PreMin;
sc.PostMin = PostMin;
sc.lIsInput = lIsInput;
sc.FixWhite = FixWhite;
sc.ColorSpace = ColorSpace;
......@@ -1231,7 +1237,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
if (!WriteNamedColorCSA(mem, hProfile, Intent)) {
free((void*) mem);
_cmsFree((void*) mem);
return 0;
}
}
......@@ -1246,7 +1252,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
ColorSpace != icSigLabData) {
cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space");
free((void*) mem);
_cmsFree((void*) mem);
return 0;
}
......@@ -1256,7 +1262,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
// Yes, so handle as LUT-based
if (!WriteInputLUT(mem, hProfile, Intent)) {
free((void*) mem);
_cmsFree((void*) mem);
return 0;
}
}
......@@ -1266,7 +1272,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
if (!WriteInputMatrixShaper(mem, hProfile)) {
free((void*) mem); // Something went wrong
_cmsFree((void*) mem); // Something went wrong
return 0;
}
}
......@@ -1277,7 +1283,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
dwBytesUsed = mem ->dwUsed;
// Get rid of memory stream
free((void*) mem);
_cmsFree((void*) mem);
// Finally, return used byte count
return dwBytesUsed;
......@@ -1350,27 +1356,40 @@ DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
static
void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute)
void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
{
Writef(m,"%% Bradford Cone Space\n"
"/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
if (lIsAbsolute) {
Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
// For absolute colorimetric intent, encode back to relative
// and generate a relative LUT
// Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
if (lIsAbsolute) {
cmsCIEXYZ White;
cmsTakeMediaWhitePoint(&White, hProfile);
// For absolute colorimetric intent, do nothing
Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
Writef(m, "%% Absolute colorimetric -- no transformation\n"
Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
"/TransformPQR [\n"
"{exch pop exch pop exch pop exch pop} bind dup dup]\n");
"{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n"
"{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n"
"{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n",
White.X, White.Y, White.Z);
return;
}
Writef(m,"%% Bradford Cone Space\n"
"/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
// No BPC
if (!DoBPC) {
......@@ -1414,6 +1433,7 @@ void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute)
static
void EmitXYZ2Lab(LPMEMSTREAM m)
{
Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
Writef(m, "/EncodeLMN [\n");
Writef(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
Writef(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
......@@ -1423,18 +1443,11 @@ void EmitXYZ2Lab(LPMEMSTREAM m)
Writef(m, "/EncodeABC [\n");
Writef(m, "{ 116 mul 16 sub 100 div } bind\n");
Writef(m, "{ 500 mul 128 add 255 div } bind\n");
Writef(m, "{ 200 mul 128 add 255 div } bind\n");
Writef(m, "{ 500 mul 128 add 256 div } bind\n");
Writef(m, "{ 200 mul 128 add 256 div } bind\n");
/*
Writef(m, "{ 116 mul 16 sub 256 mul 25700 div } bind\n");
Writef(m, "{ 500 mul 128 add 256 mul 65535 div } bind\n");
Writef(m, "{ 200 mul 128 add 256 mul 65535 div } bind\n");
*/
Writef(m, "]\n");
......@@ -1458,20 +1471,27 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
LPLUT DeviceLink;
cmsHPROFILE Profiles[3];
cmsCIEXYZ BlackPointAdaptedToD50;
BOOL lFreeDeviceLink = FALSE;
BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
LCMSBOOL lFreeDeviceLink = FALSE;
LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
int RelativeEncodingIntent;
// Trick our v4 profile as it were v2. This prevents the ajusting done
// in perceptual & saturation. We only neew v4 encoding!
hLab = cmsCreateLab4Profile(NULL);
cmsSetProfileICCversion(hLab, 0);
hLab = cmsCreateLabProfile(NULL);
ColorSpace = cmsGetColorSpace(hProfile);
nChannels = _cmsChannelsOf(ColorSpace);
OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
// For absolute colorimetric, the LUT is encoded as relative
// in order to preserve precission.
RelativeEncodingIntent = Intent;
if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC)
RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC;
// Is a devicelink profile?
if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
......@@ -1479,13 +1499,14 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
if (ColorSpace == icSigLabData) {
// adjust input to Lab to out v4
// adjust input to Lab to our v4
Profiles[0] = hLab;
Profiles[1] = hProfile;
xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL,
OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
OutputFormat, RelativeEncodingIntent,
dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
}
else {
......@@ -1499,7 +1520,7 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
// This is a normal profile
xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile,
OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION);
OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
}
if (xform == NULL) {
......@@ -1515,7 +1536,7 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
if (!DeviceLink) {
DeviceLink = _cmsPrecalculateDeviceLink(xform, 0);
DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION);
lFreeDeviceLink = TRUE;
}
......@@ -1527,7 +1548,7 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
// Emit headers, etc.
EmitWhiteBlackD50(m, &BlackPointAdaptedToD50);
EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
EmitXYZ2Lab(m);
if (DeviceLink ->wFlags & LUT_HASTL1) {
......@@ -1544,10 +1565,13 @@ int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlag
// zero. This would sacrifice a bit of highlights, but failure to do so would cause
// scum dot. Ouch.
if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
lFixWhite = FALSE;
Writef(m, "/RenderTable ");
WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE,
(Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace);
lFixWhite, ColorSpace);
Writef(m, " %d {} bind ", nChannels);
......@@ -1582,6 +1606,9 @@ void BuildColorantList(char *Colorant, int nColorant, WORD Out[])
int j;
Colorant[0] = 0;
if (nColorant > MAXCHANNELS)
nColorant = MAXCHANNELS;
for (j=0; j < nColorant; j++) {
sprintf(Buff, "%.3f", Out[j] / 65535.0);
......@@ -1677,7 +1704,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile,
if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) {
free((void*) mem);
_cmsFree((void*) mem);
return 0;
}
}
......@@ -1687,7 +1714,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile,
if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
free((void*) mem);
_cmsFree((void*) mem);
return 0;
}
}
......@@ -1702,7 +1729,7 @@ DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile,
dwBytesUsed = mem ->dwUsed;
// Get rid of memory stream
free((void*) mem);
_cmsFree((void*) mem);
// Finally, return used byte count
return dwBytesUsed;
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -120,7 +120,7 @@ int ComponentOf(int n, int clut, int nColorant)
// This routine does a sweep on whole input space, and calls its callback
// function on knots. returns TRUE if all ok, FALSE otherwise.
BOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags)
LCMSBOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags)
{
int i, t, nTotalPoints, Colorant, index;
WORD In[MAXCHANNELS], Out[MAXCHANNELS];
......@@ -145,12 +145,16 @@ BOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DW
&Lut -> In16params);
}
for (t=0; t < (int) Lut -> OutputChan; t++)
Out[t] = Lut->T[index + t];
// if (dwFlags & SAMPLER_INSPECT) {
if (dwFlags & SAMPLER_HASTL2) {
for (t=0; t < (int) Lut -> OutputChan; t++)
Out[t] = Lut->T[index + t];
// }
Out[t] = cmsLinearInterpLUT16(Out[t],
Lut -> L2[t],
&Lut -> Out16params);
}
if (!Sampler(In, Out, Cargo))
......@@ -255,9 +259,11 @@ LPLUT _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags)
LPLUT Grid;
int nGridPoints;
DWORD dwFormatIn, dwFormatOut;
DWORD SaveFormatIn, SaveFormatOut;
int ChannelsIn, ChannelsOut;
LPLUT SaveGamutLUT;
// Remove any gamut checking
SaveGamutLUT = p ->Gamut;
p ->Gamut = NULL;
......@@ -276,8 +282,13 @@ LPLUT _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags)
dwFormatIn = (CHANNELS_SH(ChannelsIn)|BYTES_SH(2));
dwFormatOut = (CHANNELS_SH(ChannelsOut)|BYTES_SH(2));
p -> FromInput = _cmsIdentifyInputFormat(p, dwFormatIn);
p -> ToOutput = _cmsIdentifyOutputFormat(p, dwFormatOut);
SaveFormatIn = p ->InputFormat;
SaveFormatOut = p ->OutputFormat;
p -> InputFormat = dwFormatIn;
p -> OutputFormat = dwFormatOut;
p -> FromInput = _cmsIdentifyInputFormat(p, dwFormatIn);
p -> ToOutput = _cmsIdentifyOutputFormat(p, dwFormatOut);
// Fix gamut & gamma possible mismatches.
......@@ -289,7 +300,6 @@ LPLUT _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags)
_cmsComputePrelinearizationTablesFromXFORM(hOne, 1, Grid);
}
// Attention to this typecast! we can take the luxury to
// do this since cmsHTRANSFORM is only an alias to a pointer
// to the transform struct.
......@@ -297,11 +307,13 @@ LPLUT _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags)
if (!cmsSample3DGrid(Grid, XFormSampler, (LPVOID) p, Grid -> wFlags)) {
cmsFreeLUT(Grid);
return NULL;
Grid = NULL;
}
p ->Gamut = SaveGamutLUT;
p ->InputFormat = SaveFormatIn;
p ->OutputFormat = SaveFormatOut;
p ->Gamut = SaveGamutLUT;
return Grid;
}
......@@ -348,7 +360,7 @@ int BlackPreservingGrayOnlySampler(register WORD In[], register WORD Out[], regi
// That is our K-preserving callback.
// Preserve all K plane.
static
int BlackPreservingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
{
......@@ -469,6 +481,7 @@ int LCMSEXPORT cmsSetCMYKPreservationStrategy(int n)
return OldVal;
}
#pragma warning(disable: 4550)
// Get a pointer to callback on depending of strategy
static
......@@ -504,11 +517,10 @@ LPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD
if (p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)
LocalFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
// Fill in cargo struct
Cargo.cmyk2cmyk = hCMYK2CMYK;
// Compute tone curve
// Compute tone curve.
Cargo.KTone = _cmsBuildKToneCurve(hCMYK2CMYK, 256);
if (Cargo.KTone == NULL) return NULL;
cmsCalcL16Params(Cargo.KTone ->nEntries, &Cargo.KToneParams);
......@@ -522,11 +534,11 @@ LPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD
Cargo.LabK2cmyk = cmsReadICCLut(p->OutputProfile, Device2PCS[p->Intent]);
// Is there any table available?
if (Cargo.LabK2cmyk == NULL) {
if (Cargo.LabK2cmyk == NULL) {
Grid = NULL;
Grid = NULL;
goto Cleanup;
}
}
// Setup a roundtrip on output profile for TAC estimation
Cargo.hRoundTrip = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16,
......@@ -654,7 +666,7 @@ void PatchLUT(LPLUT Grid, WORD At[], WORD Value[],
BOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
LCMSBOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
{
WORD *WhitePointIn, *WhitePointOut, *BlackPointIn, *BlackPointOut;
......@@ -682,3 +694,4 @@ BOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
return TRUE;
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -320,7 +320,7 @@ cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD d
cmsHPROFILE hICC;
_LPcmsTRANSFORM v = (_LPcmsTRANSFORM) hTransform;
LPLUT Lut;
BOOL MustFreeLUT;
LCMSBOOL MustFreeLUT;
LPcmsNAMEDCOLORLIST InputColorant = NULL;
LPcmsNAMEDCOLORLIST OutputColorant = NULL;
......@@ -373,10 +373,8 @@ cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD d
if (cmsGetDeviceClass(hICC) == icSigOutputClass) {
cmsAddTag(hICC, icSigBToA0Tag, (LPVOID) Lut);
}
else
cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
......@@ -404,7 +402,7 @@ cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD d
OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableTag);
}
}
}
if (InputColorant)
cmsAddTag(hICC, icSigColorantTableTag, InputColorant);
......@@ -446,6 +444,7 @@ cmsHPROFILE LCMSEXPORT cmsCreateLinearizationDeviceLink(icColorSpaceSignature Co
// Creates a LUT with prelinearization step only
Lut = cmsAllocLUT();
if (Lut == NULL) return NULL;
// Set up channels
Lut ->InputChan = Lut ->OutputChan = _cmsChannelsOf(ColorSpace);
......@@ -548,6 +547,10 @@ cmsHPROFILE LCMSEXPORT cmsCreateInkLimitingDeviceLink(icColorSpaceSignature Colo
// Creates a LUT with 3D grid only
Lut = cmsAllocLUT();
if (Lut == NULL) {
cmsCloseProfile(hICC);
return NULL;
}
cmsAlloc3DGrid(Lut, 17, _cmsChannelsOf(ColorSpace),
......@@ -584,8 +587,9 @@ static
LPLUT Create3x3EmptyLUT(void)
{
LPLUT AToB0 = cmsAllocLUT();
AToB0 -> InputChan = AToB0 -> OutputChan = 3;
if (AToB0 == NULL) return NULL;
AToB0 -> InputChan = AToB0 -> OutputChan = 3;
return AToB0;
}
......@@ -597,8 +601,8 @@ cmsHPROFILE LCMSEXPORT cmsCreateLabProfile(LPcmsCIExyY WhitePoint)
cmsHPROFILE hProfile;
LPLUT Lut;
hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetDeviceClass(hProfile, icSigAbstractClass);
cmsSetColorSpace(hProfile, icSigLabData);
......@@ -611,7 +615,10 @@ cmsHPROFILE LCMSEXPORT cmsCreateLabProfile(LPcmsCIExyY WhitePoint)
// An empty LUTs is all we need
Lut = Create3x3EmptyLUT();
if (Lut == NULL) return NULL;
if (Lut == NULL) {
cmsCloseProfile(hProfile);
return NULL;
}
cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut);
cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut);
......@@ -628,8 +635,8 @@ cmsHPROFILE LCMSEXPORT cmsCreateLab4Profile(LPcmsCIExyY WhitePoint)
cmsHPROFILE hProfile;
LPLUT Lut;
hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetProfileICCversion(hProfile, 0x4000000);
......@@ -644,7 +651,10 @@ cmsHPROFILE LCMSEXPORT cmsCreateLab4Profile(LPcmsCIExyY WhitePoint)
// An empty LUTs is all we need
Lut = Create3x3EmptyLUT();
if (Lut == NULL) return NULL;
if (Lut == NULL) {
cmsCloseProfile(hProfile);
return NULL;
}
Lut -> wFlags |= LUT_V4_INPUT_EMULATE_V2;
cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut);
......@@ -666,6 +676,7 @@ cmsHPROFILE LCMSEXPORT cmsCreateXYZProfile(void)
LPLUT Lut;
hProfile = cmsCreateRGBProfile(cmsD50_xyY(), NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetDeviceClass(hProfile, icSigAbstractClass);
cmsSetColorSpace(hProfile, icSigXYZData);
......@@ -677,15 +688,16 @@ cmsHPROFILE LCMSEXPORT cmsCreateXYZProfile(void)
// An empty LUTs is all we need
Lut = Create3x3EmptyLUT();
if (Lut == NULL) return NULL;
if (Lut == NULL) {
cmsCloseProfile(hProfile);
return NULL;
}
cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut);
cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut);
cmsAddTag(hProfile, icSigPreview0Tag, (LPVOID) Lut);
cmsFreeLUT(Lut);
return hProfile;
}
......@@ -723,6 +735,7 @@ LPGAMMATABLE Build_sRGBGamma(void)
return cmsBuildParametricGamma(1024, 4, Parameters);
}
// Create the ICC virtual profile for sRGB space
cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void)
{
cmsCIExyY D65;
......@@ -739,6 +752,7 @@ cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void)
hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma22);
cmsFreeGamma(Gamma22[0]);
if (hsRGB == NULL) return NULL;
cmsAddTag(hsRGB, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)");
......@@ -750,7 +764,6 @@ cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void)
typedef struct {
double Brightness;
double Contrast;
......@@ -793,7 +806,6 @@ int bchswSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
cmsFloat2LabEncoded(Out, &LabOut);
return TRUE;
}
......@@ -839,7 +851,10 @@ cmsHPROFILE LCMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
// Creates a LUT with 3D grid only
Lut = cmsAllocLUT();
if (Lut == NULL) {
cmsCloseProfile(hICC);
return NULL;
}
cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3);
......@@ -890,7 +905,10 @@ cmsHPROFILE LCMSEXPORT cmsCreateNULLProfile(void)
// An empty LUTs is all we need
Lut = cmsAllocLUT();
if (Lut == NULL) return NULL;
if (Lut == NULL) {
cmsCloseProfile(hProfile);
return NULL;
}
Lut -> InputChan = 3;
Lut -> OutputChan = 1;
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -51,10 +51,6 @@
#include "lcms.h"
// Uncomment this line if you want lcms to use the black point tag in profile,
// if commented, lcms will compute the black point by its own.
// It is safer to leve it commented out
// #define HONOR_BLACK_POINT_TAG
// Conversions
......@@ -79,10 +75,9 @@ void LCMSEXPORT cmsxyY2XYZ(LPcmsCIEXYZ Dest, const cmsCIExyY* Source)
}
// Obtains WhitePoint from Temperature
BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
{
double x, y;
double T, T2, T3;
......@@ -147,7 +142,7 @@ BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
// - Then, I apply these coeficients to the original matrix
BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
LPcmsCIExyYTRIPLE Primrs)
{
VEC3 WhitePoint, Coef;
......@@ -169,14 +164,12 @@ BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
// Build Primaries matrix
VEC3init(&Primaries.v[0], xr, xg, xb);
VEC3init(&Primaries.v[1], yr, yg, yb);
VEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg), (1-xb-yb));
// Result = Primaries ^ (-1) inverse matrix
if (!MAT3inverse(&Primaries, &Result))
return FALSE;
......@@ -184,11 +177,9 @@ BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
VEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
// Across inverse primaries ...
MAT3eval(&Coef, &Result, &WhitePoint);
// Give us the Coefs, then I build transformation matrix
VEC3init(&r -> v[0], Coef.n[VX]*xr, Coef.n[VY]*xg, Coef.n[VZ]*xb);
VEC3init(&r -> v[1], Coef.n[VX]*yr, Coef.n[VY]*yg, Coef.n[VZ]*yb);
VEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
......@@ -246,7 +237,7 @@ void ComputeChromaticAdaptation(LPMAT3 Conversion,
// Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll
// The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed
BOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll)
LCMSBOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll)
{
MAT3 LamRigg = {{ // Bradford matrix
{{ 0.8951, 0.2664, -0.1614 }},
......@@ -265,7 +256,7 @@ BOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcms
// Same as anterior, but assuming D50 destination. White point is given in xyY
BOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
LCMSBOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
{
cmsCIEXYZ Dn;
MAT3 Bradford;
......@@ -284,7 +275,7 @@ BOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
// Same as anterior, but assuming D50 source. White point is given in xyY
BOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
LCMSBOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
{
cmsCIEXYZ Dn;
MAT3 Bradford;
......@@ -304,7 +295,7 @@ BOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
// Adapts a color to a given illuminant. Original color is expected to have
// a SourceWhitePt white point.
BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
LPcmsCIEXYZ SourceWhitePt,
LPcmsCIEXYZ Illuminant,
LPcmsCIEXYZ Value)
......@@ -404,8 +395,6 @@ double Robertson(LPcmsCIExyY v)
dj = ((vs - vj) - tj * (us - uj)) / sqrt(1 + tj*tj);
if ((j!=0) && (di/dj < 0.0)) {
Tc = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
break;
......@@ -423,7 +412,7 @@ double Robertson(LPcmsCIExyY v)
static
BOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance)
LCMSBOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance)
{
double dist_x, dist_y;
......@@ -458,6 +447,7 @@ int FromD40toD150(LPWHITEPOINTS pts)
}
// To be removed in future versions
void _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt)
{
int i, n;
......@@ -518,7 +508,6 @@ int BlackPointAsDarkerColorant(cmsHPROFILE hInput,
cmsCIEXYZ BlackXYZ, MediaWhite;
// If the profile does not support input direction, assume Black point 0
if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {
BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
......@@ -527,7 +516,6 @@ int BlackPointAsDarkerColorant(cmsHPROFILE hInput,
// Try to get black by using black colorant
Space = cmsGetColorSpace(hInput);
if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) {
......@@ -576,7 +564,7 @@ int BlackPointAsDarkerColorant(cmsHPROFILE hInput,
// Get a black point of output CMYK profile, discounting any ink-limiting embedded
// in the profile. Fou doing that, use perceptual intent in input direction:
// in the profile. For doing that, use perceptual intent in input direction:
// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
static
......@@ -651,6 +639,8 @@ int GetV4PerceptualBlack(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, DWORD dwF
D50BlackPoint.X = PERCEPTUAL_BLACK_X;
D50BlackPoint.Y = PERCEPTUAL_BLACK_Y;
D50BlackPoint.Z = PERCEPTUAL_BLACK_Z;
// Obtain the absolute XYZ. Adapt perceptual black back from D50 to whatever media white
cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &D50BlackPoint);
}
......@@ -662,26 +652,24 @@ int GetV4PerceptualBlack(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, DWORD dwF
// This function shouldn't exist at all -- there is such quantity of broken
// profiles on black point tag, that we must somehow fix chromaticity to
// avoid huge tint when doing Black point compensation. This function does
// just that. If BP is specified, then forces it to neutral and uses only L
// component. If does not exist, computes it by taking 400% of ink or RGB=0 This
// works well on relative intent and is undefined on perceptual & saturation.
// However, I will support all intents for tricking & trapping.
// just that. There is a special flag for using black point tag, but turned
// off by default because it is bogus on most profiles. The detection algorithm
// involves to turn BP to neutral and to use only L component.
int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags)
{
// v4 + perceptual & saturation intents does have its own black point
// v4 + perceptual & saturation intents does have its own black point, and it is
// well specified enough to use it.
if ((cmsGetProfileICCversion(hProfile) >= 0x4000000) &&
(Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
// Matrix shaper share MRC & perceptual intents
if (_cmsIsMatrixShaper(hProfile))
return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, cmsFLAGS_NOTPRECALC);
// Get fixed value
// CLUT based - Get perceptual black point (fixed value)
return GetV4PerceptualBlack(BlackPoint, hProfile, dwFlags);
}
......@@ -701,7 +689,6 @@ int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent
cmsTakeMediaWhitePoint(&MediaWhite, hProfile);
// Black point is absolute XYZ, so adapt to D50 to get PCS value
cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ);
// Force a=b=0 to get rid of any chroma
......@@ -713,7 +700,6 @@ int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent
cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab);
// Return BP as D50 relative or absolute XYZ (depends on flags)
if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED))
cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &TrustedBlackPoint);
else
......@@ -724,15 +710,15 @@ int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent
#endif
// If output profile, discount ink-limiting
// That is about v2 profiles.
// If output profile, discount ink-limiting and that's all
if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
(cmsGetDeviceClass(hProfile) == icSigOutputClass) &&
(cmsGetColorSpace(hProfile) == icSigCmykData))
return BlackPointUsingPerceptualBlack(BlackPoint, hProfile, dwFlags);
// Nope, compute BP using current intent.
return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags);
}
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -52,7 +52,6 @@
#include "lcms.h"
// #define DEBUG 1
// Transformations stuff
// -----------------------------------------------------------------------
......@@ -85,7 +84,7 @@ void LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b);
void LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b);
BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
int Intent, int UsedDirection);
// -------------------------------------------------------------------------
......@@ -343,7 +342,7 @@ void PrecalculatedXFORM(_LPcmsTRANSFORM p,
p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
p ->DeviceLink -> T,
&p ->DeviceLink -> CLut16params);
}
}
else
cmsEvalLUT(p -> DeviceLink, wIn, wOut);
......@@ -414,7 +413,7 @@ void CachedXFORM(_LPcmsTRANSFORM p,
register LPBYTE output;
WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
register unsigned int i, n;
WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
accum = (LPBYTE) in;
......@@ -427,10 +426,10 @@ void CachedXFORM(_LPcmsTRANSFORM p,
ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
LCMS_READ_LOCK(&p ->rwlock);
CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
LCMS_READ_LOCK(&p ->rwlock);
CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
for (i=0; i < n; i++) {
......@@ -443,14 +442,14 @@ void CachedXFORM(_LPcmsTRANSFORM p,
}
else {
// Try to speedup things on plain devicelinks
// Try to speedup things on plain devicelinks
if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
p ->DeviceLink -> T,
&p ->DeviceLink -> CLut16params);
}
}
else
cmsEvalLUT(p -> DeviceLink, wIn, wOut);
......@@ -463,10 +462,10 @@ void CachedXFORM(_LPcmsTRANSFORM p,
}
LCMS_WRITE_LOCK(&p ->rwlock);
CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
LCMS_WRITE_LOCK(&p ->rwlock);
CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
}
......@@ -483,7 +482,7 @@ void CachedXFORMGamutCheck(_LPcmsTRANSFORM p,
register LPBYTE output;
WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
register unsigned int i, n;
WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
accum = (LPBYTE) in;
......@@ -495,10 +494,10 @@ void CachedXFORMGamutCheck(_LPcmsTRANSFORM p,
ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS);
ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
LCMS_READ_LOCK(&p ->rwlock);
CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
LCMS_READ_LOCK(&p ->rwlock);
CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
for (i=0; i < n; i++) {
......@@ -520,10 +519,10 @@ void CachedXFORMGamutCheck(_LPcmsTRANSFORM p,
output = p -> ToOutput(p, wOut, output);
}
LCMS_WRITE_LOCK(&p ->rwlock);
CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
LCMS_WRITE_LOCK(&p ->rwlock);
CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS);
CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
LCMS_UNLOCK(&p ->rwlock);
}
......@@ -635,6 +634,8 @@ LPMATSHAPER cmsBuildGrayInputMatrixShaper(cmsHPROFILE hProfile)
MAT3 Scale;
GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag); // Y
if (GrayTRC == NULL) return NULL;
cmsTakeIluminant(&Illuminant, hProfile);
if (cmsGetPCS(hProfile) == icSigLabData) {
......@@ -789,6 +790,10 @@ LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag);
InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag);
if (InverseShapes[0] == NULL ||
InverseShapes[1] == NULL ||
InverseShapes[2] == NULL) return NULL;
OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT);
cmsFreeGammaTriple(InverseShapes);
......@@ -801,7 +806,7 @@ LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
// This function builds a transform matrix chaining parameters
static
BOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
{
MAT3 From, To, ToInv, Transfer;
LPGAMMATABLE In[3], InverseOut[3];
......@@ -814,7 +819,6 @@ BOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
if (!cmsReadICCMatrixRGB2XYZ(&To, p -> OutputProfile))
return FALSE;
// invert dest
if (MAT3inverse(&To, &ToInv) < 0)
......@@ -838,10 +842,14 @@ BOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag);
InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag);
if (!InverseOut[0] || !InverseOut[1] || !InverseOut[2]) {
cmsFreeGammaTriple(In);
return FALSE;
}
p -> SmeltMatShaper = cmsAllocMatShaper2(&Transfer, In, InverseOut, MATSHAPER_ALLSMELTED);
cmsFreeGammaTriple(In);
cmsFreeGammaTriple(InverseOut);
return (p -> SmeltMatShaper != NULL);
......@@ -1029,7 +1037,7 @@ void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
// Check colorspace
static
BOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, BOOL lUsePCS)
LCMSBOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, LCMSBOOL lUsePCS)
{
int Space = T_COLORSPACE(dwFormat);
......@@ -1049,10 +1057,10 @@ _LPcmsTRANSFORM AllocEmptyTransform(void)
{
// Allocate needed memory
_LPcmsTRANSFORM p = (_LPcmsTRANSFORM) malloc(sizeof(_cmsTRANSFORM));
_LPcmsTRANSFORM p = (_LPcmsTRANSFORM) _cmsMalloc(sizeof(_cmsTRANSFORM));
if (!p) {
cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: malloc() failed");
cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: _cmsMalloc() failed");
return NULL;
}
......@@ -1078,7 +1086,7 @@ _LPcmsTRANSFORM AllocEmptyTransform(void)
p -> ExitColorSpace = (icColorSpaceSignature) 0;
p -> AdaptationState = GlobalAdaptationState;
LCMS_CREATE_LOCK(&p->rwlock);
LCMS_CREATE_LOCK(&p->rwlock);
return p;
}
......@@ -1269,12 +1277,12 @@ _LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
else {
// Can we optimize matrix-shaper only transform?
if (*FromTagPtr == 0 &&
*ToTagPtr == 0 &&
!p->PreviewProfile &&
p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC &&
if ((*FromTagPtr == 0) &&
(*ToTagPtr == 0) &&
(!p->PreviewProfile) &&
(p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
(p -> EntryColorSpace == icSigRgbData) &&
(p -> ExitColorSpace == icSigRgbData) &&
(p -> ExitColorSpace == icSigRgbData) &&
!(p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)) {
// Yes... try to smelt matrix-shapers
......@@ -1530,7 +1538,6 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
TakeConversionRoutines(p, dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
if (!(p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
LPLUT DeviceLink;
......@@ -1553,7 +1560,8 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
}
if (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK) {
// Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given
if ((p ->PreviewProfile != NULL) && (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK)) {
GamutCheck = _cmsPrecalculateGamutCheck((cmsHTRANSFORM) p);
}
......@@ -1561,7 +1569,6 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
// If input colorspace is Rgb, Cmy, then use tetrahedral interpolation
// for speed reasons (it only works well on spaces on Luma is diagonal, and
// not if luma is in separate channel)
if (p ->EntryColorSpace == icSigRgbData ||
p ->EntryColorSpace == icSigCmyData) {
......@@ -1663,12 +1670,12 @@ void LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
cmsFreeMatShaper(p -> SmeltMatShaper);
if (p ->NamedColorList)
cmsFreeNamedColorList(p ->NamedColorList);
if (p -> GamutCheck)
cmsFreeLUT(p -> GamutCheck);
if (p -> GamutCheck)
cmsFreeLUT(p -> GamutCheck);
LCMS_FREE_LOCK(&p->rwlock);
LCMS_FREE_LOCK(&p->rwlock);
free((void *) p);
_cmsFree((void *) p);
}
......@@ -1704,7 +1711,7 @@ void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b)
// Returns TRUE if the profile is implemented as matrix-shaper
BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
{
switch (cmsGetColorSpace(hProfile)) {
......@@ -1728,7 +1735,7 @@ BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
}
BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
int Intent, int UsedDirection)
{
......@@ -1774,6 +1781,16 @@ int MultiprofileSampler(register WORD In[], register WORD Out[], register LPVOID
}
static
int IsAllowedInSingleXform(icProfileClassSignature aClass)
{
return (aClass == icSigInputClass) ||
(aClass == icSigDisplayClass) ||
(aClass == icSigOutputClass) ||
(aClass == icSigColorSpaceClass);
}
// A multiprofile transform does chain several profiles into a single
// devicelink. It couls also be used to merge named color profiles into
// a single database.
......@@ -1805,10 +1822,16 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
// There is a simple case with just two profiles, try to catch it in order of getting
// black preservation to work on this function, at least with two profiles.
if (nProfiles == 2) {
if ((cmsGetDeviceClass(hProfiles[0]) != icSigLinkClass) &&
(cmsGetDeviceClass(hProfiles[1]) != icSigLinkClass))
icProfileClassSignature Class1 = cmsGetDeviceClass(hProfiles[0]);
icProfileClassSignature Class2 = cmsGetDeviceClass(hProfiles[1]);
// Only input, output and display are allowed
if (IsAllowedInSingleXform(Class1) &&
IsAllowedInSingleXform(Class2))
return cmsCreateTransform(hProfiles[0], dwInput, hProfiles[1], dwOutput, Intent, dwFlags);
}
......@@ -1984,6 +2007,14 @@ cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
if (hLab) cmsCloseProfile(hLab);
if (hXYZ) cmsCloseProfile(hXYZ);
if (p ->EntryColorSpace == icSigRgbData ||
p ->EntryColorSpace == icSigCmyData) {
p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
}
if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
!(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
_cmsFixWhiteMisalignment(p);
......
......@@ -206,6 +206,11 @@ typedef __int32_t icInt64Number[2];
#if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__)
#if defined (__MINGW) || defined(__MINGW32__)
#include <stdint.h>
#endif
typedef uint8_t icUInt8Number;
typedef uint16_t icUInt16Number;
typedef uint32_t icUInt32Number;
......
......@@ -29,7 +29,7 @@
//
//
// Little cms
// Copyright (C) 1998-2006 Marti Maria
// Copyright (C) 1998-2007 Marti Maria
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -49,8 +49,8 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Version 1.16
#undef DEBUG
// Version 1.18
#ifndef __cms_H
// ********** Configuration toggles ****************************************
......@@ -62,13 +62,8 @@
// virtually any machine.
//#define USE_FLOAT 1
#ifdef _WIN64
#define USE_C 1
#undef USE_ASSEMBLER
#else
#undef USE_C
// #define USE_C 1
#define USE_ASSEMBLER 1
#endif
// Define this if you are using this package as a DLL (windows only)
......@@ -77,15 +72,11 @@
// Uncomment if you are trying the engine in a non-windows environment
// like linux, SGI, VAX, FreeBSD, BeOS, etc.
#if !defined(_WIN32) || !defined(_WIN64)
#define NON_WINDOWS 1
#endif
// Uncomment this one if you are using big endian machines (only meaningful
// when NON_WINDOWS is used)
#ifndef _LITTLE_ENDIAN
#define USE_BIG_ENDIAN 1
#endif
// #define USE_BIG_ENDIAN 1
// Uncomment this one if your compiler/machine does support the
// "long long" type This will speedup fixed point math. (USE_C only)
......@@ -104,18 +95,24 @@
// Uncomment this line on multithreading environments
// #define USE_PTHREADS 1
// Uncomment this line if you want lcms to use the black point tag in profile,
// if commented, lcms will compute the black point by its own.
// It is safer to leve it commented out
// #define HONOR_BLACK_POINT_TAG 1
// ********** End of configuration toggles ******************************
#define LCMS_VERSION 116
#define LCMS_VERSION 118
// Microsoft VisualC++
// Deal with Microsoft's attempt at deprecating C standard runtime functions
#ifdef _MSC_VER
# undef NON_WINDOWS
# if (_MSC_VER >= 1400)
# ifndef _CRT_SECURE_NO_DEPRECATE
# define _CRT_SECURE_NO_DEPRECATE 1
# endif
# endif
#endif
......@@ -125,7 +122,6 @@
# undef NON_WINDOWS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
......@@ -134,11 +130,11 @@
#include <time.h>
// Metroworks CodeWarrior
#ifdef __MWERKS__
# define unlink remove
# if WIN32
# define USE_CUSTOM_SWAB 1
# undef NON_WINDOWS
# else
# define NON_WINDOWS 1
# endif
......@@ -172,15 +168,21 @@ typedef pthread_rwlock_t LCMS_RWLOCK_T;
# define USE_BIG_ENDIAN 1
#endif
#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__)
#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__) || defined(__s390__) || defined(__s390x__)
# define USE_BIG_ENDIAN 1
#endif
#ifdef TARGET_CPU_PPC
#if TARGET_CPU_PPC
# define USE_BIG_ENDIAN 1
#endif
#ifdef macintosh
#if macintosh
# ifndef __LITTLE_ENDIAN__
# define USE_BIG_ENDIAN 1
# endif
#endif
#ifdef __BIG_ENDIAN__
# define USE_BIG_ENDIAN 1
#endif
......@@ -217,11 +219,8 @@ typedef pthread_rwlock_t LCMS_RWLOCK_T;
typedef unsigned char BYTE, *LPBYTE;
typedef unsigned short WORD, *LPWORD;
typedef unsigned long DWORD, *LPDWORD;
typedef int BOOL;
typedef char *LPSTR;
typedef void *LPVOID;
typedef void* LCMSHANDLE;
#define ZeroMemory(p,l) memset((p),0,(l))
#define CopyMemory(d,s,l) memcpy((d),(s),(l))
......@@ -263,8 +262,12 @@ typedef void* LCMSHANDLE;
#include <windows.h>
typedef HANDLE LCMSHANDLE;
#ifdef _WIN64
# ifdef USE_ASSEMBLER
# undef USE_ASSEMBLER
# define USE_C 1
# endif
#endif
#ifdef USE_INT64
# ifndef LCMSULONGLONG
......@@ -296,6 +299,10 @@ typedef int LCMS_RWLOCK_T;
# define LCMS_UNLOCK(x)
#endif
// Base types
typedef int LCMSBOOL;
typedef void* LCMSHANDLE;
#include "icc34.h" // ICC header file
......@@ -322,16 +329,10 @@ typedef int LCMS_RWLOCK_T;
#define icSigMCHEData ((icColorSpaceSignature) 0x4d434845L) // MCHE
#define icSigMCHFData ((icColorSpaceSignature) 0x4d434846L) // MCHF
#define icSigCAM97JABData ((icColorSpaceSignature) 0x4A616231L) // 'Jab1' H. Zeng
#define icSigCAM02JABData ((icColorSpaceSignature) 0x4A616232L) // 'Jab2' H. Zeng
#define icSigCAM02JCHData ((icColorSpaceSignature) 0x4A636A32L) // 'Jch2' H. Zeng
#define icSigChromaticityTag ((icTagSignature) 0x6368726dL) // As per Addendum 2 to Spec. ICC.1:1998-09
#define icSigChromaticAdaptationTag ((icTagSignature) 0x63686164L) // 'chad'
#define icSigColorantTableTag ((icTagSignature) 0x636c7274L) // 'clrt'
#define icSigColorantTableOutTag ((icTagSignature) 0x636c6f74L) // 'clot'
#define icSigHPGamutDescTag ((icTagSignature) 0x676D7441L) // 'gmtA' H. Zeng
#define icSigParametricCurveType ((icTagTypeSignature) 0x70617261L) // parametric (ICC 4.0)
#define icSigMultiLocalizedUnicodeType ((icTagTypeSignature) 0x6D6C7563L)
......@@ -340,7 +341,6 @@ typedef int LCMS_RWLOCK_T;
#define icSiglutAtoBType ((icTagTypeSignature) 0x6d414220L) // mAB
#define icSiglutBtoAType ((icTagTypeSignature) 0x6d424120L) // mBA
#define icSigColorantTableType ((icTagTypeSignature) 0x636c7274L) // clrt
#define icSigHPGamutDescType ((icTagTypeSignature) 0x676D7441L) // gmtA H. Zeng
typedef struct {
......@@ -438,9 +438,6 @@ extern "C" {
#ifndef itoa
# define itoa _itoa
#endif
#ifndef filelength
# define filelength _filelength
#endif
#ifndef fileno
# define fileno _fileno
#endif
......@@ -450,6 +447,14 @@ extern "C" {
#ifndef hypot
# define hypot _hypot
#endif
#ifndef snprintf
# define snprintf _snprintf
#endif
#ifndef vsnprintf
# define vsnprintf _vsnprintf
#endif
#endif
......@@ -470,8 +475,9 @@ typedef LCMSHANDLE cmsHTRANSFORM;
// Format of pixel is defined by one DWORD, using bit fields as follows
//
// TTTTT U Y F P X S EEE CCCC BBB
// D TTTTT U Y F P X S EEE CCCC BBB
//
// D: Use dither (8 bits only)
// T: Pixeltype
// F: Flavor 0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla)
// P: Planar? 0=Chunky, 1=Planar
......@@ -483,6 +489,7 @@ typedef LCMSHANDLE cmsHTRANSFORM;
// Y: Swap first - changes ABGR to BGRA and KCMY to CMYK
#define DITHER_SH(s) ((s) << 22)
#define COLORSPACE_SH(s) ((s) << 16)
#define SWAPFIRST_SH(s) ((s) << 14)
#define FLAVOR_SH(s) ((s) << 13)
......@@ -711,20 +718,20 @@ typedef LCMSHANDLE cmsHTRANSFORM;
typedef struct {
unsigned int Crc32; // Has my table been touched?
unsigned int Crc32; // Has my table been touched?
// Keep initial parameters for further serialization
// Keep initial parameters for further serialization
int Type;
double Params[10];
} LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS;
} LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS;
// Gamma tables.
typedef struct {
LCMSGAMMAPARAMS Seed; // Parameters used for table creation
LCMSGAMMAPARAMS Seed; // Parameters used for table creation
// Table-based representation follows
......@@ -858,7 +865,7 @@ LCMSAPI LPcmsCIExyY LCMSEXPORT cmsD50_xyY(void);
LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess);
LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize);
LCMSAPI BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
// Predefined run-time profiles
......@@ -915,14 +922,14 @@ LCMSAPI double LCMSEXPORT cmsCIE2000DeltaE(LPcmsCIELab Lab1, LPcmsCIELab
LCMSAPI void LCMSEXPORT cmsClampLab(LPcmsCIELab Lab, double amax, double amin, double bmax, double bmin);
LCMSAPI BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint);
LCMSAPI LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint);
LCMSAPI BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
LCMSAPI LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
LPcmsCIEXYZ SourceWhitePt,
LPcmsCIEXYZ Illuminant,
LPcmsCIEXYZ Value);
LCMSAPI BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r,
LCMSAPI LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r,
LPcmsCIExyY WhitePoint,
LPcmsCIExyYTRIPLE Primaries);
......@@ -976,7 +983,7 @@ LCMSAPI LPGAMMATABLE LCMSEXPORT cmsDupGamma(LPGAMMATABLE Src);
LCMSAPI LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma);
LCMSAPI LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma);
LCMSAPI LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints);
LCMSAPI BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
LCMSAPI LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
LCMSAPI double LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t);
LCMSAPI double LCMSEXPORT cmsEstimateGammaEx(LPWORD Table, int nEntries, double Thereshold);
LCMSAPI LPGAMMATABLE LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig);
......@@ -984,14 +991,14 @@ LCMSAPI LPGAMMATABLE LCMSEXPORT cmsReadICCGammaReversed(cmsHPROFILE hProfile, i
// Access to Profile data.
LCMSAPI BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile);
LCMSAPI DWORD LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile);
LCMSAPI DWORD LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile);
LCMSAPI void LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode);
LCMSAPI void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4]);
LCMSAPI const char* LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile);
LCMSAPI const char* LCMSEXPORT cmsTakeProductDesc(cmsHPROFILE hProfile);
LCMSAPI const char* LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile);
......@@ -1000,13 +1007,13 @@ LCMSAPI const char* LCMSEXPORT cmsTakeModel(cmsHPROFILE hProfile);
LCMSAPI const char* LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile);
LCMSAPI const BYTE* LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig);
LCMSAPI int LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile);
LCMSAPI BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len);
LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len);
LCMSAPI int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Text, size_t size);
LCMSAPI int LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Text);
......@@ -1038,50 +1045,18 @@ LCMSAPI LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE h
LCMSAPI void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq);
// Extended gamut tag -- an HP extension
#define LCMSGAMUTMETHOD_SEGMENTMAXIMA 0
#define LCMSGAMUTMETHOD_CONVEXHULL 1
#define LCMSGAMUTMETHOD_ALPHASHAPE 2
#define LCMSGAMUT_PHYSICAL 0
#define LCMSGAMUT_HP1 1
#define LCMSGAMUT_HP2 2
typedef struct {
icColorSpaceSignature CoordSig; // Gamut coordinates signature
icUInt16Number Method; // Method used to generate gamut
icUInt16Number Usage; // Gamut usage or intent
char Description[LCMS_DESC_MAX]; // Textual description
cmsViewingConditions Vc; // The viewing conditions
icUInt32Number Count; // Number of entries
double Data[1]; // The current data
} cmsGAMUTEX, FAR* LPcmsGAMUTEX;
LCMSAPI LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index);
LCMSAPI void LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex);
// Translate form/to our notation to ICC
LCMSAPI icColorSpaceSignature LCMSEXPORT _cmsICCcolorSpace(int OurNotation);
LCMSAPI int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace);
LCMSAPI int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace);
LCMSAPI BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile);
LCMSAPI int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace);
LCMSAPI int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile);
// How profiles may be used
#define LCMS_USED_AS_INPUT 0
#define LCMS_USED_AS_OUTPUT 1
#define LCMS_USED_AS_PROOF 2
LCMSAPI BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
LCMSAPI icColorSpaceSignature LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile);
LCMSAPI icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile);
......@@ -1141,7 +1116,7 @@ LCMSAPI void LCMSEXPORT cmsSetProfileID(cmsHPROFILE hProfile, LPBYTE Pr
// CRD special
#define cmsFLAGS_NODEFAULTRESOURCEDEF 0x00010000
#define cmsFLAGS_NODEFAULTRESOURCEDEF 0x01000000
// Gridpoints
......@@ -1220,9 +1195,9 @@ typedef struct {
// Named color support
LCMSAPI int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform);
LCMSAPI BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix);
LCMSAPI int LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name);
LCMSAPI int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform);
LCMSAPI LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix);
LCMSAPI int LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name);
// Colorant tables
......@@ -1230,7 +1205,7 @@ LCMSAPI LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile
// Profile creation
LCMSAPI BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data);
LCMSAPI LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data);
// Converts a transform to a devicelink profile
LCMSAPI cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags);
......@@ -1240,8 +1215,8 @@ LCMSAPI void LCMSEXPORT _cmsSetLUTdepth(cmsHPROFILE hProfile, int depth);
// Save profile
LCMSAPI BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName);
LCMSAPI BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
size_t* BytesNeeded);
......@@ -1286,6 +1261,7 @@ LCMSAPI double LCMSEXPORT cmsEvalLUTreverse(LPLUT Lut, WORD Target[], WORD Resul
LCMSAPI LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig);
LCMSAPI LPLUT LCMSEXPORT cmsDupLUT(LPLUT Orig);
// LUT Sampling
typedef int (* _cmsSAMPLER)(register WORD In[],
......@@ -1325,35 +1301,37 @@ LCMSAPI int LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable);
// Persistence
LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded);
// Properties
LCMSAPI const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
LCMSAPI const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
LCMSAPI double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames);
LCMSAPI const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames);
LCMSAPI int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
// Datasets
LCMSAPI const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
LCMSAPI double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int row, int col);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
const char* Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
double Val);
LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
......@@ -1361,25 +1339,28 @@ LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPa
LCMSAPI double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
const char* cSample,
const char *Val);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
const char* cSample,
double Val);
LCMSAPI int LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample);
LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
LCMSAPI int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
LCMSAPI const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer);
LCMSAPI int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cSample);
// The LABEL extension
LCMSAPI int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType);
LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample);
// Formatter for double
LCMSAPI void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
......@@ -1405,15 +1386,16 @@ LCMSAPI void LCMSEXPORT cmsFloat2XYZEncoded(WORD XYZ[3], const cmsCIEXY
// Profiling Extensions --- Would be removed from API in future revisions
LCMSAPI BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text);
LCMSAPI BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ);
LCMSAPI BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut);
LCMSAPI BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction);
LCMSAPI BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm);
LCMSAPI BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq);
LCMSAPI BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
LCMSAPI BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime);
LCMSAPI BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat);
// --------------------------------------------------------------------------------------------------- Inline functions
......@@ -1455,6 +1437,38 @@ LCMS_INLINE WORD _cmsClampWord(int in)
return (WORD) in;
}
#ifndef LCMS_USER_ALLOC
// Low-level alloc hook
LCMS_INLINE void* _cmsMalloc(size_t size)
{
if (size > ((size_t) 1024*1024*500)) return NULL; // Never allow over 500Mb
if (size < 0) return NULL; // Prevent signed size_t exploits
return (void*) malloc(size);
}
LCMS_INLINE void* _cmsCalloc(size_t nmemb, size_t size)
{
size_t alloc = nmemb * size;
if (size == 0) {
return _cmsMalloc(0);
}
if (alloc / size != nmemb) {
return NULL;
}
return _cmsMalloc(alloc);
}
LCMS_INLINE void _cmsFree(void *Ptr)
{
if (Ptr) free(Ptr);
}
#endif
// ------------------------------------------------------------------------------------------- end of inline functions
// Signal error from inside lcms code
......@@ -1531,36 +1545,36 @@ typedef struct { // Matrix (Fixed 15.16)
void cdecl VEC3init(LPVEC3 r, double x, double y, double z); // double version
void cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version
void cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
void cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v);
void cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
void cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
void cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
void cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
void cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
void cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
BOOL cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance);
BOOL cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance);
void cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
void cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
void cdecl VEC3saturate(LPVEC3 v);
double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
double cdecl VEC3length(LPVEC3 a);
void cdecl MAT3identity(LPMAT3 a);
void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
BOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
double cdecl MAT3det(LPMAT3 m);
void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
void cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v);
void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
BOOL cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance);
void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
void cdecl VEC3init(LPVEC3 r, double x, double y, double z); // double version
void cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version
void cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
void cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v);
void cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
void cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
void cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
void cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
void cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
void cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
LCMSBOOL cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance);
LCMSBOOL cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance);
void cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
void cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
void cdecl VEC3saturate(LPVEC3 v);
double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
double cdecl VEC3length(LPVEC3 a);
void cdecl MAT3identity(LPMAT3 a);
void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
LCMSBOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
double cdecl MAT3det(LPMAT3 m);
void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
void cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v);
void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
LCMSBOOL cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance);
void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
// Is a table linear?
......@@ -1608,7 +1622,7 @@ typedef struct _lcms_l16params_struc { // Used on 16 bits interpolations
void cdecl cmsCalcL16Params(int nSamples, LPL16PARAMS p);
void cdecl cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p);
void cdecl cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
BOOL lUseTetrahedral, LPL16PARAMS p);
LCMSBOOL lUseTetrahedral, LPL16PARAMS p);
WORD cdecl cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p);
Fixed32 cdecl cmsLinearInterpFixed(WORD Value1, WORD LutTable[], LPL16PARAMS p);
......@@ -1692,18 +1706,18 @@ struct _lcms_LUT_struc {
// Gray axes fixup. Only on v2 8-bit Lab LUT
BOOL FixGrayAxes;
LCMSBOOL FixGrayAxes;
// Parameters used for curve creation
// Parameters used for curve creation
LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS];
LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS];
}; // LUT, FAR* LPLUT;
BOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries);
LCMSBOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries);
// CRC of gamma tables
......@@ -1721,7 +1735,7 @@ LPGAMMATABLE cdecl cmsConvertSampledCurveToGamma(LPSAMPLEDCURVE Sampled, doubl
void cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
void cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
BOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
LCMSBOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
void cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
......@@ -1755,19 +1769,19 @@ LPMATSHAPER cdecl cmsAllocMatShaper2(LPMAT3 matrix, LPGAMMATABLE In[], LPGAMMATA
void cdecl cmsFreeMatShaper(LPMATSHAPER MatShaper);
void cdecl cmsEvalMatShaper(LPMATSHAPER MatShaper, WORD In[], WORD Out[]);
BOOL cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile);
LCMSBOOL cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile);
LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile);
LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile);
LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile);
LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile);
// White Point & Primary chromas handling
BOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll);
BOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt);
BOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt);
LCMSBOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll);
LCMSBOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt);
LCMSBOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt);
BOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile);
LCMSBOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile);
// Inter-PCS conversion routines. They assume D50 as white point.
void cdecl cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3]);
......@@ -1782,7 +1796,7 @@ WORD cdecl _cmsQuantizeVal(double i, int MaxSamples);
LPcmsNAMEDCOLORLIST cdecl cmsAllocNamedColorList(int n);
int cdecl cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSignature sig);
void cdecl cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST List);
BOOL cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]);
LCMSBOOL cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]);
// I/O
......@@ -1804,7 +1818,7 @@ typedef struct _lcms_iccprofile_struct {
icColorSpaceSignature PCS;
icRenderingIntent RenderingIntent;
icUInt32Number flags;
icUInt32Number attributes;
icUInt32Number attributes;
cmsCIEXYZ Illuminant;
// Additions for V4 profiles
......@@ -1826,22 +1840,23 @@ typedef struct _lcms_iccprofile_struct {
char PhysicalFile[MAX_PATH];
BOOL IsWrite;
BOOL SaveAs8Bits;
LCMSBOOL IsWrite;
LCMSBOOL SaveAs8Bits;
struct tm Created;
// I/O handlers
size_t (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc);
size_t (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc);
BOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
BOOL (* Close)(struct _lcms_iccprofile_struct* Icc);
size_t (* Tell)(struct _lcms_iccprofile_struct* Icc);
LCMSBOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
LCMSBOOL (* Close)(struct _lcms_iccprofile_struct* Icc);
size_t (* Tell)(struct _lcms_iccprofile_struct* Icc);
LCMSBOOL (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount);
// Writting
BOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr);
LCMSBOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr);
size_t UsedSpace;
......@@ -1853,7 +1868,7 @@ typedef struct _lcms_iccprofile_struct {
cmsHPROFILE cdecl _cmsCreateProfilePlaceholder(void);
// Search into tag dictionary
icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError);
icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError);
// Search for a particular tag, replace if found or add new one else
LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init);
......@@ -1869,6 +1884,7 @@ void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize);
// These macros unpack format specifiers into integers
#define T_DITHER(s) (((s)>>22)&1)
#define T_COLORSPACE(s) (((s)>>16)&31)
#define T_SWAPFIRST(s) (((s)>>14)&1)
#define T_FLAVOR(s) (((s)>>13)&1)
......@@ -1965,7 +1981,7 @@ typedef struct _cmstransform_struct {
// Flag for transform involving v4 profiles
BOOL lInputV4Lab, lOutputV4Lab;
LCMSBOOL lInputV4Lab, lOutputV4Lab;
// 1-pixel cache
......@@ -1975,7 +1991,7 @@ typedef struct _cmstransform_struct {
double AdaptationState; // Figure for v4 incomplete state of adaptation
LCMS_RWLOCK_T rwlock;
LCMS_RWLOCK_T rwlock;
} _cmsTRANSFORM,FAR *_LPcmsTRANSFORM;
......@@ -2012,7 +2028,7 @@ int cdecl cmsChooseCnvrt(int Absolute,
// Clamping & Gamut handling
BOOL cdecl _cmsEndPointsBySpace(icColorSpaceSignature Space,
LCMSBOOL cdecl _cmsEndPointsBySpace(icColorSpaceSignature Space,
WORD **White, WORD **Black, int *nOutputs);
WORD * cdecl _cmsWhiteBySpace(icColorSpaceSignature Space);
......@@ -2041,7 +2057,7 @@ LPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD
LPLUT cdecl _cmsPrecalculateGamutCheck(cmsHTRANSFORM h);
// Hot fixes bad profiles
BOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p);
LCMSBOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p);
// Marks LUT as 8 bit on input
LPLUT cdecl _cmsBlessLUT8(LPLUT Lut);
......@@ -2059,6 +2075,10 @@ void cdecl _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTr
// Build a tone curve for K->K' if possible (only works on CMYK)
LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
// Validates a LUT
LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT);
// These are two VITAL macros, from converting between 8 and 16 bit
// representation.
......@@ -2076,3 +2096,4 @@ LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
#endif
#endif
......@@ -27,9 +27,6 @@ package sun.awt.X11;
import sun.awt.PlatformFont;
import java.awt.GraphicsEnvironment;
/* FIX ME */
import sun.awt.motif.MFontConfiguration;
public class XFontPeer extends PlatformFont {
/*
......@@ -51,10 +48,6 @@ public class XFontPeer extends PlatformFont {
public XFontPeer(String name, int style){
super(name, style);
if (fontConfig != null){
xfsname = ((MFontConfiguration) fontConfig).getMotifFontSet(familyName, style);
}
}
protected char getMissingGlyphCharacter() {
......
......@@ -15,7 +15,7 @@
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* along with this work; if not, write to the Free Software Foundation,
* 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,
......@@ -87,6 +87,7 @@ public class FcFontConfiguration extends FontConfiguration {
return true;
}
setFontConfiguration();
readFcInfo();
if (fcCompFonts == null) {
fcCompFonts = FontManager.loadFontConfig();
......@@ -172,7 +173,7 @@ public class FcFontConfiguration extends FontConfiguration {
@Override
public FontDescriptor[] getFontDescriptors(String fontName, int style) {
throw new InternalError("Not implemented");
return new FontDescriptor[0];
}
@Override
......
......@@ -661,6 +661,12 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
}
}
} else if (category == OrientationRequested.class) {
if (flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT)) {
return null;
}
boolean revPort = false;
OrientationRequested[] orientSup = null;
......
......@@ -362,10 +362,10 @@ public class UnixPrintJob implements CancelablePrintJob {
mOptions += " number-up="+nUp.getValue();
}
if (orient == OrientationRequested.LANDSCAPE &&
if (orient != OrientationRequested.PORTRAIT &&
(flavor != null) &&
!flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {
mOptions += " landscape";
mOptions += " orientation-requested="+orient.getValue();
}
if (sides != null) {
......
......@@ -61,18 +61,10 @@ public class WFontConfiguration extends FontConfiguration {
* been opened and its fonts loaded.
* Also note this usage is only enabled if a private flag is set.
*/
if ("98".equals(osName) || "Me".equals(osName)) {
localeMap.put("dialoginput.plain.japanese", "\uff2d\uff33 \u660e\u671d");
localeMap.put("dialoginput.bold.japanese", "\uff2d\uff33 \u660e\u671d");
localeMap.put("dialoginput.italic.japanese", "\uff2d\uff33 \u660e\u671d");
localeMap.put("dialoginput.bolditalic.japanese", "\uff2d\uff33 \u660e\u671d");
} else {
localeMap.put("dialoginput.plain.japanese", "MS Mincho");
localeMap.put("dialoginput.bold.japanese", "MS Mincho");
localeMap.put("dialoginput.italic.japanese", "MS Mincho");
localeMap.put("dialoginput.bolditalic.japanese", "MS Mincho");
}
localeMap.put("dialoginput.plain.japanese", "MS Mincho");
localeMap.put("dialoginput.bold.japanese", "MS Mincho");
localeMap.put("dialoginput.italic.japanese", "MS Mincho");
localeMap.put("dialoginput.bolditalic.japanese", "MS Mincho");
}
reorderMap = new HashMap();
reorderMap.put("UTF-8.hi", "devanagari");
......
#
#
# Copyright 2003-2004 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.
#
# Version
version=1
# Component Font Mappings
allfonts.chinese-ms936=SimSun
allfonts.dingbats=Wingdings
allfonts.lucida=Lucida Sans Regular
allfonts.symbol=Symbol
allfonts.thai=Lucida Sans Regular
serif.plain.alphabetic=Times New Roman
serif.plain.chinese-ms950=MingLiU
serif.plain.hebrew=David
serif.plain.japanese=\uff2d\uff33 \u660e\u671d
serif.plain.korean=Batang
serif.bold.alphabetic=Times New Roman Bold
serif.bold.chinese-ms950=PMingLiU
serif.bold.hebrew=David Bold
serif.bold.japanese=\uff2d\uff33 \u660e\u671d
serif.bold.korean=Batang
serif.italic.alphabetic=Times New Roman Italic
serif.italic.chinese-ms950=PMingLiU
serif.italic.hebrew=David
serif.italic.japanese=\uff2d\uff33 \u660e\u671d
serif.italic.korean=Batang
serif.bolditalic.alphabetic=Times New Roman Bold Italic
serif.bolditalic.chinese-ms950=PMingLiU
serif.bolditalic.hebrew=David Bold
serif.bolditalic.japanese=\uff2d\uff33 \u660e\u671d
serif.bolditalic.korean=Batang
sansserif.plain.alphabetic=Arial
sansserif.plain.chinese-ms950=MingLiU
sansserif.plain.hebrew=David
sansserif.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.plain.korean=Gulim
sansserif.bold.alphabetic=Arial Bold
sansserif.bold.chinese-ms950=PMingLiU
sansserif.bold.hebrew=David Bold
sansserif.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.bold.korean=Gulim
sansserif.italic.alphabetic=Arial Italic
sansserif.italic.chinese-ms950=PMingLiU
sansserif.italic.hebrew=David
sansserif.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.italic.korean=Gulim
sansserif.bolditalic.alphabetic=Arial Bold Italic
sansserif.bolditalic.chinese-ms950=PMingLiU
sansserif.bolditalic.hebrew=David Bold
sansserif.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.bolditalic.korean=Gulim
monospaced.plain.alphabetic=Courier New
monospaced.plain.chinese-ms950=MingLiU
monospaced.plain.hebrew=David
monospaced.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.plain.korean=GulimChe
monospaced.bold.alphabetic=Courier New Bold
monospaced.bold.chinese-ms950=PMingLiU
monospaced.bold.hebrew=David Bold
monospaced.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.bold.korean=GulimChe
monospaced.italic.alphabetic=Courier New Italic
monospaced.italic.chinese-ms950=PMingLiU
monospaced.italic.hebrew=David
monospaced.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.italic.korean=GulimChe
monospaced.bolditalic.alphabetic=Courier New Bold Italic
monospaced.bolditalic.chinese-ms950=PMingLiU
monospaced.bolditalic.hebrew=David Bold
monospaced.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.bolditalic.korean=GulimChe
dialog.plain.alphabetic=Arial
dialog.plain.chinese-ms950=MingLiU
dialog.plain.hebrew=David
dialog.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.plain.korean=Gulim
dialog.bold.alphabetic=Arial Bold
dialog.bold.chinese-ms950=PMingLiU
dialog.bold.hebrew=David Bold
dialog.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.bold.korean=Gulim
dialog.italic.alphabetic=Arial Italic
dialog.italic.chinese-ms950=PMingLiU
dialog.italic.hebrew=David
dialog.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.italic.korean=Gulim
dialog.bolditalic.alphabetic=Arial Bold Italic
dialog.bolditalic.chinese-ms950=PMingLiU
dialog.bolditalic.hebrew=David Bold
dialog.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.bolditalic.korean=Gulim
dialoginput.plain.alphabetic=Courier New
dialoginput.plain.chinese-ms950=MingLiU
dialoginput.plain.hebrew=David
dialoginput.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.plain.korean=Gulim
dialoginput.bold.alphabetic=Courier New Bold
dialoginput.bold.chinese-ms950=PMingLiU
dialoginput.bold.hebrew=David Bold
dialoginput.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.bold.korean=Gulim
dialoginput.italic.alphabetic=Courier New Italic
dialoginput.italic.chinese-ms950=PMingLiU
dialoginput.italic.hebrew=David
dialoginput.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.italic.korean=Gulim
dialoginput.bolditalic.alphabetic=Courier New Bold Italic
dialoginput.bolditalic.chinese-ms950=PMingLiU
dialoginput.bolditalic.hebrew=David Bold
dialoginput.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.bolditalic.korean=Gulim
# Search Sequences
sequence.allfonts=alphabetic/default,dingbats,symbol
sequence.serif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.sansserif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.monospaced.GBK=chinese-ms936,alphabetic/1252,dingbats,symbol
sequence.dialog.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.dialoginput.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.serif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.sansserif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.monospaced.x-windows-950=chinese-ms950,alphabetic/1252,dingbats,symbol
sequence.dialog.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.dialoginput.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.allfonts.windows-1255=hebrew,alphabetic/1252,dingbats,symbol
sequence.serif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.sansserif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.monospaced.windows-31j=japanese,alphabetic/1252,dingbats,symbol
sequence.dialog.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.dialoginput.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.serif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.sansserif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.monospaced.x-windows-949=korean,alphabetic/1252,dingbats,symbol
sequence.dialog.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.dialoginput.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.allfonts.x-windows-874=alphabetic/1252,thai,dingbats,symbol
sequence.fallback=lucida
# Exclusion Ranges
exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
# Monospaced to Proportional width variant mapping
# (Experimental private syntax)
proportional.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af
proportional.\uff2d\uff33_\u660e\u671d=\uff2d\uff33 \uff30\u660e\u671d
proportional.MingLiU=PMingLiU
# Font File Names
filename.Arial=ARIAL.TTF
filename.Arial_Bold=ARIALBD.TTF
filename.Arial_Italic=ARIALI.TTF
filename.Arial_Bold_Italic=ARIALBI.TTF
filename.Courier_New=COUR.TTF
filename.Courier_New_Bold=COURBD.TTF
filename.Courier_New_Italic=COURI.TTF
filename.Courier_New_Bold_Italic=COURBI.TTF
filename.Times_New_Roman=TIMES.TTF
filename.Times_New_Roman_Bold=TIMESBD.TTF
filename.Times_New_Roman_Italic=TIMESI.TTF
filename.Times_New_Roman_Bold_Italic=TIMESBI.TTF
filename.SimSun=SIMSUN.TTF
filename.MingLiU=MINGLIU.TTC
filename.PMingLiU=MINGLIU.TTC
filename.David=DAVID.TTF
filename.David_Bold=DAVIDBD.TTF
filename.\uff2d\uff33_\u660e\u671d=MSMINCHO.TTC
filename.\uff2d\uff33_\uff30\u660e\u671d=MSMINCHO.TTC
filename.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
filename.\uff2d\uff33_\uff30\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
filename.Gulim=gulim.TTC
filename.Batang=batang.TTC
filename.GulimChe=gulim.TTC
filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
filename.Symbol=SYMBOL.TTF
filename.Wingdings=WINGDING.TTF
#
#
# Copyright 2003-2004 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.
#
# Version
version=1
# Component Font Mappings
allfonts.chinese-ms936=SimSun
allfonts.dingbats=Wingdings
allfonts.lucida=Lucida Sans Regular
allfonts.symbol=Symbol
allfonts.thai=Lucida Sans Regular
serif.plain.alphabetic=Times New Roman
serif.plain.chinese-ms950=MingLiU
serif.plain.hebrew=David
serif.plain.japanese=\uff2d\uff33 \u660e\u671d
serif.plain.korean=Batang
serif.bold.alphabetic=Times New Roman Bold
serif.bold.chinese-ms950=PMingLiU
serif.bold.hebrew=David Bold
serif.bold.japanese=\uff2d\uff33 \u660e\u671d
serif.bold.korean=Batang
serif.italic.alphabetic=Times New Roman Italic
serif.italic.chinese-ms950=PMingLiU
serif.italic.hebrew=David
serif.italic.japanese=\uff2d\uff33 \u660e\u671d
serif.italic.korean=Batang
serif.bolditalic.alphabetic=Times New Roman Bold Italic
serif.bolditalic.chinese-ms950=PMingLiU
serif.bolditalic.hebrew=David Bold
serif.bolditalic.japanese=\uff2d\uff33 \u660e\u671d
serif.bolditalic.korean=Batang
sansserif.plain.alphabetic=Arial
sansserif.plain.chinese-ms950=MingLiU
sansserif.plain.hebrew=David
sansserif.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.plain.korean=Gulim
sansserif.bold.alphabetic=Arial Bold
sansserif.bold.chinese-ms950=PMingLiU
sansserif.bold.hebrew=David Bold
sansserif.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.bold.korean=Gulim
sansserif.italic.alphabetic=Arial Italic
sansserif.italic.chinese-ms950=PMingLiU
sansserif.italic.hebrew=David
sansserif.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.italic.korean=Gulim
sansserif.bolditalic.alphabetic=Arial Bold Italic
sansserif.bolditalic.chinese-ms950=PMingLiU
sansserif.bolditalic.hebrew=David Bold
sansserif.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
sansserif.bolditalic.korean=Gulim
monospaced.plain.alphabetic=Courier New
monospaced.plain.chinese-ms950=MingLiU
monospaced.plain.hebrew=David
monospaced.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.plain.korean=GulimChe
monospaced.bold.alphabetic=Courier New Bold
monospaced.bold.chinese-ms950=PMingLiU
monospaced.bold.hebrew=David Bold
monospaced.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.bold.korean=GulimChe
monospaced.italic.alphabetic=Courier New Italic
monospaced.italic.chinese-ms950=PMingLiU
monospaced.italic.hebrew=David
monospaced.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.italic.korean=GulimChe
monospaced.bolditalic.alphabetic=Courier New Bold Italic
monospaced.bolditalic.chinese-ms950=PMingLiU
monospaced.bolditalic.hebrew=David Bold
monospaced.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
monospaced.bolditalic.korean=GulimChe
dialog.plain.alphabetic=Arial
dialog.plain.chinese-ms950=MingLiU
dialog.plain.hebrew=David
dialog.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.plain.korean=Gulim
dialog.bold.alphabetic=Arial Bold
dialog.bold.chinese-ms950=PMingLiU
dialog.bold.hebrew=David Bold
dialog.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.bold.korean=Gulim
dialog.italic.alphabetic=Arial Italic
dialog.italic.chinese-ms950=PMingLiU
dialog.italic.hebrew=David
dialog.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.italic.korean=Gulim
dialog.bolditalic.alphabetic=Arial Bold Italic
dialog.bolditalic.chinese-ms950=PMingLiU
dialog.bolditalic.hebrew=David Bold
dialog.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialog.bolditalic.korean=Gulim
dialoginput.plain.alphabetic=Courier New
dialoginput.plain.chinese-ms950=MingLiU
dialoginput.plain.hebrew=David
dialoginput.plain.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.plain.korean=Gulim
dialoginput.bold.alphabetic=Courier New Bold
dialoginput.bold.chinese-ms950=PMingLiU
dialoginput.bold.hebrew=David Bold
dialoginput.bold.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.bold.korean=Gulim
dialoginput.italic.alphabetic=Courier New Italic
dialoginput.italic.chinese-ms950=PMingLiU
dialoginput.italic.hebrew=David
dialoginput.italic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.italic.korean=Gulim
dialoginput.bolditalic.alphabetic=Courier New Bold Italic
dialoginput.bolditalic.chinese-ms950=PMingLiU
dialoginput.bolditalic.hebrew=David Bold
dialoginput.bolditalic.japanese=\uff2d\uff33 \u30b4\u30b7\u30c3\u30af
dialoginput.bolditalic.korean=Gulim
# Search Sequences
sequence.allfonts=alphabetic/default,dingbats,symbol
sequence.serif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.sansserif.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.monospaced.GBK=chinese-ms936,alphabetic/1252,dingbats,symbol
sequence.dialog.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.dialoginput.GBK=alphabetic/1252,chinese-ms936,dingbats,symbol
sequence.serif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.sansserif.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.monospaced.x-windows-950=chinese-ms950,alphabetic/1252,dingbats,symbol
sequence.dialog.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.dialoginput.x-windows-950=alphabetic/1252,chinese-ms950,dingbats,symbol
sequence.allfonts.windows-1255=hebrew,alphabetic/1252,dingbats,symbol
sequence.serif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.sansserif.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.monospaced.windows-31j=japanese,alphabetic/1252,dingbats,symbol
sequence.dialog.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.dialoginput.windows-31j=alphabetic/1252,japanese,dingbats,symbol
sequence.serif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.sansserif.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.monospaced.x-windows-949=korean,alphabetic/1252,dingbats,symbol
sequence.dialog.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.dialoginput.x-windows-949=alphabetic/1252,korean,dingbats,symbol
sequence.allfonts.x-windows-874=alphabetic/1252,thai,dingbats,symbol
sequence.fallback=lucida
# Exclusion Ranges
exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff
exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac
# Monospaced to Proportional width variant mapping
# (Experimental private syntax)
proportional.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=\uff2d\uff33 \uff30\u30b4\u30b7\u30c3\u30af
proportional.\uff2d\uff33_\u660e\u671d=\uff2d\uff33 \uff30\u660e\u671d
proportional.MingLiU=PMingLiU
# Font File Names
filename.Arial=ARIAL.TTF
filename.Arial_Bold=ARIALBD.TTF
filename.Arial_Italic=ARIALI.TTF
filename.Arial_Bold_Italic=ARIALBI.TTF
filename.Courier_New=COUR.TTF
filename.Courier_New_Bold=COURBD.TTF
filename.Courier_New_Italic=COURI.TTF
filename.Courier_New_Bold_Italic=COURBI.TTF
filename.Times_New_Roman=TIMES.TTF
filename.Times_New_Roman_Bold=TIMESBD.TTF
filename.Times_New_Roman_Italic=TIMESI.TTF
filename.Times_New_Roman_Bold_Italic=TIMESBI.TTF
filename.SimSun=SIMSUN.TTF
filename.MingLiU=MINGLIU.TTC
filename.PMingLiU=MINGLIU.TTC
filename.David=DAVID.TTF
filename.David_Bold=DAVIDBD.TTF
filename.\uff2d\uff33_\u660e\u671d=MSMINCHO.TTC
filename.\uff2d\uff33_\uff30\u660e\u671d=MSMINCHO.TTC
filename.\uff2d\uff33_\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
filename.\uff2d\uff33_\uff30\u30b4\u30b7\u30c3\u30af=MSGOTHIC.TTC
filename.Gulim=gulim.TTC
filename.Batang=batang.TTC
filename.GulimChe=gulim.TTC
filename.Lucida_Sans_Regular=LucidaSansRegular.ttf
filename.Symbol=SYMBOL.TTF
filename.Wingdings=WINGDING.TTF
/*
* Copyright (c) 2009 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 6785424
* @summary Test no SecurityException searching for a font.
* @run main FontAccess
*
* This can only test the specific bug if run on something like
* Windows Citrix Server where SystemDirectory and WindowsDirectory
* are different locations.
*/
import java.awt.*;
import java.awt.image.*;
public class FontAccess {
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager());
Font f = new Font("Verdana", Font.PLAIN, 12);
BufferedImage bi = new BufferedImage(1,1,1);
Graphics2D g = bi.createGraphics();
g.setFont(f);
System.out.println(g.getFontMetrics());
}
}
/*
* Copyright (c) 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 6752638
* @summary Test no NPE calling preferLocaleFonts() on custom GE.
* @run main PreferLocaleFonts
*/
import java.util.*;
import java.awt.*;
import java.awt.image.*;
public class PreferLocaleFonts extends GraphicsEnvironment {
public static void main(String args[]) {
(new PreferLocaleFonts()).preferLocaleFonts();
}
public PreferLocaleFonts() {
super();
}
public Graphics2D createGraphics(BufferedImage image) {
return null;
}
public String[] getAvailableFontFamilyNames(Locale locale) {
return null;
}
public String[] getAvailableFontFamilyNames() {
return null;
}
public Font[] getAllFonts() {
return null;
}
public GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
return null;
}
public GraphicsDevice[] getScreenDevices() throws HeadlessException {
return null;
}
}
/*
* Copyright 2008-9 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 6448405 6519513 6745225
* @summary static HashMap cache in LineBreakMeasurer can grow wihout bounds
* @run main/othervm/timeout=600 -client -Xms16m -Xmx16m FRCTest
*/
import java.awt.*;
import java.awt.image.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
import java.util.Hashtable;
public class FRCTest {
static AttributedString vanGogh = new AttributedString(
"Many people believe that Vincent van Gogh painted his best works " +
"during the two-year period he spent in Provence. Here is where he " +
"painted The Starry Night--which some consider to be his greatest " +
"work of all. However, as his artistic brilliance reached new " +
"heights in Provence, his physical and mental health plummeted. ",
new Hashtable());
public static void main(String[] args) {
// First test the behaviour of Graphics2D.getFontRenderContext();
BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
AffineTransform g2dTx = new AffineTransform(2,0,2,0,1,1);
g2d.setTransform(g2dTx);
AffineTransform frcTx = g2d.getFontRenderContext().getTransform();
AffineTransform frcExpected = new AffineTransform(2,0,2,0,0,0);
if (!frcTx.equals(frcExpected)) {
throw new RuntimeException("FRC Tx may have translate?");
}
// Now test that using different translates with LBM is OK
// This test doesn't prove a lot since showing a leak really
// requires a basher test that can run for a long time.
for (int x=0;x<100;x++) {
for (int y=0;y<100;y++) {
AttributedCharacterIterator aci = vanGogh.getIterator();
AffineTransform tx = AffineTransform.getTranslateInstance(x, y);
FontRenderContext frc = new FontRenderContext(tx, false, false);
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
lbm.setPosition(aci.getBeginIndex());
while (lbm.getPosition() < aci.getEndIndex()) {
lbm.nextLayout(100f);
}
}
}
for (int x=0;x<25;x++) {
for (int y=0;y<25;y++) {
AttributedCharacterIterator aci = vanGogh.getIterator();
double rot = Math.random()*.4*Math.PI - .2*Math.PI;
AffineTransform tx = AffineTransform.getRotateInstance(rot);
FontRenderContext frc = new FontRenderContext(tx, false, false);
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
lbm.setPosition(aci.getBeginIndex());
while (lbm.getPosition() < aci.getEndIndex()) {
lbm.nextLayout(100f);
}
}
}
}
}
/*
* Copyright 2009 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 6799583
*
* @summary Test verifes that LogManager shutdown hook does not cause
* an application classloader leaks.
*
* @run main/othervm ClassLoaderLeakTest
*/
import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;
import java.util.logging.Logger;
public class ClassLoaderLeakTest {
private static CountDownLatch doneSignal;
private static CountDownLatch launchSignal;
private static ThreadGroup appsThreadGroup;
private static Throwable launchFailure = null;
public static void main(String[] args) {
appsThreadGroup = new ThreadGroup("MyAppsThreadGroup");
doneSignal = new CountDownLatch(1);
launchSignal = new CountDownLatch(1);
Runnable launcher = new Runnable() {
public void run() {
try {
ClassLoader cl =
Thread.currentThread().getContextClassLoader();
Class appMain = cl.loadClass("AppTest");
Method launch =
appMain.getDeclaredMethod("launch", doneSignal.getClass());
Constructor c = appMain.getConstructor();
Object o = c.newInstance();
launch.invoke(o, doneSignal);
} catch (Throwable e) {
launchFailure = e;
} finally {
launchSignal.countDown();
}
}
};
/* prepare test class loader */
URL pwd = null;
try {
pwd = new File(System.getProperty("test.classes",".")).toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("Test failed.", e);
}
URL[] urls = new URL[] { pwd };
MyClassLoader appClassLoader = new MyClassLoader(urls, "test0");
WeakReference<MyClassLoader> ref =
new WeakReference<MyClassLoader>(appClassLoader);
Thread appThread = new Thread(appsThreadGroup, launcher, "AppThread-0");
appThread.setContextClassLoader(appClassLoader);
appThread.start();
appClassLoader = null;
launcher = null;
appThread = null;
/* wait for laucnh completion */
try {
launchSignal.await();
} catch (InterruptedException e) {
}
/* check if launch failed */
if (launchFailure != null) {
throw new RuntimeException("Test failed.", launchFailure);
}
/* wait for test app excution completion */
try {
doneSignal.await();
} catch (InterruptedException e) {
}
/* give a chence to GC */
waitAndGC(5);
if (ref.get() != null) {
throw new RuntimeException("Test failed: classloader is still alive");
}
System.out.println("Test passed.");
}
private static class MyClassLoader extends URLClassLoader {
private static boolean verbose =
Boolean.getBoolean("verboseClassLoading");
private String uniqClassName;
public MyClassLoader(URL[] urls, String uniq) {
super(urls);
uniqClassName = uniq;
}
public Class loadClass(String name) throws ClassNotFoundException {
if (verbose) {
System.out.printf("%s: load class %s\n", uniqClassName, name);
}
if (uniqClassName.equals(name)) {
return Object.class;
}
return super.loadClass(name);
}
public String toString() {
return "MyClassLoader(" + uniqClassName + ")";
}
}
private static void waitAndGC(int sec) {
int cnt = sec;
System.out.print("Wait ");
while (cnt-- > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// do GC every 3 seconds
if (cnt % 3 == 2) {
System.gc();
System.out.print("+");
} else {
System.out.print(".");
}
//checkErrors();
}
System.out.println("");
}
}
class AppTest {
public AppTest() {
}
public void launch(CountDownLatch done) {
Logger log = Logger.getLogger("app_test_logger");
log.fine("Test app is launched");
done.countDown();
}
}
/*
* 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.
*/
/**
* @test
* @bug 5082756
* @summary ensure that boolean attributes follow ( "TRUE" | "FALSE" )
* including correct (i.e. upper) case
*
* @run main BooleanAttributes
*/
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.util.Arrays;
import java.util.List;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class BooleanAttributes {
private static TransformerFactory transformerFactory =
TransformerFactory.newInstance();
private static XPath xpathEngine = XPathFactory.newInstance().newXPath();
public static void main(String[] args) throws Exception {
test("image/png", false, "<javax_imageio_1.0 />",
"Chroma/BlackIsZero/@value",
"Compression/Lossless/@value");
test("image/png", false,
"<javax_imageio_png_1.0>" +
"<iTXt><iTXtEntry keyword='Comment' compressionFlag='TRUE' " +
"compressionMethod='0' languageTag='en' " +
"translatedKeyword='comment' text='foo'/></iTXt>" +
"</javax_imageio_png_1.0>",
"iTXt/iTXtEntry/@compressionFlag");
test("image/png", false,
"<javax_imageio_png_1.0>" +
"<iTXt><iTXtEntry keyword='Comment' compressionFlag='FALSE' " +
"compressionMethod='0' languageTag='en' " +
"translatedKeyword='comment' text='foo'/></iTXt>" +
"</javax_imageio_png_1.0>",
"iTXt/iTXtEntry/@compressionFlag");
test("image/gif", false, "<javax_imageio_1.0 />",
"Chroma/BlackIsZero/@value",
"Compression/Lossless/@value");
test("image/gif", false,
"<javax_imageio_gif_image_1.0>" +
"<ImageDescriptor imageLeftPosition='0' imageTopPosition='0' " +
"imageWidth='16' imageHeight='16' interlaceFlag='TRUE' />" +
"<LocalColorTable sizeOfLocalColorTable='2' " +
"backgroundColorIndex='1' sortFlag='TRUE'>" +
"<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
"<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
"</LocalColorTable>" +
"<GraphicControlExtension disposalMethod='doNotDispose' " +
"userInputFlag='FALSE' transparentColorFlag='TRUE' " +
"delayTime='100' transparentColorIndex='1' />" +
"</javax_imageio_gif_image_1.0>",
"ImageDescriptor/@interlaceFlag",
"LocalColorTable/@sortFlag",
"GraphicControlExtension/@userInputFlag",
"GraphicControlExtension/@transparentColorFlag");
test("image/gif", true,
"<javax_imageio_gif_stream_1.0>" +
"<GlobalColorTable sizeOfGlobalColorTable='2' " +
"backgroundColorIndex='1' sortFlag='TRUE'>" +
"<ColorTableEntry index='0' red='0' green='0' blue='0' />" +
"<ColorTableEntry index='1' red='255' green='255' blue='255' />" +
"</GlobalColorTable>" +
"</javax_imageio_gif_stream_1.0>",
"GlobalColorTable/@sortFlag");
test("image/jpeg", false, "<javax_imageio_1.0 />",
"Compression/Lossless/@value");
}
private static void transform(Source src, Result dst)
throws Exception
{
transformerFactory.newTransformer().transform(src, dst);
}
private static void verify(Node meta, String[] xpaths, boolean required)
throws Exception
{
for (String xpath: xpaths) {
NodeList list = (NodeList)
xpathEngine.evaluate(xpath, meta, XPathConstants.NODESET);
if (list.getLength() == 0 && required)
throw new AssertionError("Missing value: " + xpath);
for (int i = 0; i < list.getLength(); ++i) {
String value = list.item(i).getNodeValue();
if (!(value.equals("TRUE") || value.equals("FALSE")))
throw new AssertionError(xpath + " has value " + value);
}
}
}
public static void test(String mimeType, boolean useStreamMeta,
String metaXml, String... boolXpaths)
throws Exception
{
BufferedImage img =
new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
ImageWriter iw = ImageIO.getImageWritersByMIMEType(mimeType).next();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageOutputStream ios = new MemoryCacheImageOutputStream(os);
iw.setOutput(ios);
ImageWriteParam param = null;
IIOMetadata streamMeta = iw.getDefaultStreamMetadata(param);
IIOMetadata imageMeta =
iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), param);
IIOMetadata meta = useStreamMeta ? streamMeta : imageMeta;
Source src = new StreamSource(new StringReader(metaXml));
DOMResult dst = new DOMResult();
transform(src, dst);
Document doc = (Document)dst.getNode();
Element node = doc.getDocumentElement();
String metaFormat = node.getNodeName();
// Verify that the default metadata gets formatted correctly.
verify(meta.getAsTree(metaFormat), boolXpaths, false);
meta.mergeTree(metaFormat, node);
// Verify that the merged metadata gets formatte correctly.
verify(meta.getAsTree(metaFormat), boolXpaths, true);
iw.write(streamMeta, new IIOImage(img, null, imageMeta), param);
iw.dispose();
ios.close();
ImageReader ir = ImageIO.getImageReader(iw);
byte[] bytes = os.toByteArray();
if (bytes.length == 0)
throw new AssertionError("Zero length image file");
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ImageInputStream iis = new MemoryCacheImageInputStream(is);
ir.setInput(iis);
if (useStreamMeta) meta = ir.getStreamMetadata();
else meta = ir.getImageMetadata(0);
// Verify again after writing and re-reading the image
verify(meta.getAsTree(metaFormat), boolXpaths, true);
}
public static void xtest(Object... eatAnyArguments) {
System.err.println("Disabled test! Change xtest back into test!");
}
}
/*
* Copyright 2009 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 6795544
*
* @summary Test verifes that Image I/O gif writer correctly handles
* buffered images based on translated reasters (typically
* produced by getSubImage() method).
*
* @run main EncodeSubImageTest gif
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
public class EncodeSubImageTest {
private static String format = "gif";
private static ImageWriter writer;
private static String file_suffix;
private static final int subSampleX = 2;
private static final int subSampleY = 2;
public static void main(String[] args) throws IOException {
if (args.length > 0) {
format = args[0];
}
writer = ImageIO.getImageWritersByFormatName(format).next();
file_suffix =writer.getOriginatingProvider().getFileSuffixes()[0];
BufferedImage src = createTestImage();
EncodeSubImageTest m1 = new EncodeSubImageTest(src);
m1.doTest("test_src");
BufferedImage sub = src.getSubimage(subImageOffset, subImageOffset,
src.getWidth() - 2 * subImageOffset,
src.getHeight() - 2 * subImageOffset);
EncodeSubImageTest m2 = new EncodeSubImageTest(sub);
m2.doTest("test_sub");
}
BufferedImage img;
public EncodeSubImageTest(BufferedImage img) {
this.img = img;
}
public void doTest(String prefix) throws IOException {
System.out.println(prefix);
File f = new File(prefix + file_suffix);
write(f, false);
verify(f, false);
System.out.println(prefix + "_subsampled");
f = new File(prefix + "_subsampled");
write(f, true);
verify(f, true);
System.out.println(prefix + ": Test PASSED.");
}
private static final int subImageOffset = 10;
private void verify(File f, boolean isSubsampled) {
BufferedImage dst = null;
try {
dst = ImageIO.read(f);
} catch (IOException e) {
throw new RuntimeException("Test FAILED: can't readin test image " +
f.getAbsolutePath(), e);
}
if (dst == null) {
throw new RuntimeException("Test FAILED: no dst image available.");
}
checkPixel(dst, 0, 0, isSubsampled);
checkPixel(dst, img.getWidth() / 2, img.getHeight() / 2, isSubsampled);
}
private void checkPixel(BufferedImage dst, int x, int y,
boolean isSubsampled)
{
int dx = isSubsampled ? x / subSampleX : x;
int dy = isSubsampled ? y / subSampleY : y;
int src_rgb = img.getRGB(x, y);
System.out.printf("src_rgb: %x\n", src_rgb);
int dst_rgb = dst.getRGB(dx, dy);
System.out.printf("dst_rgb: %x\n", dst_rgb);
if (src_rgb != dst_rgb) {
throw new RuntimeException("Test FAILED: invalid color in dst");
}
}
private static BufferedImage createTestImage() {
int w = 100;
int h = 100;
BufferedImage src = new BufferedImage(w, h,
BufferedImage.TYPE_BYTE_INDEXED);
Graphics g = src.createGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, w, h);
g.setColor(Color.green);
g.fillRect(subImageOffset, subImageOffset,
w - 2 * subImageOffset, h - 2* subImageOffset);
g.setColor(Color.blue);
g.fillRect(2 * subImageOffset, 2 * subImageOffset,
w - 4 * subImageOffset, h - 4 * subImageOffset);
g.dispose();
return src;
}
private void write(File f, boolean subsample) throws IOException {
ImageOutputStream ios = ImageIO.createImageOutputStream(f);
writer.setOutput(ios);
ImageWriteParam p = writer.getDefaultWriteParam();
if (subsample) {
p.setSourceSubsampling(subSampleX, subSampleY, 0, 0);
}
writer.write(null, new IIOImage(img, null, null), p);
ios.close();
writer.reset();
}
}
......@@ -123,7 +123,7 @@ public class ITXtTest {
}
t.keyword = e.getAttribute("keyword");
t.isCompressed =
(Integer.valueOf(e.getAttribute("compressionFlag")).intValue() == 1);
Boolean.valueOf(e.getAttribute("compressionFlag")).booleanValue();
t.compression =
Integer.valueOf(e.getAttribute("compressionMethod")).intValue();
t.language = e.getAttribute("languageTag");
......
/*
* 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 6541476 6782079
* @summary Write and read a PNG file including an non-latin1 iTXt chunk
* Test also verifies that trunkated png images does not cause
* an OoutOfMemory error.
*
* @run main ItxtUtf8Test
*
* @run main/othervm/timeout=10 -Xmx2m ItxtUtf8Test truncate
*/
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
public class ItxtUtf8Test {
public static final String
TEXT = "\u24c9\u24d4\u24e7\u24e3" +
"\ud835\udc13\ud835\udc1e\ud835\udc31\ud835\udc2d" +
"\u24c9\u24d4\u24e7\u24e3", // a repetition for compression
VERBATIM = "\u24e5\u24d4\u24e1\u24d1\u24d0\u24e3\u24d8\u24dc",
COMPRESSED = "\u24d2\u24de\u24dc\u24df\u24e1\u24d4\u24e2\u24e2\u24d4\u24d3";
public static final byte[]
VBYTES = {
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x56, // chunk length
(byte)0x69, (byte)0x54, (byte)0x58, (byte)0x74, // chunk type "iTXt"
(byte)0x76, (byte)0x65, (byte)0x72, (byte)0x62,
(byte)0x61, (byte)0x74, (byte)0x69, (byte)0x6d, // keyword "verbatim"
(byte)0x00, // separator terminating keyword
(byte)0x00, // compression flag
(byte)0x00, // compression method, must be zero
(byte)0x78, (byte)0x2d, (byte)0x63, (byte)0x69,
(byte)0x72, (byte)0x63, (byte)0x6c, (byte)0x65,
(byte)0x64, // language tag "x-circled"
(byte)0x00, // separator terminating language tag
(byte)0xe2, (byte)0x93, (byte)0xa5, // '\u24e5'
(byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
(byte)0xe2, (byte)0x93, (byte)0xa1, // '\u24e1'
(byte)0xe2, (byte)0x93, (byte)0x91, // '\u24d1'
(byte)0xe2, (byte)0x93, (byte)0x90, // '\u24d0'
(byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
(byte)0xe2, (byte)0x93, (byte)0x98, // '\u24d8'
(byte)0xe2, (byte)0x93, (byte)0x9c, // '\u24dc'
(byte)0x00, // separator terminating the translated keyword
(byte)0xe2, (byte)0x93, (byte)0x89, // '\u24c9'
(byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
(byte)0xe2, (byte)0x93, (byte)0xa7, // '\u24e7'
(byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
(byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0x93, // '\ud835\udc13'
(byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0x9e, // '\ud835\udc1e'
(byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0xb1, // '\ud835\udc31'
(byte)0xf0, (byte)0x9d, (byte)0x90, (byte)0xad, // '\ud835\udc2d'
(byte)0xe2, (byte)0x93, (byte)0x89, // '\u24c9'
(byte)0xe2, (byte)0x93, (byte)0x94, // '\u24d4'
(byte)0xe2, (byte)0x93, (byte)0xa7, // '\u24e7'
(byte)0xe2, (byte)0x93, (byte)0xa3, // '\u24e3'
(byte)0xb5, (byte)0xcc, (byte)0x97, (byte)0x56 // CRC
},
CBYTES = {
// we don't want to check the chunk length,
// as this might depend on implementation.
(byte)0x69, (byte)0x54, (byte)0x58, (byte)0x74, // chunk type "iTXt"
(byte)0x63, (byte)0x6f, (byte)0x6d, (byte)0x70,
(byte)0x72, (byte)0x65, (byte)0x73, (byte)0x73,
(byte)0x65, (byte)0x64, // keyword "compressed"
(byte)0x00, // separator terminating keyword
(byte)0x01, // compression flag
(byte)0x00, // compression method, 0=deflate
(byte)0x78, (byte)0x2d, (byte)0x63, (byte)0x69,
(byte)0x72, (byte)0x63, (byte)0x6c, (byte)0x65,
(byte)0x64, // language tag "x-circled"
(byte)0x00, // separator terminating language tag
// we don't want to check the actual compressed data,
// as this might depend on implementation.
};
/*
*/
public static void main(String[] args) throws Exception {
List argList = Arrays.asList(args);
if (argList.contains("truncate")) {
try {
runTest(false, true);
throw new AssertionError("Expect an error for truncated file");
}
catch (IIOException e) {
// expected an error for a truncated image file.
}
}
else {
runTest(argList.contains("dump"), false);
}
}
public static void runTest(boolean dump, boolean truncate)
throws Exception
{
String format = "javax_imageio_png_1.0";
BufferedImage img =
new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
ImageWriter iw = ImageIO.getImageWritersByMIMEType("image/png").next();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageOutputStream ios = new MemoryCacheImageOutputStream(os);
iw.setOutput(ios);
IIOMetadata meta =
iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), null);
DOMImplementationRegistry registry;
registry = DOMImplementationRegistry.newInstance();
DOMImplementation impl = registry.getDOMImplementation("XML 3.0");
Document doc = impl.createDocument(null, format, null);
Element root, itxt, entry;
root = doc.getDocumentElement();
root.appendChild(itxt = doc.createElement("iTXt"));
itxt.appendChild(entry = doc.createElement("iTXtEntry"));
entry.setAttribute("keyword", "verbatim");
entry.setAttribute("compressionFlag", "false");
entry.setAttribute("compressionMethod", "0");
entry.setAttribute("languageTag", "x-circled");
entry.setAttribute("translatedKeyword", VERBATIM);
entry.setAttribute("text", TEXT);
itxt.appendChild(entry = doc.createElement("iTXtEntry"));
entry.setAttribute("keyword", "compressed");
entry.setAttribute("compressionFlag", "true");
entry.setAttribute("compressionMethod", "0");
entry.setAttribute("languageTag", "x-circled");
entry.setAttribute("translatedKeyword", COMPRESSED);
entry.setAttribute("text", TEXT);
meta.mergeTree(format, root);
iw.write(new IIOImage(img, null, meta));
iw.dispose();
byte[] bytes = os.toByteArray();
if (dump)
System.out.write(bytes);
if (findBytes(VBYTES, bytes) < 0)
throw new AssertionError("verbatim block not found");
if (findBytes(CBYTES, bytes) < 0)
throw new AssertionError("compressed block not found");
int length = bytes.length;
if (truncate)
length = findBytes(VBYTES, bytes) + 32;
ImageReader ir = ImageIO.getImageReader(iw);
ByteArrayInputStream is = new ByteArrayInputStream(bytes, 0, length);
ImageInputStream iis = new MemoryCacheImageInputStream(is);
ir.setInput(iis);
meta = ir.getImageMetadata(0);
Node node = meta.getAsTree(format);
for (node = node.getFirstChild();
!"iTXt".equals(node.getNodeName());
node = node.getNextSibling());
boolean verbatimSeen = false, compressedSeen = false;
for (node = node.getFirstChild();
node != null;
node = node.getNextSibling()) {
entry = (Element)node;
String keyword = entry.getAttribute("keyword");
String translatedKeyword = entry.getAttribute("translatedKeyword");
String text = entry.getAttribute("text");
if ("verbatim".equals(keyword)) {
if (verbatimSeen) throw new AssertionError("Duplicate");
verbatimSeen = true;
if (!VERBATIM.equals(translatedKeyword))
throw new AssertionError("Wrong translated keyword");
if (!TEXT.equals(text))
throw new AssertionError("Wrong text");
}
else if ("compressed".equals(keyword)) {
if (compressedSeen) throw new AssertionError("Duplicate");
compressedSeen = true;
if (!COMPRESSED.equals(translatedKeyword))
throw new AssertionError("Wrong translated keyword");
if (!TEXT.equals(text))
throw new AssertionError("Wrong text");
}
else {
throw new AssertionError("Unexpected keyword");
}
}
if (!(verbatimSeen && compressedSeen))
throw new AssertionError("Missing chunk");
}
private static final int findBytes(byte[] needle, byte[] haystack) {
HAYSTACK: for (int h = 0; h <= haystack.length - needle.length; ++h) {
for (int n = 0; n < needle.length; ++n) {
if (needle[n] != haystack[h + n]) {
continue HAYSTACK;
}
}
return h;
}
return -1;
}
}
/*
* 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 5106550
* @summary Merge a comment using the standard metdata format
* and only a minimal set of attributes
*/
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
public class MergeStdCommentTest {
public static void main(String[] args) throws Exception {
String format = "javax_imageio_1.0";
BufferedImage img =
new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
ImageWriter iw = ImageIO.getImageWritersByMIMEType("image/png").next();
IIOMetadata meta =
iw.getDefaultImageMetadata(new ImageTypeSpecifier(img), null);
DOMImplementationRegistry registry;
registry = DOMImplementationRegistry.newInstance();
DOMImplementation impl = registry.getDOMImplementation("XML 3.0");
Document doc = impl.createDocument(null, format, null);
Element root, text, entry;
root = doc.getDocumentElement();
root.appendChild(text = doc.createElement("Text"));
text.appendChild(entry = doc.createElement("TextEntry"));
// keyword isn't #REQUIRED by the standard metadata format.
// However, it is required by the PNG format, so we include it here.
entry.setAttribute("keyword", "Comment");
entry.setAttribute("value", "Some demo comment");
meta.mergeTree(format, root);
}
}
#!/bin/ksh -p
#
# Copyright 2009 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 6788096
# @summary Test simulates the case of multiple applets executed in
# the same VM and verifies that ImageIO shutdown hook
# StreamCloser does not cause a leak of classloaders.
#
# @build test.Main
# @build testapp.Main
# @run shell run_test.sh
# There are several resources which need to be present before many
# shell scripts can run. Following are examples of how to check for
# many common ones.
#
# Note that the shell used is the Korn Shell, KSH
#
# Also note, it is recommended that make files NOT be used. Rather,
# put the individual commands directly into this file. That way,
# it is possible to use command line arguments and other shell tech-
# niques to find the compiler, etc on different systems. For example,
# a different path could be used depending on whether this were a
# Solaris or Win32 machine, which is more difficult (if even possible)
# in a make file.
# Beginning of subroutines:
status=1
#Call this from anywhere to fail the test with an error message
# usage: fail "reason why the test failed"
fail()
{ echo "The test failed :-("
echo "$*" 1>&2
echo "exit status was $status"
exit $status
} #end of fail()
#Call this from anywhere to pass the test with a message
# usage: pass "reason why the test passed if applicable"
pass()
{ echo "The test passed!!!"
echo "$*" 1>&2
exit 0
} #end of pass()
# end of subroutines
# The beginning of the script proper
# Checking for proper OS
OS=`uname -s`
case "$OS" in
SunOS )
VAR="One value for Sun"
DEFAULT_JDK=/usr/local/java/jdk1.2/solaris
FILESEP="/"
PATHSEP=":"
TMP="/tmp"
;;
Linux )
VAR="A different value for Linux"
DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386
FILESEP="/"
PATHSEP=":"
TMP="/tmp"
;;
Windows_95 | Windows_98 | Windows_NT | Windows_ME )
VAR="A different value for Win32"
DEFAULT_JDK=/usr/local/java/jdk1.2/win32
FILESEP="\\"
PATHSEP=";"
TMP=`cd "${SystemRoot}/Temp"; echo ${PWD}`
;;
# catch all other OSs
* )
echo "Unrecognized system! $OS"
fail "Unrecognized system! $OS"
;;
esac
# Want this test to run standalone as well as in the harness, so do the
# following to copy the test's directory into the harness's scratch directory
# and set all appropriate variables:
if [ -z "${TESTJAVA}" ] ; then
# TESTJAVA is not set, so the test is running stand-alone.
# TESTJAVA holds the path to the root directory of the build of the JDK
# to be tested. That is, any java files run explicitly in this shell
# should use TESTJAVA in the path to the java interpreter.
# So, we'll set this to the JDK spec'd on the command line. If none
# is given on the command line, tell the user that and use a cheesy
# default.
# THIS IS THE JDK BEING TESTED.
if [ -n "$1" ] ;
then TESTJAVA=$1
else echo "no JDK specified on command line so using default!"
TESTJAVA=$DEFAULT_JDK
fi
TESTSRC=.
TESTCLASSES=.
STANDALONE=1;
fi
echo "JDK under test is: $TESTJAVA"
############### YOUR TEST CODE HERE!!!!!!! #############
#All files required for the test should be in the same directory with
# this file. If converting a standalone test to run with the harness,
# as long as all files are in the same directory and it returns 0 for
# pass, you should be able to cut and paste it into here and it will
# run with the test harness.
# This is an example of running something -- test
# The stuff below catches the exit status of test then passes or fails
# this shell test as appropriate ( 0 status is considered a pass here )
echo "Create TestApp.jar..."
if [ -f TestApp.jar ] ; then
rm -f TestApp.jar
fi
${TESTJAVA}/bin/jar -cvf TestApp.jar -C ${TESTCLASSES} testapp
if [ $? -ne "0" ] ; then
fail "Failed to create TestApp.jar"
fi
echo "Create Test.jar..."
if [ -f Test.jar ] ; then
rm -f Test.jar
fi
${TESTJAVA}/bin/jar -cvf Test.jar -C ${TESTCLASSES} test
if [ $? -ne 0 ] ; then
fail "Failed to create Test.jar"
fi
# Prepare temp dir for cahce files
mkdir ./tmp
if [ $? -ne 0 ] ; then
fail "Unable to create temp directory."
fi
# Verify that all classoladers are destroyed
${TESTJAVA}/bin/java -cp Test.jar test.Main
if [ $? -ne 0 ] ; then
fail "Test FAILED: some classloaders weren't destroyed."
fi
# Verify that ImageIO shutdown hook works correcly
${TESTJAVA}/bin/java -cp Test.jar -DforgetSomeStreams=true test.Main
if [ $? -ne 0 ] ; then
fail "Test FAILED: some classloaders weren't destroyed of shutdown hook failed."
fi
# sanity check: verify that all cache files were deleted
cache_files=`ls tmp`
if [ "x${cache_files}" != "x" ] ; then
echo "WARNING: some cache files was not deleted: ${cache_files}"
fi
echo "Test done."
status=$?
if [ $status -eq "0" ] ; then
pass ""
else
fail "Test failed due to test plugin was not found."
fi
/*
* Copyright 2009 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.
*/
package test;
import java.io.File;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import javax.imageio.stream.ImageInputStream;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
public class Main {
private static ThreadGroup appsThreadGroup;
private static WeakHashMap<MyClassLoader, String> refs =
new WeakHashMap<MyClassLoader, String>();
/** Collection to simulate forgrotten streams **/
private static HashMap<String, ImageInputStream> strongRefs =
new HashMap<String, ImageInputStream>();
private static ConcurrentLinkedQueue<Throwable> problems =
new ConcurrentLinkedQueue<Throwable>();
private static AppContext mainAppContext = null;
private static CountDownLatch doneSignal;
private static final int gcTimeout =
Integer.getInteger("gcTimeout", 10).intValue();
private static boolean forgetSomeStreams =
Boolean.getBoolean("forgetSomeStreams");
public static void main(String[] args) throws IOException {
mainAppContext = SunToolkit.createNewAppContext();
System.out.println("Current context class loader: " +
Thread.currentThread().getContextClassLoader());
appsThreadGroup = new ThreadGroup("MyAppsThreadGroup");
File jar = new File("TestApp.jar");
if (!jar.exists()) {
System.out.println(jar.getAbsolutePath() + " was not found!\n" +
"Please install the jar with test application correctly!");
throw new RuntimeException("Test failed: no TestApp.jar");
}
URL[] urls = new URL[]{jar.toURL()};
int numApps = Integer.getInteger("numApps", 20).intValue();
doneSignal = new CountDownLatch(numApps);
int cnt = 0;
while (cnt++ < numApps) {
launch(urls, "testapp.Main", "launch");
checkErrors();
}
System.out.println("Wait for apps completion....");
try {
doneSignal.await();
} catch (InterruptedException e) {
}
System.out.println("All apps finished.");
System.gc();
System.out.flush();
System.out.println("Enumerate strong refs:");
for (String is : strongRefs.keySet()) {
System.out.println("-> " + is);
}
System.out.println("=======================");
// wait few seconds
waitAndGC(gcTimeout);
doneSignal = new CountDownLatch(1);
Runnable workaround = new Runnable() {
public void run() {
AppContext ctx = null;
try {
ctx = SunToolkit.createNewAppContext();
} catch (Throwable e) {
// ignore...
} finally {
doneSignal.countDown();
}
}
};
Thread wt = new Thread(appsThreadGroup, workaround, "Workaround");
wt.setContextClassLoader(new MyClassLoader(urls, "workaround"));
wt.start();
wt = null;
workaround = null;
System.out.println("Wait for workaround completion...");
try {
doneSignal.await();
} catch (InterruptedException e) {
}
// give a chance to GC
waitAndGC(gcTimeout);
if (!refs.isEmpty()) {
System.out.println("Classloaders still alive:");
for (MyClassLoader l : refs.keySet()) {
String val = refs.get(l);
if (val == null) {
throw new RuntimeException("Test FAILED: Invalid classloader name");
}
System.out.println("->" + val + (strongRefs.get(val) != null ?
" (has strong ref)" : ""));
if (strongRefs.get(val) == null) {
throw new RuntimeException("Test FAILED: exta class loader is detected! ");
}
}
} else {
System.out.println("No alive class loaders!!");
}
System.out.println("Test PASSED.");
}
private static void waitAndGC(int sec) {
int cnt = sec;
System.out.print("Wait ");
while (cnt-- > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// do GC every 3 seconds
if (cnt % 3 == 2) {
System.gc();
System.out.print("+");
} else {
System.out.print(".");
}
checkErrors();
}
System.out.println("");
}
private static void checkErrors() {
while (!problems.isEmpty()) {
Throwable theProblem = problems.poll();
System.out.println("Test FAILED!");
do {
theProblem.printStackTrace(System.out);
theProblem = theProblem.getCause();
} while (theProblem != null);
throw new RuntimeException("Test FAILED");
}
}
static int counter = 0;
private static void launch(URL[] urls, final String className,
final String methodName)
{
final String uniqClassName = "testapp/Uniq" + counter;
final boolean saveStrongRef = forgetSomeStreams ? (counter % 5 == 4) : false;
System.out.printf("%s: launch the app\n", uniqClassName);
Runnable launchIt = new Runnable() {
public void run() {
AppContext ctx = SunToolkit.createNewAppContext();
try {
Class appMain =
ctx.getContextClassLoader().loadClass(className);
Method launch = appMain.getDeclaredMethod(methodName,
strongRefs.getClass());
Constructor c = appMain.getConstructor(String.class,
problems.getClass());
Object o = c.newInstance(uniqClassName, problems);
if (saveStrongRef) {
System.out.printf("%s: force strong ref\n",
uniqClassName);
launch.invoke(o, strongRefs);
} else {
HashMap<String, ImageInputStream> empty = null;
launch.invoke(o, empty);
}
ctx = null;
} catch (Throwable e) {
problems.add(e);
} finally {
doneSignal.countDown();
}
}
};
MyClassLoader appClassLoader = new MyClassLoader(urls, uniqClassName);
refs.put(appClassLoader, uniqClassName);
Thread appThread = new Thread(appsThreadGroup, launchIt,
"AppThread" + counter++);
appThread.setContextClassLoader(appClassLoader);
appThread.start();
launchIt = null;
appThread = null;
appClassLoader = null;
}
private static class MyClassLoader extends URLClassLoader {
private static boolean verbose =
Boolean.getBoolean("verboseClassLoading");
private String uniqClassName;
public MyClassLoader(URL[] urls, String uniq) {
super(urls);
uniqClassName = uniq;
}
public Class loadClass(String name) throws ClassNotFoundException {
if (verbose) {
System.out.printf("%s: load class %s\n", uniqClassName, name);
}
if (uniqClassName.equals(name)) {
return Object.class;
}
return super.loadClass(name);
}
public String toString() {
return "MyClassLoader(" + uniqClassName + ")";
}
}
}
/*
* Copyright 2009 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.
*/
package testapp;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.imageio.stream.FileCacheImageInputStream;
import javax.imageio.stream.ImageInputStream;
public class Main {
public static void main(String[] args) {
Main o = new Main("testapp.some.class", null);
o.launch(null);
}
private final String uniqClassName;
private final ConcurrentLinkedQueue<Throwable> problems;
public Main(String uniq, ConcurrentLinkedQueue<Throwable> p) {
uniqClassName = uniq;
problems = p;
}
public void launch(HashMap<String, ImageInputStream> refs) {
System.out.printf("%s: current context class loader: %s\n",
uniqClassName,
Thread.currentThread().getContextClassLoader());
try {
byte[] data = new byte[1024];
ByteArrayInputStream bais = new ByteArrayInputStream(data);
MyImageInputStream iis = new MyImageInputStream(bais,
uniqClassName,
problems);
if (refs != null) {
System.out.printf("%s: added to strong store\n",
uniqClassName);
refs.put(uniqClassName, iis);
}
iis.read();
//leave stream open : let's shutdown hook work!
} catch (IOException e) {
problems.add(e);
}
}
private static class MyImageInputStream extends FileCacheImageInputStream {
private final String uniqClassName;
private ConcurrentLinkedQueue<Throwable> problems;
public MyImageInputStream(InputStream is, String uniq,
ConcurrentLinkedQueue<Throwable> p) throws IOException
{
super(is, new File("tmp"));
uniqClassName = uniq;
problems = p;
}
@Override
public void close() throws IOException {
Test t = new Test();
try {
t.doTest(uniqClassName);
} catch (Throwable e) {
problems.add(e);
}
super.close();
problems = null;
}
}
}
class Test {
public void doTest(String uniqClassName) throws ClassNotFoundException {
System.out.printf("%s: Current thread: %s\n", uniqClassName,
Thread.currentThread());
ClassLoader thisCL = this.getClass().getClassLoader();
Class uniq = thisCL.loadClass(uniqClassName);
System.out.printf("%s: test is done!\n",uniqClassName);
}
}
/*
* Copyright 2009 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 6800846
*
* @summary Test verifes that images with short palette are rendered
* withourt artifacts.
*
* @run main DrawByteBinary
*/
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import static java.awt.image.BufferedImage.*;
public class DrawByteBinary {
public static void main(String args[]) {
int w = 100, h = 30;
int x = 10;
byte[] arr = {(byte)0xff, (byte)0x0, (byte)0x00};
IndexColorModel newCM = new IndexColorModel(1, 2, arr, arr, arr);
BufferedImage orig = new BufferedImage(w, h, TYPE_BYTE_BINARY, newCM);
Graphics2D g2d = orig.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, w, h);
g2d.setColor(Color.black);
g2d.drawLine(x, 0, x, h);
g2d.dispose();
IndexColorModel origCM = (IndexColorModel)orig.getColorModel();
BufferedImage test = new BufferedImage(w, h, TYPE_BYTE_BINARY,origCM);
g2d = test.createGraphics();
g2d.drawImage(orig, 0, 0, null);
g2d.dispose();
int y = h / 2;
// we expect white color outside the line
if (test.getRGB(x - 1, y) != 0xffffffff) {
throw new RuntimeException("Invalid color outside the line.");
}
// we expect black color on the line
if (test.getRGB(x, y) != 0xff000000) {
throw new RuntimeException("Invalid color on the line.");
}
}
}
/*
* Copyright 2007-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 6476665 6523403 6733501
* @summary Verifies reading and writing profiles and tags of the standard color
* spaces
* @run main ReadWriteProfileTest
*/
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.util.*;
import java.nio.*;
import java.util.Hashtable;
public class ReadWriteProfileTest implements Runnable {
/* Location of the tag sig counter in 4-byte words */
final static int TAG_COUNT_OFFSET = 32;
/* Location of the tag sig table in 4-byte words */
final static int TAG_ELEM_OFFSET = 33;
static byte[][] profiles;
static int [][] tagSigs;
static Hashtable<Integer,byte[]> [] tags;
static int [] cspaces = {ColorSpace.CS_sRGB, ColorSpace.CS_PYCC,
ColorSpace.CS_LINEAR_RGB, ColorSpace.CS_CIEXYZ,
ColorSpace.CS_GRAY};
static String [] csNames = {"sRGB", "PYCC", "LINEAR_RGB", "CIEXYZ", "GRAY"};
static void getProfileTags(byte [] data, Hashtable tags) {
ByteBuffer byteBuf = ByteBuffer.wrap(data);
IntBuffer intBuf = byteBuf.asIntBuffer();
int tagCount = intBuf.get(TAG_COUNT_OFFSET);
intBuf.position(TAG_ELEM_OFFSET);
for (int i = 0; i < tagCount; i++) {
int tagSig = intBuf.get();
int tagDataOff = intBuf.get();
int tagSize = intBuf.get();
byte [] tagData = new byte[tagSize];
byteBuf.position(tagDataOff);
byteBuf.get(tagData);
tags.put(tagSig, tagData);
}
}
static {
profiles = new byte[cspaces.length][];
tags = new Hashtable[cspaces.length];
for (int i = 0; i < cspaces.length; i++) {
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
profiles[i] = pf.getData();
tags[i] = new Hashtable();
getProfileTags(profiles[i], tags[i]);
}
}
public void run() {
for (int i = 0; i < cspaces.length; i++) {
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
byte [] data = pf.getData();
pf = ICC_Profile.getInstance(data);
if (!Arrays.equals(data, profiles[i])) {
System.err.println("Incorrect result of getData() " + "with " +
csNames[i] + " profile");
throw new RuntimeException("Incorrect result of getData()");
}
for (int tagSig : tags[i].keySet()) {
byte [] tagData = pf.getData(tagSig);
byte [] empty = new byte[tagData.length];
pf.setData(tagSig, empty);
pf.setData(tagSig, tagData);
byte [] tagData1 = pf.getData(tagSig);
if (!Arrays.equals(tagData1, tags[i].get(tagSig)))
{
System.err.println("Incorrect result of getData(int) with" +
" tag " +
Integer.toHexString(tagSig) +
" of " + csNames[i] + " profile");
throw new RuntimeException("Incorrect result of " +
"getData(int)");
}
}
}
}
public static void main(String [] args) {
ReadWriteProfileTest test = new ReadWriteProfileTest();
test.run();
}
}
/*
* Copyright 2009 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
* @summary verify that first element is a dash
* @bug 6793344
*/
import java.awt.*;
import java.awt.image.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class DashStrokeTest extends Component {
static BufferedImage bi;
static boolean printed = false;
public Dimension getPreferredSize() {
return new Dimension(200,200);
}
public static void drawGui() {
bi = new BufferedImage(200, 20, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 1.0f, new float[] { 0.0f, 200 },
1.0f);
g2d.setStroke(dashStroke);
g2d.setColor(Color.RED);
g2d.drawLine(5,10, 100,10);
printed =true;
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
drawGui();
}
});
} catch (Exception e) {
}
if (printed) {
checkBI(bi, Color.RED);
}
}
static void checkBI(BufferedImage bi, Color badColor) {
int badrgb = badColor.getRGB();
int col = bi.getRGB(6, 9);
if (col == badrgb) {
throw new RuntimeException("A pixel was turned on. ");
}
}
}
/*
* Copyright 2009 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
* @summary Pass if no RuntimeException.
* @bug 6812600
*/
import java.awt.*;
import java.awt.image.BufferedImage;
public class JoinMiterTest {
public static void main(String[] args) throws Exception {
BufferedImage image = new BufferedImage(200, 200,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setPaint(Color.WHITE);
g.fill(new Rectangle(image.getWidth(), image.getHeight()));
g.translate(25, 100);
g.setPaint(Color.BLACK);
g.setStroke(new BasicStroke(20, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER));
g.draw(new Polygon(new int[] {0, 150, 0}, new int[] {75, 0, -75}, 3));
if (image.getRGB(16, 10) == Color.WHITE.getRGB()) {
throw new RuntimeException("Miter is not rendered.");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册