// Copyright 2001-2006, FreeHEP. package org.freehep.graphicsio.emf; import java.awt.Dimension; import java.awt.Rectangle; import java.io.IOException; /** * EMF File Header. * * @author Mark Donszelmann * @version $Id: EMFHeader.java,v 1.4 2009-08-17 21:44:45 murkle Exp $ */ public class EMFHeader implements EMFConstants { private static final Dimension screenMM = new Dimension(320, 240); public final static int TYPE_INVALID = 0; // Invalid metafile public final static int TYPE_WMF = 1; // Standard WMF public final static int TYPE_WMF_PLACEABLE = 2; // Placeable WMF public final static int TYPE_EMF = 3; // EMF (not EMF+) public final static int TYPE_EMF_PLUS_ONLY = 4; // EMF+ without dual, // down-level records public final static int TYPE_EMF_PLUS_DUAL = 5; // EMF+ with dual, // down-level records private int type; private Rectangle bounds; private Rectangle frame; private String signature; private int versionMajor; private int versionMinor; private int bytes; private int records; private int handles; private String description; private int palEntries; private Dimension device; private Dimension millimeters; private Dimension micrometers; private boolean openGL; public EMFHeader(int type, Rectangle bounds, int versionMajor, int versionMinor, int bytes, int records, int handles, String application, String name, Dimension device) { this.type = type; this.bounds = bounds; // this assumes you use MM_ANISOTROPIC or MM_ISOTROPIC as MapMode double pixelWidth = (double) screenMM.width / device.width; double pixelHeight = (double) screenMM.height / device.height; this.frame = new Rectangle((int) (bounds.x * 100 * pixelWidth), (int) (bounds.y * 100 * pixelHeight), (int) (bounds.width * 100 * pixelWidth), (int) (bounds.height * 100 * pixelHeight)); this.signature = " EMF"; this.versionMajor = versionMajor >= 0x4000 ? versionMajor - 0x4000 : versionMajor; this.versionMinor = versionMinor; this.bytes = bytes; this.records = records; this.handles = handles; this.description = application.trim() + "\0" + name.trim() + "\0\0"; this.palEntries = 0; this.device = device; this.millimeters = screenMM; this.openGL = false; this.micrometers = new Dimension(screenMM.width * 1000, screenMM.height * 1000); } EMFHeader(EMFInputStream emf) throws IOException { // FIXME: incomplete type = emf.readDWORD(); // 4 int length = emf.readDWORD(); // 8 bounds = emf.readRECTL(); // 24 frame = emf.readRECTL(); // 40 signature = new String(emf.readBYTE(4)); // 44 int version = emf.readDWORD(); // 48 versionMajor = version >> 16; versionMinor = version & 0xFFFF; bytes = emf.readDWORD(); // 52 records = emf.readDWORD(); // 56 handles = emf.readWORD(); // 58 emf.readWORD(); // 60 int dLen = emf.readDWORD(); // 64 /* int dOffset = */ emf.readDWORD(); // 68 palEntries = emf.readDWORD(); // 72 device = emf.readSIZEL(); // 80 millimeters = emf.readSIZEL(); // 88 if ((length - (2 * dLen)) > 88) { emf.readDWORD(); // 92 emf.readDWORD(); // 96 openGL = (emf.readDWORD() != 0) ? true : false; // 100 if ((length - (2 * dLen)) > 100) { micrometers = emf.readSIZEL(); // 108 } } // FIXME: dOffset ignored description = emf.readWCHAR(dLen); // the rest... if ((length - (2 * dLen)) > 108) { emf.readUnsignedByte(length - (2 * dLen) - 108); } } public void write(EMFOutputStream emf) throws IOException { int align = emf.getTagAlignment(); int padding = (align - (size() % align)) % align; int alignedSize = size() + padding; emf.writeDWORD(type); // Header Type emf.writeDWORD(alignedSize); // length of header emf.writeRECTL(bounds); // inclusive bounds emf.writeRECTL(frame); // inclusive picture emf.writeBYTE(signature.getBytes()); // signature ID EMF emf.writeDWORD((versionMajor << 16) | versionMinor); // version emf.writeDWORD(alignedSize + bytes); // file size emf.writeDWORD(records); // # of records emf.writeWORD(handles); // # of handles, 1 minimum emf.writeWORD(0); // reserved emf.writeDWORD(type == TYPE_EMF_PLUS_ONLY ? 0 : description.length()); // size // of // descriptor // in // WORDS emf.writeDWORD(type == TYPE_EMF_PLUS_ONLY ? 0 : 0x6C); // offset to // descriptor emf.writeDWORD(palEntries); // # of palette entries emf.writeSIZEL(device); // size of ref device emf.writeSIZEL(millimeters); // size of ref device in MM if (type != TYPE_EMF_PLUS_ONLY) { emf.writeDWORD(0); // cbPixelFormat emf.writeDWORD(0); // offPixelFormat emf.writeDWORD(openGL); // bOpenGL emf.writeSIZEL(micrometers); // size of ref device in microns // optional description emf.writeWCHAR(description); } // padding for (int i = 0; i < padding; i++) { emf.write(0); } } /** size of emf file in bytes ? */ public int size() { return 108 + (2 * description.length()); } @Override public String toString() { StringBuffer s = new StringBuffer("EMF Header\n"); s.append(" bounds: " + bounds + "\n"); s.append(" frame: " + frame + "\n"); s.append(" signature: " + signature + "\n"); s.append(" versionMajor: " + versionMajor + "\n"); s.append(" versionMinor: " + versionMinor + "\n"); s.append(" #bytes: " + bytes + "\n"); s.append(" #records: " + records + "\n"); s.append(" #handles: " + handles + "\n"); s.append(" description: " + description + "\n"); s.append(" #palEntries: " + palEntries + "\n"); s.append(" device: " + device + "\n"); s.append(" millimeters: " + millimeters + "\n"); s.append(" openGL: " + openGL + "\n"); s.append(" micrometers: " + micrometers); return s.toString(); } /** * Specifies the dimensions, in device units, of the smallest rectangle that * can be drawn around the picture stored in the metafile. This rectangle is * supplied by graphics device interface (GDI). Its dimensions include the * right and bottom edges. */ public Rectangle getBounds() { return bounds; } /** * Specifies the dimensions, in .01 millimeter units, of a rectangle that * surrounds the picture stored in the metafile. This rectangle must be * supplied by the application that creates the metafile. Its dimensions * include the right and bottom edges. */ public Rectangle getFrame() { return frame; } /** * Specifies a double word signature. This member must specify the value * assigned to the ENHMETA_SIGNATURE constant. */ public String getSignature() { return signature; } /** the description of the enhanced metafile's contents */ public String getDescription() { return description; } /** Specifies the resolution of the reference device, in pixels. */ public Dimension getDevice() { return device; } /** Specifies the resolution of the reference device, in millimeters. */ public Dimension getMillimeters() { return millimeters; } /** * Windows 98/Me, Windows 2000/XP: Size of the reference device in * micrometers. */ public Dimension getMicrometers() { return micrometers; } /** * Windows 95/98/Me, Windows NT 4.0 and later: Specifies whether any OpenGL * records are present in a metafile. bOpenGL is a simple Boolean flag that * you can use to determine whether an enhanced metafile requires OpenGL * handling. When a metafile contains OpenGL records, bOpenGL is TRUE; * otherwise it is FALSE. */ public boolean isOpenGL() { return openGL; } }