diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2015-12-29 00:45:59 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2015-12-29 00:45:59 +0000 |
commit | 35a0d068fbd6a0f712272ba42392b13f45447b2e (patch) | |
tree | d74f7b5fac0cd9ce25053964dfe3590dab2d33c5 /src | |
parent | b01c8e342ca4e3a04a99f1f841bcf9ec0084ef75 (diff) | |
download | poi-35a0d068fbd6a0f712272ba42392b13f45447b2e.tar.gz poi-35a0d068fbd6a0f712272ba42392b13f45447b2e.zip |
WMF fixes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722046 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
20 files changed, 1996 insertions, 703 deletions
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java new file mode 100644 index 0000000000..64ee4cc346 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java @@ -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;
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java new file mode 100644 index 0000000000..4a07cc3304 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java @@ -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()));
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java index 52ea1d9f14..15495de012 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmap16.java @@ -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;
}
+
+ int bytes = (((width * bitsPixel + 15) >> 4) << 1) * height;
+ byte buf[] = new byte[bytes];
+ leis.read(buf);
- BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ FileOutputStream fos = new FileOutputStream("bla16.bmp");
+ fos.write(buf);
+ fos.close();
- 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;
+// 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;
+ }
+
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java index c3317d1dc3..12f9b30a9f 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBitmapDib.java @@ -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;
- }
+ }
}
+
+ private static final int BMP_HEADER_SIZE = 14;
-
- 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 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();
- }
- int bits = 32-Integer.numberOfLeadingZeros(colorTable.length);
- IndexColorModel cm = new IndexColorModel(bits,colorTable.length,r,g,b);
-
- BufferedImage bi = new BufferedImage(headerWidth, headerHeight, BufferedImage.TYPE_BYTE_INDEXED, cm);
- WritableRaster wr = bi.getRaster();
-
- int pixelCount = headerWidth*headerHeight;
- int size = 0;
- for (int pixel=0; pixel<pixelCount; size++) {
- int v = leis.readUByte();
- switch (headerBitCount) {
- default:
- throw new RuntimeException("invalid bitcount for indexed image");
- case BI_BITCOUNT_1:
- for (int j=0; j<8 && pixel<pixelCount; j++,pixel++) {
- wr.setSample(pixel/headerWidth,pixel%headerWidth,0,(v>>(7-j))&1);
- }
- break;
- case BI_BITCOUNT_2:
- wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, (v>>4)&15);
- pixel++;
- if (pixel<pixelCount) {
- wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v&15);
- pixel++;
- }
- break;
- case BI_BITCOUNT_3:
- wr.setSample(pixel/headerWidth, pixel%headerWidth, 0, v);
- pixel++;
- break;
- }
+
+ public BufferedImage getImage() {
+ if (imageData == null) {
+ throw new RecordFormatException("bitmap not initialized ... need to call init() before");
}
- 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();
+
+ // 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);
- int bitShiftRed=0,bitShiftGreen=0,bitShiftBlue=0;
- if (headerCompression == Compression.BI_BITFIELDS) {
- bitShiftGreen = 32-Integer.numberOfLeadingZeros(this.colorMaskBlue);
- bitShiftRed = 32-Integer.numberOfLeadingZeros(this.colorMaskGreen);
- }
+ System.arraycopy(imageData, 0, buf, BMP_HEADER_SIZE, imageData.length);
- 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);
+ try {
+ return ImageIO.read(new ByteArrayInputStream(buf));
+ } catch (IOException e) {
+ // ... shouldn't happen
+ throw new RecordFormatException("invalid bitmap data", e);
}
-
- return size;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java index 9a5288feae..ff11d48629 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfColorRef.java @@ -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;
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java index 81526dd0b6..a65b7b45bf 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java @@ -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[];
-
+ private int pointsPerPolygon[];
+
/**
* An array of 16-bit unsigned integers that define the coordinates of the polygons.
*/
- int xPoints[][];
+ private int xPoints[][];
/**
* An array of 16-bit unsigned integers that define the coordinates of the polygons.
*/
- int yPoints[][];
-
-
+ 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) {
+
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java index d9cddc9e9b..7d616271df 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfEscape.java @@ -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();
+ }
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java index 316d3fcf0b..ee38c7b94e 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java @@ -17,13 +17,27 @@ 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.
*/
public static class WmfFillRegion implements HwmfRecord {
@@ -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();
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java index af6703ef0c..d1a99e641a 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFont.java @@ -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;
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java index 18922bfe71..00108c4ac8 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java @@ -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;
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java new file mode 100644 index 0000000000..28a26a88f6 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMapMode.java @@ -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;
+ }
+}
\ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java index ef539fb209..be59c2dd80 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfMisc.java @@ -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);
}
}
}
\ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java index cbd0a60119..d55f9e454e 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPalette.java @@ -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) {
+
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java new file mode 100644 index 0000000000..4e908ac399 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfPenStyle.java @@ -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);
+ }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecord.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecord.java index d600b09e4c..7fd5ba5632 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecord.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfRecord.java @@ -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);
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java index 315eb11613..5ee3100fc0 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfTernaryRasterOp.java @@ -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;
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java index 84dc4b1c03..6d332607f3 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java @@ -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) {
+
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java index ee8943b232..1cb19e005f 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfWindowing.java @@ -17,44 +17,18 @@ 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.
*/
public static class WmfSetViewportOrg implements HwmfRecord {
@@ -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) {
+
+ }
}
}
diff --git a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java index b99b6b00d9..5abf2a66aa 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/usermodel/HwmfPicture.java @@ -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);
}
}
}
diff --git a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java index ac5d6c016f..a1f2cbf1d0 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java +++ b/src/scratchpad/testcases/org/apache/poi/hwmf/TestHwmfParsing.java @@ -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.");
+ }
+ }
+ }
+
}
|