mass rename and rebranding from xwt to ibex - fixed to use ixt files
[org.ibex.core.git] / src / org / xwt / translators / PNG.java
index 19e382f..5653a03 100644 (file)
 
 package org.xwt.translators;
 
-import org.xwt.*;
-import org.xwt.util.*;
+import org.ibex.*;
+import org.ibex.util.*;
 import java.io.*;
-import java.util.Hashtable;
-import java.util.Vector;
 import java.util.Enumeration;
 import java.util.zip.*;
 
@@ -26,68 +24,83 @@ public class PNG {
 
     public PNG() { }
     
+    private static Queue instances = new Queue(10);
+    private Picture p;
+
+    public static void load(InputStream is, Picture p) {
+        PNG g = (PNG)instances.remove(false);
+        if (g == null) g = new PNG();
+        try {
+            g._load(is, p);
+            p.data = g.data;
+        } catch (Exception e) {
+            if (Log.on) Log.info(PNG.class, e);
+            return;
+        }
+        // FIXME: must reset fields
+        // if (instances.size() < 10) instances.append(g);
+    }
+
     // Public Methods ///////////////////////////////////////////////////////////////////////////////
 
     /** process a PNG as an inputstream; returns null if there is an error
         @param name A string describing the image, to be used when logging errors
     */
-    public Picture fromInputStream(InputStream is, String name) throws IOException {
-        underlyingStream = is;
+    private void _load(InputStream is, Picture pic) throws IOException {
+        p = pic;
+        if (is instanceof BufferedInputStream) underlyingStream = (BufferedInputStream)is;
+        else underlyingStream = new BufferedInputStream(is);
         target_offset = 0;
         inputStream = new DataInputStream(underlyingStream);
         
         // consume the header
         if ((inputStream.read() != 137) || (inputStream.read() != 80) || (inputStream.read() != 78) || (inputStream.read() != 71) ||
             (inputStream.read() != 13) || (inputStream.read() != 10) || (inputStream.read() != 26) || (inputStream.read() != 10)) {
-            Log.log(this, "PNG: error: input file " + name + " is not a PNG file");
-            data = new int[] { };
-            width = height = 0;
-            return null;
+            Log.info(this, "PNG: error: input file is not a PNG file");
+            data = p.data = new int[] { };
+            p.width = p.height = 0;
+            return;
         }
         
-        DONE: while (!error) {
+
+        while (!error) {
             if (needChunkInfo) {
                 chunkLength = inputStream.readInt();
                 chunkType = inputStream.readInt();
                 needChunkInfo = false;
             }
             
-            switch (chunkType) {
-            case CHUNK_bKGD: inputStream.skip(chunkLength); break;
-            case CHUNK_cHRM: inputStream.skip(chunkLength); break;
-            case CHUNK_gAMA: inputStream.skip(chunkLength); break;
-            case CHUNK_hIST: inputStream.skip(chunkLength); break;
-            case CHUNK_pHYs: inputStream.skip(chunkLength); break;
-            case CHUNK_sBIT: inputStream.skip(chunkLength); break;
-            case CHUNK_tEXt: inputStream.skip(chunkLength); break;
-            case CHUNK_zTXt: inputStream.skip(chunkLength); break;
-            case CHUNK_tIME: inputStream.skip(chunkLength); break;
-                
-            case CHUNK_IHDR: handleIHDR(); break;
-            case CHUNK_PLTE: handlePLTE(); break;
-            case CHUNK_tRNS: handletRNS(); break;
-                
-            case CHUNK_IDAT: handleIDAT(); break;
-                
-            case CHUNK_IEND: break DONE;
-            default:
-                System.err.println("unrecognized chunk type " +
-                                   Integer.toHexString(chunkType) + ". skipping");
+           // I rewrote this as an if/else to work around a JODE bug with switch() blocks
+           if (chunkType == CHUNK_bKGD) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_cHRM) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_gAMA) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_hIST) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_pHYs) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_sBIT) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_tEXt) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_zTXt) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_tIME) inputStream.skip(chunkLength);
+           else if (chunkType == CHUNK_IHDR) handleIHDR();
+           else if (chunkType == CHUNK_PLTE) handlePLTE();
+           else if (chunkType == CHUNK_tRNS) handletRNS();
+           else if (chunkType == CHUNK_IDAT) handleIDAT();
+           else if (chunkType == CHUNK_IEND) break;
+           else {
+                System.err.println("unrecognized chunk type " + Integer.toHexString(chunkType) + ". skipping");
                 inputStream.skip(chunkLength);
             }
             
             int crc = inputStream.readInt();
             needChunkInfo = true;
         }
-
-        return Platform.createPicture(data, width, height);
+        p.isLoaded = true;
     }
 
     // Chunk Handlers ///////////////////////////////////////////////////////////////////////
 
     /** handle data chunk */
     private void handleIDAT() throws IOException {
-        if (width == -1 || height == -1) throw new IOException("never got image width/height");
+        if (p.width == -1 || p.height == -1) throw new IOException("never got image width/height");
         switch (depth) {
         case 1: mask = 0x1; break;
         case 2: mask = 0x3; break;
@@ -98,7 +111,7 @@ public class PNG {
         if (depth < 8) smask = mask << depth;
         else smask = mask << 8;
 
-        int count = width * height;
+        int count = p.width * p.height;
 
         switch (colorType) {
         case 0:
@@ -123,8 +136,8 @@ public class PNG {
     private void handleIHDR() throws IOException {
         if (headerFound) throw new IOException("Extraneous IHDR chunk encountered.");
         if (chunkLength != 13) throw new IOException("IHDR chunk length wrong: " + chunkLength);
-        width = inputStream.readInt();
-        height = inputStream.readInt();
+        p.width = inputStream.readInt();
+        p.height = inputStream.readInt();
         depth = inputStream.read();
         colorType = inputStream.read();
         compressionMethod = inputStream.read();
@@ -147,7 +160,7 @@ public class PNG {
     private void handletRNS() throws IOException {
         int chunkLen = chunkLength;
         if (palette == null) {
-            if (Log.on) Log.log(this, "warning: tRNS chunk encountered before pLTE; ignoring alpha channel");
+            if (Log.on) Log.info(this, "warning: tRNS chunk encountered before pLTE; ignoring alpha channel");
             inputStream.skip(chunkLength);
             return;
         }
@@ -196,21 +209,21 @@ public class PNG {
             int rInc = rowInc[pass];
             int cInc = colInc[pass];
             int sCol = startingCol[pass];
-            int val = (width - sCol + cInc - 1) / cInc;
+            int val = (p.width - sCol + cInc - 1) / cInc;
             int samples = val * filterOffset;
             int rowSize = (val * bps)>>3;
             int sRow = startingRow[pass];
-            if (height <= sRow || rowSize == 0) continue;
-            int sInc = rInc * width;
+            if (p.height <= sRow || rowSize == 0) continue;
+            int sInc = rInc * p.width;
             byte inbuf[] = new byte[rowSize];
             int pix[] = new int[rowSize];
             int upix[] = null;
             int temp[] = new int[rowSize];
             int nextY = sRow;               // next Y value and number of rows to report to sendPixels
             int rows = 0;
-            int rowStart = sRow * width;
+            int rowStart = sRow * p.width;
 
-            for (int y = sRow; y < height; y += rInc, rowStart += sInc) {
+            for (int y = sRow; y < p.height; y += rInc, rowStart += sInc) {
                 rows += rInc;
                 int rowFilter = dis.read();
                 dis.readFully(inbuf);
@@ -406,7 +419,7 @@ public class PNG {
 
     private void blockFill(int rowStart) {
         int counter;
-        int dw = width;
+        int dw = p.width;
         int pass = this.pass;
         int w = blockWidth[pass];
         int sCol = startingCol[pass];
@@ -532,8 +545,6 @@ public class PNG {
     // Private Data ///////////////////////////////////////////////////////////////////////////////////////
     
     private int target_offset = 0;
-    private int width = -1;
-    private int height = -1;
     private int sigmask = 0xffff;
     private Object pixels = null;
     private int ipixels[] = null;
@@ -542,7 +553,7 @@ public class PNG {
     private boolean complete = false;
     private boolean error = false;
 
-    private int[] data = null;
+    int[] data = null;
 
     private InputStream underlyingStream = null;
     private DataInputStream inputStream = null;