001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017: package org.apache.poi.hslf.blip;
018:
019: import org.apache.poi.util.LittleEndian;
020: import org.apache.poi.hslf.usermodel.PictureData;
021:
022: import java.awt.*;
023: import java.io.*;
024: import java.util.zip.DeflaterOutputStream;
025: import java.util.zip.InflaterInputStream;
026:
027: /**
028: * Represents a metafile picture which can be one of the following types: EMF, WMF, or PICT.
029: * A metafile is stored compressed using the ZIP deflate/inflate algorithm.
030: *
031: * @author Yegor Kozlov
032: */
033: public abstract class Metafile extends PictureData {
034:
035: /**
036: * A structure which represents a 34-byte header preceeding the compressed metafile data
037: *
038: * @author Yegor Kozlov
039: */
040: public static class Header {
041:
042: /**
043: * size of the original file
044: */
045: public int wmfsize;
046:
047: /**
048: * Boundary of the metafile drawing commands
049: */
050: public Rectangle bounds;
051:
052: /**
053: * Size of the metafile in EMUs
054: */
055: public Dimension size;
056:
057: /**
058: * size of the compressed metafile data
059: */
060: public int zipsize;
061:
062: /**
063: * Reserved. Always 0.
064: */
065: public int compression;
066:
067: /**
068: * Reserved. Always 254.
069: */
070: public int filter = 254;
071:
072: public void read(byte[] data, int offset) {
073: int pos = offset;
074: wmfsize = LittleEndian.getInt(data, pos);
075: pos += LittleEndian.INT_SIZE;
076:
077: int left = LittleEndian.getInt(data, pos);
078: pos += LittleEndian.INT_SIZE;
079: int top = LittleEndian.getInt(data, pos);
080: pos += LittleEndian.INT_SIZE;
081: int right = LittleEndian.getInt(data, pos);
082: pos += LittleEndian.INT_SIZE;
083: int bottom = LittleEndian.getInt(data, pos);
084: pos += LittleEndian.INT_SIZE;
085:
086: bounds = new Rectangle(left, top, right - left, bottom
087: - top);
088: int width = LittleEndian.getInt(data, pos);
089: pos += LittleEndian.INT_SIZE;
090: int height = LittleEndian.getInt(data, pos);
091: pos += LittleEndian.INT_SIZE;
092:
093: size = new Dimension(width, height);
094:
095: zipsize = LittleEndian.getInt(data, pos);
096: pos += LittleEndian.INT_SIZE;
097:
098: compression = LittleEndian.getUnsignedByte(data, pos);
099: pos++;
100: filter = LittleEndian.getUnsignedByte(data, pos);
101: pos++;
102: }
103:
104: public void write(OutputStream out) throws IOException {
105: byte[] header = new byte[34];
106: int pos = 0;
107: LittleEndian.putInt(header, pos, wmfsize);
108: pos += LittleEndian.INT_SIZE; //hmf
109:
110: LittleEndian.putInt(header, pos, bounds.x);
111: pos += LittleEndian.INT_SIZE; //left
112: LittleEndian.putInt(header, pos, bounds.y);
113: pos += LittleEndian.INT_SIZE; //top
114: LittleEndian.putInt(header, pos, bounds.x + bounds.width);
115: pos += LittleEndian.INT_SIZE; //right
116: LittleEndian.putInt(header, pos, bounds.y + bounds.height);
117: pos += LittleEndian.INT_SIZE; //bottom
118: LittleEndian.putInt(header, pos, size.width);
119: pos += LittleEndian.INT_SIZE; //inch
120: LittleEndian.putInt(header, pos, size.height);
121: pos += LittleEndian.INT_SIZE; //inch
122: LittleEndian.putInt(header, pos, zipsize);
123: pos += LittleEndian.INT_SIZE; //inch
124:
125: header[pos] = 0;
126: pos++;
127: header[pos] = (byte) filter;
128: pos++;
129:
130: out.write(header);
131: }
132:
133: public int getSize() {
134: return 34;
135: }
136: }
137:
138: protected byte[] compress(byte[] bytes, int offset, int length)
139: throws IOException {
140: ByteArrayOutputStream out = new ByteArrayOutputStream();
141: DeflaterOutputStream deflater = new DeflaterOutputStream(out);
142: deflater.write(bytes, offset, length);
143: deflater.close();
144: return out.toByteArray();
145: }
146: }
|