0001: /*
0002: * @(#)WMF.java 1.00 25/4/99
0003: *
0004: * Copyright (c) 1997 Axiom Software Development Ltd.
0005: * All Rights Reserved.
0006: *
0007: * Permission to use, copy, modify, and distribute this
0008: * software and its documentation for NON-COMMERCIAL purposes
0009: * and without fee is hereby granted provided that this
0010: * copyright notice appears in all copies. Please refer to
0011: * the file "copyright.html" for further important copyright
0012: * and licensing information.
0013: *
0014: * ASD MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
0015: * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
0016: * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
0017: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
0018: * NON-INFRINGEMENT. ASD SHALL NOT BE LIABLE FOR ANY DAMAGES
0019: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
0020: * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
0021: * $Revision: 1.8 $
0022: */
0023: package net.xoetrope.xui.wmf;
0024:
0025: /**
0026: * A control that extends Canvas and renders a WMF file.
0027: */
0028:
0029: import java.io.BufferedInputStream;
0030: import java.io.DataInputStream;
0031: import java.io.IOException;
0032: import java.io.Serializable;
0033: import java.net.MalformedURLException;
0034: import java.net.URL;
0035: import java.util.Stack;
0036: import java.util.Vector;
0037:
0038: import java.awt.BasicStroke;
0039: import java.awt.BorderLayout;
0040: import java.awt.Canvas;
0041: import java.awt.Color;
0042: import java.awt.Font;
0043: import java.awt.Graphics;
0044: import java.awt.Graphics2D;
0045: import java.awt.Shape;
0046: import java.awt.event.MouseEvent;
0047: import java.awt.event.MouseMotionAdapter;
0048: import java.awt.font.FontRenderContext;
0049: import java.awt.font.TextLayout;
0050: import java.awt.geom.AffineTransform;
0051: import java.awt.geom.GeneralPath;
0052: import java.awt.geom.Point2D;
0053:
0054: import net.xoetrope.xui.XContentHolder;
0055: import net.xoetrope.xui.XResourceManager;
0056: import net.xoetrope.xui.XProjectManager;
0057:
0058: /**
0059: * Core class for rendering the WMF image.
0060: *
0061: *
0062: * Allows several WMF or WMF graphics files to be played into a single graphics
0063: * context.
0064: * @version 2.00
0065: * @author Luan O'Carroll
0066: */
0067: public class XWmf extends Canvas implements Serializable,
0068: XContentHolder {
0069: static final long serialVersionUID = 1413615767071266522L;
0070: static final double PI = 57.29577951;
0071:
0072: private static BasicStroke solid = new BasicStroke(1.0f,
0073: BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
0074:
0075: /**
0076: * Basic constructor, initializes the storage.
0077: */
0078: public XWmf() {
0079: try {
0080: init();
0081: } catch (IOException e) {
0082: e.printStackTrace();
0083: }
0084: }
0085:
0086: /**
0087: * Basic constructor for use by Genny.
0088: */
0089: public XWmf(boolean bInit) {
0090: if (bInit) {
0091: try {
0092: init();
0093: } catch (IOException e) {
0094: }
0095: }
0096: }
0097:
0098: /**
0099: * Initializes the storage, add listeners for mouse motion and keyboard
0100: * handling.
0101: */
0102: public void init() throws IOException {
0103: // setDoubleBuffered( true );
0104: // this.setLayout( borderLayout );
0105: setBackground(Color.white);
0106: reset();
0107: //==========================================================================
0108: // Inner Class
0109: addMouseMotionListener(new MouseMotionAdapter() {
0110: public void mouseMoved(MouseEvent e) {
0111: Graphics g = getGraphics();
0112: if (g != null)
0113: drawCrossHairs(g, e.getX(), e.getY());
0114: g.dispose();
0115:
0116: oldX = e.getX();
0117: oldY = e.getY();
0118: }
0119: });
0120: // End inner class.
0121: //==========================================================================
0122:
0123: }
0124:
0125: /**
0126: * Resets the internal storage and the coordinate system.
0127: */
0128: public void reset() {
0129: numRecords = 0;
0130: numObjects = 0;
0131: vpX = 0;
0132: vpY = 0;
0133: vpW = 1000;
0134: vpH = 1000;
0135: XPos = 0;
0136: YPos = 0;
0137: oldX = 0;
0138: oldY = 0;
0139: xPan = 0;
0140: yPan = 0;
0141: zoom = 100;
0142: drawCrossHairs = false;
0143: dcStack = new Stack();
0144: stores = new Vector();
0145: }
0146:
0147: /**
0148: * Renders the WMF image(s).
0149: */
0150: public void paint(Graphics g) {
0151: int numStores = stores.size();
0152: for (int iStore = 0; iStore < numStores; iStore++) {
0153: currentStore = (RecordStore) stores.elementAt(iStore);
0154: int numRecords = currentStore.getNumRecords();
0155: int numObjects = currentStore.getNumObjects();
0156: vpX = currentStore.getVpX();
0157: vpY = currentStore.getVpY();
0158: vpW = currentStore.getVpW();
0159: vpH = currentStore.getVpH();
0160:
0161: if (!currentStore.isReading()) {
0162: GdiObject gdiObj;
0163: int gdiIndex;
0164: g.setPaintMode();
0165:
0166: brushObject = -1;
0167: penObject = -1;
0168: fontObject = -1;
0169: frgdColor = null;
0170: bkgdColor = null;
0171: for (int i = 0; i < numObjects; i++) {
0172: gdiObj = currentStore.getObject(i);
0173: gdiObj.Clear();
0174: }
0175:
0176: int w = getSize().width;
0177: int h = getSize().height;
0178:
0179: g.setColor(Color.white);
0180: g.fillRect(0, 0, w, h);
0181: g.setColor(Color.black);
0182:
0183: double scaleX = (double) w / vpW;
0184: double scaleY = (double) h / vpH;
0185: scaleX *= (double) zoom / 100.0;
0186: scaleY *= (double) zoom / 100.0;
0187:
0188: double xOffset = (xPan * w * zoom) / 10000.0;
0189: double yOffset = (yPan * h * zoom) / 10000.0;
0190:
0191: for (int iRec = 0; iRec < numRecords; iRec++) {
0192: MetaRecord mr = currentStore.getRecord(iRec);
0193: switch (mr.functionId) {
0194: case 0x020B: //"SETWINDOWORG", 0x020B,
0195: currentStore.setVpX(vpX = -mr.ElementAt(0)
0196: .intValue());
0197: currentStore.setVpY(vpY = -mr.ElementAt(1)
0198: .intValue());
0199: break;
0200:
0201: case 0x0000: //"SETWINDOWORG", 0x020B,
0202: case 0x020C: //"SETWINDOWEXT", 0x020C,
0203: currentStore.setVpW(vpW = mr.ElementAt(0)
0204: .intValue());
0205: currentStore.setVpH(vpH = mr.ElementAt(1)
0206: .intValue());
0207: scaleX = (double) w / vpW;
0208: scaleY = (double) h / vpH;
0209: scaleX *= (double) zoom / 100.0;
0210: scaleY *= (double) zoom / 100.0;
0211:
0212: xOffset = (xPan * w * zoom) / 10000.0;
0213: yOffset = (yPan * h * zoom) / 10000.0;
0214: // Handled in the read function.
0215: break;
0216:
0217: case 0x020D: //"SETVIEWPORTORG", 0x020D,
0218: case 0x020E: //"SETVIEWPORTEXT", 0x020E,
0219: case 0x020F: //"OFFSETWINDOWORG", 0x020F,
0220: case 0x0400: //"SCALEWINDOWEXT", 0x0400,
0221: case 0x0211: //"OFFSETVIEWPORTORG", 0x0211,
0222: case 0x0412: //"SCALEVIEWPORTEXT", 0x0412,
0223: break;
0224:
0225: case 0x0106: //"SETPOLYFILLMODE", 0x0106,
0226: break;
0227:
0228: case 0x02FA: //"CREATEPENINDIRECT", 0x02FA,
0229: {
0230: int objIndex = 0;
0231: try {
0232: objIndex = (int) mr.ElementAt(5).intValue();
0233: } catch (Exception e) {
0234: //objIndex = lastObjectIdx++;
0235: }
0236: int penStyle = (int) mr.ElementAt(0).intValue();
0237: Color newClr;
0238: if (penStyle == 5 /*PS_NULL*/) {
0239: newClr = new Color(255, 255, 255);
0240: objIndex = numObjects + 8;
0241: addObjectAt(NULL_PEN, newClr, objIndex);
0242: penWidth = -1;
0243: } else {
0244: newClr = new Color((int) mr.ElementAt(1)
0245: .intValue(), (int) mr.ElementAt(2)
0246: .intValue(), (int) mr.ElementAt(3)
0247: .intValue());
0248: addObjectAt(PEN, newClr, objIndex);
0249: penWidth = mr.ElementAt(4).intValue();
0250: }
0251: }
0252: break;
0253:
0254: case 0x02FC: //"CREATEBRUSHINDIRECT", 0x02FC,
0255: {
0256: int objIndex = 0;
0257: try {
0258: objIndex = (int) mr.ElementAt(5).intValue();
0259: } catch (Exception e) {
0260: //objIndex = lastObjectIdx++;
0261: }
0262: int brushStyle = (int) mr.ElementAt(0)
0263: .intValue();
0264: if (brushStyle != 1) {
0265: addObjectAt(BRUSH, new Color((int) mr
0266: .ElementAt(1).intValue(), (int) mr
0267: .ElementAt(2).intValue(), (int) mr
0268: .ElementAt(3).intValue()), objIndex);
0269: } else
0270: addObjectAt(NULL_BRUSH, new Color(0, 0, 0),
0271: objIndex);
0272: }
0273: break;
0274:
0275: case 0x02FB: //"CREATEFONTINDIRECT", 0x02FB,
0276: {
0277: int style = ((int) mr.ElementAt(1).intValue() > 0 ? Font.ITALIC
0278: : Font.PLAIN);
0279: style |= ((int) mr.ElementAt(2).intValue() > 400 ? Font.BOLD
0280: : Font.PLAIN);
0281:
0282: int size = (int) (scaleY * (mr.ElementAt(0)
0283: .intValue()));
0284: String face = ((StringRecord) mr).text;
0285: if (size < 0)
0286: size = (int) ((double) size * -1.3);
0287: int objIndex = 0;
0288: try {
0289: objIndex = (int) mr.ElementAt(3).intValue();
0290: } catch (Exception e) {
0291: //objIndex = lastObjectIdx++;
0292: }
0293: fontHeight = size;
0294: //fontAngle = mr.ElementAt( 5 ).intValue();
0295: //if ( fontAngle > 0 )
0296: //size = ( size *12 ) / 10;
0297: addObjectAt(FONT, font = new Font(face, style,
0298: size), objIndex);
0299: }
0300: break;
0301:
0302: case 0x0142: // "DIBCREATEPATTERNBRUSH"
0303: case 0x00F8: // "CREATEBRUSH"
0304: case 0x01F9: // "CREATEPATTERNBRUSH"
0305: case 0x02FD: // "CREATEBITMAPINDIRECT"
0306: case 0x06FE: // "CREATEBITMAP"
0307: case 0x06FF: // "CREATEREGION"
0308: case 0x00f7: // "CREATEPALETTE"
0309: addObjectAt(PALETTE, new Integer(0), 0/*lastObjectIdx++*/);
0310: break;
0311:
0312: case 0x0234: //"SELECTPALETTE", 0x0234,
0313: case 0x0035: //"REALIZEPALETTE", 0x0035,
0314: case 0x0436: //"ANIMATEPALETTE", 0x0436,
0315: case 0x0037: //"SETPALENTRIES", 0x0037,
0316: case 0x0139: //"RESIZEPALETTE", 0x0139,
0317: break;
0318:
0319: case 0x012D: //"SELECTOBJECT", 0x012D,
0320: gdiIndex = mr.ElementAt(0).intValue();
0321: if ((gdiIndex & 0x80000000) != 0) // Stock Object
0322: break;
0323: if (gdiIndex >= numObjects) {
0324: gdiIndex -= numObjects;
0325: switch (gdiIndex) {
0326: case 5://NULL_BRUSH HOLLOW_BRUSH
0327: brushObject = -1;
0328: break;
0329: case 8://NULL_PEN 8
0330: penObject = -1;
0331: break;
0332: case 0://WHITE_BRUSH
0333: case 1://LTGRAY_BRUSH 1
0334: case 2://GRAY_BRUSH 2
0335: case 3://DKGRAY_BRUSH 3
0336: case 4://BLACK_BRUSH 4
0337: case 6://WHITE_PEN 6
0338: case 7://BLACK_PEN 7
0339: case 10://OEM_FIXED_FONT 10
0340: case 11://ANSI_FIXED_FONT 11
0341: case 12://ANSI_VAR_FONT 12
0342: case 13://SYSTEM_FONT 13
0343: case 14://DEVICE_DEFAULT_FONT 14
0344: case 15://DEFAULT_PALETTE 15
0345: case 16://SYSTEM_FIXED_FONT 16
0346: break;
0347: }
0348: break;
0349: }
0350: gdiObj = currentStore.getObject(gdiIndex);
0351: if (!gdiObj.used)
0352: break;
0353: switch (gdiObj.type) {
0354: case PEN:
0355: g.setColor((Color) gdiObj.obj);
0356: penObject = gdiIndex;
0357: break;
0358: case BRUSH:
0359: g.setColor((Color) gdiObj.obj);
0360: brushObject = gdiIndex;
0361: break;
0362: case FONT:
0363: g.setFont(font = (Font) gdiObj.obj);
0364: fontObject = gdiIndex;
0365: break;
0366: case NULL_PEN:
0367: penObject = -1;
0368: break;
0369: case NULL_BRUSH:
0370: brushObject = -1;
0371: break;
0372: default:
0373: break;
0374: }
0375: break;
0376:
0377: case 0x01f0: //"DELETEOBJECT", 0x01f0,
0378: gdiIndex = mr.ElementAt(0).intValue();
0379: gdiObj = currentStore.getObject(gdiIndex);
0380: if (gdiIndex == brushObject)
0381: brushObject = -1;
0382: else if (gdiIndex == penObject)
0383: penObject = -1;
0384: else if (gdiIndex == fontObject)
0385: fontObject = -1;
0386: gdiObj.Clear();
0387: break;
0388:
0389: case 0x0538: //"POLYPOLYGON", 0x0538,
0390: {
0391: int numPolygons = mr.ElementAt(0).intValue();
0392: int[] pts = new int[numPolygons];
0393: for (int ip = 0; ip < numPolygons; ip++)
0394: pts[ip] = mr.ElementAt(ip + 1).intValue();
0395:
0396: int offset = numPolygons + 1;
0397: for (int j = 0; j < numPolygons; j++) {
0398: int count = pts[j];
0399: int[] xpts = new int[count];
0400: int[] ypts = new int[count];
0401: for (int k = 0; k < count; k++) {
0402: xpts[k] = (int) (xOffset + scaleX
0403: * (vpX + mr.ElementAt(
0404: offset + k * 2)
0405: .intValue()));
0406: ypts[k] = (int) (yOffset + scaleY
0407: * (vpY + mr.ElementAt(
0408: offset + k * 2 + 1)
0409: .intValue()));
0410: }
0411: offset += count;
0412: if (brushObject >= 0) {
0413: setBrushColor(g);
0414: g.fillPolygon(xpts, ypts, count);
0415: }
0416: setPenColor(g);
0417: g.drawPolygon(xpts, ypts, count);
0418: }
0419: }
0420: break;
0421:
0422: case 0x0324: //"POLYGON", 0x0324,
0423: {
0424: int count = mr.ElementAt(0).intValue();
0425: int[] _xpts = new int[count + 1];
0426: int[] _ypts = new int[count + 1];
0427: for (int k = 0; k < count; k++) {
0428: _xpts[k] = (int) (xOffset + scaleX
0429: * (vpX + mr.ElementAt(k * 2 + 1)
0430: .intValue()));
0431: _ypts[k] = (int) (yOffset + scaleY
0432: * (vpY + mr.ElementAt(k * 2 + 2)
0433: .intValue()));
0434: }
0435: _xpts[count] = _xpts[0];
0436: _ypts[count] = _ypts[0];
0437: if (brushObject >= 0) {
0438: setBrushColor(g);
0439: g.fillPolygon(_xpts, _ypts, count);
0440: }
0441: setPenColor(g);
0442: g.drawPolygon(_xpts, _ypts, count + 1);
0443: }
0444: break;
0445:
0446: case 0x0214: //"MOVETO", 0x0214,
0447: startX = (int) (xOffset + scaleX
0448: * (vpX + mr.ElementAt(0).intValue()));
0449: startY = (int) (yOffset + scaleY
0450: * (vpY + mr.ElementAt(1).intValue()));
0451: break;
0452:
0453: case 0x0213: //"LINETO", 0x0213,
0454: {
0455: int endX = (int) (xOffset + scaleX
0456: * (vpX + mr.ElementAt(0).intValue()));
0457: int endY = (int) (yOffset + scaleY
0458: * (vpY + mr.ElementAt(1).intValue()));
0459: setPenColor(g);
0460: g.drawLine(startX, startY, endX, endY);
0461: startX = endX;
0462: startY = endY;
0463: }
0464: break;
0465:
0466: case 0x0325: //"POLYLINE", 0x0325,
0467: {
0468: setPenColor(g);
0469: int count = mr.ElementAt(0).intValue();
0470: int endX, endY;
0471: int _startX, _startY;
0472: _startX = (int) (xOffset + scaleX
0473: * (vpX + mr.ElementAt(1).intValue()));
0474: _startY = (int) (yOffset + scaleY
0475: * (vpY + mr.ElementAt(2).intValue()));
0476: for (int j = 1; j < count; j++) {
0477: endX = (int) (xOffset + scaleX
0478: * (vpX + mr.ElementAt(j * 2 + 1)
0479: .intValue()));
0480: endY = (int) (yOffset + scaleY
0481: * (vpY + mr.ElementAt(j * 2 + 2)
0482: .intValue()));
0483: g.drawLine(_startX, _startY, endX, endY);
0484: _startX = endX;
0485: _startY = endY;
0486: }
0487: }
0488: break;
0489:
0490: case 0x041B: //"RECTANGLE", 0x041B,
0491: {
0492: int x1, y1, x2, y2;
0493: x1 = (int) (xOffset + scaleX
0494: * (vpX + mr.ElementAt(0).intValue()));
0495: x2 = (int) (xOffset + scaleX
0496: * (vpX + mr.ElementAt(2).intValue()));
0497: y1 = (int) (yOffset + scaleY
0498: * (vpY + mr.ElementAt(1).intValue()));
0499: y2 = (int) (yOffset + scaleY
0500: * (vpY + mr.ElementAt(3).intValue()));
0501:
0502: if (brushObject >= 0) {
0503: setBrushColor(g);
0504: g.fillRect(x1, y1, x2 - x1, y2 - y1);
0505: }
0506: setPenColor(g);
0507:
0508: if (penObject >= 0)
0509: g.drawRect(x1, y1, x2 - x1, y2 - y1);
0510: }
0511: break;
0512:
0513: case 0x061C: //"ROUNDRECT", 0x061C,
0514: {
0515: int x1, y1, x2, y2, x3, y3;
0516: x1 = (int) (xOffset + scaleX
0517: * (vpX + mr.ElementAt(0).intValue()));
0518: x2 = (int) (xOffset + scaleX
0519: * (vpX + mr.ElementAt(2).intValue()));
0520: x3 = (int) (scaleX * (mr.ElementAt(4)
0521: .intValue()));
0522: y1 = (int) (yOffset + scaleY
0523: * (vpY + mr.ElementAt(1).intValue()));
0524: y2 = (int) (yOffset + scaleY
0525: * (vpY + mr.ElementAt(3).intValue()));
0526: y3 = (int) (scaleY * (mr.ElementAt(5)
0527: .intValue()));
0528:
0529: if (brushObject >= 0) {
0530: setBrushColor(g);
0531: g.fillRoundRect(x1, y1, x2 - x1, y2 - y1,
0532: x3, y3);
0533: }
0534: setPenColor(g);
0535: g.drawRoundRect(x1, y1, x2 - x1, y2 - y1, x3,
0536: y3);
0537: }
0538: break;
0539:
0540: case 0x0418: //"ELLIPSE", 0x0418,
0541: {
0542: int x1, y1, x2, y2;
0543: x1 = (int) (xOffset + scaleX
0544: * (vpX + mr.ElementAt(0).intValue()));
0545: x2 = (int) (xOffset + scaleX
0546: * (vpX + mr.ElementAt(2).intValue()));
0547: y1 = (int) (yOffset + scaleY
0548: * (vpY + mr.ElementAt(1).intValue()));
0549: y2 = (int) (yOffset + scaleY
0550: * (vpY + mr.ElementAt(3).intValue()));
0551:
0552: setBrushColor(g);
0553: if (brushObject >= 0)
0554: g.fillOval(x1, y1, x2 - x1, y2 - y1);
0555:
0556: setPenColor(g);
0557: if (penObject >= 0)
0558: g
0559: .drawOval(x1, y1, x2 - x1 - 1, y2
0560: - y1 - 1);
0561: }
0562: break;
0563:
0564: case 0x0209: //"SETTEXTCOLOR", 0x0209,
0565: frgdColor = new Color((int) mr.ElementAt(0)
0566: .intValue(), (int) mr.ElementAt(1)
0567: .intValue(), (int) mr.ElementAt(2)
0568: .intValue());
0569: break;
0570:
0571: case 0x0201: //"SETBKCOLOR", 0x0201,
0572: bkgdColor = new Color((int) mr.ElementAt(0)
0573: .intValue(), (int) mr.ElementAt(1)
0574: .intValue(), (int) mr.ElementAt(2)
0575: .intValue());
0576: break;
0577:
0578: case 0x0a32: //"EXTTEXTOUT", 0x0a32,
0579: case 0x0521: //"TEXTOUT", 0x0521,
0580: case 0x062F: //"DRAWTEXT", 0x062F,
0581: try {
0582: Graphics2D g2 = (Graphics2D) g;
0583: int x, y;
0584: x = (int) (xOffset + scaleX
0585: * (vpX + mr.ElementAt(0).intValue()));
0586: y = (int) (yOffset + /*fontHeight*/+scaleY
0587: * (vpY + mr.ElementAt(1).intValue()));
0588: if (frgdColor != null)
0589: g.setColor(frgdColor);
0590: else
0591: g.setColor(Color.black);
0592: StringRecord sr = (StringRecord) mr;
0593:
0594: FontRenderContext frc = g2
0595: .getFontRenderContext();
0596:
0597: Point2D.Double pen = new Point2D.Double(0,
0598: 0);
0599: GeneralPath gp = new GeneralPath(
0600: GeneralPath.WIND_NON_ZERO);
0601: TextLayout layout = new TextLayout(sr.text,
0602: font, frc);
0603: pen.y += layout.getAscent();
0604:
0605: if ((fontAngle != 0)
0606: || sr.text
0607: .startsWith("Sono una scala verticale di prevalenza")) {
0608: AffineTransform at = new AffineTransform();
0609: float width = (float) layout
0610: .getBounds().getWidth();
0611: float height = (float) layout
0612: .getBounds().getHeight();
0613:
0614: AffineTransform textAt = new AffineTransform();
0615: textAt.translate(x, y);
0616: textAt.rotate(Math.toRadians(270));
0617: textAt.translate(0, height);
0618: Shape shape = layout.getOutline(textAt);
0619: gp
0620: .append(
0621: at
0622: .createTransformedShape(shape)/*layout.getOutline( null ))*/,
0623: false);
0624: g2.draw(shape);
0625: } else
0626: g.drawString(sr.text, x, y);
0627: } catch (Exception e) {
0628: }
0629: break;
0630:
0631: case 0x0817: //"ARC", 0x0817,
0632: case 0x081A: //"PIE", 0x081A,
0633: {
0634: int x1, y1, x2, y2, x3, y3, x4, y4;
0635: x1 = (int) (xOffset + scaleX
0636: * (vpX + mr.ElementAt(0).intValue()));
0637: x2 = (int) (xOffset + scaleX
0638: * (vpX + mr.ElementAt(2).intValue()));
0639: x3 = (int) (xOffset + scaleX
0640: * (mr.ElementAt(4).intValue()));
0641: x4 = (int) (xOffset + scaleX
0642: * (mr.ElementAt(6).intValue()));
0643: y1 = (int) (yOffset + scaleY
0644: * (vpY + mr.ElementAt(1).intValue()));
0645: y2 = (int) (yOffset + scaleY
0646: * (vpY + mr.ElementAt(3).intValue()));
0647: y3 = (int) (yOffset + scaleY
0648: * (mr.ElementAt(5).intValue()));
0649: y4 = (int) (yOffset + scaleY
0650: * (mr.ElementAt(7).intValue()));
0651:
0652: int mx = x1 + (x2 - x1) / 2;
0653: int my = y1 + (y2 - y1) / 2;
0654: int startAngle = (int) Math.toDegrees(Math
0655: .atan2(-1.0 * (y3 - my),
0656: 1.0 * (x3 - mx)));
0657: int endAngle = (int) Math.toDegrees(Math.atan2(
0658: -1.0 * (y4 - my), 1.0 * (x4 - mx)));
0659: if (mr.functionId == 0x081A) {
0660: setBrushColor(g);
0661: if (brushObject >= 0)
0662: g.fillArc(x1, y1, x2 - x1, y2 - y1,
0663: startAngle, endAngle);
0664: }
0665:
0666: setPenColor(g);
0667: if (startAngle < 0)
0668: startAngle = 360 + startAngle;
0669: if (endAngle < 0)
0670: endAngle = 360 + endAngle;
0671: int len = Math.abs(endAngle - startAngle);
0672: if (endAngle < startAngle)
0673: len = 360 - startAngle + endAngle;
0674: if (penObject >= 0)
0675: g.drawArc(x1, y1, x2 - x1, y2 - y1,
0676: startAngle, len);
0677:
0678: }
0679: break;
0680:
0681: case 0x0830: //"CHORD", 0x0830,
0682: break;
0683:
0684: case 0x001E: //"SAVEDC", 0x001E,
0685: dcStack.push(new Integer(penWidth));
0686: dcStack.push(new Integer(startX));
0687: dcStack.push(new Integer(startY));
0688: dcStack.push(new Integer(brushObject));
0689: dcStack.push(new Integer(penObject));
0690: dcStack.push(new Integer(fontObject));
0691: dcStack.push(frgdColor);
0692: dcStack.push(bkgdColor);
0693: break;
0694:
0695: case 0x0127: //"RESTOREDC", 0x0127,
0696: bkgdColor = (Color) dcStack.pop();
0697: frgdColor = (Color) dcStack.pop();
0698: fontObject = ((Integer) (dcStack.pop()))
0699: .intValue();
0700: penObject = ((Integer) (dcStack.pop()))
0701: .intValue();
0702: brushObject = ((Integer) (dcStack.pop()))
0703: .intValue();
0704: startY = ((Integer) (dcStack.pop())).intValue();
0705: startX = ((Integer) (dcStack.pop())).intValue();
0706: penWidth = ((Integer) (dcStack.pop()))
0707: .intValue();
0708: break;
0709:
0710: case 0x1000: //"POLYBEZIER16",
0711: try {
0712: Graphics2D g2 = (Graphics2D) g;
0713: setPenColor(g);
0714:
0715: int pointCount = mr.ElementAt(0).intValue();
0716: int bezierCount = (pointCount - 1) / 3;
0717: float endX, endY;
0718: float cp1X, cp1Y;
0719: float cp2X, cp2Y;
0720: float _startX, _startY;
0721: _startX = (float) (xOffset + scaleX
0722: * (vpX + mr.ElementAt(1).intValue()));
0723: _startY = (float) (yOffset + scaleY
0724: * (vpY + mr.ElementAt(2).intValue()));
0725:
0726: GeneralPath gp = new GeneralPath(
0727: GeneralPath.WIND_NON_ZERO);
0728: gp.moveTo(_startX, _startY);
0729:
0730: for (int j = 0; j < bezierCount; j++) {
0731: cp1X = (float) (xOffset + scaleX
0732: * (vpX + mr
0733: .ElementAt(j * 6 + 3)
0734: .intValue()));
0735: cp1Y = (float) (yOffset + scaleY
0736: * (vpY + mr
0737: .ElementAt(j * 6 + 4)
0738: .intValue()));
0739:
0740: cp2X = (float) (xOffset + scaleX
0741: * (vpX + mr
0742: .ElementAt(j * 6 + 5)
0743: .intValue()));
0744: cp2Y = (float) (yOffset + scaleY
0745: * (vpY + mr
0746: .ElementAt(j * 6 + 6)
0747: .intValue()));
0748:
0749: endX = (float) (xOffset + scaleX
0750: * (vpX + mr
0751: .ElementAt(j * 6 + 7)
0752: .intValue()));
0753: endY = (float) (yOffset + scaleY
0754: * (vpY + mr
0755: .ElementAt(j * 6 + 8)
0756: .intValue()));
0757:
0758: gp.curveTo(cp1X, cp1Y, cp2X, cp2Y,
0759: endX, endY);
0760: _startX = endX;
0761: _startY = endY;
0762: }
0763: //gp.closePath();
0764: g2.setStroke(solid);
0765: g2.draw(gp);
0766: } catch (Exception e) {
0767: System.out
0768: .println("Unable to draw static text as a 2D graphics context is required");
0769: }
0770: break;
0771:
0772: case 0x0415: //"EXCLUDECLIPRECT", 0x0415,
0773: case 0x0416: //"INTERSECTCLIPRECT", 0x0416,
0774: break;
0775: case 0x0220: //"OFFSETCLIPRGN", 0x0220,
0776: case 0x012C: //"SELECTCLIPREGION", 0x012C,
0777: break;
0778:
0779: case 0x0102: //"SETBKMODE", 0x0102,
0780: bkMode = mr.ElementAt(0).intValue();
0781: break;
0782:
0783: case 0x0103: //"SETMAPMODE", 0x0103,
0784: case 0x0104: //"SETROP2", 0x0104,
0785: case 0x0105: //"SETRELABS", 0x0105,
0786: case 0x0107: //"SETSTRETCHBLTMODE", 0x0107,
0787: case 0x0108: //"SETTEXTCHAREXTRA", 0x0108,
0788: case 0x020A: //"SETTEXTJUSTIFICATION", 0x020A,
0789: case 0x0419: //"FLOODFILL", 0x0419,
0790: case 0x061D: //"PATBLT", 0x061D,
0791: case 0x041F: //"SETPIXEL", 0x041F,
0792: case 0x0922: //"BITBLT", 0x0922,
0793: case 0x0B23: //"STRETCHBLT", 0x0B23,
0794: case 0x0626: //"ESCAPE", 0x0626,
0795: case 0x0228: //"FILLREGION", 0x0228,
0796: case 0x0429: //"FRAMEREGION", 0x0429,
0797: case 0x012A: //"INVERTREGION", 0x012A,
0798: case 0x012B: //"PAINTREGION", 0x012B,
0799: case 0x012E: //"SETTEXTALIGN", 0x012E,
0800: case 0x0231: //"SETMAPPERFLAGS", 0x0231,
0801: case 0x0d33: //"SETDIBTODEV", 0x0d33,
0802: case 0x0940: //"DIBBITBLT", 0x0940,
0803: case 0x0b41: //"DIBSTRETCHBLT", 0x0b41,
0804: case 0x0f43: //"STRETCHDIB", 0x0f43,
0805: default: {
0806: //int count = sizeof( MetaFunctions ) / sizeof( EMFMETARECORDS );
0807: //for ( int i = 0; i < count; i++ ) {
0808: // if ( MetaFunctions[ i ].value == lpMFR->rdFunction ) {
0809: // os << MetaFunctions[ i ].szFuncName;
0810: // break;
0811: // }
0812: //}
0813: }
0814: //os << " ------Unknown Function------";
0815: break;
0816: }
0817: }
0818:
0819: }
0820: oldX = oldY = -1;
0821: }
0822: currentStore = null;
0823: }
0824:
0825: private void setPenColor(Graphics g) {
0826: if (penObject >= 0) {
0827: GdiObject gdiObj = currentStore.getObject(penObject);
0828: g.setColor((Color) gdiObj.obj);
0829: }
0830: }
0831:
0832: private void setBrushColor(Graphics g) {
0833: if (brushObject >= 0) {
0834: GdiObject gdiObj = currentStore.getObject(brushObject);
0835: g.setColor((Color) gdiObj.obj);
0836: }
0837: }
0838:
0839: /**
0840: * Wraps addUrl to allow the url to be set as a string
0841: * @param content the URL string
0842: */
0843: public void setContent(String content) {
0844: try {
0845: addUrl(XProjectManager.getResourceManager().getUrl(content));
0846: } catch (Exception ex) {
0847: ex.printStackTrace();
0848: }
0849: }
0850:
0851: /**
0852: * Adds a url and reads the corresponding file.
0853: */
0854: public void addUrl(java.net.URL newUrl) {
0855: try {
0856: bufStream = new BufferedInputStream(newUrl.openStream(),
0857: 30720);
0858: DataInputStream is = new DataInputStream(bufStream);
0859: RecordStore recordStore;
0860: if (newUrl.toString().indexOf(".wmf") != -1)
0861: recordStore = new WmfRecordStore();
0862: else
0863: recordStore = new RecordStore();
0864:
0865: recordStore.setUrl(newUrl);
0866: recordStore.read(is);
0867:
0868: stores.addElement(recordStore);
0869: } catch (IOException e) {
0870: e.printStackTrace();
0871: }
0872: }
0873:
0874: /**
0875: * Returns the current url.
0876: */
0877: public java.net.URL getUrl(int idx) {
0878: RecordStore aStore = (RecordStore) stores.elementAt(idx);
0879: return aStore.getUrl();
0880: }
0881:
0882: /**
0883: * Adds a url and reads the corresponding file.
0884: */
0885: public void addURL(String _url) {
0886: try {
0887: URL newUrl = new URL(_url);
0888: addUrl(newUrl);
0889: } catch (MalformedURLException ex1) {
0890: System.out.println("Malformed URL: " + ex1);
0891: } catch (IOException e) {
0892: e.printStackTrace();
0893: }
0894: }
0895:
0896: /**
0897: * Returns the current url.
0898: */
0899: public String getURL(int idx) {
0900: RecordStore aStore = (RecordStore) stores.elementAt(idx);
0901: return aStore.getUrl().toString();
0902: }
0903:
0904: /**
0905: * Returns the first url if any.
0906: */
0907: public String getURL() {
0908: RecordStore aStore = (RecordStore) stores.elementAt(0);
0909: return aStore.getUrl().toString();
0910: }
0911:
0912: private int addObject(int type, Object obj) {
0913: return currentStore.addObject(type, obj);
0914: }
0915:
0916: private int addObjectAt(int type, Object obj, int idx) {
0917: return currentStore.addObjectAt(type, obj, idx);
0918: }
0919:
0920: /**
0921: * Gets the relative mouse position within bounds of the image taking account
0922: * of zooming and panning.
0923: * @return the x position in the range 0 to 1000
0924: */
0925: public int getXPos() {
0926: double xOffset = xPan * getSize().width * zoom / 10000.0;
0927: XPos = (int) (100000.0 * (oldX - xOffset) / (zoom * getSize().width));
0928:
0929: return XPos;
0930: }
0931:
0932: /**
0933: * Gets the relative mouse position within bounds of the image taking account
0934: * of zooming and panning.
0935: * @return the y position in the range 0 to 1000
0936: */
0937: public int getYPos() {
0938: double yOffset = xPan * getSize().height * zoom / 10000.0;
0939: YPos = (int) (100000.0 * (oldY - yOffset) / (zoom * getSize().height));
0940:
0941: return YPos;
0942: }
0943:
0944: public void setXPos(int newXPos) {
0945: XPos = newXPos;
0946: }
0947:
0948: public void setYPos(int newYPos) {
0949: YPos = newYPos;
0950: }
0951:
0952: /**
0953: ** This method must be called by derived classes at the end of their paint method.
0954: * @param x the mouse x position.
0955: * @param y the mouse y position.
0956: */
0957: public void drawCrossHairs(Graphics g, int x, int y) {
0958: if (drawCrossHairs) {
0959: int w = getSize().width;
0960: int h = getSize().height;
0961:
0962: g.setXORMode(Color.red);
0963: g.setColor(Color.blue);
0964: g.drawLine(0, oldY, w, oldY);
0965: g.drawLine(0, y, w, y);
0966: g.drawLine(oldX, 0, oldX, h);
0967: g.drawLine(x, 0, x, h);
0968: }
0969: }
0970:
0971: /**
0972: * Pans the image by the specified percentages, withing the range -80 to 20.
0973: * This ensures that a portion of the image is always visible
0974: * @param xPercent the amount by which to pan as a percent of the image width.
0975: * @param yPercent the amount by which to pan as a percent of the image height.
0976: */
0977: public void pan(int xPercent, int yPercent) {
0978: if (xPercent > 20)
0979: xPan = 20;
0980: else if (xPercent < -80)
0981: xPan = -80;
0982: else
0983: xPan = xPercent;
0984:
0985: if (yPercent > 20)
0986: yPan = 20;
0987: else if (yPercent < -80)
0988: yPan = -80;
0989: else
0990: yPan = yPercent;
0991: }
0992:
0993: /**
0994: * Zooms in or out on the image within the range of 25 to 400 percent of the
0995: * original image size.
0996: * @param percent the new size of the image as a percentage of the original size.
0997: */
0998: public void zoom(int percent) {
0999: if (percent > 400)
1000: zoom = 400;
1001: else if (percent < 25)
1002: zoom = 25;
1003: else
1004: zoom = percent;
1005: }
1006:
1007: void writeObject(java.io.ObjectOutputStream oos) throws IOException {
1008: oos.writeObject(new Boolean(drawCrossHairs).toString());
1009: int size = stores.size();
1010: oos.writeObject(new Integer(size));
1011: for (int i = 0; i < size; i++)
1012: oos.writeObject(((RecordStore) stores.elementAt(i))
1013: .getUrl());
1014: }
1015:
1016: void readObject(java.io.ObjectInputStream ois)
1017: throws ClassNotFoundException, IOException {
1018: drawCrossHairs = new Boolean((String) ois.readObject())
1019: .booleanValue();
1020:
1021: int size = ((Integer) ois.readObject()).intValue();
1022: for (int i = 0; i < size; i++)
1023: addURL((String) ois.readObject());
1024: }
1025:
1026: /**
1027: * @serial flag indicating the use of crosshairs
1028: */
1029: private boolean drawCrossHairs = false;
1030:
1031: transient private int numRecords;
1032: transient private int numObjects;
1033: transient private int lastObjectIdx;
1034: transient private int vpX, vpY, vpW, vpH;
1035: transient private Stack dcStack;
1036:
1037: transient private Vector stores;
1038: transient private RecordStore currentStore;
1039:
1040: // Objects on DC stack;
1041: transient private int fontHeight = 10;
1042: transient private int fontAngle = 0;
1043: transient private int penWidth = 0;
1044: transient private int startX = 0;
1045: transient private int startY = 0;
1046: transient private int brushObject = -1;
1047: transient private int penObject = -1;
1048: transient private int fontObject = -1;
1049: transient private Color frgdColor;
1050: transient private Color bkgdColor;
1051: transient private int oldX;
1052: transient private int oldY;
1053: transient private int XPos = 0;
1054: transient private int YPos = 0;
1055: transient private int xPan;
1056: transient private int yPan;
1057: transient private int zoom;
1058: transient private Font font;
1059: transient private int bkMode;
1060:
1061: public static final int PEN = 1;
1062: public static final int BRUSH = 2;
1063: public static final int FONT = 3;
1064: public static final int NULL_PEN = 4;
1065: public static final int NULL_BRUSH = 5;
1066: public static final int PALETTE = 6;
1067:
1068: transient private boolean bReadingWMF = true;
1069: transient private BufferedInputStream bufStream = null;
1070:
1071: transient private BorderLayout borderLayout = new BorderLayout();
1072: }
1073:
1074: class MetaRecord /*implements Serializable*/
1075: {
1076: public int functionId;
1077: public int numPoints;
1078:
1079: private Vector ptVector;
1080:
1081: public MetaRecord() {
1082: ptVector = new Vector();
1083: }
1084:
1085: public void EnsureCapacity(int cc) {
1086: ptVector.ensureCapacity(cc);
1087: }
1088:
1089: public void AddElement(Object obj) {
1090: ptVector.addElement(obj);
1091: }
1092:
1093: public Integer ElementAt(int offset) {
1094: return (Integer) ptVector.elementAt(offset);
1095: }
1096: }
1097:
1098: class StringRecord extends MetaRecord /*implements Serializable*/
1099: {
1100: public String text;
1101:
1102: public StringRecord(String newText) {
1103: text = new String(newText);
1104: }
1105: }
1106:
1107: class GdiObject /*implements Serializable*/
1108: {
1109: GdiObject(int _id, boolean _used) {
1110: id = _id;
1111: used = _used;
1112: type = 0;
1113: }
1114:
1115: public void Clear() {
1116: used = false;
1117: type = 0;
1118: }
1119:
1120: public void Setup(int _type, Object _obj) {
1121: obj = _obj;
1122: type = _type;
1123: used = true;
1124: }
1125:
1126: int id;
1127: boolean used;
1128: Object obj;
1129: int type = 0;
1130: }
|