1
0
mirror of https://github.com/apache/poi.git synced 2025-03-07 01:19:08 +00:00

- wmf display error

change hatch image preparation

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1883934 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2020-11-29 17:23:21 +00:00
parent 20c883b201
commit 17592b0a88
8 changed files with 100 additions and 107 deletions
src
examples/src/org/apache/poi/examples/hwmf
scratchpad/src/org/apache/poi

@ -29,12 +29,12 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.poi.hwmf.draw.HwmfGraphics;
import org.apache.poi.hwmf.draw.HwmfROP3Composite;
import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
@ -44,28 +44,17 @@ import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
* inspired from http://www.evmsoft.net/en/roptest.html
*/
public final class ROP3Table {
private ROP3Table() {
}
private static byte[] PATTERN = {
1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1,
0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 1, 1, 0, 1, 1,
0, 1, 0, 1, 0, 1, 0, 1,
};
private ROP3Table() {}
private static final long PATTERN = 0xAADDAA55AADDAA55L;
private static final HwmfTernaryRasterOp[] OPS = HwmfTernaryRasterOp.values();
private static final int COLS = 16;
private static final double BOX = 100, SCALE = 1, HEADER = 1.1;
private static final int COLS = 16, BOX = 100;
private static final double SCALE = 2, HEADER = 1.1;
private static final Rectangle2D RECT = new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.90* BOX, 0.90* BOX);
private static final Shape CIRCLE_BIG = new Ellipse2D.Double(0.15* BOX, 0.15* BOX, 0.70* BOX, 0.70* BOX);
private static final Shape CIRCLE_SMALL = new Ellipse2D.Double(0.40* BOX, 0.40* BOX, 0.20* BOX, 0.20* BOX);
private static final Shape LABEL_BOX = new Rectangle.Double(0.06* BOX, 0.85* BOX, 0.88* BOX, 0.10* BOX);
private static final Rectangle2D RECT = new Rectangle2D.Double(0.05*BOX, 0.05*BOX, 0.90*BOX, 0.90*BOX);
private static final Shape CIRCLE_BIG = new Ellipse2D.Double(0.15*BOX, 0.15*BOX, 0.70*BOX, 0.70*BOX);
private static final Shape CIRCLE_SMALL = new Ellipse2D.Double(0.40*BOX, 0.40*BOX, 0.20*BOX, 0.20*BOX);
private static final Shape LABEL_BOX = new Rectangle.Double(0.06*BOX, 0.85*BOX, 0.88*BOX, 0.10*BOX);
private static final AlphaComposite SRC_OVER = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
@ -77,29 +66,23 @@ public final class ROP3Table {
BufferedImage dest = new BufferedImage(
(int)(BOX * COLS * SCALE),
(int)(BOX *(Math.max(OPS.length/COLS,1) + HEADER)* SCALE),
(int)(BOX * (Math.max(OPS.length/COLS,1) + HEADER) * SCALE),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = dest.createGraphics();
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 10));
g.setTransform(INIT_AT);
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 10));
g.translate(BOX * (COLS-5) / 2., 0);
g.setColor(Color.BLACK);
for (int i=0; i<3; i++) {
String str = new String[]{"Dest:","Source:","Pattern:"}[i];
TextLayout t = new TextLayout(str, g.getFont(), g.getFontRenderContext());
Rectangle2D b = t.getBounds();
g.drawString(str, (float)(((i*2+0.95)*BOX - b.getWidth())), (float)(0.55 * BOX));
}
g.translate(BOX, 0);
fillDest(g);
fillLabel(g, "Dest");
g.translate(2*BOX, 0);
g.drawImage(source, 0, 0, null);
fillLabel(g, "Source");
g.translate(2*BOX, 0);
g.setPaint(new TexturePaint(pattern, RECT));
g.fill(RECT);
fillLabel(g, "Pattern");
int idx=0;
for (HwmfTernaryRasterOp op : OPS) {
@ -109,7 +92,7 @@ public final class ROP3Table {
fillDest(g);
fillPattern(g, op, pattern, source);
fillLabel(g, op);
fillLabel(g, op.name());
idx++;
}
@ -118,20 +101,17 @@ public final class ROP3Table {
}
private static BufferedImage getPattern() {
byte[] bw = { 0, -1 };
BufferedImage pattern = new BufferedImage(8, 8, BufferedImage.TYPE_BYTE_INDEXED, new IndexColorModel(1, 2, bw, bw, bw));
pattern.getRaster().setDataElements(0, 0, 8, 8, PATTERN);
return pattern;
return HwmfGraphics.getPatternFromLong(PATTERN, Color.BLACK, Color.WHITE, false);
}
private static BufferedImage getSource() {
BufferedImage checker = new BufferedImage((int) BOX, (int) BOX, BufferedImage.TYPE_INT_ARGB);
BufferedImage checker = new BufferedImage(BOX, BOX, BufferedImage.TYPE_INT_ARGB);
Graphics2D cg = checker.createGraphics();
cg.setColor(Color.PINK);
cg.fill(new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.90* BOX, 0.90* BOX));
cg.fill(RECT);
cg.setColor(new Color(0xE6E6FA, false));
cg.fill(new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.45* BOX, 0.45* BOX));
cg.fill(new Rectangle2D.Double(0.50* BOX, 0.50* BOX, 0.45* BOX, 0.45* BOX));
cg.fill(new Rectangle2D.Double(0.05*BOX, 0.05*BOX, 0.45*BOX, 0.45*BOX));
cg.fill(new Rectangle2D.Double(0.50*BOX, 0.50*BOX, 0.45*BOX, 0.45*BOX));
cg.dispose();
return checker;
}
@ -154,15 +134,13 @@ public final class ROP3Table {
g.setComposite(SRC_OVER);
}
private static void fillLabel(Graphics2D g, HwmfTernaryRasterOp op) {
private static void fillLabel(Graphics2D g, String str) {
g.setColor(Color.WHITE);
g.fill(LABEL_BOX);
g.setColor(Color.BLACK);
TextLayout t = new TextLayout(op.name(), g.getFont(), g.getFontRenderContext());
TextLayout t = new TextLayout(str, g.getFont(), g.getFontRenderContext());
Rectangle2D b = t.getBounds();
g.drawString(op.name(), (float)((BOX -b.getWidth())/2.), (float)(0.94* BOX));
g.drawString(str, (float)((BOX -b.getWidth())/2.), (float)(0.94*BOX));
}
}

@ -390,18 +390,19 @@ public class HemfGraphics extends HwmfGraphics {
@Override
public void fill(Shape shape) {
HemfDrawProperties prop = getProperties();
if (prop.getBrushStyle() == HwmfBrushStyle.BS_NULL) {
return;
}
Composite old = graphicsCtx.getComposite();
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
if (prop.getBkMode() == HwmfMisc.WmfSetBkMode.HwmfBkMode.OPAQUE) {
graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
graphicsCtx.fill(shape);
}
// if (prop.getBkMode() == HwmfMisc.WmfSetBkMode.HwmfBkMode.OPAQUE) {
// graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
// graphicsCtx.fill(shape);
// }
graphicsCtx.setPaint(getFill());
graphicsCtx.fill(shape);
}
graphicsCtx.setPaint(getFill());
graphicsCtx.fill(shape);
graphicsCtx.setComposite(old);
}

@ -197,11 +197,13 @@ public class HemfPicture implements Iterable<HemfRecord>, GenericRecord {
HemfGraphics g = new HemfGraphics(ctx, b);
int idx=0;
for (HemfRecord r : getRecords()) {
try {
g.draw(r);
} catch (RuntimeException ignored) {
}
idx++;
}
} finally {
ctx.setTransform(at);

@ -28,6 +28,7 @@ import java.awt.image.BufferedImage;
import java.util.List;
import org.apache.poi.hwmf.draw.HwmfGraphics.BufferedImageRenderer;
import org.apache.poi.hwmf.record.HwmfBinaryRasterOp;
import org.apache.poi.hwmf.record.HwmfBrushStyle;
import org.apache.poi.hwmf.record.HwmfColorRef;
import org.apache.poi.hwmf.record.HwmfFill.WmfSetPolyfillMode.HwmfPolyfillMode;
@ -68,6 +69,7 @@ public class HwmfDrawProperties {
private HwmfTextVerticalAlignment textVAlignLatin;
private HwmfTextAlignment textAlignAsian;
private HwmfTextVerticalAlignment textVAlignAsian;
private HwmfBinaryRasterOp rasterOp2;
private HwmfTernaryRasterOp rasterOp3;
protected Shape clip;
protected final AffineTransform transform = new AffineTransform();
@ -92,7 +94,8 @@ public class HwmfDrawProperties {
textVAlignLatin = HwmfTextVerticalAlignment.TOP;
textAlignAsian = HwmfTextAlignment.RIGHT;
textVAlignAsian = HwmfTextVerticalAlignment.TOP;
rasterOp3 = HwmfTernaryRasterOp.PATCOPY;
rasterOp2 = HwmfBinaryRasterOp.R2_COPYPEN;
rasterOp3 = null; // default: PATCOPY?
clip = null;
font = new HwmfFont();
font.initDefaults();
@ -128,6 +131,7 @@ public class HwmfDrawProperties {
this.textVAlignLatin = other.textVAlignLatin;
this.textAlignAsian = other.textAlignAsian;
this.textVAlignAsian = other.textVAlignAsian;
this.rasterOp2 = other.rasterOp2;
this.rasterOp3 = other.rasterOp3;
this.transform.setTransform(other.transform);
this.clip = other.clip;
@ -284,7 +288,7 @@ public class HwmfDrawProperties {
}
public void setBrushBitmap(BufferedImage brushBitmap) {
this.brushBitmap = new BufferedImageRenderer(brushBitmap);
this.brushBitmap = (brushBitmap == null) ? null : new BufferedImageRenderer(brushBitmap);
}
/**
@ -423,4 +427,11 @@ public class HwmfDrawProperties {
this.brushTransform.setTransform(brushTransform);
}
}
public HwmfBinaryRasterOp getRasterOp2() {
return rasterOp2;
}
public void setRasterOp2(HwmfBinaryRasterOp rasterOp2) {
this.rasterOp2 = rasterOp2;
}
}

@ -40,6 +40,8 @@ import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.AttributedString;
@ -60,7 +62,6 @@ import org.apache.poi.common.usermodel.fonts.FontCharset;
import org.apache.poi.common.usermodel.fonts.FontInfo;
import org.apache.poi.hwmf.record.HwmfBrushStyle;
import org.apache.poi.hwmf.record.HwmfFont;
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.HwmfObjectTableEntry;
@ -190,18 +191,18 @@ public class HwmfGraphics implements HwmfCharsetAware {
public void fill(Shape shape) {
HwmfDrawProperties prop = getProperties();
Composite old = graphicsCtx.getComposite();
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
graphicsCtx.fill(shape);
}
Composite old = graphicsCtx.getComposite();
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
// graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
// graphicsCtx.fill(shape);
// }
graphicsCtx.setPaint(getFill());
graphicsCtx.fill(shape);
graphicsCtx.setComposite(old);
}
graphicsCtx.setComposite(old);
draw(shape);
}
@ -253,31 +254,27 @@ public class HwmfGraphics implements HwmfCharsetAware {
}
protected Paint getHatchedFill() {
int dim = 7, mid = 3;
BufferedImage bi = new BufferedImage(dim, dim, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = bi.createGraphics();
Color c = (getProperties().getBkMode() == HwmfBkMode.TRANSPARENT)
? new Color(0, true)
: getProperties().getBackgroundColor().getColor();
g.setColor(c);
g.fillRect(0, 0, dim, dim);
g.setColor(getProperties().getBrushColor().getColor());
HwmfHatchStyle h = getProperties().getBrushHatch();
if (h == HwmfHatchStyle.HS_HORIZONTAL || h == HwmfHatchStyle.HS_CROSS) {
g.drawLine(0, mid, dim, mid);
HwmfDrawProperties prop = getProperties();
BufferedImage pattern = getPatternFromLong(
prop.getBrushHatch().pattern,
prop.getBackgroundColor().getColor(),
prop.getBrushColor().getColor(),
prop.getBkMode() == HwmfBkMode.TRANSPARENT
);
return new TexturePaint(pattern, new Rectangle(0,0,8,8));
}
public static BufferedImage getPatternFromLong(long patternLng, Color background, Color foreground, boolean hasAlpha) {
final int[] cmap = {background.getRGB(), foreground.getRGB()};
final IndexColorModel icm = new IndexColorModel(1, 2, cmap, 0, hasAlpha, hasAlpha ? 0 : -1, DataBuffer.TYPE_BYTE);
final BufferedImage pattern = new BufferedImage(8, 8, BufferedImage.TYPE_BYTE_INDEXED, icm);
byte[] pt = new byte[64];
for (int i=0; i<pt.length; i++) {
pt[i] = (byte)((patternLng >>> i) & 1);
}
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);
}
// TODO: handle new HS_* enumeration values
g.dispose();
return new TexturePaint(bi, new Rectangle(0,0,dim,dim));
pattern.getRaster().setDataElements(0, 0, 8, 8, pt);
return pattern;
}
protected Paint getPatternPaint() {

@ -22,34 +22,37 @@ package org.apache.poi.hwmf.record;
*/
public enum HwmfHatchStyle {
/** ----- - A horizontal hatch */
HS_HORIZONTAL(0x0000),
HS_HORIZONTAL(0x0000, 0x000000FF000000FFL),
/** ||||| - A vertical hatch */
HS_VERTICAL(0x0001),
HS_VERTICAL(0x0001, 0x8888888888888888L),
/** \\\\\ - A 45-degree downward, left-to-right hatch. */
HS_FDIAGONAL(0x0002),
HS_FDIAGONAL(0x0002, 0x0804020180402010L),
/** ///// - A 45-degree upward, left-to-right hatch. */
HS_BDIAGONAL(0x0003),
HS_BDIAGONAL(0x0003, 0x1020408001020408L),
/** +++++ - A horizontal and vertical cross-hatch. */
HS_CROSS(0x0004),
HS_CROSS(0x0004, 0x111111FF111111FFL),
/** xxxxx - A 45-degree crosshatch. */
HS_DIAGCROSS(0x0005),
HS_DIAGCROSS(0x0005, 0x1824428181422418L),
/** The hatch is not a pattern, but is a solid color. */
HS_SOLIDCLR(0x0006),
HS_SOLIDCLR(0x0006, 0xFFFFFFFFFFFFFFFFL),
/** The hatch is not a pattern, but is a dithered color. */
HS_DITHEREDCLR(0x0007),
HS_DITHEREDCLR(0x0007, 0xAA55AA55AA55AA55L),
/** The hatch is not a pattern, but is a solid color, defined by the current text (foreground) color. */
HS_SOLIDTEXTCLR(0x0008),
HS_SOLIDTEXTCLR(0x0008, 0xFFFFFFFFFFFFFFFFL),
/** The hatch is not a pattern, but is a dithered color, defined by the current text (foreground) color. */
HS_DITHEREDTEXTCLR(0x0009),
HS_DITHEREDTEXTCLR(0x0009, 0xAA55AA55AA55AA55L),
/** The hatch is not a pattern, but is a solid color, defined by the current background color. */
HS_SOLIDBKCLR(0x000A),
HS_SOLIDBKCLR(0x000A, 0x0000000000000000L),
/** The hatch is not a pattern, but is a dithered color, defined by the current background color. */
HS_DITHEREDBKCLR(0x000B)
HS_DITHEREDBKCLR(0x000B, 0xAA55AA55AA55AA55L)
;
int flag;
HwmfHatchStyle(int flag) {
public long pattern;
HwmfHatchStyle(int flag, long pattern) {
this.flag = flag;
this.pattern = pattern;
}
public static HwmfHatchStyle valueOf(int flag) {

@ -373,7 +373,8 @@ public class HwmfMisc {
@Override
public void draw(HwmfGraphics ctx) {
HwmfDrawProperties prop = ctx.getProperties();
prop.setRasterOp2(drawMode);
}
@Override
@ -532,7 +533,7 @@ public class HwmfMisc {
public void draw(HwmfGraphics ctx) {
ctx.addObjectTableEntry(this);
}
@Override
public void applyObject(HwmfGraphics ctx) {
if (patternDib != null && !patternDib.isValid()) {
@ -658,7 +659,7 @@ public class HwmfMisc {
public void draw(HwmfGraphics ctx) {
ctx.addObjectTableEntry(this);
}
@Override
public void applyObject(HwmfGraphics ctx) {
HwmfDrawProperties dp = ctx.getProperties();
@ -708,7 +709,7 @@ public class HwmfMisc {
public void draw(HwmfGraphics ctx) {
ctx.addObjectTableEntry(this);
}
@Override
public void applyObject(HwmfGraphics ctx) {
HwmfDrawProperties p = ctx.getProperties();
@ -814,7 +815,7 @@ public class HwmfMisc {
public void draw(HwmfGraphics ctx) {
ctx.addObjectTableEntry(this);
}
@Override
public void applyObject(HwmfGraphics ctx) {
HwmfDrawProperties p = ctx.getProperties();

@ -390,7 +390,7 @@ public enum HwmfTernaryRasterOp {
}
public int getOpCode() {
return opValue & 0xFF;
return opValue & 0xFFFF;
}
public String describeCmd() {