in batik-transcoder/src/main/java/org/apache/batik/transcoder/wmf/tosvg/WMFRecordStore.java [70:740]
protected boolean readRecords( DataInputStream is ) throws IOException {
short functionId = 1;
int recSize = 0;
short recData;
numRecords = 0;
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;
MetaRecord mr = new MetaRecord();
switch ( functionId ) {
case WMFConstants.META_SETMAPMODE: {
mr.numPoints = recSize;
mr.functionId = functionId;
int mapmode = readShort( is );
if (mapmode == WMFConstants.MM_ANISOTROPIC) isotropic = false;
mr.addElement(mapmode);
records.add( mr );
}
break;
case WMFConstants.META_DRAWTEXT:
{
for ( int i = 0; i < recSize; i++ )
recData = readShort( is ); // todo shouldn't the read data be used for something??
numRecords--;
}
break;
case WMFConstants.META_EXTTEXTOUT:
{
int yVal = readShort( is ) * ySign;
int xVal = (int) (readShort( is ) * xSign * scaleXY);
int lenText = readShort( is );
int flag = readShort( is );
int read = 4; // used to track the actual size really read
boolean clipped = false;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
int len;
// determination of clipping property
if ((flag & WMFConstants.ETO_CLIPPED) != 0) {
x1 = (int) (readShort( is ) * xSign * scaleXY);
y1 = readShort( is ) * ySign;
x2 = (int) (readShort( is ) * xSign * scaleXY);
y2 = readShort( is ) * ySign;
read += 4;
clipped = true;
}
byte[] bstr = new byte[ lenText ];
int i = 0;
for ( ; i < lenText; i++ ) {
bstr[ i ] = is.readByte();
}
read += (lenText + 1)/2;
/* must do this because WMF strings always have an even number of bytes, even
* if there is an odd number of characters
*/
if (lenText % 2 != 0) is.readByte();
// if the record was not completely read, finish reading
if (read < recSize) for (int j = read; j < recSize; j++) readShort( is );
/* get the StringRecord, having decoded the String, using the current
* charset (which was given by the last META_CREATEFONTINDIRECT)
*/
mr = new MetaRecord.ByteRecord(bstr);
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement( xVal );
mr.addElement( yVal );
mr.addElement( flag );
if (clipped) {
mr.addElement( x1 );
mr.addElement( y1 );
mr.addElement( x2 );
mr.addElement( y2 );
}
records.add( mr );
}
break;
case WMFConstants.META_TEXTOUT:
{
int len = readShort( is );
int read = 1; // used to track the actual size really read
byte[] bstr = new byte[ len ];
for ( int i = 0; i < len; i++ ) {
bstr[ i ] = is.readByte();
}
/* must do this because WMF strings always have an even number of bytes, even
* if there is an odd number of characters
*/
if (len % 2 != 0) is.readByte();
read += (len + 1) / 2;
int yVal = readShort( is ) * ySign;
int xVal = (int) (readShort( is ) * xSign * scaleXY);
read += 2;
// if the record was not completely read, finish reading
if (read < recSize) for (int j = read; j < recSize; j++) readShort( is );
/* get the StringRecord, having decoded the String, using the current
* charset (which was givben by the last META_CREATEFONTINDIRECT)
*/
mr = new MetaRecord.ByteRecord(bstr);
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement( xVal );
mr.addElement( yVal );
records.add( mr );
}
break;
case WMFConstants.META_CREATEFONTINDIRECT:
{
int lfHeight = readShort( is );
int lfWidth = readShort( is );
int lfEscapement = readShort( is );
int lfOrientation = readShort( is );
int lfWeight = readShort( is );
int lfItalic = is.readByte();
int lfUnderline = is.readByte();
int lfStrikeOut = is.readByte();
int lfCharSet = is.readByte() & 0x00ff;
//System.out.println("lfCharSet: "+(lfCharSet & 0x00ff));
int lfOutPrecision = is.readByte();
int lfClipPrecision = is.readByte();
int lfQuality = is.readByte();
int lfPitchAndFamily = is.readByte();
// don't need to read the end of the record,
// because it will always be completely used
int len = (2*(recSize-9));
byte[] lfFaceName = new byte[ len ];
byte ch;
for ( int i = 0; i < len; i++ ) lfFaceName[ i ] = is.readByte();
String str = new String( lfFaceName ); // what locale ?? ascii ?? platform ??
mr = new MetaRecord.StringRecord( str );
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement( lfHeight );
mr.addElement( lfItalic );
mr.addElement( lfWeight );
mr.addElement( lfCharSet );
mr.addElement( lfUnderline );
mr.addElement( lfStrikeOut );
mr.addElement( lfOrientation );
// escapement is the orientation of the text in tenth of degrees
mr.addElement( lfEscapement );
records.add( mr );
}
break;
case WMFConstants.META_SETVIEWPORTORG:
case WMFConstants.META_SETVIEWPORTEXT:
case WMFConstants.META_SETWINDOWORG:
case WMFConstants.META_SETWINDOWEXT: {
mr.numPoints = recSize;
mr.functionId = functionId;
int height = readShort( is );
int width = readShort( is );
// inverse the values signs if they are negative
if (width < 0) {
width = -width;
xSign = -1;
}
if (height < 0) {
height = -height;
ySign = -1;
}
if (_bext && functionId == WMFConstants.META_SETWINDOWEXT) {
vpW = width;
vpH = height;
// two lines below commented out due to bug BATIK-1096
// if (! isotropic) scaleXY = (float)vpW / (float)vpH;
// vpW = (int)(vpW * scaleXY);
_bext = false;
}
// sets the width, height of the image if the file does not have an APM (in this case it is retrieved
// from the viewport)
if (! isAldus) {
this.width = vpW;
this.height = vpH;
}
mr.addElement((int)(width * scaleXY));
mr.addElement( height );
records.add( mr );
}
break;
case WMFConstants.META_OFFSETVIEWPORTORG:
case WMFConstants.META_OFFSETWINDOWORG: {
mr.numPoints = recSize;
mr.functionId = functionId;
int y = readShort( is ) * ySign;
int x = (int)(readShort( is ) * xSign * scaleXY);
mr.addElement( x );
mr.addElement( y );
records.add( mr );
}
break;
case WMFConstants.META_SCALEVIEWPORTEXT:
case WMFConstants.META_SCALEWINDOWEXT: {
mr.numPoints = recSize;
mr.functionId = functionId;
int ydenom = readShort( is );
int ynum = readShort( is );
int xdenom= readShort( is );
int xnum = readShort( is );
mr.addElement( xdenom );
mr.addElement( ydenom );
mr.addElement( xnum );
mr.addElement( ynum );
records.add( mr );
scaleX = scaleX * xdenom / xnum;
scaleY = scaleY * ydenom / ynum;
}
break;
case WMFConstants.META_CREATEBRUSHINDIRECT:
{
mr.numPoints = recSize;
mr.functionId = functionId;
// The style
mr.addElement( readShort( is ));
int colorref = readInt( is );
int red = colorref & 0xff;
int green = ( colorref & 0xff00 ) >> 8;
int blue = ( colorref & 0xff0000 ) >> 16;
int flags = ( colorref & 0x3000000 ) >> 24;
mr.addElement( red );
mr.addElement( green );
mr.addElement( blue );
// The hatch style
mr.addElement( readShort( is ) );
records.add( mr );
}
break;
case WMFConstants.META_CREATEPENINDIRECT:
{
mr.numPoints = recSize;
mr.functionId = functionId;
// The style
mr.addElement( readShort( is ) );
int width = readInt( is );
int colorref = readInt( is );
/**
* sometimes records generated by PPT have a
* recSize of 6 and not 5 => in this case only we have
* to read a last short element
**/
//int height = readShort( is );
if (recSize == 6) readShort(is);
int red = colorref & 0xff; // format: fff.bbbbbbbb.gggggggg.rrrrrrrr
int green = ( colorref & 0xff00 ) >> 8;
int blue = ( colorref & 0xff0000 ) >> 16;
int flags = ( colorref & 0x3000000 ) >> 24;
mr.addElement( red );
mr.addElement( green );
mr.addElement( blue );
// The pen width
mr.addElement( width );
records.add( mr );
}
break;
case WMFConstants.META_SETTEXTALIGN:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int align = readShort( is );
// need to do this, because sometimes there is more than one short
if (recSize > 1) for (int i = 1; i < recSize; i++) readShort( is );
mr.addElement( align );
records.add( mr );
}
break;
case WMFConstants.META_SETTEXTCOLOR:
case WMFConstants.META_SETBKCOLOR:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int colorref = readInt( is );
int red = colorref & 0xff;
int green = ( colorref & 0xff00 ) >> 8;
int blue = ( colorref & 0xff0000 ) >> 16;
int flags = ( colorref & 0x3000000 ) >> 24;
mr.addElement( red );
mr.addElement( green );
mr.addElement( blue );
records.add( mr );
}
break;
case WMFConstants.META_LINETO:
case WMFConstants.META_MOVETO:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int y = readShort( is ) * ySign;
int x = (int)(readShort( is ) * xSign * scaleXY);
mr.addElement( x );
mr.addElement( y );
records.add( mr );
}
break;
case WMFConstants.META_SETPOLYFILLMODE :
{
mr.numPoints = recSize;
mr.functionId = functionId;
int mode = readShort( is );
// need to do this, because sometimes there is more than one short
if (recSize > 1) for (int i = 1; i < recSize; i++) readShort( is );
mr.addElement( mode );
records.add( mr );
}
break;
case WMFConstants.META_POLYPOLYGON:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int count = readShort( is ); // number of polygons
int[] pts = new int[ count ];
int ptCount = 0;
for ( int i = 0; i < count; i++ ) {
pts[ i ] = readShort( is ); // number of points for the polygon
ptCount += pts[ i ];
}
mr.addElement( count );
for ( int i = 0; i < count; i++ )
mr.addElement( pts[ i ] );
int offset = count+1;
for ( int i = 0; i < count; i++ ) {
int nPoints = pts[ i ];
for ( int j = 0; j < nPoints; j++ ) {
mr.addElement((int)(readShort( is ) * xSign * scaleXY)); // x position of the polygon
mr.addElement( readShort( is ) * ySign ); // y position of the polygon
}
}
records.add( mr );
}
break;
case WMFConstants.META_POLYLINE:
case WMFConstants.META_POLYGON:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int count = readShort( is );
mr.addElement( count );
for ( int i = 0; i < count; i++ ) {
mr.addElement((int)(readShort( is ) * xSign * scaleXY));
mr.addElement( readShort( is ) * ySign );
}
records.add( mr );
}
break;
case WMFConstants.META_ELLIPSE:
case WMFConstants.META_INTERSECTCLIPRECT:
case WMFConstants.META_RECTANGLE:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int bottom = readShort( is ) * ySign;
int right = (int)(readShort( is ) * xSign * scaleXY);
int top = readShort( is ) * ySign;
int left = (int)(readShort( is ) * xSign * scaleXY);
mr.addElement( left );
mr.addElement( top );
mr.addElement( right );
mr.addElement( bottom );
records.add( mr );
}
break;
case WMFConstants.META_CREATEREGION: {
mr.numPoints = recSize;
mr.functionId = functionId;
int left = (int)(readShort( is ) * xSign * scaleXY);
int top = readShort( is ) * ySign;
int right = (int)(readShort( is ) * xSign * scaleXY);
int bottom = readShort( is ) * ySign;
mr.addElement( left );
mr.addElement( top );
mr.addElement( right );
mr.addElement( bottom );
records.add( mr );
}
break;
case WMFConstants.META_ROUNDRECT: {
mr.numPoints = recSize;
mr.functionId = functionId;
int el_height = readShort( is ) * ySign;
int el_width = (int)(readShort( is ) * xSign * scaleXY);
int bottom = readShort( is ) * ySign;
int right = (int)(readShort( is ) * xSign * scaleXY);
int top = readShort( is ) * ySign;
int left = (int)(readShort( is ) * xSign * scaleXY);
mr.addElement( left );
mr.addElement( top );
mr.addElement( right );
mr.addElement( bottom );
mr.addElement( el_width );
mr.addElement( el_height );
records.add( mr );
}
break;
case WMFConstants.META_ARC:
case WMFConstants.META_PIE:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int yend = readShort( is ) * ySign;
int xend = (int)(readShort( is ) * xSign * scaleXY);
int ystart = readShort( is ) * ySign;
int xstart = (int)(readShort( is ) * xSign * scaleXY);
int bottom = readShort( is ) * ySign;
int right = (int)(readShort( is ) * xSign * scaleXY);
int top = readShort( is ) * ySign;
int left = (int)(readShort( is ) * xSign * scaleXY);
mr.addElement( left );
mr.addElement( top );
mr.addElement( right );
mr.addElement( bottom );
mr.addElement( xstart );
mr.addElement( ystart );
mr.addElement( xend );
mr.addElement( yend );
records.add( mr );
}
break;
// META_PATBLT added
case WMFConstants.META_PATBLT :
{
mr.numPoints = recSize;
mr.functionId = functionId;
int rop = readInt( is );
int height = readShort( is ) * ySign;
int width = (int)(readShort( is ) * xSign * scaleXY);
int left = (int)(readShort( is ) * xSign * scaleXY);
int top = readShort( is ) * ySign;
mr.addElement( rop );
mr.addElement( height );
mr.addElement( width );
mr.addElement( top );
mr.addElement( left );
records.add( mr );
}
break;
case WMFConstants.META_SETBKMODE:
{
mr.numPoints = recSize;
mr.functionId = functionId;
int mode = readShort( is );
mr.addElement( mode );
//if (recSize > 1) readShort( is );
if (recSize > 1) for (int i = 1; i < recSize; i++) readShort( is );
records.add( mr );
}
break;
// UPDATED : META_SETROP2 added
case WMFConstants.META_SETROP2:
{
mr.numPoints = recSize;
mr.functionId = functionId;
// rop should always be a short, but it is sometimes an int...
int rop;
if (recSize == 1) rop = readShort( is );
else rop = readInt( is );
mr.addElement( rop );
records.add( mr );
}
break;
// UPDATED : META_DIBSTRETCHBLT added
case WMFConstants.META_DIBSTRETCHBLT:
{
int mode = is.readInt() & 0xff;
int heightSrc = readShort( is ) * ySign;
int widthSrc = readShort( is ) * xSign;
int sy = readShort( is ) * ySign;
int sx = readShort( is ) * xSign;
int heightDst = readShort( is ) * ySign;
int widthDst = (int)(readShort( is ) * xSign * scaleXY);
int dy = readShort( is ) * ySign;
int dx = (int)(readShort( is ) * xSign * scaleXY);
int len = 2*recSize - 20;
byte[] bitmap = new byte[len];
for (int i = 0; i < len; i++) bitmap[i] = is.readByte();
mr = new MetaRecord.ByteRecord(bitmap);
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement( mode );
mr.addElement( heightSrc );
mr.addElement( widthSrc );
mr.addElement( sy );
mr.addElement( sx );
mr.addElement( heightDst );
mr.addElement( widthDst );
mr.addElement( dy );
mr.addElement( dx );
records.add( mr );
}
break;
case WMFConstants.META_STRETCHDIB: {
int mode = is.readInt() & 0xff;
int usage = readShort( is );
int heightSrc = readShort( is ) * ySign;
int widthSrc = readShort( is ) * xSign;
int sy = readShort( is ) * ySign;
int sx = readShort( is ) * xSign;
int heightDst = readShort( is ) * ySign;
int widthDst = (int)(readShort( is ) * xSign * scaleXY);
int dy = readShort( is ) * ySign;
int dx = (int)(readShort( is ) * xSign * scaleXY);
int len = 2*recSize - 22;
byte[] bitmap = new byte[len];
for (int i = 0; i < len; i++) bitmap[i] = is.readByte();
mr = new MetaRecord.ByteRecord(bitmap);
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement(mode);
mr.addElement(heightSrc);
mr.addElement(widthSrc);
mr.addElement(sy);
mr.addElement(sx);
mr.addElement(heightDst);
mr.addElement(widthDst);
mr.addElement(dy);
mr.addElement(dx);
records.add( mr );
}
break;
// UPDATED : META_DIBBITBLT added
case WMFConstants.META_DIBBITBLT:
{
int mode = is.readInt() & 0xff;
int sy = readShort( is );
int sx = readShort( is );
int hdc = readShort( is );
int height = readShort( is );
int width = (int)(readShort( is ) * xSign * scaleXY);
int dy = readShort( is );
int dx = (int)(readShort( is ) * xSign * scaleXY);
int len = 2*recSize - 18;
if (len > 0) {
byte[] bitmap = new byte[len];
for (int i = 0; i < len; i++)
bitmap[i] = is.readByte();
mr = new MetaRecord.ByteRecord(bitmap);
mr.numPoints = recSize;
mr.functionId = functionId;
} else {
// what does this mean?? len <= 0 ??
mr.numPoints = recSize;
mr.functionId = functionId;
for (int i = 0; i < len; i++) is.readByte();
}
mr.addElement( mode );
mr.addElement( height );
mr.addElement( width );
mr.addElement( sy );
mr.addElement( sx );
mr.addElement( dy );
mr.addElement( dx );
records.add( mr );
}
break;
// UPDATED : META_CREATEPATTERNBRUSH added
case WMFConstants.META_DIBCREATEPATTERNBRUSH:
{
int type = is.readInt() & 0xff;
int len = 2*recSize - 4;
byte[] bitmap = new byte[len];
for (int i = 0; i < len; i++) bitmap[i] = is.readByte();
mr = new MetaRecord.ByteRecord(bitmap);
mr.numPoints = recSize;
mr.functionId = functionId;
mr.addElement( type );
records.add( mr );
}
break;
default:
mr.numPoints = recSize;
mr.functionId = functionId;
for ( int j = 0; j < recSize; j++ )
mr.addElement( readShort( is ) );
records.add( mr );
break;
}
numRecords++;
}
// sets the characteristics of the image if the file does not have an APM (in this case it is retrieved
// from the viewport). This is only useful if one wants to retrieve informations about the file after
// decoding it.
if (! isAldus) {
right = (int)vpX;
left = (int)(vpX + vpW);
top = (int)vpY;
bottom = (int)(vpY + vpH);
}
setReading( false );
return true;
}