| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
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;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
abstract class GIFMetadata extends IIOMetadata { | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    static final int UNDEFINED_INTEGER_VALUE = -1;  | 
 | 
 | 
 | 
    //  | 
 | 
    // Note: These attribute methods were shamelessly lifted from  | 
 | 
    // com.sun.imageio.plugins.png.PNGMetadata and modified.  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
    protected static void fatal(Node node, String reason)  | 
 | 
      throws IIOInvalidTreeException { | 
 | 
        throw new IIOInvalidTreeException(reason, node);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
    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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    protected static float getFloatAttribute(Node node, String name)  | 
 | 
      throws IIOInvalidTreeException { | 
 | 
        return getFloatAttribute(node, name, -1.0F, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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();  | 
 | 
          | 
 | 
        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;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    protected static boolean getBooleanAttribute(Node node, String name)  | 
 | 
      throws IIOInvalidTreeException { | 
 | 
        return getBooleanAttribute(node, name, false, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    protected static int getEnumeratedAttribute(Node node,  | 
 | 
                                                String name,  | 
 | 
                                                String[] legalNames)  | 
 | 
      throws IIOInvalidTreeException { | 
 | 
        return getEnumeratedAttribute(node, name, legalNames, -1, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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;  | 
 | 
}  |