/******************************************************************************* * Copyright (c) 2009, Adobe Systems Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * · Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * · Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * · Neither the name of Adobe Systems Incorporated nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ package com.adobe.dp.office.metafile; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.util.Vector; public abstract class MetafileParser { private InputStream in; private int remainsInRecord; GDISurface handler; Vector objects = new Vector(); protected MetafileParser(InputStream in, GDISurface handler) throws IOException { this.in = in; this.handler = handler; } protected int storeObject(Object obj, int index) { int len = objects.size(); for (int i = index; i < len; i++) { if (objects.get(i) == null) { objects.set(i, obj); return i; } } while (objects.size() < index) objects.add(null); objects.add(obj); return len; } protected void setRemainsBytes(int r) { remainsInRecord = r; } protected void setRemainsShorts(int r) { remainsInRecord = 2 * r; } protected int remainsBytes() { return remainsInRecord; } protected int remainsShorts() { return remainsInRecord / 2; } protected int remainsInts() { return remainsInRecord / 4; } protected void skipBytes(int n) throws IOException { if (in.skip(n) != n) throw new EOFException(); remainsInRecord -= n; } protected void skipShorts(int n) throws IOException { int byteCount = 2 * n; if (in.skip(byteCount) != byteCount) throw new EOFException(); remainsInRecord -= byteCount; } protected void skipInts(int n) throws IOException { int byteCount = 4 * n; if (in.skip(byteCount) != byteCount) throw new EOFException(); remainsInRecord -= byteCount; } protected short readShort() throws IOException { int b1 = in.read(); if (b1 < 0) throw new EOFException(); int b2 = in.read(); if (b2 < 0) throw new EOFException(); remainsInRecord -= 2; return (short) ((b2 << 8) | (b1 & 0xFF)); } protected int readInt() throws IOException { int b1 = in.read(); if (b1 < 0) throw new EOFException(); int b2 = in.read(); if (b2 < 0) throw new EOFException(); int b3 = in.read(); if (b3 < 0) throw new EOFException(); int b4 = in.read(); if (b4 < 0) throw new EOFException(); remainsInRecord -= 4; return ((b4 & 0xFF) << 24) | ((b3 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b1 & 0xFF); } protected void readBytes(byte[] arr, int offset, int len) throws IOException { while (offset < len) { int r = in.read(arr, offset, len - offset); if (r <= 0) throw new IOException("not enough data"); offset += r; } remainsInRecord -= len; } protected void readBytes(byte[] arr) throws IOException { readBytes(arr, 0, arr.length); } protected int readRGB() throws IOException { int bgr = readInt(); int red = bgr & 0xFF; int green = (bgr >> 8) & 0xFF; int blue = (bgr >> 16) & 0xFF; return (red << 16) | (green << 8) | blue; } protected void finishRecord() throws IOException { if (remainsInRecord > 0) { in.skip(remainsInRecord); remainsInRecord = 0; } } protected GDIBitmap readDIB() throws IOException { return readDIB(0); } protected GDIBitmap readDIB(int offsetToBytes) throws IOException { int biSize = readInt(); if (biSize != 40) throw new IOException("Problem with BITMAPINFOHEADER"); int biWidth = readInt(); int biHeight = readInt(); short biPlanes = readShort(); if (biPlanes != 1) throw new IOException("Problem with BITMAPINFOHEADER"); short biBitsPixel = readShort(); int biCompression = readInt(); int biSizeImage = readInt(); if( biSizeImage == 0 ) { int stride = 4*((biBitsPixel*biWidth+31)/32); biSizeImage = stride*biHeight; } readInt(); readInt(); int biClrUsed = readInt(); readInt(); offsetToBytes -= 40; int[] colors = null; if( biClrUsed > 0 ) { colors = new int[biClrUsed]; for( int i = 0 ; i < biClrUsed ; i++ ) { offsetToBytes -= 4; colors[i] = readRGB(); } } byte[] bits = new byte[biSizeImage]; if( offsetToBytes > 0 ) skipBytes(offsetToBytes); readBytes(bits); return new GDIBitmap(biWidth, biHeight, biBitsPixel, biCompression, bits, colors); } abstract public boolean readNext() throws IOException; protected void close() throws IOException { in.close(); } }