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 2015/12/21 02:26:39 UTC

svn commit: r1721078 [1/3] - in /poi/trunk/src/scratchpad: src/org/apache/poi/hwmf/ src/org/apache/poi/hwmf/record/ src/org/apache/poi/hwmf/usermodel/ testcases/org/apache/poi/hwmf/

Author: kiwiwings
Date: Mon Dec 21 01:26:39 2015
New Revision: 1721078

URL: http://svn.apache.org/viewvc?rev=1721078&view=rev
Log:
#56004 - Support for WMF rendering (parsing the WMF records)

Added:
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHeader.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPlaceableHeader.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecord.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecordType.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/usermodel/
    poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hwmf/
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,105 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hwmf.record;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class HwmfBitmap16 {
+    final boolean isPartial;
+    int type;
+    int width;
+    int height;
+    int widthBytes;
+    int planes;
+    int bitsPixel;
+    
+    public HwmfBitmap16() {
+        this(false);
+    }
+    
+    public HwmfBitmap16(boolean isPartial) {
+        this.isPartial = isPartial;
+    }
+    
+    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();
+
+        int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE;
+        if (isPartial) {
+            // Bits (4 bytes): This field MUST be ignored.
+            long skipSize = leis.skip(LittleEndianConsts.INT_SIZE);
+            assert(skipSize == LittleEndianConsts.INT_SIZE);
+            // Reserved (18 bytes): This field MUST be ignored.
+            skipSize = leis.skip(18);
+            assert(skipSize == 18);
+            size += 18+LittleEndianConsts.INT_SIZE;
+        }
+        
+        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+        
+        int size2 = 0;
+        byte buf[] = new byte[widthBytes];
+        for (int h=0; h<height; h++) {
+            leis.read(buf);
+            size2 += widthBytes;
+
+            ImageInputStream iis = new MemoryCacheImageInputStream(new ByteArrayInputStream(buf));
+
+            for (int w=0; w<width; w++) {
+                long bitsAtPixel = iis.readBits(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/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,441 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+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 HwmfBitmapDib {
+    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/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,80 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hwmf.record;
+
+/**
+ * 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 enum HwmfBrushStyle {
+    /**
+     * 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;
+    HwmfBrushStyle(int flag) {
+        this.flag = flag;
+    }
+
+    static HwmfBrushStyle valueOf(int flag) {
+        for (HwmfBrushStyle bs : values()) {
+            if (bs.flag == flag) return bs;
+        }
+        return null;
+    }
+}

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,47 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+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 HwmfColorRef {
+    /**
+     * 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/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,619 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class HwmfDraw {
+    /**
+     * The META_MOVETO record sets the output position in the playback device context to a specified
+     * point.
+     */
+    public static class WmfMoveTo implements HwmfRecord {
+        
+        /**
+         * A 16-bit signed integer that defines the y-coordinate, in logical units.
+         */
+        int y;
+        
+        /**
+         * A 16-bit signed integer that defines the x-coordinate, in logical units.
+         */
+        int x;
+        
+        public HwmfRecordType getRecordType() {
+            return HwmfRecordType.moveTo;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            y = leis.readShort();
+            x = leis.readShort();
+            return 2*LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+    
+    /**
+     * 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 HwmfRecord {
+        
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        
+        /**
+         * A 16-bit signed integer that defines the number of points in the array.
+         */
+        int numberofPoints;
+        
+        short xPoints[], yPoints[];
+        
+        public HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * A ColorRef Object that defines the color value.
+         */
+        HwmfColorRef 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.setPixel;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            colorRef = new HwmfColorRef();
+            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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        /**
+         * 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 HwmfRecordType getRecordType() {
+            return HwmfRecordType.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 HwmfRecord {
+        
+        /**
+         * A 16-bit unsigned integer used to index into the WMF Object Table to
+         * get the object to be selected.
+         */
+        int objectIndex;
+        
+        public HwmfRecordType getRecordType() {
+            return HwmfRecordType.selectObject;
+        }
+        
+        public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
+            objectIndex = leis.readUShort();
+            return LittleEndianConsts.SHORT_SIZE;
+        }
+    }
+ }

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java?rev=1721078&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java Mon Dec 21 01:26:39 2015
@@ -0,0 +1,53 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hwmf.record;
+
+import java.io.IOException;
+
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class HwmfEscape implements HwmfRecord {
+    
+    /**
+     * 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 HwmfRecordType getRecordType() {
+        return HwmfRecordType.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;
+    }
+}



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