Skip to content

Commit 17592b0

Browse files
committed
#64716 - wmf display error
change hatch image preparation git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1883934 13f79535-47bb-0310-9956-ffa450edef68
1 parent 20c883b commit 17592b0

File tree

8 files changed

+101
-108
lines changed

8 files changed

+101
-108
lines changed

src/examples/src/org/apache/poi/examples/hwmf/ROP3Table.java

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2929
import java.awt.geom.Ellipse2D;
3030
import java.awt.geom.Rectangle2D;
3131
import java.awt.image.BufferedImage;
32-
import java.awt.image.IndexColorModel;
3332
import java.io.File;
3433
import java.io.IOException;
3534

3635
import javax.imageio.ImageIO;
3736

37+
import org.apache.poi.hwmf.draw.HwmfGraphics;
3838
import org.apache.poi.hwmf.draw.HwmfROP3Composite;
3939
import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
4040

@@ -44,28 +44,17 @@ Licensed to the Apache Software Foundation (ASF) under one or more
4444
* inspired from http://www.evmsoft.net/en/roptest.html
4545
*/
4646
public final class ROP3Table {
47-
private ROP3Table() {
48-
}
49-
50-
private static byte[] PATTERN = {
51-
1, 0, 1, 0, 1, 0, 1, 0,
52-
0, 1, 0, 1, 0, 1, 0, 1,
53-
1, 0, 1, 1, 1, 0, 1, 1,
54-
0, 1, 0, 1, 0, 1, 0, 1,
55-
1, 0, 1, 0, 1, 0, 1, 0,
56-
0, 1, 0, 1, 0, 1, 0, 1,
57-
1, 0, 1, 1, 1, 0, 1, 1,
58-
0, 1, 0, 1, 0, 1, 0, 1,
59-
};
47+
private ROP3Table() {}
6048

49+
private static final long PATTERN = 0xAADDAA55AADDAA55L;
6150
private static final HwmfTernaryRasterOp[] OPS = HwmfTernaryRasterOp.values();
62-
private static final int COLS = 16;
63-
private static final double BOX = 100, SCALE = 1, HEADER = 1.1;
51+
private static final int COLS = 16, BOX = 100;
52+
private static final double SCALE = 2, HEADER = 1.1;
6453

65-
private static final Rectangle2D RECT = new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.90* BOX, 0.90* BOX);
66-
private static final Shape CIRCLE_BIG = new Ellipse2D.Double(0.15* BOX, 0.15* BOX, 0.70* BOX, 0.70* BOX);
67-
private static final Shape CIRCLE_SMALL = new Ellipse2D.Double(0.40* BOX, 0.40* BOX, 0.20* BOX, 0.20* BOX);
68-
private static final Shape LABEL_BOX = new Rectangle.Double(0.06* BOX, 0.85* BOX, 0.88* BOX, 0.10* BOX);
54+
private static final Rectangle2D RECT = new Rectangle2D.Double(0.05*BOX, 0.05*BOX, 0.90*BOX, 0.90*BOX);
55+
private static final Shape CIRCLE_BIG = new Ellipse2D.Double(0.15*BOX, 0.15*BOX, 0.70*BOX, 0.70*BOX);
56+
private static final Shape CIRCLE_SMALL = new Ellipse2D.Double(0.40*BOX, 0.40*BOX, 0.20*BOX, 0.20*BOX);
57+
private static final Shape LABEL_BOX = new Rectangle.Double(0.06*BOX, 0.85*BOX, 0.88*BOX, 0.10*BOX);
6958

7059
private static final AlphaComposite SRC_OVER = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
7160

@@ -77,29 +66,23 @@ public static void main(String[] args) throws IOException {
7766

7867
BufferedImage dest = new BufferedImage(
7968
(int)(BOX * COLS * SCALE),
80-
(int)(BOX *(Math.max(OPS.length/COLS,1) + HEADER)* SCALE),
69+
(int)(BOX * (Math.max(OPS.length/COLS,1) + HEADER) * SCALE),
8170
BufferedImage.TYPE_INT_ARGB);
8271
Graphics2D g = dest.createGraphics();
83-
84-
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 10));
85-
8672
g.setTransform(INIT_AT);
73+
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 10));
74+
g.translate(BOX * (COLS-5) / 2., 0);
8775
g.setColor(Color.BLACK);
8876

89-
for (int i=0; i<3; i++) {
90-
String str = new String[]{"Dest:","Source:","Pattern:"}[i];
91-
TextLayout t = new TextLayout(str, g.getFont(), g.getFontRenderContext());
92-
Rectangle2D b = t.getBounds();
93-
g.drawString(str, (float)(((i*2+0.95)*BOX - b.getWidth())), (float)(0.55 * BOX));
94-
}
95-
96-
g.translate(BOX, 0);
9777
fillDest(g);
78+
fillLabel(g, "Dest");
9879
g.translate(2*BOX, 0);
9980
g.drawImage(source, 0, 0, null);
81+
fillLabel(g, "Source");
10082
g.translate(2*BOX, 0);
10183
g.setPaint(new TexturePaint(pattern, RECT));
10284
g.fill(RECT);
85+
fillLabel(g, "Pattern");
10386

10487
int idx=0;
10588
for (HwmfTernaryRasterOp op : OPS) {
@@ -109,7 +92,7 @@ public static void main(String[] args) throws IOException {
10992

11093
fillDest(g);
11194
fillPattern(g, op, pattern, source);
112-
fillLabel(g, op);
95+
fillLabel(g, op.name());
11396
idx++;
11497
}
11598

@@ -118,20 +101,17 @@ public static void main(String[] args) throws IOException {
118101
}
119102

120103
private static BufferedImage getPattern() {
121-
byte[] bw = { 0, -1 };
122-
BufferedImage pattern = new BufferedImage(8, 8, BufferedImage.TYPE_BYTE_INDEXED, new IndexColorModel(1, 2, bw, bw, bw));
123-
pattern.getRaster().setDataElements(0, 0, 8, 8, PATTERN);
124-
return pattern;
104+
return HwmfGraphics.getPatternFromLong(PATTERN, Color.BLACK, Color.WHITE, false);
125105
}
126106

127107
private static BufferedImage getSource() {
128-
BufferedImage checker = new BufferedImage((int) BOX, (int) BOX, BufferedImage.TYPE_INT_ARGB);
108+
BufferedImage checker = new BufferedImage(BOX, BOX, BufferedImage.TYPE_INT_ARGB);
129109
Graphics2D cg = checker.createGraphics();
130110
cg.setColor(Color.PINK);
131-
cg.fill(new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.90* BOX, 0.90* BOX));
111+
cg.fill(RECT);
132112
cg.setColor(new Color(0xE6E6FA, false));
133-
cg.fill(new Rectangle2D.Double(0.05* BOX, 0.05* BOX, 0.45* BOX, 0.45* BOX));
134-
cg.fill(new Rectangle2D.Double(0.50* BOX, 0.50* BOX, 0.45* BOX, 0.45* BOX));
113+
cg.fill(new Rectangle2D.Double(0.05*BOX, 0.05*BOX, 0.45*BOX, 0.45*BOX));
114+
cg.fill(new Rectangle2D.Double(0.50*BOX, 0.50*BOX, 0.45*BOX, 0.45*BOX));
135115
cg.dispose();
136116
return checker;
137117
}
@@ -154,15 +134,13 @@ private static void fillPattern(Graphics2D g, HwmfTernaryRasterOp op, BufferedIm
154134
g.setComposite(SRC_OVER);
155135
}
156136

157-
private static void fillLabel(Graphics2D g, HwmfTernaryRasterOp op) {
137+
private static void fillLabel(Graphics2D g, String str) {
158138
g.setColor(Color.WHITE);
159139
g.fill(LABEL_BOX);
160140
g.setColor(Color.BLACK);
161141

162-
TextLayout t = new TextLayout(op.name(), g.getFont(), g.getFontRenderContext());
142+
TextLayout t = new TextLayout(str, g.getFont(), g.getFontRenderContext());
163143
Rectangle2D b = t.getBounds();
164-
g.drawString(op.name(), (float)((BOX -b.getWidth())/2.), (float)(0.94* BOX));
165-
144+
g.drawString(str, (float)((BOX -b.getWidth())/2.), (float)(0.94*BOX));
166145
}
167-
168146
}

src/scratchpad/src/org/apache/poi/hemf/draw/HemfGraphics.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -390,18 +390,19 @@ public void updateWindowMapMode() {
390390
@Override
391391
public void fill(Shape shape) {
392392
HemfDrawProperties prop = getProperties();
393+
if (prop.getBrushStyle() == HwmfBrushStyle.BS_NULL) {
394+
return;
395+
}
393396

394397
Composite old = graphicsCtx.getComposite();
395398
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
396-
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
397-
if (prop.getBkMode() == HwmfMisc.WmfSetBkMode.HwmfBkMode.OPAQUE) {
398-
graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
399-
graphicsCtx.fill(shape);
400-
}
399+
// if (prop.getBkMode() == HwmfMisc.WmfSetBkMode.HwmfBkMode.OPAQUE) {
400+
// graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
401+
// graphicsCtx.fill(shape);
402+
// }
401403

402-
graphicsCtx.setPaint(getFill());
403-
graphicsCtx.fill(shape);
404-
}
404+
graphicsCtx.setPaint(getFill());
405+
graphicsCtx.fill(shape);
405406
graphicsCtx.setComposite(old);
406407
}
407408

src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,13 @@ public void draw(Graphics2D ctx, Rectangle2D graphicsBounds) {
197197

198198
HemfGraphics g = new HemfGraphics(ctx, b);
199199

200+
int idx=0;
200201
for (HemfRecord r : getRecords()) {
201202
try {
202203
g.draw(r);
203204
} catch (RuntimeException ignored) {
204205
}
206+
idx++;
205207
}
206208
} finally {
207209
ctx.setTransform(at);

src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2828
import java.util.List;
2929

3030
import org.apache.poi.hwmf.draw.HwmfGraphics.BufferedImageRenderer;
31+
import org.apache.poi.hwmf.record.HwmfBinaryRasterOp;
3132
import org.apache.poi.hwmf.record.HwmfBrushStyle;
3233
import org.apache.poi.hwmf.record.HwmfColorRef;
3334
import org.apache.poi.hwmf.record.HwmfFill.WmfSetPolyfillMode.HwmfPolyfillMode;
@@ -68,6 +69,7 @@ public class HwmfDrawProperties {
6869
private HwmfTextVerticalAlignment textVAlignLatin;
6970
private HwmfTextAlignment textAlignAsian;
7071
private HwmfTextVerticalAlignment textVAlignAsian;
72+
private HwmfBinaryRasterOp rasterOp2;
7173
private HwmfTernaryRasterOp rasterOp3;
7274
protected Shape clip;
7375
protected final AffineTransform transform = new AffineTransform();
@@ -92,7 +94,8 @@ public HwmfDrawProperties() {
9294
textVAlignLatin = HwmfTextVerticalAlignment.TOP;
9395
textAlignAsian = HwmfTextAlignment.RIGHT;
9496
textVAlignAsian = HwmfTextVerticalAlignment.TOP;
95-
rasterOp3 = HwmfTernaryRasterOp.PATCOPY;
97+
rasterOp2 = HwmfBinaryRasterOp.R2_COPYPEN;
98+
rasterOp3 = null; // default: PATCOPY?
9699
clip = null;
97100
font = new HwmfFont();
98101
font.initDefaults();
@@ -128,6 +131,7 @@ public HwmfDrawProperties(HwmfDrawProperties other) {
128131
this.textVAlignLatin = other.textVAlignLatin;
129132
this.textAlignAsian = other.textAlignAsian;
130133
this.textVAlignAsian = other.textVAlignAsian;
134+
this.rasterOp2 = other.rasterOp2;
131135
this.rasterOp3 = other.rasterOp3;
132136
this.transform.setTransform(other.transform);
133137
this.clip = other.clip;
@@ -284,7 +288,7 @@ public void setBrushBitmap(ImageRenderer brushBitmap) {
284288
}
285289

286290
public void setBrushBitmap(BufferedImage brushBitmap) {
287-
this.brushBitmap = new BufferedImageRenderer(brushBitmap);
291+
this.brushBitmap = (brushBitmap == null) ? null : new BufferedImageRenderer(brushBitmap);
288292
}
289293

290294
/**
@@ -423,4 +427,11 @@ public void setBrushTransform(AffineTransform brushTransform) {
423427
this.brushTransform.setTransform(brushTransform);
424428
}
425429
}
430+
public HwmfBinaryRasterOp getRasterOp2() {
431+
return rasterOp2;
432+
}
433+
434+
public void setRasterOp2(HwmfBinaryRasterOp rasterOp2) {
435+
this.rasterOp2 = rasterOp2;
436+
}
426437
}

src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more
4040
import java.awt.geom.Point2D;
4141
import java.awt.geom.Rectangle2D;
4242
import java.awt.image.BufferedImage;
43+
import java.awt.image.DataBuffer;
44+
import java.awt.image.IndexColorModel;
4345
import java.nio.charset.Charset;
4446
import java.nio.charset.StandardCharsets;
4547
import java.text.AttributedString;
@@ -60,7 +62,6 @@ Licensed to the Apache Software Foundation (ASF) under one or more
6062
import org.apache.poi.common.usermodel.fonts.FontInfo;
6163
import org.apache.poi.hwmf.record.HwmfBrushStyle;
6264
import org.apache.poi.hwmf.record.HwmfFont;
63-
import org.apache.poi.hwmf.record.HwmfHatchStyle;
6465
import org.apache.poi.hwmf.record.HwmfMapMode;
6566
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode;
6667
import org.apache.poi.hwmf.record.HwmfObjectTableEntry;
@@ -190,18 +191,18 @@ public void draw(Shape shape) {
190191
public void fill(Shape shape) {
191192
HwmfDrawProperties prop = getProperties();
192193

193-
Composite old = graphicsCtx.getComposite();
194-
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
195194
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
196-
if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
197-
graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
198-
graphicsCtx.fill(shape);
199-
}
195+
Composite old = graphicsCtx.getComposite();
196+
graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
197+
// if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
198+
// graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
199+
// graphicsCtx.fill(shape);
200+
// }
200201

201202
graphicsCtx.setPaint(getFill());
202203
graphicsCtx.fill(shape);
204+
graphicsCtx.setComposite(old);
203205
}
204-
graphicsCtx.setComposite(old);
205206

206207
draw(shape);
207208
}
@@ -253,31 +254,27 @@ protected Paint getSolidFill() {
253254
}
254255

255256
protected Paint getHatchedFill() {
256-
int dim = 7, mid = 3;
257-
BufferedImage bi = new BufferedImage(dim, dim, BufferedImage.TYPE_4BYTE_ABGR);
258-
Graphics2D g = bi.createGraphics();
259-
Color c = (getProperties().getBkMode() == HwmfBkMode.TRANSPARENT)
260-
? new Color(0, true)
261-
: getProperties().getBackgroundColor().getColor();
262-
g.setColor(c);
263-
g.fillRect(0, 0, dim, dim);
264-
g.setColor(getProperties().getBrushColor().getColor());
265-
HwmfHatchStyle h = getProperties().getBrushHatch();
266-
if (h == HwmfHatchStyle.HS_HORIZONTAL || h == HwmfHatchStyle.HS_CROSS) {
267-
g.drawLine(0, mid, dim, mid);
268-
}
269-
if (h == HwmfHatchStyle.HS_VERTICAL || h == HwmfHatchStyle.HS_CROSS) {
270-
g.drawLine(mid, 0, mid, dim);
271-
}
272-
if (h == HwmfHatchStyle.HS_FDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) {
273-
g.drawLine(0, 0, dim, dim);
274-
}
275-
if (h == HwmfHatchStyle.HS_BDIAGONAL || h == HwmfHatchStyle.HS_DIAGCROSS) {
276-
g.drawLine(0, dim, dim, 0);
277-
}
278-
// TODO: handle new HS_* enumeration values
279-
g.dispose();
280-
return new TexturePaint(bi, new Rectangle(0,0,dim,dim));
257+
HwmfDrawProperties prop = getProperties();
258+
BufferedImage pattern = getPatternFromLong(
259+
prop.getBrushHatch().pattern,
260+
prop.getBackgroundColor().getColor(),
261+
prop.getBrushColor().getColor(),
262+
prop.getBkMode() == HwmfBkMode.TRANSPARENT
263+
);
264+
return new TexturePaint(pattern, new Rectangle(0,0,8,8));
265+
}
266+
267+
public static BufferedImage getPatternFromLong(long patternLng, Color background, Color foreground, boolean hasAlpha) {
268+
final int[] cmap = {background.getRGB(), foreground.getRGB()};
269+
final IndexColorModel icm = new IndexColorModel(1, 2, cmap, 0, hasAlpha, hasAlpha ? 0 : -1, DataBuffer.TYPE_BYTE);
270+
final BufferedImage pattern = new BufferedImage(8, 8, BufferedImage.TYPE_BYTE_INDEXED, icm);
271+
272+
byte[] pt = new byte[64];
273+
for (int i=0; i<pt.length; i++) {
274+
pt[i] = (byte)((patternLng >>> i) & 1);
275+
}
276+
pattern.getRaster().setDataElements(0, 0, 8, 8, pt);
277+
return pattern;
281278
}
282279

283280
protected Paint getPatternPaint() {

src/scratchpad/src/org/apache/poi/hwmf/record/HwmfHatchStyle.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,37 @@ Licensed to the Apache Software Foundation (ASF) under one or more
2222
*/
2323
public enum HwmfHatchStyle {
2424
/** ----- - A horizontal hatch */
25-
HS_HORIZONTAL(0x0000),
25+
HS_HORIZONTAL(0x0000, 0x000000FF000000FFL),
2626
/** ||||| - A vertical hatch */
27-
HS_VERTICAL(0x0001),
27+
HS_VERTICAL(0x0001, 0x8888888888888888L),
2828
/** \\\\\ - A 45-degree downward, left-to-right hatch. */
29-
HS_FDIAGONAL(0x0002),
29+
HS_FDIAGONAL(0x0002, 0x0804020180402010L),
3030
/** ///// - A 45-degree upward, left-to-right hatch. */
31-
HS_BDIAGONAL(0x0003),
31+
HS_BDIAGONAL(0x0003, 0x1020408001020408L),
3232
/** +++++ - A horizontal and vertical cross-hatch. */
33-
HS_CROSS(0x0004),
33+
HS_CROSS(0x0004, 0x111111FF111111FFL),
3434
/** xxxxx - A 45-degree crosshatch. */
35-
HS_DIAGCROSS(0x0005),
35+
HS_DIAGCROSS(0x0005, 0x1824428181422418L),
3636
/** The hatch is not a pattern, but is a solid color. */
37-
HS_SOLIDCLR(0x0006),
37+
HS_SOLIDCLR(0x0006, 0xFFFFFFFFFFFFFFFFL),
3838
/** The hatch is not a pattern, but is a dithered color. */
39-
HS_DITHEREDCLR(0x0007),
39+
HS_DITHEREDCLR(0x0007, 0xAA55AA55AA55AA55L),
4040
/** The hatch is not a pattern, but is a solid color, defined by the current text (foreground) color. */
41-
HS_SOLIDTEXTCLR(0x0008),
41+
HS_SOLIDTEXTCLR(0x0008, 0xFFFFFFFFFFFFFFFFL),
4242
/** The hatch is not a pattern, but is a dithered color, defined by the current text (foreground) color. */
43-
HS_DITHEREDTEXTCLR(0x0009),
43+
HS_DITHEREDTEXTCLR(0x0009, 0xAA55AA55AA55AA55L),
4444
/** The hatch is not a pattern, but is a solid color, defined by the current background color. */
45-
HS_SOLIDBKCLR(0x000A),
45+
HS_SOLIDBKCLR(0x000A, 0x0000000000000000L),
4646
/** The hatch is not a pattern, but is a dithered color, defined by the current background color. */
47-
HS_DITHEREDBKCLR(0x000B)
47+
HS_DITHEREDBKCLR(0x000B, 0xAA55AA55AA55AA55L)
4848
;
4949

5050
int flag;
51-
HwmfHatchStyle(int flag) {
51+
public long pattern;
52+
53+
HwmfHatchStyle(int flag, long pattern) {
5254
this.flag = flag;
55+
this.pattern = pattern;
5356
}
5457

5558
public static HwmfHatchStyle valueOf(int flag) {

0 commit comments

Comments
 (0)