You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
11 KiB
318 lines
11 KiB
/*
|
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
package com.sun.imageio.plugins.gif;
|
|
|
|
import javax.imageio.metadata.IIOInvalidTreeException;
|
|
import javax.imageio.metadata.IIOMetadata;
|
|
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
|
import org.w3c.dom.Node;
|
|
|
|
/**
|
|
* Class which adds utility DOM element attribute access methods to
|
|
* <code>IIOMetadata</code> for subclass use.
|
|
*/
|
|
abstract class GIFMetadata extends IIOMetadata {
|
|
|
|
/**
|
|
* Represents an undefined value of integer attributes.
|
|
*/
|
|
static final int UNDEFINED_INTEGER_VALUE = -1;
|
|
|
|
//
|
|
// Note: These attribute methods were shamelessly lifted from
|
|
// com.sun.imageio.plugins.png.PNGMetadata and modified.
|
|
//
|
|
|
|
// Shorthand for throwing an IIOInvalidTreeException
|
|
protected static void fatal(Node node, String reason)
|
|
throws IIOInvalidTreeException {
|
|
throw new IIOInvalidTreeException(reason, node);
|
|
}
|
|
|
|
// Get an integer-valued attribute
|
|
protected static String getStringAttribute(Node node, String name,
|
|
String defaultValue,
|
|
boolean required,
|
|
String[] range)
|
|
throws IIOInvalidTreeException {
|
|
Node attr = node.getAttributes().getNamedItem(name);
|
|
if (attr == null) {
|
|
if (!required) {
|
|
return defaultValue;
|
|
} else {
|
|
fatal(node, "Required attribute " + name + " not present!");
|
|
}
|
|
}
|
|
String value = attr.getNodeValue();
|
|
|
|
if (range != null) {
|
|
if (value == null) {
|
|
fatal(node,
|
|
"Null value for "+node.getNodeName()+
|
|
" attribute "+name+"!");
|
|
}
|
|
boolean validValue = false;
|
|
int len = range.length;
|
|
for (int i = 0; i < len; i++) {
|
|
if (value.equals(range[i])) {
|
|
validValue = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!validValue) {
|
|
fatal(node,
|
|
"Bad value for "+node.getNodeName()+
|
|
" attribute "+name+"!");
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
// Get an integer-valued attribute
|
|
protected static int getIntAttribute(Node node, String name,
|
|
int defaultValue, boolean required,
|
|
boolean bounded, int min, int max)
|
|
throws IIOInvalidTreeException {
|
|
String value = getStringAttribute(node, name, null, required, null);
|
|
if (value == null || "".equals(value)) {
|
|
return defaultValue;
|
|
}
|
|
|
|
int intValue = defaultValue;
|
|
try {
|
|
intValue = Integer.parseInt(value);
|
|
} catch (NumberFormatException e) {
|
|
fatal(node,
|
|
"Bad value for "+node.getNodeName()+
|
|
" attribute "+name+"!");
|
|
}
|
|
if (bounded && (intValue < min || intValue > max)) {
|
|
fatal(node,
|
|
"Bad value for "+node.getNodeName()+
|
|
" attribute "+name+"!");
|
|
}
|
|
return intValue;
|
|
}
|
|
|
|
// Get a float-valued attribute
|
|
protected static float getFloatAttribute(Node node, String name,
|
|
float defaultValue,
|
|
boolean required)
|
|
throws IIOInvalidTreeException {
|
|
String value = getStringAttribute(node, name, null, required, null);
|
|
if (value == null) {
|
|
return defaultValue;
|
|
}
|
|
return Float.parseFloat(value);
|
|
}
|
|
|
|
// Get a required integer-valued attribute
|
|
protected static int getIntAttribute(Node node, String name,
|
|
boolean bounded, int min, int max)
|
|
throws IIOInvalidTreeException {
|
|
return getIntAttribute(node, name, -1, true, bounded, min, max);
|
|
}
|
|
|
|
// Get a required float-valued attribute
|
|
protected static float getFloatAttribute(Node node, String name)
|
|
throws IIOInvalidTreeException {
|
|
return getFloatAttribute(node, name, -1.0F, true);
|
|
}
|
|
|
|
// Get a boolean-valued attribute
|
|
protected static boolean getBooleanAttribute(Node node, String name,
|
|
boolean defaultValue,
|
|
boolean required)
|
|
throws IIOInvalidTreeException {
|
|
Node attr = node.getAttributes().getNamedItem(name);
|
|
if (attr == null) {
|
|
if (!required) {
|
|
return defaultValue;
|
|
} else {
|
|
fatal(node, "Required attribute " + name + " not present!");
|
|
}
|
|
}
|
|
String value = attr.getNodeValue();
|
|
// Allow lower case booleans for backward compatibility, #5082756
|
|
if (value.equals("TRUE") || value.equals("true")) {
|
|
return true;
|
|
} else if (value.equals("FALSE") || value.equals("false")) {
|
|
return false;
|
|
} else {
|
|
fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Get a required boolean-valued attribute
|
|
protected static boolean getBooleanAttribute(Node node, String name)
|
|
throws IIOInvalidTreeException {
|
|
return getBooleanAttribute(node, name, false, true);
|
|
}
|
|
|
|
// Get an enumerated attribute as an index into a String array
|
|
protected static int getEnumeratedAttribute(Node node,
|
|
String name,
|
|
String[] legalNames,
|
|
int defaultValue,
|
|
boolean required)
|
|
throws IIOInvalidTreeException {
|
|
Node attr = node.getAttributes().getNamedItem(name);
|
|
if (attr == null) {
|
|
if (!required) {
|
|
return defaultValue;
|
|
} else {
|
|
fatal(node, "Required attribute " + name + " not present!");
|
|
}
|
|
}
|
|
String value = attr.getNodeValue();
|
|
for (int i = 0; i < legalNames.length; i++) {
|
|
if(value.equals(legalNames[i])) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
fatal(node, "Illegal value for attribute " + name + "!");
|
|
return -1;
|
|
}
|
|
|
|
// Get a required enumerated attribute as an index into a String array
|
|
protected static int getEnumeratedAttribute(Node node,
|
|
String name,
|
|
String[] legalNames)
|
|
throws IIOInvalidTreeException {
|
|
return getEnumeratedAttribute(node, name, legalNames, -1, true);
|
|
}
|
|
|
|
// Get a String-valued attribute
|
|
protected static String getAttribute(Node node, String name,
|
|
String defaultValue, boolean required)
|
|
throws IIOInvalidTreeException {
|
|
Node attr = node.getAttributes().getNamedItem(name);
|
|
if (attr == null) {
|
|
if (!required) {
|
|
return defaultValue;
|
|
} else {
|
|
fatal(node, "Required attribute " + name + " not present!");
|
|
}
|
|
}
|
|
return attr.getNodeValue();
|
|
}
|
|
|
|
// Get a required String-valued attribute
|
|
protected static String getAttribute(Node node, String name)
|
|
throws IIOInvalidTreeException {
|
|
return getAttribute(node, name, null, true);
|
|
}
|
|
|
|
protected GIFMetadata(boolean standardMetadataFormatSupported,
|
|
String nativeMetadataFormatName,
|
|
String nativeMetadataFormatClassName,
|
|
String[] extraMetadataFormatNames,
|
|
String[] extraMetadataFormatClassNames) {
|
|
super(standardMetadataFormatSupported,
|
|
nativeMetadataFormatName,
|
|
nativeMetadataFormatClassName,
|
|
extraMetadataFormatNames,
|
|
extraMetadataFormatClassNames);
|
|
}
|
|
|
|
public void mergeTree(String formatName, Node root)
|
|
throws IIOInvalidTreeException {
|
|
if (formatName.equals(nativeMetadataFormatName)) {
|
|
if (root == null) {
|
|
throw new IllegalArgumentException("root == null!");
|
|
}
|
|
mergeNativeTree(root);
|
|
} else if (formatName.equals
|
|
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
|
|
if (root == null) {
|
|
throw new IllegalArgumentException("root == null!");
|
|
}
|
|
mergeStandardTree(root);
|
|
} else {
|
|
throw new IllegalArgumentException("Not a recognized format!");
|
|
}
|
|
}
|
|
|
|
protected byte[] getColorTable(Node colorTableNode,
|
|
String entryNodeName,
|
|
boolean lengthExpected,
|
|
int expectedLength)
|
|
throws IIOInvalidTreeException {
|
|
byte[] red = new byte[256];
|
|
byte[] green = new byte[256];
|
|
byte[] blue = new byte[256];
|
|
int maxIndex = -1;
|
|
|
|
Node entry = colorTableNode.getFirstChild();
|
|
if (entry == null) {
|
|
fatal(colorTableNode, "Palette has no entries!");
|
|
}
|
|
|
|
while (entry != null) {
|
|
if (!entry.getNodeName().equals(entryNodeName)) {
|
|
fatal(colorTableNode,
|
|
"Only a "+entryNodeName+" may be a child of a "+
|
|
entry.getNodeName()+"!");
|
|
}
|
|
|
|
int index = getIntAttribute(entry, "index", true, 0, 255);
|
|
if (index > maxIndex) {
|
|
maxIndex = index;
|
|
}
|
|
red[index] = (byte)getIntAttribute(entry, "red", true, 0, 255);
|
|
green[index] = (byte)getIntAttribute(entry, "green", true, 0, 255);
|
|
blue[index] = (byte)getIntAttribute(entry, "blue", true, 0, 255);
|
|
|
|
entry = entry.getNextSibling();
|
|
}
|
|
|
|
int numEntries = maxIndex + 1;
|
|
|
|
if (lengthExpected && numEntries != expectedLength) {
|
|
fatal(colorTableNode, "Unexpected length for palette!");
|
|
}
|
|
|
|
byte[] colorTable = new byte[3*numEntries];
|
|
for (int i = 0, j = 0; i < numEntries; i++) {
|
|
colorTable[j++] = red[i];
|
|
colorTable[j++] = green[i];
|
|
colorTable[j++] = blue[i];
|
|
}
|
|
|
|
return colorTable;
|
|
}
|
|
|
|
protected abstract void mergeNativeTree(Node root)
|
|
throws IIOInvalidTreeException;
|
|
|
|
protected abstract void mergeStandardTree(Node root)
|
|
throws IIOInvalidTreeException;
|
|
}
|