You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by de...@apache.org on 2005/09/25 20:00:07 UTC
svn commit: r291451 [3/22] - in /xmlgraphics/batik/branches/svg11: ./
samples/tests/resources/wmf/ samples/tests/spec/text/
sources/org/apache/batik/ext/awt/geom/ sources/org/apache/batik/svggen/
sources/org/apache/batik/transcoder/ sources/org/apache/...
Added: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java
URL: http://svn.apache.org/viewcvs/xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java?rev=291451&view=auto
==============================================================================
--- xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java (added)
+++ xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java Sun Sep 25 10:58:29 2005
@@ -0,0 +1,601 @@
+/*
+
+ Copyright 2005 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.apache.batik.transcoder.wmf.tosvg;
+
+import java.awt.Rectangle;
+import java.awt.Color;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Dimension2D;
+import java.awt.Shape;
+import java.io.File;
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.util.ArrayList;
+
+import org.apache.batik.transcoder.wmf.WMFConstants;
+import org.apache.batik.ext.awt.geom.Polygon2D;
+import org.apache.batik.ext.awt.geom.Polyline2D;
+
+/** This class holds simple properties about a WMF Metafile. It can be used whenever general
+ * informations must be retrieved about this file.
+ */
+public class WMFHeaderProperties extends AbstractWMFReader {
+ protected DataInputStream stream;
+ private int _bleft, _bright, _btop, _bbottom, _bwidth, _bheight;
+ private int _ileft, _iright, _itop, _ibottom;
+ private float scale = 1f;
+ private transient boolean firstEffectivePaint = true;
+ public static final int PEN = 1;
+ public static final int BRUSH = 2;
+ public static final int FONT = 3;
+ public static final int NULL_PEN = 4;
+ public static final int NULL_BRUSH = 5;
+ public static final int PALETTE = 6;
+ public static final int OBJ_BITMAP = 7;
+ public static final int OBJ_REGION = 8;
+
+ /** Creates a new WMFHeaderProperties, and sets the associated WMF File.
+ * @param wmffile the WMF Metafile
+ */
+ public WMFHeaderProperties(File wmffile) throws IOException {
+ super();
+ reset();
+ stream = new DataInputStream(new BufferedInputStream(new FileInputStream(wmffile)));
+ read(stream);
+ stream.close();
+ }
+
+ /** Creates a new WMFHeaderProperties, with no associated file.
+ */
+ public WMFHeaderProperties() {
+ super();
+ }
+
+ public void closeResource() {
+ try {
+ if (stream != null) stream.close();
+ } catch (IOException e) {
+ }
+ }
+
+ /** Creates the properties associated file.
+ */
+ public void setFile(File wmffile) throws IOException {
+ stream = new DataInputStream(new BufferedInputStream(new FileInputStream(wmffile)));
+ read(stream);
+ stream.close();
+ }
+
+ /**
+ * Resets the internal storage and viewport coordinates.
+ */
+ public void reset() {
+ left = 0;
+ right = 0;
+ top = 1000;
+ bottom = 1000;
+ inch = 100;
+ _bleft = -1;
+ _bright = -1;
+ _btop = -1;
+ _bbottom = -1;
+ _ileft = -1;
+ _iright = -1;
+ _itop = -1;
+ _ibottom = -1;
+ _bwidth = -1;
+ _bheight= -1;
+ vpW = -1;
+ vpH = -1;
+ vpX = 0;
+ vpY = 0;
+ firstEffectivePaint = true;
+ }
+
+ /** Get the associated stream.
+ */
+ public DataInputStream getStream() {
+ return stream;
+ }
+
+ protected boolean readRecords(DataInputStream is) throws IOException {
+ // effective reading of the rest of the file
+ short functionId = 1;
+ int recSize = 0;
+ int gdiIndex; // the last Object index
+ int brushObject = -1; // the last brush
+ int penObject = -1; // the last pen
+ int fontObject = -1; // the last font
+ GdiObject gdiObj;
+ /* TODO : it is assumed that the previous Font creation before a textout
+ * corresponds to the next, which can be false
+ */
+ int lfWidth = 0; // for Font width
+ int lfHeight = 0; // for Font height
+
+ while (functionId > 0) {
+ recSize = readInt( is );
+ // Subtract size in 16-bit words of recSize and functionId;
+ recSize -= 3;
+
+ functionId = readShort( is );
+ if ( functionId <= 0 )
+ break;
+
+ switch ( functionId ) {
+ case WMFConstants.META_SETWINDOWORG: {
+ vpY = readShort( is );
+ vpX = readShort( is );
+ }
+ break;
+ case WMFConstants.META_SETWINDOWEXT: {
+ vpH = readShort( is );
+ vpW = readShort( is );
+ }
+ break;
+
+ case WMFConstants.META_CREATEPENINDIRECT:
+ {
+ int objIndex = 0;
+ int penStyle = readShort( is );
+
+ readInt( is ); // width
+ // color definition
+ int colorref = readInt( is );
+ int red = colorref & 0xff;
+ int green = ( colorref & 0xff00 ) >> 8;
+ int blue = ( colorref & 0xff0000 ) >> 16;
+ Color color = new Color( red, green, blue);
+
+ if (recSize == 6) readShort(is); // if size greater than 5
+ if ( penStyle == WMFConstants.META_PS_NULL ) {
+ objIndex = addObjectAt( NULL_PEN, color, objIndex );
+ } else {
+ objIndex = addObjectAt( PEN, color, objIndex );
+ }
+ }
+ break;
+
+ case WMFConstants.META_CREATEBRUSHINDIRECT:
+ {
+ int objIndex = 0;
+ int brushStyle = readShort( is );
+ // color definition
+ int colorref = readInt( is );
+ int red = colorref & 0xff;
+ int green = ( colorref & 0xff00 ) >> 8;
+ int blue = ( colorref & 0xff0000 ) >> 16;
+ Color color = new Color( red, green, blue);
+
+ readShort( is ); // hatch
+ if ( brushStyle == WMFConstants.META_PS_NULL ) {
+ objIndex = addObjectAt( NULL_BRUSH, color, objIndex);
+ } else
+ objIndex = addObjectAt(BRUSH, color, objIndex );
+ }
+ break;
+
+ case WMFConstants.META_EXTTEXTOUT: {
+ int y = readShort( is );
+ int x = readShort( is );
+ int lenText = readInt( is );
+ int len = 2*(recSize-4);
+ for (int i = 0 ; i < len; i++ ) is.readByte();
+ resizeBounds(x, y);
+ resizeBounds(x+lfWidth*lenText, y+lfHeight);
+ firstEffectivePaint = false;
+ }
+ break;
+
+ case WMFConstants.META_TEXTOUT: {
+ int len = readShort( is );
+ for ( int i = 0; i < len; i++ ) is.readByte();
+ if (len % 2 != 0) is.readByte();
+ int y = readShort( is );
+ int x = readShort( is );
+ resizeBounds(x, y);
+ resizeBounds(x+lfWidth*len, y+lfHeight);
+ }
+ break;
+
+
+ case WMFConstants.META_CREATEFONTINDIRECT: {
+ // TODO : handle object creation for fonts, because font use can
+ // be done in a different order than font creation
+ int objIndex = 0;
+ lfHeight = readShort( is );
+ lfWidth = readShort( is );
+ readShort( is );
+ readShort( is );
+ readShort( is );
+
+ is.readByte();
+ is.readByte();
+ is.readByte();
+ is.readByte();
+ is.readByte();
+ is.readByte();
+ is.readByte();
+ is.readByte();
+
+ int len = (2*(recSize-9));
+ for ( int i = 0; i < len; i++ ) is.readByte();
+
+ objIndex = addObjectAt( FONT, new Boolean(true) , objIndex );
+ }
+ break;
+
+ case WMFConstants.META_CREATEREGION: {
+ int objIndex = 0;
+ for ( int j = 0; j < recSize; j++ ) readShort(is); // read all fields
+ objIndex = addObjectAt( PALETTE, new Integer( 0 ), 0 );
+ }
+ break;
+
+ case WMFConstants.META_CREATEPALETTE: {
+ int objIndex = 0;
+ for ( int j = 0; j < recSize; j++ ) readShort(is); // read all fields
+ objIndex = addObjectAt( OBJ_REGION, new Integer( 0 ), 0 );
+ }
+ break;
+
+ case WMFConstants.META_SELECTOBJECT:
+ gdiIndex = readShort(is);
+ if (( gdiIndex & 0x80000000 ) != 0 ) // Stock Object
+ break;
+
+ gdiObj = getObject( gdiIndex );
+ if ( !gdiObj.used )
+ break;
+ switch( gdiObj.type ) {
+ case PEN:
+ penObject = gdiIndex;
+ break;
+ case BRUSH:
+ brushObject = gdiIndex;
+ break;
+ case FONT: {
+ fontObject = gdiIndex;
+ }
+ break;
+ case NULL_PEN:
+ penObject = -1;
+ break;
+ case NULL_BRUSH:
+ brushObject = -1;
+ break;
+ }
+ break;
+
+ case WMFConstants.META_DELETEOBJECT:
+ gdiIndex = readShort(is);
+ gdiObj = getObject( gdiIndex );
+ if ( gdiIndex == brushObject ) brushObject = -1;
+ else if ( gdiIndex == penObject ) penObject = -1;
+ else if ( gdiIndex == fontObject ) fontObject = -1;
+ gdiObj.clear();
+ break;
+
+ case WMFConstants.META_LINETO:
+ case WMFConstants.META_MOVETO: {
+ int y = readShort( is );
+ int x = readShort( is );
+ if (penObject >= 0) resizeBounds(x, y);
+ firstEffectivePaint = false;
+ }
+ break;
+
+ case WMFConstants.META_POLYPOLYGON: {
+ int count = readShort( is );
+ int pts[] = new int[ count ];
+ int ptCount = 0;
+ for ( int i = 0; i < count; i++ ) {
+ pts[ i ] = readShort( is );
+ ptCount += pts[ i ];
+ }
+
+ int offset = count+1;
+ for ( int i = 0; i < count; i++ ) {
+ for ( int j = 0; j < pts[ i ]; j++ ) {
+ // FIXED 115 : correction preliminary images dimensions
+ int x = readShort( is );
+ int y = readShort( is );
+ if ((brushObject >= 0) || (penObject >= 0)) resizeBounds(x, y);
+ }
+ }
+ firstEffectivePaint = false;
+ }
+ break;
+
+ case WMFConstants.META_POLYGON: {
+ int count = readShort( is );
+ float[] _xpts = new float[ count+1 ];
+ float[] _ypts = new float[ count+1 ];
+ for ( int i = 0; i < count; i++ ) {
+ _xpts[i] = readShort( is );
+ _ypts[i] = readShort( is );
+ }
+ _xpts[count] = _xpts[0];
+ _ypts[count] = _ypts[0];
+ Polygon2D pol = new Polygon2D(_xpts, _ypts, count);
+ paint(brushObject, penObject, pol);
+ }
+ break;
+
+ case WMFConstants.META_POLYLINE:
+ {
+ int count = readShort( is );
+ float[] _xpts = new float[ count ];
+ float[] _ypts = new float[ count ];
+ for ( int i = 0; i < count; i++ ) {
+ _xpts[i] = readShort( is );
+ _ypts[i] = readShort( is );
+ }
+ Polyline2D pol = new Polyline2D(_xpts, _ypts, count);
+ paintWithPen(penObject, pol);
+ }
+ break;
+
+ case WMFConstants.META_ELLIPSE:
+ case WMFConstants.META_INTERSECTCLIPRECT:
+ case WMFConstants.META_RECTANGLE: {
+ int bot = readShort( is );
+ int right = readShort( is );
+ int top = readShort( is );
+ int left = readShort( is );
+ Rectangle2D.Float rec = new Rectangle2D.Float(left, top, right-left, bottom-top);
+ paint(brushObject, penObject, rec);
+ }
+ break;
+
+ case WMFConstants.META_ROUNDRECT: {
+ readShort( is );
+ readShort( is );
+ int bot = readShort( is );
+ int right = readShort( is );
+ int top = readShort( is );
+ int left = readShort( is );
+ Rectangle2D.Float rec = new Rectangle2D.Float(left, top, right-left, bottom-top);
+ paint(brushObject, penObject, rec);
+ }
+ break;
+
+ case WMFConstants.META_ARC:
+ case WMFConstants.META_CHORD:
+ case WMFConstants.META_PIE: {
+ readShort( is );
+ readShort( is );
+ readShort( is );
+ readShort( is );
+ int bot = readShort( is );
+ int right = readShort( is );
+ int top = readShort( is );
+ int left = readShort( is );
+ Rectangle2D.Float rec = new Rectangle2D.Float(left, top, right-left, bottom-top);
+ paint(brushObject, penObject, rec);
+ }
+ break;
+
+ case WMFConstants.META_PATBLT : {
+ readInt( is ); // rop
+ int height = readShort( is );
+ int width = readShort( is );
+ int left = readShort( is );
+ int top = readShort( is );
+ if (penObject >= 0) resizeBounds(left, top);
+ if (penObject >= 0) resizeBounds(left+width, top+height);
+ }
+ break;
+ // UPDATED : META_DIBSTRETCHBLT added
+ case WMFConstants.META_DIBSTRETCHBLT:
+ {
+ is.readInt(); // mode
+ readShort( is ); // heightSrc
+ readShort( is ); // widthSrc
+ readShort( is ); // sy
+ readShort( is ); // sx
+ float heightDst = (float)readShort( is );
+ float widthDst = (float)readShort( is );
+ float dy = (float)readShort( is ) * getVpWFactor() * (float)inch / PIXEL_PER_INCH;
+ float dx = (float)readShort( is ) * getVpWFactor() * (float)inch / PIXEL_PER_INCH;
+ widthDst = widthDst * getVpWFactor() * (float)inch / PIXEL_PER_INCH;
+ heightDst = heightDst * getVpHFactor() * (float)inch / PIXEL_PER_INCH;
+ resizeImageBounds((int)dx, (int)dy);
+ resizeImageBounds((int)(dx + widthDst), (int)(dy + heightDst));
+
+ int len = 2*recSize - 20;
+ for (int i = 0; i < len; i++) is.readByte();
+ }
+ break;
+ default:
+ for ( int j = 0; j < recSize; j++ )
+ readShort(is);
+ break;
+
+ }
+ }
+ resetBounds();
+ return true;
+ }
+
+ /** @return the width of the Rectangle bounding the figures enclosed in
+ * the Metafile, in pixels
+ */
+ public int getWidthBoundsPixels() {
+ return _bwidth;
+ }
+
+ /** @return the height of the Rectangle bounding the figures enclosed in
+ * the Metafile, in pixels.
+ */
+ public int getHeightBoundsPixels() {
+ return _bheight;
+ }
+
+ /** @return the width of the Rectangle bounding the figures enclosed in
+ * the Metafile, in Metafile Units.
+ */
+ public int getWidthBoundsUnits() {
+ return (int)((float)inch * (float)_bwidth / PIXEL_PER_INCH);
+ }
+
+ /** @return the height of the Rectangle bounding the figures enclosed in
+ * the Metafile in Metafile Units.
+ */
+ public int getHeightBoundsUnits() {
+ return (int)((float)inch * (float)_bheight / PIXEL_PER_INCH);
+ }
+
+ /** @return the X offset of the Rectangle bounding the figures enclosed in
+ * the Metafile.
+ */
+ public int getXOffset() {
+ return _bleft;
+ }
+
+ /** @return the Y offset of the Rectangle bounding the figures enclosed in
+ * the Metafile.
+ */
+ public int getYOffset() {
+ return _btop;
+ }
+
+ private void resetBounds() {
+ // calculate geometry size
+ scale = (float)getWidthPixels() / (float)vpW ;
+ if (_bright != -1) {
+ _bright = (int)(scale * (vpX +_bright));
+ _bleft = (int)(scale * (vpX +_bleft));
+ _bbottom = (int)(scale * (vpY +_bbottom));
+ _btop = (int)(scale * (vpY +_btop));
+ }
+
+ // calculate image size
+ if (_iright != -1) {
+ _iright = (int)((float)_iright * (float)getWidthPixels() / (float)width);
+ _ileft = (int)((float)_ileft * (float)getWidthPixels() / (float)width);
+ _ibottom = (int)((float)_ibottom * (float)getWidthPixels() / (float)width);
+ _itop = (int)((float)_itop * (float)getWidthPixels() / (float)width);
+
+ // merge image and geometry size
+ if ((_bright == -1) || (_iright > _bright)) _bright = _iright;
+ if ((_bleft == -1) || (_ileft < _bleft)) _bleft = _ileft;
+ if ((_btop == -1) || (_itop < _btop)) _btop = _itop;
+ if ((_bbottom == -1) || (_ibottom > _bbottom)) _bbottom = _ibottom;
+ }
+
+ if ((_bleft != -1) && (_bright != -1)) _bwidth = _bright - _bleft;
+ if ((_btop != -1) && (_bbottom != -1)) _bheight = _bbottom - _btop;
+ }
+
+ /** resize Bounds for each primitive encountered. Only elements that are in the overall
+ * width and height of the Metafile are kept.
+ */
+ private void resizeBounds(int x, int y) {
+ if ((x < right) && (x > left)) {
+ if (_bleft == -1) _bleft = x;
+ else if (x < _bleft) _bleft = x;
+ if (_bright == -1) _bright = x;
+ else if (x > _bright) _bright = x;
+ }
+
+ if ((y < bottom) && (y > top)) {
+ if (_btop == -1) _btop = y;
+ else if (y < _btop) _btop = y;
+ if (_bbottom == -1) _bbottom = y;
+ else if (y > _bbottom) _bbottom = y;
+ }
+ }
+
+ /** resize Bounds for each image primitive encountered. Only elements that are in the overall
+ * width and height of the Metafile are kept.
+ */
+ private void resizeImageBounds(int x, int y) {
+ if ((x < right) && (x > left)) {
+ if (_ileft == -1) _ileft = x;
+ else if (x < _ileft) _ileft = x;
+ if (_iright == -1) _iright = x;
+ else if (x > _iright) _iright = x;
+ }
+
+ if ((y < bottom) && (y > top)) {
+ if (_itop == -1) _itop = y;
+ else if (y < _itop) _itop = y;
+ if (_ibottom == -1) _ibottom = y;
+ else if (y > _ibottom) _ibottom = y;
+ }
+ }
+
+ /** get the Color corresponding with the Object (pen or brush object).
+ */
+ private Color getColorFromObject(int brushObject) {
+ Color color = null;
+ if ( brushObject >= 0 ) {
+ GdiObject gdiObj = getObject( brushObject );
+ return (Color)gdiObj.obj;
+ } else return null;
+ }
+
+ /** Resize the bounds of the WMF image according with the bounds of the geometric
+ * Shape.
+ * There will be no resizing if one of the following properties is true :
+ * <ul>
+ * <li>the brush and the pen objects are < 0 (null objects)</li>
+ * <li>the color of the geometric Shape is white, and no other Shapes has occured</li>
+ * </ul>
+ */
+ private void paint(int brushObject, int penObject, Shape shape) {
+ if (( brushObject >= 0 ) || (penObject >= 0)) {
+ Color col;
+ if (brushObject >= 0) col = getColorFromObject(brushObject);
+ else col = getColorFromObject(penObject);
+
+ if (!(firstEffectivePaint && (col.equals(Color.white)))) {
+ Rectangle rec = shape.getBounds();
+ resizeBounds((int)rec.getMinX(), (int)rec.getMinY());
+ resizeBounds((int)rec.getMaxX(), (int)rec.getMaxY());
+ firstEffectivePaint = false;
+ }
+ }
+ }
+
+ /** Resize the bounds of the WMF image according with the bounds of the geometric
+ * Shape.
+ * There will be no resizing if one of the following properties is true :
+ * <ul>
+ * <li>the pen objects is < 0 (null object)</li>
+ * <li>the color of the geometric Shape is white, and no other Shapes has occured</li>
+ * </ul>
+ */
+ private void paintWithPen(int penObject, Shape shape) {
+ if (penObject >= 0) {
+ Color col = getColorFromObject(penObject);
+
+ if (!(firstEffectivePaint && (col.equals(Color.white)))) {
+ Rectangle rec = shape.getBounds();
+ resizeBounds((int)rec.getMinX(), (int)rec.getMinY());
+ resizeBounds((int)rec.getMaxX(), (int)rec.getMaxY());
+ firstEffectivePaint = false;
+ }
+ }
+ }
+}
Propchange: xmlgraphics/batik/branches/svg11/sources/org/apache/batik/transcoder/wmf/tosvg/WMFHeaderProperties.java
------------------------------------------------------------------------------
svn:executable = *