git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1721078 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_14_FINAL
@@ -0,0 +1,105 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.awt.image.BufferedImage; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.IOException; | |||
import javax.imageio.stream.ImageInputStream; | |||
import javax.imageio.stream.MemoryCacheImageInputStream; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfBitmap16 { | |||
final boolean isPartial; | |||
int type; | |||
int width; | |||
int height; | |||
int widthBytes; | |||
int planes; | |||
int bitsPixel; | |||
public HwmfBitmap16() { | |||
this(false); | |||
} | |||
public HwmfBitmap16(boolean isPartial) { | |||
this.isPartial = isPartial; | |||
} | |||
public int init(LittleEndianInputStream leis) throws IOException { | |||
// A 16-bit signed integer that defines the bitmap type. | |||
type = leis.readShort(); | |||
// A 16-bit signed integer that defines the width of the bitmap in pixels. | |||
width = leis.readShort(); | |||
// A 16-bit signed integer that defines the height of the bitmap in scan lines. | |||
height = leis.readShort(); | |||
// A 16-bit signed integer that defines the number of bytes per scan line. | |||
widthBytes = leis.readShort(); | |||
// An 8-bit unsigned integer that defines the number of color planes in the | |||
// bitmap. The value of this field MUST be 0x01. | |||
planes = leis.readUByte(); | |||
// An 8-bit unsigned integer that defines the number of adjacent color bits on | |||
// each plane. | |||
bitsPixel = leis.readUByte(); | |||
int size = 2*LittleEndianConsts.BYTE_SIZE+4*LittleEndianConsts.SHORT_SIZE; | |||
if (isPartial) { | |||
// Bits (4 bytes): This field MUST be ignored. | |||
long skipSize = leis.skip(LittleEndianConsts.INT_SIZE); | |||
assert(skipSize == LittleEndianConsts.INT_SIZE); | |||
// Reserved (18 bytes): This field MUST be ignored. | |||
skipSize = leis.skip(18); | |||
assert(skipSize == 18); | |||
size += 18+LittleEndianConsts.INT_SIZE; | |||
} | |||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); | |||
int size2 = 0; | |||
byte buf[] = new byte[widthBytes]; | |||
for (int h=0; h<height; h++) { | |||
leis.read(buf); | |||
size2 += widthBytes; | |||
ImageInputStream iis = new MemoryCacheImageInputStream(new ByteArrayInputStream(buf)); | |||
for (int w=0; w<width; w++) { | |||
long bitsAtPixel = iis.readBits(bitsPixel); | |||
// TODO: is bitsPixel a multiple of 3 (r,g,b) | |||
// which colortable should be used for the various bit sizes??? | |||
} | |||
} | |||
int bytes = (((width * bitsPixel + 15) >> 4) << 1) * height; | |||
assert (bytes == size2); | |||
size += size2; | |||
return size; | |||
} | |||
} |
@@ -0,0 +1,441 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.awt.Color; | |||
import java.awt.image.BufferedImage; | |||
import java.awt.image.IndexColorModel; | |||
import java.awt.image.WritableRaster; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
/** | |||
* The DeviceIndependentBitmap Object defines an image in device-independent bitmap (DIB) format. | |||
*/ | |||
public class HwmfBitmapDib { | |||
public static enum BitCount { | |||
/** | |||
* The image SHOULD be in either JPEG or PNG format. <6> Neither of these formats includes | |||
* a color table, so this value specifies that no color table is present. See [JFIF] and [RFC2083] | |||
* for more information concerning JPEG and PNG compression formats. | |||
*/ | |||
BI_BITCOUNT_0(0x0000), | |||
/** | |||
* Each pixel in the bitmap is represented by a single bit. If the bit is clear, the pixel is displayed | |||
* with the color of the first entry in the color table; if the bit is set, the pixel has the color of the | |||
* second entry in the table. | |||
*/ | |||
BI_BITCOUNT_1(0x0001), | |||
/** | |||
* Each pixel in the bitmap is represented by a 4-bit index into the color table, and each byte | |||
* contains 2 pixels. | |||
*/ | |||
BI_BITCOUNT_2(0x0004), | |||
/** | |||
* Each pixel in the bitmap is represented by an 8-bit index into the color table, and each byte | |||
* contains 1 pixel. | |||
*/ | |||
BI_BITCOUNT_3(0x0008), | |||
/** | |||
* Each pixel in the bitmap is represented by a 16-bit value. | |||
* <br/> | |||
* If the Compression field of the BitmapInfoHeader Object is BI_RGB, the Colors field of DIB | |||
* is NULL. Each WORD in the bitmap array represents a single pixel. The relative intensities of | |||
* red, green, and blue are represented with 5 bits for each color component. The value for blue | |||
* is in the least significant 5 bits, followed by 5 bits each for green and red. The most significant | |||
* bit is not used. The color table is used for optimizing colors on palette-based devices, and | |||
* contains the number of entries specified by the ColorUsed field of the BitmapInfoHeader | |||
* Object. | |||
* <br/> | |||
* If the Compression field of the BitmapInfoHeader Object is BI_BITFIELDS, the Colors field | |||
* contains three DWORD color masks that specify the red, green, and blue components, | |||
* respectively, of each pixel. Each WORD in the bitmap array represents a single pixel. | |||
* <br/> | |||
* When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask MUST be | |||
* contiguous and SHOULD NOT overlap the bits of another mask. | |||
*/ | |||
BI_BITCOUNT_4(0x0010), | |||
/** | |||
* The bitmap has a maximum of 2^24 colors, and the Colors field of DIB is | |||
* NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green, | |||
* and red, respectively, for a pixel. The Colors color table is used for optimizing colors used on | |||
* palette-based devices, and MUST contain the number of entries specified by the ColorUsed | |||
* field of the BitmapInfoHeader Object. | |||
*/ | |||
BI_BITCOUNT_5(0x0018), | |||
/** | |||
* The bitmap has a maximum of 2^24 colors. | |||
* <br/> | |||
* If the Compression field of the BitmapInfoHeader Object is set to BI_RGB, the Colors field | |||
* of DIB is set to NULL. Each DWORD in the bitmap array represents the relative intensities of | |||
* blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. The | |||
* Colors color table is used for optimizing colors used on palette-based devices, and MUST | |||
* contain the number of entries specified by the ColorUsed field of the BitmapInfoHeader | |||
* Object. | |||
* <br/> | |||
* If the Compression field of the BitmapInfoHeader Object is set to BI_BITFIELDS, the Colors | |||
* field contains three DWORD color masks that specify the red, green, and blue components, | |||
* respectively, of each pixel. Each DWORD in the bitmap array represents a single pixel. | |||
* <br/> | |||
* When the Compression field is set to BI_BITFIELDS, bits set in each DWORD mask must be | |||
* contiguous and should not overlap the bits of another mask. All the bits in the pixel do not | |||
* need to be used. | |||
*/ | |||
BI_BITCOUNT_6(0x0020); | |||
int flag; | |||
BitCount(int flag) { | |||
this.flag = flag; | |||
} | |||
static BitCount valueOf(int flag) { | |||
for (BitCount bc : values()) { | |||
if (bc.flag == flag) return bc; | |||
} | |||
return null; | |||
} | |||
} | |||
public static enum Compression { | |||
/** | |||
* The bitmap is in uncompressed red green blue (RGB) format that is not compressed | |||
* and does not use color masks. | |||
*/ | |||
BI_RGB(0x0000), | |||
/** | |||
* An RGB format that uses run-length encoding (RLE) compression for bitmaps | |||
* with 8 bits per pixel. The compression uses a 2-byte format consisting of a count byte | |||
* followed by a byte containing a color index. | |||
*/ | |||
BI_RLE8(0x0001), | |||
/** | |||
* An RGB format that uses RLE compression for bitmaps with 4 bits per pixel. The | |||
* compression uses a 2-byte format consisting of a count byte followed by two word-length | |||
* color indexes. | |||
*/ | |||
BI_RLE4(0x0002), | |||
/** | |||
* The bitmap is not compressed and the color table consists of three DWORD | |||
* color masks that specify the red, green, and blue components, respectively, of each pixel. | |||
* This is valid when used with 16 and 32-bits per pixel bitmaps. | |||
*/ | |||
BI_BITFIELDS(0x0003), | |||
/** | |||
* The image is a JPEG image, as specified in [JFIF]. This value SHOULD only be used in | |||
* certain bitmap operations, such as JPEG pass-through. The application MUST query for the | |||
* pass-through support, since not all devices support JPEG pass-through. Using non-RGB | |||
* bitmaps MAY limit the portability of the metafile to other devices. For instance, display device | |||
* contexts generally do not support this pass-through. | |||
*/ | |||
BI_JPEG(0x0004), | |||
/** | |||
* The image is a PNG image, as specified in [RFC2083]. This value SHOULD only be | |||
* used certain bitmap operations, such as JPEG/PNG pass-through. The application MUST query | |||
* for the pass-through support, because not all devices support JPEG/PNG pass-through. Using | |||
* non-RGB bitmaps MAY limit the portability of the metafile to other devices. For instance, | |||
* display device contexts generally do not support this pass-through. | |||
*/ | |||
BI_PNG(0x0005), | |||
/** | |||
* The image is an uncompressed CMYK format. | |||
*/ | |||
BI_CMYK(0x000B), | |||
/** | |||
* A CMYK format that uses RLE compression for bitmaps with 8 bits per pixel. | |||
* The compression uses a 2-byte format consisting of a count byte followed by a byte containing | |||
* a color index. | |||
*/ | |||
BI_CMYKRLE8(0x000C), | |||
/** | |||
* A CMYK format that uses RLE compression for bitmaps with 4 bits per pixel. | |||
* The compression uses a 2-byte format consisting of a count byte followed by two word-length | |||
* color indexes. | |||
*/ | |||
BI_CMYKRLE4(0x000D); | |||
int flag; | |||
Compression(int flag) { | |||
this.flag = flag; | |||
} | |||
static Compression valueOf(int flag) { | |||
for (Compression c : values()) { | |||
if (c.flag == flag) return c; | |||
} | |||
return null; | |||
} | |||
} | |||
int headerSize; | |||
int headerWidth; | |||
int headerHeight; | |||
int headerPlanes; | |||
BitCount headerBitCount; | |||
Compression headerCompression; | |||
long headerImageSize = -1; | |||
int headerXPelsPerMeter = -1; | |||
int headerYPelsPerMeter = -1; | |||
long headerColorUsed = -1; | |||
long headerColorImportant = -1; | |||
Color colorTable[]; | |||
int colorMaskRed=0,colorMaskGreen=0,colorMaskBlue=0; | |||
public int init(LittleEndianInputStream leis) throws IOException { | |||
int size = 0; | |||
size += readHeader(leis); | |||
size += readColors(leis); | |||
int size2; | |||
switch (headerBitCount) { | |||
default: | |||
case BI_BITCOUNT_0: | |||
throw new RuntimeException("JPG and PNG formats aren't supported yet."); | |||
case BI_BITCOUNT_1: | |||
case BI_BITCOUNT_2: | |||
case BI_BITCOUNT_3: | |||
size2 = readBitmapIndexed(leis); | |||
break; | |||
case BI_BITCOUNT_4: | |||
case BI_BITCOUNT_5: | |||
case BI_BITCOUNT_6: | |||
size2 = readBitmapDirect(leis); | |||
break; | |||
} | |||
assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == size2); | |||
assert ( headerSize == 0x0C || headerImageSize == size2 ); | |||
size += size2; | |||
return size; | |||
} | |||
protected int readHeader(LittleEndianInputStream leis) throws IOException { | |||
int size = 0; | |||
/** | |||
* DIBHeaderInfo (variable): Either a BitmapCoreHeader Object or a | |||
* BitmapInfoHeader Object that specifies information about the image. | |||
* | |||
* The first 32 bits of this field is the HeaderSize value. | |||
* If it is 0x0000000C, then this is a BitmapCoreHeader; otherwise, this is a BitmapInfoHeader. | |||
*/ | |||
headerSize = leis.readInt(); | |||
size += LittleEndianConsts.INT_SIZE; | |||
// BitmapCoreHeader | |||
// A 16-bit unsigned integer that defines the width of the DIB, in pixels. | |||
headerWidth = leis.readUShort(); | |||
// A 16-bit unsigned integer that defines the height of the DIB, in pixels. | |||
headerHeight = leis.readUShort(); | |||
// A 16-bit unsigned integer that defines the number of planes for the target | |||
// device. This value MUST be 0x0001. | |||
headerPlanes = leis.readUShort(); | |||
// A 16-bit unsigned integer that defines the format of each pixel, and the | |||
// maximum number of colors in the DIB. | |||
headerBitCount = BitCount.valueOf(leis.readUShort()); | |||
size += 4*LittleEndianConsts.SHORT_SIZE; | |||
if (headerSize > 0x0C) { | |||
// BitmapInfoHeader | |||
// A 32-bit unsigned integer that defines the compression mode of the | |||
// DIB. | |||
// This value MUST NOT specify a compressed format if the DIB is a top-down bitmap, | |||
// as indicated by the Height value. | |||
headerCompression = Compression.valueOf((int)leis.readUInt()); | |||
// A 32-bit unsigned integer that defines the size, in bytes, of the image. | |||
// If the Compression value is BI_RGB, this value SHOULD be zero and MUST be ignored. | |||
// If the Compression value is BI_JPEG or BI_PNG, this value MUST specify the size of the JPEG | |||
// or PNG image buffer, respectively. | |||
headerImageSize = leis.readUInt(); | |||
// A 32-bit signed integer that defines the horizontal resolution, | |||
// in pixels-per-meter, of the target device for the DIB. | |||
headerXPelsPerMeter = leis.readInt(); | |||
// A 32-bit signed integer that defines the vertical resolution, | |||
headerYPelsPerMeter = leis.readInt(); | |||
// A 32-bit unsigned integer that specifies the number of indexes in the | |||
// color table used by the DIB | |||
// in pixelsper-meter, of the target device for the DIB. | |||
headerColorUsed = leis.readUInt(); | |||
// A 32-bit unsigned integer that defines the number of color indexes that are | |||
// required for displaying the DIB. If this value is zero, all color indexes are required. | |||
headerColorImportant = leis.readUInt(); | |||
size += 6*LittleEndianConsts.INT_SIZE; | |||
} | |||
return size; | |||
} | |||
protected int readColors(LittleEndianInputStream leis) throws IOException { | |||
switch (headerBitCount) { | |||
default: | |||
case BI_BITCOUNT_0: | |||
// no table | |||
return 0; | |||
case BI_BITCOUNT_1: | |||
// 2 colors | |||
return readRGBQuad(leis, 2); | |||
case BI_BITCOUNT_2: | |||
// 16 colors | |||
return readRGBQuad(leis, 16); | |||
case BI_BITCOUNT_3: | |||
// 256 colors | |||
return readRGBQuad(leis, 256); | |||
case BI_BITCOUNT_5: | |||
colorMaskRed=0xFF; | |||
colorMaskGreen=0xFF; | |||
colorMaskBlue=0xFF; | |||
return 0; | |||
case BI_BITCOUNT_4: | |||
if (headerCompression == Compression.BI_RGB) { | |||
colorMaskBlue = 0x1F; | |||
colorMaskGreen = 0x1F<<5; | |||
colorMaskRed = 0x1F<<10; | |||
return 0; | |||
} else { | |||
assert(headerCompression == Compression.BI_BITFIELDS); | |||
colorMaskBlue = leis.readInt(); | |||
colorMaskGreen = leis.readInt(); | |||
colorMaskRed = leis.readInt(); | |||
return 3*LittleEndianConsts.INT_SIZE; | |||
} | |||
case BI_BITCOUNT_6: | |||
if (headerCompression == Compression.BI_RGB) { | |||
colorMaskBlue = colorMaskGreen = colorMaskRed = 0xFF; | |||
return 0; | |||
} else { | |||
assert(headerCompression == Compression.BI_BITFIELDS); | |||
colorMaskBlue = leis.readInt(); | |||
colorMaskGreen = leis.readInt(); | |||
colorMaskRed = leis.readInt(); | |||
return 3*LittleEndianConsts.INT_SIZE; | |||
} | |||
} | |||
} | |||
protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException { | |||
int size = 0; | |||
List<Color> colorList = new ArrayList<Color>(); | |||
for (int i=0; i<count; i++) { | |||
int blue = leis.readUByte(); | |||
int green = leis.readUByte(); | |||
int red = leis.readUByte(); | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readUByte(); | |||
Color c = new Color(red, green, blue); | |||
colorList.add(c); | |||
size += 4 * LittleEndianConsts.BYTE_SIZE; | |||
} | |||
colorTable = colorList.toArray(new Color[colorList.size()]); | |||
return size; | |||
} | |||
protected int readBitmapIndexed(LittleEndianInputStream leis) throws IOException { | |||
assert(colorTable != null); | |||
byte r[] = new byte[colorTable.length]; | |||
byte g[] = new byte[colorTable.length]; | |||
byte b[] = new byte[colorTable.length]; | |||
for (int i=0; i<colorTable.length; i++) { | |||
r[i] = (byte)colorTable[i].getRed(); | |||
g[i] = (byte)colorTable[i].getGreen(); | |||
b[i] = (byte)colorTable[i].getBlue(); | |||
} | |||
int bits = 32-Integer.numberOfLeadingZeros(colorTable.length); | |||
IndexColorModel cm = new IndexColorModel(bits,colorTable.length,r,g,b); | |||
BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_BYTE_INDEXED, cm); | |||
WritableRaster wr = bi.getRaster(); | |||
int pixelCount = headerWidth*headerHeight; | |||
int size = 0; | |||
for (int pixel=0; pixel<pixelCount; size++) { | |||
int v = leis.readUByte(); | |||
switch (headerBitCount) { | |||
default: | |||
throw new RuntimeException("invalid bitcount for indexed image"); | |||
case BI_BITCOUNT_1: | |||
for (int j=0; j<8 && pixel<pixelCount; j++,pixel++) { | |||
wr.setSample(pixel/headerWidth,pixel%headerWidth,0,(v>>(7-j))&1); | |||
} | |||
break; | |||
case BI_BITCOUNT_2: | |||
wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, (v>>4)&15); | |||
pixel++; | |||
if (pixel<pixelCount) { | |||
wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v&15); | |||
pixel++; | |||
} | |||
break; | |||
case BI_BITCOUNT_3: | |||
wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v); | |||
pixel++; | |||
break; | |||
} | |||
} | |||
return size; | |||
} | |||
protected int readBitmapDirect(LittleEndianInputStream leis) throws IOException { | |||
assert(colorTable == null); | |||
BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_INT_RGB); | |||
WritableRaster wr = bi.getRaster(); | |||
int bitShiftRed=0,bitShiftGreen=0,bitShiftBlue=0; | |||
if (headerCompression == Compression.BI_BITFIELDS) { | |||
bitShiftGreen = 32-Integer.numberOfLeadingZeros(this.colorMaskBlue); | |||
bitShiftRed = 32-Integer.numberOfLeadingZeros(this.colorMaskGreen); | |||
} | |||
int pixelCount = headerWidth*headerHeight; | |||
int size = 0; | |||
int rgb[] = new int[3]; | |||
for (int pixel=0; pixel<pixelCount; pixel++) { | |||
int v; | |||
switch (headerBitCount) { | |||
default: | |||
throw new RuntimeException("invalid bitcount for indexed image"); | |||
case BI_BITCOUNT_4: | |||
v = leis.readUShort(); | |||
rgb[0] = (v & colorMaskRed) >> bitShiftRed; | |||
rgb[1] = (v & colorMaskGreen) >> bitShiftGreen; | |||
rgb[2] = (v & colorMaskBlue) >> bitShiftBlue; | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
break; | |||
case BI_BITCOUNT_5: | |||
rgb[2] = leis.readUByte(); | |||
rgb[1] = leis.readUByte(); | |||
rgb[0] = leis.readUByte(); | |||
size += 3*LittleEndianConsts.BYTE_SIZE; | |||
break; | |||
case BI_BITCOUNT_6: | |||
v = leis.readInt(); | |||
rgb[0] = (v & colorMaskRed) >> bitShiftRed; | |||
rgb[1] = (v & colorMaskGreen) >> bitShiftGreen; | |||
rgb[2] = (v & colorMaskBlue) >> bitShiftBlue; | |||
size += LittleEndianConsts.INT_SIZE; | |||
break; | |||
} | |||
wr.setPixel(pixel/headerWidth,pixel%headerWidth,rgb); | |||
} | |||
return size; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
/** | |||
* A 16-bit unsigned integer that defines the brush style. The legal values for this | |||
* field are defined as follows: if the value is not BS_PATTERN, BS_DIBPATTERNPT MUST be | |||
* assumed. | |||
*/ | |||
public enum HwmfBrushStyle { | |||
/** | |||
* A brush that paints a single, constant color, either solid or dithered. | |||
*/ | |||
BS_SOLID(0x0000), | |||
/** | |||
* A brush that does nothing. Using a BS_NULL brush in a graphics operation | |||
* MUST have the same effect as using no brush at all. | |||
*/ | |||
BS_NULL(0x0001), | |||
/** | |||
* A brush that paints a predefined simple pattern, or "hatch", onto a solid background. | |||
*/ | |||
BS_HATCHED(0x0002), | |||
/** | |||
* A brush that paints a pattern defined by a bitmap, which MAY be a Bitmap16 | |||
* Object or a DeviceIndependentBitmap (DIB) Object. | |||
*/ | |||
BS_PATTERN(0x0003), | |||
/** | |||
* Not supported | |||
*/ | |||
BS_INDEXED(0x0004), | |||
/** | |||
* A pattern brush specified by a DIB. | |||
*/ | |||
BS_DIBPATTERN(0x0005), | |||
/** | |||
* A pattern brush specified by a DIB. | |||
*/ | |||
BS_DIBPATTERNPT(0x0006), | |||
/** | |||
* Not supported | |||
*/ | |||
BS_PATTERN8X8(0x0007), | |||
/** | |||
* Not supported | |||
*/ | |||
BS_DIBPATTERN8X8(0x0008), | |||
/** | |||
* Not supported | |||
*/ | |||
BS_MONOPATTERN(0x0009); | |||
int flag; | |||
HwmfBrushStyle(int flag) { | |||
this.flag = flag; | |||
} | |||
static HwmfBrushStyle valueOf(int flag) { | |||
for (HwmfBrushStyle bs : values()) { | |||
if (bs.flag == flag) return bs; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.awt.Color; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfColorRef { | |||
/** | |||
* A 32-bit ColorRef Object that defines the color value. | |||
* Red (1 byte): An 8-bit unsigned integer that defines the relative intensity of red. | |||
* Green (1 byte): An 8-bit unsigned integer that defines the relative intensity of green. | |||
* Blue (1 byte): An 8-bit unsigned integer that defines the relative intensity of blue. | |||
* Reserved (1 byte): An 8-bit unsigned integer that MUST be 0x00. | |||
*/ | |||
Color colorRef; | |||
public int init(LittleEndianInputStream leis) throws IOException { | |||
int red = leis.readUByte(); | |||
int green = leis.readUByte(); | |||
int blue = leis.readUByte(); | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readUByte(); | |||
colorRef = new Color(red, green, blue); | |||
return 4*LittleEndianConsts.BYTE_SIZE; | |||
} | |||
} |
@@ -0,0 +1,619 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfDraw { | |||
/** | |||
* The META_MOVETO record sets the output position in the playback device context to a specified | |||
* point. | |||
*/ | |||
public static class WmfMoveTo implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.moveTo; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_LINETO record draws a line from the drawing position that is defined in the playback | |||
* device context up to, but not including, the specified point. | |||
*/ | |||
public static class WmfLineTo implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical component of the drawing | |||
* destination position, in logical units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal component of the drawing | |||
* destination position, in logical units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.lineTo; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_POLYGON record paints a polygon consisting of two or more vertices connected by | |||
* straight lines. The polygon is outlined by using the pen and filled by using the brush and polygon fill | |||
* mode that are defined in the playback device context. | |||
*/ | |||
public static class WmfPolygon implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the number of points in the array. | |||
*/ | |||
int numberofPoints; | |||
short xPoints[], yPoints[]; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.polygon; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
numberofPoints = leis.readShort(); | |||
xPoints = new short[numberofPoints]; | |||
yPoints = new short[numberofPoints]; | |||
for (int i=0; i<numberofPoints; i++) { | |||
// A 16-bit signed integer that defines the horizontal (x) coordinate of the point. | |||
xPoints[i] = leis.readShort(); | |||
// A 16-bit signed integer that defines the vertical (y) coordinate of the point. | |||
yPoints[i] = leis.readShort(); | |||
} | |||
return LittleEndianConsts.SHORT_SIZE+numberofPoints*LittleEndianConsts.INT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_POLYLINE record draws a series of line segments by connecting the points in the | |||
* specified array. | |||
*/ | |||
public static class WmfPolyline extends WmfPolygon { | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.polyline; | |||
} | |||
} | |||
/** | |||
* The META_ELLIPSE record draws an ellipse. The center of the ellipse is the center of the specified | |||
* bounding rectangle. The ellipse is outlined by using the pen and is filled by using the brush; these | |||
* are defined in the playback device context. | |||
*/ | |||
public static class WmfEllipse implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the bounding rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the bounding rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.ellipse; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_FRAMEREGION record draws a border around a specified region using a specified brush. | |||
*/ | |||
public static class WmfFrameRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the region to be framed. | |||
*/ | |||
int region; | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get the | |||
* Brush to use for filling the region. | |||
*/ | |||
int brush; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the | |||
* region frame. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the | |||
* region frame. | |||
*/ | |||
int width; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.frameRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
region = leis.readUShort(); | |||
brush = leis.readUShort(); | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_POLYPOLYGON record paints a series of closed polygons. Each polygon is outlined by | |||
* using the pen and filled by using the brush and polygon fill mode; these are defined in the playback | |||
* device context. The polygons drawn by this function can overlap. | |||
*/ | |||
public static class WmfPolyPolygon implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the number of polygons in the object. | |||
*/ | |||
int numberOfPolygons; | |||
/** | |||
* A NumberOfPolygons array of 16-bit unsigned integers that define the number of | |||
* points for each polygon in the object. | |||
*/ | |||
int pointsPerPolygon[]; | |||
/** | |||
* An array of 16-bit unsigned integers that define the coordinates of the polygons. | |||
*/ | |||
int xPoints[][]; | |||
/** | |||
* An array of 16-bit unsigned integers that define the coordinates of the polygons. | |||
*/ | |||
int yPoints[][]; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.polyPolygon; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
// see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;) | |||
numberOfPolygons = leis.readUShort(); | |||
pointsPerPolygon = new int[numberOfPolygons]; | |||
xPoints = new int[numberOfPolygons][]; | |||
yPoints = new int[numberOfPolygons][]; | |||
int size = LittleEndianConsts.SHORT_SIZE; | |||
for (int i=0; i<numberOfPolygons; i++) { | |||
pointsPerPolygon[i] = leis.readUShort(); | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
} | |||
for (int i=0; i<numberOfPolygons; i++) { | |||
xPoints[i] = new int[pointsPerPolygon[i]]; | |||
yPoints[i] = new int[pointsPerPolygon[i]]; | |||
for (int j=0; j<pointsPerPolygon[i]; j++) { | |||
xPoints[i][j] = leis.readUShort(); | |||
yPoints[i][j] = leis.readUShort(); | |||
size += 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and | |||
* filled by using the brush that are defined in the playback device context. | |||
*/ | |||
public static class WmfRectangle implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.frameRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_RECTANGLE record paints a rectangle. The rectangle is outlined by using the pen and | |||
* filled by using the brush that are defined in the playback device context. | |||
*/ | |||
public static class WmfSetPixel implements HwmfRecord { | |||
/** | |||
* A ColorRef Object that defines the color value. | |||
*/ | |||
HwmfColorRef colorRef; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the point | |||
* to be set. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the point | |||
* to be set. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setPixel; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
colorRef = new HwmfColorRef(); | |||
int size = colorRef.init(leis); | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE+size; | |||
} | |||
} | |||
/** | |||
* The META_ROUNDRECT record paints a rectangle with rounded corners. The rectangle is outlined | |||
* using the pen and filled using the brush, as defined in the playback device context. | |||
*/ | |||
public static class WmfRoundRect implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical coordinates, of the | |||
* ellipse used to draw the rounded corners. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical coordinates, of the | |||
* ellipse used to draw the rounded corners. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.roundRect; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 6*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_PIE record draws a pie-shaped wedge bounded by the intersection of an ellipse and two | |||
* radials. The pie is outlined by using the pen and filled by using the brush that are defined in the | |||
* playback device context. | |||
*/ | |||
public static class WmfPie implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical | |||
* coordinates, of the endpoint of the second radial. | |||
*/ | |||
int yRadial2; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical | |||
* coordinates, of the endpoint of the second radial. | |||
*/ | |||
int xRadial2; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical | |||
* coordinates, of the endpoint of the first radial. | |||
*/ | |||
int yRadial1; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical | |||
* coordinates, of the endpoint of the first radial. | |||
*/ | |||
int xRadial1; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the bounding rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the bounding rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.pie; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yRadial2 = leis.readShort(); | |||
xRadial2 = leis.readShort(); | |||
yRadial1 = leis.readShort(); | |||
xRadial1 = leis.readShort(); | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 8*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_ARC record draws an elliptical arc. | |||
*/ | |||
public static class WmfArc implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the ending point of the radial line defining the ending point of the arc. | |||
*/ | |||
int yEndArc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the ending point of the radial line defining the ending point of the arc. | |||
*/ | |||
int xEndArc; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the ending point of the radial line defining the starting point of the arc. | |||
*/ | |||
int yStartArc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the ending point of the radial line defining the starting point of the arc. | |||
*/ | |||
int xStartArc; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the bounding rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the bounding rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.arc; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yEndArc = leis.readShort(); | |||
xEndArc = leis.readShort(); | |||
yStartArc = leis.readShort(); | |||
xStartArc = leis.readShort(); | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 8*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_CHORD record draws a chord, which is defined by a region bounded by the intersection of | |||
* an ellipse with a line segment. The chord is outlined using the pen and filled using the brush | |||
* that are defined in the playback device context. | |||
*/ | |||
public static class WmfChord implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical | |||
* coordinates, of the endpoint of the second radial. | |||
*/ | |||
int yRadial2; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical | |||
* coordinates, of the endpoint of the second radial. | |||
*/ | |||
int xRadial2; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical | |||
* coordinates, of the endpoint of the first radial. | |||
*/ | |||
int yRadial1; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical | |||
* coordinates, of the endpoint of the first radial. | |||
*/ | |||
int xRadial1; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int bottomRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the lower-right corner of the bounding rectangle. | |||
*/ | |||
int rightRect; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the bounding rectangle. | |||
*/ | |||
int topRect; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of | |||
* the upper-left corner of the bounding rectangle. | |||
*/ | |||
int leftRect; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.chord; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yRadial2 = leis.readShort(); | |||
xRadial2 = leis.readShort(); | |||
yRadial1 = leis.readShort(); | |||
xRadial1 = leis.readShort(); | |||
bottomRect = leis.readShort(); | |||
rightRect = leis.readShort(); | |||
topRect = leis.readShort(); | |||
leftRect = leis.readShort(); | |||
return 8*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SELECTOBJECT record specifies a graphics object for the playback device context. The | |||
* new object replaces the previous object of the same type, unless if the previous object is a palette | |||
* object. If the previous object is a palette object, then the META_SELECTPALETTE record must be | |||
* used instead of the META_SELECTOBJECT record, as the META_SELECTOBJECT record does not | |||
* support replacing the palette object type. | |||
*/ | |||
public static class WmfSelectObject implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to | |||
* get the object to be selected. | |||
*/ | |||
int objectIndex; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.selectObject; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
objectIndex = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
} |
@@ -0,0 +1,53 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfEscape implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the escape function. The | |||
* value MUST be from the MetafileEscapes enumeration. | |||
*/ | |||
int escapeFunction; | |||
/** | |||
* A 16-bit unsigned integer that specifies the size, in bytes, of the | |||
* EscapeData field. | |||
*/ | |||
int byteCount; | |||
/** | |||
* An array of bytes of size ByteCount. | |||
*/ | |||
byte escapeData[]; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.escape; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
escapeFunction = leis.readUShort(); | |||
byteCount = leis.readUShort(); | |||
escapeData = new byte[byteCount]; | |||
leis.read(escapeData); | |||
return 2*LittleEndianConsts.SHORT_SIZE+byteCount; | |||
} | |||
} |
@@ -0,0 +1,794 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfFill { | |||
/** | |||
* The META_FILLREGION record fills a region using a specified brush. | |||
*/ | |||
public static class WmfFillRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the region to be filled. | |||
*/ | |||
int region; | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get the | |||
* brush to use for filling the region. | |||
*/ | |||
int brush; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.fillRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
region = leis.readUShort(); | |||
brush = leis.readUShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_PAINTREGION record paints the specified region by using the brush that is | |||
* defined in the playback device context. | |||
*/ | |||
public static class WmfPaintRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the region to be painted. | |||
*/ | |||
int region; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.paintRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
region = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_FLOODFILL record fills an area of the output surface with the brush that | |||
* is defined in the playback device context. | |||
*/ | |||
public static class WmfFloodFill implements HwmfRecord { | |||
/** | |||
* A 32-bit ColorRef Object that defines the color value. | |||
*/ | |||
HwmfColorRef colorRef; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* point where filling is to start. | |||
*/ | |||
int yStart; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* point where filling is to start. | |||
*/ | |||
int xStart; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.floodFill; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
colorRef = new HwmfColorRef(); | |||
int size = colorRef.init(leis); | |||
yStart = leis.readShort(); | |||
xStart = leis.readShort(); | |||
return size+2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETPOLYFILLMODE record sets polygon fill mode in the playback device context for | |||
* graphics operations that fill polygons. | |||
*/ | |||
public static class WmfSetPolyfillMode implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines polygon fill mode. | |||
* This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002 | |||
*/ | |||
int polyFillMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setPolyFillMode; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
polyFillMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_EXTFLOODFILL record fills an area with the brush that is defined in | |||
* the playback device context. | |||
*/ | |||
public static class WmfExtFloodFill implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the fill operation to be performed. This | |||
* member MUST be one of the values in the FloodFill Enumeration table: | |||
* | |||
* FLOODFILLBORDER = 0x0000: | |||
* The fill area is bounded by the color specified by the Color member. | |||
* This style is identical to the filling performed by the META_FLOODFILL record. | |||
* | |||
* FLOODFILLSURFACE = 0x0001: | |||
* The fill area is bounded by the color that is specified by the Color member. | |||
* Filling continues outward in all directions as long as the color is encountered. | |||
* This style is useful for filling areas with multicolored boundaries. | |||
*/ | |||
int mode; | |||
/** | |||
* A 32-bit ColorRef Object that defines the color value. | |||
*/ | |||
HwmfColorRef colorRef; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the point | |||
* to be set. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the point | |||
* to be set. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.extFloodFill; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
mode = leis.readUShort(); | |||
colorRef = new HwmfColorRef(); | |||
int size = colorRef.init(leis); | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return size+3*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_INVERTREGION record draws a region in which the colors are inverted. | |||
*/ | |||
public static class WmfInvertRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the region to be inverted. | |||
*/ | |||
int region; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.invertRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
region = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_PATBLT record paints a specified rectangle using the brush that is defined in the playback | |||
* device context. The brush color and the surface color or colors are combined using the specified | |||
* raster operation. | |||
*/ | |||
public static class WmfPatBlt implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines the raster operation code. | |||
* This code MUST be one of the values in the Ternary Raster Operation enumeration table. | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the rectangle. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the rectangle. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle to be filled. | |||
*/ | |||
int yLeft; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle to be filled. | |||
*/ | |||
int xLeft; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.patBlt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
yLeft = leis.readShort(); | |||
xLeft = leis.readShort(); | |||
return 6*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
*/ | |||
public static class WmfStretchBlt implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines how the source pixels, the current brush | |||
* in the playback device context, and the destination pixels are to be combined to form the new | |||
* image. This code MUST be one of the values in the Ternary Raster Operation Enumeration | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the source rectangle. | |||
*/ | |||
int srcHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the source rectangle. | |||
*/ | |||
int srcWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner | |||
* of the source rectangle. | |||
*/ | |||
int ySrc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner | |||
* of the source rectangle. | |||
*/ | |||
int xSrc; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the destination rectangle. | |||
*/ | |||
int destHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the destination rectangle. | |||
*/ | |||
int destWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left | |||
* corner of the destination rectangle. | |||
*/ | |||
int yDest; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left | |||
* corner of the destination rectangle. | |||
*/ | |||
int xDest; | |||
/** | |||
* A variable-sized Bitmap16 Object that defines source image content. | |||
* This object MUST be specified, even if the raster operation does not require a source. | |||
*/ | |||
HwmfBitmap16 target; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.stretchBlt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); | |||
int size = 0; | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
srcHeight = leis.readShort(); | |||
srcWidth = leis.readShort(); | |||
ySrc = leis.readShort(); | |||
xSrc = leis.readShort(); | |||
size = 6*LittleEndianConsts.SHORT_SIZE; | |||
if (!hasBitmap) { | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readShort(); | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
} | |||
destHeight = leis.readShort(); | |||
destWidth = leis.readShort(); | |||
yDest = leis.readShort(); | |||
xDest = leis.readShort(); | |||
size += 4*LittleEndianConsts.SHORT_SIZE; | |||
if (hasBitmap) { | |||
target = new HwmfBitmap16(); | |||
size += target.init(leis); | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_STRETCHDIB record specifies the transfer of color data from a | |||
* block of pixels in deviceindependent format according to a raster operation, | |||
* with possible expansion or contraction. | |||
* The source of the color data is a DIB, and the destination of the transfer is | |||
* the current output region in the playback device context. | |||
*/ | |||
public static class WmfStretchDib implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines how the source pixels, the current brush in | |||
* the playback device context, and the destination pixels are to be combined to | |||
* form the new image. | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit unsigned integer that defines whether the Colors field of the | |||
* DIB contains explicit RGB values or indexes into a palette. | |||
* This value MUST be in the ColorUsage Enumeration: | |||
* DIB_RGB_COLORS = 0x0000, | |||
* DIB_PAL_COLORS = 0x0001, | |||
* DIB_PAL_INDICES = 0x0002 | |||
*/ | |||
int colorUsage; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int srcHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int srcWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int ySrc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int xSrc; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the | |||
* destination rectangle. | |||
*/ | |||
int destHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the | |||
* destination rectangle. | |||
*/ | |||
int destWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the destination rectangle. | |||
*/ | |||
int yDst; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the destination rectangle. | |||
*/ | |||
int xDst; | |||
/** | |||
* A variable-sized DeviceIndependentBitmap Object (section 2.2.2.9) that is the | |||
* source of the color data. | |||
*/ | |||
HwmfBitmapDib dib; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.stretchDib; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
colorUsage = leis.readUShort(); | |||
srcHeight = leis.readShort(); | |||
srcWidth = leis.readShort(); | |||
ySrc = leis.readShort(); | |||
xSrc = leis.readShort(); | |||
destHeight = leis.readShort(); | |||
destWidth = leis.readShort(); | |||
yDst = leis.readShort(); | |||
xDst = leis.readShort(); | |||
int size = 11*LittleEndianConsts.SHORT_SIZE; | |||
dib = new HwmfBitmapDib(); | |||
size += dib.init(leis); | |||
return size; | |||
} | |||
} | |||
public static class WmfBitBlt implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines how the source pixels, the current brush in the playback | |||
* device context, and the destination pixels are to be combined to form the new image. | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left corner | |||
of the source rectangle. | |||
*/ | |||
int ySrc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left corner | |||
of the source rectangle. | |||
*/ | |||
int xSrc; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the source and | |||
destination rectangles. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the source and destination | |||
rectangles. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left | |||
corner of the destination rectangle. | |||
*/ | |||
int yDest; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left | |||
corner of the destination rectangle. | |||
*/ | |||
int xDest; | |||
/** | |||
* A variable-sized Bitmap16 Object that defines source image content. | |||
* This object MUST be specified, even if the raster operation does not require a source. | |||
*/ | |||
HwmfBitmap16 target; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.bitBlt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); | |||
int size = 0; | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
ySrc = leis.readShort(); | |||
xSrc = leis.readShort(); | |||
size = 4*LittleEndianConsts.SHORT_SIZE; | |||
if (!hasBitmap) { | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readShort(); | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
} | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
yDest = leis.readShort(); | |||
xDest = leis.readShort(); | |||
size += 4*LittleEndianConsts.SHORT_SIZE; | |||
if (hasBitmap) { | |||
target = new HwmfBitmap16(); | |||
size += target.init(leis); | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_SETDIBTODEV record sets a block of pixels in the playback device context | |||
* using deviceindependent color data. | |||
* The source of the color data is a DIB | |||
*/ | |||
public static class WmfSetDibToDev implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines whether the Colors field of the | |||
* DIB contains explicit RGB values or indexes into a palette. | |||
* This MUST be one of the values in the ColorUsage Enumeration: | |||
* DIB_RGB_COLORS = 0x0000, | |||
* DIB_PAL_COLORS = 0x0001, | |||
* DIB_PAL_INDICES = 0x0002 | |||
*/ | |||
int colorUsage; | |||
/** | |||
* A 16-bit unsigned integer that defines the number of scan lines in the source. | |||
*/ | |||
int scanCount; | |||
/** | |||
* A 16-bit unsigned integer that defines the starting scan line in the source. | |||
*/ | |||
int startScan; | |||
/** | |||
* A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int yDib; | |||
/** | |||
* A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the | |||
* source rectangle. | |||
*/ | |||
int xDib; | |||
/** | |||
* A 16-bit unsigned integer that defines the height, in logical units, of the | |||
* source and destination rectangles. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit unsigned integer that defines the width, in logical units, of the | |||
* source and destination rectangles. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the destination rectangle. | |||
*/ | |||
int yDest; | |||
/** | |||
* A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the destination rectangle. | |||
*/ | |||
int xDest; | |||
/** | |||
* A variable-sized DeviceIndependentBitmap Object that is the source of the color data. | |||
*/ | |||
HwmfBitmapDib dib; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setDibToDev; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
colorUsage = leis.readUShort(); | |||
scanCount = leis.readUShort(); | |||
startScan = leis.readUShort(); | |||
yDib = leis.readUShort(); | |||
xDib = leis.readUShort(); | |||
height = leis.readUShort(); | |||
width = leis.readUShort(); | |||
yDest = leis.readUShort(); | |||
xDest = leis.readUShort(); | |||
int size = 9*LittleEndianConsts.SHORT_SIZE; | |||
dib = new HwmfBitmapDib(); | |||
size += dib.init(leis); | |||
return size; | |||
} | |||
} | |||
public static class WmfDibBitBlt implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines how the source pixels, the current brush | |||
* in the playback device context, and the destination pixels are to be combined to form the | |||
* new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the source rectangle. | |||
*/ | |||
int ySrc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the source rectangle. | |||
*/ | |||
int xSrc; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the source and | |||
* destination rectangles. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the source and destination | |||
* rectangles. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the upper-left | |||
* corner of the destination rectangle. | |||
*/ | |||
int yDest; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the upper-left | |||
* corner of the destination rectangle. | |||
*/ | |||
int xDest; | |||
/** | |||
* A variable-sized DeviceIndependentBitmap Object that defines image content. | |||
* This object MUST be specified, even if the raster operation does not require a source. | |||
*/ | |||
HwmfBitmapDib target; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.dibBitBlt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); | |||
int size = 0; | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
ySrc = leis.readShort(); | |||
xSrc = leis.readShort(); | |||
size = 4*LittleEndianConsts.SHORT_SIZE; | |||
if (!hasBitmap) { | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readShort(); | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
} | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
yDest = leis.readShort(); | |||
xDest = leis.readShort(); | |||
size += 4*LittleEndianConsts.SHORT_SIZE; | |||
if (hasBitmap) { | |||
target = new HwmfBitmapDib(); | |||
size += target.init(leis); | |||
} | |||
return size; | |||
} | |||
} | |||
public static class WmfDibStretchBlt implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines how the source pixels, the current brush | |||
* in the playback device context, and the destination pixels are to be combined to form the | |||
* new image. This code MUST be one of the values in the Ternary Raster Operation Enumeration. | |||
*/ | |||
HwmfTernaryRasterOp rasterOperation; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the source rectangle. | |||
*/ | |||
int srcHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the source rectangle. | |||
*/ | |||
int srcWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the source rectangle. | |||
*/ | |||
int ySrc; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the source rectangle. | |||
*/ | |||
int xSrc; | |||
/** | |||
* A 16-bit signed integer that defines the height, in logical units, of the | |||
* destination rectangle. | |||
*/ | |||
int destHeight; | |||
/** | |||
* A 16-bit signed integer that defines the width, in logical units, of the | |||
* destination rectangle. | |||
*/ | |||
int destWidth; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, | |||
* of the upper-left corner of the destination rectangle. | |||
*/ | |||
int yDest; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, | |||
* of the upper-left corner of the destination rectangle. | |||
*/ | |||
int xDest; | |||
/** | |||
* A variable-sized DeviceIndependentBitmap Object that defines image content. | |||
* This object MUST be specified, even if the raster operation does not require a source. | |||
*/ | |||
HwmfBitmapDib target; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.dibStretchBlt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
boolean hasBitmap = (recordSize > ((recordFunction >> 8) + 3)); | |||
int size = 0; | |||
int rasterOpIndex = leis.readUShort(); | |||
int rasterOpCode = leis.readUShort(); | |||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex); | |||
assert(rasterOpCode == rasterOperation.opCode); | |||
srcHeight = leis.readShort(); | |||
srcWidth = leis.readShort(); | |||
ySrc = leis.readShort(); | |||
xSrc = leis.readShort(); | |||
size = 6*LittleEndianConsts.SHORT_SIZE; | |||
if (!hasBitmap) { | |||
@SuppressWarnings("unused") | |||
int reserved = leis.readShort(); | |||
size += LittleEndianConsts.SHORT_SIZE; | |||
} | |||
destHeight = leis.readShort(); | |||
destWidth = leis.readShort(); | |||
yDest = leis.readShort(); | |||
xDest = leis.readShort(); | |||
size += 4*LittleEndianConsts.SHORT_SIZE; | |||
if (hasBitmap) { | |||
target = new HwmfBitmapDib(); | |||
size += target.init(leis); | |||
} | |||
return size; | |||
} | |||
} | |||
} |
@@ -0,0 +1,498 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import java.nio.charset.Charset; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
/** | |||
* The Font object specifies the attributes of a logical font | |||
*/ | |||
public class HwmfFont { | |||
public enum WmfCharset { | |||
/** Specifies the English character set. */ | |||
ANSI_CHARSET(0x00000000), | |||
/** | |||
* Specifies a character set based on the current system locale; | |||
* for example, when the system locale is United States English, | |||
* the default character set is ANSI_CHARSET. | |||
*/ | |||
DEFAULT_CHARSET(0x00000001), | |||
/** Specifies a character set of symbols. */ | |||
SYMBOL_CHARSET(0x00000002), | |||
/** Specifies the Apple Macintosh character set. */ | |||
MAC_CHARSET(0x0000004D), | |||
/** Specifies the Japanese character set. */ | |||
SHIFTJIS_CHARSET(0x00000080), | |||
/** Also spelled "Hangeul". Specifies the Hangul Korean character set. */ | |||
HANGUL_CHARSET(0x00000081), | |||
/** Also spelled "Johap". Specifies the Johab Korean character set. */ | |||
JOHAB_CHARSET(0x00000082), | |||
/** Specifies the "simplified" Chinese character set for People's Republic of China. */ | |||
GB2312_CHARSET(0x00000086), | |||
/** | |||
* Specifies the "traditional" Chinese character set, used mostly in | |||
* Taiwan and in the Hong Kong and Macao Special Administrative Regions. | |||
*/ | |||
CHINESEBIG5_CHARSET(0x00000088), | |||
/** Specifies the Greek character set. */ | |||
GREEK_CHARSET(0x000000A1), | |||
/** Specifies the Turkish character set. */ | |||
TURKISH_CHARSET(0x000000A2), | |||
/** Specifies the Vietnamese character set. */ | |||
VIETNAMESE_CHARSET(0x000000A3), | |||
/** Specifies the Hebrew character set. */ | |||
HEBREW_CHARSET(0x000000B1), | |||
/** Specifies the Arabic character set. */ | |||
ARABIC_CHARSET(0x000000B2), | |||
/** Specifies the Baltic (Northeastern European) character set. */ | |||
BALTIC_CHARSET(0x000000BA), | |||
/** Specifies the Russian Cyrillic character set. */ | |||
RUSSIAN_CHARSET(0x000000CC), | |||
/** Specifies the Thai character set. */ | |||
THAI_CHARSET(0x000000DE), | |||
/** Specifies a Eastern European character set. */ | |||
EASTEUROPE_CHARSET(0x000000EE), | |||
/** | |||
* Specifies a mapping to one of the OEM code pages, | |||
* according to the current system locale setting. | |||
*/ | |||
OEM_CHARSET(0x000000FF); | |||
int flag; | |||
WmfCharset(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfCharset valueOf(int flag) { | |||
for (WmfCharset cs : values()) { | |||
if (cs.flag == flag) return cs; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* The output precision defines how closely the output must match the requested font's height, | |||
* width, character orientation, escapement, pitch, and font type. | |||
*/ | |||
public enum WmfOutPrecision { | |||
/** | |||
* A value that specifies default behavior. | |||
*/ | |||
OUT_DEFAULT_PRECIS(0x00000000), | |||
/** | |||
* A value that is returned when rasterized fonts are enumerated. | |||
*/ | |||
OUT_STRING_PRECIS(0x00000001), | |||
/** | |||
* A value that is returned when TrueType and other outline fonts, and | |||
* vector fonts are enumerated. | |||
*/ | |||
OUT_STROKE_PRECIS(0x00000003), | |||
/** | |||
* A value that specifies the choice of a TrueType font when the system | |||
* contains multiple fonts with the same name. | |||
*/ | |||
OUT_TT_PRECIS(0x00000004), | |||
/** | |||
* A value that specifies the choice of a device font when the system | |||
* contains multiple fonts with the same name. | |||
*/ | |||
OUT_DEVICE_PRECIS(0x00000005), | |||
/** | |||
* A value that specifies the choice of a rasterized font when the system | |||
* contains multiple fonts with the same name. | |||
*/ | |||
OUT_RASTER_PRECIS(0x00000006), | |||
/** | |||
* A value that specifies the requirement for only TrueType fonts. If | |||
* there are no TrueType fonts installed in the system, default behavior is specified. | |||
*/ | |||
OUT_TT_ONLY_PRECIS(0x00000007), | |||
/** | |||
* A value that specifies the requirement for TrueType and other outline fonts. | |||
*/ | |||
OUT_OUTLINE_PRECIS (0x00000008), | |||
/** | |||
* A value that specifies a preference for TrueType and other outline fonts. | |||
*/ | |||
OUT_SCREEN_OUTLINE_PRECIS (0x00000009), | |||
/** | |||
* A value that specifies a requirement for only PostScript fonts. If there | |||
* are no PostScript fonts installed in the system, default behavior is specified. | |||
*/ | |||
OUT_PS_ONLY_PRECIS (0x0000000A); | |||
int flag; | |||
WmfOutPrecision(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfOutPrecision valueOf(int flag) { | |||
for (WmfOutPrecision op : values()) { | |||
if (op.flag == flag) return op; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* ClipPrecision Flags specify clipping precision, which defines how to clip characters that are | |||
* partially outside a clipping region. These flags can be combined to specify multiple options. | |||
*/ | |||
public enum WmfClipPrecision { | |||
/** | |||
* Specifies that default clipping MUST be used. | |||
*/ | |||
CLIP_DEFAULT_PRECIS (0x00000000), | |||
/** | |||
* This value SHOULD NOT be used. | |||
*/ | |||
CLIP_CHARACTER_PRECIS (0x00000001), | |||
/** | |||
* This value MAY be returned when enumerating rasterized, TrueType and vector fonts. | |||
*/ | |||
CLIP_STROKE_PRECIS (0x00000002), | |||
/** | |||
* This value is used to control font rotation, as follows: | |||
* If set, the rotation for all fonts SHOULD be determined by the orientation of the coordinate system; | |||
* that is, whether the orientation is left-handed or right-handed. | |||
* | |||
* If clear, device fonts SHOULD rotate counterclockwise, but the rotation of other fonts | |||
* SHOULD be determined by the orientation of the coordinate system. | |||
*/ | |||
CLIP_LH_ANGLES (0x00000010), | |||
/** | |||
* This value SHOULD NOT be used. | |||
*/ | |||
CLIP_TT_ALWAYS (0x00000020), | |||
/** | |||
* This value specifies that font association SHOULD< be turned off. | |||
*/ | |||
CLIP_DFA_DISABLE (0x00000040), | |||
/** | |||
* This value specifies that font embedding MUST be used to render document content; | |||
* embedded fonts are read-only. | |||
*/ | |||
CLIP_EMBEDDED (0x00000080); | |||
int flag; | |||
WmfClipPrecision(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfClipPrecision valueOf(int flag) { | |||
for (WmfClipPrecision cp : values()) { | |||
if (cp.flag == flag) return cp; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* The output quality defines how carefully to attempt to match the logical font attributes to those of an actual | |||
* physical font. | |||
*/ | |||
public enum WmfFontQuality { | |||
/** | |||
* Specifies that the character quality of the font does not matter, so DRAFT_QUALITY can be used. | |||
*/ | |||
DEFAULT_QUALITY (0x00), | |||
/** | |||
* Specifies that the character quality of the font is less important than the | |||
* matching of logical attribuetes. For rasterized fonts, scaling SHOULD be enabled, which | |||
* means that more font sizes are available. | |||
*/ | |||
DRAFT_QUALITY (0x01), | |||
/** | |||
* Specifies that the character quality of the font is more important than the | |||
* matching of logical attributes. For rasterized fonts, scaling SHOULD be disabled, and the font | |||
* closest in size SHOULD be chosen. | |||
*/ | |||
PROOF_QUALITY (0x02), | |||
/** | |||
* Specifies that anti-aliasing SHOULD NOT be used when rendering text. | |||
*/ | |||
NONANTIALIASED_QUALITY (0x03), | |||
/** | |||
* Specifies that anti-aliasing SHOULD be used when rendering text, if the font supports it. | |||
*/ | |||
ANTIALIASED_QUALITY (0x04), | |||
/** | |||
* Specifies that ClearType anti-aliasing SHOULD be used when rendering text, if the font supports it. | |||
* | |||
* Fonts that do not support ClearType anti-aliasing include type 1 fonts, PostScript fonts, | |||
* OpenType fonts without TrueType outlines, rasterized fonts, vector fonts, and device fonts. | |||
*/ | |||
CLEARTYPE_QUALITY (0x05); | |||
int flag; | |||
WmfFontQuality(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfFontQuality valueOf(int flag) { | |||
for (WmfFontQuality fq : values()) { | |||
if (fq.flag == flag) return fq; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* A property of a font that describes its general appearance. | |||
*/ | |||
public enum WmfFontFamilyClass { | |||
/** | |||
* The default font is specified, which is implementation-dependent. | |||
*/ | |||
FF_DONTCARE (0x00), | |||
/** | |||
* Fonts with variable stroke widths, which are proportional to the actual widths of | |||
* the glyphs, and which have serifs. "MS Serif" is an example. | |||
*/ | |||
FF_ROMAN (0x01), | |||
/** | |||
* Fonts with variable stroke widths, which are proportional to the actual widths of the | |||
* glyphs, and which do not have serifs. "MS Sans Serif" is an example. | |||
*/ | |||
FF_SWISS (0x02), | |||
/** | |||
* Fonts with constant stroke width, with or without serifs. Fixed-width fonts are | |||
* usually modern. "Pica", "Elite", and "Courier New" are examples. | |||
*/ | |||
FF_MODERN (0x03), | |||
/** | |||
* Fonts designed to look like handwriting. "Script" and "Cursive" are examples. | |||
*/ | |||
FF_SCRIPT (0x04), | |||
/** | |||
* Novelty fonts. "Old English" is an example. | |||
*/ | |||
FF_DECORATIVE (0x05); | |||
int flag; | |||
WmfFontFamilyClass(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfFontFamilyClass valueOf(int flag) { | |||
for (WmfFontFamilyClass ff : values()) { | |||
if (ff.flag == flag) return ff; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* A property of a font that describes the pitch, of the characters. | |||
*/ | |||
public enum WmfFontPitch { | |||
/** | |||
* The default pitch, which is implementation-dependent. | |||
*/ | |||
DEFAULT_PITCH (0x00), | |||
/** | |||
* A fixed pitch, which means that all the characters in the font occupy the same | |||
* width when output in a string. | |||
*/ | |||
FIXED_PITCH (0x01), | |||
/** | |||
* A variable pitch, which means that the characters in the font occupy widths | |||
* that are proportional to the actual widths of the glyphs when output in a string. For example, | |||
* the "i" and space characters usually have much smaller widths than a "W" or "O" character. | |||
*/ | |||
VARIABLE_PITCH (0x02); | |||
int flag; | |||
WmfFontPitch(int flag) { | |||
this.flag = flag; | |||
} | |||
static WmfFontPitch valueOf(int flag) { | |||
for (WmfFontPitch fp : values()) { | |||
if (fp.flag == flag) return fp; | |||
} | |||
return null; | |||
} | |||
} | |||
/** | |||
* A 16-bit signed integer that specifies the height, in logical units, of the font's | |||
* character cell. The character height is computed as the character cell height minus the | |||
* internal leading. The font mapper SHOULD interpret the height as follows. | |||
* | |||
* negative value: | |||
* The font mapper SHOULD transform this value into device units and match its | |||
* absolute value against the character height of available fonts. | |||
* | |||
* zero value: | |||
* A default height value MUST be used when creating a physical font. | |||
* | |||
* positive value: | |||
* The font mapper SHOULD transform this value into device units and match it | |||
* against the cell height of available fonts. | |||
* | |||
* For all height comparisons, the font mapper SHOULD find the largest physical | |||
* font that does not exceed the requested size. | |||
*/ | |||
int height; | |||
/** | |||
* A 16-bit signed integer that defines the average width, in logical units, of | |||
* characters in the font. If Width is 0x0000, the aspect ratio of the device SHOULD be matched | |||
* against the digitization aspect ratio of the available fonts to find the closest match, | |||
* determined by the absolute value of the difference. | |||
*/ | |||
int width; | |||
/** | |||
* A 16-bit signed integer that defines the angle, in tenths of degrees, between the | |||
* escapement vector and the x-axis of the device. The escapement vector is parallel | |||
* to the base line of a row of text. | |||
*/ | |||
int escapement; | |||
/** | |||
* A 16-bit signed integer that defines the angle, in tenths of degrees, | |||
* between each character's base line and the x-axis of the device. | |||
*/ | |||
int orientation; | |||
/** | |||
* A 16-bit signed integer that defines the weight of the font in the range 0 | |||
* through 1000. For example, 400 is normal and 700 is bold. If this value is 0x0000, | |||
* a default weight SHOULD be used. | |||
*/ | |||
int weight; | |||
/** | |||
* A 8-bit Boolean value that specifies the italic attribute of the font. | |||
* 0 = not italic / 1 = italic. | |||
*/ | |||
boolean italic; | |||
/** | |||
* An 8-bit Boolean value that specifies the underline attribute of the font. | |||
* 0 = not underlined / 1 = underlined | |||
*/ | |||
boolean underline; | |||
/** | |||
* An 8-bit Boolean value that specifies the strike out attribute of the font. | |||
* 0 = not striked out / 1 = striked out | |||
*/ | |||
boolean strikeOut; | |||
/** | |||
* An 8-bit unsigned integer that defines the character set. | |||
* It SHOULD be set to a value in the {@link WmfCharset} Enumeration. | |||
* | |||
* The DEFAULT_CHARSET value MAY be used to allow the name and size of a font to fully | |||
* describe the logical font. If the specified font name does not exist, a font in another character | |||
* set MAY be substituted. The DEFAULT_CHARSET value is set to a value based on the current | |||
* system locale. For example, when the system locale is United States, it is set to ANSI_CHARSET. | |||
* If a typeface name in the FaceName field is specified, the CharSet value MUST match the | |||
* character set of that typeface. | |||
*/ | |||
WmfCharset charSet; | |||
/** | |||
* An 8-bit unsigned integer that defines the output precision. | |||
*/ | |||
WmfOutPrecision outPrecision; | |||
/** | |||
* An 8-bit unsigned integer that defines the clipping precision. | |||
* These flags can be combined to specify multiple options. | |||
* | |||
* @see WmfClipPrecision | |||
*/ | |||
int clipPrecision; | |||
/** | |||
* An 8-bit unsigned integer that defines the output quality. | |||
*/ | |||
WmfFontQuality quality; | |||
/** | |||
* Font families specify the look of fonts in a general way and are | |||
* intended for specifying fonts when the exact typeface wanted is not available. | |||
* (LSB 4 bits) | |||
*/ | |||
WmfFontFamilyClass family; | |||
/** | |||
* A property of a font that describes the pitch (MSB 2 bits) | |||
*/ | |||
WmfFontPitch pitch; | |||
/** | |||
* A null-terminated string of 8-bit Latin-1 [ISO/IEC-8859-1] ANSI | |||
* characters that specifies the typeface name of the font. The length of this string MUST NOT | |||
* exceed 32 8-bit characters, including the terminating null. | |||
*/ | |||
String facename; | |||
public int init(LittleEndianInputStream leis) throws IOException { | |||
height = leis.readShort(); | |||
width = leis.readShort(); | |||
escapement = leis.readShort(); | |||
orientation = leis.readShort(); | |||
weight = leis.readShort(); | |||
italic = leis.readByte() != 0; | |||
underline = leis.readByte() != 0; | |||
strikeOut = leis.readByte() != 0; | |||
charSet = WmfCharset.valueOf(leis.readUByte()); | |||
outPrecision = WmfOutPrecision.valueOf(leis.readUByte()); | |||
quality = WmfFontQuality.valueOf(leis.readUByte()); | |||
int pitchAndFamily = leis.readUByte(); | |||
family = WmfFontFamilyClass.valueOf(pitchAndFamily & 0xF); | |||
pitch = WmfFontPitch.valueOf((pitchAndFamily >>> 6) & 3); | |||
byte buf[] = new byte[32], readBytes; | |||
for (readBytes = 0; readBytes < 32; readBytes++) { | |||
if ((buf[readBytes] = leis.readByte()) == 0) { | |||
break; | |||
} | |||
} | |||
if (readBytes == 1 || readBytes == 32) { | |||
throw new IOException("Font facename can't be determined."); | |||
} | |||
facename = new String(buf, 0, readBytes-1, Charset.forName("ISO-8859-1")); | |||
return 17+readBytes; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
/** | |||
* The HatchStyle Enumeration specifies the hatch pattern. | |||
*/ | |||
public enum HwmfHatchStyle { | |||
/** A horizontal hatch */ | |||
HS_HORIZONTAL(0x0000), | |||
/** A vertical hatch */ | |||
HS_VERTICAL(0x0001), | |||
/** A 45-degree downward, left-to-right hatch. */ | |||
HS_FDIAGONAL(0x0002), | |||
/** A 45-degree upward, left-to-right hatch. */ | |||
HS_BDIAGONAL(0x0003), | |||
/** A horizontal and vertical cross-hatch. */ | |||
HS_CROSS(0x0004), | |||
/** A 45-degree crosshatch. */ | |||
HS_DIAGCROSS(0x0005); | |||
int flag; | |||
HwmfHatchStyle(int flag) { | |||
this.flag = flag; | |||
} | |||
static HwmfHatchStyle valueOf(int flag) { | |||
for (HwmfHatchStyle hs : values()) { | |||
if (hs.flag == flag) return hs; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfHeader { | |||
private int type; | |||
private int recordSize; | |||
private int version; | |||
private int filesize; | |||
private int numberOfObjects; | |||
private long maxRecord; | |||
private int numberOfMembers; | |||
public HwmfHeader(LittleEndianInputStream leis) throws IOException { | |||
// Type (2 bytes): A 16-bit unsigned integer that defines the type of metafile | |||
// MEMORYMETAFILE = 0x0001, DISKMETAFILE = 0x0002 | |||
type = leis.readUShort(); | |||
// HeaderSize (2 bytes): A 16-bit unsigned integer that defines the number | |||
// of 16-bit words in the header. | |||
recordSize = leis.readUShort(); | |||
int bytesLeft = recordSize*LittleEndianConsts.SHORT_SIZE-4; | |||
// Version (2 bytes): A 16-bit unsigned integer that defines the metafile version. | |||
// METAVERSION100 = 0x0100, METAVERSION300 = 0x0300 | |||
version = leis.readUShort(); | |||
bytesLeft -= LittleEndianConsts.SHORT_SIZE; | |||
// SizeLow (2 bytes): A 16-bit unsigned integer that defines the low-order word | |||
// of the number of 16-bit words in the entire metafile. | |||
// SizeHigh (2 bytes): A 16-bit unsigned integer that defines the high-order word | |||
// of the number of 16-bit words in the entire metafile. | |||
filesize = leis.readInt(); | |||
bytesLeft -= LittleEndianConsts.INT_SIZE; | |||
// NumberOfObjects (2 bytes): A 16-bit unsigned integer that specifies the number | |||
// of graphics objects that are defined in the entire metafile. These objects include | |||
// brushes, pens, and the other objects | |||
numberOfObjects = leis.readUShort(); | |||
bytesLeft -= LittleEndianConsts.SHORT_SIZE; | |||
// MaxRecord (4 bytes): A 32-bit unsigned integer that specifies the size of the | |||
// largest record used in the metafile (in 16-bit elements). | |||
maxRecord = leis.readUInt(); | |||
bytesLeft -= LittleEndianConsts.INT_SIZE; | |||
// NumberOfMembers (2 bytes): A 16-bit unsigned integer that is not used. | |||
// It SHOULD be 0x0000. | |||
numberOfMembers = leis.readUShort(); | |||
bytesLeft -= LittleEndianConsts.SHORT_SIZE; | |||
if (bytesLeft > 0) { | |||
leis.skip(bytesLeft); | |||
} | |||
} | |||
} |
@@ -0,0 +1,506 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfMisc { | |||
/** | |||
* The META_SAVEDC record saves the playback device context for later retrieval. | |||
*/ | |||
public static class WmfSaveDc implements HwmfRecord { | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.saveDc; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
return 0; | |||
} | |||
} | |||
/** | |||
* The META_SETRELABS record is reserved and not supported. | |||
*/ | |||
public static class WmfSetRelabs implements HwmfRecord { | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.setRelabs; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
return 0; | |||
} | |||
} | |||
/** | |||
* The META_RESTOREDC record restores the playback device context from a previously saved device | |||
* context. | |||
*/ | |||
public static class WmfRestoreDc implements HwmfRecord { | |||
/** | |||
* nSavedDC (2 bytes): A 16-bit signed integer that defines the saved state to be restored. If this | |||
* member is positive, nSavedDC represents a specific instance of the state to be restored. If | |||
* this member is negative, nSavedDC represents an instance relative to the current state. | |||
*/ | |||
int nSavedDC; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.restoreDc; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
nSavedDC = leis.readShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETBKCOLOR record sets the background color in the playback device context to a | |||
* specified color, or to the nearest physical color if the device cannot represent the specified color. | |||
*/ | |||
public static class WmfSetBkColor implements HwmfRecord { | |||
HwmfColorRef colorRef; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setBkColor; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
colorRef = new HwmfColorRef(); | |||
return colorRef.init(leis); | |||
} | |||
} | |||
/** | |||
* The META_SETBKMODE record defines the background raster operation mix mode in the playback | |||
* device context. The background mix mode is the mode for combining pens, text, hatched brushes, | |||
* and interiors of filled objects with background colors on the output surface. | |||
*/ | |||
public static class WmfSetBkMode implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines background mix mode. | |||
* This MUST be either TRANSPARENT = 0x0001 or OPAQUE = 0x0002 | |||
*/ | |||
int bkMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setBkMode; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
bkMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETLAYOUT record defines the layout orientation in the playback device context. | |||
* The layout orientation determines the direction in which text and graphics are drawn | |||
*/ | |||
public static class WmfSetLayout implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the layout of text and graphics. | |||
* LAYOUT_LTR = 0x0000 | |||
* LAYOUT_RTL = 0x0001 | |||
* LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008 | |||
*/ | |||
int layout; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setLayout; | |||
} | |||
@SuppressWarnings("unused") | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
layout = leis.readUShort(); | |||
// A 16-bit field that MUST be ignored. | |||
int reserved = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETMAPMODE record defines the mapping mode in the playback device context. | |||
* The mapping mode defines the unit of measure used to transform page-space units into | |||
* device-space units, and also defines the orientation of the device's x and y axes. | |||
*/ | |||
public static class WmfSetMapMode implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the mapping mode. | |||
* | |||
* The MapMode defines how logical units are mapped to physical units; | |||
* that is, assuming that the origins in both the logical and physical coordinate systems | |||
* are at the same point on the drawing surface, what is the physical coordinate (x',y') | |||
* that corresponds to logical coordinate (x,y). | |||
* | |||
* For example, suppose the mapping mode is MM_TEXT. Given the following definition of that | |||
* mapping mode, and an origin (0,0) at the top left corner of the drawing surface, logical | |||
* coordinate (4,5) would map to physical coordinate (4,5) in pixels. | |||
* | |||
* Now suppose the mapping mode is MM_LOENGLISH, with the same origin as the previous | |||
* example. Given the following definition of that mapping mode, logical coordinate (4,-5) | |||
* would map to physical coordinate (0.04,0.05) in inches. | |||
* | |||
* This MUST be one of the following: | |||
* | |||
* MM_TEXT (= 0x0001): | |||
* Each logical unit is mapped to one device pixel. | |||
* Positive x is to the right; positive y is down. | |||
* | |||
* MM_LOMETRIC (= 0x0002): | |||
* Each logical unit is mapped to 0.1 millimeter. | |||
* Positive x is to the right; positive y is up. | |||
* | |||
* MM_HIMETRIC (= 0x0003): | |||
* Each logical unit is mapped to 0.01 millimeter. | |||
* Positive x is to the right; positive y is up. | |||
* | |||
* MM_LOENGLISH (= 0x0004): | |||
* Each logical unit is mapped to 0.01 inch. | |||
* Positive x is to the right; positive y is up. | |||
* | |||
* MM_HIENGLISH (= 0x0005): | |||
* Each logical unit is mapped to 0.001 inch. | |||
* Positive x is to the right; positive y is up. | |||
* | |||
* MM_TWIPS (= 0x0006): | |||
* Each logical unit is mapped to one twentieth (1/20) of a point. | |||
* In printing, a point is 1/72 of an inch; therefore, 1/20 of a point is 1/1440 of an inch. | |||
* This unit is also known as a "twip". | |||
* Positive x is to the right; positive y is up. | |||
* | |||
* MM_ISOTROPIC (= 0x0007): | |||
* Logical units are mapped to arbitrary device units with equally scaled axes; | |||
* that is, one unit along the x-axis is equal to one unit along the y-axis. | |||
* The META_SETWINDOWEXT and META_SETVIEWPORTEXT records specify the units and the | |||
* orientation of the axes. | |||
* The processing application SHOULD make adjustments as necessary to ensure the x and y | |||
* units remain the same size. For example, when the window extent is set, the viewport | |||
* SHOULD be adjusted to keep the units isotropic. | |||
* | |||
* MM_ANISOTROPIC (= 0x0008): | |||
* Logical units are mapped to arbitrary units with arbitrarily scaled axes. | |||
*/ | |||
int mapMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setMapMode; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
mapMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps | |||
* logical fonts to physical fonts. | |||
*/ | |||
public static class WmfSetMapperFlags implements HwmfRecord { | |||
/** | |||
* A 32-bit unsigned integer that defines whether the font mapper should attempt to | |||
* match a font's aspect ratio to the current device's aspect ratio. If bit 0 is | |||
* set, the mapper selects only matching fonts. | |||
*/ | |||
long mapperValues; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setMapperFlags; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
mapperValues = leis.readUInt(); | |||
return LittleEndianConsts.INT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETROP2 record defines the foreground raster operation mix mode in the playback device | |||
* context. The foreground mix mode is the mode for combining pens and interiors of filled objects with | |||
* foreground colors on the output surface. | |||
*/ | |||
public static class WmfSetRop2 implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the foreground binary raster | |||
* operation mixing mode. This MUST be one of the values: | |||
* R2_BLACK = 0x0001, | |||
* R2_NOTMERGEPEN = 0x0002, | |||
* R2_MASKNOTPEN = 0x0003, | |||
* R2_NOTCOPYPEN = 0x0004, | |||
* R2_MASKPENNOT = 0x0005, | |||
* R2_NOT = 0x0006, | |||
* R2_XORPEN = 0x0007, | |||
* R2_NOTMASKPEN = 0x0008, | |||
* R2_MASKPEN = 0x0009, | |||
* R2_NOTXORPEN = 0x000A, | |||
* R2_NOP = 0x000B, | |||
* R2_MERGENOTPEN = 0x000C, | |||
* R2_COPYPEN = 0x000D, | |||
* R2_MERGEPENNOT = 0x000E, | |||
* R2_MERGEPEN = 0x000F, | |||
* R2_WHITE = 0x0010 | |||
*/ | |||
int drawMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setRop2; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
drawMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device | |||
* context. | |||
*/ | |||
public static class WmfSetStretchBltMode implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines bitmap stretching mode. | |||
* This MUST be one of the values: | |||
* BLACKONWHITE = 0x0001, | |||
* WHITEONBLACK = 0x0002, | |||
* COLORONCOLOR = 0x0003, | |||
* HALFTONE = 0x0004 | |||
*/ | |||
int setStretchBltMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setStretchBltMode; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
setStretchBltMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a | |||
* pattern specified by a DeviceIndependentBitmap (DIB) Object | |||
*/ | |||
public static class WmfDibCreatePatternBrush implements HwmfRecord { | |||
HwmfBrushStyle style; | |||
/** | |||
* A 16-bit unsigned integer that defines whether the Colors field of a DIB | |||
* Object contains explicit RGB values, or indexes into a palette. | |||
* | |||
* If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be | |||
* used regardless of the contents of this field. | |||
* | |||
* If the Style field specified anything but BS_PATTERN, this field MUST be one of the values: | |||
* DIB_RGB_COLORS = 0x0000, | |||
* DIB_PAL_COLORS = 0x0001, | |||
* DIB_PAL_INDICES = 0x0002 | |||
*/ | |||
int colorUsage; | |||
HwmfBitmapDib patternDib; | |||
HwmfBitmap16 pattern16; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.dibCreatePatternBrush; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
style = HwmfBrushStyle.valueOf(leis.readUShort()); | |||
colorUsage = leis.readUShort(); | |||
int size = 2*LittleEndianConsts.SHORT_SIZE; | |||
switch (style) { | |||
case BS_SOLID: | |||
case BS_NULL: | |||
case BS_DIBPATTERN: | |||
case BS_DIBPATTERNPT: | |||
case BS_HATCHED: | |||
patternDib = new HwmfBitmapDib(); | |||
size += patternDib.init(leis); | |||
break; | |||
case BS_PATTERN: | |||
pattern16 = new HwmfBitmap16(); | |||
size += pattern16.init(leis); | |||
break; | |||
case BS_INDEXED: | |||
case BS_DIBPATTERN8X8: | |||
case BS_MONOPATTERN: | |||
case BS_PATTERN8X8: | |||
throw new RuntimeException("pattern not supported"); | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_DELETEOBJECT record deletes an object, including Bitmap16, Brush, | |||
* DeviceIndependentBitmap, Font, Palette, Pen, and Region. After the object is deleted, | |||
* its index in the WMF Object Table is no longer valid but is available to be reused. | |||
*/ | |||
public static class WmfDeleteObject implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to | |||
get the object to be deleted. | |||
*/ | |||
int objectIndex; | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.deleteObject; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
objectIndex = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
public static class WmfCreatePatternBrush implements HwmfRecord { | |||
HwmfBitmap16 pattern; | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.createPatternBrush; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
pattern = new HwmfBitmap16(true); | |||
return pattern.init(leis); | |||
} | |||
} | |||
public static class WmfCreatePenIndirect implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that specifies the pen style. | |||
* The value MUST be defined from the PenStyle Enumeration table. | |||
* | |||
* PS_COSMETIC = 0x0000, | |||
* PS_ENDCAP_ROUND = 0x0000, | |||
* PS_JOIN_ROUND = 0x0000, | |||
* PS_SOLID = 0x0000, | |||
* PS_DASH = 0x0001, | |||
* PS_DOT = 0x0002, | |||
* PS_DASHDOT = 0x0003, | |||
* PS_DASHDOTDOT = 0x0004, | |||
* PS_NULL = 0x0005, | |||
* PS_INSIDEFRAME = 0x0006, | |||
* PS_USERSTYLE = 0x0007, | |||
* PS_ALTERNATE = 0x0008, | |||
* PS_ENDCAP_SQUARE = 0x0100, | |||
* PS_ENDCAP_FLAT = 0x0200, | |||
* PS_JOIN_BEVEL = 0x1000, | |||
* PS_JOIN_MITER = 0x2000 | |||
*/ | |||
int penStyle; | |||
/** | |||
* A 32-bit PointS Object that specifies a point for the object dimensions. | |||
* The xcoordinate is the pen width. The y-coordinate is ignored. | |||
*/ | |||
int xWidth, yWidth; | |||
/** | |||
* A 32-bit ColorRef Object that specifies the pen color value. | |||
*/ | |||
HwmfColorRef colorRef; | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.createPenIndirect; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
penStyle = leis.readUShort(); | |||
xWidth = leis.readShort(); | |||
yWidth = leis.readShort(); | |||
colorRef = new HwmfColorRef(); | |||
int size = 3*LittleEndianConsts.SHORT_SIZE; | |||
size += colorRef.init(leis); | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_CREATEBRUSHINDIRECT record creates a Brush Object | |||
* from a LogBrush Object. | |||
* | |||
* The following table shows the relationship between values in the BrushStyle, | |||
* ColorRef and BrushHatch fields in a LogBrush Object. Only supported brush styles are listed. | |||
* | |||
* <table> | |||
* <tr> | |||
* <th>BrushStyle</th> | |||
* <th>ColorRef</th> | |||
* <th>BrushHatch</th> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_SOLID</td> | |||
* <td>SHOULD be a ColorRef Object, which determines the color of the brush.</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_NULL</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_PATTERN</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_DIBPATTERN</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created</td> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_DIBPATTERNPT</td> | |||
* <td>Not used, and SHOULD be ignored.</td> | |||
* <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td> | |||
* </tr> | |||
* <tr> | |||
* <td>BS_HATCHED</td> | |||
* <td>SHOULD be a ColorRef Object, which determines the foreground color of the hatch pattern.</td> | |||
* <td>A value from the {@link HwmfHatchStyle} Enumeration that specifies the orientation of lines used to create the hatch.</td> | |||
* </tr> | |||
* </table> | |||
*/ | |||
public static class WmfCreateBrushIndirect implements HwmfRecord { | |||
HwmfBrushStyle brushStyle; | |||
HwmfColorRef colorRef; | |||
/** | |||
* A 16-bit field that specifies the brush hatch type. | |||
* Its interpretation depends on the value of BrushStyle. | |||
* | |||
*/ | |||
HwmfHatchStyle brushHatch; | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.createBrushIndirect; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
brushStyle = HwmfBrushStyle.valueOf(leis.readUShort()); | |||
colorRef = new HwmfColorRef(); | |||
int size = colorRef.init(leis); | |||
brushHatch = HwmfHatchStyle.valueOf(leis.readUShort()); | |||
size += 4; | |||
return size; | |||
} | |||
} | |||
} |
@@ -0,0 +1,163 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfPalette { | |||
public static class PaletteEntry { | |||
// Values (1 byte): An 8-bit unsigned integer that defines how the palette entry is to be used. | |||
// The Values field MUST be 0x00 or one of the values in the PaletteEntryFlag Enumeration table. | |||
// Blue (1 byte): An 8-bit unsigned integer that defines the blue intensity value for the palette entry. | |||
// Green (1 byte): An 8-bit unsigned integer that defines the green intensity value for the palette entry. | |||
// Red (1 byte): An 8-bit unsigned integer that defines the red intensity value for the palette entry. | |||
int values, blue, green, red; | |||
public int init(LittleEndianInputStream leis) throws IOException { | |||
values = leis.readUByte(); | |||
blue = leis.readUByte(); | |||
green = leis.readUByte(); | |||
red = leis.readUByte(); | |||
return 4*LittleEndianConsts.BYTE_SIZE; | |||
} | |||
} | |||
public static abstract class WmfPaletteParent implements HwmfRecord { | |||
/** | |||
* Start (2 bytes): A 16-bit unsigned integer that defines the offset into the Palette Object when | |||
* used with the META_SETPALENTRIES and META_ANIMATEPALETTE record types. | |||
* When used with META_CREATEPALETTE, it MUST be 0x0300 | |||
*/ | |||
int start; | |||
/** | |||
* NumberOfEntries (2 bytes): A 16-bit unsigned integer that defines the number of objects in | |||
* aPaletteEntries. | |||
*/ | |||
int numberOfEntries; | |||
PaletteEntry entries[]; | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
start = leis.readUShort(); | |||
numberOfEntries = leis.readUShort(); | |||
int size = 2*LittleEndianConsts.SHORT_SIZE; | |||
entries = new PaletteEntry[numberOfEntries]; | |||
for (int i=0; i<numberOfEntries; i++) { | |||
entries[i] = new PaletteEntry(); | |||
size += entries[i].init(leis); | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_CREATEPALETTE record creates a Palette Object | |||
*/ | |||
public static class WmfCreatePalette extends WmfPaletteParent { | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.createPalette; | |||
} | |||
} | |||
/** | |||
* The META_SETPALENTRIES record defines RGB color values in a range of entries in the logical | |||
* palette that is defined in the playback device context. | |||
*/ | |||
public static class WmfSetPaletteEntries extends WmfPaletteParent { | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setPalEntries; | |||
} | |||
} | |||
/** | |||
* The META_RESIZEPALETTE record redefines the size of the logical palette that is defined in the | |||
* playback device context. | |||
*/ | |||
public static class WmfResizePalette implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the number of entries in | |||
* the logical palette. | |||
*/ | |||
int numberOfEntries; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.resizePalette; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
numberOfEntries = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SELECTPALETTE record defines the current logical palette with a specified Palette Object. | |||
*/ | |||
public static class WmfSelectPalette implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the Palette Object to be selected. | |||
*/ | |||
int palette; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.selectPalette; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
palette = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_REALIZEPALETTE record maps entries from the logical palette that | |||
* is defined in the playback device context to the system palette. | |||
*/ | |||
public static class WmfRealizePalette implements HwmfRecord { | |||
public HwmfRecordType getRecordType() { return HwmfRecordType.realizePalette; } | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
return 0; | |||
} | |||
} | |||
/** | |||
* The META_ANIMATEPALETTE record redefines entries in the logical palette that | |||
* is defined in the playback device context with the specified Palette object | |||
* | |||
* The logical palette that is specified by the Palette object in this record is the | |||
* source of the palette changes, and the logical palette that is currently selected | |||
* into the playback device context is the destination. Entries in the destination | |||
* palette with the PC_RESERVED PaletteEntryFlag set SHOULD be modified by this record, | |||
* and entries with that flag clear SHOULD NOT be modified. | |||
* If none of the entries in the destination palette have the PC_RESERVED flag set, then | |||
* this record SHOULD have no effect. | |||
*/ | |||
public static class WmfAnimatePalette extends WmfPaletteParent { | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.animatePalette; | |||
} | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfPlaceableHeader { | |||
public static int WMF_HEADER_MAGIC = 0x9AC6CDD7; | |||
protected HwmfPlaceableHeader(LittleEndianInputStream leis) throws IOException { | |||
/* | |||
* HWmf (2 bytes): The resource handle to the metafile, when the metafile is in memory. When | |||
* the metafile is on disk, this field MUST contain 0x0000. This attribute of the metafile is | |||
* specified in the Type field of the META_HEADER record. | |||
*/ | |||
leis.readShort(); // ignore | |||
/* | |||
* BoundingBox (8 bytes): The destination rectangle, measured in logical units, for displaying | |||
* the metafile. The size of a logical unit is specified by the Inch field. | |||
*/ | |||
int x1 = leis.readShort(); | |||
int y1 = leis.readShort(); | |||
int x2 = leis.readShort(); | |||
int y2 = leis.readShort(); | |||
/* | |||
* Inch (2 bytes): The number of logical units per inch used to represent the image. | |||
* This value can be used to scale an image. | |||
* By convention, an image is considered to be recorded at 1440 logical units (twips) per inch. | |||
* Thus, a value of 720 specifies that the image SHOULD be rendered at twice its normal size, | |||
* and a value of 2880 specifies that the image SHOULD be rendered at half its normal size. | |||
*/ | |||
int inch = leis.readShort(); | |||
/* | |||
* Reserved (4 bytes): A field that is not used and MUST be set to 0x00000000. | |||
*/ | |||
leis.readInt(); | |||
/* | |||
* Checksum (2 bytes): A checksum for the previous 10 16-bit values in the header. | |||
* This value can be used to determine whether the metafile has become corrupted. | |||
*/ | |||
leis.readShort(); | |||
} | |||
public static HwmfPlaceableHeader readHeader(LittleEndianInputStream leis) throws IOException { | |||
leis.mark(LittleEndianConsts.INT_SIZE); | |||
int magic = leis.readInt(); | |||
if (magic == WMF_HEADER_MAGIC) { | |||
return new HwmfPlaceableHeader(leis); | |||
} else { | |||
leis.reset(); | |||
return null; | |||
} | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public interface HwmfRecord { | |||
HwmfRecordType getRecordType(); | |||
/** | |||
* Init record from stream | |||
* | |||
* @param leis the little endian input stream | |||
* @return count of processed bytes | |||
* @throws IOException | |||
*/ | |||
int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException; | |||
} |
@@ -0,0 +1,111 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
/** | |||
* Available record types for WMF | |||
* | |||
* @see <a href="http://www.symantec.com/avcenter/reference/inside.the.windows.meta.file.format.pdf">Inside the Windows Meta File Format</a> | |||
*/ | |||
public enum HwmfRecordType { | |||
eof(0x0000, null), | |||
realizePalette(0x0035, HwmfPalette.WmfRealizePalette.class), | |||
setPalEntries(0x0037, HwmfPalette.WmfSetPaletteEntries.class), | |||
setBkMode(0x0102, HwmfMisc.WmfSetBkMode.class), | |||
setMapMode(0x0103, HwmfMisc.WmfSetMapMode.class), | |||
setRop2(0x0104, HwmfMisc.WmfSetRop2.class), | |||
setRelabs(0x0105, HwmfMisc.WmfSetRelabs.class), | |||
setPolyFillMode(0x0106, HwmfFill.WmfSetPolyfillMode.class), | |||
setStretchBltMode(0x0107, HwmfMisc.WmfSetStretchBltMode.class), | |||
setTextCharExtra(0x0108, HwmfText.WmfSetTextCharExtra.class), | |||
restoreDc(0x0127, HwmfMisc.WmfRestoreDc.class), | |||
resizePalette(0x0139, HwmfPalette.WmfResizePalette.class), | |||
dibCreatePatternBrush(0x0142, HwmfMisc.WmfDibCreatePatternBrush.class), | |||
setLayout(0x0149, HwmfMisc.WmfSetLayout.class), | |||
setBkColor(0x0201, HwmfMisc.WmfSetBkColor.class), | |||
setTextColor(0x0209, HwmfText.WmfSetTextColor.class), | |||
offsetViewportOrg(0x0211, HwmfWindowing.WmfOffsetViewportOrg.class), | |||
lineTo(0x0213, HwmfDraw.WmfLineTo.class), | |||
moveTo(0x0214, HwmfDraw.WmfMoveTo.class), | |||
offsetClipRgn(0x0220, HwmfWindowing.WmfOffsetClipRgn.class), | |||
fillRegion(0x0228, HwmfFill.WmfFillRegion.class), | |||
setMapperFlags(0x0231, HwmfMisc.WmfSetMapperFlags.class), | |||
selectPalette(0x0234, HwmfPalette.WmfSelectPalette.class), | |||
polygon(0x0324, HwmfDraw.WmfPolygon.class), | |||
polyline(0x0325, HwmfDraw.WmfPolyline.class), | |||
setTextJustification(0x020a, HwmfText.WmfSetTextJustification.class), | |||
setWindowOrg(0x020b, HwmfWindowing.WmfSetWindowOrg.class), | |||
setWindowExt(0x020c, HwmfWindowing.WmfSetWindowExt.class), | |||
setViewportOrg(0x020d, HwmfWindowing.WmfSetViewportOrg.class), | |||
setViewportExt(0x020e, HwmfWindowing.WmfSetViewportExt.class), | |||
offsetWindowOrg(0x020f, HwmfWindowing.WmfOffsetWindowOrg.class), | |||
scaleWindowExt(0x0410, HwmfWindowing.WmfScaleWindowExt.class), | |||
scaleViewportExt(0x0412, HwmfWindowing.WmfScaleViewportExt.class), | |||
excludeClipRect(0x0415, HwmfWindowing.WmfExcludeClipRect.class), | |||
intersectClipRect(0x0416, HwmfWindowing.WmfIntersectClipRect.class), | |||
ellipse(0x0418, HwmfDraw.WmfEllipse.class), | |||
floodFill(0x0419, HwmfFill.WmfFloodFill.class), | |||
frameRegion(0x0429, HwmfDraw.WmfFrameRegion.class), | |||
animatePalette(0x0436, HwmfPalette.WmfAnimatePalette.class), | |||
textOut(0x0521, HwmfText.WmfTextOut.class), | |||
polyPolygon(0x0538, HwmfDraw.WmfPolyPolygon.class), | |||
extFloodFill(0x0548, HwmfFill.WmfExtFloodFill.class), | |||
rectangle(0x041b, HwmfDraw.WmfRectangle.class), | |||
setPixel(0x041f, HwmfDraw.WmfSetPixel.class), | |||
roundRect(0x061c, HwmfDraw.WmfRoundRect.class), | |||
patBlt(0x061d, HwmfFill.WmfPatBlt.class), | |||
saveDc(0x001e, HwmfMisc.WmfSaveDc.class), | |||
pie(0x081a, HwmfDraw.WmfPie.class), | |||
stretchBlt(0x0b23, HwmfFill.WmfStretchBlt.class), | |||
escape(0x0626, HwmfEscape.class), | |||
invertRegion(0x012a, HwmfFill.WmfInvertRegion.class), | |||
paintRegion(0x012b, HwmfFill.WmfPaintRegion.class), | |||
selectClipRegion(0x012c, HwmfWindowing.WmfSelectClipRegion.class), | |||
selectObject(0x012d, HwmfDraw.WmfSelectObject.class), | |||
setTextAlign(0x012e, HwmfText.WmfSetTextAlign.class), | |||
arc(0x0817, HwmfDraw.WmfArc.class), | |||
chord(0x0830, HwmfDraw.WmfChord.class), | |||
bitBlt(0x0922, HwmfFill.WmfBitBlt.class), | |||
extTextOut(0x0a32, HwmfText.WmfExtTextOut.class), | |||
setDibToDev(0x0d33, HwmfFill.WmfSetDibToDev.class), | |||
dibBitBlt(0x0940, HwmfFill.WmfDibBitBlt.class), | |||
dibStretchBlt(0x0b41, HwmfFill.WmfDibStretchBlt.class), | |||
stretchDib(0x0f43, HwmfFill.WmfStretchDib.class), | |||
deleteObject(0x01f0, HwmfMisc.WmfDeleteObject.class), | |||
createPalette(0x00f7, HwmfPalette.WmfCreatePalette.class), | |||
createPatternBrush(0x01f9, HwmfMisc.WmfCreatePatternBrush.class), | |||
createPenIndirect(0x02fa, HwmfMisc.WmfCreatePenIndirect.class), | |||
createFontIndirect(0x02fb, HwmfText.WmfCreateFontIndirect.class), | |||
createBrushIndirect(0x02fc, HwmfMisc.WmfCreateBrushIndirect.class), | |||
createRegion(0x06ff, HwmfWindowing.WmfCreateRegion.class); | |||
public int id; | |||
public Class<? extends HwmfRecord> clazz; | |||
HwmfRecordType(int id, Class<? extends HwmfRecord> clazz) { | |||
this.id = id; | |||
this.clazz = clazz; | |||
} | |||
public static HwmfRecordType getById(int id) { | |||
for (HwmfRecordType wrt : values()) { | |||
if (wrt.id == id) return wrt; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,336 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
public enum HwmfTernaryRasterOp { | |||
BLACKNESS(0x0000,0x0042,"0"), | |||
DPSOON(0x0001,0x0289,"DPSoon"), | |||
DPSONA(0x0002,0x0C89,"DPSona"), | |||
PSON(0x0003,0x00AA,"PSon"), | |||
SDPONA(0x0004,0x0C88,"SDPona"), | |||
DPON(0x0005,0x00A9,"DPon"), | |||
PDSXNON(0x0006,0x0865,"PDSxnon"), | |||
PDSAON(0x0007,0x02C5,"PDSaon"), | |||
SDPNAA(0x0008,0x0F08,"SDPnaa"), | |||
PDSXON(0x0009,0x0245,"PDSxon"), | |||
DPNA(0x000A,0x0329,"DPna"), | |||
PSDNAON(0x000B,0x0B2A,"PSDnaon"), | |||
SPNA(0x000C,0x0324,"SPna"), | |||
PDSNAON(0x000D,0x0B25,"PDSnaon"), | |||
PDSONON(0x000E,0x08A5,"PDSonon"), | |||
PN(0x000F,0x0001,"Pn"), | |||
PDSONA(0x0010,0x0C85,"PDSona"), | |||
NOTSRCERASE(0x0011,0x00A6,"DSon"), | |||
SDPXNON(0x0012,0x0868,"SDPxnon"), | |||
SDPAON(0x0013,0x02C8,"SDPaon"), | |||
DPSXNON(0x0014,0x0869,"DPSxnon"), | |||
DPSAON(0x0015,0x02C9,"DPSaon"), | |||
PSDPSANAXX(0x0016,0x5CCA,"PSDPSanaxx"), | |||
SSPXDSXAXN(0x0017,0x1D54,"SSPxDSxaxn"), | |||
SPXPDXA(0x0018,0x0D59,"SPxPDxa"), | |||
SDPSANAXN(0x0019,0x1CC8,"SDPSanaxn"), | |||
PDSPAOX(0x001A,0x06C5,"PDSPaox"), | |||
SDPSXAXN(0x001B,0x0768,"SDPSxaxn"), | |||
PSDPAOX(0x001C,0x06CA,"PSDPaox"), | |||
DSPDXAXN(0x001D,0x0766,"DSPDxaxn"), | |||
PDSOX(0x001E,0x01A5,"PDSox"), | |||
PDSOAN(0x001F,0x0385,"PDSoan"), | |||
DPSNAA(0x0020,0x0F09,"DPSnaa"), | |||
SDPXON(0x0021,0x0248,"SDPxon"), | |||
DSNA(0x0022,0x0326,"DSna"), | |||
SPDNAON(0x0023,0x0B24,"SPDnaon"), | |||
SPXDSXA(0x0024,0x0D55,"SPxDSxa"), | |||
PDSPANAXN(0x0025,0x1CC5,"PDSPanaxn"), | |||
SDPSAOX(0x0026,0x06C8,"SDPSaox"), | |||
SDPSXNOX(0x0027,0x1868,"SDPSxnox"), | |||
DPSXA(0x0028,0x0369,"DPSxa"), | |||
PSDPSAOXXN(0x0029,0x16CA,"PSDPSaoxxn"), | |||
DPSANA(0x002A,0x0CC9,"DPSana"), | |||
SSPXPDXAXN(0x002B,0x1D58,"SSPxPDxaxn"), | |||
SPDSOAX(0x002C,0x0784,"SPDSoax"), | |||
PSDNOX(0x002D,0x060A,"PSDnox"), | |||
PSDPXOX(0x002E,0x064A,"PSDPxox"), | |||
PSDNOAN(0x002F,0x0E2A,"PSDnoan"), | |||
PSNA(0x0030,0x032A,"PSna"), | |||
SDPNAON(0x0031,0x0B28,"SDPnaon"), | |||
SDPSOOX(0x0032,0x0688,"SDPSoox"), | |||
NOTSRCCOPY(0x0033,0x0008,"Sn"), | |||
SPDSAOX(0x0034,0x06C4,"SPDSaox"), | |||
SPDSXNOX(0x0035,0x1864,"SPDSxnox"), | |||
SDPOX(0x0036,0x01A8,"SDPox"), | |||
SDPOAN(0x0037,0x0388,"SDPoan"), | |||
PSDPOAX(0x0038,0x078A,"PSDPoax"), | |||
SPDNOX(0x0390,0x604,"SPDnox"), | |||
SPDSXOX(0x003A,0x0644,"SPDSxox"), | |||
SPDNOAN(0x003B,0x0E24,"SPDnoan"), | |||
PSX(0x003C,0x004A,"PSx"), | |||
SPDSONOX(0x003D,0x18A4,"SPDSonox"), | |||
SPDSNAOX(0x003E,0x1B24,"SPDSnaox"), | |||
PSAN(0x003F,0x00EA,"PSan"), | |||
PSDNAA(0x0040,0x0F0A,"PSDnaa"), | |||
DPSXON(0x0041,0x0249,"DPSxon"), | |||
SDXPDXA(0x0042,0x0D5D,"SDxPDxa"), | |||
SPDSANAXN(0x0043,0x1CC4,"SPDSanaxn"), | |||
SRCERASE(0x0044,0x0328,"SDna"), | |||
DPSNAON(0x0045,0x0B29,"DPSnaon"), | |||
DSPDAOX(0x0046,0x06C6,"DSPDaox"), | |||
PSDPXAXN(0x0047,0x076A,"PSDPxaxn"), | |||
SDPXA(0x0048,0x0368,"SDPxa"), | |||
PDSPDAOXXN(0x0049,0x16C5,"PDSPDaoxxn"), | |||
DPSDOAX(0x004A,0x0789,"DPSDoax"), | |||
PDSNOX(0x004B,0x0605,"PDSnox"), | |||
SDPANA(0x004C,0x0CC8,"SDPana"), | |||
SSPXDSXOXN(0x004D,0x1954,"SSPxDSxoxn"), | |||
PDSPXOX(0x004E,0x0645,"PDSPxox"), | |||
PDSNOAN(0x004F,0x0E25,"PDSnoan"), | |||
PDNA(0x0050,0x0325,"PDna"), | |||
DSPNAON(0x0051,0x0B26,"DSPnaon"), | |||
DPSDAOX(0x0052,0x06C9,"DPSDaox"), | |||
SPDSXAXN(0x0053,0x0764,"SPDSxaxn"), | |||
DPSONON(0x0054,0x08A9,"DPSonon"), | |||
DSTINVERT(0x0055,0x0009,"Dn"), | |||
DPSOX(0x0056,0x01A9,"DPSox"), | |||
DPSOAN(0x0005,0x70389,"DPSoan"), | |||
PDSPOAX(0x0058,0x0785,"PDSPoax"), | |||
DPSNOX(0x0059,0x0609,"DPSnox"), | |||
PATINVERT(0x005A,0x0049,"DPx"), | |||
DPSDONOX(0x005B,0x18A9,"DPSDonox"), | |||
DPSDXOX(0x005C,0x0649,"DPSDxox"), | |||
DPSNOAN(0x005D,0x0E29,"DPSnoan"), | |||
DPSDNAOX(0x005E,0x1B29,"DPSDnaox"), | |||
DPAN(0x005F,0x00E9,"DPan"), | |||
PDSXA(0x0060,0x0365,"PDSxa"), | |||
DSPDSAOXXN(0x0061,0x16C6,"DSPDSaoxxn"), | |||
DSPDOAX(0x0062,0x0786,"DSPDoax"), | |||
SDPNOX(0x0063,0x0608,"SDPnox"), | |||
SDPSOAX(0x0064,0x0788,"SDPSoax"), | |||
DSPNOX(0x0065,0x0606,"DSPnox"), | |||
SRCINVERT(0x0066,0x0046,"DSx"), | |||
SDPSONOX(0x0067,0x18A8,"SDPSonox"), | |||
DSPDSONOXXN(0x0068,0x58A6,"DSPDSonoxxn"), | |||
PDSXXN(0x0069,0x0145,"PDSxxn"), | |||
DPSAX(0x006A,0x01E9,"DPSax"), | |||
PSDPSOAXXN(0x006B,0x178A,"PSDPSoaxxn"), | |||
SDPAX(0x006C,0x01E8,"SDPax"), | |||
PDSPDOAXXN(0x006D,0x1785,"PDSPDoaxxn"), | |||
SDPSNOAX(0x006E,0x1E28,"SDPSnoax"), | |||
// PDXNAN(0x006F,0x0C65,"PDXnan"), // invalid combo | |||
PDSANA(0x0070,0x0CC5,"PDSana"), | |||
SSDXPDXAXN(0x0071,0x1D5C,"SSDxPDxaxn"), | |||
SDPSXOX(0x0072,0x0648,"SDPSxox"), | |||
SDPNOAN(0x0073,0x0E28,"SDPnoan"), | |||
DSPDXOX(0x0074,0x0646,"DSPDxox"), | |||
DSPNOAN(0x0075,0x0E26,"DSPnoan"), | |||
SDPSNAOX(0x0076,0x1B28,"SDPSnaox"), | |||
DSAN(0x0077,0x00E6,"DSan"), | |||
PDSAX(0x0078,0x01E5,"PDSax"), | |||
DSPDSOAXXN(0x0079,0x1786,"DSPDSoaxxn"), | |||
DPSDNOAX(0x007A,0x1E29,"DPSDnoax"), | |||
SDPXNAN(0x007B,0x0C68,"SDPxnan"), | |||
SPDSNOAX(0x007C,0x1E24,"SPDSnoax"), | |||
DPSXNAN(0x007D,0x0C69,"DPSxnan"), | |||
SPXDSXO(0x007E,0x0955,"SPxDSxo"), | |||
DPSAAN(0x007F,0x03C9,"DPSaan"), | |||
DPSAA(0x0080,0x03E9,"DPSaa"), | |||
SPXDSXON(0x0081,0x0975,"SPxDSxon"), | |||
DPSXNA(0x0082,0x0C49,"DPSxna"), | |||
SPDSNOAXN(0x0083,0x1E04,"SPDSnoaxn"), | |||
SDPXNA(0x0084,0x0C48,"SDPxna"), | |||
PDSPNOAXN(0x0085,0x1E05,"PDSPnoaxn"), | |||
DSPDSOAXX(0x0086,0x17A6,"DSPDSoaxx"), | |||
PDSAXN(0x0087,0x01C5,"PDSaxn"), | |||
SRCAND(0x0088,0x00C6,"DSa"), | |||
SDPSNAOXN(0x0089,0x1B08,"SDPSnaoxn"), | |||
DSPNOA(0x008A,0x0E06,"DSPnoa"), | |||
DSPDXOXN(0x008B,0x0666,"DSPDxoxn"), | |||
SDPNOA(0x008C,0x0E08,"SDPnoa"), | |||
SDPSXOXN(0x008D,0x0668,"SDPSxoxn"), | |||
SSDXPDXAX(0x008E,0x1D7C,"SSDxPDxax"), | |||
PDSANAN(0x008F,0x0CE5,"PDSanan"), | |||
PDSXNA(0x0090,0x0C45,"PDSxna"), | |||
SDPSNOAXN(0x0091,0x1E08,"SDPSnoaxn"), | |||
DPSDPOAXX(0x0092,0x17A9,"DPSDPoaxx"), | |||
SPDAXN(0x0093,0x01C4,"SPDaxn"), | |||
PSDPSOAXX(0x0094,0x17AA,"PSDPSoaxx"), | |||
DPSAXN(0x0095,0x01C9,"DPSaxn"), | |||
DPSXX(0x0096,0x0169,"DPSxx"), | |||
PSDPSONOXX(0x0097,0x588A,"PSDPSonoxx"), | |||
SDPSONOXN(0x0098,0x1888,"SDPSonoxn"), | |||
DSXN(0x0099,0x0066,"DSxn"), | |||
DPSNAX(0x009A,0x0709,"DPSnax"), | |||
SDPSOAXN(0x009B,0x07A8,"SDPSoaxn"), | |||
SPDNAX(0x009C,0x0704,"SPDnax"), | |||
DSPDOAXN(0x009D,0x07A6,"DSPDoaxn"), | |||
DSPDSAOXX(0x009E,0x16E6,"DSPDSaoxx"), | |||
PDSXAN(0x009F,0x0345,"PDSxan"), | |||
DPA(0x00A0,0x00C9,"DPa"), | |||
PDSPNAOXN(0x00A1,0x1B05,"PDSPnaoxn"), | |||
DPSNOA(0x00A2,0x0E09,"DPSnoa"), | |||
DPSDXOXN(0x00A3,0x0669,"DPSDxoxn"), | |||
PDSPONOXN(0x00A4,0x1885,"PDSPonoxn"), | |||
PDXN(0x00A5,0x0065,"PDxn"), | |||
DSPNAX(0x00A6,0x0706,"DSPnax"), | |||
PDSPOAXN(0x00A7,0x07A5,"PDSPoaxn"), | |||
DPSOA(0x00A8,0x03A9,"DPSoa"), | |||
DPSOXN(0x00A9,0x0189,"DPSoxn"), | |||
D(0x00AA,0x0029,"D"), | |||
DPSONO(0x00AB,0x0889,"DPSono"), | |||
SPDSXAX(0x00AC,0x0744,"SPDSxax"), | |||
DPSDAOXN(0x00AD,0x06E9,"DPSDaoxn"), | |||
DSPNAO(0x00AE,0x0B06,"DSPnao"), | |||
DPNO(0x00AF,0x0229,"DPno"), | |||
PDSNOA(0x00B0,0x0E05,"PDSnoa"), | |||
PDSPXOXN(0x00B1,0x0665,"PDSPxoxn"), | |||
SSPXDSXOX(0x00B2,0x1974,"SSPxDSxox"), | |||
SDPANAN(0x00B3,0x0CE8,"SDPanan"), | |||
PSDNAX(0x00B4,0x070A,"PSDnax"), | |||
DPSDOAXN(0x00B5,0x07A9,"DPSDoaxn"), | |||
DPSDPAOXX(0x00B6,0x16E9,"DPSDPaoxx"), | |||
SDPXAN(0x00B7,0x0348,"SDPxan"), | |||
PSDPXAX(0x00B8,0x074A,"PSDPxax"), | |||
DSPDAOXN(0x00B9,0x06E6,"DSPDaoxn"), | |||
DPSNAO(0x00BA,0x0B09,"DPSnao"), | |||
MERGEPAINT(0x00BB,0x0226,"DSno"), | |||
SPDSANAX(0x00BC,0x1CE4,"SPDSanax"), | |||
SDXPDXAN(0x00BD,0x0D7D,"SDxPDxan"), | |||
DPSXO(0x00BE,0x0269,"DPSxo"), | |||
DPSANO(0x00BF,0x08C9,"DPSano"), | |||
MERGECOPY(0x00C0,0x00CA,"PSa"), | |||
SPDSNAOXN(0x00C1,0x1B04,"SPDSnaoxn"), | |||
SPDSONOXN(0x00C2,0x1884,"SPDSonoxn"), | |||
PSXN(0x00C3,0x006A,"PSxn"), | |||
SPDNOA(0x00C4,0x0E04,"SPDnoa"), | |||
SPDSXOXN(0x00C5,0x0664,"SPDSxoxn"), | |||
SDPNAX(0x00C6,0x0708,"SDPnax"), | |||
PSDPOAXN(0x00C7,0x07AA,"PSDPoaxn"), | |||
SDPOA(0x00C8,0x03A8,"SDPoa"), | |||
SPDOXN(0x00C9,0x0184,"SPDoxn"), | |||
DPSDXAX(0x00CA,0x0749,"DPSDxax"), | |||
SPDSAOXN(0x00CB,0x06E4,"SPDSaoxn"), | |||
SRCCOPY(0x00CC,0x0020,"S"), | |||
SDPONO(0x00CD,0x0888,"SDPono"), | |||
SDPNAO(0x00CE,0x0B08,"SDPnao"), | |||
SPNO(0x00CF,0x0224,"SPno"), | |||
PSDNOA(0x00D0,0x0E0A,"PSDnoa"), | |||
PSDPXOXN(0x00D1,0x066A,"PSDPxoxn"), | |||
PDSNAX(0x00D2,0x0705,"PDSnax"), | |||
SPDSOAXN(0x00D3,0x07A4,"SPDSoaxn"), | |||
SSPXPDXAX(0x00D4,0x1D78,"SSPxPDxax"), | |||
DPSANAN(0x00D5,0x0CE9,"DPSanan"), | |||
PSDPSAOXX(0x00D6,0x16EA,"PSDPSaoxx"), | |||
DPSXAN(0x00D7,0x0349,"DPSxan"), | |||
PDSPXAX(0x00D8,0x0745,"PDSPxax"), | |||
SDPSAOXN(0x00D9,0x06E8,"SDPSaoxn"), | |||
DPSDANAX(0x00DA,0x1CE9,"DPSDanax"), | |||
SPXDSXAN(0x00DB,0x0D75,"SPxDSxan"), | |||
SPDNAO(0x00DC,0x0B04,"SPDnao"), | |||
SDNO(0x00DD,0x0228,"SDno"), | |||
SDPXO(0x00DE,0x0268,"SDPxo"), | |||
SDPANO(0x00DF,0x08C8,"SDPano"), | |||
PDSOA(0x00E0,0x03A5,"PDSoa"), | |||
PDSOXN(0x00E1,0x0185,"PDSoxn"), | |||
DSPDXAX(0x00E2,0x0746,"DSPDxax"), | |||
PSDPAOXN(0x00E3,0x06EA,"PSDPaoxn"), | |||
SDPSXAX(0x00E4,0x0748,"SDPSxax"), | |||
PDSPAOXN(0x00E5,0x06E5,"PDSPaoxn"), | |||
SDPSANAX(0x00E6,0x1CE8,"SDPSanax"), | |||
SPXPDXAN(0x00E7,0x0D79,"SPxPDxan"), | |||
SSPXDSXAX(0x00E8,0x1D74,"SSPxDSxax"), | |||
DSPDSANAXXN(0x00E9,0x5CE6,"DSPDSanaxxn"), | |||
DPSAO(0x00EA,0x02E9,"DPSao"), | |||
DPSXNO(0x00EB,0x0849,"DPSxno"), | |||
SDPAO(0x00EC,0x02E8,"SDPao"), | |||
SDPXNO(0x00ED,0x0848,"SDPxno"), | |||
SRCPAINT(0x00EE,0x0086,"DSo"), | |||
SDPNOO(0x00EF,0x0A08,"SDPnoo"), | |||
PATCOPY(0x00F0,0x0021,"P"), | |||
PDSONO(0x00F1,0x0885,"PDSono"), | |||
PDSNAO(0x00F2,0x0B05,"PDSnao"), | |||
PSNO(0x00F3,0x022A,"PSno"), | |||
PSDNAO(0x00F4,0x0B0A,"PSDnao"), | |||
PDNO(0x00F5,0x0225,"PDno"), | |||
PDSXO(0x00F6,0x0265,"PDSxo"), | |||
PDSANO(0x00F7,0x08C5,"PDSano"), | |||
PDSAO(0x00F8,0x02E5,"PDSao"), | |||
PDSXNO(0x00F9,0x0845,"PDSxno"), | |||
DPO(0x00FA,0x0089,"DPo"), | |||
PATPAINT(0x00FB,0x0A09,"DPSnoo"), | |||
PSO(0x00FC,0x008A,"PSo"), | |||
PSDNOO(0x00FD,0x0A0A,"PSDnoo"), | |||
DPSOO(0x00FE,0x02A9,"DPSoo"), | |||
WHITENESS(0x00FF,0x0062,"1"); | |||
int opIndex; | |||
int opCode; | |||
String opCmd; | |||
HwmfTernaryRasterOp(int opIndex, int opCode, String opCmd) { | |||
this.opIndex=opIndex; | |||
this.opCode=opCode; | |||
this.opCmd=opCmd; | |||
} | |||
public static HwmfTernaryRasterOp fromOpIndex(int opIndex) { | |||
for (HwmfTernaryRasterOp bb : HwmfTernaryRasterOp.values()) { | |||
if (bb.opIndex == opIndex) { | |||
return bb; | |||
} | |||
} | |||
return null; | |||
} | |||
public String describeCmd() { | |||
String stack[] = new String[10]; | |||
int stackPnt = 0; | |||
for (char c : opCmd.toCharArray()) { | |||
switch (c) { | |||
case 'S': | |||
case 'D': | |||
case 'P': | |||
stack[stackPnt++] = ""+c; | |||
break; | |||
case 'n': | |||
stack[stackPnt-1] = "not("+stack[stackPnt-1]+")"; | |||
break; | |||
case 'a': | |||
stack[stackPnt-2] = "("+stack[stackPnt-1]+" and "+stack[stackPnt-2]+")"; | |||
stackPnt--; | |||
break; | |||
case 'o': | |||
stack[stackPnt-2] = "("+stack[stackPnt-1]+" or "+stack[stackPnt-2]+")"; | |||
stackPnt--; | |||
break; | |||
case 'x': | |||
stack[stackPnt-2] = "("+stack[stackPnt-1]+" xor "+stack[stackPnt-2]+")"; | |||
stackPnt--; | |||
break; | |||
case '1': | |||
stack[stackPnt++] = "all white"; | |||
break; | |||
case '0': | |||
stack[stackPnt++] = "all black"; | |||
break; | |||
default: | |||
throw new RuntimeException("unknown cmd '"+c+"'."); | |||
} | |||
} | |||
return stack[--stackPnt]; | |||
} | |||
} |
@@ -0,0 +1,347 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfText { | |||
/** | |||
* The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the | |||
* playback device context. Spacing is added to the white space between each character, including | |||
* break characters, when a line of justified text is output. | |||
*/ | |||
public static class WmfSetTextCharExtra implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines the amount of extra space, in | |||
* logical units, to be added to each character. If the current mapping mode is not MM_TEXT, | |||
* this value is transformed and rounded to the nearest pixel. For details about setting the | |||
* mapping mode, see META_SETMAPMODE | |||
*/ | |||
int charExtra; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setTextCharExtra; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
charExtra = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETTEXTCOLOR record defines the text foreground color in the playback device context. | |||
*/ | |||
public static class WmfSetTextColor implements HwmfRecord { | |||
HwmfColorRef colorRef; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setTextColor; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
colorRef = new HwmfColorRef(); | |||
return colorRef.init(leis); | |||
} | |||
} | |||
/** | |||
* The META_SETTEXTJUSTIFICATION record defines the amount of space to add to break characters | |||
* in a string of justified text. | |||
*/ | |||
public static class WmfSetTextJustification implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that specifies the number of space characters in the line. | |||
*/ | |||
int breakCount; | |||
/** | |||
* A 16-bit unsigned integer that specifies the total extra space, in logical | |||
* units, to be added to the line of text. If the current mapping mode is not MM_TEXT, the value | |||
* identified by the BreakExtra member is transformed and rounded to the nearest pixel. For | |||
* details about setting the mapping mode, see {@link WmfSetMapMode}. | |||
*/ | |||
int breakExtra; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setBkColor; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
breakCount = leis.readUShort(); | |||
breakExtra = leis.readUShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_TEXTOUT record outputs a character string at the specified location by using the font, | |||
* background color, and text color that are defined in the playback device context. | |||
*/ | |||
public static class WmfTextOut implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String. | |||
*/ | |||
int stringLength; | |||
/** | |||
* The size of this field MUST be a multiple of two. If StringLength is an odd | |||
* number, then this field MUST be of a size greater than or equal to StringLength + 1. | |||
* A variable-length string that specifies the text to be drawn. | |||
* The string does not need to be null-terminated, because StringLength specifies the | |||
* length of the string. | |||
* The string is written at the location specified by the XStart and YStart fields. | |||
*/ | |||
String text; | |||
/** | |||
* A 16-bit signed integer that defines the vertical (y-axis) coordinate, in logical | |||
* units, of the point where drawing is to start. | |||
*/ | |||
int yStart; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal (x-axis) coordinate, in | |||
* logical units, of the point where drawing is to start. | |||
*/ | |||
int xStart; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.textOut; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
stringLength = leis.readShort(); | |||
byte buf[] = new byte[stringLength+(stringLength%2)]; | |||
leis.readFully(buf); | |||
text = new String(buf, "UTF16-LE").trim(); | |||
yStart = leis.readShort(); | |||
xStart = leis.readShort(); | |||
return 3*LittleEndianConsts.SHORT_SIZE+buf.length; | |||
} | |||
} | |||
/** | |||
* The META_EXTTEXTOUT record outputs text by using the font, background color, and text color that | |||
* are defined in the playback device context. Optionally, dimensions can be provided for clipping, | |||
* opaquing, or both. | |||
*/ | |||
public static class WmfExtTextOut implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, where the | |||
text string is to be located. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, where the | |||
text string is to be located. | |||
*/ | |||
int x; | |||
/** | |||
* A 16-bit signed integer that defines the length of the string. | |||
*/ | |||
int stringLength; | |||
/** | |||
* A 16-bit unsigned integer that defines the use of the application-defined | |||
* rectangle. This member can be a combination of one or more values in the | |||
* ExtTextOutOptions Flags: | |||
* | |||
* ETO_OPAQUE (0x0002): | |||
* Indicates that the background color that is defined in the playback device context | |||
* SHOULD be used to fill the rectangle. | |||
* | |||
* ETO_CLIPPED (0x0004): | |||
* Indicates that the text SHOULD be clipped to the rectangle. | |||
* | |||
* ETO_GLYPH_INDEX (0x0010): | |||
* Indicates that the string to be output SHOULD NOT require further processing | |||
* with respect to the placement of the characters, and an array of character | |||
* placement values SHOULD be provided. This character placement process is | |||
* useful for fonts in which diacritical characters affect character spacing. | |||
* | |||
* ETO_RTLREADING (0x0080): | |||
* Indicates that the text MUST be laid out in right-to-left reading order, instead of | |||
* the default left-to-right order. This SHOULD be applied only when the font that is | |||
* defined in the playback device context is either Hebrew or Arabic. <37> | |||
* | |||
* ETO_NUMERICSLOCAL (0x0400): | |||
* Indicates that to display numbers, digits appropriate to the locale SHOULD be | |||
* used. | |||
* | |||
* ETO_NUMERICSLATIN (0x0800): | |||
* Indicates that to display numbers, European digits SHOULD be used. <39> | |||
* | |||
* ETO_PDY (0x2000): | |||
* Indicates that both horizontal and vertical character displacement values | |||
* SHOULD be provided. | |||
*/ | |||
int fwOpts; | |||
/** | |||
* An optional 8-byte Rect Object (section 2.2.2.18) that defines the | |||
* dimensions, in logical coordinates, of a rectangle that is used for clipping, opaquing, or both. | |||
* | |||
* The corners are given in the order left, top, right, bottom. | |||
* Each value is a 16-bit signed integer that defines the coordinate, in logical coordinates, of | |||
* the upper-left corner of the rectangle | |||
*/ | |||
int left,top,right,bottom; | |||
/** | |||
* A variable-length string that specifies the text to be drawn. The string does | |||
* not need to be null-terminated, because StringLength specifies the length of the string. If | |||
* the length is odd, an extra byte is placed after it so that the following member (optional Dx) is | |||
* aligned on a 16-bit boundary. | |||
*/ | |||
String text; | |||
/** | |||
* An optional array of 16-bit signed integers that indicate the distance between | |||
* origins of adjacent character cells. For example, Dx[i] logical units separate the origins of | |||
* character cell i and character cell i + 1. If this field is present, there MUST be the same | |||
* number of values as there are characters in the string. | |||
*/ | |||
int dx[]; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.extTextOut; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
stringLength = leis.readShort(); | |||
fwOpts = leis.readUShort(); | |||
left = leis.readShort(); | |||
top = leis.readShort(); | |||
right = leis.readShort(); | |||
bottom = leis.readShort(); | |||
byte buf[] = new byte[stringLength+(stringLength%2)]; | |||
leis.readFully(buf); | |||
text = new String(buf, "UTF16-LE"); | |||
int size = 8*LittleEndianConsts.SHORT_SIZE+buf.length; | |||
if (size < recordSize) { | |||
dx = new int[text.length()]; | |||
for (int i=0; i<dx.length; i++) { | |||
dx[i] = leis.readShort(); | |||
} | |||
size += dx.length*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
return size; | |||
} | |||
} | |||
/** | |||
* The META_SETTEXTALIGN record defines text-alignment values in the playback device context. | |||
*/ | |||
public static class WmfSetTextAlign implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer that defines text alignment. | |||
* This value MUST be a combination of one or more TextAlignmentMode Flags | |||
* for text with a horizontal baseline, and VerticalTextAlignmentMode Flags | |||
* for text with a vertical baseline. | |||
* | |||
* TextAlignmentMode Flags: | |||
* TA_NOUPDATECP (0x0000): | |||
* The drawing position in the playback device context MUST NOT be updated after each | |||
* text output call. The reference point MUST be passed to the text output function. | |||
* | |||
* TA_LEFT (0x0000): | |||
* The reference point MUST be on the left edge of the bounding rectangle. | |||
* | |||
* TA_TOP (0x0000): | |||
* The reference point MUST be on the top edge of the bounding rectangle. | |||
* | |||
* TA_UPDATECP (0x0001): | |||
* The drawing position in the playback device context MUST be updated after each text | |||
* output call. It MUST be used as the reference point. | |||
* | |||
* TA_RIGHT (0x0002): | |||
* The reference point MUST be on the right edge of the bounding rectangle. | |||
* | |||
* TA_CENTER (0x0006): | |||
* The reference point MUST be aligned horizontally with the center of the bounding | |||
* rectangle. | |||
* | |||
* TA_BOTTOM (0x0008): | |||
* The reference point MUST be on the bottom edge of the bounding rectangle. | |||
* | |||
* TA_BASELINE (0x0018): | |||
* The reference point MUST be on the baseline of the text. | |||
* | |||
* TA_RTLREADING (0x0100): | |||
* The text MUST be laid out in right-to-left reading order, instead of the default | |||
* left-toright order. This SHOULD be applied only when the font that is defined in the | |||
* playback device context is either Hebrew or Arabic. | |||
* | |||
* | |||
* VerticalTextAlignmentMode Flags (e.g. for Kanji fonts) | |||
* VTA_TOP (0x0000): | |||
* The reference point MUST be on the top edge of the bounding rectangle. | |||
* | |||
* VTA_RIGHT (0x0000): | |||
* The reference point MUST be on the right edge of the bounding rectangle. | |||
* | |||
* VTA_BOTTOM (0x0002): | |||
* The reference point MUST be on the bottom edge of the bounding rectangle. | |||
* | |||
* VTA_CENTER (0x0006): | |||
* The reference point MUST be aligned vertically with the center of the bounding | |||
* rectangle. | |||
* | |||
* VTA_LEFT (0x0008): | |||
* The reference point MUST be on the left edge of the bounding rectangle. | |||
* | |||
* VTA_BASELINE (0x0018): | |||
* The reference point MUST be on the baseline of the text. | |||
*/ | |||
int textAlignmentMode; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setTextAlign; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
textAlignmentMode = leis.readUShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
public static class WmfCreateFontIndirect implements HwmfRecord { | |||
HwmfFont font; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.createFontIndirect; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
font = new HwmfFont(); | |||
return font.init(leis); | |||
} | |||
} | |||
} |
@@ -0,0 +1,549 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.record; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfWindowing { | |||
/** | |||
* The META_OFFSETCLIPRGN record moves the clipping region in the playback device context by the | |||
* specified offsets. | |||
*/ | |||
public static class WmfOffsetClipRgn implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the number of logical units to move up or down. | |||
*/ | |||
int yOffset; | |||
/** | |||
* A 16-bit signed integer that defines the number of logical units to move left or right. | |||
*/ | |||
int xOffset; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.offsetClipRgn; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yOffset = leis.readShort(); | |||
xOffset = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETVIEWPORTORG record defines the viewport origin in the playback device context. | |||
*/ | |||
public static class WmfSetViewportOrg implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical offset, in device units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal offset, in device units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setViewportOrg; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETVIEWPORTEXT record sets the horizontal and vertical extents | |||
* of the viewport in the playback device context. | |||
*/ | |||
public static class WmfSetViewportExt implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical extent | |||
* of the viewport in device units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal extent | |||
* of the viewport in device units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setViewportExt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_OFFSETVIEWPORTORG record moves the viewport origin in the playback device context | |||
* by specified horizontal and vertical offsets. | |||
*/ | |||
public static class WmfOffsetViewportOrg implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical offset, in device units. | |||
*/ | |||
int yOffset; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal offset, in device units. | |||
*/ | |||
int xOffset; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.offsetViewportOrg; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yOffset = leis.readShort(); | |||
xOffset = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETWINDOWORG record defines the output window origin in the playback device context. | |||
*/ | |||
public static class WmfSetWindowOrg implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setWindowOrg; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SETWINDOWEXT record defines the horizontal and vertical extents | |||
* of the output window in the playback device context. | |||
*/ | |||
public static class WmfSetWindowExt implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical extent of | |||
* the window in logical units. | |||
*/ | |||
int y; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal extent of | |||
* the window in logical units. | |||
*/ | |||
int x; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.setWindowExt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
y = leis.readShort(); | |||
x = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_OFFSETWINDOWORG record moves the output window origin in the | |||
* playback device context by specified horizontal and vertical offsets. | |||
*/ | |||
public static class WmfOffsetWindowOrg implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the vertical offset, in device units. | |||
*/ | |||
int yOffset; | |||
/** | |||
* A 16-bit signed integer that defines the horizontal offset, in device units. | |||
*/ | |||
int xOffset; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.offsetWindowOrg; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yOffset = leis.readShort(); | |||
xOffset = leis.readShort(); | |||
return 2*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_OFFSETWINDOWORG record moves the output window origin in the | |||
* playback device context by specified horizontal and vertical offsets. | |||
*/ | |||
public static class WmfScaleWindowExt implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to divide the | |||
* result of multiplying the current y-extent by the value of the yNum member. | |||
*/ | |||
int yDenom; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to multiply the | |||
* current y-extent. | |||
*/ | |||
int yNum; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to divide the | |||
* result of multiplying the current x-extent by the value of the xNum member. | |||
*/ | |||
int xDenom; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to multiply the | |||
* current x-extent. | |||
*/ | |||
int xNum; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.scaleWindowExt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yDenom = leis.readShort(); | |||
yNum = leis.readShort(); | |||
xDenom = leis.readShort(); | |||
xNum = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_SCALEVIEWPORTEXT record scales the horizontal and vertical extents of the viewport | |||
* that is defined in the playback device context by using the ratios formed by the specified | |||
* multiplicands and divisors. | |||
*/ | |||
public static class WmfScaleViewportExt implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to divide the | |||
* result of multiplying the current y-extent by the value of the yNum member. | |||
*/ | |||
int yDenom; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to multiply the | |||
* current y-extent. | |||
*/ | |||
int yNum; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to divide the | |||
* result of multiplying the current x-extent by the value of the xNum member. | |||
*/ | |||
int xDenom; | |||
/** | |||
* A 16-bit signed integer that defines the amount by which to multiply the | |||
* current x-extent. | |||
*/ | |||
int xNum; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.scaleViewportExt; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
yDenom = leis.readShort(); | |||
yNum = leis.readShort(); | |||
xDenom = leis.readShort(); | |||
xNum = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_EXCLUDECLIPRECT record sets the clipping region in the playback device context to the | |||
* existing clipping region minus the specified rectangle. | |||
*/ | |||
public static class WmfExcludeClipRect implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int bottom; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int right; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int top; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int left; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.excludeClipRect; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
bottom = leis.readShort(); | |||
right = leis.readShort(); | |||
top = leis.readShort(); | |||
left = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_INTERSECTCLIPRECT record sets the clipping region in the playback device context to the | |||
* intersection of the existing clipping region and the specified rectangle. | |||
*/ | |||
public static class WmfIntersectClipRect implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int bottom; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int right; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int top; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int left; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.intersectClipRect; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
bottom = leis.readShort(); | |||
right = leis.readShort(); | |||
top = leis.readShort(); | |||
left = leis.readShort(); | |||
return 4*LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
/** | |||
* The META_INTERSECTCLIPRECT record sets the clipping region in the playback device context to the | |||
* intersection of the existing clipping region and the specified rectangle. | |||
*/ | |||
public static class WmfSelectClipRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit unsigned integer used to index into the WMF Object Table to get | |||
* the region to be clipped. | |||
*/ | |||
int region; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.selectClipRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
region = leis.readShort(); | |||
return LittleEndianConsts.SHORT_SIZE; | |||
} | |||
} | |||
public static class WmfScanObject { | |||
/** | |||
* A 16-bit unsigned integer that specifies the number of horizontal (x-axis) | |||
* coordinates in the ScanLines array. This value MUST be a multiple of 2, since left and right | |||
* endpoints are required to specify each scanline. | |||
*/ | |||
int count; | |||
/** | |||
* A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the top scanline. | |||
*/ | |||
int top; | |||
/** | |||
* A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the bottom scanline. | |||
*/ | |||
int bottom; | |||
/** | |||
* A 16-bit unsigned integer that defines the horizontal (x-axis) coordinate, | |||
* in logical units, of the left endpoint of the scanline. | |||
*/ | |||
int left_scanline[]; | |||
/** | |||
* A 16-bit unsigned integer that defines the horizontal (x-axis) coordinate, | |||
* in logical units, of the right endpoint of the scanline. | |||
*/ | |||
int right_scanline[]; | |||
/** | |||
* A 16-bit unsigned integer that MUST be the same as the value of the Count | |||
* field; it is present to allow upward travel in the structure. | |||
*/ | |||
int count2; | |||
public int init(LittleEndianInputStream leis) { | |||
count = leis.readUShort(); | |||
top = leis.readUShort(); | |||
bottom = leis.readUShort(); | |||
left_scanline = new int[count]; | |||
right_scanline = new int[count]; | |||
for (int i=0; i*2<count; i++) { | |||
left_scanline[i] = leis.readUShort(); | |||
right_scanline[i] = leis.readUShort(); | |||
} | |||
count2 = leis.readUShort(); | |||
return 8 + count*4; | |||
} | |||
} | |||
public static class WmfCreateRegion implements HwmfRecord { | |||
/** | |||
* A 16-bit signed integer. A value that MUST be ignored. | |||
*/ | |||
int nextInChain; | |||
/** | |||
* A 16-bit signed integer that specifies the region identifier. It MUST be 0x0006. | |||
*/ | |||
int objectType; | |||
/** | |||
* A 32-bit unsigned integer. A value that MUST be ignored. | |||
*/ | |||
int objectCount; | |||
/** | |||
* A 16-bit signed integer that defines the size of the region in bytes plus the size of aScans in bytes. | |||
*/ | |||
int regionSize; | |||
/** | |||
* A 16-bit signed integer that defines the number of scanlines composing the region. | |||
*/ | |||
int scanCount; | |||
/** | |||
* A 16-bit signed integer that defines the maximum number of points in any one scan in this region. | |||
*/ | |||
int maxScan; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int bottom; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* lower-right corner of the rectangle. | |||
*/ | |||
int right; | |||
/** | |||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int top; | |||
/** | |||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the | |||
* upper-left corner of the rectangle. | |||
*/ | |||
int left; | |||
/** | |||
* An array of Scan objects that define the scanlines in the region. | |||
*/ | |||
WmfScanObject scanObjects[]; | |||
public HwmfRecordType getRecordType() { | |||
return HwmfRecordType.createRegion; | |||
} | |||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { | |||
nextInChain = leis.readShort(); | |||
objectType = leis.readShort(); | |||
objectCount = leis.readUShort(); | |||
regionSize = leis.readShort(); | |||
scanCount = leis.readShort(); | |||
maxScan = leis.readShort(); | |||
bottom = leis.readShort(); | |||
right = leis.readShort(); | |||
top = leis.readShort(); | |||
left = leis.readShort(); | |||
List<WmfScanObject> soList = new ArrayList<WmfScanObject>(); | |||
int scanCountI = 0, size = 0; | |||
do { | |||
WmfScanObject so = new WmfScanObject(); | |||
size += so.init(leis); | |||
scanCountI += so.count; | |||
soList.add(so); | |||
} while (scanCountI < scanCount); | |||
scanObjects = soList.toArray(new WmfScanObject[soList.size()]); | |||
return 20 + size; | |||
} | |||
} | |||
} |
@@ -0,0 +1,75 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf.usermodel; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import org.apache.poi.hwmf.record.HwmfHeader; | |||
import org.apache.poi.hwmf.record.HwmfPlaceableHeader; | |||
import org.apache.poi.hwmf.record.HwmfRecord; | |||
import org.apache.poi.hwmf.record.HwmfRecordType; | |||
import org.apache.poi.util.LittleEndianInputStream; | |||
public class HwmfPicture { | |||
List<HwmfRecord> records = new ArrayList<HwmfRecord>(); | |||
public List<HwmfRecord> getRecords() { | |||
return Collections.unmodifiableList(records); | |||
} | |||
public HwmfPicture(InputStream inputStream) throws IOException { | |||
LittleEndianInputStream leis = new LittleEndianInputStream(inputStream); | |||
HwmfPlaceableHeader placeableHeader = HwmfPlaceableHeader.readHeader(leis); | |||
HwmfHeader header = new HwmfHeader(leis); | |||
for (;;) { | |||
// recordSize in DWORDs | |||
long recordSize = leis.readUInt()*2; | |||
int recordFunction = leis.readShort(); | |||
// 4 bytes (recordSize) + 2 bytes (recordFunction) | |||
int consumedSize = 6; | |||
HwmfRecordType wrt = HwmfRecordType.getById(recordFunction); | |||
if (wrt == null) { | |||
throw new IOException("unexpected record type: "+recordFunction); | |||
} | |||
if (wrt == HwmfRecordType.eof) break; | |||
if (wrt.clazz == null) { | |||
throw new IOException("unsupported record type: "+recordFunction); | |||
} | |||
HwmfRecord wr; | |||
try { | |||
wr = wrt.clazz.newInstance(); | |||
records.add(wr); | |||
} catch (Exception e) { | |||
throw (IOException)new IOException("can't create wmf record").initCause(e); | |||
} | |||
consumedSize += wr.init(leis, recordSize, recordFunction); | |||
if (consumedSize < recordSize) { | |||
leis.skip(recordSize - consumedSize); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hwmf; | |||
import static org.junit.Assert.assertEquals; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import org.apache.poi.POIDataSamples; | |||
import org.apache.poi.hwmf.record.HwmfRecord; | |||
import org.apache.poi.hwmf.usermodel.HwmfPicture; | |||
import org.junit.Test; | |||
public class TestHwmfParsing { | |||
@Test | |||
public void parse() throws IOException { | |||
File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf"); | |||
FileInputStream fis = new FileInputStream(f); | |||
HwmfPicture wmf = new HwmfPicture(fis); | |||
fis.close(); | |||
List<HwmfRecord> records = wmf.getRecords(); | |||
assertEquals(581, records.size()); | |||
} | |||
} |