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 2018/09/14 21:37:38 UTC

svn commit: r1840956 [3/5] - in /poi/branches/hemf/src: java/org/apache/poi/util/ ooxml/java/org/apache/poi/xdgf/geom/ ooxml/java/org/apache/poi/xdgf/usermodel/ ooxml/java/org/apache/poi/xdgf/util/ scratchpad/src/org/apache/poi/hemf/draw/ scratchpad/sr...

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfRecordType.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfRecordType.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfRecordType.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfRecordType.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfRecordType.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfRecordType.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfRecordType.java Fri Sep 14 21:37:37 2018
@@ -15,139 +15,145 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.record;
+package org.apache.poi.hemf.record.emf;
+
+import java.util.function.Supplier;
 
 import org.apache.poi.util.Internal;
 
 @Internal
 public enum HemfRecordType {
 
-    header(0x00000001, UnimplementedHemfRecord.class),
-    polybeizer(0x00000002, UnimplementedHemfRecord.class),
-    polygon(0x00000003, UnimplementedHemfRecord.class),
-    polyline(0x00000004, UnimplementedHemfRecord.class),
-    polybezierto(0x00000005, UnimplementedHemfRecord.class),
-    polylineto(0x00000006, UnimplementedHemfRecord.class),
-    polypolyline(0x00000007, UnimplementedHemfRecord.class),
-    polypolygon(0x00000008, UnimplementedHemfRecord.class),
-    setwindowextex(0x00000009, UnimplementedHemfRecord.class),
-    setwindoworgex(0x0000000A, UnimplementedHemfRecord.class),
-    setviewportextex(0x0000000B, UnimplementedHemfRecord.class),
-    setviewportorgex(0x0000000C, UnimplementedHemfRecord.class),
-    setbrushorgex(0x0000000D, UnimplementedHemfRecord.class),
-    eof(0x0000000E, UnimplementedHemfRecord.class),
-    setpixelv(0x0000000F, UnimplementedHemfRecord.class),
-    setmapperflags(0x00000010, UnimplementedHemfRecord.class),
-    setmapmode(0x00000011, UnimplementedHemfRecord.class),
-    setbkmode(0x00000012, UnimplementedHemfRecord.class),
-    setpolyfillmode(0x00000013, UnimplementedHemfRecord.class),
-    setrop2(0x00000014, UnimplementedHemfRecord.class),
-    setstretchbltmode(0x00000015, UnimplementedHemfRecord.class),
-    settextalign(0x00000016, HemfText.SetTextAlign.class),
-    setcoloradjustment(0x00000017, UnimplementedHemfRecord.class),
-    settextcolor(0x00000018, HemfText.SetTextColor.class),
-    setbkcolor(0x00000019, UnimplementedHemfRecord.class),
-    setoffsetcliprgn(0x0000001A, UnimplementedHemfRecord.class),
-    setmovetoex(0x0000001B, UnimplementedHemfRecord.class),
-    setmetargn(0x0000001C, UnimplementedHemfRecord.class),
-    setexcludecliprect(0x0000001D, UnimplementedHemfRecord.class),
-    setintersectcliprect(0x0000001E, UnimplementedHemfRecord.class),
-    scaleviewportextex(0x0000001F, UnimplementedHemfRecord.class),
-    scalewindowextex(0x00000020, UnimplementedHemfRecord.class),
-    savedc(0x00000021, UnimplementedHemfRecord.class),
-    restoredc(0x00000022, UnimplementedHemfRecord.class),
-    setworldtransform(0x00000023, UnimplementedHemfRecord.class),
-    modifyworldtransform(0x00000024, UnimplementedHemfRecord.class),
-    selectobject(0x00000025, UnimplementedHemfRecord.class),
-    createpen(0x00000026, UnimplementedHemfRecord.class),
-    createbrushindirect(0x00000027, UnimplementedHemfRecord.class),
-    deleteobject(0x00000028, UnimplementedHemfRecord.class),
-    anglearc(0x00000029, UnimplementedHemfRecord.class),
-    ellipse(0x0000002A, UnimplementedHemfRecord.class),
-    rectangle(0x0000002B, UnimplementedHemfRecord.class),
-    roundirect(0x0000002C, UnimplementedHemfRecord.class),
-    arc(0x0000002D, UnimplementedHemfRecord.class),
-    chord(0x0000002E, UnimplementedHemfRecord.class),
-    pie(0x0000002F, UnimplementedHemfRecord.class),
-    selectpalette(0x00000030, UnimplementedHemfRecord.class),
-    createpalette(0x00000031, UnimplementedHemfRecord.class),
-    setpaletteentries(0x00000032, UnimplementedHemfRecord.class),
-    resizepalette(0x00000033, UnimplementedHemfRecord.class),
-    realizepalette(0x0000034, UnimplementedHemfRecord.class),
-    extfloodfill(0x00000035, UnimplementedHemfRecord.class),
-    lineto(0x00000036, UnimplementedHemfRecord.class),
-    arcto(0x00000037, UnimplementedHemfRecord.class),
-    polydraw(0x00000038, UnimplementedHemfRecord.class),
-    setarcdirection(0x00000039, UnimplementedHemfRecord.class),
-    setmiterlimit(0x0000003A, UnimplementedHemfRecord.class),
-    beginpath(0x0000003B, UnimplementedHemfRecord.class),
-    endpath(0x0000003C, UnimplementedHemfRecord.class),
-    closefigure(0x0000003D, UnimplementedHemfRecord.class),
-    fillpath(0x0000003E, UnimplementedHemfRecord.class),
-    strokeandfillpath(0x0000003F, UnimplementedHemfRecord.class),
-    strokepath(0x00000040, UnimplementedHemfRecord.class),
-    flattenpath(0x00000041, UnimplementedHemfRecord.class),
-    widenpath(0x00000042, UnimplementedHemfRecord.class),
-    selectclippath(0x00000043, UnimplementedHemfRecord.class),
-    abortpath(0x00000044, UnimplementedHemfRecord.class), //no 45?!
-    comment(0x00000046, HemfCommentRecord.class),
-    fillrgn(0x00000047, UnimplementedHemfRecord.class),
-    framergn(0x00000048, UnimplementedHemfRecord.class),
-    invertrgn(0x00000049, UnimplementedHemfRecord.class),
-    paintrgn(0x0000004A, UnimplementedHemfRecord.class),
-    extselectciprrgn(0x0000004B, UnimplementedHemfRecord.class),
-    bitblt(0x0000004C, UnimplementedHemfRecord.class),
-    stretchblt(0x0000004D, UnimplementedHemfRecord.class),
-    maskblt(0x0000004E, UnimplementedHemfRecord.class),
-    plgblt(0x0000004F, UnimplementedHemfRecord.class),
-    setbitstodevice(0x00000050, UnimplementedHemfRecord.class),
-    stretchdibits(0x00000051, UnimplementedHemfRecord.class),
-    extcreatefontindirectw(0x00000052, HemfText.ExtCreateFontIndirectW.class),
-    exttextouta(0x00000053, HemfText.ExtTextOutA.class),
-    exttextoutw(0x00000054, HemfText.ExtTextOutW.class),
-    polybezier16(0x00000055, UnimplementedHemfRecord.class),
-    polygon16(0x00000056, UnimplementedHemfRecord.class),
-    polyline16(0x00000057, UnimplementedHemfRecord.class),
-    polybezierto16(0x00000058, UnimplementedHemfRecord.class),
-    polylineto16(0x00000059, UnimplementedHemfRecord.class),
-    polypolyline16(0x0000005A, UnimplementedHemfRecord.class),
-    polypolygon16(0x0000005B, UnimplementedHemfRecord.class),
-    polydraw16(0x0000005C, UnimplementedHemfRecord.class),
-    createmonobrush16(0x0000005D, UnimplementedHemfRecord.class),
-    createdibpatternbrushpt(0x0000005E, UnimplementedHemfRecord.class),
-    extcreatepen(0x0000005F, UnimplementedHemfRecord.class),
-    polytextouta(0x00000060, HemfText.PolyTextOutA.class),
-    polytextoutw(0x00000061, HemfText.PolyTextOutW.class),
-    seticmmode(0x00000062, UnimplementedHemfRecord.class),
-    createcolorspace(0x00000063, UnimplementedHemfRecord.class),
-    setcolorspace(0x00000064, UnimplementedHemfRecord.class),
-    deletecolorspace(0x00000065, UnimplementedHemfRecord.class),
-    glsrecord(0x00000066, UnimplementedHemfRecord.class),
-    glsboundedrecord(0x00000067, UnimplementedHemfRecord.class),
-    pixelformat(0x00000068, UnimplementedHemfRecord.class),
-    drawescape(0x00000069, UnimplementedHemfRecord.class),
-    extescape(0x0000006A, UnimplementedHemfRecord.class),//no 6b?!
-    smalltextout(0x0000006C, UnimplementedHemfRecord.class),
-    forceufimapping(0x0000006D, UnimplementedHemfRecord.class),
-    namedescape(0x0000006E, UnimplementedHemfRecord.class),
-    colorcorrectpalette(0x0000006F, UnimplementedHemfRecord.class),
-    seticmprofilea(0x00000070, UnimplementedHemfRecord.class),
-    seticmprofilew(0x00000071, UnimplementedHemfRecord.class),
-    alphablend(0x00000072, UnimplementedHemfRecord.class),
-    setlayout(0x00000073, UnimplementedHemfRecord.class),
-    transparentblt(0x00000074, UnimplementedHemfRecord.class),
-    gradientfill(0x00000076, UnimplementedHemfRecord.class), //no 75?!
-    setlinkdufis(0x00000077, UnimplementedHemfRecord.class),
-    settextjustification(0x00000078, HemfText.SetTextJustification.class),
-    colormatchtargetw(0x00000079, UnimplementedHemfRecord.class),
-    createcolorspacew(0x0000007A, UnimplementedHemfRecord.class);
+    header(0x00000001, HemfHeader::new),
+    polyBezier(0x00000002, HemfDraw.EmfPolyBezier::new),
+    polygon(0x00000003, HemfDraw.EmfPolygon::new),
+    polyline(0x00000004, HemfDraw.EmfPolyline::new),
+    polyBezierTo(0x00000005, HemfDraw.EmfPolyBezierTo::new),
+    polylineTo(0x00000006, HemfDraw.EmfPolylineTo::new),
+    polyPolyline(0x00000007, HemfDraw.EmfPolyPolyline::new),
+    polyPolygon(0x00000008, HemfDraw.EmfPolyPolygon::new),
+    setWindowExtEx(0x00000009, HemfWindowing.EmfSetWindowExtEx::new),
+    setWindowOrgEx(0x0000000A, HemfWindowing.EmfSetWindowOrgEx::new),
+    setViewportExtEx(0x0000000B, HemfWindowing.EmfSetViewportExtEx::new),
+    setViewportOrgEx(0x0000000C, HemfWindowing.EmfSetViewportOrgEx::new),
+    setbrushorgex(0x0000000D, UnimplementedHemfRecord::new),
+    eof(0x0000000E, HemfMisc.EmfEof::new),
+    setPixelV(0x0000000F, HemfDraw.EmfSetPixelV::new),
+    setMapperFlags(0x00000010, HemfMisc.EmfSetMapperFlags::new),
+    setMapMode(0x00000011, HemfMisc.EmfSetMapMode::new),
+    setBkMode(0x00000012, HemfMisc.EmfSetBkMode::new),
+    setPolyfillMode(0x00000013, HemfFill.EmfSetPolyfillMode::new),
+    setRop2(0x00000014, HemfMisc.EmfSetRop2::new),
+    setStretchBltMode(0x00000015, HemfMisc.EmfSetStretchBltMode::new),
+    setTextAlign(0x00000016, HemfText.EmfSetTextAlign::new),
+    setcoloradjustment(0x00000017, UnimplementedHemfRecord::new),
+    setTextColor(0x00000018, HemfText.SetTextColor::new),
+    setBkColor(0x00000019, HemfMisc.EmfSetBkColor::new),
+    setOffsetClipRgn(0x0000001A, HemfWindowing.EmfSetOffsetClipRgn::new),
+    setMoveToEx(0x0000001B, HemfDraw.EmfSetMoveToEx::new),
+    setmetargn(0x0000001C, UnimplementedHemfRecord::new),
+    setExcludeClipRect(0x0000001D, HemfWindowing.EmfSetExcludeClipRect::new),
+    setIntersectClipRect(0x0000001E, HemfWindowing.EmfSetIntersectClipRect::new),
+    scaleViewportExtEx(0x0000001F, HemfWindowing.EmfScaleViewportExtEx::new),
+    scaleWindowExtEx(0x00000020, HemfWindowing.EmfScaleWindowExtEx::new),
+    saveDc(0x00000021, HemfMisc.EmfSaveDc::new),
+    restoreDc(0x00000022, HemfMisc.EmfRestoreDc::new),
+    setworldtransform(0x00000023, UnimplementedHemfRecord::new),
+    modifyworldtransform(0x00000024, UnimplementedHemfRecord::new),
+    selectObject(0x00000025, HemfDraw.EmfSelectObject::new),
+    createPen(0x00000026, HemfMisc.EmfCreatePen::new),
+    createBrushIndirect(0x00000027, HemfMisc.EmfCreateBrushIndirect::new),
+    deleteobject(0x00000028, HemfMisc.EmfDeleteObject::new),
+    anglearc(0x00000029, UnimplementedHemfRecord::new),
+    ellipse(0x0000002A, HemfDraw.EmfEllipse::new),
+    rectangle(0x0000002B, HemfDraw.EmfRectangle::new),
+    roundRect(0x0000002C, HemfDraw.EmfRoundRect::new),
+    arc(0x0000002D, HemfDraw.EmfArc::new),
+    chord(0x0000002E, HemfDraw.EmfChord::new),
+    pie(0x0000002F, HemfDraw.EmfPie::new),
+    selectPalette(0x00000030, HemfPalette.EmfSelectPalette::new),
+    createPalette(0x00000031, HemfPalette.EmfCreatePalette::new),
+    setPaletteEntries(0x00000032, HemfPalette.EmfSetPaletteEntries::new),
+    resizePalette(0x00000033, HemfPalette.EmfResizePalette::new),
+    realizePalette(0x0000034, HemfPalette.EmfRealizePalette::new),
+    extFloodFill(0x00000035, HemfFill.EmfExtFloodFill::new),
+    lineTo(0x00000036, HemfDraw.EmfLineTo::new),
+    arcTo(0x00000037, HemfDraw.EmfArcTo::new),
+    polyDraw(0x00000038, HemfDraw.EmfPolyDraw::new),
+    setarcdirection(0x00000039, UnimplementedHemfRecord::new),
+    setMiterLimit(0x0000003A, HemfMisc.EmfSetMiterLimit::new),
+    beginpath(0x0000003B, UnimplementedHemfRecord::new),
+    endpath(0x0000003C, UnimplementedHemfRecord::new),
+    closefigure(0x0000003D, UnimplementedHemfRecord::new),
+    fillpath(0x0000003E, UnimplementedHemfRecord::new),
+    strokeandfillpath(0x0000003F, UnimplementedHemfRecord::new),
+    strokepath(0x00000040, UnimplementedHemfRecord::new),
+    flattenpath(0x00000041, UnimplementedHemfRecord::new),
+    widenpath(0x00000042, UnimplementedHemfRecord::new),
+    selectclippath(0x00000043, UnimplementedHemfRecord::new),
+    abortpath(0x00000044, UnimplementedHemfRecord::new),
+    // no 45 ?!
+    comment(0x00000046, HemfComment.EmfComment::new),
+    fillRgn(0x00000047, HemfFill.EmfFillRgn::new),
+    frameRgn(0x00000048, HemfFill.EmfFrameRgn::new),
+    invertRgn(0x00000049, HemfFill.EmfInvertRgn::new),
+    paintRgn(0x0000004A, HemfFill.EmfPaintRgn::new),
+    extSelectClipRgn(0x0000004B, HemfFill.EmfExtSelectClipRgn::new),
+    bitBlt(0x0000004C, HemfFill.EmfBitBlt::new),
+    stretchBlt(0x0000004D, HemfFill.EmfStretchBlt::new),
+    maskblt(0x0000004E, UnimplementedHemfRecord::new),
+    plgblt(0x0000004F, UnimplementedHemfRecord::new),
+    setDiBitsToDevice(0x00000050, HemfFill.EmfSetDiBitsToDevice::new),
+    stretchdibits(0x00000051, UnimplementedHemfRecord::new),
+    extCreateFontIndirectW(0x00000052, HemfText.ExtCreateFontIndirectW::new),
+    exttextouta(0x00000053, HemfText.ExtTextOutA::new),
+    exttextoutw(0x00000054, HemfText.ExtTextOutW::new),
+    polyBezier16(0x00000055, HemfDraw.EmfPolyBezier16::new),
+    polygon16(0x00000056, HemfDraw.EmfPolygon16::new),
+    polyline16(0x00000057, HemfDraw.EmfPolyline16::new),
+    polyBezierTo16(0x00000058, HemfDraw.EmfPolyBezierTo16::new),
+    polylineTo16(0x00000059, HemfDraw.EmfPolylineTo16::new),
+    polyPolyline16(0x0000005A, HemfDraw.EmfPolyPolyline16::new),
+    polyPolygon16(0x0000005B, HemfDraw.EmfPolyPolygon16::new),
+    polyDraw16(0x0000005C, HemfDraw.EmfPolyDraw16::new),
+    createmonobrush16(0x0000005D, UnimplementedHemfRecord::new),
+    createdibpatternbrushpt(0x0000005E, UnimplementedHemfRecord::new),
+    extCreatePen(0x0000005F, HemfMisc.EmfExtCreatePen::new),
+    polytextouta(0x00000060, HemfText.PolyTextOutA::new),
+    polytextoutw(0x00000061, HemfText.PolyTextOutW::new),
+    seticmmode(0x00000062, UnimplementedHemfRecord::new),
+    createcolorspace(0x00000063, UnimplementedHemfRecord::new),
+    setcolorspace(0x00000064, UnimplementedHemfRecord::new),
+    deletecolorspace(0x00000065, UnimplementedHemfRecord::new),
+    glsrecord(0x00000066, UnimplementedHemfRecord::new),
+    glsboundedrecord(0x00000067, UnimplementedHemfRecord::new),
+    pixelformat(0x00000068, UnimplementedHemfRecord::new),
+    drawescape(0x00000069, UnimplementedHemfRecord::new),
+    extescape(0x0000006A, UnimplementedHemfRecord::new),
+    // no 6b ?!
+    smalltextout(0x0000006C, UnimplementedHemfRecord::new),
+    forceufimapping(0x0000006D, UnimplementedHemfRecord::new),
+    namedescape(0x0000006E, UnimplementedHemfRecord::new),
+    colorcorrectpalette(0x0000006F, UnimplementedHemfRecord::new),
+    seticmprofilea(0x00000070, UnimplementedHemfRecord::new),
+    seticmprofilew(0x00000071, UnimplementedHemfRecord::new),
+    alphaBlend(0x00000072, HemfFill.EmfAlphaBlend::new),
+    setlayout(0x00000073, UnimplementedHemfRecord::new),
+    transparentblt(0x00000074, UnimplementedHemfRecord::new),
+    // no 75 ?!
+    gradientfill(0x00000076, UnimplementedHemfRecord::new),
+    setlinkdufis(0x00000077, UnimplementedHemfRecord::new),
+    settextjustification(0x00000078, HemfText.SetTextJustification::new),
+    colormatchtargetw(0x00000079, UnimplementedHemfRecord::new),
+    createcolorspacew(0x0000007A, UnimplementedHemfRecord::new);
+
 
     public final long id;
-    public final Class<? extends HemfRecord> clazz;
+    public final Supplier<? extends HemfRecord> constructor;
 
-    HemfRecordType(long id, Class<? extends HemfRecord> clazz) {
+    HemfRecordType(long id, Supplier<? extends HemfRecord> constructor) {
         this.id = id;
-        this.clazz = clazz;
+        this.constructor = constructor;
     }
 
     public static HemfRecordType getById(long id) {

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfText.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfText.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfText.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/HemfText.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfText.java Fri Sep 14 21:37:37 2018
@@ -15,20 +15,27 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.record;
+package org.apache.poi.hemf.record.emf;
 
 import static java.nio.charset.StandardCharsets.UTF_16LE;
+import static org.apache.poi.hemf.record.emf.HemfDraw.readRectL;
+import static org.apache.poi.hemf.record.emf.HemfDraw.readDimensionFloat;
+import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
 
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
+import java.awt.geom.Dimension2D;
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
 import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
 
+import org.apache.poi.hwmf.record.HwmfColorRef;
+import org.apache.poi.hwmf.record.HwmfText;
+import org.apache.poi.hwmf.record.HwmfText.WmfSetTextAlign;
+import org.apache.poi.util.Dimension2DDouble;
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
 import org.apache.poi.util.LittleEndianInputStream;
 import org.apache.poi.util.RecordFormatException;
 
@@ -42,53 +49,56 @@ public class HemfText {
 
     private static final int MAX_RECORD_LENGTH = 1_000_000;
 
-    public static class ExtCreateFontIndirectW extends UnimplementedHemfRecord {
+    public enum EmfGraphicsMode {
+        GM_COMPATIBLE, GM_ADVANCED
     }
 
     public static class ExtTextOutA implements HemfRecord {
 
-        private long left,top,right,bottom;
+        protected final Rectangle2D boundsIgnored = new Rectangle2D.Double();
 
-        //TODO: translate this to a graphicsmode enum
-        private long graphicsMode;
+        protected EmfGraphicsMode graphicsMode;
 
-        private long exScale;
-        private long eyScale;
-        EmrTextObject textObject;
+        /**
+         * The scale factor to apply along the X/Y axis to convert from page space units to .01mm units.
+         * This SHOULD be used only if the graphics mode specified by iGraphicsMode is GM_COMPATIBLE.
+         */
+        protected final Dimension2D scale = new Dimension2DDouble();
+
+        protected final EmrTextObject textObject;
+
+        public ExtTextOutA() {
+            this(false);
+        }
+
+        protected ExtTextOutA(boolean isUnicode) {
+            textObject = new EmrTextObject(isUnicode);
+        }
 
         @Override
-        public HemfRecordType getRecordType() {
+        public HemfRecordType getEmfRecordType() {
             return HemfRecordType.exttextouta;
         }
 
         @Override
-        public long init(LittleEndianInputStream leis, long recordId, long recordSize) throws IOException {
-            //note that the first 2 uInts have been read off and the recordsize has
-            //been decreased by 8
-            left = leis.readInt();
-            top = leis.readInt();
-            right = leis.readInt();
-            bottom = leis.readInt();
-            graphicsMode = leis.readUInt();
-            exScale = leis.readUInt();
-            eyScale = leis.readUInt();
-
-            int recordSizeInt = -1;
-            if (recordSize < Integer.MAX_VALUE) {
-                recordSizeInt = (int)recordSize;
-            } else {
-                throw new RecordFormatException("can't have text length > Integer.MAX_VALUE");
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            if (recordSize < 0 || Integer.MAX_VALUE <= recordSize) {
+                throw new RecordFormatException("recordSize must be a positive integer (0-0x7FFFFFFF)");
             }
-            //guarantee to read the rest of the EMRTextObjectRecord
-            //emrtextbytes start after 7*4 bytes read above
-            byte[] emrTextBytes = IOUtils.safelyAllocate(recordSizeInt-(7*LittleEndian.INT_SIZE), MAX_RECORD_LENGTH);
-            IOUtils.readFully(leis, emrTextBytes);
-            textObject = new EmrTextObject(emrTextBytes, getEncodingHint(), 20);//should be 28, but recordSizeInt has already subtracted 8
-            return recordSize;
-        }
 
-        protected Charset getEncodingHint() {
-            return null;
+            // A WMF RectL object. It is not used and MUST be ignored on receipt.
+            long size = readRectL(leis, boundsIgnored);
+
+            // A 32-bit unsigned integer that specifies the graphics mode from the GraphicsMode enumeration
+            graphicsMode = EmfGraphicsMode.values()[leis.readInt()-1];
+            size += LittleEndianConsts.INT_SIZE;
+
+            size += readDimensionFloat(leis, scale);
+
+            // guarantee to read the rest of the EMRTextObjectRecord
+            size += textObject.init(leis, recordSize, (int)size);
+
+            return size;
         }
 
         /**
@@ -111,58 +121,28 @@ public class HemfText {
          *
          * @return the x offset for the EmrTextObject
          */
-        public long getX() {
-            return textObject.x;
-        }
-
-        /**
-         *
-         * @return the y offset for the EmrTextObject
-         */
-        public long getY() {
-            return textObject.y;
-        }
-
-        public long getLeft() {
-            return left;
-        }
-
-        public long getTop() {
-            return top;
+        public EmrTextObject getTextObject() {
+            return textObject;
         }
 
-        public long getRight() {
-            return right;
-        }
-
-        public long getBottom() {
-            return bottom;
-        }
-
-        public long getGraphicsMode() {
+        public EmfGraphicsMode getGraphicsMode() {
             return graphicsMode;
         }
 
-        public long getExScale() {
-            return exScale;
-        }
-
-        public long getEyScale() {
-            return eyScale;
+        public Dimension2D getScale() {
+            return scale;
         }
-
     }
 
     public static class ExtTextOutW extends ExtTextOutA {
 
-        @Override
-        public HemfRecordType getRecordType() {
-            return HemfRecordType.exttextoutw;
+        public ExtTextOutW() {
+            super(true);
         }
 
         @Override
-        protected Charset getEncodingHint() {
-            return UTF_16LE;
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.exttextoutw;
         }
 
         public String getText() throws IOException {
@@ -171,92 +151,167 @@ public class HemfText {
     }
 
     /**
-     * Needs to be implemented.  Couldn't find example.
+     * The EMR_SETTEXTALIGN record specifies text alignment.
      */
-    public static class PolyTextOutA extends UnimplementedHemfRecord {
+    public static class EmfSetTextAlign extends WmfSetTextAlign implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setTextAlign;
+        }
 
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            /**
+             * A 32-bit unsigned integer that specifies text alignment by using a mask of text alignment flags.
+             * These are either WMF TextAlignmentMode Flags for text with a horizontal baseline,
+             * or WMF VerticalTextAlignmentMode Flags for text with a vertical baseline.
+             * Only one value can be chosen from those that affect horizontal and vertical alignment.
+             */
+            textAlignmentMode = (int)leis.readUInt();
+            return LittleEndianConsts.INT_SIZE;
+        }
     }
 
     /**
-     * Needs to be implemented.  Couldn't find example.
+     * The EMR_SETTEXTCOLOR record defines the current text color.
      */
-    public static class PolyTextOutW extends UnimplementedHemfRecord {
+    public static class SetTextColor implements HemfRecord {
+        /** A WMF ColorRef object that specifies the text color value. */
+        private final HwmfColorRef colorRef = new HwmfColorRef();
 
-    }
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setTextColor;
+        }
 
-    public static class SetTextAlign extends UnimplementedHemfRecord {
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            return colorRef.init(leis);
+        }
     }
 
-    public static class SetTextColor extends UnimplementedHemfRecord {
-    }
+    public static class EmrTextObject extends HwmfText.WmfExtTextOut {
+        protected final boolean isUnicode;
+        protected final List<Integer> outputDx = new ArrayList<>();
+
+        public EmrTextObject(boolean isUnicode) {
+            super(new EmfExtTextOutOptions());
+            this.isUnicode = isUnicode;
+        }
 
+        @Override
+        public int init(LittleEndianInputStream leis, final long recordSize, final int offset) throws IOException {
+            // A WMF PointL object that specifies the coordinates of the reference point used to position the string.
+            // The reference point is defined by the last EMR_SETTEXTALIGN record.
+            // If no such record has been set, the default alignment is TA_LEFT,TA_TOP.
+            long size = readPointL(leis, reference);
+            // A 32-bit unsigned integer that specifies the number of characters in the string.
+            stringLength = (int)leis.readUInt();
+            // A 32-bit unsigned integer that specifies the offset to the output string, in bytes,
+            // from the start of the record in which this object is contained.
+            // This value MUST be 8- or 16-bit aligned, according to the character format.
+            int offString = (int)leis.readUInt();
+            size += 2*LittleEndianConsts.INT_SIZE;
+
+            size += options.init(leis);
+            // An optional WMF RectL object that defines a clipping and/or opaquing rectangle in logical units.
+            // This rectangle is applied to the text output performed by the containing record.
+            if (options.isClipped() || options.isOpaque()) {
+                size += readRectL(leis, bounds);
+            }
 
-    public static class SetTextJustification extends UnimplementedHemfRecord {
+            // A 32-bit unsigned integer that specifies the offset to an intercharacter spacing array, in bytes,
+            // from the start of the record in which this object is contained. This value MUST be 32-bit aligned.
+            int offDx = (int)leis.readUInt();
+            size += LittleEndianConsts.INT_SIZE;
+
+            int undefinedSpace1 = (int)(offString-offset-size-2*LittleEndianConsts.INT_SIZE);
+            assert (undefinedSpace1 >= 0);
+            leis.skipFully(undefinedSpace1);
+            size += undefinedSpace1;
+
+            rawTextBytes = IOUtils.safelyAllocate(stringLength*(isUnicode?2:1), MAX_RECORD_LENGTH);
+            leis.readFully(rawTextBytes);
+            size += rawTextBytes.length;
+
+            outputDx.clear();
+            if (offDx > 0) {
+                int undefinedSpace2 = (int) (offDx - offset - size - 2 * LittleEndianConsts.INT_SIZE);
+                assert (undefinedSpace2 >= 0);
+                leis.skipFully(undefinedSpace2);
+                size += undefinedSpace2;
+
+                // An array of 32-bit unsigned integers that specify the output spacing between the origins of adjacent
+                // character cells in logical units. The location of this field is specified by the value of offDx
+                // in bytes from the start of this record. If spacing is defined, this field contains the same number
+                // of values as characters in the output string.
+                //
+                // If the Options field of the EmrText object contains the ETO_PDY flag, then this buffer
+                // contains twice as many values as there are characters in the output string, one
+                // horizontal and one vertical offset for each, in that order.
+                //
+                // If ETO_RTLREADING is specified, characters are laid right to left instead of left to right.
+                // No other options affect the interpretation of this field.
+                while (size < recordSize) {
+                    outputDx.add((int) leis.readUInt());
+                    size += LittleEndianConsts.INT_SIZE;
+                }
+            }
 
+            return (int)size;
+        }
     }
 
-    private static class EmrTextObject {
-        long x;
-        long y;
-        int numChars;
-        byte[] rawTextBytes;//this stores _all_ of the bytes to the end of the EMRTextObject record.
-                            //Because of potential variable length encodings, must
-                            //carefully read only the numChars from this byte array.
-
-        EmrTextObject(byte[] emrTextObjBytes, Charset charsetHint, int readSoFar) throws IOException {
-
-            int offset = 0;
-            x = LittleEndian.getUInt(emrTextObjBytes, offset); offset+= LittleEndian.INT_SIZE;
-            y = LittleEndian.getUInt(emrTextObjBytes, offset); offset+= LittleEndian.INT_SIZE;
-            long numCharsLong = LittleEndian.getUInt(emrTextObjBytes, offset); offset += LittleEndian.INT_SIZE;
-            long offString = LittleEndian.getUInt(emrTextObjBytes, offset); offset += LittleEndian.INT_SIZE;
-            int start = (int)offString-offset-readSoFar;
-
-            if (numCharsLong == 0) {
-                rawTextBytes = new byte[0];
-                numChars = 0;
-                return;
-            }
-            if (numCharsLong > Integer.MAX_VALUE) {
-                throw new RecordFormatException("Number of characters can't be > Integer.MAX_VALUE");
-            } else if (numCharsLong < 0) {
-                throw new RecordFormatException("Number of characters can't be < 0");
-            }
 
-            numChars = (int)numCharsLong;
-            rawTextBytes = IOUtils.safelyAllocate(emrTextObjBytes.length-start, MAX_RECORD_LENGTH);
-            System.arraycopy(emrTextObjBytes, start, rawTextBytes, 0, emrTextObjBytes.length-start);
+    public static class ExtCreateFontIndirectW extends HwmfText.WmfCreateFontIndirect
+    implements HemfRecord {
+        int fontIdx;
+
+        public ExtCreateFontIndirectW() {
+            super(new HemfFont());
         }
 
-        String getText(Charset charset) throws IOException {
-            StringBuilder sb = new StringBuilder();
-            try (Reader r = new InputStreamReader(new ByteArrayInputStream(rawTextBytes), charset)) {
-                for (int i = 0; i < numChars; i++) {
-                    sb.appendCodePoint(readCodePoint(r));
-                }
-            }
-            return sb.toString();
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.extCreateFontIndirectW;
         }
 
-        //TODO: move this to IOUtils?
-        private int readCodePoint(Reader r) throws IOException {
-            int c1 = r.read();
-            if (c1 == -1) {
-                throw new EOFException("Tried to read beyond byte array");
-            }
-            if (!Character.isHighSurrogate((char)c1)) {
-                return c1;
-            }
-            int c2 = r.read();
-            if (c2 == -1) {
-                throw new EOFException("Tried to read beyond byte array");
-            }
-            if (!Character.isLowSurrogate((char)c2)) {
-                throw new RecordFormatException("Expected low surrogate after high surrogate");
-            }
-            return Character.toCodePoint((char)c1, (char)c2);
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // A 32-bit unsigned integer that specifies the index of the logical font object
+            // in the EMF Object Table
+            fontIdx = (int)leis.readUInt();
+            int size = font.init(leis, (int)(recordSize-LittleEndianConsts.INT_SIZE));
+            return size+LittleEndianConsts.INT_SIZE;
         }
     }
 
+    public static class EmfExtTextOutOptions extends HwmfText.WmfExtTextOutOptions {
+        @Override
+        public int init(LittleEndianInputStream leis) {
+            // A 32-bit unsigned integer that specifies how to use the rectangle specified in the Rectangle field.
+            // This field can be a combination of more than one ExtTextOutOptions enumeration
+            flag = (int)leis.readUInt();
+            return LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    public static class SetTextJustification extends UnimplementedHemfRecord {
+
+    }
+
+    /**
+     * Needs to be implemented.  Couldn't find example.
+     */
+    public static class PolyTextOutA extends UnimplementedHemfRecord {
+
+    }
+
+    /**
+     * Needs to be implemented.  Couldn't find example.
+     */
+    public static class PolyTextOutW extends UnimplementedHemfRecord {
+
+    }
 
 }

Added: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfWindowing.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfWindowing.java?rev=1840956&view=auto
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfWindowing.java (added)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfWindowing.java Fri Sep 14 21:37:37 2018
@@ -0,0 +1,200 @@
+/* ====================================================================
+   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 java.io.IOException;
+
+import org.apache.poi.hwmf.record.HwmfWindowing;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
+
+public class HemfWindowing {
+
+    /**
+     * The EMR_SETWINDOWEXTEX record defines the window extent.
+     */
+    public static class EmfSetWindowExtEx extends HwmfWindowing.WmfSetWindowExt implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setWindowExtEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // cx (4 bytes): A 32-bit unsigned integer that defines the x-coordinate of the point.
+            width = (int)leis.readUInt();
+            // cy (4 bytes): A 32-bit unsigned integer that defines the y-coordinate of the point.
+            height = (int)leis.readUInt();
+
+            return 2*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_SETWINDOWORGEX record defines the window origin.
+     */
+    public static class EmfSetWindowOrgEx extends HwmfWindowing.WmfSetWindowOrg implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setWindowOrgEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // x (4 bytes): A 32-bit signed integer that defines the horizontal (x) coordinate of the point.
+            x = leis.readInt();
+            // y (4 bytes): A 32-bit signed integer that defines the vertical (y) coordinate of the point.
+            y = leis.readInt();
+
+            return 2*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_SETVIEWPORTEXTEX record defines the viewport extent.
+     */
+    public static class EmfSetViewportExtEx extends HwmfWindowing.WmfSetViewportExt implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setViewportExtEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // cx (4 bytes): A 32-bit unsigned integer that defines the x-coordinate of the point.
+            width = (int)leis.readUInt();
+            // cy (4 bytes): A 32-bit unsigned integer that defines the y-coordinate of the point.
+            height = (int)leis.readUInt();
+
+            return 2*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_SETVIEWPORTORGEX record defines the viewport origin.
+     */
+    public static class EmfSetViewportOrgEx extends HwmfWindowing.WmfSetViewportOrg implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setViewportOrgEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // x (4 bytes): A 32-bit signed integer that defines the horizontal (x) coordinate of the point.
+            x = leis.readInt();
+            // y (4 bytes): A 32-bit signed integer that defines the vertical (y) coordinate of the point.
+            y = leis.readInt();
+
+            return 2*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_OFFSETCLIPRGN record moves the current clipping region in the playback device context
+     * by the specified offsets.
+     */
+    public static class EmfSetOffsetClipRgn extends HwmfWindowing.WmfOffsetClipRgn implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setOffsetClipRgn;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            // x (4 bytes): A 32-bit signed integer that defines the horizontal (x) coordinate of the point.
+            xOffset = leis.readInt();
+            // y (4 bytes): A 32-bit signed integer that defines the vertical (y) coordinate of the point.
+            yOffset = leis.readInt();
+
+            return 2*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_EXCLUDECLIPRECT record specifies a new clipping region that consists of the existing
+     * clipping region minus the specified rectangle.
+     */
+    public static class EmfSetExcludeClipRect extends HwmfWindowing.WmfExcludeClipRect implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setExcludeClipRect;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            return HemfDraw.readRectL(leis, bounds);
+        }
+    }
+
+    /**
+     * The EMR_INTERSECTCLIPRECT record specifies a new clipping region from the intersection of the
+     * current clipping region and the specified rectangle.
+     */
+    public static class EmfSetIntersectClipRect extends HwmfWindowing.WmfIntersectClipRect implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.setIntersectClipRect;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            return HemfDraw.readRectL(leis, bounds);
+        }
+    }
+
+    /**
+     * The EMR_SCALEVIEWPORTEXTEX record respecifies the viewport for a device context by using the
+     * ratios formed by the specified multiplicands and divisors.
+     */
+    public static class EmfScaleViewportExtEx extends HwmfWindowing.WmfScaleViewportExt implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.scaleViewportExtEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            xNum = leis.readInt();
+            xDenom = leis.readInt();
+            yNum = leis.readInt();
+            yDenom = leis.readInt();
+            return 4*LittleEndianConsts.INT_SIZE;
+        }
+    }
+
+    /**
+     * The EMR_SCALEWINDOWEXTEX record respecifies the window for a playback device context by
+     * using the ratios formed by the specified multiplicands and divisors.
+     */
+    public static class EmfScaleWindowExtEx extends HwmfWindowing.WmfScaleWindowExt implements HemfRecord {
+        @Override
+        public HemfRecordType getEmfRecordType() {
+            return HemfRecordType.scaleWindowExtEx;
+        }
+
+        @Override
+        public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
+            xNum = leis.readInt();
+            xDenom = leis.readInt();
+            yNum = leis.readInt();
+            yDenom = leis.readInt();
+            return 4*LittleEndianConsts.INT_SIZE;
+        }
+    }
+}

Propchange: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfWindowing.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/UnimplementedHemfRecord.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/UnimplementedHemfRecord.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/UnimplementedHemfRecord.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/UnimplementedHemfRecord.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/UnimplementedHemfRecord.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/UnimplementedHemfRecord.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emf/UnimplementedHemfRecord.java Fri Sep 14 21:37:37 2018
@@ -15,7 +15,7 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.record;
+package org.apache.poi.hemf.record.emf;
 
 
 import java.io.IOException;
@@ -33,12 +33,12 @@ public class UnimplementedHemfRecord imp
     }
 
     @Override
-    public HemfRecordType getRecordType() {
+    public HemfRecordType getEmfRecordType() {
         return HemfRecordType.getById(recordId);
     }
 
     @Override
-    public long init(LittleEndianInputStream leis, long recordId, long recordSize) throws IOException {
+    public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
         this.recordId = recordId;
         long skipped = IOUtils.skipFully(leis, recordSize);
         if (skipped < recordSize) {

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusHeader.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusHeader.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusHeader.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusHeader.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusHeader.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusHeader.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusHeader.java Fri Sep 14 21:37:37 2018
@@ -15,13 +15,14 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.hemfplus.record;
+package org.apache.poi.hemf.record.emfplus;
 
 
 import java.io.IOException;
 
 import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LittleEndianInputStream;
 
 @Internal
 public class HemfPlusHeader implements HemfPlusRecord {
@@ -42,15 +43,19 @@ public class HemfPlusHeader implements H
     }
 
     @Override
-    public void init(byte[] dataBytes, int recordId, int flags) throws IOException {
-        //assert record id == header
+    public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
         this.flags = flags;
-        int offset = 0;
-        this.version = LittleEndian.getUInt(dataBytes, offset); offset += LittleEndian.INT_SIZE;
-        this.emfPlusFlags = LittleEndian.getUInt(dataBytes, offset); offset += LittleEndian.INT_SIZE;
-        this.logicalDpiX = LittleEndian.getUInt(dataBytes, offset); offset += LittleEndian.INT_SIZE;
-        this.logicalDpiY = LittleEndian.getUInt(dataBytes, offset);
+        version = leis.readUInt();
 
+        // verify MetafileSignature (20 bits) == 0xDBC01 and
+        // GraphicsVersion (12 bits) in (1 or 2)
+        assert((version & 0xFFFFFA00) == 0xDBC01000L && ((version & 0x3FF) == 1 || (version & 0x3FF) == 2));
+
+        emfPlusFlags = leis.readUInt();
+
+        logicalDpiX = leis.readUInt();
+        logicalDpiY = leis.readUInt();
+        return 4* LittleEndianConsts.INT_SIZE;
     }
 
     public long getVersion() {
@@ -79,4 +84,4 @@ public class HemfPlusHeader implements H
                 ", logicalDpiY=" + logicalDpiY +
                 '}';
     }
-}
+}
\ No newline at end of file

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecord.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecord.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecord.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecord.java Fri Sep 14 21:37:37 2018
@@ -15,12 +15,14 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.hemfplus.record;
+package org.apache.poi.hemf.record.emfplus;
 
 
 import java.io.IOException;
 
+import org.apache.poi.hemf.record.emf.HemfRecordType;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndianInputStream;
 
 @Internal
 public interface HemfPlusRecord {
@@ -30,15 +32,17 @@ public interface HemfPlusRecord {
     int getFlags();
 
     /**
+     * Init record from stream
      *
-     * @param dataBytes these are the bytes that start after the id, flags, record size
-     *                    and go to the end of the record; they do not include any required padding
-     *                    at the end.
-     * @param recordId record type id
-     * @param flags flags
-     * @throws IOException, RecordFormatException
+     * @param leis the little endian input stream
+     * @param dataSize the size limit for this record
+     * @param recordId the id of the {@link HemfPlusRecordType}
+     * @param flags the record flags
+     *
+     * @return count of processed bytes
+     *
+     * @throws IOException when the inputstream is malformed
      */
-    void init(byte[] dataBytes, int recordId, int flags) throws IOException;
-
+    long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException;
 
 }

Added: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordIterator.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordIterator.java?rev=1840956&view=auto
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordIterator.java (added)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordIterator.java Fri Sep 14 21:37:37 2018
@@ -0,0 +1,98 @@
+/* ====================================================================
+   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.emfplus;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.apache.poi.util.LittleEndianInputStream;
+import org.apache.poi.util.RecordFormatException;
+
+public class HemfPlusRecordIterator implements Iterator<HemfPlusRecord> {
+
+    private final LittleEndianInputStream leis;
+    private final int startIdx;
+    private final int limit;
+    private HemfPlusRecord currentRecord;
+
+    public HemfPlusRecordIterator(LittleEndianInputStream leis) {
+        this(leis, -1);
+    }
+
+    public HemfPlusRecordIterator(LittleEndianInputStream leis, int limit) {
+        this.leis = leis;
+        this.limit = limit;
+        startIdx = leis.getReadIndex();
+        //queue the first non-header record
+        currentRecord = _next();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return currentRecord != null;
+    }
+
+    @Override
+    public HemfPlusRecord next() {
+        HemfPlusRecord toReturn = currentRecord;
+        final boolean isEOF = (limit == -1 || leis.getReadIndex()-startIdx >= limit);
+        // (currentRecord instanceof HemfPlusMisc.EmfEof)
+        currentRecord = isEOF ? null : _next();
+        return toReturn;
+    }
+
+    private HemfPlusRecord _next() {
+        if (currentRecord != null && HemfPlusRecordType.eof == currentRecord.getRecordType()) {
+            return null;
+        }
+        // A 16-bit unsigned integer that identifies this record type
+        int recordId = leis.readUShort();
+        // A 16-bit unsigned integer that provides information about how the operation is
+        // to be performed, and about the structure of the record.
+        int flags = leis.readUShort();
+        // A 32-bit unsigned integer that specifies the 32-bit-aligned size of the entire
+        // record in bytes, including the 12-byte record header and record-specific data.
+        int recordSize = (int)leis.readUInt();
+        // A 32-bit unsigned integer that specifies the 32-bit-aligned number of bytes of data
+        // in the record-specific data that follows. This number does not include the size of
+        // the invariant part of this record.
+        int dataSize = (int)leis.readUInt();
+
+        HemfPlusRecordType type = HemfPlusRecordType.getById(recordId);
+        if (type == null) {
+            throw new RecordFormatException("Undefined record of type:"+recordId);
+        }
+        final HemfPlusRecord record = type.constructor.get();
+
+        try {
+            long readBytes = record.init(leis, dataSize, recordId, flags);
+            assert (readBytes <= recordSize-12);
+            leis.skipFully((int)(recordSize-12-readBytes));
+        } catch (IOException e) {
+            throw new RecordFormatException(e);
+        }
+
+        return record;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Remove not supported");
+    }
+
+}

Propchange: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordType.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecordType.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordType.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordType.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecordType.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/HemfPlusRecordType.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusRecordType.java Fri Sep 14 21:37:37 2018
@@ -15,77 +15,80 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.hemfplus.record;
+package org.apache.poi.hemf.record.emfplus;
+
+import java.util.function.Supplier;
 
 import org.apache.poi.util.Internal;
 
 @Internal
 public enum HemfPlusRecordType {
-    header(0x4001, HemfPlusHeader.class),
-    endOfFile(0x4002, UnimplementedHemfPlusRecord.class),
-    comment(0x4003, UnimplementedHemfPlusRecord.class),
-    getDC(0x4004, UnimplementedHemfPlusRecord.class),
-    multiFormatStart(0x4005, UnimplementedHemfPlusRecord.class),
-    multiFormatSection(0x4006, UnimplementedHemfPlusRecord.class),
-    multiFormatEnd(0x4007, UnimplementedHemfPlusRecord.class),
-    object(0x4008, UnimplementedHemfPlusRecord.class),
-    clear(0x4009, UnimplementedHemfPlusRecord.class),
-    fillRects(0x400A, UnimplementedHemfPlusRecord.class),
-    drawRects(0x400B, UnimplementedHemfPlusRecord.class),
-    fillPolygon(0x400C, UnimplementedHemfPlusRecord.class),
-    drawLines(0x400D, UnimplementedHemfPlusRecord.class),
-    fillEllipse(0x400E, UnimplementedHemfPlusRecord.class),
-    drawEllipse(0x400F, UnimplementedHemfPlusRecord.class),
-    fillPie(0x4010, UnimplementedHemfPlusRecord.class),
-    drawPie(0x4011, UnimplementedHemfPlusRecord.class),
-    drawArc(0x4012, UnimplementedHemfPlusRecord.class),
-    fillRegion(0x4013, UnimplementedHemfPlusRecord.class),
-    fillPath(0x4014, UnimplementedHemfPlusRecord.class),
-    drawPath(0x4015, UnimplementedHemfPlusRecord.class),
-    fillClosedCurve(0x4016, UnimplementedHemfPlusRecord.class),
-    drawClosedCurve(0x4017, UnimplementedHemfPlusRecord.class),
-    drawCurve(0x4018, UnimplementedHemfPlusRecord.class),
-    drawBeziers(0x4019, UnimplementedHemfPlusRecord.class),
-    drawImage(0x401A, UnimplementedHemfPlusRecord.class),
-    drawImagePoints(0x401B, UnimplementedHemfPlusRecord.class),
-    drawString(0x401C, UnimplementedHemfPlusRecord.class),
-    setRenderingOrigin(0x401D, UnimplementedHemfPlusRecord.class),
-    setAntiAliasMode(0x401E, UnimplementedHemfPlusRecord.class),
-    setTextRenderingHint(0x401F, UnimplementedHemfPlusRecord.class),
-    setTextContrast(0x4020, UnimplementedHemfPlusRecord.class),
-    setInterpolationMode(0x4021, UnimplementedHemfPlusRecord.class),
-    setPixelOffsetMode(0x4022, UnimplementedHemfPlusRecord.class),
-    setComositingMode(0x4023, UnimplementedHemfPlusRecord.class),
-    setCompositingQuality(0x4024, UnimplementedHemfPlusRecord.class),
-    save(0x4025, UnimplementedHemfPlusRecord.class),
-    restore(0x4026, UnimplementedHemfPlusRecord.class),
-    beginContainer(0x4027, UnimplementedHemfPlusRecord.class),
-    beginContainerNoParams(0x428, UnimplementedHemfPlusRecord.class),
-    endContainer(0x4029, UnimplementedHemfPlusRecord.class),
-    setWorldTransform(0x402A, UnimplementedHemfPlusRecord.class),
-    resetWorldTransform(0x402B, UnimplementedHemfPlusRecord.class),
-    multiplyWorldTransform(0x402C, UnimplementedHemfPlusRecord.class),
-    translateWorldTransform(0x402D, UnimplementedHemfPlusRecord.class),
-    scaleWorldTransform(0x402E, UnimplementedHemfPlusRecord.class),
-    rotateWorldTransform(0x402F, UnimplementedHemfPlusRecord.class),
-    setPageTransform(0x4030, UnimplementedHemfPlusRecord.class),
-    resetClip(0x4031, UnimplementedHemfPlusRecord.class),
-    setClipRect(0x4032, UnimplementedHemfPlusRecord.class),
-    setClipRegion(0x4033, UnimplementedHemfPlusRecord.class),
-    setClipPath(0x4034, UnimplementedHemfPlusRecord.class),
-    offsetClip(0x4035, UnimplementedHemfPlusRecord.class),
-    drawDriverstring(0x4036, UnimplementedHemfPlusRecord.class),
-    strokeFillPath(0x4037, UnimplementedHemfPlusRecord.class),
-    serializableObject(0x4038, UnimplementedHemfPlusRecord.class),
-    setTSGraphics(0x4039, UnimplementedHemfPlusRecord.class),
-    setTSClip(0x403A, UnimplementedHemfPlusRecord.class);
+    header(0x4001, HemfPlusHeader::new),
+    eof(0x4002, UnimplementedHemfPlusRecord::new),
+    comment(0x4003, UnimplementedHemfPlusRecord::new),
+    getDC(0x4004, UnimplementedHemfPlusRecord::new),
+    multiFormatStart(0x4005, UnimplementedHemfPlusRecord::new),
+    multiFormatSection(0x4006, UnimplementedHemfPlusRecord::new),
+    multiFormatEnd(0x4007, UnimplementedHemfPlusRecord::new),
+    object(0x4008, UnimplementedHemfPlusRecord::new),
+    clear(0x4009, UnimplementedHemfPlusRecord::new),
+    fillRects(0x400A, UnimplementedHemfPlusRecord::new),
+    drawRects(0x400B, UnimplementedHemfPlusRecord::new),
+    fillPolygon(0x400C, UnimplementedHemfPlusRecord::new),
+    drawLines(0x400D, UnimplementedHemfPlusRecord::new),
+    fillEllipse(0x400E, UnimplementedHemfPlusRecord::new),
+    drawEllipse(0x400F, UnimplementedHemfPlusRecord::new),
+    fillPie(0x4010, UnimplementedHemfPlusRecord::new),
+    drawPie(0x4011, UnimplementedHemfPlusRecord::new),
+    drawArc(0x4012, UnimplementedHemfPlusRecord::new),
+    fillRegion(0x4013, UnimplementedHemfPlusRecord::new),
+    fillPath(0x4014, UnimplementedHemfPlusRecord::new),
+    drawPath(0x4015, UnimplementedHemfPlusRecord::new),
+    fillClosedCurve(0x4016, UnimplementedHemfPlusRecord::new),
+    drawClosedCurve(0x4017, UnimplementedHemfPlusRecord::new),
+    drawCurve(0x4018, UnimplementedHemfPlusRecord::new),
+    drawBeziers(0x4019, UnimplementedHemfPlusRecord::new),
+    drawImage(0x401A, UnimplementedHemfPlusRecord::new),
+    drawImagePoints(0x401B, UnimplementedHemfPlusRecord::new),
+    drawString(0x401C, UnimplementedHemfPlusRecord::new),
+    setRenderingOrigin(0x401D, UnimplementedHemfPlusRecord::new),
+    setAntiAliasMode(0x401E, UnimplementedHemfPlusRecord::new),
+    setTextRenderingHint(0x401F, UnimplementedHemfPlusRecord::new),
+    setTextContrast(0x4020, UnimplementedHemfPlusRecord::new),
+    setInterpolationMode(0x4021, UnimplementedHemfPlusRecord::new),
+    setPixelOffsetMode(0x4022, UnimplementedHemfPlusRecord::new),
+    setComositingMode(0x4023, UnimplementedHemfPlusRecord::new),
+    setCompositingQuality(0x4024, UnimplementedHemfPlusRecord::new),
+    save(0x4025, UnimplementedHemfPlusRecord::new),
+    restore(0x4026, UnimplementedHemfPlusRecord::new),
+    beginContainer(0x4027, UnimplementedHemfPlusRecord::new),
+    beginContainerNoParams(0x428, UnimplementedHemfPlusRecord::new),
+    endContainer(0x4029, UnimplementedHemfPlusRecord::new),
+    setWorldTransform(0x402A, UnimplementedHemfPlusRecord::new),
+    resetWorldTransform(0x402B, UnimplementedHemfPlusRecord::new),
+    multiplyWorldTransform(0x402C, UnimplementedHemfPlusRecord::new),
+    translateWorldTransform(0x402D, UnimplementedHemfPlusRecord::new),
+    scaleWorldTransform(0x402E, UnimplementedHemfPlusRecord::new),
+    rotateWorldTransform(0x402F, UnimplementedHemfPlusRecord::new),
+    setPageTransform(0x4030, UnimplementedHemfPlusRecord::new),
+    resetClip(0x4031, UnimplementedHemfPlusRecord::new),
+    setClipRect(0x4032, UnimplementedHemfPlusRecord::new),
+    setClipRegion(0x4033, UnimplementedHemfPlusRecord::new),
+    setClipPath(0x4034, UnimplementedHemfPlusRecord::new),
+    offsetClip(0x4035, UnimplementedHemfPlusRecord::new),
+    drawDriverstring(0x4036, UnimplementedHemfPlusRecord::new),
+    strokeFillPath(0x4037, UnimplementedHemfPlusRecord::new),
+    serializableObject(0x4038, UnimplementedHemfPlusRecord::new),
+    setTSGraphics(0x4039, UnimplementedHemfPlusRecord::new),
+    setTSClip(0x403A, UnimplementedHemfPlusRecord::new);
+
 
     public final long id;
-    public final Class<? extends HemfPlusRecord> clazz;
+    public final Supplier<? extends HemfPlusRecord> constructor;
 
-    HemfPlusRecordType(long id, Class<? extends HemfPlusRecord> clazz) {
+    HemfPlusRecordType(long id, Supplier<? extends HemfPlusRecord> constructor) {
         this.id = id;
-        this.clazz = clazz;
+        this.constructor = constructor;
     }
 
     public static HemfPlusRecordType getById(long id) {

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/UnimplementedHemfPlusRecord.java (from r1840955, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/UnimplementedHemfPlusRecord.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/UnimplementedHemfPlusRecord.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/UnimplementedHemfPlusRecord.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/UnimplementedHemfPlusRecord.java&r1=1840955&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/hemfplus/record/UnimplementedHemfPlusRecord.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/UnimplementedHemfPlusRecord.java Fri Sep 14 21:37:37 2018
@@ -15,17 +15,21 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.hemfplus.record;
+package org.apache.poi.hemf.record.emfplus;
 
 
 import java.io.IOException;
 
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndianInputStream;
 
 @Internal
 public class UnimplementedHemfPlusRecord implements HemfPlusRecord {
 
-    private int recordId;
+    private static final int MAX_RECORD_LENGTH = 1_000_000;
+
+    private long recordId;
     private int flags;
     private byte[] recordBytes;
 
@@ -40,14 +44,16 @@ public class UnimplementedHemfPlusRecord
     }
 
     @Override
-    public void init(byte[] recordBytes, int recordId, int flags) throws IOException {
+    public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
         this.recordId = recordId;
         this.flags = flags;
-        this.recordBytes = recordBytes;
+        recordBytes = IOUtils.safelyAllocate(dataSize, MAX_RECORD_LENGTH);
+        leis.readFully(recordBytes);
+        return recordBytes.length;
     }
 
     public byte[] getRecordBytes() {
         //should probably defensively return a copy.
         return recordBytes;
     }
-}
+}
\ No newline at end of file

Copied: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java (from r1840385, poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/extractor/HemfExtractor.java)
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java?p2=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java&p1=poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/extractor/HemfExtractor.java&r1=1840385&r2=1840956&rev=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/extractor/HemfExtractor.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hemf/usermodel/HemfPicture.java Fri Sep 14 21:37:37 2018
@@ -15,101 +15,63 @@
    limitations under the License.
 ==================================================================== */
 
-package org.apache.poi.hemf.extractor;
+package org.apache.poi.hemf.usermodel;
 
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Iterator;
-
-import org.apache.poi.hemf.record.HemfHeader;
-import org.apache.poi.hemf.record.HemfRecord;
-import org.apache.poi.hemf.record.HemfRecordType;
+import java.util.List;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+
+import org.apache.poi.hemf.record.emf.HemfHeader;
+import org.apache.poi.hemf.record.emf.HemfRecord;
+import org.apache.poi.hemf.record.emf.HemfRecordIterator;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndianInputStream;
-import org.apache.poi.util.RecordFormatException;
 
 /**
  * Read-only EMF extractor.  Lots remain
  */
 @Internal
-public class HemfExtractor implements Iterable<HemfRecord> {
+public class HemfPicture implements Iterable<HemfRecord> {
 
-    private HemfHeader header;
     private final LittleEndianInputStream stream;
+    private final List<HemfRecord> records = new ArrayList<>();
 
-    public HemfExtractor(InputStream is) throws IOException {
-        stream = new LittleEndianInputStream(is);
-        header = new HemfHeader();
-        long recordId = stream.readUInt();
-        long recordSize = stream.readUInt();
-
-        header = new HemfHeader();
-        header.init(stream, recordId, recordSize-8);
+    public HemfPicture(InputStream is) throws IOException {
+        this(new LittleEndianInputStream(is));
     }
 
-    @Override
-    public Iterator<HemfRecord> iterator() {
-        return new HemfRecordIterator();
+    public HemfPicture(LittleEndianInputStream is) throws IOException {
+        stream = is;
     }
 
     public HemfHeader getHeader() {
-        return header;
+        return (HemfHeader)getRecords().get(0);
     }
 
-    private class HemfRecordIterator implements Iterator<HemfRecord> {
-
-        private HemfRecord currentRecord;
-
-        HemfRecordIterator() {
-            //queue the first non-header record
-            currentRecord = _next();
-        }
-
-        @Override
-        public boolean hasNext() {
-            return currentRecord != null;
-        }
-
-        @Override
-        public HemfRecord next() {
-            HemfRecord toReturn = currentRecord;
-            currentRecord = _next();
-            return toReturn;
+    public List<HemfRecord> getRecords() {
+        if (records.isEmpty()) {
+            new HemfRecordIterator(stream).forEachRemaining(records::add);
         }
+        return records;
+    }
 
-        private HemfRecord _next() {
-            if (currentRecord != null && currentRecord.getRecordType().equals(HemfRecordType.eof)) {
-                return null;
-            }
-            long recordId = stream.readUInt();
-            long recordSize = stream.readUInt();
-
-            HemfRecord record = null;
-            HemfRecordType type = HemfRecordType.getById(recordId);
-            if (type == null) {
-                throw new RuntimeException("Undefined record of type:"+recordId);
-            }
-            try {
-                record = type.clazz.newInstance();
-            } catch (InstantiationException e) {
-                throw new RuntimeException(e);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException(e);
-            }
-            try {
-                record.init(stream, recordId, recordSize-8);
-            } catch (IOException e) {
-                throw new RecordFormatException(e);
-            }
-
-            return record;
-        }
+    @Override
+    public Iterator<HemfRecord> iterator() {
+        return getRecords().iterator();
+    }
 
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException("Remove not supported");
-        }
+    @Override
+    public Spliterator<HemfRecord> spliterator() {
+        return getRecords().spliterator();
+    }
 
+    @Override
+    public void forEach(Consumer<? super HemfRecord> action) {
+        getRecords().forEach(action);
     }
 }

Modified: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java?rev=1840956&r1=1840955&r2=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java Fri Sep 14 21:37:37 2018
@@ -43,32 +43,48 @@ public class HwmfDrawProperties {
     private final Rectangle2D window;
     private Rectangle2D viewport;
     private final Point2D location;
-    private HwmfMapMode mapMode = HwmfMapMode.MM_ANISOTROPIC;
-    private HwmfColorRef backgroundColor = new HwmfColorRef(Color.BLACK);
-    private HwmfBrushStyle brushStyle = HwmfBrushStyle.BS_SOLID;
-    private HwmfColorRef brushColor = new HwmfColorRef(Color.BLACK);
-    private HwmfHatchStyle brushHatch = HwmfHatchStyle.HS_HORIZONTAL;
+    private HwmfMapMode mapMode;
+    private HwmfColorRef backgroundColor;
+    private HwmfBrushStyle brushStyle;
+    private HwmfColorRef brushColor;
+    private HwmfHatchStyle brushHatch;
     private BufferedImage brushBitmap;
-    private double penWidth = 1;
-    private HwmfPenStyle penStyle = HwmfPenStyle.valueOf(0);
-    private HwmfColorRef penColor = new HwmfColorRef(Color.BLACK);
-    private double penMiterLimit = 10;
-    private HwmfBkMode bkMode = HwmfBkMode.OPAQUE;
-    private HwmfPolyfillMode polyfillMode = HwmfPolyfillMode.WINDING;
+    private double penWidth;
+    private HwmfPenStyle penStyle;
+    private HwmfColorRef penColor;
+    private double penMiterLimit;
+    private HwmfBkMode bkMode;
+    private HwmfPolyfillMode polyfillMode;
     private Shape region;
     private List<PaletteEntry> palette;
     private int paletteOffset;
     private HwmfFont font;
-    private HwmfColorRef textColor = new HwmfColorRef(Color.BLACK);
-    private HwmfTextAlignment textAlignLatin = HwmfTextAlignment.LEFT;
-    private HwmfTextVerticalAlignment textVAlignLatin = HwmfTextVerticalAlignment.TOP;
-    private HwmfTextAlignment textAlignAsian = HwmfTextAlignment.RIGHT;
-    private HwmfTextVerticalAlignment textVAlignAsian = HwmfTextVerticalAlignment.TOP;
+    private HwmfColorRef textColor;
+    private HwmfTextAlignment textAlignLatin;
+    private HwmfTextVerticalAlignment textVAlignLatin;
+    private HwmfTextAlignment textAlignAsian;
+    private HwmfTextVerticalAlignment textVAlignAsian;
 
     public HwmfDrawProperties() {
         window = new Rectangle2D.Double(0, 0, 1, 1);
         viewport = null;
         location = new Point2D.Double(0,0);
+        mapMode = HwmfMapMode.MM_ANISOTROPIC;
+        backgroundColor = new HwmfColorRef(Color.BLACK);
+        brushStyle = HwmfBrushStyle.BS_SOLID;
+        brushColor = new HwmfColorRef(Color.BLACK);
+        brushHatch = HwmfHatchStyle.HS_HORIZONTAL;
+        penWidth = 1;
+        penStyle = HwmfPenStyle.valueOf(0);
+        penColor = new HwmfColorRef(Color.BLACK);
+        penMiterLimit = 10;
+        bkMode = HwmfBkMode.OPAQUE;
+        polyfillMode = HwmfPolyfillMode.WINDING;
+        textColor = new HwmfColorRef(Color.BLACK);
+        textAlignLatin = HwmfTextAlignment.LEFT;
+        textVAlignLatin = HwmfTextVerticalAlignment.TOP;
+        textAlignAsian = HwmfTextAlignment.RIGHT;
+        textVAlignAsian = HwmfTextVerticalAlignment.TOP;
     }
     
     public HwmfDrawProperties(HwmfDrawProperties other) {
@@ -86,7 +102,7 @@ public class HwmfDrawProperties {
             WritableRaster raster = other.brushBitmap.copyData(null);
             this.brushBitmap = new BufferedImage(cm, raster, isAlphaPremultiplied, null);            
         }
-        this.penWidth = 1;
+        this.penWidth = other.penWidth;
         this.penStyle = (other.penStyle == null) ? null : other.penStyle.clone();
         this.penColor = (other.penColor == null) ? null : other.penColor.clone();
         this.penMiterLimit = other.penMiterLimit;
@@ -101,6 +117,10 @@ public class HwmfDrawProperties {
         this.paletteOffset = other.paletteOffset;
         this.font = other.font;
         this.textColor = (other.textColor == null) ? null : other.textColor.clone();
+        this.textAlignLatin = other.textAlignLatin;
+        this.textVAlignLatin = other.textVAlignLatin;
+        this.textAlignAsian = other.textAlignAsian;
+        this.textVAlignAsian = other.textVAlignAsian;
     }
     
     public void setViewportExt(double width, double height) {
@@ -149,6 +169,10 @@ public class HwmfDrawProperties {
         location.setLocation(x, y);
     }
 
+    public void setLocation(Point2D point) {
+        location.setLocation(point);
+    }
+
     public Point2D getLocation() {
         return (Point2D)location.clone();
     }

Modified: poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java
URL: http://svn.apache.org/viewvc/poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java?rev=1840956&r1=1840955&r2=1840956&view=diff
==============================================================================
--- poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java (original)
+++ poi/branches/hemf/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfBrushStyle.java Fri Sep 14 21:37:37 2018
@@ -71,7 +71,7 @@ public enum HwmfBrushStyle {
         this.flag = flag;
     }
 
-    static HwmfBrushStyle valueOf(int flag) {
+    public static HwmfBrushStyle valueOf(int flag) {
         for (HwmfBrushStyle bs : values()) {
             if (bs.flag == flag) return bs;
         }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org