You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2014/02/09 02:14:55 UTC

svn commit: r1566181 [1/2] - in /poi/branches/wmf_render/src: java/org/apache/poi/util/ scratchpad/src/org/apache/poi/hwmf/ scratchpad/src/org/apache/poi/hwmf/record/

Author: kiwiwings
Date: Sun Feb  9 01:14:54 2014
New Revision: 1566181

URL: http://svn.apache.org/r1566181
Log:
Bug 56004 - Support for WMF rendering - (working copy commit)

Added:
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/HwmfPicture.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/BitInputStream.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap16.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmapDib.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfColorRef.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDibCreatePatternBrush.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDraw.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfEscape.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfFill.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfHeader.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfMoveTo.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfNoArg.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfPalette.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfPlaceableHeader.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfRecord.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfRecordType.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfRestoreDc.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetBkColor.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetBkMode.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetLayout.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetMapMode.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetMapperFlags.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetRop2.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfSetStretchBltMode.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfTernaryRasterOp.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfText.java
    poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfWindowing.java
Modified:
    poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndian.java
    poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndianInputStream.java

Modified: poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndian.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndian.java?rev=1566181&r1=1566180&r2=1566181&view=diff
==============================================================================
--- poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndian.java (original)
+++ poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndian.java Sun Feb  9 01:14:54 2014
@@ -111,7 +111,7 @@ public class LittleEndian implements Lit
      * 
      * @param data
      *            the byte array
-     * @return the double (64-bit) value
+     * @return the float (32-bit) value
      */
     public static float getFloat( byte[] data )
     {
@@ -127,7 +127,7 @@ public class LittleEndian implements Lit
      *            the byte array
      * @param offset
      *            a starting offset into the byte array
-     * @return the double (64-bit) value
+     * @return the float (32-bit) value
      */
     public static float getFloat( byte[] data, int offset )
     {

Modified: poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndianInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndianInputStream.java?rev=1566181&r1=1566180&r2=1566181&view=diff
==============================================================================
--- poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndianInputStream.java (original)
+++ poi/branches/wmf_render/src/java/org/apache/poi/util/LittleEndianInputStream.java Sun Feb  9 01:14:54 2014
@@ -30,9 +30,12 @@ import java.io.InputStream;
  * @author Josh Micich
  */
 public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
+    private byte _buf[] = new byte[LittleEndianConsts.LONG_SIZE];
+    
 	public LittleEndianInputStream(InputStream is) {
 		super(is);
 	}
+	
 	public int available() {
 		try {
 			return super.available();
@@ -40,105 +43,65 @@ public class LittleEndianInputStream ext
 			throw new RuntimeException(e);
 		}
 	}
+	
 	public byte readByte() {
-		return (byte)readUByte();
+	    readFully(_buf, 0, LittleEndianConsts.BYTE_SIZE);
+	    return _buf[0];
 	}
+	
 	public int readUByte() {
-		int ch;
-		try {
-			ch = in.read();
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-		checkEOF(ch);
-		return ch;
-	}
-	public double readDouble() {
-		return Double.longBitsToDouble(readLong());
+        readFully(_buf, 0, LittleEndianConsts.BYTE_SIZE);
+        return LittleEndian.getUByte(_buf);
 	}
+	
+    public short readShort() {
+        readFully(_buf, 0, LittleEndianConsts.SHORT_SIZE);
+        return LittleEndian.getShort(_buf);
+    }
+    
+    public int readUShort() {
+        readFully(_buf, 0, LittleEndianConsts.SHORT_SIZE);
+        return LittleEndian.getUShort(_buf);
+    }
+    
 	public int readInt() {
-		int ch1;
-		int ch2;
-		int ch3;
-		int ch4;
-		try {
-			ch1 = in.read();
-			ch2 = in.read();
-			ch3 = in.read();
-			ch4 = in.read();
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-		checkEOF(ch1 | ch2 | ch3 | ch4);
-		return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
+        readFully(_buf, 0, LittleEndianConsts.INT_SIZE);
+	    return LittleEndian.getInt(_buf);
 	}
+
+    public long readUInt() {
+        readFully(_buf, 0, LittleEndianConsts.INT_SIZE);
+        return LittleEndian.getUInt(_buf);
+    }
+	
 	public long readLong() {
-		int b0;
-		int b1;
-		int b2;
-		int b3;
-		int b4;
-		int b5;
-		int b6;
-		int b7;
-		try {
-			b0 = in.read();
-			b1 = in.read();
-			b2 = in.read();
-			b3 = in.read();
-			b4 = in.read();
-			b5 = in.read();
-			b6 = in.read();
-			b7 = in.read();
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-		checkEOF(b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7);
-		return (((long)b7 << 56) +
-				((long)b6 << 48) +
-				((long)b5 << 40) +
-				((long)b4 << 32) +
-				((long)b3 << 24) +
-				(b2 << 16) +
-				(b1 <<  8) +
-				(b0 <<  0));
-	}
-	public short readShort() {
-		return (short)readUShort();
-	}
-	public int readUShort() {
-		int ch1;
-		int ch2;
-		try {
-			ch1 = in.read();
-			ch2 = in.read();
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-		checkEOF(ch1 | ch2);
-		return (ch2 << 8) + (ch1 << 0);
-	}
-	private static void checkEOF(int value) {
-		if (value <0) {
-			throw new RuntimeException("Unexpected end-of-file");
-		}
+        readFully(_buf, 0, LittleEndianConsts.LONG_SIZE);
+        return LittleEndian.getLong(_buf);
 	}
-
+	
+    public double readDouble() {
+        readFully(_buf, 0, LittleEndianConsts.LONG_SIZE);
+        return LittleEndian.getDouble(_buf);
+    }
+    
 	public void readFully(byte[] buf) {
 		readFully(buf, 0, buf.length);
 	}
 
 	public void readFully(byte[] buf, int off, int len) {
-		int max = off+len;
-		for(int i=off; i<max; i++) {
-			int ch;
-			try {
-				ch = in.read();
-			} catch (IOException e) {
-				throw new RuntimeException(e);
-			}
-			checkEOF(ch);
-			buf[i] = (byte) ch;
-		}
+	    if (buf == null || buf.length == 0) {
+	        return;
+	    }
+	    
+	    int readBytes;
+	    try {
+	        readBytes = super.read(buf, off, len);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+	    }
+	    
+        if (readBytes == -1 || readBytes < len ) {
+            throw new RuntimeException("Unexpected end-of-file");
+        }
 	}
 }

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/HwmfPicture.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/HwmfPicture.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/HwmfPicture.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/HwmfPicture.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,47 @@
+package org.apache.poi.hwmf;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.poi.hwmf.record.WmfHeader;
+import org.apache.poi.hwmf.record.WmfPlaceableHeader;
+import org.apache.poi.hwmf.record.WmfRecord;
+import org.apache.poi.hwmf.record.WmfRecordType;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class HwmfPicture {
+    // http://www.symantec.com/avcenter/reference/inside.the.windows.meta.file.format.pdf
+    
+    public HwmfPicture(InputStream inputStream) throws IOException {
+        LittleEndianInputStream leis = new LittleEndianInputStream(inputStream);
+        WmfPlaceableHeader placeableHeader = WmfPlaceableHeader.readHeader(leis);
+        WmfHeader header = new WmfHeader(leis);
+        
+        for (;;) {
+            long recordSize = leis.readUInt();
+            int recordFunction = leis.readShort();
+            WmfRecordType wrt = WmfRecordType.getById(recordFunction);
+            if (wrt == null) {
+                throw new IOException("unexpected record type: "+recordFunction);
+            }
+            if (wrt == WmfRecordType.eof) break;
+            if (wrt.clazz == null) {
+                throw new IOException("unsupported record type: "+recordFunction);
+            }
+            
+            WmfRecord wr;
+            try {
+                wr = wrt.clazz.newInstance();
+            } catch (Exception e) {
+                throw (IOException)new IOException("can't create wmf record").initCause(e);
+            }
+            
+            int consumedSize = wr.init(leis, recordSize, recordFunction);
+            if (consumedSize < recordSize) {
+                leis.skip(recordSize - consumedSize);
+            }
+        }
+    }
+
+
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/BitInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/BitInputStream.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/BitInputStream.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/BitInputStream.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,159 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Taken from https://code.google.com/p/javasupport/source/browse/branches/java-examples/src/main/java/deng/huffman/dukehuff/test/BitInputStream.java?r=587
+ * 
+ * reads bits-at-a-time where the number of bits is between 1 and 32.
+ * Updated for version 2.0 to extend java.io.InputStream
+ * <P>
+ * @author Owen Astrachan
+ * @version 1.0, July 2000
+ * @version 2.0, October 2004
+ */
+
+public class BitInputStream extends InputStream
+{
+    private InputStream     myInput;
+    private int             myBitCount;
+    private int             myBuffer;
+    private File            myFile;
+    
+    private static final int bmask[] = {
+        0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
+        0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
+        0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,
+        0x7fffff,0xffffff,0x1ffffff,0x3ffffff,0x7ffffff,
+        0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
+    };
+
+    private static final int BITS_PER_BYTE = 8;
+    /**
+     * Construct a bit-at-a-time input stream from a file
+     */
+    public BitInputStream(String filename)
+    {
+        this(new File(filename));
+    }
+    
+    /**
+     * Construct a bit-at-a-time input stream from <code>file</code>
+     * @param file is the File that is the source of the input
+     */
+    public BitInputStream(File file)
+    {
+        myFile = file;  
+        try {
+            reset();
+        } catch (IOException e) {
+            // eat the exception
+        }
+        
+    }
+    
+    public BitInputStream(InputStream in){
+        myInput = in;
+        myFile = null;
+    }
+    
+    /**
+     * This is a reset-able stream, so return true.
+     * @return true
+     */
+    public boolean markSupported(){
+        return myFile != null;
+    }
+
+    /**
+     * reset stream to beginning. The implementation creates a new
+     * stream.
+     * @throws IOException
+     */
+    
+    public void reset() throws IOException
+    {
+        if (! markSupported()){
+            throw new IOException("not resettable");
+        }
+        try{
+            close();
+            myInput = new BufferedInputStream(new FileInputStream(myFile));
+        }
+        catch (FileNotFoundException fnf){
+            System.err.println("error opening " + myFile.getName() + " " + fnf);
+        }
+        myBuffer = myBitCount = 0;
+    } 
+
+    /**
+     * closes the input stream
+     */
+    
+    public void close()
+    {
+        try{
+            if (myInput != null) {
+                myInput.close();
+            }
+        }
+        catch (java.io.IOException ioe){
+            System.err.println("error closing bit stream " + ioe);
+        }
+    }
+
+    /**
+     * returns the number of bits requested as rightmost bits in
+     * returned value, returns -1 if not enough bits available to
+     * satisfy the request
+     *
+     * @param howManyBits is the number of bits to read and return
+     * @return the value read, only rightmost <code>howManyBits</code>
+     * are valid, returns -1 if not enough bits left
+     */
+
+    public int read(int howManyBits) throws IOException
+    {
+        int retval = 0;
+        if (myInput == null){
+            return -1;
+        }
+        
+        while (howManyBits > myBitCount){
+            retval |= ( myBuffer << (howManyBits - myBitCount) );
+            howManyBits -= myBitCount;
+            try{
+                if ( (myBuffer = myInput.read()) == -1) {
+                    return -1;
+                }
+            }
+            catch (IOException ioe) {
+                throw new IOException("bitreading trouble "+ioe);
+            }
+            myBitCount = BITS_PER_BYTE;
+        }
+
+        if (howManyBits > 0){
+            retval |= myBuffer >> (myBitCount - howManyBits);
+            myBuffer &= bmask[myBitCount - howManyBits];
+            myBitCount -= howManyBits;
+        }
+        return retval;
+    }
+
+    /**
+     * Required by classes extending InputStream, returns
+     * the next byte from this stream as an int value.
+     * @return the next byte from this stream
+     */
+    public int read() throws IOException {
+        return read(8);
+    }
+}
+
+

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,92 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfBitmap {
+
+    /**
+     * The META_SETDIBTODEV record sets a block of pixels in the playback device context
+     * using deviceindependent color data.
+     * The source of the color data is a DIB
+     */
+    public static class WmfSetDibToDev implements WmfRecord {
+
+        /**
+         * A 16-bit unsigned integer that defines whether the Colors field of the
+         * DIB contains explicit RGB values or indexes into a palette.
+         * This MUST be one of the values in the ColorUsage Enumeration:
+         * DIB_RGB_COLORS = 0x0000,
+         * DIB_PAL_COLORS = 0x0001,
+         * DIB_PAL_INDICES = 0x0002
+         */
+        int colorUsage;  
+        /**
+         * A 16-bit unsigned integer that defines the number of scan lines in the source.
+         */
+        int scanCount;
+        /**
+         * A 16-bit unsigned integer that defines the starting scan line in the source.
+         */
+        int startScan;  
+        /**
+         * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the
+         * source rectangle.
+         */
+        int yDib;  
+        /**
+         * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the
+         * source rectangle.
+         */
+        int xDib;  
+        /**
+         * A 16-bit unsigned integer that defines the height, in logical units, of the
+         * source and destination rectangles.
+         */
+        int height;
+        /**
+         * A 16-bit unsigned integer that defines the width, in logical units, of the
+         * source and destination rectangles.
+         */
+        int width;
+        /**
+         * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the
+         * upper-left corner of the destination rectangle.
+         */
+        int yDest;
+        /**
+         * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the
+         * upper-left corner of the destination rectangle.
+         */
+        int xDest;
+        /**
+         * A variable-sized DeviceIndependentBitmap Object that is the source of the color data.
+         */
+        WmfBitmapDib dib;        
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.setDibToDev;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            colorUsage = leis.readUShort();
+            scanCount = leis.readUShort();
+            startScan = leis.readUShort();
+            yDib = leis.readUShort();
+            xDib = leis.readUShort();
+            height = leis.readUShort();
+            width = leis.readUShort();
+            yDest = leis.readUShort();
+            xDest = leis.readUShort();
+            
+            int size = 9*LittleEndianConsts.SHORT_SIZE;
+            dib = new WmfBitmapDib();
+            size += dib.init(leis);
+            
+            return size;
+        }        
+    }
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap16.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap16.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap16.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmap16.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,65 @@
+package org.apache.poi.hwmf.record;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfBitmap16 {
+    int type;
+    int width;
+    int height;
+    int widthBytes;
+    int planes;
+    int bitsPixel;
+    
+    public int init(LittleEndianInputStream leis) throws IOException {
+        // A 16-bit signed integer that defines the bitmap type.
+        type = leis.readShort();
+        
+        // A 16-bit signed integer that defines the width of the bitmap in pixels.
+        width = leis.readShort();
+        
+        // A 16-bit signed integer that defines the height of the bitmap in scan lines.
+        height = leis.readShort();
+        
+        // A 16-bit signed integer that defines the number of bytes per scan line.
+        widthBytes = leis.readShort();
+        
+        // An 8-bit unsigned integer that defines the number of color planes in the 
+        // bitmap. The value of this field MUST be 0x01.
+        planes = leis.readUByte();
+        
+        // An 8-bit unsigned integer that defines the number of adjacent color bits on 
+        // each plane.
+        bitsPixel = leis.readUByte();
+        
+        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE;
+        
+        int size2 = 0;
+        byte buf[] = new byte[widthBytes];
+        for (int h=0; h<height; h++) {
+            leis.read(buf);
+            size2 += widthBytes;
+
+            BitInputStream bis = new  BitInputStream(new ByteArrayInputStream(buf));
+            for (int w=0; w<width; w++) {
+                int bitsAtPixel = bis.read(bitsPixel);
+                // TODO: is bitsPixel a multiple of 3 (r,g,b)
+                // which colortable should be used for the various bit sizes???
+                
+            }
+        }
+        
+        int bytes = (((width * bitsPixel + 15) >> 4) << 1) * height;
+        assert (bytes == size2);
+
+        size += size2;
+        
+        
+        return size;
+    }
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmapDib.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmapDib.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmapDib.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfBitmapDib.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,424 @@
+package org.apache.poi.hwmf.record;
+
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+/**
+ * The DeviceIndependentBitmap Object defines an image in device-independent bitmap (DIB) format.
+ */
+public class WmfBitmapDib {
+    public static enum BitCount {
+        /**
+         * The image SHOULD be in either JPEG or PNG format. <6> Neither of these formats includes
+         *  a color table, so this value specifies that no color table is present. See [JFIF] and [RFC2083]
+         *  for more information concerning JPEG and PNG compression formats.
+         */
+        BI_BITCOUNT_0(0x0000),
+        /**
+         * Each pixel in the bitmap is represented by a single bit. If the bit is clear, the pixel is displayed
+         *  with the color of the first entry in the color table; if the bit is set, the pixel has the color of the
+         *  second entry in the table.
+         */
+        BI_BITCOUNT_1(0x0001),
+        /**
+         * Each pixel in the bitmap is represented by a 4-bit index into the color table, and each byte
+         *  contains 2 pixels.
+         */
+        BI_BITCOUNT_2(0x0004),
+        /**
+         * Each pixel in the bitmap is represented by an 8-bit index into the color table, and each byte
+         *  contains 1 pixel.
+         */
+        BI_BITCOUNT_3(0x0008),
+        /**
+         * Each pixel in the bitmap is represented by a 16-bit value.
+         * <br/>
+         * If the Compression field of the BitmapInfoHeader Object is BI_RGB, the Colors field of DIB
+         *  is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of 
+         *  red, green, and blue are represented with 5 bits for each color component. The value for blue 
+         *  is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant 
+         *  bit is not used. The color table is used for optimizing colors on palette-based devices, and 
+         *  contains the number of entries specified by the ColorUsed field of the BitmapInfoHeader 
+         *  Object.
+         * <br/>
+         * If the Compression field of the BitmapInfoHeader Object is BI_BITFIELDS, the Colors field 
+         *  contains three DWORD color masks that specify the red, green, and blue components,
+         *  respectively, of each pixel. Each WORD in the bitmap array represents a single pixel.
+         * <br/>
+         * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask MUST be 
+         *  contiguous and SHOULD NOT overlap the bits of another mask.
+         */
+        BI_BITCOUNT_4(0x0010),
+        /**
+         * The bitmap has a maximum of 2^24 colors, and the Colors field of DIB is 
+         *  NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, 
+         *  and red, respectively, for a pixel. The Colors color table is used for optimizing colors used on 
+         *  palette-based devices, and MUST contain the number of entries specified by the ColorUsed
+         *  field of the BitmapInfoHeader Object.
+         */
+        BI_BITCOUNT_5(0x0018),
+        /**
+         * The bitmap has a maximum of 2^24 colors.
+         * <br/>
+         * If the Compression field of the BitmapInfoHeader Object is set to BI_RGB, the Colors field 
+         *  of DIB is set to NULL. Each DWORD in the bitmap array represents the relative intensities of 
+         *  blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. The 
+         *  Colors color table is used for optimizing colors used on palette-based devices, and MUST 
+         *  contain the number of entries specified by the ColorUsed field of the BitmapInfoHeader 
+         *  Object.
+         * <br/>
+         * If the Compression field of the BitmapInfoHeader Object is set to BI_BITFIELDS, the Colors
+         *  field contains three DWORD color masks that specify the red, green, and blue components, 
+         *  respectively, of each pixel. Each DWORD in the bitmap array represents a single pixel.
+         * <br/>
+         * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask must be 
+         *  contiguous and should not overlap the bits of another mask. All the bits in the pixel do not 
+         *  need to be used.
+         */
+        BI_BITCOUNT_6(0x0020);
+        
+        int flag;
+        BitCount(int flag) {
+            this.flag = flag;
+        }
+        static BitCount valueOf(int flag) {
+            for (BitCount bc : values()) {
+                if (bc.flag == flag) return bc;
+            }
+            return null;
+        }
+    }
+
+    public static enum Compression {
+        /**
+         * The bitmap is in uncompressed red green blue (RGB) format that is not compressed
+         * and does not use color masks.
+         */
+        BI_RGB(0x0000),
+        /**
+         * An RGB format that uses run-length encoding (RLE) compression for bitmaps
+         * with 8 bits per pixel. The compression uses a 2-byte format consisting of a count byte
+         * followed by a byte containing a color index.
+         */
+        BI_RLE8(0x0001),
+        /**
+         * An RGB format that uses RLE compression for bitmaps with 4 bits per pixel. The
+         * compression uses a 2-byte format consisting of a count byte followed by two word-length
+         * color indexes.
+         */
+        BI_RLE4(0x0002),
+        /**
+         * The bitmap is not compressed and the color table consists of three DWORD
+         * color masks that specify the red, green, and blue components, respectively, of each pixel.
+         * This is valid when used with 16 and 32-bits per pixel bitmaps.
+         */
+        BI_BITFIELDS(0x0003),
+        /**
+         * The image is a JPEG image, as specified in [JFIF]. This value SHOULD only be used in 
+         * certain bitmap operations, such as JPEG pass-through. The application MUST query for the 
+         * pass-through support, since not all devices support JPEG pass-through. Using non-RGB 
+         * bitmaps MAY limit the portability of the metafile to other devices. For instance, display device 
+         * contexts generally do not support this pass-through.
+         */
+        BI_JPEG(0x0004),
+        /**
+         * The image is a PNG image, as specified in [RFC2083]. This value SHOULD only be 
+         * used certain bitmap operations, such as JPEG/PNG pass-through. The application MUST query 
+         * for the pass-through support, because not all devices support JPEG/PNG pass-through. Using 
+         * non-RGB bitmaps MAY limit the portability of the metafile to other devices. For instance, 
+         * display device contexts generally do not support this pass-through.
+         */
+        BI_PNG(0x0005),
+        /**
+         * The image is an uncompressed CMYK format.
+         */
+        BI_CMYK(0x000B),
+        /**
+         * A CMYK format that uses RLE compression for bitmaps with 8 bits per pixel.
+         * The compression uses a 2-byte format consisting of a count byte followed by a byte containing
+         * a color index.
+         */
+        BI_CMYKRLE8(0x000C),
+        /**
+         * A CMYK format that uses RLE compression for bitmaps with 4 bits per pixel.
+         * The compression uses a 2-byte format consisting of a count byte followed by two word-length
+         * color indexes.
+         */
+        BI_CMYKRLE4(0x000D);
+        
+        int flag;
+        Compression(int flag) {
+            this.flag = flag;
+        }
+        static Compression valueOf(int flag) {
+            for (Compression c : values()) {
+                if (c.flag == flag) return c;
+            }
+            return null;
+        }        
+    }
+    
+    
+    int headerSize;
+    int headerWidth;
+    int headerHeight;
+    int headerPlanes;
+    BitCount headerBitCount;
+    Compression headerCompression;
+    long headerImageSize = -1;
+    int headerXPelsPerMeter = -1;
+    int headerYPelsPerMeter = -1;
+    long headerColorUsed = -1;
+    long headerColorImportant = -1;
+    
+    Color colorTable[];
+    int colorMaskRed=0,colorMaskGreen=0,colorMaskBlue=0;
+    
+    public int init(LittleEndianInputStream leis) throws IOException {
+        int size = 0;
+        size += readHeader(leis);
+        size += readColors(leis);
+        int size2;
+        switch (headerBitCount) {
+            default:
+            case BI_BITCOUNT_0:
+                throw new RuntimeException("JPG and PNG formats aren't supported yet.");
+            case BI_BITCOUNT_1:
+            case BI_BITCOUNT_2:
+            case BI_BITCOUNT_3:
+                size2 = readBitmapIndexed(leis);
+                break;
+            case BI_BITCOUNT_4:
+            case BI_BITCOUNT_5:
+            case BI_BITCOUNT_6:
+                size2 = readBitmapDirect(leis);
+                break;
+        }
+        
+        assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == size2);
+        assert ( headerSize == 0x0C || headerImageSize == size2 );
+        
+        size += size2;
+        
+        return size;
+    }
+
+    protected int readHeader(LittleEndianInputStream leis) throws IOException {
+        int size = 0;
+        
+        /**
+         * DIBHeaderInfo (variable): Either a BitmapCoreHeader Object or a
+         * BitmapInfoHeader Object that specifies information about the image.
+         * 
+         * The first 32 bits of this field is the HeaderSize value.
+         * If it is 0x0000000C, then this is a BitmapCoreHeader; otherwise, this is a BitmapInfoHeader.
+         */
+        headerSize = leis.readInt();
+        size += LittleEndianConsts.INT_SIZE;
+        
+        // BitmapCoreHeader
+        // A 16-bit unsigned integer that defines the width of the DIB, in pixels.
+        headerWidth = leis.readUShort();
+        // A 16-bit unsigned integer that defines the height of the DIB, in pixels.
+        headerHeight = leis.readUShort();
+        // A 16-bit unsigned integer that defines the number of planes for the target
+        // device. This value MUST be 0x0001.
+        headerPlanes = leis.readUShort();
+        // A 16-bit unsigned integer that defines the format of each pixel, and the
+        // maximum number of colors in the DIB.
+        headerBitCount = BitCount.valueOf(leis.readUShort());
+        size += 4*LittleEndianConsts.SHORT_SIZE;
+
+        if (headerSize > 0x0C) {
+            // BitmapInfoHeader
+            // A 32-bit unsigned integer that defines the compression mode of the 
+            // DIB. 
+            // This value MUST NOT specify a compressed format if the DIB is a top-down bitmap,
+            // as indicated by the Height value.
+            headerCompression = Compression.valueOf((int)leis.readUInt());
+            // A 32-bit unsigned integer that defines the size, in bytes, of the image.
+            // If the Compression value is BI_RGB, this value SHOULD be zero and MUST be ignored.
+            // If the Compression value is BI_JPEG or BI_PNG, this value MUST specify the size of the JPEG 
+            // or PNG image buffer, respectively.
+            headerImageSize = leis.readUInt();
+            // A 32-bit signed integer that defines the horizontal resolution, 
+            // in pixels-per-meter, of the target device for the DIB.
+            headerXPelsPerMeter = leis.readInt();
+            // A 32-bit signed integer that defines the vertical resolution,
+            headerYPelsPerMeter = leis.readInt();
+            // A 32-bit unsigned integer that specifies the number of indexes in the
+            // color table used by the DIB
+            // in pixelsper-meter, of the target device for the DIB.
+            headerColorUsed = leis.readUInt();
+            // A 32-bit unsigned integer that defines the number of color indexes that are
+            // required for displaying the DIB. If this value is zero, all color indexes are required.
+            headerColorImportant = leis.readUInt();
+            size += 6*LittleEndianConsts.INT_SIZE;
+        }
+        return size;
+    }
+
+    protected int readColors(LittleEndianInputStream leis) throws IOException {
+        switch (headerBitCount) {
+        default:
+        case BI_BITCOUNT_0:
+            // no table
+            return 0;
+        case BI_BITCOUNT_1:
+            // 2 colors
+            return readRGBQuad(leis, 2);
+        case BI_BITCOUNT_2:
+            // 16 colors
+            return readRGBQuad(leis, 16);
+        case BI_BITCOUNT_3:
+            // 256 colors
+            return readRGBQuad(leis, 256);
+        case BI_BITCOUNT_5:
+            colorMaskRed=0xFF;
+            colorMaskGreen=0xFF;
+            colorMaskBlue=0xFF;
+            return 0;
+        case BI_BITCOUNT_4:
+            if (headerCompression == Compression.BI_RGB) {
+                colorMaskBlue = 0x1F;
+                colorMaskGreen = 0x1F<<5;
+                colorMaskRed = 0x1F<<10;
+                return 0;
+            } else {
+                assert(headerCompression == Compression.BI_BITFIELDS);
+                colorMaskBlue = leis.readInt();
+                colorMaskGreen = leis.readInt();
+                colorMaskRed = leis.readInt();
+                return 3*LittleEndianConsts.INT_SIZE;
+            }
+        case BI_BITCOUNT_6:    
+            if (headerCompression == Compression.BI_RGB) {
+                colorMaskBlue = colorMaskGreen = colorMaskRed = 0xFF;
+                return 0;
+            } else {
+                assert(headerCompression == Compression.BI_BITFIELDS);
+                colorMaskBlue = leis.readInt();
+                colorMaskGreen = leis.readInt();
+                colorMaskRed = leis.readInt();
+                return 3*LittleEndianConsts.INT_SIZE;
+            }
+        }
+    }
+    
+    protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException {
+        int size = 0;
+        List<Color> colorList = new ArrayList<Color>();
+        for (int i=0; i<count; i++) {
+            int blue = leis.readUByte();
+            int green = leis.readUByte();
+            int red = leis.readUByte();
+            @SuppressWarnings("unused")
+            int reserved = leis.readUByte();
+            Color c = new Color(red, green, blue);
+            colorList.add(c);
+            size += 4 * LittleEndianConsts.BYTE_SIZE;
+        }
+        colorTable = colorList.toArray(new Color[colorList.size()]);
+        return size;
+    }
+    
+    protected int readBitmapIndexed(LittleEndianInputStream leis) throws IOException {
+        assert(colorTable != null);
+        byte r[] = new byte[colorTable.length];
+        byte g[] = new byte[colorTable.length];
+        byte b[] = new byte[colorTable.length];
+        for (int i=0; i<colorTable.length; i++) {
+            r[i] = (byte)colorTable[i].getRed();
+            g[i] = (byte)colorTable[i].getGreen();
+            b[i] = (byte)colorTable[i].getBlue();
+        }
+        int bits = 32-Integer.numberOfLeadingZeros(colorTable.length);
+        IndexColorModel cm = new IndexColorModel(bits,colorTable.length,r,g,b);
+        
+        BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_BYTE_INDEXED, cm);
+        WritableRaster wr = bi.getRaster();
+        
+        int pixelCount = headerWidth*headerHeight;
+        int size = 0;
+        for (int pixel=0; pixel<pixelCount; size++) {
+            int v = leis.readUByte();
+            switch (headerBitCount) {
+            default:
+                throw new RuntimeException("invalid bitcount for indexed image");
+            case BI_BITCOUNT_1:
+                for (int j=0; j<8 && pixel<pixelCount; j++,pixel++) {
+                    wr.setSample(pixel/headerWidth,pixel%headerWidth,0,(v>>(7-j))&1);
+                }
+                break;
+            case BI_BITCOUNT_2:
+                wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, (v>>4)&15);
+                pixel++;
+                if (pixel<pixelCount) {
+                    wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v&15);
+                    pixel++;
+                }
+                break;
+            case BI_BITCOUNT_3:
+                wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v);
+                pixel++;
+                break;
+            }
+        }
+        return size;
+    }
+    
+    protected int readBitmapDirect(LittleEndianInputStream leis) throws IOException {
+        assert(colorTable == null);
+        
+        BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_INT_RGB);
+        WritableRaster wr = bi.getRaster();
+        
+        int bitShiftRed=0,bitShiftGreen=0,bitShiftBlue=0;
+        if (headerCompression == Compression.BI_BITFIELDS) {
+            bitShiftGreen = 32-Integer.numberOfLeadingZeros(this.colorMaskBlue);
+            bitShiftRed = 32-Integer.numberOfLeadingZeros(this.colorMaskGreen);
+        }
+        
+        int pixelCount = headerWidth*headerHeight;
+        int size = 0;
+        int rgb[] = new int[3];
+        for (int pixel=0; pixel<pixelCount; pixel++) {
+            int v;
+            switch (headerBitCount) {
+            default:
+                throw new RuntimeException("invalid bitcount for indexed image");
+            case BI_BITCOUNT_4:
+                v = leis.readUShort();
+                rgb[0] = (v & colorMaskRed) >> bitShiftRed;
+                rgb[1] = (v & colorMaskGreen) >> bitShiftGreen;
+                rgb[2] = (v & colorMaskBlue) >> bitShiftBlue;
+                size += LittleEndianConsts.SHORT_SIZE;
+                break;
+            case BI_BITCOUNT_5:
+                rgb[2] = leis.readUByte();
+                rgb[1] = leis.readUByte();
+                rgb[0] = leis.readUByte();
+                size += 3*LittleEndianConsts.BYTE_SIZE;
+                break;
+            case BI_BITCOUNT_6:
+                v = leis.readInt();
+                rgb[0] = (v & colorMaskRed) >> bitShiftRed;
+                rgb[1] = (v & colorMaskGreen) >> bitShiftGreen;
+                rgb[2] = (v & colorMaskBlue) >> bitShiftBlue;
+                size += LittleEndianConsts.INT_SIZE;
+                break;
+            }
+            wr.setPixel(pixel/headerWidth,pixel%headerWidth,rgb);
+        }
+        
+        return size;
+    }
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfColorRef.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfColorRef.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfColorRef.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfColorRef.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,30 @@
+package org.apache.poi.hwmf.record;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfColorRef {
+    /**
+     * A 32-bit ColorRef Object that defines the color value.
+     * Red (1 byte):  An 8-bit unsigned integer that defines the relative intensity of red.
+     * Green (1 byte):  An 8-bit unsigned integer that defines the relative intensity of green.
+     * Blue (1 byte):  An 8-bit unsigned integer that defines the relative intensity of blue.
+     * Reserved (1 byte):  An 8-bit unsigned integer that MUST be 0x00.
+     */
+    Color colorRef;
+    
+    public int init(LittleEndianInputStream leis) throws IOException {
+        int red = leis.readUByte();
+        int green = leis.readUByte();
+        int blue = leis.readUByte();
+        @SuppressWarnings("unused")
+        int reserved = leis.readUByte();
+
+        colorRef = new Color(red, green, blue);
+        return 4*LittleEndianConsts.BYTE_SIZE;
+    }
+
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDibCreatePatternBrush.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDibCreatePatternBrush.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDibCreatePatternBrush.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDibCreatePatternBrush.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,124 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+/**
+ * The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a
+ * pattern specified by a DeviceIndependentBitmap (DIB) Object 
+ */
+public class WmfDibCreatePatternBrush implements WmfRecord {
+    
+    /**
+     * A 16-bit unsigned integer that defines the brush style. The legal values for this
+     * field are defined as follows: if the value is not BS_PATTERN, BS_DIBPATTERNPT MUST be
+     * assumed.
+     */
+    public static enum BrushStyle {
+        /**
+         * A brush that paints a single, constant color, either solid or dithered.
+         */
+        BS_SOLID(0x0000),
+        /**
+         * A brush that does nothing. Using a BS_NULL brush in a graphics operation
+         * MUST have the same effect as using no brush at all.
+         */
+        BS_NULL(0x0001),
+        /**
+         * A brush that paints a predefined simple pattern, or "hatch", onto a solid background.
+         */
+        BS_HATCHED(0x0002),
+        /**
+         * A brush that paints a pattern defined by a bitmap, which MAY be a Bitmap16
+         * Object or a DeviceIndependentBitmap (DIB) Object.
+         */
+        BS_PATTERN(0x0003),
+        /**
+         * Not supported
+         */
+        BS_INDEXED(0x0004),
+        /**
+         * A pattern brush specified by a DIB.
+         */
+        BS_DIBPATTERN(0x0005),
+        /**
+         * A pattern brush specified by a DIB.
+         */
+        BS_DIBPATTERNPT(0x0006),
+        /**
+         * Not supported
+         */
+        BS_PATTERN8X8(0x0007),
+        /**
+         * Not supported
+         */
+        BS_DIBPATTERN8X8(0x0008),
+        /**
+         * Not supported
+         */
+        BS_MONOPATTERN(0x0009);
+        
+        int flag;
+        BrushStyle(int flag) {
+            this.flag = flag;
+        }
+        
+        static BrushStyle valueOf(int flag) {
+            for (BrushStyle bs : values()) {
+                if (bs.flag == flag) return bs;
+            }
+            return null;
+        }
+    }
+    
+    BrushStyle style;
+    
+    /**
+     * A 16-bit unsigned integer that defines whether the Colors field of a DIB
+     * Object contains explicit RGB values, or indexes into a palette.
+     * 
+     * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be
+     * used regardless of the contents of this field.
+     * 
+     * If the Style field specified anything but BS_PATTERN, this field MUST be one of the values:
+     * DIB_RGB_COLORS = 0x0000,
+     * DIB_PAL_COLORS = 0x0001,
+     * DIB_PAL_INDICES = 0x0002
+     */
+    int colorUsage;
+    
+    WmfBitmapDib patternDib;
+    WmfBitmap16 pattern16;
+    
+    public WmfRecordType getRecordType() {
+        return WmfRecordType.dibCreatePatternBrush;
+    }
+    
+    public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+        style = BrushStyle.valueOf(leis.readUShort());
+        colorUsage = leis.readUShort();
+        int size = 2*LittleEndianConsts.SHORT_SIZE; 
+        switch (style) {
+        case BS_SOLID:
+        case BS_NULL:
+        case BS_DIBPATTERN:
+        case BS_DIBPATTERNPT:
+        case BS_HATCHED:
+            patternDib = new WmfBitmapDib();
+            size += patternDib.init(leis);
+            break;
+        case BS_PATTERN:
+            pattern16 = new WmfBitmap16();
+            size += pattern16.init(leis);
+            break;
+        case BS_INDEXED:
+        case BS_DIBPATTERN8X8:
+        case BS_MONOPATTERN:
+        case BS_PATTERN8X8:
+            throw new RuntimeException("pattern not supported");
+        }
+        return size;
+    }
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDraw.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDraw.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDraw.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfDraw.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,575 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfDraw {
+    /**
+     * The META_LINETO record draws a line from the drawing position that is defined in the playback
+     * device context up to, but not including, the specified point.
+     */
+    public static class WmfLineTo implements WmfRecord {
+        
+        /**
+         * A 16-bit signed integer that defines the vertical component of the drawing
+         * destination position, in logical units.
+         */
+        int y;
+        
+        /**
+         * A 16-bit signed integer that defines the horizontal component of the drawing
+         * destination position, in logical units.
+         */
+        int x;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.lineTo;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            y = leis.readShort();
+            x = leis.readShort();
+            return 2*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+    
+    /**
+     * The META_POLYGON record paints a polygon consisting of two or more vertices connected by
+     * straight lines. The polygon is outlined by using the pen and filled by using the brush and polygon fill
+     * mode that are defined in the playback device context.
+     */
+    public static class WmfPolygon implements WmfRecord {
+        
+        /**
+         * A 16-bit signed integer that defines the number of points in the array.
+         */
+        int numberofPoints;
+        
+        short xPoints[], yPoints[];
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.polygon;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            numberofPoints = leis.readShort();
+            xPoints = new short[numberofPoints];
+            yPoints = new short[numberofPoints];
+            
+            for (int i=0; i<numberofPoints; i++) {
+                // A 16-bit signed integer that defines the horizontal (x) coordinate of the point.
+                xPoints[i] = leis.readShort();
+                // A 16-bit signed integer that defines the vertical (y) coordinate of the point.
+                yPoints[i] = leis.readShort();
+            }
+            
+            return LittleEndianConsts.SHORT_SIZE+numberofPoints*LittleEndianConsts.INT_SIZE;
+        }
+    }
+    
+    /**
+     * The META_POLYLINE record draws a series of line segments by connecting the points in the
+     * specified array.
+     */
+    public static class WmfPolyline extends WmfPolygon {
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.polyline;
+        }
+    }
+    
+    /**
+     * The META_ELLIPSE record draws an ellipse. The center of the ellipse is the center of the specified
+     * bounding rectangle. The ellipse is outlined by using the pen and is filled by using the brush; these
+     * are defined in the playback device context.
+     */
+    public static class WmfEllipse implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of
+         * the lower-right corner of the bounding rectangle.
+         */
+        int bottomRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the lower-right corner of the bounding rectangle.
+         */
+        int rightRect;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the
+         * upper-left corner of the bounding rectangle.
+         */
+        int topRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the upper-left corner of the bounding rectangle.
+         */
+        int leftRect;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.ellipse;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 4*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+
+    /**
+     * The META_FRAMEREGION record draws a border around a specified region using a specified brush.
+     */
+    public static class WmfFrameRegion implements WmfRecord {
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get
+         * the region to be framed.
+         */
+        int region;  
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get the
+         * Brush to use for filling the region.
+         */
+        int brush;
+        /**
+         * A 16-bit signed integer that defines the height, in logical units, of the
+         * region frame.
+         */
+        int height;
+        /**
+         * A 16-bit signed integer that defines the width, in logical units, of the
+         * region frame.
+         */
+        int width;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.frameRegion;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            region = leis.readUShort();
+            brush = leis.readUShort();
+            height = leis.readShort();
+            width = leis.readShort();
+            return 4*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_POLYPOLYGON record paints a series of closed polygons. Each polygon is outlined by
+     * using the pen and filled by using the brush and polygon fill mode; these are defined in the playback
+     * device context. The polygons drawn by this function can overlap.
+     */
+    public static class WmfPolyPolygon implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer that defines the number of polygons in the object.
+         */
+        int numberOfPolygons;
+        
+        /**
+         * A NumberOfPolygons array of 16-bit unsigned integers that define the number of
+         * points for each polygon in the object.
+         */
+        int pointsPerPolygon[];
+        
+        /**
+         * An array of 16-bit unsigned integers that define the coordinates of the polygons.
+         */
+        int xPoints[][];
+
+        /**
+         * An array of 16-bit unsigned integers that define the coordinates of the polygons.
+         */
+        int yPoints[][];
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.polyPolygon;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            // see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;)
+            numberOfPolygons = leis.readUShort();
+            pointsPerPolygon = new int[numberOfPolygons];
+            xPoints = new int[numberOfPolygons][];
+            yPoints = new int[numberOfPolygons][];
+
+            int size = LittleEndianConsts.SHORT_SIZE;
+            
+            for (int i=0; i<numberOfPolygons; i++) {
+                pointsPerPolygon[i] = leis.readUShort();
+                size += LittleEndianConsts.SHORT_SIZE;
+            }
+            
+            for (int i=0; i<numberOfPolygons; i++) {
+                
+                xPoints[i] = new int[pointsPerPolygon[i]];
+                yPoints[i] = new int[pointsPerPolygon[i]];
+                
+                for (int j=0; j<pointsPerPolygon[i]; j++) {
+                    xPoints[i][j] = leis.readUShort();
+                    yPoints[i][j] = leis.readUShort();
+                    size += 2*LittleEndianConsts.SHORT_SIZE;
+                }
+            }
+            
+            return size;
+        }
+    }
+
+    /**
+     * The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and
+     * filled by using the brush that are defined in the playback device context.
+     */
+    public static class WmfRectangle implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of
+         * the lower-right corner of the rectangle.
+         */
+        int bottomRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the lower-right corner of the rectangle.
+         */
+        int rightRect;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the
+         * upper-left corner of the rectangle.
+         */
+        int topRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the upper-left corner of the rectangle.
+         */
+        int leftRect;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.frameRegion;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 4*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and
+     * filled by using the brush that are defined in the playback device context.
+     */
+    public static class WmfSetPixel implements WmfRecord {
+        /**
+         * A ColorRef Object that defines the color value.
+         */
+        WmfColorRef colorRef; 
+
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point
+         * to be set.
+         */
+        int y;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point
+         * to be set.
+         */
+        int x;
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.setPixel;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            colorRef = new WmfColorRef();
+            int size = colorRef.init(leis);
+            y = leis.readShort();
+            x = leis.readShort();
+            return 2*LittleEndianConsts.SHORT_SIZE+size;
+        }
+    }
+
+    /**
+     * The META_ROUNDRECT record paints a rectangle with rounded corners. The rectangle is outlined
+     * using the pen and filled using the brush, as defined in the playback device context.
+     */
+    public static class WmfRoundRect implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the height, in logical coordinates, of the
+         * ellipse used to draw the rounded corners.
+         */
+        int height;
+        
+        /**
+         * A 16-bit signed integer that defines the width, in logical coordinates, of the
+         * ellipse used to draw the rounded corners.
+         */
+        int width;
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of
+         * the lower-right corner of the rectangle.
+         */
+        int bottomRect;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the lower-right corner of the rectangle.
+         */
+        int rightRect;
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the
+         * upper-left corner of the rectangle.
+         */
+        int topRect;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of
+         * the upper-left corner of the rectangle.
+         */
+        int leftRect;
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.roundRect;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            height = leis.readShort();
+            width = leis.readShort();
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 6*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+    
+
+
+    /**
+     * The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two
+     * radials. The pie is outlined by using the pen and filled by using the brush that are defined in the
+     * playback device context.
+     */
+    public static class WmfPie implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical
+         * coordinates, of the endpoint of the second radial.
+         */
+        int yRadial2;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical
+         * coordinates, of the endpoint of the second radial.
+         */
+        int xRadial2;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical 
+         * coordinates, of the endpoint of the first radial.
+         */
+        int yRadial1;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical 
+         * coordinates, of the endpoint of the first radial.
+         */
+        int xRadial1;  
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int bottomRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int rightRect;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the 
+         * upper-left corner of the bounding rectangle.
+         */
+        int topRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the upper-left corner of the bounding rectangle.
+         */
+        int leftRect;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.pie;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            yRadial2 = leis.readShort();
+            xRadial2 = leis.readShort();
+            yRadial1 = leis.readShort();
+            xRadial1 = leis.readShort();
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 8*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_ARC record draws an elliptical arc.
+     */
+    public static class WmfArc implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of
+         * the ending point of the radial line defining the ending point of the arc.
+         */
+        int yEndArc; 
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the ending point of the radial line defining the ending point of the arc.
+         */
+        int xEndArc; 
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of 
+         * the ending point of the radial line defining the starting point of the arc.
+         */
+        int yStartArc;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the ending point of the radial line defining the starting point of the arc.
+         */
+        int xStartArc;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int bottomRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int rightRect;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the 
+         * upper-left corner of the bounding rectangle.
+         */
+        int topRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the upper-left corner of the bounding rectangle.
+         */
+        int leftRect;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.arc;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            yEndArc = leis.readShort();
+            xEndArc = leis.readShort();
+            yStartArc = leis.readShort();
+            xStartArc = leis.readShort();
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 8*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of
+     * an ellipse with a line segment. The chord is outlined using the pen and filled using the brush
+     * that are defined in the playback device context.
+     */
+    public static class WmfChord implements WmfRecord {
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical 
+         * coordinates, of the endpoint of the second radial.
+         */
+        int yRadial2;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical 
+         * coordinates, of the endpoint of the second radial.
+         */
+        int xRadial2;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical 
+         * coordinates, of the endpoint of the first radial.
+         */
+        int yRadial1;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical 
+         * coordinates, of the endpoint of the first radial.
+         */
+        int xRadial1;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int bottomRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the lower-right corner of the bounding rectangle.
+         */
+        int rightRect;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the 
+         * upper-left corner of the bounding rectangle.
+         */
+        int topRect;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of 
+         * the upper-left corner of the bounding rectangle.
+         */
+        int leftRect;
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.chord;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            yRadial2 = leis.readShort();
+            xRadial2 = leis.readShort();
+            yRadial1 = leis.readShort();
+            xRadial1 = leis.readShort();
+            bottomRect = leis.readShort();
+            rightRect = leis.readShort();
+            topRect = leis.readShort();
+            leftRect = leis.readShort();
+            return 8*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+
+    /**
+     * The META_SELECTOBJECT record specifies a graphics object for the playback device context. The 
+     * new object replaces the previous object of the same type, unless if the previous object is a palette 
+     * object. If the previous object is a palette object, then the META_SELECTPALETTE record must be 
+     * used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not 
+     * support replacing the palette object type.
+     */
+    public static class WmfSelectObject implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to
+         * get the object to be selected.
+         */
+        int objectIndex;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.selectObject;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            objectIndex = leis.readUShort();
+            return LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+ }

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfEscape.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfEscape.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfEscape.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfEscape.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,36 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfEscape implements WmfRecord {
+    
+    /**
+     * A 16-bit unsigned integer that defines the escape function. The 
+     * value MUST be from the MetafileEscapes enumeration.
+     */
+    int escapeFunction;
+    /**
+     * A 16-bit unsigned integer that specifies the size, in bytes, of the 
+     * EscapeData field.
+     */
+    int byteCount;
+    /**
+     * An array of bytes of size ByteCount.
+     */
+    byte escapeData[];
+    
+    public WmfRecordType getRecordType() {
+        return WmfRecordType.escape;
+    }
+    
+    public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+        escapeFunction = leis.readUShort();
+        byteCount = leis.readUShort();
+        escapeData = new byte[byteCount];
+        leis.read(escapeData);
+        return 2*LittleEndianConsts.SHORT_SIZE+byteCount;
+    }
+}

Added: poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfFill.java
URL: http://svn.apache.org/viewvc/poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfFill.java?rev=1566181&view=auto
==============================================================================
--- poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfFill.java (added)
+++ poi/branches/wmf_render/src/scratchpad/src/org/apache/poi/hwmf/record/WmfFill.java Sun Feb  9 01:14:54 2014
@@ -0,0 +1,424 @@
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class WmfFill {
+    /**
+     * The META_FILLREGION record fills a region using a specified brush.
+     */
+    public static class WmfFillRegion implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get
+         * the region to be filled.
+         */
+        int region;
+
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get the
+         * brush to use for filling the region.
+         */
+        int brush;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.fillRegion;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            region = leis.readUShort();
+            brush = leis.readUShort();
+            return 2*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_PAINTREGION record paints the specified region by using the brush that is
+     * defined in the playback device context.
+     */
+    public static class WmfPaintRegion implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get
+         * the region to be painted.
+         */
+        int region;
+
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.paintRegion;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            region = leis.readUShort();
+            return LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+    
+    
+    /**
+     * The META_FLOODFILL record fills an area of the output surface with the brush that
+     * is defined in the playback device context.
+     */
+    public static class WmfFloodFill implements WmfRecord {
+        
+        /**
+         * A 32-bit ColorRef Object that defines the color value.
+         */
+        WmfColorRef colorRef;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the
+         * point where filling is to start.
+         */
+        int yStart;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the
+         * point where filling is to start.
+         */
+        int xStart;
+        
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.floodFill;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            colorRef = new WmfColorRef();
+            int size = colorRef.init(leis);
+            yStart = leis.readShort();
+            xStart = leis.readShort();
+            return size+2*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_SETPOLYFILLMODE record sets polygon fill mode in the playback device context for
+     * graphics operations that fill polygons.
+     */
+    public static class WmfSetPolyfillMode implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer that defines polygon fill mode.
+         * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002
+         */
+        int polyFillMode;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.setPolyFillMode;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            polyFillMode = leis.readUShort();
+            return LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+
+    /**
+     * The META_EXTFLOODFILL record fills an area with the brush that is defined in
+     * the playback device context.
+     */
+    public static class WmfExtFloodFill implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer that defines the fill operation to be performed. This
+         * member MUST be one of the values in the FloodFill Enumeration table:
+         * 
+         * FLOODFILLBORDER = 0x0000:
+         * The fill area is bounded by the color specified by the Color member.
+         * This style is identical to the filling performed by the META_FLOODFILL record.
+         * 
+         * FLOODFILLSURFACE = 0x0001:
+         * The fill area is bounded by the color that is specified by the Color member.
+         * Filling continues outward in all directions as long as the color is encountered.
+         * This style is useful for filling areas with multicolored boundaries.
+         */
+        int mode;
+        
+        /**
+         * A 32-bit ColorRef Object that defines the color value.
+         */
+        WmfColorRef colorRef;
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point
+         * to be set.
+         */
+        int y;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point
+         * to be set.
+         */
+        int x;  
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.extFloodFill;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            mode = leis.readUShort();
+            colorRef = new WmfColorRef();
+            int size = colorRef.init(leis);
+            y = leis.readShort();
+            x = leis.readShort();
+            return size+3*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    /**
+     * The META_INVERTREGION record draws a region in which the colors are inverted.
+     */
+    public static class WmfInvertRegion implements WmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to get
+         * the region to be inverted.
+         */
+        int region;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.invertRegion;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            region = leis.readUShort();
+            return LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+    
+
+    /**
+     * The META_PATBLT record paints a specified rectangle using the brush that is defined in the playback
+     * device context. The brush color and the surface color or colors are combined using the specified
+     * raster operation.
+     */
+    public static class WmfPatBlt implements WmfRecord {
+        
+        /**
+         * A 32-bit unsigned integer that defines the raster operation code.
+         * This code MUST be one of the values in the Ternary Raster Operation enumeration table.
+         */
+        WmfTernaryRasterOp rasterOperation;
+        
+        /**
+         * A 16-bit signed integer that defines the height, in logical units, of the rectangle.
+         */
+        int height;
+        
+        /**
+         * A 16-bit signed integer that defines the width, in logical units, of the rectangle.
+         */
+        int width;
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the
+         * upper-left corner of the rectangle to be filled.
+         */
+        int yLeft;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the
+         * upper-left corner of the rectangle to be filled.
+         */
+        int xLeft;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.patBlt;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            int rasterOpIndex = leis.readUShort();
+            int rasterOpCode = leis.readUShort();
+
+            rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
+            assert(rasterOpCode == rasterOperation.opCode);
+            
+            height = leis.readShort();
+            width = leis.readShort();
+            yLeft = leis.readShort();
+            xLeft = leis.readShort();
+
+            return 6*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+
+    public static class WmfStretchBlt implements WmfRecord {
+        /**
+         */
+        
+        /**
+         * A 32-bit unsigned integer that defines how the source pixels, the current brush
+         * in the playback device context, and the destination pixels are to be combined to form the new 
+         * image. This code MUST be one of the values in the Ternary Raster Operation Enumeration
+         */
+        WmfTernaryRasterOp rasterOperation;
+        
+        /**
+         * A 16-bit signed integer that defines the height, in logical units, of the source rectangle.
+         */
+        int srcHeight; 
+        /**
+         * A 16-bit signed integer that defines the width, in logical units, of the source rectangle.
+         */
+        int srcWidth; 
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner 
+         * of the source rectangle.
+         */
+        int ySrc;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner 
+         * of the source rectangle.
+         */
+        int xSrc;
+        /**
+         * A 16-bit signed integer that defines the height, in logical units, of the destination rectangle.
+         */
+        int destHeight;
+        /**
+         * A 16-bit signed integer that defines the width, in logical units, of the destination rectangle.
+         */
+        int destWidth;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left 
+         * corner of the destination rectangle.
+         */
+        int yDest;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left 
+         * corner of the destination rectangle.
+         */
+        int xDest;
+        
+        /**
+         * A variable-sized Bitmap16 Object that defines source image content.
+         * This object MUST be specified, even if the raster operation does not require a source.
+         */
+        WmfBitmap16 target;
+        
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.stretchBlt;
+        }
+        
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));
+
+            int size = 0;
+            int rasterOpIndex = leis.readUShort();
+            int rasterOpCode = leis.readUShort();
+            
+            rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
+            assert(rasterOpCode == rasterOperation.opCode);
+
+            srcHeight = leis.readShort();
+            srcWidth = leis.readShort();
+            ySrc = leis.readShort();
+            xSrc = leis.readShort();
+            size = 6*LittleEndianConsts.SHORT_SIZE;
+            if (!hasBitmap) {
+                @SuppressWarnings("unused")
+                int reserved = leis.readShort();
+                size += LittleEndianConsts.SHORT_SIZE;
+            }
+            destHeight = leis.readShort();
+            destWidth = leis.readShort();
+            yDest = leis.readShort();
+            xDest = leis.readShort();
+            size += 4*LittleEndianConsts.SHORT_SIZE;
+            if (hasBitmap) {
+                target = new WmfBitmap16();
+                size += target.init(leis);
+            }
+            
+            return size;
+        }
+    }
+
+    public static class WmfBitBlt implements WmfRecord {
+
+        /**
+         * A 32-bit unsigned integer that defines how the source pixels, the current brush in the playback 
+         * device context, and the destination pixels are to be combined to form the new image.
+         */
+        WmfTernaryRasterOp rasterOperation;
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner 
+        of the source rectangle.
+         */
+        int ySrc; 
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner 
+        of the source rectangle.
+         */
+        int xSrc; 
+        /**
+         * A 16-bit signed integer that defines the height, in logical units, of the source and 
+        destination rectangles.
+         */
+        int height;
+        /**
+         * A 16-bit signed integer that defines the width, in logical units, of the source and destination 
+        rectangles.
+         */
+        int width;
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left 
+        corner of the destination rectangle.
+         */
+        int yDest;
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left 
+        corner of the destination rectangle.
+         */
+        int xDest;
+        
+        /**
+         * A variable-sized Bitmap16 Object that defines source image content.
+         * This object MUST be specified, even if the raster operation does not require a source.
+         */
+        WmfBitmap16 target;
+
+        public WmfRecordType getRecordType() {
+            return WmfRecordType.bitBlt;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));
+
+            int size = 0;
+            int rasterOpIndex = leis.readUShort();
+            int rasterOpCode = leis.readUShort();
+            
+            rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
+            assert(rasterOpCode == rasterOperation.opCode);
+
+            ySrc = leis.readShort();
+            xSrc = leis.readShort();
+
+            size = 4*LittleEndianConsts.SHORT_SIZE;
+            
+            if (!hasBitmap) {
+                @SuppressWarnings("unused")
+                int reserved = leis.readShort();
+                size += LittleEndianConsts.SHORT_SIZE;
+            }
+            
+            height = leis.readShort();
+            width = leis.readShort();
+            yDest = leis.readShort();
+            xDest = leis.readShort();
+
+            size += 4*LittleEndianConsts.SHORT_SIZE;
+            if (hasBitmap) {
+                target = new WmfBitmap16();
+                size += target.init(leis);
+            }
+            
+            return size;
+        }
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org