123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.poi.hemf.record.emf;
-
- import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
- import static org.apache.poi.hemf.record.emf.HemfDraw.readRectL;
- import static org.apache.poi.hemf.record.emf.HemfRecordIterator.HEADER_SIZE;
- import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
- import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
-
- import java.awt.Shape;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Area;
- import java.awt.geom.Point2D;
- import java.awt.geom.Rectangle2D;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
-
- import org.apache.poi.hemf.draw.HemfDrawProperties;
- import org.apache.poi.hemf.draw.HemfGraphics;
- import org.apache.poi.hwmf.draw.HwmfGraphics;
- import org.apache.poi.hwmf.record.HwmfBitmapDib;
- import org.apache.poi.hwmf.record.HwmfColorRef;
- import org.apache.poi.hwmf.record.HwmfDraw;
- import org.apache.poi.hwmf.record.HwmfFill;
- import org.apache.poi.hwmf.record.HwmfFill.ColorUsage;
- import org.apache.poi.hwmf.record.HwmfRegionMode;
- import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
- import org.apache.poi.util.IOUtils;
- import org.apache.poi.util.LittleEndian;
- import org.apache.poi.util.LittleEndianConsts;
- import org.apache.poi.util.LittleEndianInputStream;
-
- public class HemfFill {
- private static final int MAX_RECORD_LENGTH = 10_000_000;
-
- /**
- * The EMR_SETPOLYFILLMODE record defines polygon fill mode.
- */
- public static class EmfSetPolyfillMode extends HwmfFill.WmfSetPolyfillMode implements HemfRecord {
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.setPolyfillMode;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- // A 32-bit unsigned integer that specifies the polygon fill mode and
- // MUST be in the PolygonFillMode enumeration.
- polyFillMode = HwmfPolyfillMode.valueOf((int)leis.readUInt());
- return LittleEndianConsts.INT_SIZE;
- }
- }
-
- public static class EmfExtFloodFill extends HwmfFill.WmfExtFloodFill implements HemfRecord {
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.extFloodFill;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- long size = readPointL(leis, start);
- size += colorRef.init(leis);
- // A 32-bit unsigned integer that specifies how to use the Color value to determine the area for
- // the flood fill operation. The value MUST be in the FloodFill enumeration
- mode = (int)leis.readUInt();
- return size + LittleEndianConsts.INT_SIZE;
- }
- }
-
- /**
- * The EMR_STRETCHBLT record specifies a block transfer of pixels from a source bitmap to a destination rectangle,
- * optionally in combination with a brush pattern, according to a specified raster operation, stretching or
- * compressing the output to fit the dimensions of the destination, if necessary.
- */
- public static class EmfStretchBlt extends HwmfFill.WmfStretchDib implements HemfRecord {
- protected final Rectangle2D bounds = new Rectangle2D.Double();
-
- /** An XForm object that specifies a world-space to page-space transform to apply to the source bitmap. */
- protected final AffineTransform xFormSrc = new AffineTransform();
-
- /** A WMF ColorRef object that specifies the background color of the source bitmap. */
- protected final HwmfColorRef bkColorSrc = new HwmfColorRef();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.stretchBlt;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- int startIdx = leis.getReadIndex();
-
- long size = readRectL(leis, bounds);
-
- size += readBounds2(leis, this.dstBounds);
-
- // A 32-bit unsigned integer that specifies the raster operation code. This code defines how the
- // color data of the source rectangle is to be combined with the color data of the destination
- // rectangle and optionally a brush pattern, to achieve the final color.
- int rasterOpIndex = (int)leis.readUInt();
-
- rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex >>> 16);
-
- size += LittleEndianConsts.INT_SIZE;
-
- final Point2D srcPnt = new Point2D.Double();
- size += readPointL(leis, srcPnt);
-
- size += readXForm(leis, xFormSrc);
-
- size += bkColorSrc.init(leis);
-
- colorUsage = ColorUsage.valueOf((int)leis.readUInt());
-
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap header in the BitmapBuffer field.
- final int offBmiSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap header.
- final int cbBmiSrc = (int)leis.readUInt();
- size += 3*LittleEndianConsts.INT_SIZE;
- if (size >= recordSize) {
- return size;
- }
-
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap bits in the BitmapBuffer field.
- final int offBitsSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap bits.
- final int cbBitsSrc = (int)leis.readUInt();
- size += 2*LittleEndianConsts.INT_SIZE;
-
- if (size >= recordSize) {
- return size;
- }
-
- if (srcEqualsDstDimension()) {
- srcBounds.setRect(srcPnt.getX(), srcPnt.getY(), dstBounds.getWidth(), dstBounds.getHeight());
- } else {
- int srcWidth = leis.readInt();
- int srcHeight = leis.readInt();
- size += 2 * LittleEndianConsts.INT_SIZE;
- srcBounds.setRect(srcPnt.getX(), srcPnt.getY(), srcWidth, srcHeight);
- }
-
- size += readBitmap(leis, bitmap, startIdx, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc);
-
- return size;
- }
-
- protected boolean srcEqualsDstDimension() {
- return false;
- }
-
- @Override
- public void draw(HemfGraphics ctx) {
- HemfDrawProperties prop = ctx.getProperties();
- prop.setBackgroundColor(this.bkColorSrc);
- super.draw(ctx);
- }
-
- @Override
- public String toString() {
- return
- "{ bounds: "+boundsToString(bounds)+
- ", xFormSrc: { scaleX: "+xFormSrc.getScaleX()+", shearX: "+xFormSrc.getShearX()+", transX: "+xFormSrc.getTranslateX()+", scaleY: "+xFormSrc.getScaleY()+", shearY: "+xFormSrc.getShearY()+", transY: "+xFormSrc.getTranslateY()+" }"+
- ", bkColorSrc: "+bkColorSrc+
- ","+super.toString().substring(1);
- }
- }
-
- /**
- * The EMR_STRETCHDIBITS record specifies a block transfer of pixels from a source bitmap to a
- * destination rectangle, optionally in combination with a brush pattern, according to a specified raster
- * operation, stretching or compressing the output to fit the dimensions of the destination, if necessary.
- */
- public static class EmfStretchDiBits extends HwmfFill.WmfStretchDib implements HemfRecord {
- protected final Rectangle2D bounds = new Rectangle2D.Double();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.stretchDiBits;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- final int startIdx = leis.getReadIndex();
-
- long size = readRectL(leis, bounds);
-
- // A 32-bit signed integer that specifies the logical x-coordinate of the upper-left
- // corner of the destination rectangle.
- int xDest = leis.readInt();
- int yDest = leis.readInt();
- size += 2*LittleEndianConsts.INT_SIZE;
-
- size += readBounds2(leis, srcBounds);
-
- // A 32-bit unsigned integer that specifies the offset, in bytes from the start
- // of this record to the source bitmap header.
- int offBmiSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap header.
- int cbBmiSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap bits.
- int offBitsSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap bits.
- int cbBitsSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies how to interpret values in the color table
- // in the source bitmap header. This value MUST be in the DIBColors enumeration
- colorUsage = ColorUsage.valueOf(leis.readInt());
-
- // A 32-bit unsigned integer that specifies a raster operation code.
- // These codes define how the color data of the source rectangle is to be combined with the color data
- // of the destination rectangle and optionally a brush pattern, to achieve the final color.
- // The value MUST be in the WMF Ternary Raster Operation enumeration
- int rasterOpIndex = (int)leis.readUInt();
- rasterOperation = HwmfTernaryRasterOp.valueOf(rasterOpIndex >>> 16);
-
- // A 32-bit signed integer that specifies the logical width of the destination rectangle.
- int cxDest = leis.readInt();
-
- // A 32-bit signed integer that specifies the logical height of the destination rectangle.
- int cyDest = leis.readInt();
-
- dstBounds.setRect(xDest, yDest, cxDest, cyDest);
-
- size += 8*LittleEndianConsts.INT_SIZE;
-
- size += readBitmap(leis, bitmap, startIdx, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc);
-
- return size;
- }
- }
-
- /**
- * The EMR_BITBLT record specifies a block transfer of pixels from a source bitmap to a destination rectangle,
- * optionally in combination with a brush pattern, according to a specified raster operation.
- */
- public static class EmfBitBlt extends EmfStretchBlt {
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.bitBlt;
- }
-
- @Override
- protected boolean srcEqualsDstDimension() {
- return false;
- }
- }
-
-
- /** The EMR_FRAMERGN record draws a border around the specified region using the specified brush. */
- public static class EmfFrameRgn extends HwmfDraw.WmfFrameRegion implements HemfRecord {
- private final Rectangle2D bounds = new Rectangle2D.Double();
- private final List<Rectangle2D> rgnRects = new ArrayList<>();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.frameRgn;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- long size = readRectL(leis, bounds);
- // A 32-bit unsigned integer that specifies the size of region data, in bytes.
- long rgnDataSize = leis.readUInt();
- // A 32-bit unsigned integer that specifies the brush EMF Object Table index.
- brushIndex = (int)leis.readUInt();
- // A 32-bit signed integer that specifies the width of the vertical brush stroke, in logical units.
- width = leis.readInt();
- // A 32-bit signed integer that specifies the height of the horizontal brush stroke, in logical units.
- height = leis.readInt();
- size += 4*LittleEndianConsts.INT_SIZE;
- size += readRgnData(leis, rgnRects);
- return size;
- }
-
- @Override
- public void draw(HwmfGraphics ctx) {
- ctx.applyObjectTableEntry(brushIndex);
- ctx.fill(getShape());
- }
-
- protected Shape getShape() {
- return getRgnShape(rgnRects);
- }
- }
-
- /** The EMR_INVERTRGN record inverts the colors in the specified region. */
- public static class EmfInvertRgn implements HemfRecord {
- protected final Rectangle2D bounds = new Rectangle2D.Double();
- protected final List<Rectangle2D> rgnRects = new ArrayList<>();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.invertRgn;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- long size = readRectL(leis, bounds);
- // A 32-bit unsigned integer that specifies the size of region data, in bytes.
- long rgnDataSize = leis.readUInt();
- size += LittleEndianConsts.INT_SIZE;
- size += readRgnData(leis, rgnRects);
- return size;
- }
-
- protected Shape getShape() {
- return getRgnShape(rgnRects);
- }
- }
-
- /**
- * The EMR_PAINTRGN record paints the specified region by using the brush currently selected into the
- * playback device context.
- */
- public static class EmfPaintRgn extends EmfInvertRgn {
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.paintRgn;
- }
- }
-
- /** The EMR_FILLRGN record fills the specified region by using the specified brush. */
- public static class EmfFillRgn extends HwmfFill.WmfFillRegion implements HemfRecord {
- protected final Rectangle2D bounds = new Rectangle2D.Double();
- protected final List<Rectangle2D> rgnRects = new ArrayList<>();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.fillRgn;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- long size = readRectL(leis, bounds);
- // A 32-bit unsigned integer that specifies the size of region data, in bytes.
- long rgnDataSize = leis.readUInt();
- brushIndex = (int)leis.readUInt();
- size += 2*LittleEndianConsts.INT_SIZE;
- size += readRgnData(leis, rgnRects);
- return size;
- }
-
- protected Shape getShape() {
- return getRgnShape(rgnRects);
- }
- }
-
- public static class EmfExtSelectClipRgn implements HemfRecord {
- protected HwmfRegionMode regionMode;
- protected final List<Rectangle2D> rgnRects = new ArrayList<>();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.extSelectClipRgn;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- // A 32-bit unsigned integer that specifies the size of region data in bytes
- long rgnDataSize = leis.readUInt();
- // A 32-bit unsigned integer that specifies the way to use the region.
- regionMode = HwmfRegionMode.valueOf((int)leis.readUInt());
- long size = 2* LittleEndianConsts.INT_SIZE;
-
- // If RegionMode is RGN_COPY, this data can be omitted and the clip region
- // SHOULD be set to the default (NULL) clip region.
- if (regionMode != HwmfRegionMode.RGN_COPY) {
- size += readRgnData(leis, rgnRects);
- }
- return size;
- }
-
- protected Shape getShape() {
- return getRgnShape(rgnRects);
- }
-
- @Override
- public void draw(HemfGraphics ctx) {
- HemfDrawProperties prop = ctx.getProperties();
- ctx.setClip(getShape(), regionMode, true);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("{ regionMode: '"+regionMode+"'");
- sb.append(", regions: [");
- boolean isFirst = true;
- for (Rectangle2D r : rgnRects) {
- if (!isFirst) {
- sb.append(",");
- }
- isFirst = false;
- sb.append(boundsToString(r));
- }
- sb.append("]}");
- return sb.toString();
- }
- }
-
- public static class EmfAlphaBlend implements HemfRecord {
- /** the destination bounding rectangle in device units */
- protected final Rectangle2D bounds = new Rectangle2D.Double();
- /** the destination rectangle */
- protected final Rectangle2D destRect = new Rectangle2D.Double();
- /** the source rectangle */
- protected final Rectangle2D srcRect = new Rectangle2D.Double();
- /**
- * The blend operation code. The only source and destination blend operation that has been defined
- * is 0x00, which specifies that the source bitmap MUST be combined with the destination bitmap based
- * on the alpha transparency values of the source pixels.
- */
- protected byte blendOperation;
- /** This value MUST be 0x00 and MUST be ignored. */
- protected byte blendFlags;
- /**
- * An 8-bit unsigned integer that specifies alpha transparency, which determines the blend of the source
- * and destination bitmaps. This value MUST be used on the entire source bitmap. The minimum alpha
- * transparency value, zero, corresponds to completely transparent; the maximum value, 0xFF, corresponds
- * to completely opaque. In effect, a value of 0xFF specifies that the per-pixel alpha values determine
- * the blend of the source and destination bitmaps.
- */
- protected int srcConstantAlpha;
- /**
- * A byte that specifies how source and destination pixels are interpreted with respect to alpha transparency.
- *
- * 0x00:
- * The pixels in the source bitmap do not specify alpha transparency.
- * In this case, the SrcConstantAlpha value determines the blend of the source and destination bitmaps.
- * Note that in the following equations SrcConstantAlpha is divided by 255,
- * which produces a value in the range 0 to 1.
- *
- * 0x01: "AC_SRC_ALPHA"
- * Indicates that the source bitmap is 32 bits-per-pixel and specifies an alpha transparency value
- * for each pixel.
- */
- protected byte alphaFormat;
- /** a world-space to page-space transform to apply to the source bitmap. */
- protected final AffineTransform xFormSrc = new AffineTransform();
- /** the background color of the source bitmap. */
- protected final HwmfColorRef bkColorSrc = new HwmfColorRef();
- /**
- * A 32-bit unsigned integer that specifies how to interpret values in the
- * color table in the source bitmap header.
- */
- protected ColorUsage usageSrc;
-
- protected final HwmfBitmapDib bitmap = new HwmfBitmapDib();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.alphaBlend;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- final int startIdx = leis.getReadIndex();
-
- long size = readRectL(leis, bounds);
- size += readBounds2(leis, destRect);
-
- blendOperation = leis.readByte();
- assert (blendOperation == 0);
- blendFlags = leis.readByte();
- assert (blendOperation == 0);
- srcConstantAlpha = leis.readUByte();
- alphaFormat = leis.readByte();
-
- // A 32-bit signed integer that specifies the logical x-coordinate of the upper-left
- // corner of the source rectangle.
- final int xSrc = leis.readInt();
- // A 32-bit signed integer that specifies the logical y-coordinate of the upper-left
- // corner of the source rectangle.
- final int ySrc = leis.readInt();
-
- size += 3*LittleEndianConsts.INT_SIZE;
- size += readXForm(leis, xFormSrc);
- size += bkColorSrc.init(leis);
-
- usageSrc = ColorUsage.valueOf((int)leis.readUInt());
-
-
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap header in the BitmapBuffer field.
- final int offBmiSrc = (int)leis.readUInt();
-
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap header.
- final int cbBmiSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap bits in the BitmapBuffer field.
- final int offBitsSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap bits.
- final int cbBitsSrc = (int)leis.readUInt();
-
- // A 32-bit signed integer that specifies the logical width of the source rectangle.
- // This value MUST be greater than zero.
- final int cxSrc = leis.readInt();
- // A 32-bit signed integer that specifies the logical height of the source rectangle.
- // This value MUST be greater than zero.
- final int cySrc = leis.readInt();
-
- srcRect.setRect(xSrc, ySrc, cxSrc, cySrc);
-
- size += 7 * LittleEndianConsts.INT_SIZE;
-
- size += readBitmap(leis, bitmap, startIdx, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc);
-
- return size;
- }
- }
-
- /**
- * The EMR_SETDIBITSTODEVICE record specifies a block transfer of pixels from specified scanlines of
- * a source bitmap to a destination rectangle.
- */
- public static class EmfSetDiBitsToDevice implements HemfRecord {
- protected final Rectangle2D bounds = new Rectangle2D.Double();
- protected final Point2D dest = new Point2D.Double();
- protected final Rectangle2D src = new Rectangle2D.Double();
- protected ColorUsage usageSrc;
- protected final HwmfBitmapDib bitmap = new HwmfBitmapDib();
-
- @Override
- public HemfRecordType getEmfRecordType() {
- return HemfRecordType.setDiBitsToDevice;
- }
-
- @Override
- public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
- int startIdx = leis.getReadIndex();
-
- // A WMF RectL object that defines the destination bounding rectangle in device units.
- long size = readRectL(leis, bounds);
- // the logical x/y-coordinate of the upper-left corner of the destination rectangle.
- size += readPointL(leis, dest);
- // the source rectangle
- size += readBounds2(leis, src);
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap header in the BitmapBuffer field.
- final int offBmiSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap header.
- final int cbBmiSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the offset, in bytes, from the
- // start of this record to the source bitmap bits in the BitmapBuffer field.
- final int offBitsSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the size, in bytes, of the source bitmap bits.
- final int cbBitsSrc = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies how to interpret values in the color table
- // in the source bitmap header. This value MUST be in the DIBColors enumeration
- usageSrc = ColorUsage.valueOf((int)leis.readUInt());
- // A 32-bit unsigned integer that specifies the first scan line in the array.
- final int iStartScan = (int)leis.readUInt();
- // A 32-bit unsigned integer that specifies the number of scan lines.
- final int cScans = (int)leis.readUInt();
- size += 7*LittleEndianConsts.INT_SIZE;
-
- size += readBitmap(leis, bitmap, startIdx, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc);
-
- return size;
- }
-
- @Override
- public String toString() {
- return
- "{ bounds: " + boundsToString(bounds) +
- ", dest: " + pointToString(dest) +
- ", src: " + boundsToString(src) +
- ", usageSrc: '" + usageSrc + "'" +
- ", bitmap: " + bitmap +
- "}";
- }
- }
-
- static long readBitmap(final LittleEndianInputStream leis, final HwmfBitmapDib bitmap,
- final int startIdx, final int offBmi, final int cbBmi, final int offBits, int cbBits)
- throws IOException {
- if (offBmi == 0) {
- return 0;
- }
-
- final int offCurr = leis.getReadIndex()-(startIdx-HEADER_SIZE);
- final int undefinedSpace1 = offBmi-offCurr;
- if (undefinedSpace1 < 0) {
- return 0;
- }
-
- final int undefinedSpace2 = offBits-offCurr-cbBmi-undefinedSpace1;
- assert(undefinedSpace2 >= 0);
-
- leis.skipFully(undefinedSpace1);
-
- if (cbBmi == 0 || cbBits == 0) {
- return undefinedSpace1;
- }
-
- final int dibSize = cbBmi+cbBits;
- if (undefinedSpace2 == 0) {
- return undefinedSpace1 + bitmap.init(leis, dibSize);
- }
-
- final ByteArrayOutputStream bos = new ByteArrayOutputStream(cbBmi+cbBits);
- final long cbBmiSrcAct = IOUtils.copy(leis, bos, cbBmi);
- assert (cbBmiSrcAct == cbBmi);
- leis.skipFully(undefinedSpace2);
- final long cbBitsSrcAct = IOUtils.copy(leis, bos, cbBits);
- assert (cbBitsSrcAct == cbBits);
-
- final LittleEndianInputStream leisDib = new LittleEndianInputStream(new ByteArrayInputStream(bos.toByteArray()));
- final int dibSizeAct = bitmap.init(leisDib, dibSize);
- assert (dibSizeAct <= dibSize);
- return undefinedSpace1 + cbBmi + undefinedSpace2 + cbBits;
- }
-
-
- static long readRgnData(final LittleEndianInputStream leis, final List<Rectangle2D> rgnRects) {
- // *** RegionDataHeader ***
- // A 32-bit unsigned integer that specifies the size of this object in bytes. This MUST be 0x00000020.
- long rgnHdrSize = leis.readUInt();
- assert(rgnHdrSize == 0x20);
- // A 32-bit unsigned integer that specifies the region type. This SHOULD be RDH_RECTANGLES (0x00000001)
- long rgnHdrType = leis.readUInt();
- assert(rgnHdrType == 1);
- // A 32-bit unsigned integer that specifies the number of rectangles in this region.
- long rgnCntRect = leis.readUInt();
- // A 32-bit unsigned integer that specifies the size of the buffer of rectangles in bytes.
- long rgnCntBytes = leis.readUInt();
- long size = 4*LittleEndianConsts.INT_SIZE;
- // A 128-bit WMF RectL object, which specifies the bounds of the region.
- Rectangle2D rgnBounds = new Rectangle2D.Double();
- size += readRectL(leis, rgnBounds);
- for (int i=0; i<rgnCntRect; i++) {
- Rectangle2D rgnRct = new Rectangle2D.Double();
- size += readRectL(leis, rgnRct);
- rgnRects.add(rgnRct);
- }
- return size;
- }
-
-
- static int readBounds2(LittleEndianInputStream leis, Rectangle2D bounds) {
- /**
- * The 32-bit signed integers that defines the corners of the bounding rectangle.
- */
- int x = leis.readInt();
- int y = leis.readInt();
- int w = leis.readInt();
- int h = leis.readInt();
-
- bounds.setRect(x, y, w, h);
-
- return 4 * LittleEndianConsts.INT_SIZE;
- }
-
- static int readXForm(LittleEndianInputStream leis, AffineTransform xform) {
- // mapping <java AffineTransform> = <xform>
-
- // m00 (scaleX) = eM11 (Horizontal scaling component)
- double m00 = leis.readFloat();
-
- // m01 (shearX) = eM12 (Horizontal proportionality constant)
- double m01 = leis.readFloat();
-
- // m10 (shearY) = eM21 (Vertical proportionality constant)
- double m10 = leis.readFloat();
-
- // m11 (scaleY) = eM22 (Vertical scaling component)
- double m11 = leis.readFloat();
-
- // m02 (translateX) = eDx (The horizontal translation component, in logical units.)
- double m02 = leis.readFloat();
-
- // m12 (translateY) = eDy (The vertical translation component, in logical units.)
- double m12 = leis.readFloat();
-
- xform.setTransform(m00, m10, m01, m11, m02, m12);
-
- return 6 * LittleEndian.INT_SIZE;
- }
-
- protected static Shape getRgnShape(List<Rectangle2D> rgnRects) {
- if (rgnRects.size() == 1) {
- return rgnRects.get(0);
- }
- final Area frame = new Area();
- rgnRects.forEach((rct) -> frame.add(new Area(rct)));
- return frame;
- }
- }
|