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