001: /*
002: * $Id: MetaDo.java 2752 2007-05-15 14:58:33Z blowagie $
003: * $Name$
004: *
005: * Copyright 2001, 2002 Paulo Soares
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.pdf.codec.wmf;
052:
053: import java.awt.Color;
054: import java.awt.Point;
055: import java.io.ByteArrayInputStream;
056: import java.io.ByteArrayOutputStream;
057: import java.io.IOException;
058: import java.io.InputStream;
059: import java.io.OutputStream;
060: import java.io.UnsupportedEncodingException;
061: import java.util.ArrayList;
062:
063: import com.lowagie.text.DocumentException;
064: import com.lowagie.text.Image;
065: import com.lowagie.text.pdf.BaseFont;
066: import com.lowagie.text.pdf.PdfContentByte;
067: import com.lowagie.text.pdf.codec.BmpImage;
068:
069: public class MetaDo {
070:
071: public static final int META_SETBKCOLOR = 0x0201;
072: public static final int META_SETBKMODE = 0x0102;
073: public static final int META_SETMAPMODE = 0x0103;
074: public static final int META_SETROP2 = 0x0104;
075: public static final int META_SETRELABS = 0x0105;
076: public static final int META_SETPOLYFILLMODE = 0x0106;
077: public static final int META_SETSTRETCHBLTMODE = 0x0107;
078: public static final int META_SETTEXTCHAREXTRA = 0x0108;
079: public static final int META_SETTEXTCOLOR = 0x0209;
080: public static final int META_SETTEXTJUSTIFICATION = 0x020A;
081: public static final int META_SETWINDOWORG = 0x020B;
082: public static final int META_SETWINDOWEXT = 0x020C;
083: public static final int META_SETVIEWPORTORG = 0x020D;
084: public static final int META_SETVIEWPORTEXT = 0x020E;
085: public static final int META_OFFSETWINDOWORG = 0x020F;
086: public static final int META_SCALEWINDOWEXT = 0x0410;
087: public static final int META_OFFSETVIEWPORTORG = 0x0211;
088: public static final int META_SCALEVIEWPORTEXT = 0x0412;
089: public static final int META_LINETO = 0x0213;
090: public static final int META_MOVETO = 0x0214;
091: public static final int META_EXCLUDECLIPRECT = 0x0415;
092: public static final int META_INTERSECTCLIPRECT = 0x0416;
093: public static final int META_ARC = 0x0817;
094: public static final int META_ELLIPSE = 0x0418;
095: public static final int META_FLOODFILL = 0x0419;
096: public static final int META_PIE = 0x081A;
097: public static final int META_RECTANGLE = 0x041B;
098: public static final int META_ROUNDRECT = 0x061C;
099: public static final int META_PATBLT = 0x061D;
100: public static final int META_SAVEDC = 0x001E;
101: public static final int META_SETPIXEL = 0x041F;
102: public static final int META_OFFSETCLIPRGN = 0x0220;
103: public static final int META_TEXTOUT = 0x0521;
104: public static final int META_BITBLT = 0x0922;
105: public static final int META_STRETCHBLT = 0x0B23;
106: public static final int META_POLYGON = 0x0324;
107: public static final int META_POLYLINE = 0x0325;
108: public static final int META_ESCAPE = 0x0626;
109: public static final int META_RESTOREDC = 0x0127;
110: public static final int META_FILLREGION = 0x0228;
111: public static final int META_FRAMEREGION = 0x0429;
112: public static final int META_INVERTREGION = 0x012A;
113: public static final int META_PAINTREGION = 0x012B;
114: public static final int META_SELECTCLIPREGION = 0x012C;
115: public static final int META_SELECTOBJECT = 0x012D;
116: public static final int META_SETTEXTALIGN = 0x012E;
117: public static final int META_CHORD = 0x0830;
118: public static final int META_SETMAPPERFLAGS = 0x0231;
119: public static final int META_EXTTEXTOUT = 0x0a32;
120: public static final int META_SETDIBTODEV = 0x0d33;
121: public static final int META_SELECTPALETTE = 0x0234;
122: public static final int META_REALIZEPALETTE = 0x0035;
123: public static final int META_ANIMATEPALETTE = 0x0436;
124: public static final int META_SETPALENTRIES = 0x0037;
125: public static final int META_POLYPOLYGON = 0x0538;
126: public static final int META_RESIZEPALETTE = 0x0139;
127: public static final int META_DIBBITBLT = 0x0940;
128: public static final int META_DIBSTRETCHBLT = 0x0b41;
129: public static final int META_DIBCREATEPATTERNBRUSH = 0x0142;
130: public static final int META_STRETCHDIB = 0x0f43;
131: public static final int META_EXTFLOODFILL = 0x0548;
132: public static final int META_DELETEOBJECT = 0x01f0;
133: public static final int META_CREATEPALETTE = 0x00f7;
134: public static final int META_CREATEPATTERNBRUSH = 0x01F9;
135: public static final int META_CREATEPENINDIRECT = 0x02FA;
136: public static final int META_CREATEFONTINDIRECT = 0x02FB;
137: public static final int META_CREATEBRUSHINDIRECT = 0x02FC;
138: public static final int META_CREATEREGION = 0x06FF;
139:
140: public PdfContentByte cb;
141: public InputMeta in;
142: int left;
143: int top;
144: int right;
145: int bottom;
146: int inch;
147: MetaState state = new MetaState();
148:
149: public MetaDo(InputStream in, PdfContentByte cb) {
150: this .cb = cb;
151: this .in = new InputMeta(in);
152: }
153:
154: public void readAll() throws IOException, DocumentException {
155: if (in.readInt() != 0x9AC6CDD7) {
156: throw new DocumentException(
157: "Not a placeable windows metafile");
158: }
159: in.readWord();
160: left = in.readShort();
161: top = in.readShort();
162: right = in.readShort();
163: bottom = in.readShort();
164: inch = in.readWord();
165: state.setScalingX((float) (right - left) / (float) inch * 72f);
166: state.setScalingY((float) (bottom - top) / (float) inch * 72f);
167: state.setOffsetWx(left);
168: state.setOffsetWy(top);
169: state.setExtentWx(right - left);
170: state.setExtentWy(bottom - top);
171: in.readInt();
172: in.readWord();
173: in.skip(18);
174:
175: int tsize;
176: int function;
177: cb.setLineCap(1);
178: cb.setLineJoin(1);
179: for (;;) {
180: int lenMarker = in.getLength();
181: tsize = in.readInt();
182: if (tsize < 3)
183: break;
184: function = in.readWord();
185: switch (function) {
186: case 0:
187: break;
188: case META_CREATEPALETTE:
189: case META_CREATEREGION:
190: case META_DIBCREATEPATTERNBRUSH:
191: state.addMetaObject(new MetaObject());
192: break;
193: case META_CREATEPENINDIRECT: {
194: MetaPen pen = new MetaPen();
195: pen.init(in);
196: state.addMetaObject(pen);
197: break;
198: }
199: case META_CREATEBRUSHINDIRECT: {
200: MetaBrush brush = new MetaBrush();
201: brush.init(in);
202: state.addMetaObject(brush);
203: break;
204: }
205: case META_CREATEFONTINDIRECT: {
206: MetaFont font = new MetaFont();
207: font.init(in);
208: state.addMetaObject(font);
209: break;
210: }
211: case META_SELECTOBJECT: {
212: int idx = in.readWord();
213: state.selectMetaObject(idx, cb);
214: break;
215: }
216: case META_DELETEOBJECT: {
217: int idx = in.readWord();
218: state.deleteMetaObject(idx);
219: break;
220: }
221: case META_SAVEDC:
222: state.saveState(cb);
223: break;
224: case META_RESTOREDC: {
225: int idx = in.readShort();
226: state.restoreState(idx, cb);
227: break;
228: }
229: case META_SETWINDOWORG:
230: state.setOffsetWy(in.readShort());
231: state.setOffsetWx(in.readShort());
232: break;
233: case META_SETWINDOWEXT:
234: state.setExtentWy(in.readShort());
235: state.setExtentWx(in.readShort());
236: break;
237: case META_MOVETO: {
238: int y = in.readShort();
239: Point p = new Point(in.readShort(), y);
240: state.setCurrentPoint(p);
241: break;
242: }
243: case META_LINETO: {
244: int y = in.readShort();
245: int x = in.readShort();
246: Point p = state.getCurrentPoint();
247: cb.moveTo(state.transformX(p.x), state.transformY(p.y));
248: cb.lineTo(state.transformX(x), state.transformY(y));
249: cb.stroke();
250: state.setCurrentPoint(new Point(x, y));
251: break;
252: }
253: case META_POLYLINE: {
254: state.setLineJoinPolygon(cb);
255: int len = in.readWord();
256: int x = in.readShort();
257: int y = in.readShort();
258: cb.moveTo(state.transformX(x), state.transformY(y));
259: for (int k = 1; k < len; ++k) {
260: x = in.readShort();
261: y = in.readShort();
262: cb.lineTo(state.transformX(x), state.transformY(y));
263: }
264: cb.stroke();
265: break;
266: }
267: case META_POLYGON: {
268: if (isNullStrokeFill(false))
269: break;
270: int len = in.readWord();
271: int sx = in.readShort();
272: int sy = in.readShort();
273: cb.moveTo(state.transformX(sx), state.transformY(sy));
274: for (int k = 1; k < len; ++k) {
275: int x = in.readShort();
276: int y = in.readShort();
277: cb.lineTo(state.transformX(x), state.transformY(y));
278: }
279: cb.lineTo(state.transformX(sx), state.transformY(sy));
280: strokeAndFill();
281: break;
282: }
283: case META_POLYPOLYGON: {
284: if (isNullStrokeFill(false))
285: break;
286: int numPoly = in.readWord();
287: int lens[] = new int[numPoly];
288: for (int k = 0; k < lens.length; ++k)
289: lens[k] = in.readWord();
290: for (int j = 0; j < lens.length; ++j) {
291: int len = lens[j];
292: int sx = in.readShort();
293: int sy = in.readShort();
294: cb.moveTo(state.transformX(sx), state
295: .transformY(sy));
296: for (int k = 1; k < len; ++k) {
297: int x = in.readShort();
298: int y = in.readShort();
299: cb.lineTo(state.transformX(x), state
300: .transformY(y));
301: }
302: cb.lineTo(state.transformX(sx), state
303: .transformY(sy));
304: }
305: strokeAndFill();
306: break;
307: }
308: case META_ELLIPSE: {
309: if (isNullStrokeFill(state.getLineNeutral()))
310: break;
311: int b = in.readShort();
312: int r = in.readShort();
313: int t = in.readShort();
314: int l = in.readShort();
315: cb.arc(state.transformX(l), state.transformY(b), state
316: .transformX(r), state.transformY(t), 0, 360);
317: strokeAndFill();
318: break;
319: }
320: case META_ARC: {
321: if (isNullStrokeFill(state.getLineNeutral()))
322: break;
323: float yend = state.transformY(in.readShort());
324: float xend = state.transformX(in.readShort());
325: float ystart = state.transformY(in.readShort());
326: float xstart = state.transformX(in.readShort());
327: float b = state.transformY(in.readShort());
328: float r = state.transformX(in.readShort());
329: float t = state.transformY(in.readShort());
330: float l = state.transformX(in.readShort());
331: float cx = (r + l) / 2;
332: float cy = (t + b) / 2;
333: float arc1 = getArc(cx, cy, xstart, ystart);
334: float arc2 = getArc(cx, cy, xend, yend);
335: arc2 -= arc1;
336: if (arc2 <= 0)
337: arc2 += 360;
338: cb.arc(l, b, r, t, arc1, arc2);
339: cb.stroke();
340: break;
341: }
342: case META_PIE: {
343: if (isNullStrokeFill(state.getLineNeutral()))
344: break;
345: float yend = state.transformY(in.readShort());
346: float xend = state.transformX(in.readShort());
347: float ystart = state.transformY(in.readShort());
348: float xstart = state.transformX(in.readShort());
349: float b = state.transformY(in.readShort());
350: float r = state.transformX(in.readShort());
351: float t = state.transformY(in.readShort());
352: float l = state.transformX(in.readShort());
353: float cx = (r + l) / 2;
354: float cy = (t + b) / 2;
355: float arc1 = getArc(cx, cy, xstart, ystart);
356: float arc2 = getArc(cx, cy, xend, yend);
357: arc2 -= arc1;
358: if (arc2 <= 0)
359: arc2 += 360;
360: ArrayList ar = PdfContentByte.bezierArc(l, b, r, t,
361: arc1, arc2);
362: if (ar.isEmpty())
363: break;
364: float pt[] = (float[]) ar.get(0);
365: cb.moveTo(cx, cy);
366: cb.lineTo(pt[0], pt[1]);
367: for (int k = 0; k < ar.size(); ++k) {
368: pt = (float[]) ar.get(k);
369: cb
370: .curveTo(pt[2], pt[3], pt[4], pt[5], pt[6],
371: pt[7]);
372: }
373: cb.lineTo(cx, cy);
374: strokeAndFill();
375: break;
376: }
377: case META_CHORD: {
378: if (isNullStrokeFill(state.getLineNeutral()))
379: break;
380: float yend = state.transformY(in.readShort());
381: float xend = state.transformX(in.readShort());
382: float ystart = state.transformY(in.readShort());
383: float xstart = state.transformX(in.readShort());
384: float b = state.transformY(in.readShort());
385: float r = state.transformX(in.readShort());
386: float t = state.transformY(in.readShort());
387: float l = state.transformX(in.readShort());
388: float cx = (r + l) / 2;
389: float cy = (t + b) / 2;
390: float arc1 = getArc(cx, cy, xstart, ystart);
391: float arc2 = getArc(cx, cy, xend, yend);
392: arc2 -= arc1;
393: if (arc2 <= 0)
394: arc2 += 360;
395: ArrayList ar = PdfContentByte.bezierArc(l, b, r, t,
396: arc1, arc2);
397: if (ar.isEmpty())
398: break;
399: float pt[] = (float[]) ar.get(0);
400: cx = pt[0];
401: cy = pt[1];
402: cb.moveTo(cx, cy);
403: for (int k = 0; k < ar.size(); ++k) {
404: pt = (float[]) ar.get(k);
405: cb
406: .curveTo(pt[2], pt[3], pt[4], pt[5], pt[6],
407: pt[7]);
408: }
409: cb.lineTo(cx, cy);
410: strokeAndFill();
411: break;
412: }
413: case META_RECTANGLE: {
414: if (isNullStrokeFill(true))
415: break;
416: float b = state.transformY(in.readShort());
417: float r = state.transformX(in.readShort());
418: float t = state.transformY(in.readShort());
419: float l = state.transformX(in.readShort());
420: cb.rectangle(l, b, r - l, t - b);
421: strokeAndFill();
422: break;
423: }
424: case META_ROUNDRECT: {
425: if (isNullStrokeFill(true))
426: break;
427: float h = state.transformY(0)
428: - state.transformY(in.readShort());
429: float w = state.transformX(in.readShort())
430: - state.transformX(0);
431: float b = state.transformY(in.readShort());
432: float r = state.transformX(in.readShort());
433: float t = state.transformY(in.readShort());
434: float l = state.transformX(in.readShort());
435: cb.roundRectangle(l, b, r - l, t - b, (h + w) / 4);
436: strokeAndFill();
437: break;
438: }
439: case META_INTERSECTCLIPRECT: {
440: float b = state.transformY(in.readShort());
441: float r = state.transformX(in.readShort());
442: float t = state.transformY(in.readShort());
443: float l = state.transformX(in.readShort());
444: cb.rectangle(l, b, r - l, t - b);
445: cb.eoClip();
446: cb.newPath();
447: break;
448: }
449: case META_EXTTEXTOUT: {
450: int y = in.readShort();
451: int x = in.readShort();
452: int count = in.readWord();
453: int flag = in.readWord();
454: int x1 = 0;
455: int y1 = 0;
456: int x2 = 0;
457: int y2 = 0;
458: if ((flag & (MetaFont.ETO_CLIPPED | MetaFont.ETO_OPAQUE)) != 0) {
459: x1 = in.readShort();
460: y1 = in.readShort();
461: x2 = in.readShort();
462: y2 = in.readShort();
463: }
464: byte text[] = new byte[count];
465: int k;
466: for (k = 0; k < count; ++k) {
467: byte c = (byte) in.readByte();
468: if (c == 0)
469: break;
470: text[k] = c;
471: }
472: String s;
473: try {
474: s = new String(text, 0, k, "Cp1252");
475: } catch (UnsupportedEncodingException e) {
476: s = new String(text, 0, k);
477: }
478: outputText(x, y, flag, x1, y1, x2, y2, s);
479: break;
480: }
481: case META_TEXTOUT: {
482: int count = in.readWord();
483: byte text[] = new byte[count];
484: int k;
485: for (k = 0; k < count; ++k) {
486: byte c = (byte) in.readByte();
487: if (c == 0)
488: break;
489: text[k] = c;
490: }
491: String s;
492: try {
493: s = new String(text, 0, k, "Cp1252");
494: } catch (UnsupportedEncodingException e) {
495: s = new String(text, 0, k);
496: }
497: count = (count + 1) & 0xfffe;
498: in.skip(count - k);
499: int y = in.readShort();
500: int x = in.readShort();
501: outputText(x, y, 0, 0, 0, 0, 0, s);
502: break;
503: }
504: case META_SETBKCOLOR:
505: state.setCurrentBackgroundColor(in.readColor());
506: break;
507: case META_SETTEXTCOLOR:
508: state.setCurrentTextColor(in.readColor());
509: break;
510: case META_SETTEXTALIGN:
511: state.setTextAlign(in.readWord());
512: break;
513: case META_SETBKMODE:
514: state.setBackgroundMode(in.readWord());
515: break;
516: case META_SETPOLYFILLMODE:
517: state.setPolyFillMode(in.readWord());
518: break;
519: case META_SETPIXEL: {
520: Color color = in.readColor();
521: int y = in.readShort();
522: int x = in.readShort();
523: cb.saveState();
524: cb.setColorFill(color);
525: cb.rectangle(state.transformX(x), state.transformY(y),
526: .2f, .2f);
527: cb.fill();
528: cb.restoreState();
529: break;
530: }
531: case META_DIBSTRETCHBLT:
532: case META_STRETCHDIB: {
533: int rop = in.readInt();
534: if (function == META_STRETCHDIB) {
535: /*int usage = */in.readWord();
536: }
537: int srcHeight = in.readShort();
538: int srcWidth = in.readShort();
539: int ySrc = in.readShort();
540: int xSrc = in.readShort();
541: float destHeight = state.transformY(in.readShort())
542: - state.transformY(0);
543: float destWidth = state.transformX(in.readShort())
544: - state.transformX(0);
545: float yDest = state.transformY(in.readShort());
546: float xDest = state.transformX(in.readShort());
547: byte b[] = new byte[(tsize * 2)
548: - (in.getLength() - lenMarker)];
549: for (int k = 0; k < b.length; ++k)
550: b[k] = (byte) in.readByte();
551: try {
552: ByteArrayInputStream inb = new ByteArrayInputStream(
553: b);
554: Image bmp = BmpImage.getImage(inb, true, b.length);
555: cb.saveState();
556: cb.rectangle(xDest, yDest, destWidth, destHeight);
557: cb.clip();
558: cb.newPath();
559: bmp.scaleAbsolute(destWidth * bmp.getWidth()
560: / srcWidth, -destHeight * bmp.getHeight()
561: / srcHeight);
562: bmp.setAbsolutePosition(xDest - destWidth * xSrc
563: / srcWidth, yDest + destHeight * ySrc
564: / srcHeight - bmp.getScaledHeight());
565: cb.addImage(bmp);
566: cb.restoreState();
567: } catch (Exception e) {
568: // empty on purpose
569: }
570: break;
571: }
572: }
573: in.skip((tsize * 2) - (in.getLength() - lenMarker));
574: }
575: state.cleanup(cb);
576: }
577:
578: public void outputText(int x, int y, int flag, int x1, int y1,
579: int x2, int y2, String text) {
580: MetaFont font = state.getCurrentFont();
581: float refX = state.transformX(x);
582: float refY = state.transformY(y);
583: float angle = state.transformAngle(font.getAngle());
584: float sin = (float) Math.sin(angle);
585: float cos = (float) Math.cos(angle);
586: float fontSize = font.getFontSize(state);
587: BaseFont bf = font.getFont();
588: int align = state.getTextAlign();
589: float textWidth = bf.getWidthPoint(text, fontSize);
590: float tx = 0;
591: float ty = 0;
592: float descender = bf.getFontDescriptor(BaseFont.DESCENT,
593: fontSize);
594: float ury = bf.getFontDescriptor(BaseFont.BBOXURY, fontSize);
595: cb.saveState();
596: cb.concatCTM(cos, sin, -sin, cos, refX, refY);
597: if ((align & MetaState.TA_CENTER) == MetaState.TA_CENTER)
598: tx = -textWidth / 2;
599: else if ((align & MetaState.TA_RIGHT) == MetaState.TA_RIGHT)
600: tx = -textWidth;
601: if ((align & MetaState.TA_BASELINE) == MetaState.TA_BASELINE)
602: ty = 0;
603: else if ((align & MetaState.TA_BOTTOM) == MetaState.TA_BOTTOM)
604: ty = -descender;
605: else
606: ty = -ury;
607: Color textColor;
608: if (state.getBackgroundMode() == MetaState.OPAQUE) {
609: textColor = state.getCurrentBackgroundColor();
610: cb.setColorFill(textColor);
611: cb
612: .rectangle(tx, ty + descender, textWidth, ury
613: - descender);
614: cb.fill();
615: }
616: textColor = state.getCurrentTextColor();
617: cb.setColorFill(textColor);
618: cb.beginText();
619: cb.setFontAndSize(bf, fontSize);
620: cb.setTextMatrix(tx, ty);
621: cb.showText(text);
622: cb.endText();
623: if (font.isUnderline()) {
624: cb.rectangle(tx, ty - fontSize / 4, textWidth,
625: fontSize / 15);
626: cb.fill();
627: }
628: if (font.isStrikeout()) {
629: cb.rectangle(tx, ty + fontSize / 3, textWidth,
630: fontSize / 15);
631: cb.fill();
632: }
633: cb.restoreState();
634: }
635:
636: public boolean isNullStrokeFill(boolean isRectangle) {
637: MetaPen pen = state.getCurrentPen();
638: MetaBrush brush = state.getCurrentBrush();
639: boolean noPen = (pen.getStyle() == MetaPen.PS_NULL);
640: int style = brush.getStyle();
641: boolean isBrush = (style == MetaBrush.BS_SOLID || (style == MetaBrush.BS_HATCHED && state
642: .getBackgroundMode() == MetaState.OPAQUE));
643: boolean result = noPen && !isBrush;
644: if (!noPen) {
645: if (isRectangle)
646: state.setLineJoinRectangle(cb);
647: else
648: state.setLineJoinPolygon(cb);
649: }
650: return result;
651: }
652:
653: public void strokeAndFill() {
654: MetaPen pen = state.getCurrentPen();
655: MetaBrush brush = state.getCurrentBrush();
656: int penStyle = pen.getStyle();
657: int brushStyle = brush.getStyle();
658: if (penStyle == MetaPen.PS_NULL) {
659: cb.closePath();
660: if (state.getPolyFillMode() == MetaState.ALTERNATE) {
661: cb.eoFill();
662: } else {
663: cb.fill();
664: }
665: } else {
666: boolean isBrush = (brushStyle == MetaBrush.BS_SOLID || (brushStyle == MetaBrush.BS_HATCHED && state
667: .getBackgroundMode() == MetaState.OPAQUE));
668: if (isBrush) {
669: if (state.getPolyFillMode() == MetaState.ALTERNATE)
670: cb.closePathEoFillStroke();
671: else
672: cb.closePathFillStroke();
673: } else {
674: cb.closePathStroke();
675: }
676: }
677: }
678:
679: static float getArc(float xCenter, float yCenter, float xDot,
680: float yDot) {
681: double s = Math.atan2(yDot - yCenter, xDot - xCenter);
682: if (s < 0)
683: s += Math.PI * 2;
684: return (float) (s / Math.PI * 180);
685: }
686:
687: public static byte[] wrapBMP(Image image) throws IOException {
688: if (image.getOriginalType() != Image.ORIGINAL_BMP)
689: throw new IOException("Only BMP can be wrapped in WMF.");
690: InputStream imgIn;
691: byte data[] = null;
692: if (image.getOriginalData() == null) {
693: imgIn = image.getUrl().openStream();
694: ByteArrayOutputStream out = new ByteArrayOutputStream();
695: int b = 0;
696: while ((b = imgIn.read()) != -1)
697: out.write(b);
698: imgIn.close();
699: data = out.toByteArray();
700: } else
701: data = image.getOriginalData();
702: int sizeBmpWords = (data.length - 14 + 1) >>> 1;
703: ByteArrayOutputStream os = new ByteArrayOutputStream();
704: // write metafile header
705: writeWord(os, 1);
706: writeWord(os, 9);
707: writeWord(os, 0x0300);
708: writeDWord(os, 9 + 4 + 5 + 5 + (13 + sizeBmpWords) + 3); // total metafile size
709: writeWord(os, 1);
710: writeDWord(os, 14 + sizeBmpWords); // max record size
711: writeWord(os, 0);
712: // write records
713: writeDWord(os, 4);
714: writeWord(os, META_SETMAPMODE);
715: writeWord(os, 8);
716:
717: writeDWord(os, 5);
718: writeWord(os, META_SETWINDOWORG);
719: writeWord(os, 0);
720: writeWord(os, 0);
721:
722: writeDWord(os, 5);
723: writeWord(os, META_SETWINDOWEXT);
724: writeWord(os, (int) image.getHeight());
725: writeWord(os, (int) image.getWidth());
726:
727: writeDWord(os, 13 + sizeBmpWords);
728: writeWord(os, META_DIBSTRETCHBLT);
729: writeDWord(os, 0x00cc0020);
730: writeWord(os, (int) image.getHeight());
731: writeWord(os, (int) image.getWidth());
732: writeWord(os, 0);
733: writeWord(os, 0);
734: writeWord(os, (int) image.getHeight());
735: writeWord(os, (int) image.getWidth());
736: writeWord(os, 0);
737: writeWord(os, 0);
738: os.write(data, 14, data.length - 14);
739: if ((data.length & 1) == 1)
740: os.write(0);
741: // writeDWord(os, 14 + sizeBmpWords);
742: // writeWord(os, META_STRETCHDIB);
743: // writeDWord(os, 0x00cc0020);
744: // writeWord(os, 0);
745: // writeWord(os, (int)image.height());
746: // writeWord(os, (int)image.width());
747: // writeWord(os, 0);
748: // writeWord(os, 0);
749: // writeWord(os, (int)image.height());
750: // writeWord(os, (int)image.width());
751: // writeWord(os, 0);
752: // writeWord(os, 0);
753: // os.write(data, 14, data.length - 14);
754: // if ((data.length & 1) == 1)
755: // os.write(0);
756:
757: writeDWord(os, 3);
758: writeWord(os, 0);
759: os.close();
760: return os.toByteArray();
761: }
762:
763: public static void writeWord(OutputStream os, int v)
764: throws IOException {
765: os.write(v & 0xff);
766: os.write((v >>> 8) & 0xff);
767: }
768:
769: public static void writeDWord(OutputStream os, int v)
770: throws IOException {
771: writeWord(os, v & 0xffff);
772: writeWord(os, (v >>> 16) & 0xffff);
773: }
774: }
|