| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.hwmf.record; |
| |
| import java.awt.image.BufferedImage; |
| import java.io.IOException; |
| |
| import org.apache.poi.hwmf.draw.HwmfDrawProperties; |
| import org.apache.poi.hwmf.draw.HwmfGraphics; |
| import org.apache.poi.hwmf.record.HwmfFill.ColorUsage; |
| import org.apache.poi.hwmf.record.HwmfFill.HwmfImageRecord; |
| import org.apache.poi.util.LittleEndianConsts; |
| import org.apache.poi.util.LittleEndianInputStream; |
| |
| public class HwmfMisc { |
| |
| /** |
| * The META_SAVEDC record saves the playback device context for later retrieval. |
| */ |
| public static class WmfSaveDc implements HwmfRecord { |
| @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) { |
| ctx.saveProperties(); |
| } |
| } |
| |
| /** |
| * The META_SETRELABS record is reserved and not supported. |
| */ |
| public static class WmfSetRelabs implements HwmfRecord { |
| public HwmfRecordType getRecordType() { |
| return HwmfRecordType.setRelabs; |
| } |
| |
| public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { |
| return 0; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| |
| } |
| } |
| |
| /** |
| * The META_RESTOREDC record restores the playback device context from a previously saved device |
| * context. |
| */ |
| public static class WmfRestoreDc implements HwmfRecord { |
| |
| /** |
| * nSavedDC (2 bytes): A 16-bit signed integer that defines the saved state to be restored. If this |
| * member is positive, nSavedDC represents a specific instance of the state to be restored. If |
| * this member is negative, nSavedDC represents an instance relative to the current state. |
| */ |
| 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) { |
| ctx.restoreProperties(nSavedDC); |
| } |
| } |
| |
| /** |
| * The META_SETBKCOLOR record sets the background color in the playback device context to a |
| * specified color, or to the nearest physical color if the device cannot represent the specified color. |
| */ |
| public static class WmfSetBkColor implements HwmfRecord { |
| |
| 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); |
| } |
| } |
| |
| /** |
| * The META_SETBKMODE record defines the background raster operation mix mode in the playback |
| * device context. The background mix mode is the mode for combining pens, text, hatched brushes, |
| * and interiors of filled objects with background colors on the output surface. |
| */ |
| public static class WmfSetBkMode implements HwmfRecord { |
| |
| /** |
| * A 16-bit unsigned integer that defines background mix mode. |
| */ |
| 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 = HwmfBkMode.valueOf(leis.readUShort()); |
| return LittleEndianConsts.SHORT_SIZE; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| ctx.getProperties().setBkMode(bkMode); |
| } |
| } |
| |
| /** |
| * The META_SETLAYOUT record defines the layout orientation in the playback device context. |
| * The layout orientation determines the direction in which text and graphics are drawn |
| */ |
| public static class WmfSetLayout implements HwmfRecord { |
| |
| /** |
| * A 16-bit unsigned integer that defines the layout of text and graphics. |
| * LAYOUT_LTR = 0x0000 |
| * LAYOUT_RTL = 0x0001 |
| * LAYOUT_BITMAPORIENTATIONPRESERVED = 0x0008 |
| */ |
| private int layout; |
| |
| @Override |
| public HwmfRecordType getRecordType() { |
| return HwmfRecordType.setLayout; |
| } |
| |
| @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) { |
| |
| } |
| } |
| |
| /** |
| * The META_SETMAPMODE record defines the mapping mode in the playback device context. |
| * The mapping mode defines the unit of measure used to transform page-space units into |
| * device-space units, and also defines the orientation of the device's x and y axes. |
| */ |
| public static class WmfSetMapMode implements HwmfRecord { |
| |
| private HwmfMapMode mapMode; |
| |
| @Override |
| public HwmfRecordType getRecordType() { |
| return HwmfRecordType.setMapMode; |
| } |
| |
| @Override |
| public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { |
| mapMode = HwmfMapMode.valueOf(leis.readUShort()); |
| return LittleEndianConsts.SHORT_SIZE; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| ctx.getProperties().setMapMode(mapMode); |
| ctx.updateWindowMapMode(); |
| } |
| } |
| |
| /** |
| * The META_SETMAPPERFLAGS record defines the algorithm that the font mapper uses when it maps |
| * logical fonts to physical fonts. |
| */ |
| public static class WmfSetMapperFlags implements HwmfRecord { |
| |
| /** |
| * A 32-bit unsigned integer that defines whether the font mapper should attempt to |
| * match a font's aspect ratio to the current device's aspect ratio. If bit 0 is |
| * set, the mapper selects only matching fonts. |
| */ |
| 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) { |
| |
| } |
| } |
| |
| /** |
| * The META_SETROP2 record defines the foreground raster operation mix mode in the playback device |
| * context. The foreground mix mode is the mode for combining pens and interiors of filled objects with |
| * foreground colors on the output surface. |
| */ |
| public static class WmfSetRop2 implements HwmfRecord { |
| |
| /** |
| * A 16-bit unsigned integer that defines the foreground binary raster |
| * operation mixing mode |
| */ |
| private HwmfBinaryRasterOp drawMode; |
| |
| @Override |
| public HwmfRecordType getRecordType() { |
| return HwmfRecordType.setRop2; |
| } |
| |
| @Override |
| public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { |
| drawMode = HwmfBinaryRasterOp.valueOf(leis.readUShort()); |
| return LittleEndianConsts.SHORT_SIZE; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| |
| } |
| } |
| |
| /** |
| * The META_SETSTRETCHBLTMODE record defines the bitmap stretching mode in the playback device |
| * context. |
| */ |
| public static class WmfSetStretchBltMode implements HwmfRecord { |
| |
| /** |
| * A 16-bit unsigned integer that defines bitmap stretching mode. |
| * This MUST be one of the values: |
| * BLACKONWHITE = 0x0001, |
| * WHITEONBLACK = 0x0002, |
| * COLORONCOLOR = 0x0003, |
| * HALFTONE = 0x0004 |
| */ |
| 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, HwmfImageRecord, HwmfObjectTableEntry { |
| |
| private HwmfBrushStyle style; |
| |
| /** |
| * A 16-bit unsigned integer that defines whether the Colors field of a DIB |
| * Object contains explicit RGB values, or indexes into a palette. |
| * |
| * If the Style field specifies BS_PATTERN, a ColorUsage value of DIB_RGB_COLORS MUST be |
| * used regardless of the contents of this field. |
| * |
| * If the Style field specified anything but BS_PATTERN, this field MUST be one of the ColorUsage values. |
| */ |
| private ColorUsage colorUsage; |
| |
| 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 = ColorUsage.valueOf(leis.readUShort()); |
| int size = 2*LittleEndianConsts.SHORT_SIZE; |
| switch (style) { |
| case BS_SOLID: |
| case BS_NULL: |
| case BS_DIBPATTERN: |
| case BS_DIBPATTERNPT: |
| case BS_HATCHED: |
| case BS_PATTERN: |
| patternDib = new HwmfBitmapDib(); |
| size += patternDib.init(leis, (int)(recordSize-6-size)); |
| break; |
| case BS_INDEXED: |
| case BS_DIBPATTERN8X8: |
| case BS_MONOPATTERN: |
| case BS_PATTERN8X8: |
| throw new RuntimeException("pattern not supported"); |
| } |
| return size; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| ctx.addObjectTableEntry(this); |
| } |
| |
| @Override |
| public void applyObject(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; |
| } |
| } |
| } |
| |
| /** |
| * The META_DELETEOBJECT record deletes an object, including Bitmap16, Brush, |
| * DeviceIndependentBitmap, Font, Palette, Pen, and Region. After the object is deleted, |
| * its index in the WMF Object Table is no longer valid but is available to be reused. |
| */ |
| public static class WmfDeleteObject implements HwmfRecord { |
| /** |
| * A 16-bit unsigned integer used to index into the WMF Object Table to |
| * get the object to be deleted. |
| */ |
| private int objectIndex; |
| |
| @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) { |
| ctx.unsetObjectTableEntry(objectIndex); |
| } |
| } |
| |
| public static class WmfCreatePatternBrush implements HwmfRecord, HwmfObjectTableEntry { |
| |
| private HwmfBitmap16 pattern; |
| |
| @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) { |
| ctx.addObjectTableEntry(this); |
| } |
| |
| @Override |
| public void applyObject(HwmfGraphics ctx) { |
| HwmfDrawProperties dp = ctx.getProperties(); |
| dp.setBrushBitmap(pattern.getImage()); |
| dp.setBrushStyle(HwmfBrushStyle.BS_PATTERN); |
| } |
| } |
| |
| public static class WmfCreatePenIndirect implements HwmfRecord, HwmfObjectTableEntry { |
| |
| private HwmfPenStyle penStyle; |
| /** |
| * A 32-bit PointS Object that specifies a point for the object dimensions. |
| * The x-coordinate is the pen width. The y-coordinate is ignored. |
| */ |
| private int xWidth; |
| @SuppressWarnings("unused") |
| private int yWidth; |
| /** |
| * A 32-bit ColorRef Object that specifies the pen color value. |
| */ |
| private HwmfColorRef colorRef; |
| |
| @Override |
| public HwmfRecordType getRecordType() { |
| return HwmfRecordType.createPenIndirect; |
| } |
| |
| @Override |
| public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException { |
| penStyle = HwmfPenStyle.valueOf(leis.readUShort()); |
| xWidth = leis.readShort(); |
| yWidth = leis.readShort(); |
| colorRef = new HwmfColorRef(); |
| int size = colorRef.init(leis); |
| return size+3*LittleEndianConsts.SHORT_SIZE; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| ctx.addObjectTableEntry(this); |
| } |
| |
| @Override |
| public void applyObject(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> |
| * <th>ColorRef</th> |
| * <th>BrushHatch</th> |
| * </tr> |
| * <tr> |
| * <td>BS_SOLID</td> |
| * <td>SHOULD be a ColorRef Object, which determines the color of the brush.</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * </tr> |
| * <tr> |
| * <td>BS_NULL</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * </tr> |
| * <tr> |
| * <td>BS_PATTERN</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td> |
| * </tr> |
| * <tr> |
| * <td>BS_DIBPATTERN</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created</td> |
| * </tr> |
| * <tr> |
| * <td>BS_DIBPATTERNPT</td> |
| * <td>Not used, and SHOULD be ignored.</td> |
| * <td>Not used. A default object, such as a solidcolor black Brush Object, MAY be created.</td> |
| * </tr> |
| * <tr> |
| * <td>BS_HATCHED</td> |
| * <td>SHOULD be a ColorRef Object, which determines the foreground color of the hatch pattern.</td> |
| * <td>A value from the {@link HwmfHatchStyle} Enumeration that specifies the orientation of lines used to create the hatch.</td> |
| * </tr> |
| * </table> |
| */ |
| public static class WmfCreateBrushIndirect implements HwmfRecord, HwmfObjectTableEntry { |
| private HwmfBrushStyle brushStyle; |
| |
| private HwmfColorRef colorRef; |
| |
| /** |
| * A 16-bit field that specifies the brush hatch type. |
| * Its interpretation depends on the value of BrushStyle. |
| * |
| */ |
| private HwmfHatchStyle brushHatch; |
| |
| @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()); |
| return size+2*LittleEndianConsts.SHORT_SIZE; |
| } |
| |
| @Override |
| public void draw(HwmfGraphics ctx) { |
| ctx.addObjectTableEntry(this); |
| } |
| |
| @Override |
| public void applyObject(HwmfGraphics ctx) { |
| HwmfDrawProperties p = ctx.getProperties(); |
| p.setBrushStyle(brushStyle); |
| p.setBrushColor(colorRef); |
| p.setBrushHatch(brushHatch); |
| } |
| } |
| } |