package net.arnx.wmf2svg.gdi.wmf; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.arnx.wmf2svg.gdi.Gdi; import net.arnx.wmf2svg.gdi.GdiBrush; import net.arnx.wmf2svg.gdi.GdiFont; import net.arnx.wmf2svg.gdi.GdiObject; import net.arnx.wmf2svg.gdi.GdiPalette; import net.arnx.wmf2svg.gdi.GdiPatternBrush; import net.arnx.wmf2svg.gdi.GdiPen; import net.arnx.wmf2svg.gdi.GdiRegion; import net.arnx.wmf2svg.gdi.Point; import net.arnx.wmf2svg.gdi.Size; public class WmfGdi implements Gdi, WmfConstants { private byte[] placeableHeader; private byte[] header; private List objects = new ArrayList(); private List records = new ArrayList(); public WmfGdi() { } public void write(OutputStream out) throws IOException { footer(); if (placeableHeader != null) out.write(placeableHeader); if (header != null) out.write(header); Iterator i = records.iterator(); while (i.hasNext()) { out.write((byte[])i.next()); } } public void placeableHeader(int vsx, int vsy, int vex, int vey, int dpi) { byte[] record = new byte[22]; int pos = 0; pos = setUint32(record, pos, 0x9AC6CDD7); pos = setInt16(record, pos, 0x0000); pos = setInt16(record, pos, vsx); pos = setInt16(record, pos, vsy); pos = setInt16(record, pos, vex); pos = setInt16(record, pos, vey); pos = setUint16(record, pos, dpi); pos = setUint32(record, pos, 0x00000000); int checksum = 0; for (int i = 0; i < record.length-2; i+=2) { checksum ^= (0xFF & record[i]) | ((0xFF & record[i+1]) << 8); } pos = setUint16(record, pos, checksum); placeableHeader = record; } public void header() { byte[] record = new byte[18]; int pos = 0; pos = setUint16(record, pos, 0x0001); pos = setUint16(record, pos, 0x0009); pos = setUint16(record, pos, 0x0300); pos = setUint32(record, pos, 0x0000); // dummy size pos = setUint16(record, pos, 0x0000); // dummy noObjects pos = setUint32(record, pos, 0x0000); // dummy maxRecords pos = setUint16(record, pos, 0x0000); header = record; } public void animatePalette(GdiPalette palette, int startIndex, int[] entries) { byte[] record = new byte[22]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_ANIMATE_PALETTE); pos = setUint16(record, pos, entries.length); pos = setUint16(record, pos, startIndex); pos = setUint16(record, pos, ((WmfPalette)palette).getID()); for (int i = 0; i < entries.length; i++) { pos = setInt32(record, pos, entries[i]); } records.add(record); } public void arc(int sxr, int syr, int exr, int eyr, int sxa, int sya, int exa, int eya) { byte[] record = new byte[22]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_ARC); pos = setInt16(record, pos, eya); pos = setInt16(record, pos, exa); pos = setInt16(record, pos, sya); pos = setInt16(record, pos, sxa); pos = setInt16(record, pos, eyr); pos = setInt16(record, pos, exr); pos = setInt16(record, pos, syr); pos = setInt16(record, pos, sxr); records.add(record); } public void bitBlt(byte[] image, int dx, int dy, int dw, int dh, int sx, int sy, long rop) { byte[] record = new byte[22 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_BIT_BLT); pos = setUint32(record, pos, rop); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public void chord(int sxr, int syr, int exr, int eyr, int sxa, int sya, int exa, int eya) { byte[] record = new byte[22]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CHORD); pos = setInt16(record, pos, eya); pos = setInt16(record, pos, exa); pos = setInt16(record, pos, sya); pos = setInt16(record, pos, sxa); pos = setInt16(record, pos, eyr); pos = setInt16(record, pos, exr); pos = setInt16(record, pos, syr); pos = setInt16(record, pos, sxr); records.add(record); } public GdiBrush createBrushIndirect(int style, int color, int hatch) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_BRUSH_INDIRECT); pos = setUint16(record, pos, style); pos = setInt32(record, pos, color); pos = setUint16(record, pos, hatch); records.add(record); WmfBrush brush = new WmfBrush(objects.size(), style, color, hatch); objects.add(brush); return brush; } public GdiFont createFontIndirect(int height, int width, int escapement, int orientation, int weight, boolean italic, boolean underline, boolean strikeout, int charset, int outPrecision, int clipPrecision, int quality, int pitchAndFamily, byte[] faceName) { byte[] record = new byte[24 + (faceName.length + faceName.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_FONT_INDIRECT); pos = setInt16(record, pos, height); pos = setInt16(record, pos, width); pos = setInt16(record, pos, escapement); pos = setInt16(record, pos, orientation); pos = setInt16(record, pos, weight); pos = setByte(record, pos, (italic) ? 0x01 : 0x00); pos = setByte(record, pos, (underline) ? 0x01 : 0x00); pos = setByte(record, pos, (strikeout) ? 0x01 : 0x00); pos = setByte(record, pos, charset); pos = setByte(record, pos, outPrecision); pos = setByte(record, pos, clipPrecision); pos = setByte(record, pos, quality); pos = setByte(record, pos, pitchAndFamily); pos = setBytes(record, pos, faceName); if (faceName.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); WmfFont font = new WmfFont(objects.size(), height, width, escapement, orientation, weight, italic, underline, strikeout, charset, outPrecision, clipPrecision, quality, pitchAndFamily, faceName); objects.add(font); return font; } public GdiPalette createPalette(int version, int[] entries) { byte[] record = new byte[10 + entries.length * 4]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_PALETTE); pos = setUint16(record, pos, version); pos = setUint16(record, pos, entries.length); for (int i = 0; i < entries.length; i++) { pos = setInt32(record, pos, entries[i]); } records.add(record); GdiPalette palette = new WmfPalette(objects.size(), version, entries); objects.add(palette); return palette; } public GdiPatternBrush createPatternBrush(byte[] image) { byte[] record = new byte[6 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_PATTERN_BRUSH); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); GdiPatternBrush brush = new WmfPatternBrush(objects.size(), image); objects.add(brush); return brush; } public GdiPen createPenIndirect(int style, int width, int color) { byte[] record = new byte[16]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_PEN_INDIRECT); pos = setUint16(record, pos, style); pos = setInt16(record, pos, width); pos = setInt16(record, pos, 0); pos = setInt32(record, pos, color); records.add(record); WmfPen pen = new WmfPen(objects.size(), style, width, color); objects.add(pen); return pen; } public GdiRegion createRectRgn(int left, int top, int right, int bottom) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_CREATE_RECT_RGN); pos = setInt16(record, pos, bottom); pos = setInt16(record, pos, right); pos = setInt16(record, pos, top); pos = setInt16(record, pos, left); records.add(record); WmfRectRegion rgn = new WmfRectRegion(objects.size(), left, top, right, bottom); objects.add(rgn); return rgn; } public void deleteObject(GdiObject obj) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_DELETE_OBJECT); pos = setUint16(record, pos, ((WmfObject)obj).getID()); records.add(record); objects.set(((WmfObject)obj).getID(), null); } public void dibBitBlt(byte[] image, int dx, int dy, int dw, int dh, int sx, int sy, long rop) { byte[] record = new byte[22 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_DIB_BIT_BLT); pos = setUint32(record, pos, rop); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public GdiPatternBrush dibCreatePatternBrush(byte[] image, int usage) { byte[] record = new byte[10 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_DIB_CREATE_PATTERN_BRUSH); pos = setInt32(record, pos, usage); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); // TODO usage GdiPatternBrush brush = new WmfPatternBrush(objects.size(), image); objects.add(brush); return brush; } public void dibStretchBlt(byte[] image, int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, long rop) { byte[] record = new byte[26 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_DIB_STRETCH_BLT); pos = setUint32(record, pos, rop); pos = setInt16(record, pos, sh); pos = setInt16(record, pos, sw); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public void ellipse(int sx, int sy, int ex, int ey) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_ELLIPSE); pos = setInt16(record, pos, ey); pos = setInt16(record, pos, ex); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); records.add(record); } public void escape(byte[] data) { byte[] record = new byte[10 + (data.length + data.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_ESCAPE); pos = setBytes(record, pos, data); if (data.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public int excludeClipRect(int left, int top, int right, int bottom) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_EXCLUDE_CLIP_RECT); pos = setInt16(record, pos, bottom); pos = setInt16(record, pos, right); pos = setInt16(record, pos, top); pos = setInt16(record, pos, left); records.add(record); // TODO return GdiRegion.COMPLEXREGION; } public void extFloodFill(int x, int y, int color, int type) { byte[] record = new byte[16]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_EXT_FLOOD_FILL); pos = setUint16(record, pos, type); pos = setInt32(record, pos, color); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void extTextOut(int x, int y, int options, int[] rect, byte[] text, int[] lpdx) { if (rect != null && rect.length != 4) { throw new IllegalArgumentException("rect must be 4 length."); } byte[] record = new byte[14 + ((rect != null) ? 8 : 0) + (text.length + text.length%2) + (lpdx.length * 2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_EXT_TEXT_OUT); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); pos = setInt16(record, pos, text.length); pos = setInt16(record, pos, options); if (rect != null) { pos = setInt16(record, pos, rect[0]); pos = setInt16(record, pos, rect[1]); pos = setInt16(record, pos, rect[2]); pos = setInt16(record, pos, rect[3]); } pos = setBytes(record, pos, text); if (text.length%2 == 1) pos = setByte(record, pos, 0); for (int i = 0; i < lpdx.length; i++) { pos = setInt16(record, pos, lpdx[i]); } records.add(record); } public void fillRgn(GdiRegion rgn, GdiBrush brush) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_FLOOD_FILL); pos = setUint16(record, pos, ((WmfBrush)brush).getID()); pos = setUint16(record, pos, ((WmfRegion)rgn).getID()); records.add(record); } public void floodFill(int x, int y, int color) { byte[] record = new byte[16]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_FLOOD_FILL); pos = setInt32(record, pos, color); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void frameRgn(GdiRegion rgn, GdiBrush brush, int w, int h) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_FRAME_RGN); pos = setInt16(record, pos, h); pos = setInt16(record, pos, w); pos = setUint16(record, pos, ((WmfBrush)brush).getID()); pos = setUint16(record, pos, ((WmfRegion)rgn).getID()); records.add(record); } public void intersectClipRect(int left, int top, int right, int bottom) { byte[] record = new byte[16]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_INTERSECT_CLIP_RECT); pos = setInt16(record, pos, bottom); pos = setInt16(record, pos, right); pos = setInt16(record, pos, top); pos = setInt16(record, pos, left); records.add(record); } public void invertRgn(GdiRegion rgn) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_INVERT_RGN); pos = setUint16(record, pos, ((WmfRegion)rgn).getID()); records.add(record); } public void lineTo(int ex, int ey) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_LINE_TO); pos = setInt16(record, pos, ey); pos = setInt16(record, pos, ex); records.add(record); } public void moveToEx(int x, int y, Point old) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_MOVE_TO_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); //TODO old records.add(record); } public void offsetClipRgn(int x, int y) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_OFFSET_CLIP_RGN); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void offsetViewportOrgEx(int x, int y, Point point) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_OFFSET_VIEWPORT_ORG_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); // TODO records.add(record); } public void offsetWindowOrgEx(int x, int y, Point point) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_OFFSET_WINDOW_ORG_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); // TODO records.add(record); } public void paintRgn(GdiRegion rgn) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_PAINT_RGN); pos = setUint16(record, pos, ((WmfRegion)rgn).getID()); records.add(record); } public void patBlt(int x, int y, int width, int height, long rop) { byte[] record = new byte[18]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_PAT_BLT); pos = setUint32(record, pos, rop); pos = setInt16(record, pos, height); pos = setInt16(record, pos, width); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void pie(int sx, int sy, int ex, int ey, int sxr, int syr, int exr, int eyr) { byte[] record = new byte[22]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_PIE); pos = setInt16(record, pos, eyr); pos = setInt16(record, pos, exr); pos = setInt16(record, pos, syr); pos = setInt16(record, pos, sxr); pos = setInt16(record, pos, ey); pos = setInt16(record, pos, ex); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); records.add(record); } public void polygon(Point[] points) { byte[] record = new byte[8 + points.length * 4]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_POLYGON); pos = setInt16(record, pos, points.length); for (int i = 0; i < points.length; i++) { pos = setInt16(record, pos, points[i].x); pos = setInt16(record, pos, points[i].y); } records.add(record); } public void polyline(Point[] points) { byte[] record = new byte[8 + points.length * 4]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_POLYLINE); pos = setInt16(record, pos, points.length); for (int i = 0; i < points.length; i++) { pos = setInt16(record, pos, points[i].x); pos = setInt16(record, pos, points[i].y); } records.add(record); } public void polyPolygon(Point[][] points) { int length = 8; for (int i = 0; i < points.length; i++) { length += 2 + points[i].length * 4; } byte[] record = new byte[length]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_POLYLINE); pos = setInt16(record, pos, points.length); for (int i = 0; i < points.length; i++) { pos = setInt16(record, pos, points[i].length); } for (int i = 0; i < points.length; i++) { for (int j = 0; j < points[i].length; j++) { pos = setInt16(record, pos, points[i][j].x); pos = setInt16(record, pos, points[i][j].y); } } records.add(record); } public void realizePalette() { byte[] record = new byte[6]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_REALIZE_PALETTE); records.add(record); } public void restoreDC(int savedDC) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_RESTORE_DC); pos = setInt16(record, pos, savedDC); records.add(record); } public void rectangle(int sx, int sy, int ex, int ey) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_RECTANGLE); pos = setInt16(record, pos, ey); pos = setInt16(record, pos, ex); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); records.add(record); } public void resizePalette(GdiPalette palette) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_REALIZE_PALETTE); pos = setUint16(record, pos, ((WmfPalette)palette).getID()); records.add(record); } public void roundRect(int sx, int sy, int ex, int ey, int rw, int rh) { byte[] record = new byte[18]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_ROUND_RECT); pos = setInt16(record, pos, rh); pos = setInt16(record, pos, rw); pos = setInt16(record, pos, ey); pos = setInt16(record, pos, ex); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); records.add(record); } public void seveDC() { byte[] record = new byte[6]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SAVE_DC); records.add(record); } public void scaleViewportExtEx(int x, int xd, int y, int yd, Size old) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SCALE_VIEWPORT_EXT_EX); pos = setInt16(record, pos, yd); pos = setInt16(record, pos, y); pos = setInt16(record, pos, xd); pos = setInt16(record, pos, x); // TODO records.add(record); } public void scaleWindowExtEx(int x, int xd, int y, int yd, Size old) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SCALE_WINDOW_EXT_EX); pos = setInt16(record, pos, yd); pos = setInt16(record, pos, y); pos = setInt16(record, pos, xd); pos = setInt16(record, pos, x); // TODO records.add(record); } public void selectClipRgn(GdiRegion rgn) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SELECT_CLIP_RGN); pos = setUint16(record, pos, ((WmfRegion)rgn).getID()); records.add(record); } public void selectObject(GdiObject obj) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SELECT_OBJECT); pos = setUint16(record, pos, ((WmfObject)obj).getID()); records.add(record); } public void selectPalette(GdiPalette palette, boolean mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SELECT_PALETTE); pos = setInt16(record, pos, mode ? 1 : 0); pos = setUint16(record, pos, ((WmfPalette)palette).getID()); records.add(record); } public void setBkColor(int color) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_BK_COLOR); pos = setInt32(record, pos, color); records.add(record); } public void setBkMode(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_BK_MODE); pos = setInt16(record, pos, mode); records.add(record); } public void setDIBitsToDevice(int dx, int dy, int dw, int dh, int sx, int sy, int startscan, int scanlines, byte[] image, int colorUse) { byte[] record = new byte[24 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_DIBITS_TO_DEVICE); pos = setUint16(record, pos, colorUse); pos = setUint16(record, pos, scanlines); pos = setUint16(record, pos, startscan); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public void setLayout(long layout) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_LAYOUT); pos = setUint32(record, pos, layout); records.add(record); } public void setMapMode(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_MAP_MODE); pos = setInt16(record, pos, mode); records.add(record); } public void setMapperFlags(long flags) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_MAPPER_FLAGS); pos = setUint32(record, pos, flags); records.add(record); } public void setPaletteEntries(GdiPalette palette, int startIndex, int[] entries) { byte[] record = new byte[6 + entries.length * 4]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_PALETTE_ENTRIES); pos = setUint16(record, pos, ((WmfPalette)palette).getID()); pos = setUint16(record, pos, entries.length); pos = setUint16(record, pos, startIndex); for (int i = 0; i < entries.length; i++) { pos = setInt32(record, pos, entries[i]); } records.add(record); } public void setPixel(int x, int y, int color) { byte[] record = new byte[14]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_PIXEL); pos = setInt32(record, pos, color); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void setPolyFillMode(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_POLY_FILL_MODE); pos = setInt16(record, pos, mode); records.add(record); } public void setRelAbs(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_REL_ABS); pos = setInt16(record, pos, mode); records.add(record); } public void setROP2(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_ROP2); pos = setInt16(record, pos, mode); records.add(record); } public void setStretchBltMode(int mode) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_STRETCH_BLT_MODE); pos = setInt16(record, pos, mode); records.add(record); } public void setTextAlign(int align) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_TEXT_ALIGN); pos = setInt16(record, pos, align); records.add(record); } public void setTextCharacterExtra(int extra) { byte[] record = new byte[8]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_TEXT_CHARACTER_EXTRA); pos = setInt16(record, pos, extra); records.add(record); } public void setTextColor(int color) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_TEXT_COLOR); pos = setInt32(record, pos, color); records.add(record); } public void setTextJustification(int breakExtra, int breakCount) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_TEXT_COLOR); pos = setInt16(record, pos, breakCount); pos = setInt16(record, pos, breakExtra); records.add(record); } public void setViewportExtEx(int x, int y, Size old) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_VIEWPORT_EXT_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void setViewportOrgEx(int x, int y, Point old) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_VIEWPORT_ORG_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void setWindowExtEx(int width, int height, Size old) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_WINDOW_EXT_EX); pos = setInt16(record, pos, height); pos = setInt16(record, pos, width); records.add(record); } public void setWindowOrgEx(int x, int y, Point old) { byte[] record = new byte[10]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_SET_WINDOW_ORG_EX); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void stretchBlt(byte[] image, int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, long rop) { byte[] record = new byte[26 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_STRETCH_BLT); pos = setUint32(record, pos, rop); pos = setInt16(record, pos, sh); pos = setInt16(record, pos, sw); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public void stretchDIBits(int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, byte[] image, int usage, long rop) { byte[] record = new byte[26 + (image.length + image.length%2)]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_STRETCH_DIBITS); pos = setUint32(record, pos, rop); pos = setUint16(record, pos, usage); pos = setInt16(record, pos, sh); pos = setInt16(record, pos, sw); pos = setInt16(record, pos, sy); pos = setInt16(record, pos, sx); pos = setInt16(record, pos, dw); pos = setInt16(record, pos, dh); pos = setInt16(record, pos, dy); pos = setInt16(record, pos, dx); pos = setBytes(record, pos, image); if (image.length%2 == 1) pos = setByte(record, pos, 0); records.add(record); } public void textOut(int x, int y, byte[] text) { byte[] record = new byte[10 + text.length + text.length%2]; int pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, RECORD_TEXT_OUT); pos = setInt16(record, pos, text.length); pos = setBytes(record, pos, text); if (text.length%2 == 1) pos = setByte(record, pos, 0); pos = setInt16(record, pos, y); pos = setInt16(record, pos, x); records.add(record); } public void footer() { int pos = 0; if (header != null) { long size = header.length; long maxRecordSize = 0; Iterator i = records.iterator(); while (i.hasNext()) { byte[] record = (byte[])i.next(); size += record.length; if (record.length > maxRecordSize) maxRecordSize = record.length; } pos = setUint32(header, 6, size/2); pos = setUint16(header, pos, objects.size()); pos = setUint32(header, pos, maxRecordSize / 2); } byte[] record = new byte[6]; pos = 0; pos = setUint32(record, pos, record.length/2); pos = setUint16(record, pos, 0x0000); records.add(record); } private int setByte(byte[] out, int pos, int value) { out[pos] = (byte)(0xFF & value); return pos + 1; } private int setBytes(byte[] out, int pos, byte[] data) { System.arraycopy(data, 0, out, pos, data.length); return pos + data.length; } private int setInt16(byte[] out, int pos, int value) { out[pos] = (byte)(0xFF & value); out[pos+1] = (byte)(0xFF & (value >> 8)); return pos + 2; } private int setInt32(byte[] out, int pos, int value) { out[pos] = (byte)(0xFF & value); out[pos+1] = (byte)(0xFF & (value >> 8)); out[pos+2] = (byte)(0xFF & (value >> 16)); out[pos+3] = (byte)(0xFF & (value >> 24)); return pos + 4; } private int setUint16(byte[] out, int pos, int value) { out[pos] = (byte)(0xFF & value); out[pos+1] = (byte)(0xFF & (value >> 8)); return pos + 2; } private int setUint32(byte[] out, int pos, long value) { out[pos] = (byte)(0xFF & value); out[pos+1] = (byte)(0xFF & (value >> 8)); out[pos+2] = (byte)(0xFF & (value >> 16)); out[pos+3] = (byte)(0xFF & (value >> 24)); return pos + 4; } }