WMF fixes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722046 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ae1020ac35
commit
a89d5210c3
@ -0,0 +1,189 @@
|
||||
/* ====================================================================
|
||||
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.draw;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.apache.poi.hwmf.record.HwmfBrushStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfColorRef;
|
||||
import org.apache.poi.hwmf.record.HwmfFill.WmfSetPolyfillMode.HwmfPolyfillMode;
|
||||
import org.apache.poi.hwmf.record.HwmfHatchStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfMapMode;
|
||||
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode;
|
||||
import org.apache.poi.hwmf.record.HwmfPenStyle;
|
||||
|
||||
public class HwmfDrawProperties {
|
||||
private Rectangle2D window = new Rectangle2D.Double(0, 0, 1, 1);
|
||||
private Rectangle2D viewport = new Rectangle2D.Double(0, 0, 1, 1);
|
||||
private Point2D location = new Point2D.Double(0,0);
|
||||
private HwmfMapMode mapMode = HwmfMapMode.MM_ANISOTROPIC;
|
||||
private HwmfColorRef backgroundColor = new HwmfColorRef(Color.BLACK);
|
||||
private HwmfBrushStyle brushStyle = HwmfBrushStyle.BS_SOLID;
|
||||
private HwmfColorRef brushColor = new HwmfColorRef(Color.BLACK);
|
||||
private HwmfHatchStyle brushHatch = HwmfHatchStyle.HS_HORIZONTAL;
|
||||
private BufferedImage brushBitmap = null;
|
||||
private double penWidth = 1;
|
||||
private HwmfPenStyle penStyle = HwmfPenStyle.valueOf(0);
|
||||
private HwmfColorRef penColor = new HwmfColorRef(Color.BLACK);
|
||||
private double penMiterLimit = 10;
|
||||
private HwmfBkMode bkMode = HwmfBkMode.OPAQUE;
|
||||
private HwmfPolyfillMode polyfillMode = HwmfPolyfillMode.WINDING;
|
||||
|
||||
public void setViewportExt(double width, double height) {
|
||||
double x = viewport.getX();
|
||||
double y = viewport.getY();
|
||||
double w = (width != 0) ? width : viewport.getWidth();
|
||||
double h = (height != 0) ? height : viewport.getHeight();
|
||||
viewport.setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
public void setViewportOrg(double x, double y) {
|
||||
double w = viewport.getWidth();
|
||||
double h = viewport.getHeight();
|
||||
viewport.setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
public Rectangle2D getViewport() {
|
||||
return (Rectangle2D)viewport.clone();
|
||||
}
|
||||
|
||||
public void setWindowExt(double width, double height) {
|
||||
double x = window.getX();
|
||||
double y = window.getY();
|
||||
double w = (width != 0) ? width : window.getWidth();
|
||||
double h = (height != 0) ? height : window.getHeight();
|
||||
window.setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
public void setWindowOrg(double x, double y) {
|
||||
double w = window.getWidth();
|
||||
double h = window.getHeight();
|
||||
window.setRect(x, y, w, h);
|
||||
}
|
||||
|
||||
public Rectangle2D getWindow() {
|
||||
return (Rectangle2D)window.clone();
|
||||
}
|
||||
|
||||
public void setLocation(double x, double y) {
|
||||
location.setLocation(x, y);
|
||||
}
|
||||
|
||||
public Point2D getLocation() {
|
||||
return (Point2D)location.clone();
|
||||
}
|
||||
|
||||
public void setMapMode(HwmfMapMode mapMode) {
|
||||
this.mapMode = mapMode;
|
||||
}
|
||||
|
||||
public HwmfMapMode getMapMode() {
|
||||
return mapMode;
|
||||
}
|
||||
|
||||
public HwmfBrushStyle getBrushStyle() {
|
||||
return brushStyle;
|
||||
}
|
||||
|
||||
public void setBrushStyle(HwmfBrushStyle brushStyle) {
|
||||
this.brushStyle = brushStyle;
|
||||
}
|
||||
|
||||
public HwmfHatchStyle getBrushHatch() {
|
||||
return brushHatch;
|
||||
}
|
||||
|
||||
public void setBrushHatch(HwmfHatchStyle brushHatch) {
|
||||
this.brushHatch = brushHatch;
|
||||
}
|
||||
|
||||
public HwmfColorRef getBrushColor() {
|
||||
return brushColor;
|
||||
}
|
||||
|
||||
public void setBrushColor(HwmfColorRef brushColor) {
|
||||
this.brushColor = brushColor;
|
||||
}
|
||||
|
||||
public HwmfBkMode getBkMode() {
|
||||
return bkMode;
|
||||
}
|
||||
|
||||
public void setBkMode(HwmfBkMode bkMode) {
|
||||
this.bkMode = bkMode;
|
||||
}
|
||||
|
||||
public HwmfPenStyle getPenStyle() {
|
||||
return penStyle;
|
||||
}
|
||||
|
||||
public void setPenStyle(HwmfPenStyle penStyle) {
|
||||
this.penStyle = penStyle;
|
||||
}
|
||||
|
||||
public HwmfColorRef getPenColor() {
|
||||
return penColor;
|
||||
}
|
||||
|
||||
public void setPenColor(HwmfColorRef penColor) {
|
||||
this.penColor = penColor;
|
||||
}
|
||||
|
||||
public double getPenWidth() {
|
||||
return penWidth;
|
||||
}
|
||||
|
||||
public void setPenWidth(double penWidth) {
|
||||
this.penWidth = penWidth;
|
||||
}
|
||||
|
||||
public double getPenMiterLimit() {
|
||||
return penMiterLimit;
|
||||
}
|
||||
|
||||
public void setPenMiterLimit(double penMiterLimit) {
|
||||
this.penMiterLimit = penMiterLimit;
|
||||
}
|
||||
|
||||
public HwmfColorRef getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(HwmfColorRef backgroundColor) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
public HwmfPolyfillMode getPolyfillMode() {
|
||||
return polyfillMode;
|
||||
}
|
||||
|
||||
public void setPolyfillMode(HwmfPolyfillMode polyfillMode) {
|
||||
this.polyfillMode = polyfillMode;
|
||||
}
|
||||
|
||||
public BufferedImage getBrushBitmap() {
|
||||
return brushBitmap;
|
||||
}
|
||||
|
||||
public void setBrushBitmap(BufferedImage brushBitmap) {
|
||||
this.brushBitmap = brushBitmap;
|
||||
}
|
||||
}
|
185
src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java
Normal file
185
src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java
Normal file
@ -0,0 +1,185 @@
|
||||
/* ====================================================================
|
||||
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.draw;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.apache.poi.hwmf.record.HwmfBrushStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfHatchStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode;
|
||||
import org.apache.poi.hwmf.record.HwmfPenStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineDash;
|
||||
import org.apache.poi.util.Units;
|
||||
|
||||
public class HwmfGraphics {
|
||||
private final Graphics2D graphicsCtx;
|
||||
private final Deque<HwmfDrawProperties> propStack = new ArrayDeque<HwmfDrawProperties>();
|
||||
HwmfDrawProperties prop;
|
||||
|
||||
public HwmfGraphics(Graphics2D graphicsCtx) {
|
||||
this.graphicsCtx = graphicsCtx;
|
||||
prop = new HwmfDrawProperties();
|
||||
propStack.push(prop);
|
||||
}
|
||||
|
||||
public HwmfDrawProperties getProperties() {
|
||||
return prop;
|
||||
}
|
||||
|
||||
public void draw(Shape shape) {
|
||||
HwmfLineDash lineDash = prop.getPenStyle().getLineDash();
|
||||
if (lineDash == HwmfLineDash.NULL) {
|
||||
// line is not drawn
|
||||
return;
|
||||
}
|
||||
|
||||
Shape tshape = fitShapeToView(shape);
|
||||
BasicStroke stroke = getStroke();
|
||||
|
||||
// first draw a solid background line (depending on bkmode)
|
||||
// only makes sense if the line is not solid
|
||||
if (prop.getBkMode() == HwmfBkMode.OPAQUE && (lineDash != HwmfLineDash.SOLID && lineDash != HwmfLineDash.INSIDEFRAME)) {
|
||||
graphicsCtx.setStroke(new BasicStroke(stroke.getLineWidth()));
|
||||
graphicsCtx.setColor(prop.getBackgroundColor().getColor());
|
||||
graphicsCtx.draw(tshape);
|
||||
}
|
||||
|
||||
// then draw the (dashed) line
|
||||
graphicsCtx.setStroke(stroke);
|
||||
graphicsCtx.setColor(prop.getPenColor().getColor());
|
||||
graphicsCtx.draw(tshape);
|
||||
}
|
||||
|
||||
public void fill(Shape shape) {
|
||||
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
|
||||
GeneralPath gp = new GeneralPath(shape);
|
||||
gp.setWindingRule(prop.getPolyfillMode().awtFlag);
|
||||
Shape tshape = fitShapeToView(gp);
|
||||
graphicsCtx.setPaint(getFill());
|
||||
graphicsCtx.fill(tshape);
|
||||
}
|
||||
|
||||
draw(shape);
|
||||
}
|
||||
|
||||
protected Shape fitShapeToView(Shape shape) {
|
||||
int scaleUnits = prop.getMapMode().scale;
|
||||
Rectangle2D view = prop.getViewport(), win = prop.getWindow();
|
||||
double scaleX, scaleY;
|
||||
switch (scaleUnits) {
|
||||
case -1:
|
||||
scaleX = view.getWidth() / win.getWidth();
|
||||
scaleY = view.getHeight() / win.getHeight();
|
||||
break;
|
||||
case 0:
|
||||
scaleX = scaleY = 1;
|
||||
break;
|
||||
default:
|
||||
scaleX = scaleY = scaleUnits / (double)Units.POINT_DPI;
|
||||
}
|
||||
|
||||
AffineTransform at = new AffineTransform();
|
||||
at.translate(view.getX(), view.getY());
|
||||
at.scale(scaleX, scaleY);
|
||||
at.translate(-win.getX(), -win.getY());
|
||||
at.translate(-view.getX(), -view.getY());
|
||||
|
||||
return at.createTransformedShape(shape);
|
||||
}
|
||||
|
||||
protected BasicStroke getStroke() {
|
||||
Rectangle2D view = prop.getViewport(), win = prop.getWindow();
|
||||
float width = (float)(prop.getPenWidth() * view.getWidth() / win.getWidth());
|
||||
HwmfPenStyle ps = prop.getPenStyle();
|
||||
int cap = ps.getLineCap().awtFlag;
|
||||
int join = ps.getLineJoin().awtFlag;
|
||||
float miterLimit = (float)prop.getPenMiterLimit();
|
||||
float dashes[] = ps.getLineDash().dashes;
|
||||
boolean dashAlt = ps.isAlternateDash();
|
||||
// This value is not an integer index into the dash pattern array.
|
||||
// Instead, it is a floating-point value that specifies a linear distance.
|
||||
float dashStart = (dashAlt && dashes.length > 1) ? dashes[0] : 0;
|
||||
|
||||
return new BasicStroke(width, cap, join, miterLimit, dashes, dashStart);
|
||||
}
|
||||
|
||||
protected Paint getFill() {
|
||||
switch (prop.getBrushStyle()) {
|
||||
default:
|
||||
case BS_INDEXED:
|
||||
case BS_PATTERN8X8:
|
||||
case BS_DIBPATTERN8X8:
|
||||
case BS_MONOPATTERN:
|
||||
case BS_NULL: return null;
|
||||
case BS_PATTERN:
|
||||
case BS_DIBPATTERN:
|
||||
case BS_DIBPATTERNPT: return getPatternPaint();
|
||||
case BS_SOLID: return getSolidFill();
|
||||
case BS_HATCHED: return getHatchedFill();
|
||||
}
|
||||
}
|
||||
|
||||
protected Paint getSolidFill() {
|
||||
return prop.getBrushColor().getColor();
|
||||
}
|
||||
|
||||
protected Paint getHatchedFill() {
|
||||
int dim = 7, mid = 3;
|
||||
BufferedImage bi = new BufferedImage(dim, dim, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
Graphics2D g = bi.createGraphics();
|
||||
Color c = (prop.getBkMode() == HwmfBkMode.TRANSPARENT)
|
||||
? new Color(0, true)
|
||||
: prop.getBackgroundColor().getColor();
|
||||
g.setColor(c);
|
||||
g.fillRect(0, 0, dim, dim);
|
||||
g.setColor(prop.getBrushColor().getColor());
|
||||
HwmfHatchStyle h = prop.getBrushHatch();
|
||||
if (h == HwmfHatchStyle.HS_HORIZONTAL || h == HwmfHatchStyle.HS_CROSS) {
|
||||
g.drawLine(0, mid, dim, mid);
|
||||
}
|
||||
if (h == HwmfHatchStyle.HS_VERTICAL || h == HwmfHatchStyle.HS_CROSS) {
|
||||
g.drawLine(mid, 0, mid, dim);
|
||||
}
|
||||
if (h == HwmfHatchStyle.HS_FDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) {
|
||||
g.drawLine(0, 0, dim, dim);
|
||||
}
|
||||
if (h == HwmfHatchStyle.HS_BDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) {
|
||||
g.drawLine(0, dim, dim, 0);
|
||||
}
|
||||
g.dispose();
|
||||
return new TexturePaint(bi, new Rectangle(0,0,dim,dim));
|
||||
}
|
||||
|
||||
protected Paint getPatternPaint() {
|
||||
BufferedImage bi = prop.getBrushBitmap();
|
||||
return (bi == null) ? null
|
||||
: new TexturePaint(bi, new Rectangle(0,0,bi.getWidth(),bi.getHeight()));
|
||||
}
|
||||
}
|
@ -18,12 +18,9 @@
|
||||
package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
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;
|
||||
|
||||
@ -75,31 +72,45 @@ public class HwmfBitmap16 {
|
||||
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;
|
||||
byte buf[] = new byte[bytes];
|
||||
leis.read(buf);
|
||||
|
||||
FileOutputStream fos = new FileOutputStream("bla16.bmp");
|
||||
fos.write(buf);
|
||||
fos.close();
|
||||
|
||||
|
||||
// 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???
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// assert (bytes == size2);
|
||||
//
|
||||
// size += size2;
|
||||
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
return bi;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,12 +19,16 @@ 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.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@ -59,25 +63,25 @@ public class HwmfBitmapDib {
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
@ -85,23 +89,23 @@ public class HwmfBitmapDib {
|
||||
/**
|
||||
* 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
|
||||
* 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,
|
||||
* 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
|
||||
* 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;
|
||||
@ -139,18 +143,18 @@ public class HwmfBitmapDib {
|
||||
*/
|
||||
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
|
||||
* 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,
|
||||
* 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),
|
||||
@ -170,7 +174,7 @@ public class HwmfBitmapDib {
|
||||
* color indexes.
|
||||
*/
|
||||
BI_CMYKRLE4(0x000D);
|
||||
|
||||
|
||||
int flag;
|
||||
Compression(int flag) {
|
||||
this.flag = flag;
|
||||
@ -180,93 +184,113 @@ public class HwmfBitmapDib {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int BMP_HEADER_SIZE = 14;
|
||||
|
||||
private int headerSize;
|
||||
private int headerWidth;
|
||||
private int headerHeight;
|
||||
private int headerPlanes;
|
||||
private BitCount headerBitCount;
|
||||
private Compression headerCompression;
|
||||
private long headerImageSize = -1;
|
||||
@SuppressWarnings("unused")
|
||||
private int headerXPelsPerMeter = -1;
|
||||
@SuppressWarnings("unused")
|
||||
private int headerYPelsPerMeter = -1;
|
||||
private long headerColorUsed = -1;
|
||||
@SuppressWarnings("unused")
|
||||
private long headerColorImportant = -1;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Color colorTable[];
|
||||
@SuppressWarnings("unused")
|
||||
private int colorMaskRed=0,colorMaskGreen=0,colorMaskBlue=0;
|
||||
|
||||
// size of header and color table, for start of image data calculation
|
||||
private int introSize;
|
||||
private byte imageData[];
|
||||
|
||||
public int init(LittleEndianInputStream leis, int recordSize) throws IOException {
|
||||
leis.mark(10000);
|
||||
|
||||
assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == size2);
|
||||
assert ( headerSize == 0x0C || headerImageSize == size2 );
|
||||
// need to read the header to calculate start of bitmap data correct
|
||||
introSize = readHeader(leis);
|
||||
assert(introSize == headerSize);
|
||||
introSize += readColors(leis);
|
||||
assert(introSize < 10000);
|
||||
|
||||
int fileSize = (headerImageSize != 0) ? (int)(introSize+headerImageSize) : recordSize;
|
||||
|
||||
size += size2;
|
||||
imageData = new byte[fileSize];
|
||||
leis.reset();
|
||||
leis.read(imageData, 0, fileSize);
|
||||
|
||||
return size;
|
||||
assert( headerSize != 0x0C || ((((headerWidth * headerPlanes * headerBitCount.flag + 31) & ~31) / 8) * Math.abs(headerHeight)) == headerImageSize);
|
||||
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (headerSize == 0x0C) {
|
||||
// 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;
|
||||
} else {
|
||||
// BitmapInfoHeader
|
||||
// A 32-bit unsigned integer that defines the compression mode of the
|
||||
// DIB.
|
||||
// A 32-bit signed integer that defines the width of the DIB, in pixels.
|
||||
// This value MUST be positive.
|
||||
// This field SHOULD specify the width of the decompressed image file,
|
||||
// if the Compression value specifies JPEG or PNG format.
|
||||
headerWidth = leis.readInt();
|
||||
// A 32-bit signed integer that defines the height of the DIB, in pixels.
|
||||
// This value MUST NOT be zero.
|
||||
// - If this value is positive, the DIB is a bottom-up bitmap,
|
||||
// and its origin is the lower-left corner.
|
||||
// This field SHOULD specify the height of the decompressed image file,
|
||||
// if the Compression value specifies JPEG or PNG format.
|
||||
// - If this value is negative, the DIB is a top-down bitmap,
|
||||
// and its origin is the upper-left corner. Top-down bitmaps do not support compression.
|
||||
headerHeight = leis.readInt();
|
||||
// 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());
|
||||
// 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
|
||||
// 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,
|
||||
// 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,
|
||||
@ -278,8 +302,9 @@ public class HwmfBitmapDib {
|
||||
// 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;
|
||||
size += 8*LittleEndianConsts.INT_SIZE+2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
assert(size == headerSize);
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -297,7 +322,7 @@ public class HwmfBitmapDib {
|
||||
return readRGBQuad(leis, 16);
|
||||
case BI_BITCOUNT_3:
|
||||
// 256 colors
|
||||
return readRGBQuad(leis, 256);
|
||||
return readRGBQuad(leis, (int)headerColorUsed);
|
||||
case BI_BITCOUNT_5:
|
||||
colorMaskRed=0xFF;
|
||||
colorMaskGreen=0xFF;
|
||||
@ -316,7 +341,7 @@ public class HwmfBitmapDib {
|
||||
colorMaskRed = leis.readInt();
|
||||
return 3*LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
case BI_BITCOUNT_6:
|
||||
case BI_BITCOUNT_6:
|
||||
if (headerCompression == Compression.BI_RGB) {
|
||||
colorMaskBlue = colorMaskGreen = colorMaskRed = 0xFF;
|
||||
return 0;
|
||||
@ -329,7 +354,7 @@ public class HwmfBitmapDib {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int readRGBQuad(LittleEndianInputStream leis, int count) throws IOException {
|
||||
int size = 0;
|
||||
List<Color> colorList = new ArrayList<Color>();
|
||||
@ -346,96 +371,32 @@ public class HwmfBitmapDib {
|
||||
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();
|
||||
|
||||
public BufferedImage getImage() {
|
||||
if (imageData == null) {
|
||||
throw new RecordFormatException("bitmap not initialized ... need to call init() before");
|
||||
}
|
||||
int bits = 32-Integer.numberOfLeadingZeros(colorTable.length);
|
||||
IndexColorModel cm = new IndexColorModel(bits,colorTable.length,r,g,b);
|
||||
|
||||
// create the image data and leave the parsing to the ImageIO api
|
||||
byte buf[] = new byte[BMP_HEADER_SIZE+imageData.length];
|
||||
|
||||
// https://en.wikipedia.org/wiki/BMP_file_format # Bitmap file header
|
||||
buf[0] = (byte)'B';
|
||||
buf[1] = (byte)'M';
|
||||
// the full size of the bmp
|
||||
LittleEndian.putInt(buf, 2, (int)(BMP_HEADER_SIZE + introSize + headerImageSize));
|
||||
// the next 4 bytes are unused
|
||||
LittleEndian.putInt(buf, 6, 0);
|
||||
// start of image = BMP header length + dib header length + color tables length
|
||||
LittleEndian.putInt(buf, 10, BMP_HEADER_SIZE + introSize);
|
||||
|
||||
BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_BYTE_INDEXED, cm);
|
||||
WritableRaster wr = bi.getRaster();
|
||||
System.arraycopy(imageData, 0, buf, BMP_HEADER_SIZE, imageData.length);
|
||||
|
||||
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;
|
||||
}
|
||||
try {
|
||||
return ImageIO.read(new ByteArrayInputStream(buf));
|
||||
} catch (IOException e) {
|
||||
// ... shouldn't happen
|
||||
throw new RecordFormatException("invalid bitmap data", e);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,21 @@ import java.io.IOException;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
private Color colorRef = Color.BLACK;
|
||||
|
||||
public HwmfColorRef() {}
|
||||
|
||||
public HwmfColorRef(Color colorRef) {
|
||||
this.colorRef = colorRef;
|
||||
}
|
||||
|
||||
public int init(LittleEndianInputStream leis) throws IOException {
|
||||
int red = leis.readUByte();
|
||||
@ -44,4 +50,7 @@ public class HwmfColorRef {
|
||||
return 4*LittleEndianConsts.BYTE_SIZE;
|
||||
}
|
||||
|
||||
public Color getColor() {
|
||||
return colorRef;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,13 @@
|
||||
|
||||
package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.awt.Polygon;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@ -28,102 +33,140 @@ public class HwmfDraw {
|
||||
* point.
|
||||
*/
|
||||
public static class WmfMoveTo implements HwmfRecord {
|
||||
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units.
|
||||
*/
|
||||
int y;
|
||||
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units.
|
||||
*/
|
||||
int x;
|
||||
|
||||
private int x;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.moveTo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setLocation(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal component of the drawing
|
||||
* destination position, in logical units.
|
||||
*/
|
||||
int x;
|
||||
|
||||
private int x;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.lineTo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
Point2D start = ctx.getProperties().getLocation();
|
||||
Line2D line = new Line2D.Double(start.getX(), start.getY(), x, y);
|
||||
ctx.draw(line);
|
||||
ctx.getProperties().setLocation(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
private int numberofPoints;
|
||||
|
||||
short xPoints[], yPoints[];
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.polygon;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.fill(getShape());
|
||||
}
|
||||
|
||||
protected Polygon getShape() {
|
||||
Polygon polygon = new Polygon();
|
||||
for(int i = 0; i < numberofPoints; i++) {
|
||||
polygon.addPoint(xPoints[i], yPoints[i]);
|
||||
}
|
||||
return polygon;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The META_POLYLINE record draws a series of line segments by connecting the points in the
|
||||
* specified array.
|
||||
*/
|
||||
public static class WmfPolyline extends WmfPolygon {
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.polyline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.draw(getShape());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -134,27 +177,29 @@ public class HwmfDraw {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int bottomRect;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
|
||||
private int leftRect;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.ellipse;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
bottomRect = leis.readShort();
|
||||
rightRect = leis.readShort();
|
||||
@ -162,6 +207,11 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -173,27 +223,29 @@ public class HwmfDraw {
|
||||
* A 16-bit unsigned integer used to index into the WMF Object Table to get
|
||||
* the region to be framed.
|
||||
*/
|
||||
int region;
|
||||
private 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;
|
||||
private int brush;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the
|
||||
* region frame.
|
||||
*/
|
||||
int height;
|
||||
private int height;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the
|
||||
* region frame.
|
||||
*/
|
||||
int width;
|
||||
|
||||
private int width;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.frameRegion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
region = leis.readUShort();
|
||||
brush = leis.readUShort();
|
||||
@ -201,6 +253,11 @@ public class HwmfDraw {
|
||||
width = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,33 +266,35 @@ public class HwmfDraw {
|
||||
* 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;
|
||||
|
||||
private 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[][];
|
||||
private int pointsPerPolygon[];
|
||||
|
||||
/**
|
||||
* An array of 16-bit unsigned integers that define the coordinates of the polygons.
|
||||
*/
|
||||
int yPoints[][];
|
||||
|
||||
|
||||
private int xPoints[][];
|
||||
|
||||
/**
|
||||
* An array of 16-bit unsigned integers that define the coordinates of the polygons.
|
||||
*/
|
||||
private int yPoints[][];
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.polyPolygon;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
// see http://secunia.com/gfx/pdf/SA31675_BA.pdf ;)
|
||||
numberOfPolygons = leis.readUShort();
|
||||
@ -244,26 +303,31 @@ public class HwmfDraw {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,27 +339,29 @@ public class HwmfDraw {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* the lower-right corner of the rectangle.
|
||||
*/
|
||||
int bottomRect;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
|
||||
private int leftRect;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.frameRegion;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
bottomRect = leis.readShort();
|
||||
rightRect = leis.readShort();
|
||||
@ -303,6 +369,11 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,25 +384,27 @@ public class HwmfDraw {
|
||||
/**
|
||||
* A ColorRef Object that defines the color value.
|
||||
*/
|
||||
HwmfColorRef colorRef;
|
||||
HwmfColorRef colorRef;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the point
|
||||
* to be set.
|
||||
*/
|
||||
int y;
|
||||
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the point
|
||||
* to be set.
|
||||
*/
|
||||
int x;
|
||||
|
||||
|
||||
private int x;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setPixel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
colorRef = new HwmfColorRef();
|
||||
int size = colorRef.init(leis);
|
||||
@ -339,6 +412,11 @@ public class HwmfDraw {
|
||||
x = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE+size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -350,43 +428,45 @@ public class HwmfDraw {
|
||||
* A 16-bit signed integer that defines the height, in logical coordinates, of the
|
||||
* ellipse used to draw the rounded corners.
|
||||
*/
|
||||
int height;
|
||||
|
||||
private 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;
|
||||
|
||||
private 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;
|
||||
|
||||
private 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;
|
||||
|
||||
private 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;
|
||||
|
||||
private 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;
|
||||
|
||||
|
||||
private int leftRect;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.roundRect;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
height = leis.readShort();
|
||||
width = leis.readShort();
|
||||
@ -396,8 +476,13 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 6*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -410,47 +495,49 @@ public class HwmfDraw {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* coordinates, of the endpoint of the second radial.
|
||||
*/
|
||||
int yRadial2;
|
||||
private int yRadial2;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* coordinates, of the endpoint of the second radial.
|
||||
*/
|
||||
int xRadial2;
|
||||
private int xRadial2;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* coordinates, of the endpoint of the first radial.
|
||||
*/
|
||||
int yRadial1;
|
||||
private int yRadial1;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* coordinates, of the endpoint of the first radial.
|
||||
*/
|
||||
int xRadial1;
|
||||
private int xRadial1;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int bottomRect;
|
||||
private int bottomRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int rightRect;
|
||||
private int rightRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int topRect;
|
||||
private int topRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int leftRect;
|
||||
|
||||
private int leftRect;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.pie;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yRadial2 = leis.readShort();
|
||||
xRadial2 = leis.readShort();
|
||||
@ -462,6 +549,12 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 8*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,47 +565,49 @@ public class HwmfDraw {
|
||||
* 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;
|
||||
private int yEndArc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* 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;
|
||||
private int xEndArc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* 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;
|
||||
private int yStartArc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* 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;
|
||||
private int xStartArc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int bottomRect;
|
||||
private int bottomRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int rightRect;
|
||||
private int rightRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int topRect;
|
||||
private int topRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int leftRect;
|
||||
|
||||
private int leftRect;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.arc;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yEndArc = leis.readShort();
|
||||
xEndArc = leis.readShort();
|
||||
@ -524,6 +619,11 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 8*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -533,51 +633,53 @@ public class HwmfDraw {
|
||||
*/
|
||||
public static class WmfChord implements HwmfRecord {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* coordinates, of the endpoint of the second radial.
|
||||
*/
|
||||
int yRadial2;
|
||||
private int yRadial2;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* coordinates, of the endpoint of the second radial.
|
||||
*/
|
||||
int xRadial2;
|
||||
private int xRadial2;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical
|
||||
* coordinates, of the endpoint of the first radial.
|
||||
*/
|
||||
int yRadial1;
|
||||
private int yRadial1;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical
|
||||
* coordinates, of the endpoint of the first radial.
|
||||
*/
|
||||
int xRadial1;
|
||||
private int xRadial1;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int bottomRect;
|
||||
private int bottomRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the lower-right corner of the bounding rectangle.
|
||||
*/
|
||||
int rightRect;
|
||||
private int rightRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int topRect;
|
||||
private int topRect;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of
|
||||
* the upper-left corner of the bounding rectangle.
|
||||
*/
|
||||
int leftRect;
|
||||
|
||||
|
||||
private int leftRect;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.chord;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yRadial2 = leis.readShort();
|
||||
xRadial2 = leis.readShort();
|
||||
@ -589,31 +691,43 @@ public class HwmfDraw {
|
||||
leftRect = leis.readShort();
|
||||
return 8*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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;
|
||||
|
||||
private int objectIndex;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.selectObject;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
objectIndex = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@ -28,21 +30,23 @@ 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;
|
||||
private int escapeFunction;
|
||||
/**
|
||||
* A 16-bit unsigned integer that specifies the size, in bytes, of the
|
||||
* EscapeData field.
|
||||
*/
|
||||
int byteCount;
|
||||
private int byteCount;
|
||||
/**
|
||||
* An array of bytes of size ByteCount.
|
||||
*/
|
||||
byte escapeData[];
|
||||
private byte escapeData[];
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.escape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
escapeFunction = leis.readUShort();
|
||||
byteCount = leis.readUShort();
|
||||
@ -50,4 +54,16 @@ public class HwmfEscape implements HwmfRecord {
|
||||
leis.read(escapeData);
|
||||
return 2*LittleEndianConsts.SHORT_SIZE+byteCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("escape - function: "+escapeFunction+"\n");
|
||||
sb.append(HexDump.dump(escapeData, 0, 0));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,26 @@
|
||||
|
||||
package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
public class HwmfFill {
|
||||
/**
|
||||
* A record which contains an image (to be extracted)
|
||||
*/
|
||||
public interface HwmfImageRecord {
|
||||
BufferedImage getImage();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The META_FILLREGION record fills a region using a specified brush.
|
||||
*/
|
||||
@ -32,23 +46,30 @@ public class HwmfFill {
|
||||
* A 16-bit unsigned integer used to index into the WMF Object Table to get
|
||||
* the region to be filled.
|
||||
*/
|
||||
int region;
|
||||
private 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;
|
||||
private int brush;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.fillRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
region = leis.readUShort();
|
||||
brush = leis.readUShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,6 +92,11 @@ public class HwmfFill {
|
||||
region = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -83,23 +109,25 @@ public class HwmfFill {
|
||||
/**
|
||||
* A 32-bit ColorRef Object that defines the color value.
|
||||
*/
|
||||
HwmfColorRef colorRef;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xStart;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.floodFill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
colorRef = new HwmfColorRef();
|
||||
int size = colorRef.init(leis);
|
||||
@ -107,6 +135,11 @@ public class HwmfFill {
|
||||
xStart = leis.readShort();
|
||||
return size+2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,21 +147,57 @@ public class HwmfFill {
|
||||
* 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
|
||||
*/
|
||||
public enum HwmfPolyfillMode {
|
||||
/**
|
||||
* Selects alternate mode (fills the area between odd-numbered and
|
||||
* even-numbered polygon sides on each scan line).
|
||||
*/
|
||||
ALTERNATE(0x0001, Path2D.WIND_EVEN_ODD),
|
||||
/**
|
||||
* Selects winding mode (fills any region with a nonzero winding value).
|
||||
*/
|
||||
WINDING(0x0002, Path2D.WIND_NON_ZERO);
|
||||
|
||||
public int wmfFlag;
|
||||
public int awtFlag;
|
||||
HwmfPolyfillMode(int wmfFlag, int awtFlag) {
|
||||
this.wmfFlag = wmfFlag;
|
||||
this.awtFlag = awtFlag;
|
||||
}
|
||||
|
||||
static HwmfPolyfillMode valueOf(int wmfFlag) {
|
||||
for (HwmfPolyfillMode pm : values()) {
|
||||
if (pm.wmfFlag == wmfFlag) return pm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines polygon fill mode.
|
||||
* This MUST be one of the values: ALTERNATE = 0x0001, WINDING = 0x0002
|
||||
*/
|
||||
int polyFillMode;
|
||||
private HwmfPolyfillMode polyfillMode;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setPolyFillMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
polyFillMode = leis.readUShort();
|
||||
polyfillMode = HwmfPolyfillMode.valueOf(leis.readUShort());
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setPolyfillMode(polyfillMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -151,29 +220,31 @@ public class HwmfFill {
|
||||
* 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;
|
||||
private int mode;
|
||||
|
||||
/**
|
||||
* A 32-bit ColorRef Object that defines the color value.
|
||||
*/
|
||||
HwmfColorRef colorRef;
|
||||
private HwmfColorRef colorRef;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the point
|
||||
* to be set.
|
||||
*/
|
||||
int y;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the point
|
||||
* to be set.
|
||||
*/
|
||||
int x;
|
||||
private int x;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.extFloodFill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
mode = leis.readUShort();
|
||||
colorRef = new HwmfColorRef();
|
||||
@ -182,6 +253,11 @@ public class HwmfFill {
|
||||
x = leis.readShort();
|
||||
return size+3*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,16 +269,23 @@ public class HwmfFill {
|
||||
* A 16-bit unsigned integer used to index into the WMF Object Table to get
|
||||
* the region to be inverted.
|
||||
*/
|
||||
int region;
|
||||
private int region;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.invertRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
region = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -217,39 +300,41 @@ public class HwmfFill {
|
||||
* 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;
|
||||
private HwmfTernaryRasterOp rasterOperation;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the rectangle.
|
||||
*/
|
||||
int height;
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the rectangle.
|
||||
*/
|
||||
int width;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xLeft;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.patBlt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
int rasterOpCode = leis.readUShort();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
height = leis.readShort();
|
||||
@ -259,6 +344,11 @@ public class HwmfFill {
|
||||
|
||||
return 6*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,44 +359,44 @@ public class HwmfFill {
|
||||
* 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;
|
||||
private HwmfTernaryRasterOp rasterOperation;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the source rectangle.
|
||||
*/
|
||||
int srcHeight;
|
||||
private int srcHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the source rectangle.
|
||||
*/
|
||||
int srcWidth;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xSrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the destination rectangle.
|
||||
*/
|
||||
int destHeight;
|
||||
private int destHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the destination rectangle.
|
||||
*/
|
||||
int destWidth;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xDest;
|
||||
|
||||
/**
|
||||
* A variable-sized Bitmap16 Object that defines source image content.
|
||||
@ -314,19 +404,21 @@ public class HwmfFill {
|
||||
*/
|
||||
HwmfBitmap16 target;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.stretchBlt;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
srcHeight = leis.readShort();
|
||||
@ -351,6 +443,11 @@ public class HwmfFill {
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -360,13 +457,13 @@ public class HwmfFill {
|
||||
* 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 {
|
||||
public static class WmfStretchDib implements HwmfRecord, HwmfImageRecord {
|
||||
/**
|
||||
* 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;
|
||||
private HwmfTernaryRasterOp rasterOperation;
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines whether the Colors field of the
|
||||
@ -376,63 +473,65 @@ public class HwmfFill {
|
||||
* DIB_PAL_COLORS = 0x0001,
|
||||
* DIB_PAL_INDICES = 0x0002
|
||||
*/
|
||||
int colorUsage;
|
||||
private int colorUsage;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int srcHeight;
|
||||
private int srcHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int srcWidth;
|
||||
private int srcWidth;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int ySrc;
|
||||
private int ySrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int xSrc;
|
||||
private int xSrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the
|
||||
* destination rectangle.
|
||||
*/
|
||||
int destHeight;
|
||||
private int destHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the
|
||||
* destination rectangle.
|
||||
*/
|
||||
int destWidth;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xDst;
|
||||
/**
|
||||
* A variable-sized DeviceIndependentBitmap Object (section 2.2.2.9) that is the
|
||||
* source of the color data.
|
||||
*/
|
||||
HwmfBitmapDib dib;
|
||||
private HwmfBitmapDib dib;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.stretchDib;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
int rasterOpCode = leis.readUShort();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
colorUsage = leis.readUShort();
|
||||
@ -447,9 +546,20 @@ public class HwmfFill {
|
||||
|
||||
int size = 11*LittleEndianConsts.SHORT_SIZE;
|
||||
dib = new HwmfBitmapDib();
|
||||
size += dib.init(leis);
|
||||
size += dib.init(leis, (int)(recordSize-6-size));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
return dib.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
public static class WmfBitBlt implements HwmfRecord {
|
||||
@ -458,57 +568,59 @@ public class HwmfFill {
|
||||
* 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xSrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the source and
|
||||
destination rectangles.
|
||||
*/
|
||||
int height;
|
||||
private int height;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the source and destination
|
||||
rectangles.
|
||||
*/
|
||||
int width;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private HwmfBitmap16 target;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.bitBlt;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
ySrc = leis.readShort();
|
||||
@ -535,6 +647,11 @@ public class HwmfFill {
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -543,7 +660,7 @@ public class HwmfFill {
|
||||
* using deviceindependent color data.
|
||||
* The source of the color data is a DIB
|
||||
*/
|
||||
public static class WmfSetDibToDev implements HwmfRecord {
|
||||
public static class WmfSetDibToDev implements HwmfRecord, HwmfImageRecord {
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines whether the Colors field of the
|
||||
@ -553,55 +670,57 @@ public class HwmfFill {
|
||||
* DIB_PAL_COLORS = 0x0001,
|
||||
* DIB_PAL_INDICES = 0x0002
|
||||
*/
|
||||
int colorUsage;
|
||||
private int colorUsage;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the number of scan lines in the source.
|
||||
*/
|
||||
int scanCount;
|
||||
private int scanCount;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the starting scan line in the source.
|
||||
*/
|
||||
int startScan;
|
||||
private int startScan;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the y-coordinate, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int yDib;
|
||||
private int yDib;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the x-coordinate, in logical units, of the
|
||||
* source rectangle.
|
||||
*/
|
||||
int xDib;
|
||||
private int xDib;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the height, in logical units, of the
|
||||
* source and destination rectangles.
|
||||
*/
|
||||
int height;
|
||||
private int height;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the width, in logical units, of the
|
||||
* source and destination rectangles.
|
||||
*/
|
||||
int width;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xDest;
|
||||
/**
|
||||
* A variable-sized DeviceIndependentBitmap Object that is the source of the color data.
|
||||
*/
|
||||
HwmfBitmapDib dib;
|
||||
private HwmfBitmapDib dib;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setDibToDev;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
colorUsage = leis.readUShort();
|
||||
scanCount = leis.readUShort();
|
||||
@ -615,14 +734,24 @@ public class HwmfFill {
|
||||
|
||||
int size = 9*LittleEndianConsts.SHORT_SIZE;
|
||||
dib = new HwmfBitmapDib();
|
||||
size += dib.init(leis);
|
||||
size += dib.init(leis, (int)(recordSize-6-size));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
return dib.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class WmfDibBitBlt implements HwmfRecord {
|
||||
public static class WmfDibBitBlt implements HwmfRecord, HwmfImageRecord {
|
||||
|
||||
/**
|
||||
* A 32-bit unsigned integer that defines how the source pixels, the current brush
|
||||
@ -633,51 +762,53 @@ public class HwmfFill {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the source rectangle.
|
||||
*/
|
||||
int ySrc;
|
||||
private int ySrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units, of the source rectangle.
|
||||
*/
|
||||
int xSrc;
|
||||
private int xSrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the source and
|
||||
* destination rectangles.
|
||||
*/
|
||||
int height;
|
||||
private int height;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the source and destination
|
||||
* rectangles.
|
||||
*/
|
||||
int width;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private HwmfBitmapDib target;
|
||||
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.dibBitBlt;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
ySrc = leis.readShort();
|
||||
@ -696,76 +827,88 @@ public class HwmfFill {
|
||||
size += 4*LittleEndianConsts.SHORT_SIZE;
|
||||
if (hasBitmap) {
|
||||
target = new HwmfBitmapDib();
|
||||
size += target.init(leis);
|
||||
size += target.init(leis, (int)(recordSize-6-size));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
return target.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
public static class WmfDibStretchBlt implements HwmfRecord {
|
||||
public static class WmfDibStretchBlt implements HwmfRecord, HwmfImageRecord {
|
||||
/**
|
||||
* 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;
|
||||
private HwmfTernaryRasterOp rasterOperation;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the source rectangle.
|
||||
*/
|
||||
int srcHeight;
|
||||
private int srcHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the source rectangle.
|
||||
*/
|
||||
int srcWidth;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xSrc;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the height, in logical units, of the
|
||||
* destination rectangle.
|
||||
*/
|
||||
int destHeight;
|
||||
private int destHeight;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the width, in logical units, of the
|
||||
* destination rectangle.
|
||||
*/
|
||||
int destWidth;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.dibStretchBlt;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
int rasterOpIndex = leis.readUShort();
|
||||
|
||||
rasterOperation = HwmfTernaryRasterOp.fromOpIndex(rasterOpIndex);
|
||||
rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex);
|
||||
assert(rasterOpCode == rasterOperation.opCode);
|
||||
|
||||
srcHeight = leis.readShort();
|
||||
@ -785,10 +928,20 @@ public class HwmfFill {
|
||||
size += 4*LittleEndianConsts.SHORT_SIZE;
|
||||
if (hasBitmap) {
|
||||
target = new HwmfBitmapDib();
|
||||
size += target.init(leis);
|
||||
size += target.init(leis, (int)(recordSize-6-size));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
return target.getImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package org.apache.poi.hwmf.record;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
/**
|
||||
@ -440,7 +441,7 @@ public class HwmfFont {
|
||||
*
|
||||
* @see WmfClipPrecision
|
||||
*/
|
||||
int clipPrecision;
|
||||
WmfClipPrecision clipPrecision;
|
||||
|
||||
/**
|
||||
* An 8-bit unsigned integer that defines the output quality.
|
||||
@ -477,22 +478,23 @@ public class HwmfFont {
|
||||
strikeOut = leis.readByte() != 0;
|
||||
charSet = WmfCharset.valueOf(leis.readUByte());
|
||||
outPrecision = WmfOutPrecision.valueOf(leis.readUByte());
|
||||
clipPrecision = WmfClipPrecision.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;
|
||||
byte buf[] = new byte[32], b, readBytes = 0;
|
||||
do {
|
||||
if (readBytes == 32) {
|
||||
throw new IOException("Font facename can't be determined.");
|
||||
}
|
||||
}
|
||||
if (readBytes == 1 || readBytes == 32) {
|
||||
throw new IOException("Font facename can't be determined.");
|
||||
}
|
||||
|
||||
buf[readBytes++] = b = leis.readByte();
|
||||
} while (b != 0 && b != -1 && readBytes <= 32);
|
||||
|
||||
facename = new String(buf, 0, readBytes-1, Charset.forName("ISO-8859-1"));
|
||||
|
||||
return 17+readBytes;
|
||||
return 5*LittleEndianConsts.SHORT_SIZE+8*LittleEndianConsts.BYTE_SIZE+readBytes;
|
||||
}
|
||||
}
|
||||
|
@ -21,17 +21,17 @@ package org.apache.poi.hwmf.record;
|
||||
* The HatchStyle Enumeration specifies the hatch pattern.
|
||||
*/
|
||||
public enum HwmfHatchStyle {
|
||||
/** A horizontal hatch */
|
||||
/** ----- - A horizontal hatch */
|
||||
HS_HORIZONTAL(0x0000),
|
||||
/** A vertical hatch */
|
||||
/** ||||| - A vertical hatch */
|
||||
HS_VERTICAL(0x0001),
|
||||
/** A 45-degree downward, left-to-right hatch. */
|
||||
/** \\\\\ - A 45-degree downward, left-to-right hatch. */
|
||||
HS_FDIAGONAL(0x0002),
|
||||
/** A 45-degree upward, left-to-right hatch. */
|
||||
/** ///// - A 45-degree upward, left-to-right hatch. */
|
||||
HS_BDIAGONAL(0x0003),
|
||||
/** A horizontal and vertical cross-hatch. */
|
||||
/** +++++ - A horizontal and vertical cross-hatch. */
|
||||
HS_CROSS(0x0004),
|
||||
/** A 45-degree crosshatch. */
|
||||
/** xxxxx - A 45-degree crosshatch. */
|
||||
HS_DIAGCROSS(0x0005);
|
||||
|
||||
int flag;
|
||||
|
114
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java
Normal file
114
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java
Normal file
@ -0,0 +1,114 @@
|
||||
/* ====================================================================
|
||||
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 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.
|
||||
*/
|
||||
public enum HwmfMapMode {
|
||||
/**
|
||||
* Each logical unit is mapped to one device pixel.
|
||||
* Positive x is to the right; positive y is down.
|
||||
*/
|
||||
MM_TEXT(0x0001, 0),
|
||||
|
||||
/**
|
||||
* Each logical unit is mapped to 0.1 millimeter.
|
||||
* Positive x is to the right; positive y is up.
|
||||
*/
|
||||
MM_LOMETRIC(0x0002, 254),
|
||||
|
||||
/**
|
||||
* Each logical unit is mapped to 0.01 millimeter.
|
||||
* Positive x is to the right; positive y is up.
|
||||
*/
|
||||
MM_HIMETRIC(0x0003, 2540),
|
||||
|
||||
/**
|
||||
* Each logical unit is mapped to 0.01 inch.
|
||||
* Positive x is to the right; positive y is up.
|
||||
*/
|
||||
MM_LOENGLISH(0x0004, 100),
|
||||
|
||||
/**
|
||||
* Each logical unit is mapped to 0.001 inch.
|
||||
* Positive x is to the right; positive y is up.
|
||||
*/
|
||||
MM_HIENGLISH(0x0005, 1000),
|
||||
|
||||
/**
|
||||
* 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_TWIPS(0x0006, 1440),
|
||||
|
||||
/**
|
||||
* 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_ISOTROPIC(0x0007, -1),
|
||||
|
||||
/**
|
||||
* Logical units are mapped to arbitrary units with arbitrarily scaled axes.
|
||||
*/
|
||||
MM_ANISOTROPIC(0x0008, -1);
|
||||
|
||||
/**
|
||||
* native flag
|
||||
*/
|
||||
public final int flag;
|
||||
|
||||
/**
|
||||
* transformation units - usually scale relative to current dpi.
|
||||
* when scale == 0, then don't scale
|
||||
* when scale == -1, then scale relative to window dimension.
|
||||
*/
|
||||
public final int scale;
|
||||
|
||||
HwmfMapMode(int flag, int scale) {
|
||||
this.flag = flag;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
static HwmfMapMode valueOf(int flag) {
|
||||
for (HwmfMapMode mm : values()) {
|
||||
if (mm.flag == flag) return mm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -17,8 +17,12 @@
|
||||
|
||||
package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfDrawProperties;
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@ -28,22 +32,38 @@ 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; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.saveDc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The META_SETRELABS record is reserved and not supported.
|
||||
*/
|
||||
public static class WmfSetRelabs implements HwmfRecord {
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.setRelabs; }
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setRelabs;
|
||||
}
|
||||
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,16 +77,23 @@ public class HwmfMisc {
|
||||
* 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;
|
||||
private int nSavedDC;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.restoreDc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
nSavedDC = leis.readShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,16 +102,23 @@ public class HwmfMisc {
|
||||
*/
|
||||
public static class WmfSetBkColor implements HwmfRecord {
|
||||
|
||||
HwmfColorRef colorRef;
|
||||
private HwmfColorRef colorRef;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setBkColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
colorRef = new HwmfColorRef();
|
||||
return colorRef.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setBackgroundColor(colorRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,18 +130,38 @@ public class HwmfMisc {
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines background mix mode.
|
||||
* This MUST be either TRANSPARENT = 0x0001 or OPAQUE = 0x0002
|
||||
*/
|
||||
int bkMode;
|
||||
public enum HwmfBkMode {
|
||||
TRANSPARENT(0x0001), OPAQUE(0x0002);
|
||||
|
||||
int flag;
|
||||
HwmfBkMode(int flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
static HwmfBkMode valueOf(int flag) {
|
||||
for (HwmfBkMode bs : values()) {
|
||||
if (bs.flag == flag) return bs;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private HwmfBkMode bkMode;
|
||||
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setBkMode;
|
||||
}
|
||||
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
bkMode = leis.readUShort();
|
||||
bkMode = HwmfBkMode.valueOf(leis.readUShort());
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setBkMode(bkMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,19 +176,26 @@ public class HwmfMisc {
|
||||
* LAYOUT_RTL = 0x0001
|
||||
* LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008
|
||||
*/
|
||||
int layout;
|
||||
private int layout;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setLayout;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,72 +205,23 @@ public class HwmfMisc {
|
||||
*/
|
||||
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;
|
||||
private HwmfMapMode mapMode;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setMapMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
mapMode = leis.readUShort();
|
||||
mapMode = HwmfMapMode.valueOf(leis.readUShort());
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setMapMode(mapMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -223,16 +235,23 @@ public class HwmfMisc {
|
||||
* 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;
|
||||
private long mapperValues;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setMapperFlags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
mapperValues = leis.readUInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,16 +281,23 @@ public class HwmfMisc {
|
||||
* R2_MERGEPEN = 0x000F,
|
||||
* R2_WHITE = 0x0010
|
||||
*/
|
||||
int drawMode;
|
||||
private int drawMode;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setRop2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
drawMode = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,25 +314,32 @@ public class HwmfMisc {
|
||||
* COLORONCOLOR = 0x0003,
|
||||
* HALFTONE = 0x0004
|
||||
*/
|
||||
int setStretchBltMode;
|
||||
private int setStretchBltMode;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setStretchBltMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
setStretchBltMode = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The META_DIBCREATEPATTERNBRUSH record creates a Brush Object with a
|
||||
* pattern specified by a DeviceIndependentBitmap (DIB) Object
|
||||
*/
|
||||
public static class WmfDibCreatePatternBrush implements HwmfRecord {
|
||||
public static class WmfDibCreatePatternBrush implements HwmfRecord, HwmfImageRecord {
|
||||
|
||||
HwmfBrushStyle style;
|
||||
private HwmfBrushStyle style;
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines whether the Colors field of a DIB
|
||||
@ -320,15 +353,17 @@ public class HwmfMisc {
|
||||
* DIB_PAL_COLORS = 0x0001,
|
||||
* DIB_PAL_INDICES = 0x0002
|
||||
*/
|
||||
int colorUsage;
|
||||
private int colorUsage;
|
||||
|
||||
HwmfBitmapDib patternDib;
|
||||
HwmfBitmap16 pattern16;
|
||||
private HwmfBitmapDib patternDib;
|
||||
private HwmfBitmap16 pattern16;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.dibCreatePatternBrush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
style = HwmfBrushStyle.valueOf(leis.readUShort());
|
||||
colorUsage = leis.readUShort();
|
||||
@ -339,12 +374,9 @@ public class HwmfMisc {
|
||||
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);
|
||||
patternDib = new HwmfBitmapDib();
|
||||
size += patternDib.init(leis, (int)(recordSize-6-size));
|
||||
break;
|
||||
case BS_INDEXED:
|
||||
case BS_DIBPATTERN8X8:
|
||||
@ -354,6 +386,24 @@ public class HwmfMisc {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
HwmfDrawProperties prop = ctx.getProperties();
|
||||
prop.setBrushStyle(style);
|
||||
prop.setBrushBitmap(getImage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
if (patternDib != null) {
|
||||
return patternDib.getImage();
|
||||
} else if (pattern16 != null) {
|
||||
return pattern16.getImage();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,84 +414,94 @@ public class HwmfMisc {
|
||||
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.
|
||||
* get the object to be deleted.
|
||||
*/
|
||||
int objectIndex;
|
||||
private int objectIndex;
|
||||
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.deleteObject; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.deleteObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
objectIndex = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class WmfCreatePatternBrush implements HwmfRecord {
|
||||
|
||||
HwmfBitmap16 pattern;
|
||||
private HwmfBitmap16 pattern;
|
||||
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.createPatternBrush; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createPatternBrush;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
pattern = new HwmfBitmap16(true);
|
||||
return pattern.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
private HwmfPenStyle 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;
|
||||
private int xWidth;
|
||||
@SuppressWarnings("unused")
|
||||
private int yWidth;
|
||||
/**
|
||||
* A 32-bit ColorRef Object that specifies the pen color value.
|
||||
*/
|
||||
HwmfColorRef colorRef;
|
||||
private HwmfColorRef colorRef;
|
||||
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.createPenIndirect; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createPenIndirect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
penStyle = leis.readUShort();
|
||||
penStyle = HwmfPenStyle.valueOf(leis.readUShort());
|
||||
xWidth = leis.readShort();
|
||||
yWidth = leis.readShort();
|
||||
colorRef = new HwmfColorRef();
|
||||
int size = 3*LittleEndianConsts.SHORT_SIZE;
|
||||
size += colorRef.init(leis);
|
||||
return size;
|
||||
int size = colorRef.init(leis);
|
||||
return size+3*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
HwmfDrawProperties p = ctx.getProperties();
|
||||
p.setPenStyle(penStyle);
|
||||
p.setPenColor(colorRef);
|
||||
p.setPenWidth(xWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
@ -481,26 +541,37 @@ public class HwmfMisc {
|
||||
* </table>
|
||||
*/
|
||||
public static class WmfCreateBrushIndirect implements HwmfRecord {
|
||||
HwmfBrushStyle brushStyle;
|
||||
private HwmfBrushStyle brushStyle;
|
||||
|
||||
HwmfColorRef colorRef;
|
||||
private HwmfColorRef colorRef;
|
||||
|
||||
/**
|
||||
* A 16-bit field that specifies the brush hatch type.
|
||||
* Its interpretation depends on the value of BrushStyle.
|
||||
*
|
||||
*
|
||||
*/
|
||||
HwmfHatchStyle brushHatch;
|
||||
private HwmfHatchStyle brushHatch;
|
||||
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.createBrushIndirect; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createBrushIndirect;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
return size+2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
HwmfDrawProperties p = ctx.getProperties();
|
||||
p.setBrushStyle(brushStyle);
|
||||
p.setBrushColor(colorRef);
|
||||
p.setBrushHatch(brushHatch);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@ -30,7 +31,7 @@ public class HwmfPalette {
|
||||
// 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;
|
||||
private int values, blue, green, red;
|
||||
|
||||
public int init(LittleEndianInputStream leis) throws IOException {
|
||||
values = leis.readUByte();
|
||||
@ -48,16 +49,17 @@ public class HwmfPalette {
|
||||
* used with the META_SETPALENTRIES and META_ANIMATEPALETTE record types.
|
||||
* When used with META_CREATEPALETTE, it MUST be 0x0300
|
||||
*/
|
||||
int start;
|
||||
private int start;
|
||||
|
||||
/**
|
||||
* NumberOfEntries (2 bytes): A 16-bit unsigned integer that defines the number of objects in
|
||||
* aPaletteEntries.
|
||||
*/
|
||||
int numberOfEntries;
|
||||
private int numberOfEntries;
|
||||
|
||||
PaletteEntry entries[];
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
start = leis.readUShort();
|
||||
numberOfEntries = leis.readUShort();
|
||||
@ -69,15 +71,26 @@ public class HwmfPalette {
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The META_CREATEPALETTE record creates a Palette Object
|
||||
*/
|
||||
public static class WmfCreatePalette extends WmfPaletteParent {
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createPalette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,9 +98,15 @@ public class HwmfPalette {
|
||||
* palette that is defined in the playback device context.
|
||||
*/
|
||||
public static class WmfSetPaletteEntries extends WmfPaletteParent {
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setPalEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,14 +120,21 @@ public class HwmfPalette {
|
||||
*/
|
||||
int numberOfEntries;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.resizePalette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
numberOfEntries = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,16 +145,23 @@ public class HwmfPalette {
|
||||
* A 16-bit unsigned integer used to index into the WMF Object Table to get
|
||||
* the Palette Object to be selected.
|
||||
*/
|
||||
int palette;
|
||||
private int palette;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.selectPalette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
palette = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,11 +169,20 @@ public class HwmfPalette {
|
||||
* is defined in the playback device context to the system palette.
|
||||
*/
|
||||
public static class WmfRealizePalette implements HwmfRecord {
|
||||
public HwmfRecordType getRecordType() { return HwmfRecordType.realizePalette; }
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.realizePalette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,8 +198,14 @@ public class HwmfPalette {
|
||||
* this record SHOULD have no effect.
|
||||
*/
|
||||
public static class WmfAnimatePalette extends WmfPaletteParent {
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.animatePalette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
171
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java
Normal file
171
src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java
Normal file
@ -0,0 +1,171 @@
|
||||
/* ====================================================================
|
||||
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.BasicStroke;
|
||||
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
|
||||
/**
|
||||
* The 16-bit PenStyle Enumeration is used to specify different types of pens
|
||||
* that can be used in graphics operations.
|
||||
*
|
||||
* Various styles can be combined by using a logical OR statement, one from
|
||||
* each subsection of Style, EndCap, Join, and Type (Cosmetic).
|
||||
*
|
||||
* The defaults in case the other values of the subsection aren't set are
|
||||
* solid, round end caps, round joins and cosmetic type.
|
||||
*/
|
||||
public class HwmfPenStyle {
|
||||
public enum HwmfLineCap {
|
||||
/** Rounded ends */
|
||||
ROUND(0, BasicStroke.CAP_ROUND),
|
||||
/** Square protrudes by half line width */
|
||||
SQUARE(1, BasicStroke.CAP_SQUARE),
|
||||
/** Line ends at end point*/
|
||||
FLAT(2, BasicStroke.CAP_BUTT);
|
||||
|
||||
public int wmfFlag;
|
||||
public int awtFlag;
|
||||
HwmfLineCap(int wmfFlag, int awtFlag) {
|
||||
this.wmfFlag = wmfFlag;
|
||||
this.awtFlag = awtFlag;
|
||||
}
|
||||
|
||||
static HwmfLineCap valueOf(int wmfFlag) {
|
||||
for (HwmfLineCap hs : values()) {
|
||||
if (hs.wmfFlag == wmfFlag) return hs;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum HwmfLineJoin {
|
||||
/**Line joins are round. */
|
||||
ROUND(0, BasicStroke.JOIN_ROUND),
|
||||
/** Line joins are beveled. */
|
||||
BEVEL(1, BasicStroke.JOIN_BEVEL),
|
||||
/**
|
||||
* Line joins are mitered when they are within the current limit set by the
|
||||
* SETMITERLIMIT META_ESCAPE record. A join is beveled when it would exceed the limit
|
||||
*/
|
||||
MITER(2, BasicStroke.JOIN_MITER);
|
||||
|
||||
public int wmfFlag;
|
||||
public int awtFlag;
|
||||
HwmfLineJoin(int wmfFlag, int awtFlag) {
|
||||
this.wmfFlag = wmfFlag;
|
||||
this.awtFlag = awtFlag;
|
||||
}
|
||||
|
||||
static HwmfLineJoin valueOf(int wmfFlag) {
|
||||
for (HwmfLineJoin hs : values()) {
|
||||
if (hs.wmfFlag == wmfFlag) return hs;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum HwmfLineDash {
|
||||
/**
|
||||
* The pen is solid.
|
||||
*/
|
||||
SOLID(0x0000, 10),
|
||||
/**
|
||||
* The pen is dashed. (-----)
|
||||
*/
|
||||
DASH(0x0001, 10, 8),
|
||||
/**
|
||||
* The pen is dotted. (.....)
|
||||
*/
|
||||
DOT(0x0002, 2, 4),
|
||||
/**
|
||||
* The pen has alternating dashes and dots. (_._._._)
|
||||
*/
|
||||
DASHDOT(0x0003, 10, 8, 2, 8),
|
||||
/**
|
||||
* The pen has dashes and double dots. (_.._.._)
|
||||
*/
|
||||
DASHDOTDOT(0x0004, 10, 4, 2, 4, 2, 4),
|
||||
/**
|
||||
* The pen is invisible.
|
||||
*/
|
||||
NULL(0x0005),
|
||||
/**
|
||||
* The pen is solid. When this pen is used in any drawing record that takes a
|
||||
* bounding rectangle, the dimensions of the figure are shrunk so that it fits
|
||||
* entirely in the bounding rectangle, taking into account the width of the pen.
|
||||
*/
|
||||
INSIDEFRAME(0x0006, 10),
|
||||
/**
|
||||
* The pen uses a styling array supplied by the user.
|
||||
* (this is currently not supported and drawn as solid ... no idea where the user
|
||||
* styling is supposed to come from ...)
|
||||
*/
|
||||
USERSTYLE(0x0007, 10);
|
||||
|
||||
|
||||
public int wmfFlag;
|
||||
public float[] dashes;
|
||||
HwmfLineDash(int wmfFlag, float... dashes) {
|
||||
this.wmfFlag = wmfFlag;
|
||||
this.dashes = dashes;
|
||||
}
|
||||
|
||||
static HwmfLineDash valueOf(int wmfFlag) {
|
||||
for (HwmfLineDash hs : values()) {
|
||||
if (hs.wmfFlag == wmfFlag) return hs;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final BitField SUBSECTION_DASH = BitFieldFactory.getInstance(0x0007);
|
||||
private static final BitField SUBSECTION_ALTERNATE = BitFieldFactory.getInstance(0x0008);
|
||||
private static final BitField SUBSECTION_ENDCAP = BitFieldFactory.getInstance(0x0300);
|
||||
private static final BitField SUBSECTION_JOIN = BitFieldFactory.getInstance(0x3000);
|
||||
|
||||
private int flag;
|
||||
|
||||
public static HwmfPenStyle valueOf(int flag) {
|
||||
HwmfPenStyle ps = new HwmfPenStyle();
|
||||
ps.flag = flag;
|
||||
return ps;
|
||||
}
|
||||
|
||||
public HwmfLineCap getLineCap() {
|
||||
return HwmfLineCap.valueOf(SUBSECTION_ENDCAP.getValue(flag));
|
||||
}
|
||||
|
||||
public HwmfLineJoin getLineJoin() {
|
||||
return HwmfLineJoin.valueOf(SUBSECTION_JOIN.getValue(flag));
|
||||
}
|
||||
|
||||
public HwmfLineDash getLineDash() {
|
||||
return HwmfLineDash.valueOf(SUBSECTION_DASH.getValue(flag));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The pen sets every other pixel (this style is applicable only for cosmetic pens).
|
||||
*/
|
||||
public boolean isAlternateDash() {
|
||||
return SUBSECTION_ALTERNATE.isSet(flag);
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
public interface HwmfRecord {
|
||||
@ -32,4 +33,11 @@ public interface HwmfRecord {
|
||||
* @throws IOException
|
||||
*/
|
||||
int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException;
|
||||
|
||||
/**
|
||||
* Apply the record settings to the graphics context
|
||||
*
|
||||
* @param ctx the graphics context to modify
|
||||
*/
|
||||
void draw(HwmfGraphics ctx);
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ public enum HwmfTernaryRasterOp {
|
||||
this.opCmd=opCmd;
|
||||
}
|
||||
|
||||
public static HwmfTernaryRasterOp fromOpIndex(int opIndex) {
|
||||
public static HwmfTernaryRasterOp valueOf(int opIndex) {
|
||||
for (HwmfTernaryRasterOp bb : HwmfTernaryRasterOp.values()) {
|
||||
if (bb.opIndex == opIndex) {
|
||||
return bb;
|
||||
|
@ -19,9 +19,12 @@ package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
||||
public class HwmfText {
|
||||
|
||||
@ -38,16 +41,23 @@ public class HwmfText {
|
||||
* this value is transformed and rounded to the nearest pixel. For details about setting the
|
||||
* mapping mode, see META_SETMAPMODE
|
||||
*/
|
||||
int charExtra;
|
||||
private int charExtra;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setTextCharExtra;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
charExtra = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,16 +65,23 @@ public class HwmfText {
|
||||
*/
|
||||
public static class WmfSetTextColor implements HwmfRecord {
|
||||
|
||||
HwmfColorRef colorRef;
|
||||
private HwmfColorRef colorRef;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setTextColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
colorRef = new HwmfColorRef();
|
||||
return colorRef.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +93,7 @@ public class HwmfText {
|
||||
/**
|
||||
* A 16-bit unsigned integer that specifies the number of space characters in the line.
|
||||
*/
|
||||
int breakCount;
|
||||
private int breakCount;
|
||||
|
||||
/**
|
||||
* A 16-bit unsigned integer that specifies the total extra space, in logical
|
||||
@ -84,17 +101,24 @@ public class HwmfText {
|
||||
* 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;
|
||||
private int breakExtra;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setBkColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
breakCount = leis.readUShort();
|
||||
breakExtra = leis.readUShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +129,7 @@ public class HwmfText {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String.
|
||||
*/
|
||||
int stringLength;
|
||||
private 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.
|
||||
@ -114,31 +138,38 @@ public class HwmfText {
|
||||
* length of the string.
|
||||
* The string is written at the location specified by the XStart and YStart fields.
|
||||
*/
|
||||
String text;
|
||||
private 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;
|
||||
private 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;
|
||||
private int xStart;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.textOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
stringLength = leis.readShort();
|
||||
byte buf[] = new byte[stringLength+(stringLength%2)];
|
||||
byte buf[] = new byte[stringLength+(stringLength&1)];
|
||||
leis.readFully(buf);
|
||||
text = new String(buf, "UTF16-LE").trim();
|
||||
text = new String(buf, 0, stringLength, LocaleUtil.CHARSET_1252).trim();
|
||||
yStart = leis.readShort();
|
||||
xStart = leis.readShort();
|
||||
return 3*LittleEndianConsts.SHORT_SIZE+buf.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,16 +183,16 @@ public class HwmfText {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, where the
|
||||
text string is to be located.
|
||||
*/
|
||||
int y;
|
||||
private 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;
|
||||
private int x;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the length of the string.
|
||||
*/
|
||||
int stringLength;
|
||||
private 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
|
||||
@ -196,7 +227,7 @@ public class HwmfText {
|
||||
* Indicates that both horizontal and vertical character displacement values
|
||||
* SHOULD be provided.
|
||||
*/
|
||||
int fwOpts;
|
||||
private 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.
|
||||
@ -205,43 +236,58 @@ public class HwmfText {
|
||||
* 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;
|
||||
private 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;
|
||||
private 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[];
|
||||
private int dx[];
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.extTextOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
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)];
|
||||
int size = 4*LittleEndianConsts.SHORT_SIZE;
|
||||
|
||||
if (fwOpts != 0) {
|
||||
// the bounding rectangle is optional and only read when fwOpts are given
|
||||
left = leis.readShort();
|
||||
top = leis.readShort();
|
||||
right = leis.readShort();
|
||||
bottom = leis.readShort();
|
||||
size += 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
byte buf[] = new byte[stringLength+(stringLength&1)];
|
||||
leis.readFully(buf);
|
||||
text = new String(buf, "UTF16-LE");
|
||||
text = new String(buf, 0, stringLength, LocaleUtil.CHARSET_1252);
|
||||
size += buf.length;
|
||||
|
||||
int size = 8*LittleEndianConsts.SHORT_SIZE+buf.length;
|
||||
if (size < recordSize) {
|
||||
dx = new int[text.length()];
|
||||
// -6 bytes of record function and length header
|
||||
int remainingRecordSize = (int)(recordSize-6);
|
||||
if (size < remainingRecordSize) {
|
||||
if (size + stringLength*LittleEndianConsts.SHORT_SIZE < remainingRecordSize) {
|
||||
throw new RecordFormatException("can't read Dx array - given recordSize doesn't contain enough values for string length "+stringLength);
|
||||
}
|
||||
|
||||
dx = new int[stringLength];
|
||||
for (int i=0; i<dx.length; i++) {
|
||||
dx[i] = leis.readShort();
|
||||
}
|
||||
@ -250,6 +296,11 @@ public class HwmfText {
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -320,28 +371,42 @@ public class HwmfText {
|
||||
* VTA_BASELINE (0x0018):
|
||||
* The reference point MUST be on the baseline of the text.
|
||||
*/
|
||||
int textAlignmentMode;
|
||||
private int textAlignmentMode;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setTextAlign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
textAlignmentMode = leis.readUShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class WmfCreateFontIndirect implements HwmfRecord {
|
||||
HwmfFont font;
|
||||
private HwmfFont font;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createFontIndirect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
font = new HwmfFont();
|
||||
return font.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,43 +17,17 @@
|
||||
|
||||
package org.apache.poi.hwmf.record;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
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.
|
||||
*/
|
||||
@ -62,22 +36,29 @@ public class HwmfWindowing {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the vertical offset, in device units.
|
||||
*/
|
||||
int y;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal offset, in device units.
|
||||
*/
|
||||
int x;
|
||||
private int x;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setViewportOrg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setViewportOrg(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,23 +71,30 @@ public class HwmfWindowing {
|
||||
* A 16-bit signed integer that defines the vertical extent
|
||||
* of the viewport in device units.
|
||||
*/
|
||||
int y;
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal extent
|
||||
* of the viewport in device units.
|
||||
*/
|
||||
int x;
|
||||
private int width;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setViewportExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
height = leis.readShort();
|
||||
width = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setViewportExt(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,22 +106,30 @@ public class HwmfWindowing {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the vertical offset, in device units.
|
||||
*/
|
||||
int yOffset;
|
||||
private int yOffset;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal offset, in device units.
|
||||
*/
|
||||
int xOffset;
|
||||
private int xOffset;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.offsetViewportOrg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yOffset = leis.readShort();
|
||||
xOffset = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
Rectangle2D viewport = ctx.getProperties().getViewport();
|
||||
ctx.getProperties().setViewportOrg(viewport.getX()+xOffset, viewport.getY()+yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,22 +140,29 @@ public class HwmfWindowing {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units.
|
||||
*/
|
||||
int y;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the x-coordinate, in logical units.
|
||||
*/
|
||||
int x;
|
||||
private int x;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setWindowOrg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setWindowOrg(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,23 +175,30 @@ public class HwmfWindowing {
|
||||
* A 16-bit signed integer that defines the vertical extent of
|
||||
* the window in logical units.
|
||||
*/
|
||||
int y;
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal extent of
|
||||
* the window in logical units.
|
||||
*/
|
||||
int x;
|
||||
private int width;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.setWindowExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
y = leis.readShort();
|
||||
x = leis.readShort();
|
||||
height = leis.readShort();
|
||||
width = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
ctx.getProperties().setWindowExt(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,22 +210,30 @@ public class HwmfWindowing {
|
||||
/**
|
||||
* A 16-bit signed integer that defines the vertical offset, in device units.
|
||||
*/
|
||||
int yOffset;
|
||||
private int yOffset;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the horizontal offset, in device units.
|
||||
*/
|
||||
int xOffset;
|
||||
private int xOffset;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.offsetWindowOrg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yOffset = leis.readShort();
|
||||
xOffset = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
Rectangle2D window = ctx.getProperties().getWindow();
|
||||
ctx.getProperties().setWindowOrg(window.getX()+xOffset, window.getY()+yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -228,30 +246,32 @@ public class HwmfWindowing {
|
||||
* 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;
|
||||
private int yDenom;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the amount by which to multiply the
|
||||
* current y-extent.
|
||||
*/
|
||||
int yNum;
|
||||
private 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;
|
||||
private int xDenom;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the amount by which to multiply the
|
||||
* current x-extent.
|
||||
*/
|
||||
int xNum;
|
||||
private int xNum;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.scaleWindowExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yDenom = leis.readShort();
|
||||
yNum = leis.readShort();
|
||||
@ -259,6 +279,14 @@ public class HwmfWindowing {
|
||||
xNum = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
Rectangle2D window = ctx.getProperties().getWindow();
|
||||
double width = window.getWidth() * xNum / xDenom;
|
||||
double height = window.getHeight() * yNum / yDenom;
|
||||
ctx.getProperties().setWindowExt(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -273,30 +301,32 @@ public class HwmfWindowing {
|
||||
* 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;
|
||||
private int yDenom;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the amount by which to multiply the
|
||||
* current y-extent.
|
||||
*/
|
||||
int yNum;
|
||||
private 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;
|
||||
private int xDenom;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the amount by which to multiply the
|
||||
* current x-extent.
|
||||
*/
|
||||
int xNum;
|
||||
private int xNum;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.scaleViewportExt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yDenom = leis.readShort();
|
||||
yNum = leis.readShort();
|
||||
@ -304,6 +334,48 @@ public class HwmfWindowing {
|
||||
xNum = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
Rectangle2D viewport = ctx.getProperties().getViewport();
|
||||
double width = viewport.getWidth() * xNum / xDenom;
|
||||
double height = viewport.getHeight() * yNum / yDenom;
|
||||
ctx.getProperties().setViewportExt(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private int yOffset;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the number of logical units to move left or right.
|
||||
*/
|
||||
private int xOffset;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.offsetClipRgn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
yOffset = leis.readShort();
|
||||
xOffset = leis.readShort();
|
||||
return 2*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,30 +388,32 @@ public class HwmfWindowing {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* lower-right corner of the rectangle.
|
||||
*/
|
||||
int bottom;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private int left;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.excludeClipRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
bottom = leis.readShort();
|
||||
right = leis.readShort();
|
||||
@ -347,6 +421,11 @@ public class HwmfWindowing {
|
||||
left = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -360,30 +439,32 @@ public class HwmfWindowing {
|
||||
* A 16-bit signed integer that defines the y-coordinate, in logical units, of the
|
||||
* lower-right corner of the rectangle.
|
||||
*/
|
||||
int bottom;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private int left;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.intersectClipRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
bottom = leis.readShort();
|
||||
right = leis.readShort();
|
||||
@ -391,11 +472,15 @@ public class HwmfWindowing {
|
||||
left = leis.readShort();
|
||||
return 4*LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* The META_SELECTCLIPREGION record specifies a Region Object to be the current clipping region.
|
||||
*/
|
||||
public static class WmfSelectClipRegion implements HwmfRecord {
|
||||
|
||||
@ -403,16 +488,23 @@ public class HwmfWindowing {
|
||||
* A 16-bit unsigned integer used to index into the WMF Object Table to get
|
||||
* the region to be clipped.
|
||||
*/
|
||||
int region;
|
||||
private int region;
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.selectClipRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
region = leis.readShort();
|
||||
return LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class WmfScanObject {
|
||||
@ -421,30 +513,30 @@ public class HwmfWindowing {
|
||||
* 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;
|
||||
private int count;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the top scanline.
|
||||
*/
|
||||
int top;
|
||||
private int top;
|
||||
/**
|
||||
* A 16-bit unsigned integer that defines the vertical (y-axis) coordinate, in logical units, of the bottom scanline.
|
||||
*/
|
||||
int bottom;
|
||||
private 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[];
|
||||
private 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[];
|
||||
private 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;
|
||||
private int count2;
|
||||
|
||||
public int init(LittleEndianInputStream leis) {
|
||||
count = leis.readUShort();
|
||||
@ -465,62 +557,64 @@ public class HwmfWindowing {
|
||||
/**
|
||||
* A 16-bit signed integer. A value that MUST be ignored.
|
||||
*/
|
||||
int nextInChain;
|
||||
private int nextInChain;
|
||||
/**
|
||||
* A 16-bit signed integer that specifies the region identifier. It MUST be 0x0006.
|
||||
*/
|
||||
int objectType;
|
||||
private int objectType;
|
||||
/**
|
||||
* A 32-bit unsigned integer. A value that MUST be ignored.
|
||||
*/
|
||||
int objectCount;
|
||||
private 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;
|
||||
private int regionSize;
|
||||
/**
|
||||
* A 16-bit signed integer that defines the number of scanlines composing the region.
|
||||
*/
|
||||
int scanCount;
|
||||
private int scanCount;
|
||||
|
||||
/**
|
||||
* A 16-bit signed integer that defines the maximum number of points in any one scan in this region.
|
||||
*/
|
||||
int maxScan;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private 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;
|
||||
private int left;
|
||||
|
||||
/**
|
||||
* An array of Scan objects that define the scanlines in the region.
|
||||
*/
|
||||
WmfScanObject scanObjects[];
|
||||
private WmfScanObject scanObjects[];
|
||||
|
||||
@Override
|
||||
public HwmfRecordType getRecordType() {
|
||||
return HwmfRecordType.createRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
|
||||
nextInChain = leis.readShort();
|
||||
objectType = leis.readShort();
|
||||
@ -545,5 +639,10 @@ public class HwmfWindowing {
|
||||
|
||||
return 20 + size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(HwmfGraphics ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
package org.apache.poi.hwmf.usermodel;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
@ -37,7 +39,8 @@ public class HwmfPicture {
|
||||
}
|
||||
|
||||
public HwmfPicture(InputStream inputStream) throws IOException {
|
||||
LittleEndianInputStream leis = new LittleEndianInputStream(inputStream);
|
||||
BufferedInputStream bis = new BufferedInputStream(inputStream, 10000);
|
||||
LittleEndianInputStream leis = new LittleEndianInputStream(bis);
|
||||
HwmfPlaceableHeader placeableHeader = HwmfPlaceableHeader.readHeader(leis);
|
||||
HwmfHeader header = new HwmfHeader(leis);
|
||||
|
||||
@ -65,8 +68,15 @@ public class HwmfPicture {
|
||||
}
|
||||
|
||||
consumedSize += wr.init(leis, recordSize, recordFunction);
|
||||
if (consumedSize < recordSize) {
|
||||
leis.skip(recordSize - consumedSize);
|
||||
int remainingSize = (int)(recordSize - consumedSize);
|
||||
assert(remainingSize >= 0);
|
||||
if (remainingSize > 0) {
|
||||
byte remaining[] = new byte[remainingSize];
|
||||
leis.read(remaining);
|
||||
FileOutputStream fos = new FileOutputStream("remaining.dat");
|
||||
fos.write(remaining);
|
||||
fos.close();
|
||||
// leis.skip(remainingSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,27 @@ package org.apache.poi.hwmf;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord;
|
||||
import org.apache.poi.hwmf.record.HwmfRecord;
|
||||
import org.apache.poi.hwmf.usermodel.HwmfPicture;
|
||||
import org.apache.poi.sl.usermodel.PictureData;
|
||||
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
||||
import org.apache.poi.sl.usermodel.SlideShow;
|
||||
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestHwmfParsing {
|
||||
@ -39,4 +52,58 @@ public class TestHwmfParsing {
|
||||
List<HwmfRecord> records = wmf.getRecords();
|
||||
assertEquals(581, records.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void extract() throws IOException {
|
||||
File dir = new File("test-data/slideshow");
|
||||
File files[] = dir.listFiles(new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.getName().matches("(?i).*\\.pptx?$");
|
||||
}
|
||||
});
|
||||
|
||||
boolean outputFiles = false;
|
||||
|
||||
File outdir = new File("build/ppt");
|
||||
if (outputFiles) {
|
||||
outdir.mkdirs();
|
||||
}
|
||||
int wmfIdx = 1;
|
||||
for (File f : files) {
|
||||
try {
|
||||
SlideShow<?,?> ss = SlideShowFactory.create(f);
|
||||
for (PictureData pd : ss.getPictureData()) {
|
||||
if (pd.getType() != PictureType.WMF) continue;
|
||||
byte wmfData[] = pd.getData();
|
||||
if (outputFiles) {
|
||||
String filename = String.format(Locale.ROOT, "pic%04d.wmf", wmfIdx);
|
||||
FileOutputStream fos = new FileOutputStream(new File(outdir, filename));
|
||||
fos.write(wmfData);
|
||||
fos.close();
|
||||
}
|
||||
|
||||
HwmfPicture wmf = new HwmfPicture(new ByteArrayInputStream(wmfData));
|
||||
|
||||
int bmpIndex = 1;
|
||||
for (HwmfRecord r : wmf.getRecords()) {
|
||||
if (r instanceof HwmfImageRecord) {
|
||||
BufferedImage bi = ((HwmfImageRecord)r).getImage();
|
||||
if (outputFiles) {
|
||||
String filename = String.format(Locale.ROOT, "pic%04d-%04d.png", wmfIdx, bmpIndex);
|
||||
ImageIO.write(bi, "PNG", new File(outdir, filename));
|
||||
}
|
||||
bmpIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
wmfIdx++;
|
||||
}
|
||||
ss.close();
|
||||
} catch (Exception e) {
|
||||
System.out.println(f+" ignored.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user