You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2019/06/06 22:32:41 UTC
svn commit: r1860732 [2/2] - in /poi/trunk/src/scratchpad:
src/org/apache/poi/hemf/draw/ src/org/apache/poi/hemf/record/emf/
src/org/apache/poi/hemf/record/emfplus/ src/org/apache/poi/hemf/usermodel/
src/org/apache/poi/hwmf/draw/ src/org/apache/poi/hwm...
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusPen.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusPen.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusPen.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusPen.java Thu Jun 6 22:32:41 2019
@@ -23,12 +23,17 @@ import static org.apache.poi.hemf.record
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.io.IOException;
+import java.util.List;
import java.util.function.Consumer;
+import org.apache.poi.hemf.draw.HemfDrawProperties;
+import org.apache.poi.hemf.draw.HemfGraphics;
+import org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusUnitType;
import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
+import org.apache.poi.hwmf.record.HwmfPenStyle;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.Internal;
@@ -215,6 +220,13 @@ public class HemfPlusPen {
}
}
+
+ @Internal
+ public interface EmfPlusCustomLineCap {
+ long init(LittleEndianInputStream leis) throws IOException;
+ }
+
+
public static class EmfPlusPen implements EmfPlusObjectData {
@@ -283,16 +295,17 @@ public class HemfPlusPen {
private int type;
private int penDataFlags;
- private HemfPlusDraw.EmfPlusUnitType unitType;
+ private EmfPlusUnitType unitType;
private double penWidth;
- private AffineTransform trans;
- private EmfPlusLineCapType startCap, endCap;
- private EmfPlusLineJoin join;
- private Double mitterLimit;
- private EmfPlusLineStyle style;
- EmfPlusDashedLineCapType dashedLineCapType;
+ private final AffineTransform trans = new AffineTransform();
+ private EmfPlusLineCapType startCap = EmfPlusLineCapType.FLAT;
+ private EmfPlusLineCapType endCap = startCap;
+ private EmfPlusLineJoin join = EmfPlusLineJoin.ROUND;
+ private Double miterLimit = 1.;
+ private EmfPlusLineStyle style = EmfPlusLineStyle.SOLID;
+ private EmfPlusDashedLineCapType dashedLineCapType;
private Double dashOffset;
- private double[] dashedLineData;
+ private float[] dashedLineData;
private EmfPlusPenAlignment penAlignment;
private double[] compoundLineData;
private EmfPlusCustomLineCap customStartCap;
@@ -310,17 +323,16 @@ public class HemfPlusPen {
penDataFlags = leis.readInt();
// A 32-bit unsigned integer that specifies the measuring units for the pen.
// The value MUST be from the UnitType enumeration
- unitType = HemfPlusDraw.EmfPlusUnitType.valueOf(leis.readInt());
+ unitType = EmfPlusUnitType.valueOf(leis.readInt());
// A 32-bit floating-point value that specifies the width of the line drawn by the pen in the units specified
// by the PenUnit field. If a zero width is specified, a minimum value is used, which is determined by the units.
penWidth = leis.readFloat();
- size += 4* LittleEndianConsts.INT_SIZE;
+ size += 4*LittleEndianConsts.INT_SIZE;
if (TRANSFORM.isSet(penDataFlags)) {
// An optional EmfPlusTransformMatrix object that specifies a world space to device space transform for
// the pen. This field MUST be present if the PenDataTransform flag is set in the PenDataFlags field of
// the EmfPlusPenData object.
- trans = new AffineTransform();
size += readXForm(leis, trans);
}
@@ -354,7 +366,7 @@ public class HemfPlusPen {
// line walls on the inside the join to the intersection of the line walls outside the join. The miter
// length can be large when the angle between two lines is small. This field MUST be present if the
// PenDataMiterLimit flag is set in the PenDataFlags field of the EmfPlusPenData object.
- mitterLimit = (double)leis.readFloat();
+ miterLimit = (double)leis.readFloat();
size += LittleEndianConsts.INT_SIZE;
}
@@ -390,7 +402,7 @@ public class HemfPlusPen {
}
// An array of DashedLineDataSize floating-point values that specify the lengths of the dashes and spaces in a dashed line.
- dashedLineData = new double[dashesSize];
+ dashedLineData = new float[dashesSize];
for (int i=0; i<dashesSize; i++) {
dashedLineData[i] = leis.readFloat();
}
@@ -435,6 +447,11 @@ public class HemfPlusPen {
return size;
}
+ @Override
+ public EmfPlusGraphicsVersion getGraphicsVersion() {
+ return graphicsVersion;
+ }
+
private long initCustomCap(Consumer<EmfPlusCustomLineCap> setter, LittleEndianInputStream leis) throws IOException {
EmfPlusGraphicsVersion version = new EmfPlusGraphicsVersion();
long size = version.init(leis);
@@ -450,153 +467,209 @@ public class HemfPlusPen {
return size;
}
- @Internal
- public interface EmfPlusCustomLineCap {
- long init(LittleEndianInputStream leis) throws IOException;
- }
-
- public static class EmfPlusPathArrowCap implements EmfPlusCustomLineCap {
- /**
- * If set, an EmfPlusFillPath object MUST be specified in the OptionalData field of the
- * EmfPlusCustomLineCapData object for filling the custom line cap.
- */
- private static final BitField FILL_PATH = BitFieldFactory.getInstance(0x00000001);
- /**
- * If set, an EmfPlusLinePath object MUST be specified in the OptionalData field of the
- * EmfPlusCustomLineCapData object for outlining the custom line cap.
- */
- private static final BitField LINE_PATH = BitFieldFactory.getInstance(0x00000002);
-
-
- private int dataFlags;
- private EmfPlusLineCapType baseCap;
- private double baseInset;
- private EmfPlusLineCapType startCap;
- private EmfPlusLineCapType endCap;
- private EmfPlusLineJoin join;
- private double mitterLimit;
- private double widthScale;
- private final Point2D fillHotSpot = new Point2D.Double();
- private final Point2D lineHotSpot = new Point2D.Double();
- private EmfPlusPath fillPath;
- private EmfPlusPath outlinePath;
-
- @Override
- public long init(LittleEndianInputStream leis) throws IOException {
- // A 32-bit unsigned integer that specifies the data in the OptionalData field.
- // This value MUST be composed of CustomLineCapData flags
- dataFlags = leis.readInt();
-
- // A 32-bit unsigned integer that specifies the value from the LineCap enumeration on which
- // the custom line cap is based.
- baseCap = EmfPlusLineCapType.valueOf(leis.readInt());
-
- // A 32-bit floating-point value that specifies the distance between the
- // beginning of the line cap and the end of the line.
- baseInset = leis.readFloat();
+ @Override
+ public void applyObject(HemfGraphics ctx, List<? extends EmfPlusObjectData> continuedObjectData) {
+ final HemfDrawProperties prop = ctx.getProperties();
+ // TOOD:
+ // - set width according unit type
+ // - provide logic for different start and end cap
+ // - provide standard caps like diamondd
+ // - support custom caps
+
+ // workaround for too wide pens ... just arbitrary reduce high values ...
+ prop.setPenWidth(penWidth > 20 ? 1 : penWidth);
+ prop.setPenStyle(new HwmfPenStyle(){
+ @Override
+ public HwmfLineCap getLineCap() {
+ // ignore endCap for now
+ switch(startCap) {
+ default:
+ case FLAT:
+ return HwmfLineCap.FLAT;
+ case ROUND:
+ return HwmfLineCap.ROUND;
+ case SQUARE:
+ return HwmfLineCap.SQUARE;
+ }
+ }
- // A 32-bit unsigned integer that specifies the value in the LineCap enumeration that indicates the line
- // cap used at the start/end of the line to be drawn.
- startCap = EmfPlusLineCapType.valueOf(leis.readInt());
- endCap = EmfPlusLineCapType.valueOf(leis.readInt());
+ @Override
+ public HwmfLineJoin getLineJoin() {
+ switch (join) {
+ default:
+ case BEVEL:
+ return HwmfLineJoin.BEVEL;
+ case ROUND:
+ return HwmfLineJoin.ROUND;
+ case MITER_CLIPPED:
+ case MITER:
+ return HwmfLineJoin.MITER;
+ }
+ }
- // A 32-bit unsigned integer that specifies the value in the LineJoin enumeration, which specifies how
- // to join two lines that are drawn by the same pen and whose ends meet. At the intersection of the two
- // line ends, a line join makes the connection look more continuous.
- join = EmfPlusLineJoin.valueOf(leis.readInt());
+ @Override
+ public HwmfLineDash getLineDash() {
+ return dashedLineData == null ? HwmfLineDash.SOLID : HwmfLineDash.USERSTYLE;
+ }
- // A 32-bit floating-point value that contains the limit of the thickness of the join on a mitered corner
- // by setting the maximum allowed ratio of miter length to line width.
- mitterLimit = leis.readFloat();
-
- // A 32-bit floating-point value that specifies the amount by which to scale the custom line cap with
- // respect to the width of the EmfPlusPen object that is used to draw the lines.
- widthScale = leis.readFloat();
-
- int size = 8* LittleEndianConsts.INT_SIZE;
-
- // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
- size += readPointF(leis, fillHotSpot);
- size += readPointF(leis, lineHotSpot);
-
- if (FILL_PATH.isSet(dataFlags)) {
- fillPath = new EmfPlusPath();
- size += fillPath.init(leis, -1, null, -1);
+ @Override
+ public float[] getLineDashes() {
+ return dashedLineData;
}
- if (LINE_PATH.isSet(dataFlags)) {
- outlinePath = new EmfPlusPath();
- size += outlinePath.init(leis, -1, null, -1);
+ @Override
+ public boolean isAlternateDash() {
+ return (getLineDash() != HwmfLineDash.SOLID && dashOffset != null && dashOffset == 0);
}
- return size;
- }
+ @Override
+ public boolean isGeometric() {
+ return (unitType == EmfPlusUnitType.World || unitType == EmfPlusUnitType.Display);
+ }
+ });
}
+ }
- public static class EmfPlusAdjustableArrowCap implements EmfPlusCustomLineCap {
- private double width;
- private double height;
- private double middleInset;
- private boolean isFilled;
- private EmfPlusLineCapType startCap;
- private EmfPlusLineCapType endCap;
- private EmfPlusLineJoin join;
- private double mitterLimit;
- private double widthScale;
- private final Point2D fillHotSpot = new Point2D.Double();
- private final Point2D lineHotSpot = new Point2D.Double();
-
- @Override
- public long init(LittleEndianInputStream leis) throws IOException {
- // A 32-bit floating-point value that specifies the width of the arrow cap.
- // The width of the arrow cap is scaled by the width of the EmfPlusPen object that is used to draw the
- // line being capped. For example, when drawing a capped line with a pen that has a width of 5 pixels,
- // and the adjustable arrow cap object has a width of 3, the actual arrow cap is drawn 15 pixels wide.
- width = leis.readFloat();
-
- // A 32-bit floating-point value that specifies the height of the arrow cap.
- // The height of the arrow cap is scaled by the width of the EmfPlusPen object that is used to draw the
- // line being capped. For example, when drawing a capped line with a pen that has a width of 5 pixels,
- // and the adjustable arrow cap object has a height of 3, the actual arrow cap is drawn 15 pixels high.
- height = leis.readFloat();
-
- // A 32-bit floating-point value that specifies the number of pixels between the outline of the arrow
- // cap and the fill of the arrow cap.
- middleInset = leis.readFloat();
-
- // A 32-bit Boolean value that specifies whether the arrow cap is filled.
- // If the arrow cap is not filled, only the outline is drawn.
- isFilled = (leis.readInt() != 0);
+ public static class EmfPlusPathArrowCap implements EmfPlusCustomLineCap {
+ /**
+ * If set, an EmfPlusFillPath object MUST be specified in the OptionalData field of the
+ * EmfPlusCustomLineCapData object for filling the custom line cap.
+ */
+ private static final BitField FILL_PATH = BitFieldFactory.getInstance(0x00000001);
+ /**
+ * If set, an EmfPlusLinePath object MUST be specified in the OptionalData field of the
+ * EmfPlusCustomLineCapData object for outlining the custom line cap.
+ */
+ private static final BitField LINE_PATH = BitFieldFactory.getInstance(0x00000002);
- // A 32-bit unsigned integer that specifies the value in the LineCap enumeration that indicates
- // the line cap to be used at the start/end of the line to be drawn.
- startCap = EmfPlusLineCapType.valueOf(leis.readInt());
- endCap = EmfPlusLineCapType.valueOf(leis.readInt());
- // 32-bit unsigned integer that specifies the value in the LineJoin enumeration that specifies how to
- // join two lines that are drawn by the same pen and whose ends meet. At the intersection of the two
- // line ends, a line join makes the connection look more continuous.
- join = EmfPlusLineJoin.valueOf(leis.readInt());
+ private int dataFlags;
+ private EmfPlusLineCapType baseCap;
+ private double baseInset;
+ private EmfPlusLineCapType startCap;
+ private EmfPlusLineCapType endCap;
+ private EmfPlusLineJoin join;
+ private double mitterLimit;
+ private double widthScale;
+ private final Point2D fillHotSpot = new Point2D.Double();
+ private final Point2D lineHotSpot = new Point2D.Double();
+ private EmfPlusPath fillPath;
+ private EmfPlusPath outlinePath;
+
+ @Override
+ public long init(LittleEndianInputStream leis) throws IOException {
+ // A 32-bit unsigned integer that specifies the data in the OptionalData field.
+ // This value MUST be composed of CustomLineCapData flags
+ dataFlags = leis.readInt();
- // A 32-bit floating-point value that specifies the limit of the thickness of the join on a mitered
- // corner by setting the maximum allowed ratio of miter length to line width.
- mitterLimit = leis.readFloat();
+ // A 32-bit unsigned integer that specifies the value from the LineCap enumeration on which
+ // the custom line cap is based.
+ baseCap = EmfPlusLineCapType.valueOf(leis.readInt());
- // A 32-bit floating-point value that specifies the amount by which to scale an EmfPlusCustomLineCap
- // object with respect to the width of the graphics pen that is used to draw the lines.
- widthScale = leis.readFloat();
+ // A 32-bit floating-point value that specifies the distance between the
+ // beginning of the line cap and the end of the line.
+ baseInset = leis.readFloat();
- int size = 9 * LittleEndianConsts.INT_SIZE;
+ // A 32-bit unsigned integer that specifies the value in the LineCap enumeration that indicates the line
+ // cap used at the start/end of the line to be drawn.
+ startCap = EmfPlusLineCapType.valueOf(leis.readInt());
+ endCap = EmfPlusLineCapType.valueOf(leis.readInt());
- // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
- size += readPointF(leis, fillHotSpot);
+ // A 32-bit unsigned integer that specifies the value in the LineJoin enumeration, which specifies how
+ // to join two lines that are drawn by the same pen and whose ends meet. At the intersection of the two
+ // line ends, a line join makes the connection look more continuous.
+ join = EmfPlusLineJoin.valueOf(leis.readInt());
- // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
- size += readPointF(leis, lineHotSpot);
+ // A 32-bit floating-point value that contains the limit of the thickness of the join on a mitered corner
+ // by setting the maximum allowed ratio of miter length to line width.
+ mitterLimit = leis.readFloat();
- return size;
+ // A 32-bit floating-point value that specifies the amount by which to scale the custom line cap with
+ // respect to the width of the EmfPlusPen object that is used to draw the lines.
+ widthScale = leis.readFloat();
+
+ int size = 8* LittleEndianConsts.INT_SIZE;
+
+ // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
+ size += readPointF(leis, fillHotSpot);
+ size += readPointF(leis, lineHotSpot);
+
+ if (FILL_PATH.isSet(dataFlags)) {
+ fillPath = new EmfPlusPath();
+ size += fillPath.init(leis, -1, null, -1);
}
+
+ if (LINE_PATH.isSet(dataFlags)) {
+ outlinePath = new EmfPlusPath();
+ size += outlinePath.init(leis, -1, null, -1);
+ }
+
+ return size;
}
+ }
+
+ public static class EmfPlusAdjustableArrowCap implements EmfPlusCustomLineCap {
+ private double width;
+ private double height;
+ private double middleInset;
+ private boolean isFilled;
+ private EmfPlusLineCapType startCap;
+ private EmfPlusLineCapType endCap;
+ private EmfPlusLineJoin join;
+ private double mitterLimit;
+ private double widthScale;
+ private final Point2D fillHotSpot = new Point2D.Double();
+ private final Point2D lineHotSpot = new Point2D.Double();
+
+ @Override
+ public long init(LittleEndianInputStream leis) throws IOException {
+ // A 32-bit floating-point value that specifies the width of the arrow cap.
+ // The width of the arrow cap is scaled by the width of the EmfPlusPen object that is used to draw the
+ // line being capped. For example, when drawing a capped line with a pen that has a width of 5 pixels,
+ // and the adjustable arrow cap object has a width of 3, the actual arrow cap is drawn 15 pixels wide.
+ width = leis.readFloat();
+
+ // A 32-bit floating-point value that specifies the height of the arrow cap.
+ // The height of the arrow cap is scaled by the width of the EmfPlusPen object that is used to draw the
+ // line being capped. For example, when drawing a capped line with a pen that has a width of 5 pixels,
+ // and the adjustable arrow cap object has a height of 3, the actual arrow cap is drawn 15 pixels high.
+ height = leis.readFloat();
+
+ // A 32-bit floating-point value that specifies the number of pixels between the outline of the arrow
+ // cap and the fill of the arrow cap.
+ middleInset = leis.readFloat();
+
+ // A 32-bit Boolean value that specifies whether the arrow cap is filled.
+ // If the arrow cap is not filled, only the outline is drawn.
+ isFilled = (leis.readInt() != 0);
+
+ // A 32-bit unsigned integer that specifies the value in the LineCap enumeration that indicates
+ // the line cap to be used at the start/end of the line to be drawn.
+ startCap = EmfPlusLineCapType.valueOf(leis.readInt());
+ endCap = EmfPlusLineCapType.valueOf(leis.readInt());
+
+ // 32-bit unsigned integer that specifies the value in the LineJoin enumeration that specifies how to
+ // join two lines that are drawn by the same pen and whose ends meet. At the intersection of the two
+ // line ends, a line join makes the connection look more continuous.
+ join = EmfPlusLineJoin.valueOf(leis.readInt());
+
+ // A 32-bit floating-point value that specifies the limit of the thickness of the join on a mitered
+ // corner by setting the maximum allowed ratio of miter length to line width.
+ mitterLimit = leis.readFloat();
+
+ // A 32-bit floating-point value that specifies the amount by which to scale an EmfPlusCustomLineCap
+ // object with respect to the width of the graphics pen that is used to draw the lines.
+ widthScale = leis.readFloat();
+ int size = 9 * LittleEndianConsts.INT_SIZE;
+
+ // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
+ size += readPointF(leis, fillHotSpot);
+
+ // An EmfPlusPointF object that is not currently used. It MUST be set to {0.0, 0.0}.
+ size += readPointF(leis, lineHotSpot);
+
+ return size;
+ }
}
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java Thu Jun 6 22:32:41 2019
@@ -20,7 +20,7 @@ package org.apache.poi.hemf.record.emfpl
import java.io.IOException;
-import org.apache.poi.hemf.record.emf.HemfRecordType;
+import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInputStream;
@@ -45,4 +45,13 @@ public interface HemfPlusRecord {
*/
long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException;
+
+
+ /**
+ * Draws the record, the default redirects to the parent WMF record drawing
+ * @param ctx the drawing context
+ */
+ default void draw(HemfGraphics ctx) {
+ }
+
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRegion.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRegion.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRegion.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRegion.java Thu Jun 6 22:32:41 2019
@@ -21,9 +21,11 @@ import static org.apache.poi.hemf.record
import java.awt.geom.Rectangle2D;
import java.io.IOException;
+import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
@@ -92,12 +94,12 @@ public class HemfPlusRegion {
public static class EmfPlusRegion implements EmfPlusObjectData {
- private final EmfPlusGraphicsVersion version = new EmfPlusGraphicsVersion();
+ private final EmfPlusGraphicsVersion graphicsVersion = new EmfPlusGraphicsVersion();
private EmfPlusRegionNodeData regionNode;
@Override
public long init(LittleEndianInputStream leis, long dataSize, EmfPlusObjectType objectType, int flags) throws IOException {
- long size = version.init(leis);
+ long size = graphicsVersion.init(leis);
// A 32-bit unsigned integer that specifies the number of child nodes in the RegionNode field.
int nodeCount = leis.readInt();
@@ -111,7 +113,15 @@ public class HemfPlusRegion {
return size;
}
+ @Override
+ public void applyObject(HemfGraphics ctx, List<? extends EmfPlusObjectData> continuedObjectData) {
+
+ }
+ @Override
+ public EmfPlusGraphicsVersion getGraphicsVersion() {
+ return graphicsVersion;
+ }
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfEmbeddedIterator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfEmbeddedIterator.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfEmbeddedIterator.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfEmbeddedIterator.java Thu Jun 6 22:32:41 2019
@@ -267,36 +267,7 @@ public class HemfEmbeddedIterator implem
* Compress GDIs internal format to something useful
*/
private void compressGDIBitmap(EmfPlusImage img, HwmfEmbedded emb, HwmfEmbeddedType et) {
- final int width = img.getBitmapWidth();
- final int height = img.getBitmapHeight();
- final int stride = img.getBitmapStride();
- final EmfPlusPixelFormat pf = img.getPixelFormat();
-
- int[] nBits, bOffs;
- switch (pf) {
- case ARGB_32BPP:
- nBits = new int[]{8, 8, 8, 8};
- bOffs = new int[]{2, 1, 0, 3};
- break;
- case RGB_24BPP:
- nBits = new int[]{8, 8, 8};
- bOffs = new int[]{2, 1, 0};
- break;
- default:
- throw new RuntimeException("not yet implemented");
- }
-
- ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- ComponentColorModel cm = new ComponentColorModel
- (cs, nBits, pf.isAlpha(), pf.isPreMultiplied(), Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
- PixelInterleavedSampleModel csm =
- new PixelInterleavedSampleModel(cm.getTransferType(), width, height, cm.getNumColorComponents(), stride, bOffs);
-
- byte d[] = emb.getRawData();
- WritableRaster raster = (WritableRaster) Raster.createRaster(csm, new DataBufferByte(d, d.length), null);
-
- BufferedImage bi = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
-
+ BufferedImage bi = img.readGDIImage(emb.getRawData());
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// use HwmfEmbeddedType literal for conversion
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java Thu Jun 6 22:32:41 2019
@@ -46,7 +46,6 @@ import org.apache.poi.util.Units;
*/
@Internal
public class HemfPicture implements Iterable<HemfRecord> {
-
private final LittleEndianInputStream stream;
private final List<HemfRecord> records = new ArrayList<>();
private boolean isParsed = false;
@@ -96,32 +95,52 @@ public class HemfPicture implements Iter
}
/**
- * Return the image size in points
+ * Returns the bounding box in device-independent units. Usually this is taken from the placeable header.
*
- * @return the image size in points
+ * @return the bounding box
*/
- public Dimension2D getSize() {
+ public Rectangle2D getBounds() {
HemfHeader header = (HemfHeader)getRecords().get(0);
- final double coeff = (double) Units.EMU_PER_CENTIMETER / Units.EMU_PER_POINT / 10.;
Rectangle2D dim = header.getFrameRectangle();
+ double x = dim.getX(), y = dim.getY();
double width = dim.getWidth(), height = dim.getHeight();
- if (dim.isEmpty() || Math.rint(width*coeff) == 0 || Math.rint(height*coeff) == 0) {
+ if (dim.isEmpty() || Math.rint(width) == 0 || Math.rint(height) == 0) {
for (HemfRecord r : getRecords()) {
if (r instanceof HemfWindowing.EmfSetWindowExtEx) {
- Dimension2D d = ((HemfWindowing.EmfSetWindowExtEx)r).getSize();
+ HemfWindowing.EmfSetWindowExtEx extEx = (HemfWindowing.EmfSetWindowExtEx)r;
+ Dimension2D d = extEx.getSize();
width = d.getWidth();
height = d.getHeight();
// keep searching - sometimes there's another record
}
+ if (r instanceof HemfWindowing.EmfSetWindowOrgEx) {
+ HemfWindowing.EmfSetWindowOrgEx orgEx = (HemfWindowing.EmfSetWindowOrgEx)r;
+ x = orgEx.getX();
+ y = orgEx.getY();
+ }
}
}
- if (Math.rint(width*coeff) == 0 || Math.rint(height*coeff) == 0) {
- width = 100;
- height = 100;
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+
+ /**
+ * Return the image size in points
+ *
+ * @return the image size in points
+ */
+ public Dimension2D getSize() {
+ final Rectangle2D bounds = getBounds();
+
+ if (bounds.isEmpty()) {
+ return new Dimension2DDouble(100,100);
}
- return new Dimension2DDouble(Math.abs(width*coeff), Math.abs(height*coeff));
+ final double coeff = (double) Units.EMU_PER_CENTIMETER / Units.EMU_PER_POINT / 10.;
+ double width = Math.abs(bounds.getWidth()*coeff);
+ double height = Math.abs(bounds.getHeight()*coeff);
+
+ return new Dimension2DDouble(width, height);
}
private static double minX(Rectangle2D bounds) {
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java Thu Jun 6 22:32:41 2019
@@ -17,8 +17,10 @@
package org.apache.poi.hwmf.draw;
+import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
+import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Paint;
@@ -132,6 +134,9 @@ public class HwmfGraphics {
public void fill(Shape shape) {
HwmfDrawProperties prop = getProperties();
+
+ Composite old = graphicsCtx.getComposite();
+ graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
if (prop.getBrushStyle() != HwmfBrushStyle.BS_NULL) {
if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
graphicsCtx.setPaint(prop.getBackgroundColor().getColor());
@@ -141,20 +146,22 @@ public class HwmfGraphics {
graphicsCtx.setPaint(getFill());
graphicsCtx.fill(shape);
}
+ graphicsCtx.setComposite(old);
draw(shape);
}
protected BasicStroke getStroke() {
+ HwmfDrawProperties prop = getProperties();
+ HwmfPenStyle ps = prop.getPenStyle();
// TODO: fix line width calculation
- float width = (float)getProperties().getPenWidth();
+ float width = (float)prop.getPenWidth();
if (width == 0) {
width = 1;
}
- HwmfPenStyle ps = getProperties().getPenStyle();
int cap = ps.getLineCap().awtFlag;
int join = ps.getLineJoin().awtFlag;
- float miterLimit = (float)getProperties().getPenMiterLimit();
+ float miterLimit = (float)prop.getPenMiterLimit();
float[] dashes = ps.getLineDashes();
boolean dashAlt = ps.isAlternateDash();
// This value is not an integer index into the dash pattern array.
@@ -602,7 +609,14 @@ public class HwmfGraphics {
graphicsCtx.scale(dstBounds.getWidth()/srcBounds2.getWidth(), dstBounds.getHeight()/srcBounds2.getHeight());
graphicsCtx.translate(-srcBounds2.getX(), -srcBounds2.getY());
- graphicsCtx.drawImage(img, 0, 0, prop.getBackgroundColor().getColor(), null);
+ if (prop.getBkMode() == HwmfBkMode.OPAQUE) {
+ graphicsCtx.drawImage(img, 0, 0, prop.getBackgroundColor().getColor(), null);
+ } else {
+ Composite old = graphicsCtx.getComposite();
+ graphicsCtx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+ graphicsCtx.drawImage(img, 0, 0, null);
+ graphicsCtx.setComposite(old);
+ }
graphicsCtx.setTransform(at);
graphicsCtx.setClip(clip);
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java Thu Jun 6 22:32:41 2019
@@ -18,6 +18,7 @@
package org.apache.poi.hwmf.record;
import java.awt.Shape;
+import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Dimension2D;
@@ -749,17 +750,17 @@ public class HwmfDraw {
@Internal
public static String pointToString(Point2D point) {
- return "{ x: "+point.getX()+", y: "+point.getY()+" }";
+ return (point == null) ? "null" : "{ x: "+point.getX()+", y: "+point.getY()+" }";
}
@Internal
public static String boundsToString(Rectangle2D bounds) {
- return "{ x: "+bounds.getX()+", y: "+bounds.getY()+", w: "+bounds.getWidth()+", h: "+bounds.getHeight()+" }";
+ return (bounds == null) ? "null" : "{ x: "+bounds.getX()+", y: "+bounds.getY()+", w: "+bounds.getWidth()+", h: "+bounds.getHeight()+" }";
}
@Internal
public static String dimToString(Dimension2D dim) {
- return "{ w: "+dim.getWidth()+", h: "+dim.getHeight()+" }";
+ return (dim == null) ? "null" : "{ w: "+dim.getWidth()+", h: "+dim.getHeight()+" }";
}
@Internal
@@ -772,5 +773,4 @@ public class HwmfDraw {
Math.abs(bounds.getHeight())
);
}
-
}
Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hemf/usermodel/HemfPictureTest.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hemf/usermodel/HemfPictureTest.java?rev=1860732&r1=1860731&r2=1860732&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hemf/usermodel/HemfPictureTest.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hemf/usermodel/HemfPictureTest.java Thu Jun 6 22:32:41 2019
@@ -24,22 +24,14 @@ import static org.junit.Assert.assertNot
import static org.junit.Assert.assertTrue;
import java.awt.geom.Point2D;
-import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.stream.Stream;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hemf.record.emf.HemfComment;
@@ -64,11 +56,10 @@ public class HemfPictureTest {
private static final POIDataSamples ss_samples = POIDataSamples.getSpreadSheetInstance();
private static final POIDataSamples sl_samples = POIDataSamples.getSlideShowInstance();
- /*
- @Test
+/* @Test
@Ignore("Only for manual tests - need to add org.tukaani:xz:1.8 for this to work")
public void paint() throws IOException {
- byte buf[] = new byte[50_000_000];
+ final byte buf[] = new byte[50_000_000];
// good test samples to validate rendering:
// emfs/commoncrawl2/NB/NBWN2YH5VFCLZRFDQU7PB7IDD4UKY7DN_2.emf
@@ -78,15 +69,16 @@ public class HemfPictureTest {
final boolean writeLog = false;
final boolean dumpRecords = false;
- final boolean savePng = false;
- final boolean dumpEmbedded = true;
+ final boolean savePng = true;
+ final boolean dumpEmbedded = false;
Set<String> passed = new HashSet<>();
- try (BufferedWriter sucWrite = parseEmfLog(passed, "emf-success.txt");
- BufferedWriter parseError = parseEmfLog(passed, "emf-parse.txt");
- BufferedWriter renderError = parseEmfLog(passed, "emf-render.txt");
- SevenZFile sevenZFile = new SevenZFile(new File("tmp/plus_emf.7z"))) {
+ try (BufferedWriter sucWrite = parseEmfLog(passed, "emf-success.txt")
+ ;BufferedWriter parseError = parseEmfLog(passed, "emf-parse.txt")
+ ;BufferedWriter renderError = parseEmfLog(passed, "emf-render.txt")
+ ;SevenZFile sevenZFile = new SevenZFile(new File("tmp/plus_emf.7z"))
+ ) {
for (int idx=0;;idx++) {
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
if (entry == null) break;
@@ -94,10 +86,14 @@ public class HemfPictureTest {
if (entry.isDirectory() || !etName.endsWith(".emf") || passed.contains(etName)) continue;
- // if (!etName.equals("emfs/commoncrawl2/2S/2SYMYPLNJURGCXJKLNZCJQGIBHVMQTRS_0.emf")) continue;
- // emfs/commoncrawl2/ZJ/ZJT2BZPLQR7DKSKYLYL6GRDEUM2KIO5F_4.emf
- // emfs/govdocs1/005/005203.ppt_3.emf
+ // KEEDHN6XES4EKK52E3AJHKCARNTQF7PO_0.emf takes ages, time is spent while drawing paths
+// if (!etName.contains("KEEDHN6XES4EKK52E3AJHKCARNTQF7PO_0.emf")) continue;
+
+ // F7GK5XOLERFURVTQALOCX3GJ6FH45LNQ strange colors
+ // ISS3ANIX2PL4PXR7SZSJSPBZI7YQQE3U stroke wrong
+// if (!etName.contains("ISS3ANIX2PL4PXR7SZSJSPBZI7YQQE3U")) continue;
+
System.out.println(etName);
@@ -129,9 +125,9 @@ public class HemfPictureTest {
int embIdx = 0;
for (HwmfEmbedded emb : emf.getEmbeddings()) {
final File embName = new File("build/tmp", "emb_"+etName.replaceFirst(".+/", "").replace(".emf", "_"+embIdx + emb.getEmbeddedType().extension) );
-// try (FileOutputStream fos = new FileOutputStream(embName)) {
-// fos.write(emb.getRawData());
-// }
+ try (FileOutputStream fos = new FileOutputStream(embName)) {
+ fos.write(emb.getRawData());
+ }
embIdx++;
}
}
@@ -154,17 +150,19 @@ public class HemfPictureTest {
BufferedImage bufImg = new BufferedImage((int)width, (int)height, BufferedImage.TYPE_INT_ARGB);
g = bufImg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
- g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
+ g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.setComposite(AlphaComposite.Clear);
g.fillRect(0, 0, (int)width, (int)height);
g.setComposite(AlphaComposite.Src);
+ final File pngName = new File("build/tmp", etName.replaceFirst(".+/", "").replace(".emf", ".png"));
+
emf.draw(g, new Rectangle2D.Double(0, 0, width, height));
- final File pngName = new File("build/tmp", etName.replaceFirst(".+/", "").replace(".emf", ".png"));
if (savePng) {
ImageIO.write(bufImg, "PNG", pngName);
}
@@ -186,7 +184,7 @@ public class HemfPictureTest {
}
}
}
- } */
+ }
private static int hashException(Throwable e) {
StringBuilder sb = new StringBuilder();
@@ -222,7 +220,7 @@ public class HemfPictureTest {
}
return Files.newBufferedWriter(log, StandardCharsets.UTF_8, soo);
- }
+ }*/
@Test
public void testBasicWindows() throws Exception {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org