*
* @param data
* the byte array
- * @return the double (64-bit) value
+ * @return the float (32-bit) value
*/
public static float getFloat( byte[] data )
{
* 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 )
{
* @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();
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");
+ }
}
}
--- /dev/null
+package org.apache.poi.hwmf;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import org.apache.poi.hwmf.record.WmfHeader;\r
+import org.apache.poi.hwmf.record.WmfPlaceableHeader;\r
+import org.apache.poi.hwmf.record.WmfRecord;\r
+import org.apache.poi.hwmf.record.WmfRecordType;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class HwmfPicture {\r
+ // http://www.symantec.com/avcenter/reference/inside.the.windows.meta.file.format.pdf\r
+ \r
+ public HwmfPicture(InputStream inputStream) throws IOException {\r
+ LittleEndianInputStream leis = new LittleEndianInputStream(inputStream);\r
+ WmfPlaceableHeader placeableHeader = WmfPlaceableHeader.readHeader(leis);\r
+ WmfHeader header = new WmfHeader(leis);\r
+ \r
+ for (;;) {\r
+ long recordSize = leis.readUInt();\r
+ int recordFunction = leis.readShort();\r
+ WmfRecordType wrt = WmfRecordType.getById(recordFunction);\r
+ if (wrt == null) {\r
+ throw new IOException("unexpected record type: "+recordFunction);\r
+ }\r
+ if (wrt == WmfRecordType.eof) break;\r
+ if (wrt.clazz == null) {\r
+ throw new IOException("unsupported record type: "+recordFunction);\r
+ }\r
+ \r
+ WmfRecord wr;\r
+ try {\r
+ wr = wrt.clazz.newInstance();\r
+ } catch (Exception e) {\r
+ throw (IOException)new IOException("can't create wmf record").initCause(e);\r
+ }\r
+ \r
+ int consumedSize = wr.init(leis, recordSize, recordFunction);\r
+ if (consumedSize < recordSize) {\r
+ leis.skip(recordSize - consumedSize);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+/**\r
+ * Taken from https://code.google.com/p/javasupport/source/browse/branches/java-examples/src/main/java/deng/huffman/dukehuff/test/BitInputStream.java?r=587\r
+ * \r
+ * reads bits-at-a-time where the number of bits is between 1 and 32.\r
+ * Updated for version 2.0 to extend java.io.InputStream\r
+ * <P>\r
+ * @author Owen Astrachan\r
+ * @version 1.0, July 2000\r
+ * @version 2.0, October 2004\r
+ */\r
+\r
+public class BitInputStream extends InputStream\r
+{\r
+ private InputStream myInput;\r
+ private int myBitCount;\r
+ private int myBuffer;\r
+ private File myFile;\r
+ \r
+ private static final int bmask[] = {\r
+ 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,\r
+ 0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,\r
+ 0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,\r
+ 0x7fffff,0xffffff,0x1ffffff,0x3ffffff,0x7ffffff,\r
+ 0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff\r
+ };\r
+\r
+ private static final int BITS_PER_BYTE = 8;\r
+ /**\r
+ * Construct a bit-at-a-time input stream from a file\r
+ */\r
+ public BitInputStream(String filename)\r
+ {\r
+ this(new File(filename));\r
+ }\r
+ \r
+ /**\r
+ * Construct a bit-at-a-time input stream from <code>file</code>\r
+ * @param file is the File that is the source of the input\r
+ */\r
+ public BitInputStream(File file)\r
+ {\r
+ myFile = file; \r
+ try {\r
+ reset();\r
+ } catch (IOException e) {\r
+ // eat the exception\r
+ }\r
+ \r
+ }\r
+ \r
+ public BitInputStream(InputStream in){\r
+ myInput = in;\r
+ myFile = null;\r
+ }\r
+ \r
+ /**\r
+ * This is a reset-able stream, so return true.\r
+ * @return true\r
+ */\r
+ public boolean markSupported(){\r
+ return myFile != null;\r
+ }\r
+\r
+ /**\r
+ * reset stream to beginning. The implementation creates a new\r
+ * stream.\r
+ * @throws IOException\r
+ */\r
+ \r
+ public void reset() throws IOException\r
+ {\r
+ if (! markSupported()){\r
+ throw new IOException("not resettable");\r
+ }\r
+ try{\r
+ close();\r
+ myInput = new BufferedInputStream(new FileInputStream(myFile));\r
+ }\r
+ catch (FileNotFoundException fnf){\r
+ System.err.println("error opening " + myFile.getName() + " " + fnf);\r
+ }\r
+ myBuffer = myBitCount = 0;\r
+ } \r
+\r
+ /**\r
+ * closes the input stream\r
+ */\r
+ \r
+ public void close()\r
+ {\r
+ try{\r
+ if (myInput != null) {\r
+ myInput.close();\r
+ }\r
+ }\r
+ catch (java.io.IOException ioe){\r
+ System.err.println("error closing bit stream " + ioe);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * returns the number of bits requested as rightmost bits in\r
+ * returned value, returns -1 if not enough bits available to\r
+ * satisfy the request\r
+ *\r
+ * @param howManyBits is the number of bits to read and return\r
+ * @return the value read, only rightmost <code>howManyBits</code>\r
+ * are valid, returns -1 if not enough bits left\r
+ */\r
+\r
+ public int read(int howManyBits) throws IOException\r
+ {\r
+ int retval = 0;\r
+ if (myInput == null){\r
+ return -1;\r
+ }\r
+ \r
+ while (howManyBits > myBitCount){\r
+ retval |= ( myBuffer << (howManyBits - myBitCount) );\r
+ howManyBits -= myBitCount;\r
+ try{\r
+ if ( (myBuffer = myInput.read()) == -1) {\r
+ return -1;\r
+ }\r
+ }\r
+ catch (IOException ioe) {\r
+ throw new IOException("bitreading trouble "+ioe);\r
+ }\r
+ myBitCount = BITS_PER_BYTE;\r
+ }\r
+\r
+ if (howManyBits > 0){\r
+ retval |= myBuffer >> (myBitCount - howManyBits);\r
+ myBuffer &= bmask[myBitCount - howManyBits];\r
+ myBitCount -= howManyBits;\r
+ }\r
+ return retval;\r
+ }\r
+\r
+ /**\r
+ * Required by classes extending InputStream, returns\r
+ * the next byte from this stream as an int value.\r
+ * @return the next byte from this stream\r
+ */\r
+ public int read() throws IOException {\r
+ return read(8);\r
+ }\r
+}\r
+\r
+\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfBitmap {\r
+\r
+ /**\r
+ * The META_SETDIBTODEV record sets a block of pixels in the playback device context\r
+ * using deviceindependent color data.\r
+ * The source of the color data is a DIB\r
+ */\r
+ public static class WmfSetDibToDev implements WmfRecord {\r
+\r
+ /**\r
+ * A 16-bit unsigned integer that defines whether the Colors field of the\r
+ * DIB contains explicit RGB values or indexes into a palette.\r
+ * This MUST be one of the values in the ColorUsage Enumeration:\r
+ * DIB_RGB_COLORS = 0x0000,\r
+ * DIB_PAL_COLORS = 0x0001,\r
+ * DIB_PAL_INDICES = 0x0002\r
+ */\r
+ int colorUsage; \r
+ /**\r
+ * A 16-bit unsigned integer that defines the number of scan lines in the source.\r
+ */\r
+ int scanCount;\r
+ /**\r
+ * A 16-bit unsigned integer that defines the starting scan line in the source.\r
+ */\r
+ int startScan; \r
+ /**\r
+ * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the\r
+ * source rectangle.\r
+ */\r
+ int yDib; \r
+ /**\r
+ * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the\r
+ * source rectangle.\r
+ */\r
+ int xDib; \r
+ /**\r
+ * A 16-bit unsigned integer that defines the height, in logical units, of the\r
+ * source and destination rectangles.\r
+ */\r
+ int height;\r
+ /**\r
+ * A 16-bit unsigned integer that defines the width, in logical units, of the\r
+ * source and destination rectangles.\r
+ */\r
+ int width;\r
+ /**\r
+ * A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the destination rectangle.\r
+ */\r
+ int yDest;\r
+ /**\r
+ * A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the\r
+ * upper-left corner of the destination rectangle.\r
+ */\r
+ int xDest;\r
+ /**\r
+ * A variable-sized DeviceIndependentBitmap Object that is the source of the color data.\r
+ */\r
+ WmfBitmapDib dib; \r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setDibToDev;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ colorUsage = leis.readUShort();\r
+ scanCount = leis.readUShort();\r
+ startScan = leis.readUShort();\r
+ yDib = leis.readUShort();\r
+ xDib = leis.readUShort();\r
+ height = leis.readUShort();\r
+ width = leis.readUShort();\r
+ yDest = leis.readUShort();\r
+ xDest = leis.readUShort();\r
+ \r
+ int size = 9*LittleEndianConsts.SHORT_SIZE;\r
+ dib = new WmfBitmapDib();\r
+ size += dib.init(leis);\r
+ \r
+ return size;\r
+ } \r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfBitmap16 {\r
+ int type;\r
+ int width;\r
+ int height;\r
+ int widthBytes;\r
+ int planes;\r
+ int bitsPixel;\r
+ \r
+ public int init(LittleEndianInputStream leis) throws IOException {\r
+ // A 16-bit signed integer that defines the bitmap type.\r
+ type = leis.readShort();\r
+ \r
+ // A 16-bit signed integer that defines the width of the bitmap in pixels.\r
+ width = leis.readShort();\r
+ \r
+ // A 16-bit signed integer that defines the height of the bitmap in scan lines.\r
+ height = leis.readShort();\r
+ \r
+ // A 16-bit signed integer that defines the number of bytes per scan line.\r
+ widthBytes = leis.readShort();\r
+ \r
+ // An 8-bit unsigned integer that defines the number of color planes in the \r
+ // bitmap. The value of this field MUST be 0x01.\r
+ planes = leis.readUByte();\r
+ \r
+ // An 8-bit unsigned integer that defines the number of adjacent color bits on \r
+ // each plane.\r
+ bitsPixel = leis.readUByte();\r
+ \r
+ BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
+ int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ int size2 = 0;\r
+ byte buf[] = new byte[widthBytes];\r
+ for (int h=0; h<height; h++) {\r
+ leis.read(buf);\r
+ size2 += widthBytes;\r
+\r
+ BitInputStream bis = new BitInputStream(new ByteArrayInputStream(buf));\r
+ for (int w=0; w<width; w++) {\r
+ int bitsAtPixel = bis.read(bitsPixel);\r
+ // TODO: is bitsPixel a multiple of 3 (r,g,b)\r
+ // which colortable should be used for the various bit sizes???\r
+ \r
+ }\r
+ }\r
+ \r
+ int bytes = (((width * bitsPixel + 15) >> 4) << 1) * height;\r
+ assert (bytes == size2);\r
+\r
+ size += size2;\r
+ \r
+ \r
+ return size;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.awt.Color;\r
+import java.awt.image.BufferedImage;\r
+import java.awt.image.IndexColorModel;\r
+import java.awt.image.WritableRaster;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The DeviceIndependentBitmap Object defines an image in device-independent bitmap (DIB) format.\r
+ */\r
+public class WmfBitmapDib {\r
+ public static enum BitCount {\r
+ /**\r
+ * The image SHOULD be in either JPEG or PNG format. <6> Neither of these formats includes\r
+ * a color table, so this value specifies that no color table is present. See [JFIF] and [RFC2083]\r
+ * for more information concerning JPEG and PNG compression formats.\r
+ */\r
+ BI_BITCOUNT_0(0x0000),\r
+ /**\r
+ * Each pixel in the bitmap is represented by a single bit. If the bit is clear, the pixel is displayed\r
+ * with the color of the first entry in the color table; if the bit is set, the pixel has the color of the\r
+ * second entry in the table.\r
+ */\r
+ BI_BITCOUNT_1(0x0001),\r
+ /**\r
+ * Each pixel in the bitmap is represented by a 4-bit index into the color table, and each byte\r
+ * contains 2 pixels.\r
+ */\r
+ BI_BITCOUNT_2(0x0004),\r
+ /**\r
+ * Each pixel in the bitmap is represented by an 8-bit index into the color table, and each byte\r
+ * contains 1 pixel.\r
+ */\r
+ BI_BITCOUNT_3(0x0008),\r
+ /**\r
+ * Each pixel in the bitmap is represented by a 16-bit value.\r
+ * <br/>\r
+ * If the Compression field of the BitmapInfoHeader Object is BI_RGB, the Colors field of DIB\r
+ * is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of \r
+ * red, green, and blue are represented with 5 bits for each color component. The value for blue \r
+ * is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant \r
+ * bit is not used. The color table is used for optimizing colors on palette-based devices, and \r
+ * contains the number of entries specified by the ColorUsed field of the BitmapInfoHeader \r
+ * Object.\r
+ * <br/>\r
+ * If the Compression field of the BitmapInfoHeader Object is BI_BITFIELDS, the Colors field \r
+ * contains three DWORD color masks that specify the red, green, and blue components,\r
+ * respectively, of each pixel. Each WORD in the bitmap array represents a single pixel.\r
+ * <br/>\r
+ * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask MUST be \r
+ * contiguous and SHOULD NOT overlap the bits of another mask.\r
+ */\r
+ BI_BITCOUNT_4(0x0010),\r
+ /**\r
+ * The bitmap has a maximum of 2^24 colors, and the Colors field of DIB is \r
+ * NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, \r
+ * and red, respectively, for a pixel. The Colors color table is used for optimizing colors used on \r
+ * palette-based devices, and MUST contain the number of entries specified by the ColorUsed\r
+ * field of the BitmapInfoHeader Object.\r
+ */\r
+ BI_BITCOUNT_5(0x0018),\r
+ /**\r
+ * The bitmap has a maximum of 2^24 colors.\r
+ * <br/>\r
+ * If the Compression field of the BitmapInfoHeader Object is set to BI_RGB, the Colors field \r
+ * of DIB is set to NULL. Each DWORD in the bitmap array represents the relative intensities of \r
+ * blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. The \r
+ * Colors color table is used for optimizing colors used on palette-based devices, and MUST \r
+ * contain the number of entries specified by the ColorUsed field of the BitmapInfoHeader \r
+ * Object.\r
+ * <br/>\r
+ * If the Compression field of the BitmapInfoHeader Object is set to BI_BITFIELDS, the Colors\r
+ * field contains three DWORD color masks that specify the red, green, and blue components, \r
+ * respectively, of each pixel. Each DWORD in the bitmap array represents a single pixel.\r
+ * <br/>\r
+ * When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask must be \r
+ * contiguous and should not overlap the bits of another mask. All the bits in the pixel do not \r
+ * need to be used.\r
+ */\r
+ BI_BITCOUNT_6(0x0020);\r
+ \r
+ int flag;\r
+ BitCount(int flag) {\r
+ this.flag = flag;\r
+ }\r
+ static BitCount valueOf(int flag) {\r
+ for (BitCount bc : values()) {\r
+ if (bc.flag == flag) return bc;\r
+ }\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public static enum Compression {\r
+ /**\r
+ * The bitmap is in uncompressed red green blue (RGB) format that is not compressed\r
+ * and does not use color masks.\r
+ */\r
+ BI_RGB(0x0000),\r
+ /**\r
+ * An RGB format that uses run-length encoding (RLE) compression for bitmaps\r
+ * with 8 bits per pixel. The compression uses a 2-byte format consisting of a count byte\r
+ * followed by a byte containing a color index.\r
+ */\r
+ BI_RLE8(0x0001),\r
+ /**\r
+ * An RGB format that uses RLE compression for bitmaps with 4 bits per pixel. The\r
+ * compression uses a 2-byte format consisting of a count byte followed by two word-length\r
+ * color indexes.\r
+ */\r
+ BI_RLE4(0x0002),\r
+ /**\r
+ * The bitmap is not compressed and the color table consists of three DWORD\r
+ * color masks that specify the red, green, and blue components, respectively, of each pixel.\r
+ * This is valid when used with 16 and 32-bits per pixel bitmaps.\r
+ */\r
+ BI_BITFIELDS(0x0003),\r
+ /**\r
+ * The image is a JPEG image, as specified in [JFIF]. This value SHOULD only be used in \r
+ * certain bitmap operations, such as JPEG pass-through. The application MUST query for the \r
+ * pass-through support, since not all devices support JPEG pass-through. Using non-RGB \r
+ * bitmaps MAY limit the portability of the metafile to other devices. For instance, display device \r
+ * contexts generally do not support this pass-through.\r
+ */\r
+ BI_JPEG(0x0004),\r
+ /**\r
+ * The image is a PNG image, as specified in [RFC2083]. This value SHOULD only be \r
+ * used certain bitmap operations, such as JPEG/PNG pass-through. The application MUST query \r
+ * for the pass-through support, because not all devices support JPEG/PNG pass-through. Using \r
+ * non-RGB bitmaps MAY limit the portability of the metafile to other devices. For instance, \r
+ * display device contexts generally do not support this pass-through.\r
+ */\r
+ BI_PNG(0x0005),\r
+ /**\r
+ * The image is an uncompressed CMYK format.\r
+ */\r
+ BI_CMYK(0x000B),\r
+ /**\r
+ * A CMYK format that uses RLE compression for bitmaps with 8 bits per pixel.\r
+ * The compression uses a 2-byte format consisting of a count byte followed by a byte containing\r
+ * a color index.\r
+ */\r
+ BI_CMYKRLE8(0x000C),\r
+ /**\r
+ * A CMYK format that uses RLE compression for bitmaps with 4 bits per pixel.\r
+ * The compression uses a 2-byte format consisting of a count byte followed by two word-length\r
+ * color indexes.\r
+ */\r
+ BI_CMYKRLE4(0x000D);\r
+ \r
+ int flag;\r
+ Compression(int flag) {\r
+ this.flag = flag;\r
+ }\r
+ static Compression valueOf(int flag) {\r
+ for (Compression c : values()) {\r
+ if (c.flag == flag) return c;\r
+ }\r
+ return null;\r
+ } \r
+ }\r
+ \r
+ \r
+ int headerSize;\r
+ int headerWidth;\r
+ int headerHeight;\r
+ int headerPlanes;\r
+ BitCount headerBitCount;\r
+ Compression headerCompression;\r
+ long headerImageSize = -1;\r
+ int headerXPelsPerMeter = -1;\r
+ int headerYPelsPerMeter = -1;\r
+ long headerColorUsed = -1;\r
+ long headerColorImportant = -1;\r
+ \r
+ Color colorTable[];\r
+ int colorMaskRed=0,colorMaskGreen=0,colorMaskBlue=0;\r
+ \r
+ public int init(LittleEndianInputStream leis) throws IOException {\r
+ int size = 0;\r
+ size += readHeader(leis);\r
+ size += readColors(leis);\r
+ int size2;\r
+ switch (headerBitCount) {\r
+ default:\r
+ case BI_BITCOUNT_0:\r
+ throw new RuntimeException("JPG and PNG formats aren't supported yet.");\r
+ case BI_BITCOUNT_1:\r
+ case BI_BITCOUNT_2:\r
+ case BI_BITCOUNT_3:\r
+ size2 = readBitmapIndexed(leis);\r
+ break;\r
+ case BI_BITCOUNT_4:\r
+ case BI_BITCOUNT_5:\r
+ case BI_BITCOUNT_6:\r
+ size2 = readBitmapDirect(leis);\r
+ break;\r
+ }\r
+ \r
+ assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == size2);\r
+ assert ( headerSize == 0x0C || headerImageSize == size2 );\r
+ \r
+ size += size2;\r
+ \r
+ return size;\r
+ }\r
+\r
+ protected int readHeader(LittleEndianInputStream leis) throws IOException {\r
+ int size = 0;\r
+ \r
+ /**\r
+ * DIBHeaderInfo (variable): Either a BitmapCoreHeader Object or a\r
+ * BitmapInfoHeader Object that specifies information about the image.\r
+ * \r
+ * The first 32 bits of this field is the HeaderSize value.\r
+ * If it is 0x0000000C, then this is a BitmapCoreHeader; otherwise, this is a BitmapInfoHeader.\r
+ */\r
+ headerSize = leis.readInt();\r
+ size += LittleEndianConsts.INT_SIZE;\r
+ \r
+ // BitmapCoreHeader\r
+ // A 16-bit unsigned integer that defines the width of the DIB, in pixels.\r
+ headerWidth = leis.readUShort();\r
+ // A 16-bit unsigned integer that defines the height of the DIB, in pixels.\r
+ headerHeight = leis.readUShort();\r
+ // A 16-bit unsigned integer that defines the number of planes for the target\r
+ // device. This value MUST be 0x0001.\r
+ headerPlanes = leis.readUShort();\r
+ // A 16-bit unsigned integer that defines the format of each pixel, and the\r
+ // maximum number of colors in the DIB.\r
+ headerBitCount = BitCount.valueOf(leis.readUShort());\r
+ size += 4*LittleEndianConsts.SHORT_SIZE;\r
+\r
+ if (headerSize > 0x0C) {\r
+ // BitmapInfoHeader\r
+ // A 32-bit unsigned integer that defines the compression mode of the \r
+ // DIB. \r
+ // This value MUST NOT specify a compressed format if the DIB is a top-down bitmap,\r
+ // as indicated by the Height value.\r
+ headerCompression = Compression.valueOf((int)leis.readUInt());\r
+ // A 32-bit unsigned integer that defines the size, in bytes, of the image.\r
+ // If the Compression value is BI_RGB, this value SHOULD be zero and MUST be ignored.\r
+ // If the Compression value is BI_JPEG or BI_PNG, this value MUST specify the size of the JPEG \r
+ // or PNG image buffer, respectively.\r
+ headerImageSize = leis.readUInt();\r
+ // A 32-bit signed integer that defines the horizontal resolution, \r
+ // in pixels-per-meter, of the target device for the DIB.\r
+ headerXPelsPerMeter = leis.readInt();\r
+ // A 32-bit signed integer that defines the vertical resolution,\r
+ headerYPelsPerMeter = leis.readInt();\r
+ // A 32-bit unsigned integer that specifies the number of indexes in the\r
+ // color table used by the DIB\r
+ // in pixelsper-meter, of the target device for the DIB.\r
+ headerColorUsed = leis.readUInt();\r
+ // A 32-bit unsigned integer that defines the number of color indexes that are\r
+ // required for displaying the DIB. If this value is zero, all color indexes are required.\r
+ headerColorImportant = leis.readUInt();\r
+ size += 6*LittleEndianConsts.INT_SIZE;\r
+ }\r
+ return size;\r
+ }\r
+\r
+ protected int readColors(LittleEndianInputStream leis) throws IOException {\r
+ switch (headerBitCount) {\r
+ default:\r
+ case BI_BITCOUNT_0:\r
+ // no table\r
+ return 0;\r
+ case BI_BITCOUNT_1:\r
+ // 2 colors\r
+ return readRGBQuad(leis, 2);\r
+ case BI_BITCOUNT_2:\r
+ // 16 colors\r
+ return readRGBQuad(leis, 16);\r
+ case BI_BITCOUNT_3:\r
+ // 256 colors\r
+ return readRGBQuad(leis, 256);\r
+ case BI_BITCOUNT_5:\r
+ colorMaskRed=0xFF;\r
+ colorMaskGreen=0xFF;\r
+ colorMaskBlue=0xFF;\r
+ return 0;\r
+ case BI_BITCOUNT_4:\r
+ if (headerCompression == Compression.BI_RGB) {\r
+ colorMaskBlue = 0x1F;\r
+ colorMaskGreen = 0x1F<<5;\r
+ colorMaskRed = 0x1F<<10;\r
+ return 0;\r
+ } else {\r
+ assert(headerCompression == Compression.BI_BITFIELDS);\r
+ colorMaskBlue = leis.readInt();\r
+ colorMaskGreen = leis.readInt();\r
+ colorMaskRed = leis.readInt();\r
+ return 3*LittleEndianConsts.INT_SIZE;\r
+ }\r
+ case BI_BITCOUNT_6: \r
+ if (headerCompression == Compression.BI_RGB) {\r
+ colorMaskBlue = colorMaskGreen = colorMaskRed = 0xFF;\r
+ return 0;\r
+ } else {\r
+ assert(headerCompression == Compression.BI_BITFIELDS);\r
+ colorMaskBlue = leis.readInt();\r
+ colorMaskGreen = leis.readInt();\r
+ colorMaskRed = leis.readInt();\r
+ return 3*LittleEndianConsts.INT_SIZE;\r
+ }\r
+ }\r
+ }\r
+ \r
+ protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException {\r
+ int size = 0;\r
+ List<Color> colorList = new ArrayList<Color>();\r
+ for (int i=0; i<count; i++) {\r
+ int blue = leis.readUByte();\r
+ int green = leis.readUByte();\r
+ int red = leis.readUByte();\r
+ @SuppressWarnings("unused")\r
+ int reserved = leis.readUByte();\r
+ Color c = new Color(red, green, blue);\r
+ colorList.add(c);\r
+ size += 4 * LittleEndianConsts.BYTE_SIZE;\r
+ }\r
+ colorTable = colorList.toArray(new Color[colorList.size()]);\r
+ return size;\r
+ }\r
+ \r
+ protected int readBitmapIndexed(LittleEndianInputStream leis) throws IOException {\r
+ assert(colorTable != null);\r
+ byte r[] = new byte[colorTable.length];\r
+ byte g[] = new byte[colorTable.length];\r
+ byte b[] = new byte[colorTable.length];\r
+ for (int i=0; i<colorTable.length; i++) {\r
+ r[i] = (byte)colorTable[i].getRed();\r
+ g[i] = (byte)colorTable[i].getGreen();\r
+ b[i] = (byte)colorTable[i].getBlue();\r
+ }\r
+ int bits = 32-Integer.numberOfLeadingZeros(colorTable.length);\r
+ IndexColorModel cm = new IndexColorModel(bits,colorTable.length,r,g,b);\r
+ \r
+ BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_BYTE_INDEXED, cm);\r
+ WritableRaster wr = bi.getRaster();\r
+ \r
+ int pixelCount = headerWidth*headerHeight;\r
+ int size = 0;\r
+ for (int pixel=0; pixel<pixelCount; size++) {\r
+ int v = leis.readUByte();\r
+ switch (headerBitCount) {\r
+ default:\r
+ throw new RuntimeException("invalid bitcount for indexed image");\r
+ case BI_BITCOUNT_1:\r
+ for (int j=0; j<8 && pixel<pixelCount; j++,pixel++) {\r
+ wr.setSample(pixel/headerWidth,pixel%headerWidth,0,(v>>(7-j))&1);\r
+ }\r
+ break;\r
+ case BI_BITCOUNT_2:\r
+ wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, (v>>4)&15);\r
+ pixel++;\r
+ if (pixel<pixelCount) {\r
+ wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v&15);\r
+ pixel++;\r
+ }\r
+ break;\r
+ case BI_BITCOUNT_3:\r
+ wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v);\r
+ pixel++;\r
+ break;\r
+ }\r
+ }\r
+ return size;\r
+ }\r
+ \r
+ protected int readBitmapDirect(LittleEndianInputStream leis) throws IOException {\r
+ assert(colorTable == null);\r
+ \r
+ BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_INT_RGB);\r
+ WritableRaster wr = bi.getRaster();\r
+ \r
+ int bitShiftRed=0,bitShiftGreen=0,bitShiftBlue=0;\r
+ if (headerCompression == Compression.BI_BITFIELDS) {\r
+ bitShiftGreen = 32-Integer.numberOfLeadingZeros(this.colorMaskBlue);\r
+ bitShiftRed = 32-Integer.numberOfLeadingZeros(this.colorMaskGreen);\r
+ }\r
+ \r
+ int pixelCount = headerWidth*headerHeight;\r
+ int size = 0;\r
+ int rgb[] = new int[3];\r
+ for (int pixel=0; pixel<pixelCount; pixel++) {\r
+ int v;\r
+ switch (headerBitCount) {\r
+ default:\r
+ throw new RuntimeException("invalid bitcount for indexed image");\r
+ case BI_BITCOUNT_4:\r
+ v = leis.readUShort();\r
+ rgb[0] = (v & colorMaskRed) >> bitShiftRed;\r
+ rgb[1] = (v & colorMaskGreen) >> bitShiftGreen;\r
+ rgb[2] = (v & colorMaskBlue) >> bitShiftBlue;\r
+ size += LittleEndianConsts.SHORT_SIZE;\r
+ break;\r
+ case BI_BITCOUNT_5:\r
+ rgb[2] = leis.readUByte();\r
+ rgb[1] = leis.readUByte();\r
+ rgb[0] = leis.readUByte();\r
+ size += 3*LittleEndianConsts.BYTE_SIZE;\r
+ break;\r
+ case BI_BITCOUNT_6:\r
+ v = leis.readInt();\r
+ rgb[0] = (v & colorMaskRed) >> bitShiftRed;\r
+ rgb[1] = (v & colorMaskGreen) >> bitShiftGreen;\r
+ rgb[2] = (v & colorMaskBlue) >> bitShiftBlue;\r
+ size += LittleEndianConsts.INT_SIZE;\r
+ break;\r
+ }\r
+ wr.setPixel(pixel/headerWidth,pixel%headerWidth,rgb);\r
+ }\r
+ \r
+ return size;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.awt.Color;\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfColorRef {\r
+ /**\r
+ * A 32-bit ColorRef Object that defines the color value.\r
+ * Red (1 byte): An 8-bit unsigned integer that defines the relative intensity of red.\r
+ * Green (1 byte): An 8-bit unsigned integer that defines the relative intensity of green.\r
+ * Blue (1 byte): An 8-bit unsigned integer that defines the relative intensity of blue.\r
+ * Reserved (1 byte): An 8-bit unsigned integer that MUST be 0x00.\r
+ */\r
+ Color colorRef;\r
+ \r
+ public int init(LittleEndianInputStream leis) throws IOException {\r
+ int red = leis.readUByte();\r
+ int green = leis.readUByte();\r
+ int blue = leis.readUByte();\r
+ @SuppressWarnings("unused")\r
+ int reserved = leis.readUByte();\r
+\r
+ colorRef = new Color(red, green, blue);\r
+ return 4*LittleEndianConsts.BYTE_SIZE;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a\r
+ * pattern specified by a DeviceIndependentBitmap (DIB) Object \r
+ */\r
+public class WmfDibCreatePatternBrush implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the brush style. The legal values for this\r
+ * field are defined as follows: if the value is not BS_PATTERN, BS_DIBPATTERNPT MUST be\r
+ * assumed.\r
+ */\r
+ public static enum BrushStyle {\r
+ /**\r
+ * A brush that paints a single, constant color, either solid or dithered.\r
+ */\r
+ BS_SOLID(0x0000),\r
+ /**\r
+ * A brush that does nothing. Using a BS_NULL brush in a graphics operation\r
+ * MUST have the same effect as using no brush at all.\r
+ */\r
+ BS_NULL(0x0001),\r
+ /**\r
+ * A brush that paints a predefined simple pattern, or "hatch", onto a solid background.\r
+ */\r
+ BS_HATCHED(0x0002),\r
+ /**\r
+ * A brush that paints a pattern defined by a bitmap, which MAY be a Bitmap16\r
+ * Object or a DeviceIndependentBitmap (DIB) Object.\r
+ */\r
+ BS_PATTERN(0x0003),\r
+ /**\r
+ * Not supported\r
+ */\r
+ BS_INDEXED(0x0004),\r
+ /**\r
+ * A pattern brush specified by a DIB.\r
+ */\r
+ BS_DIBPATTERN(0x0005),\r
+ /**\r
+ * A pattern brush specified by a DIB.\r
+ */\r
+ BS_DIBPATTERNPT(0x0006),\r
+ /**\r
+ * Not supported\r
+ */\r
+ BS_PATTERN8X8(0x0007),\r
+ /**\r
+ * Not supported\r
+ */\r
+ BS_DIBPATTERN8X8(0x0008),\r
+ /**\r
+ * Not supported\r
+ */\r
+ BS_MONOPATTERN(0x0009);\r
+ \r
+ int flag;\r
+ BrushStyle(int flag) {\r
+ this.flag = flag;\r
+ }\r
+ \r
+ static BrushStyle valueOf(int flag) {\r
+ for (BrushStyle bs : values()) {\r
+ if (bs.flag == flag) return bs;\r
+ }\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ BrushStyle style;\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines whether the Colors field of a DIB\r
+ * Object contains explicit RGB values, or indexes into a palette.\r
+ * \r
+ * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be\r
+ * used regardless of the contents of this field.\r
+ * \r
+ * If the Style field specified anything but BS_PATTERN, this field MUST be one of the values:\r
+ * DIB_RGB_COLORS = 0x0000,\r
+ * DIB_PAL_COLORS = 0x0001,\r
+ * DIB_PAL_INDICES = 0x0002\r
+ */\r
+ int colorUsage;\r
+ \r
+ WmfBitmapDib patternDib;\r
+ WmfBitmap16 pattern16;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.dibCreatePatternBrush;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ style = BrushStyle.valueOf(leis.readUShort());\r
+ colorUsage = leis.readUShort();\r
+ int size = 2*LittleEndianConsts.SHORT_SIZE; \r
+ switch (style) {\r
+ case BS_SOLID:\r
+ case BS_NULL:\r
+ case BS_DIBPATTERN:\r
+ case BS_DIBPATTERNPT:\r
+ case BS_HATCHED:\r
+ patternDib = new WmfBitmapDib();\r
+ size += patternDib.init(leis);\r
+ break;\r
+ case BS_PATTERN:\r
+ pattern16 = new WmfBitmap16();\r
+ size += pattern16.init(leis);\r
+ break;\r
+ case BS_INDEXED:\r
+ case BS_DIBPATTERN8X8:\r
+ case BS_MONOPATTERN:\r
+ case BS_PATTERN8X8:\r
+ throw new RuntimeException("pattern not supported");\r
+ }\r
+ return size;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfDraw {\r
+ /**\r
+ * The META_LINETO record draws a line from the drawing position that is defined in the playback\r
+ * device context up to, but not including, the specified point.\r
+ */\r
+ public static class WmfLineTo implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical component of the drawing\r
+ * destination position, in logical units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal component of the drawing\r
+ * destination position, in logical units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.lineTo;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_POLYGON record paints a polygon consisting of two or more vertices connected by\r
+ * straight lines. The polygon is outlined by using the pen and filled by using the brush and polygon fill\r
+ * mode that are defined in the playback device context.\r
+ */\r
+ public static class WmfPolygon implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the number of points in the array.\r
+ */\r
+ int numberofPoints;\r
+ \r
+ short xPoints[], yPoints[];\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.polygon;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ numberofPoints = leis.readShort();\r
+ xPoints = new short[numberofPoints];\r
+ yPoints = new short[numberofPoints];\r
+ \r
+ for (int i=0; i<numberofPoints; i++) {\r
+ // A 16-bit signed integer that defines the horizontal (x) coordinate of the point.\r
+ xPoints[i] = leis.readShort();\r
+ // A 16-bit signed integer that defines the vertical (y) coordinate of the point.\r
+ yPoints[i] = leis.readShort();\r
+ }\r
+ \r
+ return LittleEndianConsts.SHORT_SIZE+numberofPoints*LittleEndianConsts.INT_SIZE;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_POLYLINE record draws a series of line segments by connecting the points in the\r
+ * specified array.\r
+ */\r
+ public static class WmfPolyline extends WmfPolygon {\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.polyline;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_ELLIPSE record draws an ellipse. The center of the ellipse is the center of the specified\r
+ * bounding rectangle. The ellipse is outlined by using the pen and is filled by using the brush; these\r
+ * are defined in the playback device context.\r
+ */\r
+ public static class WmfEllipse implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of\r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int bottomRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int rightRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the bounding rectangle.\r
+ */\r
+ int topRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the upper-left corner of the bounding rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.ellipse;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The META_FRAMEREGION record draws a border around a specified region using a specified brush.\r
+ */\r
+ public static class WmfFrameRegion implements WmfRecord {\r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the region to be framed.\r
+ */\r
+ int region; \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get the\r
+ * Brush to use for filling the region.\r
+ */\r
+ int brush;\r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical units, of the\r
+ * region frame.\r
+ */\r
+ int height;\r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical units, of the\r
+ * region frame.\r
+ */\r
+ int width;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.frameRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ region = leis.readUShort();\r
+ brush = leis.readUShort();\r
+ height = leis.readShort();\r
+ width = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_POLYPOLYGON record paints a series of closed polygons. Each polygon is outlined by\r
+ * using the pen and filled by using the brush and polygon fill mode; these are defined in the playback\r
+ * device context. The polygons drawn by this function can overlap.\r
+ */\r
+ public static class WmfPolyPolygon implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the number of polygons in the object.\r
+ */\r
+ int numberOfPolygons;\r
+ \r
+ /**\r
+ * A NumberOfPolygons array of 16-bit unsigned integers that define the number of\r
+ * points for each polygon in the object.\r
+ */\r
+ int pointsPerPolygon[];\r
+ \r
+ /**\r
+ * An array of 16-bit unsigned integers that define the coordinates of the polygons.\r
+ */\r
+ int xPoints[][];\r
+\r
+ /**\r
+ * An array of 16-bit unsigned integers that define the coordinates of the polygons.\r
+ */\r
+ int yPoints[][];\r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.polyPolygon;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ // see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;)\r
+ numberOfPolygons = leis.readUShort();\r
+ pointsPerPolygon = new int[numberOfPolygons];\r
+ xPoints = new int[numberOfPolygons][];\r
+ yPoints = new int[numberOfPolygons][];\r
+\r
+ int size = LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ for (int i=0; i<numberOfPolygons; i++) {\r
+ pointsPerPolygon[i] = leis.readUShort();\r
+ size += LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ \r
+ for (int i=0; i<numberOfPolygons; i++) {\r
+ \r
+ xPoints[i] = new int[pointsPerPolygon[i]];\r
+ yPoints[i] = new int[pointsPerPolygon[i]];\r
+ \r
+ for (int j=0; j<pointsPerPolygon[i]; j++) {\r
+ xPoints[i][j] = leis.readUShort();\r
+ yPoints[i][j] = leis.readUShort();\r
+ size += 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ return size;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and\r
+ * filled by using the brush that are defined in the playback device context.\r
+ */\r
+ public static class WmfRectangle implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of\r
+ * the lower-right corner of the rectangle.\r
+ */\r
+ int bottomRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the lower-right corner of the rectangle.\r
+ */\r
+ int rightRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int topRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the upper-left corner of the rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.frameRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and\r
+ * filled by using the brush that are defined in the playback device context.\r
+ */\r
+ public static class WmfSetPixel implements WmfRecord {\r
+ /**\r
+ * A ColorRef Object that defines the color value.\r
+ */\r
+ WmfColorRef colorRef; \r
+\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point\r
+ * to be set.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point\r
+ * to be set.\r
+ */\r
+ int x;\r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setPixel;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ colorRef = new WmfColorRef();\r
+ int size = colorRef.init(leis);\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE+size;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_ROUNDRECT record paints a rectangle with rounded corners. The rectangle is outlined\r
+ * using the pen and filled using the brush, as defined in the playback device context.\r
+ */\r
+ public static class WmfRoundRect implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical coordinates, of the\r
+ * ellipse used to draw the rounded corners.\r
+ */\r
+ int height;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical coordinates, of the\r
+ * ellipse used to draw the rounded corners.\r
+ */\r
+ int width;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of\r
+ * the lower-right corner of the rectangle.\r
+ */\r
+ int bottomRect;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the lower-right corner of the rectangle.\r
+ */\r
+ int rightRect;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int topRect;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of\r
+ * the upper-left corner of the rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.roundRect;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ height = leis.readShort();\r
+ width = leis.readShort();\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 6*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+\r
+\r
+ /**\r
+ * The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two\r
+ * radials. The pie is outlined by using the pen and filled by using the brush that are defined in the\r
+ * playback device context.\r
+ */\r
+ public static class WmfPie implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical\r
+ * coordinates, of the endpoint of the second radial.\r
+ */\r
+ int yRadial2;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical\r
+ * coordinates, of the endpoint of the second radial.\r
+ */\r
+ int xRadial2;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical \r
+ * coordinates, of the endpoint of the first radial.\r
+ */\r
+ int yRadial1;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical \r
+ * coordinates, of the endpoint of the first radial.\r
+ */\r
+ int xRadial1; \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int bottomRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int rightRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the \r
+ * upper-left corner of the bounding rectangle.\r
+ */\r
+ int topRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the upper-left corner of the bounding rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.pie;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yRadial2 = leis.readShort();\r
+ xRadial2 = leis.readShort();\r
+ yRadial1 = leis.readShort();\r
+ xRadial1 = leis.readShort();\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 8*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_ARC record draws an elliptical arc.\r
+ */\r
+ public static class WmfArc implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of\r
+ * the ending point of the radial line defining the ending point of the arc.\r
+ */\r
+ int yEndArc; \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the ending point of the radial line defining the ending point of the arc.\r
+ */\r
+ int xEndArc; \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of \r
+ * the ending point of the radial line defining the starting point of the arc.\r
+ */\r
+ int yStartArc;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the ending point of the radial line defining the starting point of the arc.\r
+ */\r
+ int xStartArc;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int bottomRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int rightRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the \r
+ * upper-left corner of the bounding rectangle.\r
+ */\r
+ int topRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the upper-left corner of the bounding rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.arc;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yEndArc = leis.readShort();\r
+ xEndArc = leis.readShort();\r
+ yStartArc = leis.readShort();\r
+ xStartArc = leis.readShort();\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 8*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of\r
+ * an ellipse with a line segment. The chord is outlined using the pen and filled using the brush\r
+ * that are defined in the playback device context.\r
+ */\r
+ public static class WmfChord implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical \r
+ * coordinates, of the endpoint of the second radial.\r
+ */\r
+ int yRadial2;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical \r
+ * coordinates, of the endpoint of the second radial.\r
+ */\r
+ int xRadial2;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical \r
+ * coordinates, of the endpoint of the first radial.\r
+ */\r
+ int yRadial1;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical \r
+ * coordinates, of the endpoint of the first radial.\r
+ */\r
+ int xRadial1;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int bottomRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the lower-right corner of the bounding rectangle.\r
+ */\r
+ int rightRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the \r
+ * upper-left corner of the bounding rectangle.\r
+ */\r
+ int topRect;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of \r
+ * the upper-left corner of the bounding rectangle.\r
+ */\r
+ int leftRect;\r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.chord;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yRadial2 = leis.readShort();\r
+ xRadial2 = leis.readShort();\r
+ yRadial1 = leis.readShort();\r
+ xRadial1 = leis.readShort();\r
+ bottomRect = leis.readShort();\r
+ rightRect = leis.readShort();\r
+ topRect = leis.readShort();\r
+ leftRect = leis.readShort();\r
+ return 8*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The META_SELECTOBJECT record specifies a graphics object for the playback device context. The \r
+ * new object replaces the previous object of the same type, unless if the previous object is a palette \r
+ * object. If the previous object is a palette object, then the META_SELECTPALETTE record must be \r
+ * used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not \r
+ * support replacing the palette object type.\r
+ */\r
+ public static class WmfSelectObject implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to\r
+ * get the object to be selected.\r
+ */\r
+ int objectIndex;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.selectObject;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ objectIndex = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ }\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfEscape implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the escape function. The \r
+ * value MUST be from the MetafileEscapes enumeration.\r
+ */\r
+ int escapeFunction;\r
+ /**\r
+ * A 16-bit unsigned integer that specifies the size, in bytes, of the \r
+ * EscapeData field.\r
+ */\r
+ int byteCount;\r
+ /**\r
+ * An array of bytes of size ByteCount.\r
+ */\r
+ byte escapeData[];\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.escape;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ escapeFunction = leis.readUShort();\r
+ byteCount = leis.readUShort();\r
+ escapeData = new byte[byteCount];\r
+ leis.read(escapeData);\r
+ return 2*LittleEndianConsts.SHORT_SIZE+byteCount;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfFill {\r
+ /**\r
+ * The META_FILLREGION record fills a region using a specified brush.\r
+ */\r
+ public static class WmfFillRegion implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the region to be filled.\r
+ */\r
+ int region;\r
+\r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get the\r
+ * brush to use for filling the region.\r
+ */\r
+ int brush;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.fillRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ region = leis.readUShort();\r
+ brush = leis.readUShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_PAINTREGION record paints the specified region by using the brush that is\r
+ * defined in the playback device context.\r
+ */\r
+ public static class WmfPaintRegion implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the region to be painted.\r
+ */\r
+ int region;\r
+\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.paintRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ region = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ \r
+ /**\r
+ * The META_FLOODFILL record fills an area of the output surface with the brush that\r
+ * is defined in the playback device context.\r
+ */\r
+ public static class WmfFloodFill implements WmfRecord {\r
+ \r
+ /**\r
+ * A 32-bit ColorRef Object that defines the color value.\r
+ */\r
+ WmfColorRef colorRef;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * point where filling is to start.\r
+ */\r
+ int yStart;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * point where filling is to start.\r
+ */\r
+ int xStart;\r
+ \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.floodFill;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ colorRef = new WmfColorRef();\r
+ int size = colorRef.init(leis);\r
+ yStart = leis.readShort();\r
+ xStart = leis.readShort();\r
+ return size+2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_SETPOLYFILLMODE record sets polygon fill mode in the playback device context for\r
+ * graphics operations that fill polygons.\r
+ */\r
+ public static class WmfSetPolyfillMode implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines polygon fill mode.\r
+ * This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002\r
+ */\r
+ int polyFillMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setPolyFillMode;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ polyFillMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The META_EXTFLOODFILL record fills an area with the brush that is defined in\r
+ * the playback device context.\r
+ */\r
+ public static class WmfExtFloodFill implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the fill operation to be performed. This\r
+ * member MUST be one of the values in the FloodFill Enumeration table:\r
+ * \r
+ * FLOODFILLBORDER = 0x0000:\r
+ * The fill area is bounded by the color specified by the Color member.\r
+ * This style is identical to the filling performed by the META_FLOODFILL record.\r
+ * \r
+ * FLOODFILLSURFACE = 0x0001:\r
+ * The fill area is bounded by the color that is specified by the Color member.\r
+ * Filling continues outward in all directions as long as the color is encountered.\r
+ * This style is useful for filling areas with multicolored boundaries.\r
+ */\r
+ int mode;\r
+ \r
+ /**\r
+ * A 32-bit ColorRef Object that defines the color value.\r
+ */\r
+ WmfColorRef colorRef;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the point\r
+ * to be set.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the point\r
+ * to be set.\r
+ */\r
+ int x; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.extFloodFill;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ mode = leis.readUShort();\r
+ colorRef = new WmfColorRef();\r
+ int size = colorRef.init(leis);\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return size+3*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_INVERTREGION record draws a region in which the colors are inverted.\r
+ */\r
+ public static class WmfInvertRegion implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the region to be inverted.\r
+ */\r
+ int region;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.invertRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ region = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+\r
+ /**\r
+ * The META_PATBLT record paints a specified rectangle using the brush that is defined in the playback\r
+ * device context. The brush color and the surface color or colors are combined using the specified\r
+ * raster operation.\r
+ */\r
+ public static class WmfPatBlt implements WmfRecord {\r
+ \r
+ /**\r
+ * A 32-bit unsigned integer that defines the raster operation code.\r
+ * This code MUST be one of the values in the Ternary Raster Operation enumeration table.\r
+ */\r
+ WmfTernaryRasterOp rasterOperation;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical units, of the rectangle.\r
+ */\r
+ int height;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical units, of the rectangle.\r
+ */\r
+ int width;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle to be filled.\r
+ */\r
+ int yLeft;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle to be filled.\r
+ */\r
+ int xLeft;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.patBlt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ int rasterOpIndex = leis.readUShort();\r
+ int rasterOpCode = leis.readUShort();\r
+\r
+ rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);\r
+ assert(rasterOpCode == rasterOperation.opCode);\r
+ \r
+ height = leis.readShort();\r
+ width = leis.readShort();\r
+ yLeft = leis.readShort();\r
+ xLeft = leis.readShort();\r
+\r
+ return 6*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ public static class WmfStretchBlt implements WmfRecord {\r
+ /**\r
+ */\r
+ \r
+ /**\r
+ * A 32-bit unsigned integer that defines how the source pixels, the current brush\r
+ * in the playback device context, and the destination pixels are to be combined to form the new \r
+ * image. This code MUST be one of the values in the Ternary Raster Operation Enumeration\r
+ */\r
+ WmfTernaryRasterOp rasterOperation;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical units, of the source rectangle.\r
+ */\r
+ int srcHeight; \r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical units, of the source rectangle.\r
+ */\r
+ int srcWidth; \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner \r
+ * of the source rectangle.\r
+ */\r
+ int ySrc;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner \r
+ * of the source rectangle.\r
+ */\r
+ int xSrc;\r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical units, of the destination rectangle.\r
+ */\r
+ int destHeight;\r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical units, of the destination rectangle.\r
+ */\r
+ int destWidth;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left \r
+ * corner of the destination rectangle.\r
+ */\r
+ int yDest;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left \r
+ * corner of the destination rectangle.\r
+ */\r
+ int xDest;\r
+ \r
+ /**\r
+ * A variable-sized Bitmap16 Object that defines source image content.\r
+ * This object MUST be specified, even if the raster operation does not require a source.\r
+ */\r
+ WmfBitmap16 target;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.stretchBlt;\r
+ }\r
+ \r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));\r
+\r
+ int size = 0;\r
+ int rasterOpIndex = leis.readUShort();\r
+ int rasterOpCode = leis.readUShort();\r
+ \r
+ rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);\r
+ assert(rasterOpCode == rasterOperation.opCode);\r
+\r
+ srcHeight = leis.readShort();\r
+ srcWidth = leis.readShort();\r
+ ySrc = leis.readShort();\r
+ xSrc = leis.readShort();\r
+ size = 6*LittleEndianConsts.SHORT_SIZE;\r
+ if (!hasBitmap) {\r
+ @SuppressWarnings("unused")\r
+ int reserved = leis.readShort();\r
+ size += LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ destHeight = leis.readShort();\r
+ destWidth = leis.readShort();\r
+ yDest = leis.readShort();\r
+ xDest = leis.readShort();\r
+ size += 4*LittleEndianConsts.SHORT_SIZE;\r
+ if (hasBitmap) {\r
+ target = new WmfBitmap16();\r
+ size += target.init(leis);\r
+ }\r
+ \r
+ return size;\r
+ }\r
+ }\r
+\r
+ public static class WmfBitBlt implements WmfRecord {\r
+\r
+ /**\r
+ * A 32-bit unsigned integer that defines how the source pixels, the current brush in the playback \r
+ * device context, and the destination pixels are to be combined to form the new image.\r
+ */\r
+ WmfTernaryRasterOp rasterOperation;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner \r
+ of the source rectangle.\r
+ */\r
+ int ySrc; \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner \r
+ of the source rectangle.\r
+ */\r
+ int xSrc; \r
+ /**\r
+ * A 16-bit signed integer that defines the height, in logical units, of the source and \r
+ destination rectangles.\r
+ */\r
+ int height;\r
+ /**\r
+ * A 16-bit signed integer that defines the width, in logical units, of the source and destination \r
+ rectangles.\r
+ */\r
+ int width;\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left \r
+ corner of the destination rectangle.\r
+ */\r
+ int yDest;\r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left \r
+ corner of the destination rectangle.\r
+ */\r
+ int xDest;\r
+ \r
+ /**\r
+ * A variable-sized Bitmap16 Object that defines source image content.\r
+ * This object MUST be specified, even if the raster operation does not require a source.\r
+ */\r
+ WmfBitmap16 target;\r
+\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.bitBlt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3));\r
+\r
+ int size = 0;\r
+ int rasterOpIndex = leis.readUShort();\r
+ int rasterOpCode = leis.readUShort();\r
+ \r
+ rasterOperation = WmfTernaryRasterOp.fromOpIndex(rasterOpIndex);\r
+ assert(rasterOpCode == rasterOperation.opCode);\r
+\r
+ ySrc = leis.readShort();\r
+ xSrc = leis.readShort();\r
+\r
+ size = 4*LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ if (!hasBitmap) {\r
+ @SuppressWarnings("unused")\r
+ int reserved = leis.readShort();\r
+ size += LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ \r
+ height = leis.readShort();\r
+ width = leis.readShort();\r
+ yDest = leis.readShort();\r
+ xDest = leis.readShort();\r
+\r
+ size += 4*LittleEndianConsts.SHORT_SIZE;\r
+ if (hasBitmap) {\r
+ target = new WmfBitmap16();\r
+ size += target.init(leis);\r
+ }\r
+ \r
+ return size;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfHeader {\r
+ private int type;\r
+ private int recordSize;\r
+ private int version;\r
+ private int filesize;\r
+ private int numberOfObjects;\r
+ private long maxRecord;\r
+ private int numberOfMembers;\r
+ \r
+ public WmfHeader(LittleEndianInputStream leis) throws IOException {\r
+ // Type (2 bytes): A 16-bit unsigned integer that defines the type of metafile\r
+ // MEMORYMETAFILE = 0x0001, DISKMETAFILE = 0x0002 \r
+ type = leis.readUShort();\r
+\r
+ // HeaderSize (2 bytes): A 16-bit unsigned integer that defines the number\r
+ // of 16-bit words in the header.\r
+ recordSize = leis.readUShort();\r
+ int bytesLeft = recordSize*LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ // Version (2 bytes): A 16-bit unsigned integer that defines the metafile version.\r
+ // METAVERSION100 = 0x0100, METAVERSION300 = 0x0300\r
+ version = leis.readUShort();\r
+ bytesLeft -= LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ // SizeLow (2 bytes): A 16-bit unsigned integer that defines the low-order word\r
+ // of the number of 16-bit words in the entire metafile.\r
+ // SizeHigh (2 bytes): A 16-bit unsigned integer that defines the high-order word\r
+ // of the number of 16-bit words in the entire metafile.\r
+ filesize = leis.readInt();\r
+ bytesLeft -= LittleEndianConsts.INT_SIZE;\r
+ \r
+ // NumberOfObjects (2 bytes): A 16-bit unsigned integer that specifies the number\r
+ // of graphics objects that are defined in the entire metafile. These objects include\r
+ // brushes, pens, and the other objects\r
+ numberOfObjects = leis.readUShort();\r
+ bytesLeft -= LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ // MaxRecord (4 bytes): A 32-bit unsigned integer that specifies the size of the\r
+ // largest record used in the metafile (in 16-bit elements).\r
+ maxRecord = leis.readUInt();\r
+ bytesLeft -= LittleEndianConsts.INT_SIZE;\r
+ \r
+ // NumberOfMembers (2 bytes): A 16-bit unsigned integer that is not used.\r
+ // It SHOULD be 0x0000.\r
+ numberOfMembers = leis.readUShort();\r
+ bytesLeft -= LittleEndianConsts.SHORT_SIZE;\r
+ \r
+ leis.skip(bytesLeft);\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_MOVETO record sets the output position in the playback device context to a specified\r
+ * point.\r
+ */\r
+public class WmfMoveTo implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.moveTo;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfNoArg {\r
+ protected static abstract class WmfNoArgParent implements WmfRecord {\r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ return 0;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_SAVEDC record saves the playback device context for later retrieval.\r
+ */\r
+ public static class WmfSaveDc extends WmfNoArgParent {\r
+ public WmfRecordType getRecordType() { return WmfRecordType.saveDc; }\r
+ }\r
+\r
+ /**\r
+ * The META_SETRELABS record is reserved and not supported.\r
+ */\r
+ public static class WmfSetRelabs extends WmfNoArgParent {\r
+ public WmfRecordType getRecordType() { return WmfRecordType.setRelabs; }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfPalette {\r
+ \r
+ public static class PaletteEntry {\r
+ // Values (1 byte): An 8-bit unsigned integer that defines how the palette entry is to be used. \r
+ // The Values field MUST be 0x00 or one of the values in the PaletteEntryFlag Enumeration table.\r
+ // Blue (1 byte): An 8-bit unsigned integer that defines the blue intensity value for the palette entry.\r
+ // Green (1 byte): An 8-bit unsigned integer that defines the green intensity value for the palette entry.\r
+ // Red (1 byte): An 8-bit unsigned integer that defines the red intensity value for the palette entry.\r
+ int values, blue, green, red;\r
+ \r
+ public int init(LittleEndianInputStream leis) throws IOException {\r
+ values = leis.readUByte();\r
+ blue = leis.readUByte();\r
+ green = leis.readUByte();\r
+ red = leis.readUByte();\r
+ return 4*LittleEndianConsts.BYTE_SIZE;\r
+ }\r
+ }\r
+ \r
+ public static abstract class WmfPaletteParent implements WmfRecord {\r
+ \r
+ /**\r
+ * Start (2 bytes): A 16-bit unsigned integer that defines the offset into the Palette Object when\r
+ * used with the META_SETPALENTRIES and META_ANIMATEPALETTE record types.\r
+ * When used with META_CREATEPALETTE, it MUST be 0x0300\r
+ */\r
+ int start;\r
+ \r
+ /**\r
+ * NumberOfEntries (2 bytes): A 16-bit unsigned integer that defines the number of objects in\r
+ * aPaletteEntries. \r
+ */\r
+ int numberOfEntries;\r
+ \r
+ PaletteEntry entries[];\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ start = leis.readUShort();\r
+ numberOfEntries = leis.readUShort();\r
+ int size = 2*LittleEndianConsts.SHORT_SIZE;\r
+ entries = new PaletteEntry[numberOfEntries];\r
+ for (int i=0; i<numberOfEntries; i++) {\r
+ entries[i] = new PaletteEntry();\r
+ size += entries[i].init(leis);\r
+ }\r
+ return size;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_CREATEPALETTE record creates a Palette Object\r
+ */\r
+ public static class WmfCreatePalette extends WmfPaletteParent {\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.createPalette;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_SETPALENTRIES record defines RGB color values in a range of entries in the logical\r
+ * palette that is defined in the playback device context.\r
+ */\r
+ public static class WmfSetPaletteEntries extends WmfPaletteParent {\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setPalEntries;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_RESIZEPALETTE record redefines the size of the logical palette that is defined in the\r
+ * playback device context.\r
+ */\r
+ public static class WmfResizePalette implements WmfRecord {\r
+ /**\r
+ * A 16-bit unsigned integer that defines the number of entries in \r
+ * the logical palette.\r
+ */\r
+ int numberOfEntries;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.resizePalette;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ numberOfEntries = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ } \r
+ }\r
+\r
+ /**\r
+ * The META_SELECTPALETTE record defines the current logical palette with a specified Palette Object.\r
+ */\r
+ public static class WmfSelectPalette implements WmfRecord {\r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the Palette Object to be selected.\r
+ */\r
+ int palette;\r
+\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.selectPalette;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ palette = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ } \r
+ }\r
+\r
+ /**\r
+ * The META_REALIZEPALETTE record maps entries from the logical palette that\r
+ * is defined in the playback device context to the system palette.\r
+ */\r
+ public static class WmfRealizePalette implements WmfRecord {\r
+ public WmfRecordType getRecordType() { return WmfRecordType.realizePalette; }\r
+\r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_ANIMATEPALETTE record redefines entries in the logical palette that\r
+ * is defined in the playback device context with the specified Palette object\r
+ * \r
+ * The logical palette that is specified by the Palette object in this record is the\r
+ * source of the palette changes, and the logical palette that is currently selected\r
+ * into the playback device context is the destination. Entries in the destination\r
+ * palette with the PC_RESERVED PaletteEntryFlag set SHOULD be modified by this record,\r
+ * and entries with that flag clear SHOULD NOT be modified.\r
+ * If none of the entries in the destination palette have the PC_RESERVED flag set, then\r
+ * this record SHOULD have no effect.\r
+ */\r
+ public static class WmfAnimatePalette extends WmfPaletteParent {\r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.animatePalette;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfPlaceableHeader {\r
+ public static int WMF_HEADER_MAGIC = 0x9AC6CDD7;\r
+ \r
+ protected WmfPlaceableHeader(LittleEndianInputStream leis) throws IOException {\r
+ /*\r
+ * HWmf (2 bytes): The resource handle to the metafile, when the metafile is in memory. When\r
+ * the metafile is on disk, this field MUST contain 0x0000. This attribute of the metafile is\r
+ * specified in the Type field of the META_HEADER record.\r
+ */\r
+ leis.readShort(); // ignore\r
+ \r
+ /*\r
+ * BoundingBox (8 bytes): The destination rectangle, measured in logical units, for displaying\r
+ * the metafile. The size of a logical unit is specified by the Inch field.\r
+ */\r
+ int x1 = leis.readShort();\r
+ int y1 = leis.readShort();\r
+ int x2 = leis.readShort();\r
+ int y2 = leis.readShort();\r
+ \r
+ /*\r
+ * Inch (2 bytes): The number of logical units per inch used to represent the image.\r
+ * This value can be used to scale an image.\r
+ * By convention, an image is considered to be recorded at 1440 logical units (twips) per inch.\r
+ * Thus, a value of 720 specifies that the image SHOULD be rendered at twice its normal size,\r
+ * and a value of 2880 specifies that the image SHOULD be rendered at half its normal size.\r
+ */\r
+ int inch = leis.readShort();\r
+ \r
+ /*\r
+ * Reserved (4 bytes): A field that is not used and MUST be set to 0x00000000.\r
+ */\r
+ leis.readInt();\r
+ \r
+ /*\r
+ * Checksum (2 bytes): A checksum for the previous 10 16-bit values in the header.\r
+ * This value can be used to determine whether the metafile has become corrupted.\r
+ */\r
+ leis.readShort();\r
+ \r
+ }\r
+ \r
+ public static WmfPlaceableHeader readHeader(LittleEndianInputStream leis) throws IOException {\r
+ leis.mark(LittleEndianConsts.INT_SIZE);\r
+ int magic = leis.readInt();\r
+ if (magic == WMF_HEADER_MAGIC) {\r
+ return new WmfPlaceableHeader(leis);\r
+ } else {\r
+ leis.reset();\r
+ return null;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public interface WmfRecord {\r
+ WmfRecordType getRecordType();\r
+\r
+ /**\r
+ * Init record from stream\r
+ *\r
+ * @param leis the little endian input stream\r
+ * @return count of processed bytes\r
+ * @throws IOException\r
+ */\r
+ int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException;\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+public enum WmfRecordType {\r
+ eof(0x0000, null),\r
+ realizePalette(0x0035, WmfPalette.WmfRealizePalette.class),\r
+ setPalEntries(0x0037, WmfPalette.WmfSetPaletteEntries.class),\r
+ setBkMode(0x0102, WmfSetBkMode.class),\r
+ setMapMode(0x0103, WmfSetMapMode.class),\r
+ setRop2(0x0104, WmfSetRop2.class),\r
+ setRelabs(0x0105, WmfNoArg.WmfSetRelabs.class),\r
+ setPolyFillMode(0x0106, WmfFill.WmfSetPolyfillMode.class),\r
+ setStretchBltMode(0x0107, WmfSetStretchBltMode.class),\r
+ setTextCharExtra(0x0108, WmfText.WmfSetTextCharExtra.class),\r
+ restoreDc(0x0127, WmfRestoreDc.class),\r
+ resizePalette(0x0139, WmfPalette.WmfResizePalette.class),\r
+ dibCreatePatternBrush(0x0142, WmfDibCreatePatternBrush.class),\r
+ setLayout(0x0149, WmfSetLayout.class),\r
+ setBkColor(0x0201, WmfSetBkColor.class),\r
+ setTextColor(0x0209, WmfText.WmfSetTextColor.class),\r
+ offsetViewportOrg(0x0211, WmfWindowing.WmfOffsetViewportOrg.class),\r
+ lineTo(0x0213, WmfDraw.WmfLineTo.class),\r
+ moveTo(0x0214, WmfMoveTo.class),\r
+ offsetClipRgn(0x0220, WmfWindowing.WmfOffsetClipRgn.class),\r
+ fillRegion(0x0228, WmfFill.WmfFillRegion.class),\r
+ setMapperFlags(0x0231, WmfSetMapperFlags.class),\r
+ selectPalette(0x0234, WmfPalette.WmfSelectPalette.class),\r
+ polygon(0x0324, WmfDraw.WmfPolygon.class),\r
+ polyline(0x0325, WmfDraw.WmfPolyline.class),\r
+ setTextJustification(0x020a, WmfText.WmfSetTextJustification.class),\r
+ setWindowOrg(0x020b, WmfWindowing.WmfSetWindowOrg.class),\r
+ setWindowExt(0x020c, WmfWindowing.WmfSetWindowExt.class),\r
+ setViewportOrg(0x020d, WmfWindowing.WmfSetViewportOrg.class),\r
+ setViewportExt(0x020e, WmfWindowing.WmfSetViewportExt.class),\r
+ offsetWindowOrg(0x020f, WmfWindowing.WmfOffsetWindowOrg.class),\r
+ scaleWindowExt(0x0410, WmfWindowing.WmfScaleWindowExt.class),\r
+ scaleViewportExt(0x0412, WmfWindowing.WmfScaleViewportExt.class), \r
+ excludeClipRect(0x0415, WmfWindowing.WmfExcludeClipRect.class),\r
+ intersectClipRect(0x0416, WmfWindowing.WmfIntersectClipRect.class),\r
+ ellipse(0x0418, WmfDraw.WmfEllipse.class),\r
+ floodFill(0x0419, WmfFill.WmfFloodFill.class),\r
+ frameRegion(0x0429, WmfDraw.WmfFrameRegion.class),\r
+ animatePalette(0x0436, WmfPalette.WmfAnimatePalette.class),\r
+ textOut(0x0521, WmfText.WmfTextOut.class),\r
+ polyPolygon(0x0538, WmfDraw.WmfPolyPolygon.class),\r
+ extFloodFill(0x0548, WmfFill.WmfExtFloodFill.class),\r
+ rectangle(0x041b, WmfDraw.WmfRectangle.class),\r
+ setPixel(0x041f, WmfDraw.WmfSetPixel.class),\r
+ roundRect(0x061c, WmfDraw.WmfRoundRect.class),\r
+ patBlt(0x061d, WmfFill.WmfPatBlt.class),\r
+ saveDc(0x001e, WmfNoArg.WmfSaveDc.class),\r
+ pie(0x081a, WmfDraw.WmfPie.class),\r
+ stretchBlt(0x0b23, WmfFill.WmfStretchBlt.class),\r
+ escape(0x0626, WmfEscape.class),\r
+ invertRegion(0x012a, WmfFill.WmfInvertRegion.class),\r
+ paintRegion(0x012b, WmfFill.WmfPaintRegion.class),\r
+ selectClipRegion(0x012c, WmfWindowing.WmfSelectClipRegion.class),\r
+ selectObject(0x012d, WmfDraw.WmfSelectObject.class),\r
+ setTextAlign(0x012e, WmfText.WmfSetTextAlign.class),\r
+ arc(0x0817, WmfDraw.WmfArc.class),\r
+ chord(0x0830, WmfDraw.WmfChord.class),\r
+ bitBlt(0x0922, WmfFill.WmfBitBlt.class),\r
+ extTextOut(0x0a32, WmfText.WmfExtTextOut.class),\r
+ setDibToDev(0x0d33, WmfBitmap.WmfSetDibToDev.class),\r
+ dibBitBlt(0x0940, null),\r
+ dibStretchBlt(0x0b41, null),\r
+ stretchDib(0x0f43, null),\r
+ deleteObject(0x01f0, null),\r
+ createPalette(0x00f7, WmfPalette.WmfCreatePalette.class),\r
+ createPatternBrush(0x01f9, null),\r
+ createPenIndirect(0x02fa, null),\r
+ createFontIndirect(0x02fb, null),\r
+ createBrushIndirect(0x02fc, null),\r
+ createRegion(0x06ff, null);\r
+ \r
+ public int id;\r
+ public Class<? extends WmfRecord> clazz;\r
+ \r
+ WmfRecordType(int id, Class<? extends WmfRecord> clazz) {\r
+ this.id = id;\r
+ this.clazz = clazz;\r
+ }\r
+ \r
+ public static WmfRecordType getById(int id) {\r
+ for (WmfRecordType wrt : values()) {\r
+ if (wrt.id == id) return wrt;\r
+ }\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_RESTOREDC record restores the playback device context from a previously saved device\r
+ * context.\r
+ */\r
+public class WmfRestoreDc implements WmfRecord {\r
+ \r
+ /**\r
+ * nSavedDC (2 bytes): A 16-bit signed integer that defines the saved state to be restored. If this \r
+ * member is positive, nSavedDC represents a specific instance of the state to be restored. If \r
+ * this member is negative, nSavedDC represents an instance relative to the current state.\r
+ */\r
+ int nSavedDC;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.restoreDc;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ nSavedDC = leis.readShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETBKCOLOR record sets the background color in the playback device context to a\r
+ * specified color, or to the nearest physical color if the device cannot represent the specified color.\r
+ */\r
+public class WmfSetBkColor implements WmfRecord {\r
+ \r
+ WmfColorRef colorRef;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setBkColor;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ WmfColorRef colorRef = new WmfColorRef();\r
+ return colorRef.init(leis);\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETBKMODE record defines the background raster operation mix mode in the playback\r
+ * device context. The background mix mode is the mode for combining pens, text, hatched brushes,\r
+ * and interiors of filled objects with background colors on the output surface.\r
+ */\r
+public class WmfSetBkMode implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines background mix mode.\r
+ * This MUST be either TRANSPARENT = 0x0001 or OPAQUE = 0x0002\r
+ */\r
+ int bkMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setBkMode;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ bkMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETLAYOUT record defines the layout orientation in the playback device context.\r
+ * The layout orientation determines the direction in which text and graphics are drawn\r
+ */\r
+public class WmfSetLayout implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the layout of text and graphics.\r
+ * LAYOUT_LTR = 0x0000\r
+ * LAYOUT_RTL = 0x0001\r
+ * LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008\r
+ */\r
+ int layout;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setLayout;\r
+ }\r
+ \r
+ @SuppressWarnings("unused")\r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ layout = leis.readUShort();\r
+ // A 16-bit field that MUST be ignored.\r
+ int reserved = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETMAPMODE record defines the mapping mode in the playback device context.\r
+ * The mapping mode defines the unit of measure used to transform page-space units into\r
+ * device-space units, and also defines the orientation of the device's x and y axes. \r
+ */\r
+public class WmfSetMapMode implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the mapping mode.\r
+ * \r
+ * The MapMode defines how logical units are mapped to physical units;\r
+ * that is, assuming that the origins in both the logical and physical coordinate systems\r
+ * are at the same point on the drawing surface, what is the physical coordinate (x',y')\r
+ * that corresponds to logical coordinate (x,y).\r
+ * \r
+ * For example, suppose the mapping mode is MM_TEXT. Given the following definition of that\r
+ * mapping mode, and an origin (0,0) at the top left corner of the drawing surface, logical\r
+ * coordinate (4,5) would map to physical coordinate (4,5) in pixels.\r
+ * \r
+ * Now suppose the mapping mode is MM_LOENGLISH, with the same origin as the previous\r
+ * example. Given the following definition of that mapping mode, logical coordinate (4,-5)\r
+ * would map to physical coordinate (0.04,0.05) in inches.\r
+ * \r
+ * This MUST be one of the following:\r
+ * \r
+ * MM_TEXT (= 0x0001):\r
+ * Each logical unit is mapped to one device pixel.\r
+ * Positive x is to the right; positive y is down.\r
+ * \r
+ * MM_LOMETRIC (= 0x0002):\r
+ * Each logical unit is mapped to 0.1 millimeter.\r
+ * Positive x is to the right; positive y is up.\r
+ *\r
+ * MM_HIMETRIC (= 0x0003):\r
+ * Each logical unit is mapped to 0.01 millimeter.\r
+ * Positive x is to the right; positive y is up.\r
+ *\r
+ * MM_LOENGLISH (= 0x0004):\r
+ * Each logical unit is mapped to 0.01 inch.\r
+ * Positive x is to the right; positive y is up.\r
+ * \r
+ * MM_HIENGLISH (= 0x0005):\r
+ * Each logical unit is mapped to 0.001 inch.\r
+ * Positive x is to the right; positive y is up.\r
+ * \r
+ * MM_TWIPS (= 0x0006):\r
+ * Each logical unit is mapped to one twentieth (1/20) of a point.\r
+ * In printing, a point is 1/72 of an inch; therefore, 1/20 of a point is 1/1440 of an inch.\r
+ * This unit is also known as a "twip".\r
+ * Positive x is to the right; positive y is up.\r
+ *\r
+ * MM_ISOTROPIC (= 0x0007):\r
+ * Logical units are mapped to arbitrary device units with equally scaled axes;\r
+ * that is, one unit along the x-axis is equal to one unit along the y-axis.\r
+ * The META_SETWINDOWEXT and META_SETVIEWPORTEXT records specify the units and the\r
+ * orientation of the axes.\r
+ * The processing application SHOULD make adjustments as necessary to ensure the x and y\r
+ * units remain the same size. For example, when the window extent is set, the viewport\r
+ * SHOULD be adjusted to keep the units isotropic.\r
+ *\r
+ * MM_ANISOTROPIC (= 0x0008):\r
+ * Logical units are mapped to arbitrary units with arbitrarily scaled axes.\r
+ */\r
+ int mapMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setMapMode;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ mapMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps\r
+ * logical fonts to physical fonts.\r
+ */\r
+public class WmfSetMapperFlags implements WmfRecord {\r
+ \r
+ /**\r
+ * A 32-bit unsigned integer that defines whether the font mapper should attempt to\r
+ * match a font's aspect ratio to the current device's aspect ratio. If bit 0 is\r
+ * set, the mapper selects only matching fonts.\r
+ */\r
+ long mapperValues;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setMapperFlags;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ mapperValues = leis.readUInt();\r
+ return LittleEndianConsts.INT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETROP2 record defines the foreground raster operation mix mode in the playback device\r
+ * context. The foreground mix mode is the mode for combining pens and interiors of filled objects with\r
+ * foreground colors on the output surface.\r
+ */\r
+public class WmfSetRop2 implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the foreground binary raster\r
+ * operation mixing mode. This MUST be one of the values:\r
+ * R2_BLACK = 0x0001,\r
+ * R2_NOTMERGEPEN = 0x0002,\r
+ * R2_MASKNOTPEN = 0x0003,\r
+ * R2_NOTCOPYPEN = 0x0004,\r
+ * R2_MASKPENNOT = 0x0005,\r
+ * R2_NOT = 0x0006,\r
+ * R2_XORPEN = 0x0007,\r
+ * R2_NOTMASKPEN = 0x0008,\r
+ * R2_MASKPEN = 0x0009,\r
+ * R2_NOTXORPEN = 0x000A,\r
+ * R2_NOP = 0x000B,\r
+ * R2_MERGENOTPEN = 0x000C,\r
+ * R2_COPYPEN = 0x000D,\r
+ * R2_MERGEPENNOT = 0x000E,\r
+ * R2_MERGEPEN = 0x000F,\r
+ * R2_WHITE = 0x0010\r
+ */\r
+ int drawMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setRop2;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ drawMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+/**\r
+ * The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device\r
+ * context.\r
+ */\r
+public class WmfSetStretchBltMode implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines bitmap stretching mode.\r
+ * This MUST be one of the values:\r
+ * BLACKONWHITE = 0x0001,\r
+ * WHITEONBLACK = 0x0002,\r
+ * COLORONCOLOR = 0x0003,\r
+ * HALFTONE = 0x0004\r
+ */\r
+ int setStretchBltMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setStretchBltMode;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ setStretchBltMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+public enum WmfTernaryRasterOp {\r
+ BLACKNESS(0x0000,0x0042,"0"),\r
+ DPSOON(0x0001,0x0289,"DPSoon"),\r
+ DPSONA(0x0002,0x0C89,"DPSona"),\r
+ PSON(0x0003,0x00AA,"PSon"),\r
+ SDPONA(0x0004,0x0C88,"SDPona"),\r
+ DPON(0x0005,0x00A9,"DPon"),\r
+ PDSXNON(0x0006,0x0865,"PDSxnon"),\r
+ PDSAON(0x0007,0x02C5,"PDSaon"),\r
+ SDPNAA(0x0008,0x0F08,"SDPnaa"),\r
+ PDSXON(0x0009,0x0245,"PDSxon"),\r
+ DPNA(0x000A,0x0329,"DPna"),\r
+ PSDNAON(0x000B,0x0B2A,"PSDnaon"),\r
+ SPNA(0x000C,0x0324,"SPna"),\r
+ PDSNAON(0x000D,0x0B25,"PDSnaon"),\r
+ PDSONON(0x000E,0x08A5,"PDSonon"),\r
+ PN(0x000F,0x0001,"Pn"),\r
+ PDSONA(0x0010,0x0C85,"PDSona"),\r
+ NOTSRCERASE(0x0011,0x00A6,"DSon"),\r
+ SDPXNON(0x0012,0x0868,"SDPxnon"),\r
+ SDPAON(0x0013,0x02C8,"SDPaon"),\r
+ DPSXNON(0x0014,0x0869,"DPSxnon"),\r
+ DPSAON(0x0015,0x02C9,"DPSaon"),\r
+ PSDPSANAXX(0x0016,0x5CCA,"PSDPSanaxx"),\r
+ SSPXDSXAXN(0x0017,0x1D54,"SSPxDSxaxn"),\r
+ SPXPDXA(0x0018,0x0D59,"SPxPDxa"),\r
+ SDPSANAXN(0x0019,0x1CC8,"SDPSanaxn"),\r
+ PDSPAOX(0x001A,0x06C5,"PDSPaox"),\r
+ SDPSXAXN(0x001B,0x0768,"SDPSxaxn"),\r
+ PSDPAOX(0x001C,0x06CA,"PSDPaox"),\r
+ DSPDXAXN(0x001D,0x0766,"DSPDxaxn"),\r
+ PDSOX(0x001E,0x01A5,"PDSox"),\r
+ PDSOAN(0x001F,0x0385,"PDSoan"),\r
+ DPSNAA(0x0020,0x0F09,"DPSnaa"),\r
+ SDPXON(0x0021,0x0248,"SDPxon"),\r
+ DSNA(0x0022,0x0326,"DSna"),\r
+ SPDNAON(0x0023,0x0B24,"SPDnaon"),\r
+ SPXDSXA(0x0024,0x0D55,"SPxDSxa"),\r
+ PDSPANAXN(0x0025,0x1CC5,"PDSPanaxn"),\r
+ SDPSAOX(0x0026,0x06C8,"SDPSaox"),\r
+ SDPSXNOX(0x0027,0x1868,"SDPSxnox"),\r
+ DPSXA(0x0028,0x0369,"DPSxa"),\r
+ PSDPSAOXXN(0x0029,0x16CA,"PSDPSaoxxn"),\r
+ DPSANA(0x002A,0x0CC9,"DPSana"),\r
+ SSPXPDXAXN(0x002B,0x1D58,"SSPxPDxaxn"),\r
+ SPDSOAX(0x002C,0x0784,"SPDSoax"),\r
+ PSDNOX(0x002D,0x060A,"PSDnox"),\r
+ PSDPXOX(0x002E,0x064A,"PSDPxox"),\r
+ PSDNOAN(0x002F,0x0E2A,"PSDnoan"),\r
+ PSNA(0x0030,0x032A,"PSna"),\r
+ SDPNAON(0x0031,0x0B28,"SDPnaon"),\r
+ SDPSOOX(0x0032,0x0688,"SDPSoox"),\r
+ NOTSRCCOPY(0x0033,0x0008,"Sn"),\r
+ SPDSAOX(0x0034,0x06C4,"SPDSaox"),\r
+ SPDSXNOX(0x0035,0x1864,"SPDSxnox"),\r
+ SDPOX(0x0036,0x01A8,"SDPox"),\r
+ SDPOAN(0x0037,0x0388,"SDPoan"),\r
+ PSDPOAX(0x0038,0x078A,"PSDPoax"),\r
+ SPDNOX(0x0390,0x604,"SPDnox"),\r
+ SPDSXOX(0x003A,0x0644,"SPDSxox"),\r
+ SPDNOAN(0x003B,0x0E24,"SPDnoan"),\r
+ PSX(0x003C,0x004A,"PSx"),\r
+ SPDSONOX(0x003D,0x18A4,"SPDSonox"),\r
+ SPDSNAOX(0x003E,0x1B24,"SPDSnaox"),\r
+ PSAN(0x003F,0x00EA,"PSan"),\r
+ PSDNAA(0x0040,0x0F0A,"PSDnaa"),\r
+ DPSXON(0x0041,0x0249,"DPSxon"),\r
+ SDXPDXA(0x0042,0x0D5D,"SDxPDxa"),\r
+ SPDSANAXN(0x0043,0x1CC4,"SPDSanaxn"),\r
+ SRCERASE(0x0044,0x0328,"SDna"),\r
+ DPSNAON(0x0045,0x0B29,"DPSnaon"),\r
+ DSPDAOX(0x0046,0x06C6,"DSPDaox"),\r
+ PSDPXAXN(0x0047,0x076A,"PSDPxaxn"),\r
+ SDPXA(0x0048,0x0368,"SDPxa"),\r
+ PDSPDAOXXN(0x0049,0x16C5,"PDSPDaoxxn"),\r
+ DPSDOAX(0x004A,0x0789,"DPSDoax"),\r
+ PDSNOX(0x004B,0x0605,"PDSnox"),\r
+ SDPANA(0x004C,0x0CC8,"SDPana"),\r
+ SSPXDSXOXN(0x004D,0x1954,"SSPxDSxoxn"),\r
+ PDSPXOX(0x004E,0x0645,"PDSPxox"),\r
+ PDSNOAN(0x004F,0x0E25,"PDSnoan"),\r
+ PDNA(0x0050,0x0325,"PDna"),\r
+ DSPNAON(0x0051,0x0B26,"DSPnaon"),\r
+ DPSDAOX(0x0052,0x06C9,"DPSDaox"),\r
+ SPDSXAXN(0x0053,0x0764,"SPDSxaxn"),\r
+ DPSONON(0x0054,0x08A9,"DPSonon"),\r
+ DSTINVERT(0x0055,0x0009,"Dn"),\r
+ DPSOX(0x0056,0x01A9,"DPSox"),\r
+ DPSOAN(0x0005,0x70389,"DPSoan"),\r
+ PDSPOAX(0x0058,0x0785,"PDSPoax"),\r
+ DPSNOX(0x0059,0x0609,"DPSnox"),\r
+ PATINVERT(0x005A,0x0049,"DPx"),\r
+ DPSDONOX(0x005B,0x18A9,"DPSDonox"),\r
+ DPSDXOX(0x005C,0x0649,"DPSDxox"),\r
+ DPSNOAN(0x005D,0x0E29,"DPSnoan"),\r
+ DPSDNAOX(0x005E,0x1B29,"DPSDnaox"),\r
+ DPAN(0x005F,0x00E9,"DPan"),\r
+ PDSXA(0x0060,0x0365,"PDSxa"),\r
+ DSPDSAOXXN(0x0061,0x16C6,"DSPDSaoxxn"),\r
+ DSPDOAX(0x0062,0x0786,"DSPDoax"),\r
+ SDPNOX(0x0063,0x0608,"SDPnox"),\r
+ SDPSOAX(0x0064,0x0788,"SDPSoax"),\r
+ DSPNOX(0x0065,0x0606,"DSPnox"),\r
+ SRCINVERT(0x0066,0x0046,"DSx"),\r
+ SDPSONOX(0x0067,0x18A8,"SDPSonox"),\r
+ DSPDSONOXXN(0x0068,0x58A6,"DSPDSonoxxn"),\r
+ PDSXXN(0x0069,0x0145,"PDSxxn"),\r
+ DPSAX(0x006A,0x01E9,"DPSax"),\r
+ PSDPSOAXXN(0x006B,0x178A,"PSDPSoaxxn"),\r
+ SDPAX(0x006C,0x01E8,"SDPax"),\r
+ PDSPDOAXXN(0x006D,0x1785,"PDSPDoaxxn"),\r
+ SDPSNOAX(0x006E,0x1E28,"SDPSnoax"),\r
+ // PDXNAN(0x006F,0x0C65,"PDXnan"), // invalid combo\r
+ PDSANA(0x0070,0x0CC5,"PDSana"),\r
+ SSDXPDXAXN(0x0071,0x1D5C,"SSDxPDxaxn"),\r
+ SDPSXOX(0x0072,0x0648,"SDPSxox"),\r
+ SDPNOAN(0x0073,0x0E28,"SDPnoan"),\r
+ DSPDXOX(0x0074,0x0646,"DSPDxox"),\r
+ DSPNOAN(0x0075,0x0E26,"DSPnoan"),\r
+ SDPSNAOX(0x0076,0x1B28,"SDPSnaox"),\r
+ DSAN(0x0077,0x00E6,"DSan"),\r
+ PDSAX(0x0078,0x01E5,"PDSax"),\r
+ DSPDSOAXXN(0x0079,0x1786,"DSPDSoaxxn"),\r
+ DPSDNOAX(0x007A,0x1E29,"DPSDnoax"),\r
+ SDPXNAN(0x007B,0x0C68,"SDPxnan"),\r
+ SPDSNOAX(0x007C,0x1E24,"SPDSnoax"),\r
+ DPSXNAN(0x007D,0x0C69,"DPSxnan"),\r
+ SPXDSXO(0x007E,0x0955,"SPxDSxo"),\r
+ DPSAAN(0x007F,0x03C9,"DPSaan"),\r
+ DPSAA(0x0080,0x03E9,"DPSaa"),\r
+ SPXDSXON(0x0081,0x0975,"SPxDSxon"),\r
+ DPSXNA(0x0082,0x0C49,"DPSxna"),\r
+ SPDSNOAXN(0x0083,0x1E04,"SPDSnoaxn"),\r
+ SDPXNA(0x0084,0x0C48,"SDPxna"),\r
+ PDSPNOAXN(0x0085,0x1E05,"PDSPnoaxn"),\r
+ DSPDSOAXX(0x0086,0x17A6,"DSPDSoaxx"),\r
+ PDSAXN(0x0087,0x01C5,"PDSaxn"),\r
+ SRCAND(0x0088,0x00C6,"DSa"),\r
+ SDPSNAOXN(0x0089,0x1B08,"SDPSnaoxn"),\r
+ DSPNOA(0x008A,0x0E06,"DSPnoa"),\r
+ DSPDXOXN(0x008B,0x0666,"DSPDxoxn"),\r
+ SDPNOA(0x008C,0x0E08,"SDPnoa"),\r
+ SDPSXOXN(0x008D,0x0668,"SDPSxoxn"),\r
+ SSDXPDXAX(0x008E,0x1D7C,"SSDxPDxax"),\r
+ PDSANAN(0x008F,0x0CE5,"PDSanan"),\r
+ PDSXNA(0x0090,0x0C45,"PDSxna"),\r
+ SDPSNOAXN(0x0091,0x1E08,"SDPSnoaxn"),\r
+ DPSDPOAXX(0x0092,0x17A9,"DPSDPoaxx"),\r
+ SPDAXN(0x0093,0x01C4,"SPDaxn"),\r
+ PSDPSOAXX(0x0094,0x17AA,"PSDPSoaxx"),\r
+ DPSAXN(0x0095,0x01C9,"DPSaxn"),\r
+ DPSXX(0x0096,0x0169,"DPSxx"),\r
+ PSDPSONOXX(0x0097,0x588A,"PSDPSonoxx"),\r
+ SDPSONOXN(0x0098,0x1888,"SDPSonoxn"),\r
+ DSXN(0x0099,0x0066,"DSxn"),\r
+ DPSNAX(0x009A,0x0709,"DPSnax"),\r
+ SDPSOAXN(0x009B,0x07A8,"SDPSoaxn"),\r
+ SPDNAX(0x009C,0x0704,"SPDnax"),\r
+ DSPDOAXN(0x009D,0x07A6,"DSPDoaxn"),\r
+ DSPDSAOXX(0x009E,0x16E6,"DSPDSaoxx"),\r
+ PDSXAN(0x009F,0x0345,"PDSxan"),\r
+ DPA(0x00A0,0x00C9,"DPa"),\r
+ PDSPNAOXN(0x00A1,0x1B05,"PDSPnaoxn"),\r
+ DPSNOA(0x00A2,0x0E09,"DPSnoa"),\r
+ DPSDXOXN(0x00A3,0x0669,"DPSDxoxn"),\r
+ PDSPONOXN(0x00A4,0x1885,"PDSPonoxn"),\r
+ PDXN(0x00A5,0x0065,"PDxn"),\r
+ DSPNAX(0x00A6,0x0706,"DSPnax"),\r
+ PDSPOAXN(0x00A7,0x07A5,"PDSPoaxn"),\r
+ DPSOA(0x00A8,0x03A9,"DPSoa"),\r
+ DPSOXN(0x00A9,0x0189,"DPSoxn"),\r
+ D(0x00AA,0x0029,"D"),\r
+ DPSONO(0x00AB,0x0889,"DPSono"),\r
+ SPDSXAX(0x00AC,0x0744,"SPDSxax"),\r
+ DPSDAOXN(0x00AD,0x06E9,"DPSDaoxn"),\r
+ DSPNAO(0x00AE,0x0B06,"DSPnao"),\r
+ DPNO(0x00AF,0x0229,"DPno"),\r
+ PDSNOA(0x00B0,0x0E05,"PDSnoa"),\r
+ PDSPXOXN(0x00B1,0x0665,"PDSPxoxn"),\r
+ SSPXDSXOX(0x00B2,0x1974,"SSPxDSxox"),\r
+ SDPANAN(0x00B3,0x0CE8,"SDPanan"),\r
+ PSDNAX(0x00B4,0x070A,"PSDnax"),\r
+ DPSDOAXN(0x00B5,0x07A9,"DPSDoaxn"),\r
+ DPSDPAOXX(0x00B6,0x16E9,"DPSDPaoxx"),\r
+ SDPXAN(0x00B7,0x0348,"SDPxan"),\r
+ PSDPXAX(0x00B8,0x074A,"PSDPxax"),\r
+ DSPDAOXN(0x00B9,0x06E6,"DSPDaoxn"),\r
+ DPSNAO(0x00BA,0x0B09,"DPSnao"),\r
+ MERGEPAINT(0x00BB,0x0226,"DSno"),\r
+ SPDSANAX(0x00BC,0x1CE4,"SPDSanax"),\r
+ SDXPDXAN(0x00BD,0x0D7D,"SDxPDxan"),\r
+ DPSXO(0x00BE,0x0269,"DPSxo"),\r
+ DPSANO(0x00BF,0x08C9,"DPSano"),\r
+ MERGECOPY(0x00C0,0x00CA,"PSa"),\r
+ SPDSNAOXN(0x00C1,0x1B04,"SPDSnaoxn"),\r
+ SPDSONOXN(0x00C2,0x1884,"SPDSonoxn"),\r
+ PSXN(0x00C3,0x006A,"PSxn"),\r
+ SPDNOA(0x00C4,0x0E04,"SPDnoa"),\r
+ SPDSXOXN(0x00C5,0x0664,"SPDSxoxn"),\r
+ SDPNAX(0x00C6,0x0708,"SDPnax"),\r
+ PSDPOAXN(0x00C7,0x07AA,"PSDPoaxn"),\r
+ SDPOA(0x00C8,0x03A8,"SDPoa"),\r
+ SPDOXN(0x00C9,0x0184,"SPDoxn"),\r
+ DPSDXAX(0x00CA,0x0749,"DPSDxax"),\r
+ SPDSAOXN(0x00CB,0x06E4,"SPDSaoxn"),\r
+ SRCCOPY(0x00CC,0x0020,"S"),\r
+ SDPONO(0x00CD,0x0888,"SDPono"),\r
+ SDPNAO(0x00CE,0x0B08,"SDPnao"),\r
+ SPNO(0x00CF,0x0224,"SPno"),\r
+ PSDNOA(0x00D0,0x0E0A,"PSDnoa"),\r
+ PSDPXOXN(0x00D1,0x066A,"PSDPxoxn"),\r
+ PDSNAX(0x00D2,0x0705,"PDSnax"),\r
+ SPDSOAXN(0x00D3,0x07A4,"SPDSoaxn"),\r
+ SSPXPDXAX(0x00D4,0x1D78,"SSPxPDxax"),\r
+ DPSANAN(0x00D5,0x0CE9,"DPSanan"),\r
+ PSDPSAOXX(0x00D6,0x16EA,"PSDPSaoxx"),\r
+ DPSXAN(0x00D7,0x0349,"DPSxan"),\r
+ PDSPXAX(0x00D8,0x0745,"PDSPxax"),\r
+ SDPSAOXN(0x00D9,0x06E8,"SDPSaoxn"),\r
+ DPSDANAX(0x00DA,0x1CE9,"DPSDanax"),\r
+ SPXDSXAN(0x00DB,0x0D75,"SPxDSxan"),\r
+ SPDNAO(0x00DC,0x0B04,"SPDnao"),\r
+ SDNO(0x00DD,0x0228,"SDno"),\r
+ SDPXO(0x00DE,0x0268,"SDPxo"),\r
+ SDPANO(0x00DF,0x08C8,"SDPano"),\r
+ PDSOA(0x00E0,0x03A5,"PDSoa"),\r
+ PDSOXN(0x00E1,0x0185,"PDSoxn"),\r
+ DSPDXAX(0x00E2,0x0746,"DSPDxax"),\r
+ PSDPAOXN(0x00E3,0x06EA,"PSDPaoxn"),\r
+ SDPSXAX(0x00E4,0x0748,"SDPSxax"),\r
+ PDSPAOXN(0x00E5,0x06E5,"PDSPaoxn"),\r
+ SDPSANAX(0x00E6,0x1CE8,"SDPSanax"),\r
+ SPXPDXAN(0x00E7,0x0D79,"SPxPDxan"),\r
+ SSPXDSXAX(0x00E8,0x1D74,"SSPxDSxax"),\r
+ DSPDSANAXXN(0x00E9,0x5CE6,"DSPDSanaxxn"),\r
+ DPSAO(0x00EA,0x02E9,"DPSao"),\r
+ DPSXNO(0x00EB,0x0849,"DPSxno"),\r
+ SDPAO(0x00EC,0x02E8,"SDPao"),\r
+ SDPXNO(0x00ED,0x0848,"SDPxno"),\r
+ SRCPAINT(0x00EE,0x0086,"DSo"),\r
+ SDPNOO(0x00EF,0x0A08,"SDPnoo"),\r
+ PATCOPY(0x00F0,0x0021,"P"),\r
+ PDSONO(0x00F1,0x0885,"PDSono"),\r
+ PDSNAO(0x00F2,0x0B05,"PDSnao"),\r
+ PSNO(0x00F3,0x022A,"PSno"),\r
+ PSDNAO(0x00F4,0x0B0A,"PSDnao"),\r
+ PDNO(0x00F5,0x0225,"PDno"),\r
+ PDSXO(0x00F6,0x0265,"PDSxo"),\r
+ PDSANO(0x00F7,0x08C5,"PDSano"),\r
+ PDSAO(0x00F8,0x02E5,"PDSao"),\r
+ PDSXNO(0x00F9,0x0845,"PDSxno"),\r
+ DPO(0x00FA,0x0089,"DPo"),\r
+ PATPAINT(0x00FB,0x0A09,"DPSnoo"),\r
+ PSO(0x00FC,0x008A,"PSo"),\r
+ PSDNOO(0x00FD,0x0A0A,"PSDnoo"),\r
+ DPSOO(0x00FE,0x02A9,"DPSoo"),\r
+ WHITENESS(0x00FF,0x0062,"1");\r
+ \r
+ int opIndex;\r
+ int opCode;\r
+ String opCmd;\r
+ \r
+ WmfTernaryRasterOp(int opIndex, int opCode, String opCmd) {\r
+ this.opIndex=opIndex;\r
+ this.opCode=opCode;\r
+ this.opCmd=opCmd;\r
+ }\r
+ \r
+ public static WmfTernaryRasterOp fromOpIndex(int opIndex) {\r
+ for (WmfTernaryRasterOp bb : WmfTernaryRasterOp.values()) {\r
+ if (bb.opIndex == opIndex) {\r
+ return bb;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+ \r
+ public String describeCmd() {\r
+ String stack[] = new String[10];\r
+ int stackPnt = 0;\r
+ \r
+ for (char c : opCmd.toCharArray()) {\r
+ switch (c) {\r
+ case 'S':\r
+ case 'D':\r
+ case 'P':\r
+ stack[stackPnt++] = ""+c;\r
+ break;\r
+ case 'n':\r
+ stack[stackPnt-1] = "not("+stack[stackPnt-1]+")";\r
+ break;\r
+ case 'a':\r
+ stack[stackPnt-2] = "("+stack[stackPnt-1]+" and "+stack[stackPnt-2]+")";\r
+ stackPnt--;\r
+ break;\r
+ case 'o':\r
+ stack[stackPnt-2] = "("+stack[stackPnt-1]+" or "+stack[stackPnt-2]+")";\r
+ stackPnt--;\r
+ break;\r
+ case 'x':\r
+ stack[stackPnt-2] = "("+stack[stackPnt-1]+" xor "+stack[stackPnt-2]+")";\r
+ stackPnt--;\r
+ break;\r
+ case '1':\r
+ stack[stackPnt++] = "all white";\r
+ break;\r
+ case '0':\r
+ stack[stackPnt++] = "all black";\r
+ break;\r
+ default:\r
+ throw new RuntimeException("unknown cmd '"+c+"'.");\r
+ }\r
+ }\r
+\r
+ return stack[--stackPnt];\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfText {\r
+\r
+ /**\r
+ * The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the \r
+ * playback device context. Spacing is added to the white space between each character, including\r
+ * break characters, when a line of justified text is output.\r
+ */\r
+ public static class WmfSetTextCharExtra implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines the amount of extra space, in\r
+ * logical units, to be added to each character. If the current mapping mode is not MM_TEXT,\r
+ * this value is transformed and rounded to the nearest pixel. For details about setting the\r
+ * mapping mode, see META_SETMAPMODE\r
+ */\r
+ int charExtra;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setTextCharExtra;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ charExtra = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_SETTEXTCOLOR record defines the text foreground color in the playback device context.\r
+ */\r
+ public static class WmfSetTextColor implements WmfRecord {\r
+ \r
+ WmfColorRef colorRef;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setTextColor;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ WmfColorRef colorRef = new WmfColorRef();\r
+ return colorRef.init(leis);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_SETTEXTJUSTIFICATION record defines the amount of space to add to break characters\r
+ * in a string of justified text.\r
+ */\r
+ public static class WmfSetTextJustification implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that specifies the number of space characters in the line.\r
+ */\r
+ int breakCount;\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that specifies the total extra space, in logical\r
+ * units, to be added to the line of text. If the current mapping mode is not MM_TEXT, the value\r
+ * identified by the BreakExtra member is transformed and rounded to the nearest pixel. For\r
+ * details about setting the mapping mode, see {@link WmfSetMapMode}.\r
+ */\r
+ int breakExtra;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setBkColor;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ breakCount = leis.readUShort();\r
+ breakExtra = leis.readUShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_TEXTOUT record outputs a character string at the specified location by using the font,\r
+ * background color, and text color that are defined in the playback device context.\r
+ */\r
+ public static class WmfTextOut implements WmfRecord {\r
+ /**\r
+ * A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String.\r
+ */\r
+ int stringLength;\r
+ /**\r
+ * The size of this field MUST be a multiple of two. If StringLength is an odd\r
+ * number, then this field MUST be of a size greater than or equal to StringLength + 1.\r
+ * A variable-length string that specifies the text to be drawn.\r
+ * The string does not need to be null-terminated, because StringLength specifies the\r
+ * length of the string.\r
+ * The string is written at the location specified by the XStart and YStart fields.\r
+ */\r
+ String text;\r
+ /**\r
+ * A 16-bit signed integer that defines the vertical (y-axis) coordinate, in logical\r
+ * units, of the point where drawing is to start.\r
+ */\r
+ int yStart;\r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal (x-axis) coordinate, in\r
+ * logical units, of the point where drawing is to start.\r
+ */\r
+ int xStart; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.textOut;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ stringLength = leis.readShort();\r
+ byte buf[] = new byte[stringLength+(stringLength%2)];\r
+ leis.readFully(buf);\r
+ text = new String(buf, "UTF16-LE").trim();\r
+ yStart = leis.readShort();\r
+ xStart = leis.readShort();\r
+ return 3*LittleEndianConsts.SHORT_SIZE+buf.length;\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * The META_EXTTEXTOUT record outputs text by using the font, background color, and text color that\r
+ * are defined in the playback device context. Optionally, dimensions can be provided for clipping,\r
+ * opaquing, or both.\r
+ */\r
+ public static class WmfExtTextOut implements WmfRecord {\r
+\r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, where the \r
+ text string is to be located.\r
+ */\r
+ int y; \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, where the \r
+ text string is to be located.\r
+ */\r
+ int x; \r
+ /**\r
+ * A 16-bit signed integer that defines the length of the string.\r
+ */\r
+ int stringLength;\r
+ /**\r
+ * A 16-bit unsigned integer that defines the use of the application-defined \r
+ * rectangle. This member can be a combination of one or more values in the \r
+ * ExtTextOutOptions Flags:\r
+ * \r
+ * ETO_OPAQUE (0x0002):\r
+ * Indicates that the background color that is defined in the playback device context \r
+ * SHOULD be used to fill the rectangle.\r
+ * \r
+ * ETO_CLIPPED (0x0004):\r
+ * Indicates that the text SHOULD be clipped to the rectangle.\r
+ * \r
+ * ETO_GLYPH_INDEX (0x0010):\r
+ * Indicates that the string to be output SHOULD NOT require further processing \r
+ * with respect to the placement of the characters, and an array of character \r
+ * placement values SHOULD be provided. This character placement process is \r
+ * useful for fonts in which diacritical characters affect character spacing.\r
+ * \r
+ * ETO_RTLREADING (0x0080):\r
+ * Indicates that the text MUST be laid out in right-to-left reading order, instead of \r
+ * the default left-to-right order. This SHOULD be applied only when the font that is \r
+ * defined in the playback device context is either Hebrew or Arabic. <37>\r
+ * \r
+ * ETO_NUMERICSLOCAL (0x0400):\r
+ * Indicates that to display numbers, digits appropriate to the locale SHOULD be \r
+ * used.\r
+ * \r
+ * ETO_NUMERICSLATIN (0x0800):\r
+ * Indicates that to display numbers, European digits SHOULD be used. <39>\r
+ * \r
+ * ETO_PDY (0x2000):\r
+ * Indicates that both horizontal and vertical character displacement values \r
+ * SHOULD be provided.\r
+ */\r
+ int fwOpts;\r
+ /**\r
+ * An optional 8-byte Rect Object (section 2.2.2.18) that defines the \r
+ * dimensions, in logical coordinates, of a rectangle that is used for clipping, opaquing, or both.\r
+ * \r
+ * The corners are given in the order left, top, right, bottom.\r
+ * Each value is a 16-bit signed integer that defines the coordinate, in logical coordinates, of \r
+ * the upper-left corner of the rectangle\r
+ */\r
+ int left,top,right,bottom;\r
+ /**\r
+ * A variable-length string that specifies the text to be drawn. The string does \r
+ * not need to be null-terminated, because StringLength specifies the length of the string. If \r
+ * the length is odd, an extra byte is placed after it so that the following member (optional Dx) is \r
+ * aligned on a 16-bit boundary.\r
+ */\r
+ String text;\r
+ /**\r
+ * An optional array of 16-bit signed integers that indicate the distance between \r
+ * origins of adjacent character cells. For example, Dx[i] logical units separate the origins of \r
+ * character cell i and character cell i + 1. If this field is present, there MUST be the same \r
+ * number of values as there are characters in the string.\r
+ */\r
+ int dx[];\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.extTextOut;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ stringLength = leis.readShort();\r
+ fwOpts = leis.readUShort();\r
+ left = leis.readShort();\r
+ top = leis.readShort();\r
+ right = leis.readShort();\r
+ bottom = leis.readShort();\r
+ \r
+ byte buf[] = new byte[stringLength+(stringLength%2)];\r
+ leis.readFully(buf);\r
+ text = new String(buf, "UTF16-LE");\r
+ \r
+ int size = 8*LittleEndianConsts.SHORT_SIZE+buf.length;\r
+ if (size < recordSize) {\r
+ dx = new int[text.length()];\r
+ for (int i=0; i<dx.length; i++) {\r
+ dx[i] = leis.readShort();\r
+ }\r
+ size += dx.length*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ \r
+ return size;\r
+ }\r
+ }\r
+ \r
+\r
+ \r
+ \r
+ /**\r
+ * The META_SETTEXTALIGN record defines text-alignment values in the playback device context.\r
+ */\r
+ public static class WmfSetTextAlign implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer that defines text alignment.\r
+ * This value MUST be a combination of one or more TextAlignmentMode Flags\r
+ * for text with a horizontal baseline, and VerticalTextAlignmentMode Flags\r
+ * for text with a vertical baseline.\r
+ * \r
+ * TextAlignmentMode Flags:\r
+ * TA_NOUPDATECP (0x0000):\r
+ * The drawing position in the playback device context MUST NOT be updated after each\r
+ * text output call. The reference point MUST be passed to the text output function.\r
+ * \r
+ * TA_LEFT (0x0000):\r
+ * The reference point MUST be on the left edge of the bounding rectangle.\r
+ * \r
+ * TA_TOP (0x0000):\r
+ * The reference point MUST be on the top edge of the bounding rectangle.\r
+ * \r
+ * TA_UPDATECP (0x0001):\r
+ * The drawing position in the playback device context MUST be updated after each text\r
+ * output call. It MUST be used as the reference point.\r
+ * \r
+ * TA_RIGHT (0x0002):\r
+ * The reference point MUST be on the right edge of the bounding rectangle.\r
+ * \r
+ * TA_CENTER (0x0006):\r
+ * The reference point MUST be aligned horizontally with the center of the bounding\r
+ * rectangle.\r
+ * \r
+ * TA_BOTTOM (0x0008):\r
+ * The reference point MUST be on the bottom edge of the bounding rectangle.\r
+ * \r
+ * TA_BASELINE (0x0018):\r
+ * The reference point MUST be on the baseline of the text.\r
+ * \r
+ * TA_RTLREADING (0x0100):\r
+ * The text MUST be laid out in right-to-left reading order, instead of the default\r
+ * left-toright order. This SHOULD be applied only when the font that is defined in the\r
+ * playback device context is either Hebrew or Arabic.\r
+ * \r
+ * \r
+ * VerticalTextAlignmentMode Flags (e.g. for Kanji fonts)\r
+ * VTA_TOP (0x0000):\r
+ * The reference point MUST be on the top edge of the bounding rectangle.\r
+ * \r
+ * VTA_RIGHT (0x0000):\r
+ * The reference point MUST be on the right edge of the bounding rectangle.\r
+ * \r
+ * VTA_BOTTOM (0x0002):\r
+ * The reference point MUST be on the bottom edge of the bounding rectangle.\r
+ * \r
+ * VTA_CENTER (0x0006):\r
+ * The reference point MUST be aligned vertically with the center of the bounding\r
+ * rectangle.\r
+ * \r
+ * VTA_LEFT (0x0008):\r
+ * The reference point MUST be on the left edge of the bounding rectangle.\r
+ * \r
+ * VTA_BASELINE (0x0018):\r
+ * The reference point MUST be on the baseline of the text.\r
+ */\r
+ int textAlignmentMode;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setTextAlign;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ textAlignmentMode = leis.readUShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package org.apache.poi.hwmf.record;\r
+\r
+import java.io.IOException;\r
+\r
+import org.apache.poi.util.LittleEndianConsts;\r
+import org.apache.poi.util.LittleEndianInputStream;\r
+\r
+public class WmfWindowing {\r
+ \r
+ /**\r
+ * The META_OFFSETCLIPRGN record moves the clipping region in the playback device context by the\r
+ * specified offsets.\r
+ */\r
+ public static class WmfOffsetClipRgn implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the number of logical units to move up or down.\r
+ */\r
+ int yOffset;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the number of logical units to move left or right. \r
+ */\r
+ int xOffset;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.offsetClipRgn;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yOffset = leis.readShort();\r
+ xOffset = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+ \r
+ \r
+ /**\r
+ * The META_SETVIEWPORTORG record defines the viewport origin in the playback device context.\r
+ */\r
+ public static class WmfSetViewportOrg implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical offset, in device units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal offset, in device units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setViewportOrg;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_SETVIEWPORTEXT record sets the horizontal and vertical extents\r
+ * of the viewport in the playback device context.\r
+ */\r
+ public static class WmfSetViewportExt implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical extent\r
+ * of the viewport in device units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal extent\r
+ * of the viewport in device units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setViewportExt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_OFFSETVIEWPORTORG record moves the viewport origin in the playback device context\r
+ * by specified horizontal and vertical offsets.\r
+ */\r
+ public static class WmfOffsetViewportOrg implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical offset, in device units.\r
+ */\r
+ int yOffset;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal offset, in device units.\r
+ */\r
+ int xOffset;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.offsetViewportOrg;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yOffset = leis.readShort();\r
+ xOffset = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_SETWINDOWORG record defines the output window origin in the playback device context.\r
+ */\r
+ public static class WmfSetWindowOrg implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setWindowOrg;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_SETWINDOWEXT record defines the horizontal and vertical extents\r
+ * of the output window in the playback device context.\r
+ */\r
+ public static class WmfSetWindowExt implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical extent of\r
+ * the window in logical units.\r
+ */\r
+ int y;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal extent of\r
+ * the window in logical units.\r
+ */\r
+ int x;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.setWindowExt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ y = leis.readShort();\r
+ x = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_OFFSETWINDOWORG record moves the output window origin in the\r
+ * playback device context by specified horizontal and vertical offsets.\r
+ */\r
+ public static class WmfOffsetWindowOrg implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the vertical offset, in device units.\r
+ */\r
+ int yOffset;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the horizontal offset, in device units.\r
+ */\r
+ int xOffset;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.offsetWindowOrg;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yOffset = leis.readShort();\r
+ xOffset = leis.readShort();\r
+ return 2*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_OFFSETWINDOWORG record moves the output window origin in the\r
+ * playback device context by specified horizontal and vertical offsets.\r
+ */\r
+ public static class WmfScaleWindowExt implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to divide the\r
+ * result of multiplying the current y-extent by the value of the yNum member.\r
+ */\r
+ int yDenom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to multiply the\r
+ * current y-extent.\r
+ */\r
+ int yNum;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to divide the\r
+ * result of multiplying the current x-extent by the value of the xNum member.\r
+ */\r
+ int xDenom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to multiply the\r
+ * current x-extent.\r
+ */\r
+ int xNum; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.scaleWindowExt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yDenom = leis.readShort();\r
+ yNum = leis.readShort();\r
+ xDenom = leis.readShort();\r
+ xNum = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The META_SCALEVIEWPORTEXT record scales the horizontal and vertical extents of the viewport\r
+ * that is defined in the playback device context by using the ratios formed by the specified\r
+ * multiplicands and divisors.\r
+ */\r
+ public static class WmfScaleViewportExt implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to divide the\r
+ * result of multiplying the current y-extent by the value of the yNum member.\r
+ */\r
+ int yDenom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to multiply the\r
+ * current y-extent.\r
+ */\r
+ int yNum;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to divide the\r
+ * result of multiplying the current x-extent by the value of the xNum member.\r
+ */\r
+ int xDenom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the amount by which to multiply the\r
+ * current x-extent.\r
+ */\r
+ int xNum; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.scaleViewportExt;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ yDenom = leis.readShort();\r
+ yNum = leis.readShort();\r
+ xDenom = leis.readShort();\r
+ xNum = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_EXCLUDECLIPRECT record sets the clipping region in the playback device context to the\r
+ * existing clipping region minus the specified rectangle.\r
+ */\r
+ public static class WmfExcludeClipRect implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * lower-right corner of the rectangle.\r
+ */\r
+ int bottom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * lower-right corner of the rectangle.\r
+ */\r
+ int right;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int top;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int left; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.excludeClipRect;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ bottom = leis.readShort();\r
+ right = leis.readShort();\r
+ top = leis.readShort();\r
+ left = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * The META_INTERSECTCLIPRECT record sets the clipping region in the playback device context to the\r
+ * intersection of the existing clipping region and the specified rectangle.\r
+ */\r
+ public static class WmfIntersectClipRect implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * lower-right corner of the rectangle.\r
+ */\r
+ int bottom;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * lower-right corner of the rectangle.\r
+ */\r
+ int right;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the y-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int top;\r
+ \r
+ /**\r
+ * A 16-bit signed integer that defines the x-coordinate, in logical units, of the\r
+ * upper-left corner of the rectangle.\r
+ */\r
+ int left; \r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.intersectClipRect;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ bottom = leis.readShort();\r
+ right = leis.readShort();\r
+ top = leis.readShort();\r
+ left = leis.readShort();\r
+ return 4*LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * The META_INTERSECTCLIPRECT record sets the clipping region in the playback device context to the\r
+ * intersection of the existing clipping region and the specified rectangle.\r
+ */\r
+ public static class WmfSelectClipRegion implements WmfRecord {\r
+ \r
+ /**\r
+ * A 16-bit unsigned integer used to index into the WMF Object Table to get\r
+ * the region to be clipped.\r
+ */\r
+ int region;\r
+ \r
+ public WmfRecordType getRecordType() {\r
+ return WmfRecordType.selectClipRegion;\r
+ }\r
+ \r
+ public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {\r
+ region = leis.readShort();\r
+ return LittleEndianConsts.SHORT_SIZE;\r
+ }\r
+ }\r
+\r
+}\r