001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019:
020: package org.apache.batik.transcoder.wmf.tosvg;
021:
022: import java.awt.Color;
023: import java.awt.Font;
024: import java.awt.Rectangle;
025: import java.awt.Shape;
026: import java.awt.font.FontRenderContext;
027: import java.awt.font.TextLayout;
028: import java.awt.geom.AffineTransform;
029: import java.awt.geom.Rectangle2D;
030: import java.io.BufferedInputStream;
031: import java.io.DataInputStream;
032: import java.io.File;
033: import java.io.FileInputStream;
034: import java.io.IOException;
035:
036: import org.apache.batik.ext.awt.geom.Polygon2D;
037: import org.apache.batik.ext.awt.geom.Polyline2D;
038: import org.apache.batik.transcoder.wmf.WMFConstants;
039:
040: /**
041: * This class holds simple properties about a WMF Metafile. It can be used
042: * whenever general information must be retrieved about this file.
043: *
044: * @version $Id: WMFHeaderProperties.java 501495 2007-01-30 18:00:36Z dvholten $
045: */
046: public class WMFHeaderProperties extends AbstractWMFReader {
047:
048: private static final Integer INTEGER_0 = new Integer(0);
049:
050: protected DataInputStream stream;
051: private int _bleft, _bright, _btop, _bbottom, _bwidth, _bheight;
052: private int _ileft, _iright, _itop, _ibottom;
053: private float scale = 1.0f;
054: private int startX = 0;
055: private int startY = 0;
056: private int currentHorizAlign = 0;
057: private int currentVertAlign = 0;
058: private WMFFont wf = null;
059: private static final FontRenderContext fontCtx = new FontRenderContext(
060: new AffineTransform(), false, true);
061: private transient boolean firstEffectivePaint = true;
062: public static final int PEN = 1;
063: public static final int BRUSH = 2;
064: public static final int FONT = 3;
065: public static final int NULL_PEN = 4;
066: public static final int NULL_BRUSH = 5;
067: public static final int PALETTE = 6;
068: public static final int OBJ_BITMAP = 7;
069: public static final int OBJ_REGION = 8;
070:
071: /** Creates a new WMFHeaderProperties, and sets the associated WMF File.
072: * @param wmffile the WMF Metafile
073: */
074: public WMFHeaderProperties(File wmffile) throws IOException {
075: super ();
076: reset();
077: stream = new DataInputStream(new BufferedInputStream(
078: new FileInputStream(wmffile)));
079: read(stream);
080: stream.close();
081: }
082:
083: /** Creates a new WMFHeaderProperties, with no associated file.
084: */
085: public WMFHeaderProperties() {
086: super ();
087: }
088:
089: public void closeResource() {
090: try {
091: if (stream != null)
092: stream.close();
093: } catch (IOException e) {
094: }
095: }
096:
097: /** Creates the properties associated file.
098: */
099: public void setFile(File wmffile) throws IOException {
100: stream = new DataInputStream(new BufferedInputStream(
101: new FileInputStream(wmffile)));
102: read(stream);
103: stream.close();
104: }
105:
106: /**
107: * Resets the internal storage and viewport coordinates.
108: */
109: public void reset() {
110: left = 0;
111: right = 0;
112: top = 1000;
113: bottom = 1000;
114: inch = 100;
115: _bleft = -1;
116: _bright = -1;
117: _btop = -1;
118: _bbottom = -1;
119: _ileft = -1;
120: _iright = -1;
121: _itop = -1;
122: _ibottom = -1;
123: _bwidth = -1;
124: _bheight = -1;
125: vpW = -1;
126: vpH = -1;
127: vpX = 0;
128: vpY = 0;
129: startX = 0;
130: startY = 0;
131: firstEffectivePaint = true;
132: }
133:
134: /** Get the associated stream.
135: */
136: public DataInputStream getStream() {
137: return stream;
138: }
139:
140: protected boolean readRecords(DataInputStream is)
141: throws IOException {
142: // effective reading of the rest of the file
143: short functionId = 1;
144: int recSize = 0;
145: int gdiIndex; // the last Object index
146: int brushObject = -1; // the last brush
147: int penObject = -1; // the last pen
148: int fontObject = -1; // the last font
149: GdiObject gdiObj;
150:
151: while (functionId > 0) {
152: recSize = readInt(is);
153: // Subtract size in 16-bit words of recSize and functionId;
154: recSize -= 3;
155:
156: functionId = readShort(is);
157: if (functionId <= 0)
158: break;
159:
160: switch (functionId) {
161: case WMFConstants.META_SETWINDOWORG: {
162: vpY = readShort(is);
163: vpX = readShort(is);
164: }
165: break;
166: case WMFConstants.META_SETWINDOWEXT: {
167: vpH = readShort(is);
168: vpW = readShort(is);
169: }
170: break;
171:
172: case WMFConstants.META_CREATEPENINDIRECT: {
173: int objIndex = 0;
174: int penStyle = readShort(is);
175:
176: readInt(is); // width
177: // color definition
178: int colorref = readInt(is);
179: int red = colorref & 0xff;
180: int green = (colorref & 0xff00) >> 8;
181: int blue = (colorref & 0xff0000) >> 16;
182: Color color = new Color(red, green, blue);
183:
184: if (recSize == 6)
185: readShort(is); // if size greater than 5
186: if (penStyle == WMFConstants.META_PS_NULL) {
187: objIndex = addObjectAt(NULL_PEN, color, objIndex);
188: } else {
189: objIndex = addObjectAt(PEN, color, objIndex);
190: }
191: }
192: break;
193:
194: case WMFConstants.META_CREATEBRUSHINDIRECT: {
195: int objIndex = 0;
196: int brushStyle = readShort(is);
197: // color definition
198: int colorref = readInt(is);
199: int red = colorref & 0xff;
200: int green = (colorref & 0xff00) >> 8;
201: int blue = (colorref & 0xff0000) >> 16;
202: Color color = new Color(red, green, blue);
203:
204: readShort(is); // hatch
205: if (brushStyle == WMFConstants.META_PS_NULL) {
206: objIndex = addObjectAt(NULL_BRUSH, color, objIndex);
207: } else
208: objIndex = addObjectAt(BRUSH, color, objIndex);
209: }
210: break;
211:
212: case WMFConstants.META_SETTEXTALIGN:
213: int align = readShort(is);
214: // need to do this, because sometimes there is more than one short
215: if (recSize > 1)
216: for (int i = 1; i < recSize; i++)
217: readShort(is);
218: currentHorizAlign = WMFUtilities
219: .getHorizontalAlignment(align);
220: currentVertAlign = WMFUtilities
221: .getVerticalAlignment(align);
222: break;
223:
224: case WMFConstants.META_EXTTEXTOUT: {
225: int y = readShort(is);
226: int x = readShort(is);
227: int lenText = readShort(is);
228: int flag = readShort(is);
229: int read = 4; // used to track the actual size really read
230: boolean clipped = false;
231: int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
232: int len;
233: // determination of clipping property
234: if ((flag & WMFConstants.ETO_CLIPPED) != 0) {
235: x1 = readShort(is);
236: y1 = readShort(is);
237: x2 = readShort(is);
238: y2 = readShort(is);
239: read += 4;
240: clipped = true;
241: }
242: byte[] bstr = new byte[lenText];
243: int i = 0;
244: for (; i < lenText; i++) {
245: bstr[i] = is.readByte();
246: }
247: String sr = WMFUtilities.decodeString(wf, bstr);
248:
249: read += (lenText + 1) / 2;
250: /* must do this because WMF strings always have an even number of bytes, even
251: * if there is an odd number of characters
252: */
253: if (lenText % 2 != 0)
254: is.readByte();
255: // if the record was not completely read, finish reading
256: if (read < recSize)
257: for (int j = read; j < recSize; j++)
258: readShort(is);
259: TextLayout layout = new TextLayout(sr, wf.font, fontCtx);
260:
261: int lfWidth = (int) layout.getBounds().getWidth();
262: x = (int) layout.getBounds().getX();
263: int lfHeight = (int) getVerticalAlignmentValue(layout,
264: currentVertAlign);
265:
266: resizeBounds(x, y);
267: resizeBounds(x + lfWidth, y + lfHeight);
268: firstEffectivePaint = false;
269: }
270: break;
271:
272: case WMFConstants.META_DRAWTEXT:
273: case WMFConstants.META_TEXTOUT: {
274: int len = readShort(is);
275: int read = 1; // used to track the actual size really read
276: byte[] bstr = new byte[len];
277: for (int i = 0; i < len; i++) {
278: bstr[i] = is.readByte();
279: }
280: String sr = WMFUtilities.decodeString(wf, bstr);
281:
282: /* must do this because WMF strings always have an even number of bytes, even
283: * if there is an odd number of characters
284: */
285: if (len % 2 != 0)
286: is.readByte();
287: read += (len + 1) / 2;
288:
289: int y = readShort(is);
290: int x = readShort(is);
291: read += 2;
292: // if the record was not completely read, finish reading
293: if (read < recSize)
294: for (int j = read; j < recSize; j++)
295: readShort(is);
296: TextLayout layout = new TextLayout(sr, wf.font, fontCtx);
297: int lfWidth = (int) layout.getBounds().getWidth();
298: x = (int) layout.getBounds().getX();
299: int lfHeight = (int) getVerticalAlignmentValue(layout,
300: currentVertAlign);
301:
302: resizeBounds(x, y);
303: resizeBounds(x + lfWidth, y + lfHeight);
304: }
305: break;
306:
307: case WMFConstants.META_CREATEFONTINDIRECT: {
308: int lfHeight = readShort(is);
309: float size = (int) (scaleY * lfHeight);
310: int lfWidth = readShort(is);
311: int escape = (int) readShort(is);
312: int orient = (int) readShort(is);
313: int weight = (int) readShort(is);
314:
315: int italic = (int) is.readByte();
316: int underline = (int) is.readByte();
317: int strikeOut = (int) is.readByte();
318: int charset = (int) (is.readByte() & 0x00ff);
319: int lfOutPrecision = is.readByte();
320: int lfClipPrecision = is.readByte();
321: int lfQuality = is.readByte();
322: int lfPitchAndFamily = is.readByte();
323:
324: int style = italic > 0 ? Font.ITALIC : Font.PLAIN;
325: style |= (weight > 400) ? Font.BOLD : Font.PLAIN;
326:
327: // don't need to read the end of the record,
328: // because it will always be completely used
329: int len = (2 * (recSize - 9));
330: byte[] lfFaceName = new byte[len];
331: byte ch;
332: for (int i = 0; i < len; i++)
333: lfFaceName[i] = is.readByte();
334: String face = new String(lfFaceName);
335:
336: // FIXED : management of font names
337: int d = 0;
338: while ((d < face.length())
339: && ((Character.isLetterOrDigit(face.charAt(d))) || (Character
340: .isWhitespace(face.charAt(d)))))
341: d++;
342: if (d > 0)
343: face = face.substring(0, d);
344: else
345: face = "System";
346:
347: if (size < 0)
348: size = -size /* * -1.3 */;
349: int objIndex = 0;
350:
351: Font f = new Font(face, style, (int) size);
352: f = f.deriveFont(size);
353: WMFFont wf = new WMFFont(f, charset, underline,
354: strikeOut, italic, weight, orient, escape);
355:
356: objIndex = addObjectAt(FONT, wf, objIndex);
357: }
358: break;
359:
360: case WMFConstants.META_CREATEREGION: {
361: int objIndex = 0;
362: for (int j = 0; j < recSize; j++)
363: readShort(is); // read all fields
364: objIndex = addObjectAt(PALETTE, INTEGER_0, 0);
365: }
366: break;
367:
368: case WMFConstants.META_CREATEPALETTE: {
369: int objIndex = 0;
370: for (int j = 0; j < recSize; j++)
371: readShort(is); // read all fields
372: objIndex = addObjectAt(OBJ_REGION, INTEGER_0, 0);
373: }
374: break;
375:
376: case WMFConstants.META_SELECTOBJECT:
377: gdiIndex = readShort(is);
378: if ((gdiIndex & 0x80000000) != 0) // Stock Object
379: break;
380:
381: gdiObj = getObject(gdiIndex);
382: if (!gdiObj.used)
383: break;
384: switch (gdiObj.type) {
385: case PEN:
386: penObject = gdiIndex;
387: break;
388: case BRUSH:
389: brushObject = gdiIndex;
390: break;
391: case FONT: {
392: this .wf = ((WMFFont) gdiObj.obj);
393: fontObject = gdiIndex;
394: }
395: break;
396: case NULL_PEN:
397: penObject = -1;
398: break;
399: case NULL_BRUSH:
400: brushObject = -1;
401: break;
402: }
403: break;
404:
405: case WMFConstants.META_DELETEOBJECT:
406: gdiIndex = readShort(is);
407: gdiObj = getObject(gdiIndex);
408: if (gdiIndex == brushObject)
409: brushObject = -1;
410: else if (gdiIndex == penObject)
411: penObject = -1;
412: else if (gdiIndex == fontObject)
413: fontObject = -1;
414: gdiObj.clear();
415: break;
416:
417: case WMFConstants.META_LINETO: {
418: int y = readShort(is);
419: int x = readShort(is);
420: if (penObject >= 0) {
421: resizeBounds(startX, startY);
422: resizeBounds(x, y);
423: firstEffectivePaint = false;
424: }
425: startX = x;
426: startY = y;
427: }
428: break;
429: case WMFConstants.META_MOVETO: {
430: startY = readShort(is);
431: startX = readShort(is);
432: }
433: break;
434:
435: case WMFConstants.META_POLYPOLYGON: {
436: int count = readShort(is);
437: int[] pts = new int[count];
438: int ptCount = 0;
439: for (int i = 0; i < count; i++) {
440: pts[i] = readShort(is);
441: ptCount += pts[i];
442: }
443:
444: int offset = count + 1;
445: for (int i = 0; i < count; i++) {
446: for (int j = 0; j < pts[i]; j++) {
447: // FIXED 115 : correction preliminary images dimensions
448: int x = readShort(is);
449: int y = readShort(is);
450: if ((brushObject >= 0) || (penObject >= 0))
451: resizeBounds(x, y);
452: }
453: }
454: firstEffectivePaint = false;
455: }
456: break;
457:
458: case WMFConstants.META_POLYGON: {
459: int count = readShort(is);
460: float[] _xpts = new float[count + 1];
461: float[] _ypts = new float[count + 1];
462: for (int i = 0; i < count; i++) {
463: _xpts[i] = readShort(is);
464: _ypts[i] = readShort(is);
465: }
466: _xpts[count] = _xpts[0];
467: _ypts[count] = _ypts[0];
468: Polygon2D pol = new Polygon2D(_xpts, _ypts, count);
469: paint(brushObject, penObject, pol);
470: }
471: break;
472:
473: case WMFConstants.META_POLYLINE: {
474: int count = readShort(is);
475: float[] _xpts = new float[count];
476: float[] _ypts = new float[count];
477: for (int i = 0; i < count; i++) {
478: _xpts[i] = readShort(is);
479: _ypts[i] = readShort(is);
480: }
481: Polyline2D pol = new Polyline2D(_xpts, _ypts, count);
482: paintWithPen(penObject, pol);
483: }
484: break;
485:
486: case WMFConstants.META_ELLIPSE:
487: case WMFConstants.META_INTERSECTCLIPRECT:
488: case WMFConstants.META_RECTANGLE: {
489: int bot = readShort(is);
490: int right = readShort(is);
491: int top = readShort(is);
492: int left = readShort(is);
493: Rectangle2D.Float rec = new Rectangle2D.Float(left,
494: top, right - left, bot - top);
495: paint(brushObject, penObject, rec);
496: }
497: break;
498:
499: case WMFConstants.META_ROUNDRECT: {
500: readShort(is);
501: readShort(is);
502: int bot = readShort(is);
503: int right = readShort(is);
504: int top = readShort(is);
505: int left = readShort(is);
506: Rectangle2D.Float rec = new Rectangle2D.Float(left,
507: top, right - left, bot - top);
508: paint(brushObject, penObject, rec);
509: }
510: break;
511:
512: case WMFConstants.META_ARC:
513: case WMFConstants.META_CHORD:
514: case WMFConstants.META_PIE: {
515: readShort(is);
516: readShort(is);
517: readShort(is);
518: readShort(is);
519: int bot = readShort(is);
520: int right = readShort(is);
521: int top = readShort(is);
522: int left = readShort(is);
523: Rectangle2D.Float rec = new Rectangle2D.Float(left,
524: top, right - left, bot - top);
525: paint(brushObject, penObject, rec);
526: }
527: break;
528:
529: case WMFConstants.META_PATBLT: {
530: readInt(is); // rop
531: int height = readShort(is);
532: int width = readShort(is);
533: int left = readShort(is);
534: int top = readShort(is);
535: if (penObject >= 0)
536: resizeBounds(left, top);
537: if (penObject >= 0)
538: resizeBounds(left + width, top + height);
539: }
540: break;
541: // UPDATED : META_DIBSTRETCHBLT added
542: case WMFConstants.META_DIBSTRETCHBLT: {
543: is.readInt(); // mode
544: readShort(is); // heightSrc
545: readShort(is); // widthSrc
546: readShort(is); // sy
547: readShort(is); // sx
548: float heightDst = (float) readShort(is);
549: float widthDst = (float) readShort(is);
550: float dy = (float) readShort(is) * getVpWFactor()
551: * (float) inch / PIXEL_PER_INCH;
552: float dx = (float) readShort(is) * getVpWFactor()
553: * (float) inch / PIXEL_PER_INCH;
554: widthDst = widthDst * getVpWFactor() * (float) inch
555: / PIXEL_PER_INCH;
556: heightDst = heightDst * getVpHFactor() * (float) inch
557: / PIXEL_PER_INCH;
558: resizeImageBounds((int) dx, (int) dy);
559: resizeImageBounds((int) (dx + widthDst),
560: (int) (dy + heightDst));
561:
562: int len = 2 * recSize - 20;
563: for (int i = 0; i < len; i++)
564: is.readByte();
565: }
566: break;
567: default:
568: for (int j = 0; j < recSize; j++)
569: readShort(is);
570: break;
571:
572: }
573: }
574: resetBounds();
575: return true;
576: }
577:
578: /** @return the width of the Rectangle bounding the figures enclosed in
579: * the Metafile, in pixels
580: */
581: public int getWidthBoundsPixels() {
582: return _bwidth;
583: }
584:
585: /** @return the height of the Rectangle bounding the figures enclosed in
586: * the Metafile, in pixels.
587: */
588: public int getHeightBoundsPixels() {
589: return _bheight;
590: }
591:
592: /** @return the width of the Rectangle bounding the figures enclosed in
593: * the Metafile, in Metafile Units.
594: */
595: public int getWidthBoundsUnits() {
596: return (int) ((float) inch * (float) _bwidth / PIXEL_PER_INCH);
597: }
598:
599: /** @return the height of the Rectangle bounding the figures enclosed in
600: * the Metafile in Metafile Units.
601: */
602: public int getHeightBoundsUnits() {
603: return (int) ((float) inch * (float) _bheight / PIXEL_PER_INCH);
604: }
605:
606: /** @return the X offset of the Rectangle bounding the figures enclosed in
607: * the Metafile.
608: */
609: public int getXOffset() {
610: return _bleft;
611: }
612:
613: /** @return the Y offset of the Rectangle bounding the figures enclosed in
614: * the Metafile.
615: */
616: public int getYOffset() {
617: return _btop;
618: }
619:
620: private void resetBounds() {
621: // calculate geometry size
622: scale = (float) getWidthPixels() / (float) vpW;
623: if (_bright != -1) {
624: _bright = (int) (scale * (vpX + _bright));
625: _bleft = (int) (scale * (vpX + _bleft));
626: _bbottom = (int) (scale * (vpY + _bbottom));
627: _btop = (int) (scale * (vpY + _btop));
628: }
629:
630: // calculate image size
631: if (_iright != -1) {
632: _iright = (int) ((float) _iright * (float) getWidthPixels() / (float) width);
633: _ileft = (int) ((float) _ileft * (float) getWidthPixels() / (float) width);
634: _ibottom = (int) ((float) _ibottom
635: * (float) getWidthPixels() / (float) width);
636: _itop = (int) ((float) _itop * (float) getWidthPixels() / (float) width);
637:
638: // merge image and geometry size
639: if ((_bright == -1) || (_iright > _bright))
640: _bright = _iright;
641: if ((_bleft == -1) || (_ileft < _bleft))
642: _bleft = _ileft;
643: if ((_btop == -1) || (_itop < _btop))
644: _btop = _itop;
645: if ((_bbottom == -1) || (_ibottom > _bbottom))
646: _bbottom = _ibottom;
647: }
648:
649: if ((_bleft != -1) && (_bright != -1))
650: _bwidth = _bright - _bleft;
651: if ((_btop != -1) && (_bbottom != -1))
652: _bheight = _bbottom - _btop;
653: }
654:
655: /** resize Bounds for each primitive encountered. Only elements that are in the overall
656: * width and height of the Metafile are kept.
657: */
658: private void resizeBounds(int x, int y) {
659: if (_bleft == -1)
660: _bleft = x;
661: else if (x < _bleft)
662: _bleft = x;
663: if (_bright == -1)
664: _bright = x;
665: else if (x > _bright)
666: _bright = x;
667:
668: if (_btop == -1)
669: _btop = y;
670: else if (y < _btop)
671: _btop = y;
672: if (_bbottom == -1)
673: _bbottom = y;
674: else if (y > _bbottom)
675: _bbottom = y;
676: }
677:
678: /** resize Bounds for each image primitive encountered. Only elements that are in the overall
679: * width and height of the Metafile are kept.
680: */
681: private void resizeImageBounds(int x, int y) {
682: if (_ileft == -1)
683: _ileft = x;
684: else if (x < _ileft)
685: _ileft = x;
686: if (_iright == -1)
687: _iright = x;
688: else if (x > _iright)
689: _iright = x;
690:
691: if (_itop == -1)
692: _itop = y;
693: else if (y < _itop)
694: _itop = y;
695: if (_ibottom == -1)
696: _ibottom = y;
697: else if (y > _ibottom)
698: _ibottom = y;
699: }
700:
701: /** get the Color corresponding with the Object (pen or brush object).
702: */
703: private Color getColorFromObject(int brushObject) {
704: Color color = null;
705: if (brushObject >= 0) {
706: GdiObject gdiObj = getObject(brushObject);
707: return (Color) gdiObj.obj;
708: } else
709: return null;
710: }
711:
712: /** Resize the bounds of the WMF image according with the bounds of the geometric
713: * Shape.
714: * There will be no resizing if one of the following properties is true :
715: * <ul>
716: * <li>the brush and the pen objects are < 0 (null objects)</li>
717: * <li>the color of the geometric Shape is white, and no other Shapes has occured</li>
718: * </ul>
719: */
720: private void paint(int brushObject, int penObject, Shape shape) {
721: if ((brushObject >= 0) || (penObject >= 0)) {
722: Color col;
723: if (brushObject >= 0)
724: col = getColorFromObject(brushObject);
725: else
726: col = getColorFromObject(penObject);
727:
728: if (!(firstEffectivePaint && (col.equals(Color.white)))) {
729: Rectangle rec = shape.getBounds();
730: resizeBounds((int) rec.getMinX(), (int) rec.getMinY());
731: resizeBounds((int) rec.getMaxX(), (int) rec.getMaxY());
732: firstEffectivePaint = false;
733: }
734: }
735: }
736:
737: /** Resize the bounds of the WMF image according with the bounds of the geometric
738: * Shape.
739: * There will be no resizing if one of the following properties is true :
740: * <ul>
741: * <li>the pen objects is < 0 (null object)</li>
742: * <li>the color of the geometric Shape is white, and no other Shapes has occured</li>
743: * </ul>
744: */
745: private void paintWithPen(int penObject, Shape shape) {
746: if (penObject >= 0) {
747: Color col = getColorFromObject(penObject);
748:
749: if (!(firstEffectivePaint && (col.equals(Color.white)))) {
750: Rectangle rec = shape.getBounds();
751: resizeBounds((int) rec.getMinX(), (int) rec.getMinY());
752: resizeBounds((int) rec.getMaxX(), (int) rec.getMaxY());
753: firstEffectivePaint = false;
754: }
755: }
756: }
757:
758: /** get the vertical Alignment value for the text.
759: */
760: private float getVerticalAlignmentValue(TextLayout layout,
761: int vertAlign) {
762: if (vertAlign == WMFConstants.TA_BASELINE)
763: return -layout.getAscent();
764: else if (vertAlign == WMFConstants.TA_TOP)
765: return (layout.getAscent() + layout.getDescent());
766: else
767: return 0;
768: }
769: }
|