]> source.dussan.org Git - poi.git/commitdiff
introduce picture descriptor structure (internal), now Picture class extends it;
authorSergey Vladimirov <sergey@apache.org>
Sat, 16 Jul 2011 16:19:49 +0000 (16:19 +0000)
committerSergey Vladimirov <sergey@apache.org>
Sat, 16 Jul 2011 16:19:49 +0000 (16:19 +0000)
add test case with correctly cropped picture info

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1147450 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlUtils.java
src/scratchpad/src/org/apache/poi/hwpf/model/PictureDescriptor.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java
src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java
src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestPictures.java
test-data/document/picture.doc [new file with mode: 0644]

index 3046c46047568120508f8cc0281621bc3a636ff5..b1656aeb6c5b4c7e082a7bcfc151f06756c82c65 100644 (file)
@@ -59,22 +59,6 @@ import static org.apache.poi.hwpf.converter.AbstractWordUtils.TWIPS_PER_INCH;
 public class WordToHtmlConverter extends AbstractWordConverter
 {
 
-    /**
-     * Holds properties values, applied to current <tt>p</tt> element. Those
-     * properties shall not be doubled in children <tt>span</tt> elements.
-     */
-    private static class BlockProperies
-    {
-        final String pFontName;
-        final int pFontSize;
-
-        public BlockProperies( String pFontName, int pFontSize )
-        {
-            this.pFontName = pFontName;
-            this.pFontSize = pFontSize;
-        }
-    }
-
     private static final POILogger logger = POILogFactory
             .getLogger( WordToHtmlConverter.class );
 
@@ -248,19 +232,12 @@ public class WordToHtmlConverter extends AbstractWordConverter
                     basicLink );
     }
 
-    @Override
-    protected void processLineBreak( Element block, CharacterRun characterRun )
-    {
-        block.appendChild( htmlDocumentFacade.createLineBreak() );
-    }
-
     /**
      * This method shall store image bytes in external file and convert it if
      * necessary. Images shall be stored using PNG format. Other formats may be
      * not supported by user browser.
      * <p>
-     * Please note the
-     * {@link WordToHtmlUtils#setPictureProperties(Picture, Element)} method.
+     * Please note the {@link #processImage(Element, boolean, Picture, String)}.
      * 
      * @param currentBlock
      *            currently processed HTML element, like <tt>p</tt>. Shall be
@@ -279,6 +256,99 @@ public class WordToHtmlConverter extends AbstractWordConverter
                         + picture.suggestFullFileName() + "' can be here" ) );
     }
 
+    protected void processImage( Element currentBlock, boolean inlined,
+            Picture picture, String imageSourcePath )
+    {
+        final int aspectRatioX = picture.getHorizontalScalingFactor();
+        final int aspectRatioY = picture.getVerticalScalingFactor();
+
+        StringBuilder style = new StringBuilder();
+
+        final float imageWidth;
+        final float imageHeight;
+
+        final float cropTop;
+        final float cropBottom;
+        final float cropLeft;
+        final float cropRight;
+
+        if ( aspectRatioX > 0 )
+        {
+            imageWidth = picture.getDxaGoal() * aspectRatioX / 1000
+                    / TWIPS_PER_INCH;
+            cropRight = picture.getDxaCropRight() * aspectRatioX / 1000
+                    / TWIPS_PER_INCH;
+            cropLeft = picture.getDxaCropLeft() * aspectRatioX / 1000
+                    / TWIPS_PER_INCH;
+        }
+        else
+        {
+            imageWidth = picture.getDxaGoal() / TWIPS_PER_INCH;
+            cropRight = picture.getDxaCropRight() / TWIPS_PER_INCH;
+            cropLeft = picture.getDxaCropLeft() / TWIPS_PER_INCH;
+        }
+
+        if ( aspectRatioY > 0 )
+        {
+            imageHeight = picture.getDyaGoal() * aspectRatioY / 1000
+                    / TWIPS_PER_INCH;
+            cropTop = picture.getDyaCropTop() * aspectRatioY / 1000
+                    / TWIPS_PER_INCH;
+            cropBottom = picture.getDyaCropBottom() * aspectRatioY / 1000
+                    / TWIPS_PER_INCH;
+        }
+        else
+        {
+            imageHeight = picture.getDyaGoal() / TWIPS_PER_INCH;
+            cropTop = picture.getDyaCropTop() / TWIPS_PER_INCH;
+            cropBottom = picture.getDyaCropBottom() / TWIPS_PER_INCH;
+        }
+
+        Element root;
+        if ( cropTop != 0 || cropRight != 0 || cropBottom != 0 || cropLeft != 0 )
+        {
+            float visibleWidth = Math
+                    .max( 0, imageWidth - cropLeft - cropRight );
+            float visibleHeight = Math.max( 0, imageHeight - cropTop
+                    - cropBottom );
+
+            root = htmlDocumentFacade.document.createElement( "div" );
+            root.setAttribute( "style", "vertical-align:text-bottom;width:"
+                    + visibleWidth + "in;height:" + visibleHeight + "in;" );
+
+            // complex
+            Element inner = htmlDocumentFacade.document.createElement( "div" );
+            inner.setAttribute( "style", "position:relative;width:"
+                    + visibleWidth + "in;height:" + visibleHeight
+                    + "in;overflow:hidden;" );
+            root.appendChild( inner );
+
+            Element image = htmlDocumentFacade.document.createElement( "img" );
+            image.setAttribute( "src", imageSourcePath );
+            image.setAttribute( "style", "position:absolute;left:-" + cropLeft
+                    + ";top:-" + cropTop + ";width:" + imageWidth
+                    + "in;height:" + imageHeight + "in;" );
+            inner.appendChild( image );
+
+            style.append( "overflow:hidden;" );
+        }
+        else
+        {
+            root = htmlDocumentFacade.document.createElement( "img" );
+            root.setAttribute( "src", imageSourcePath );
+            root.setAttribute( "style", "width:" + imageWidth + "in;height:"
+                    + imageHeight + "in;vertical-align:text-bottom;" );
+        }
+
+        currentBlock.appendChild( root );
+    }
+
+    @Override
+    protected void processLineBreak( Element block, CharacterRun characterRun )
+    {
+        block.appendChild( htmlDocumentFacade.createLineBreak() );
+    }
+
     protected void processPageref( HWPFDocumentCore hwpfDocument,
             Element currentBlock, Range textRange, int currentTableLevel,
             String pageref )
@@ -506,4 +576,20 @@ public class WordToHtmlConverter extends AbstractWordConverter
         }
     }
 
+    /**
+     * Holds properties values, applied to current <tt>p</tt> element. Those
+     * properties shall not be doubled in children <tt>span</tt> elements.
+     */
+    private static class BlockProperies
+    {
+        final String pFontName;
+        final int pFontSize;
+
+        public BlockProperies( String pFontName, int pFontSize )
+        {
+            this.pFontName = pFontName;
+            this.pFontSize = pFontSize;
+        }
+    }
+
 }
index f257ed3c0d2c3cc9be1ba430d237cdc94aa55cde..ad2d6e932631b091a97ee4a1c77c0c3a91e29102 100644 (file)
@@ -232,34 +232,27 @@ public class WordToHtmlUtils extends AbstractWordUtils
         final int aspectRatioX = picture.getAspectRatioX();
         final int aspectRatioY = picture.getAspectRatioY();
 
+        StringBuilder style = new StringBuilder();
+
         if ( aspectRatioX > 0 )
         {
-            graphicElement
-                    .setAttribute( "content-width", ( ( picture.getDxaGoal()
-                            * aspectRatioX / 100 ) / TWIPS_PER_PT )
-                            + "pt" );
+            style.append( "width:"
+                    + ( ( picture.getDxaGoal() * aspectRatioX / 1000 ) / TWIPS_PER_INCH )
+                    + "in;" );
         }
         else
-            graphicElement.setAttribute( "content-width",
-                    ( picture.getDxaGoal() / TWIPS_PER_PT ) + "pt" );
+            style.append( "width:" + ( picture.getDxaGoal() / TWIPS_PER_INCH )
+                    + "in;" );
 
         if ( aspectRatioY > 0 )
-            graphicElement
-                    .setAttribute( "content-height", ( ( picture.getDyaGoal()
-                            * aspectRatioY / 100 ) / TWIPS_PER_PT )
-                            + "pt" );
-        else
-            graphicElement.setAttribute( "content-height",
-                    ( picture.getDyaGoal() / TWIPS_PER_PT ) + "pt" );
-
-        if ( aspectRatioX <= 0 || aspectRatioY <= 0 )
         {
-            graphicElement.setAttribute( "scaling", "uniform" );
+            style.append( "height:"
+                    + ( ( picture.getDyaGoal() * aspectRatioY / 1000 ) / TWIPS_PER_INCH )
+                    + "in;" );
         }
         else
-        {
-            graphicElement.setAttribute( "scaling", "non-uniform" );
-        }
+            style.append( "height:" + ( picture.getDyaGoal() / TWIPS_PER_INCH )
+                    + "in;" );
 
         graphicElement.setAttribute( "vertical-align", "text-bottom" );
 
@@ -267,15 +260,18 @@ public class WordToHtmlUtils extends AbstractWordUtils
                 || picture.getDyaCropBottom() != 0
                 || picture.getDxaCropLeft() != 0 )
         {
-            int rectTop = picture.getDyaCropTop() / TWIPS_PER_PT;
-            int rectRight = picture.getDxaCropRight() / TWIPS_PER_PT;
-            int rectBottom = picture.getDyaCropBottom() / TWIPS_PER_PT;
-            int rectLeft = picture.getDxaCropLeft() / TWIPS_PER_PT;
-            graphicElement.setAttribute( "clip", "rect(" + rectTop + "pt, "
-                    + rectRight + "pt, " + rectBottom + "pt, " + rectLeft
-                    + "pt)" );
-            graphicElement.setAttribute( "oveerflow", "hidden" );
+            float rectTop = picture.getDyaCropTop() / TWIPS_PER_INCH;
+            float rectRight = picture.getDxaCropRight() / TWIPS_PER_INCH;
+            float rectBottom = picture.getDyaCropBottom() / TWIPS_PER_INCH;
+            float rectLeft = picture.getDxaCropLeft() / TWIPS_PER_INCH;
+
+            style.append( "clip:rect(" + rectTop + "in," + rectRight + "in, "
+                    + rectBottom + "in, " + rectLeft + "in);" );
+            style.append( "overflow:hidden;" );
         }
+
+        graphicElement.setAttribute( "style", style.toString() );
+
     }
 
 }
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/PictureDescriptor.java b/src/scratchpad/src/org/apache/poi/hwpf/model/PictureDescriptor.java
new file mode 100644 (file)
index 0000000..22ee6cd
--- /dev/null
@@ -0,0 +1,203 @@
+package org.apache.poi.hwpf.model;
+
+import java.util.Arrays;
+
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * Picture Descriptor (on File) (PICF)
+ * <p>
+ * Based on Microsoft Office Word 97-2007 Binary File Format (.doc)
+ * Specification; Page 181 of 210
+ * 
+ * @author Sergey Vladimirov ( vlsergey {at} gmail {dot} com )
+ */
+public class PictureDescriptor
+{
+    private static final int LCB_OFFSET = 0x00;
+    private static final int CBHEADER_OFFSET = 0x04;
+
+    private static final int MFP_MM_OFFSET = 0x06;
+    private static final int MFP_XEXT_OFFSET = 0x08;
+    private static final int MFP_YEXT_OFFSET = 0x0A;
+    private static final int MFP_HMF_OFFSET = 0x0C;
+
+    private static final int DXAGOAL_OFFSET = 0x1C;
+    private static final int DYAGOAL_OFFSET = 0x1E;
+
+    private static final int MX_OFFSET = 0x20;
+    private static final int MY_OFFSET = 0x22;
+
+    private static final int DXACROPLEFT_OFFSET = 0x24;
+    private static final int DYACROPTOP_OFFSET = 0x26;
+    private static final int DXACROPRIGHT_OFFSET = 0x28;
+    private static final int DYACROPBOTTOM_OFFSET = 0x2A;
+
+    /**
+     * Number of bytes in the PIC structure plus size of following picture data
+     * which may be a Window's metafile, a bitmap, or the filename of a TIFF
+     * file. In the case of a Macintosh PICT picture, this includes the size of
+     * the PIC, the standard "x" metafile, and the Macintosh PICT data. See
+     * Appendix B for more information.
+     */
+    protected int lcb;
+
+    /**
+     * Number of bytes in the PIC (to allow for future expansion).
+     */
+    protected int cbHeader;
+
+    /*
+     * Microsoft Office Word 97-2007 Binary File Format (.doc) Specification
+     * 
+     * Page 181 of 210
+     * 
+     * If a Windows metafile is stored immediately following the PIC structure,
+     * the mfp is a Window's METAFILEPICT structure. See
+     * http://msdn2.microsoft.com/en-us/library/ms649017(VS.85).aspx for more
+     * information about the METAFILEPICT structure and
+     * http://download.microsoft.com/download/0/B/E/0BE8BDD7-E5E8-422A-ABFD-
+     * 4342ED7AD886/WindowsMetafileFormat(wmf)Specification.pdf for Windows
+     * Metafile Format specification.
+     * 
+     * When the data immediately following the PIC is a TIFF filename,
+     * mfp.mm==98 If a bitmap is stored after the pic, mfp.mm==99.
+     * 
+     * When the PIC describes a bitmap, mfp.xExt is the width of the bitmap in
+     * pixels and mfp.yExt is the height of the bitmap in pixels.
+     */
+
+    protected int mfp_mm;
+    protected int mfp_xExt;
+    protected int mfp_yExt;
+    protected int mfp_hMF;
+
+    /**
+     * <li>Window's bitmap structure when PIC describes a BITMAP (14 bytes)
+     * 
+     * <li>Rectangle for window origin and extents when metafile is stored --
+     * ignored if 0 (8 bytes)
+     */
+    protected byte[] offset14 = new byte[14];
+
+    /**
+     * Horizontal measurement in twips of the rectangle the picture should be
+     * imaged within
+     */
+    protected short dxaGoal = 0;
+
+    /**
+     * Vertical measurement in twips of the rectangle the picture should be
+     * imaged within
+     */
+    protected short dyaGoal = 0;
+
+    /**
+     * Horizontal scaling factor supplied by user expressed in .001% units
+     */
+    protected short mx;
+
+    /**
+     * Vertical scaling factor supplied by user expressed in .001% units
+     */
+    protected short my;
+
+    /**
+     * The amount the picture has been cropped on the left in twips
+     */
+    protected short dxaCropLeft = 0;
+
+    /**
+     * The amount the picture has been cropped on the top in twips
+     */
+    protected short dyaCropTop = 0;
+
+    /**
+     * The amount the picture has been cropped on the right in twips
+     */
+    protected short dxaCropRight = 0;
+
+    /**
+     * The amount the picture has been cropped on the bottom in twips
+     */
+    protected short dyaCropBottom = 0;
+
+    public PictureDescriptor()
+    {
+    }
+
+    public PictureDescriptor( byte[] _dataStream, int startOffset )
+    {
+        this.lcb = LittleEndian.getInt( _dataStream, startOffset + LCB_OFFSET );
+        this.cbHeader = LittleEndian.getUShort( _dataStream, startOffset
+                + CBHEADER_OFFSET );
+
+        this.mfp_mm = LittleEndian.getUShort( _dataStream, startOffset
+                + MFP_MM_OFFSET );
+        this.mfp_xExt = LittleEndian.getUShort( _dataStream, startOffset
+                + MFP_XEXT_OFFSET );
+        this.mfp_yExt = LittleEndian.getUShort( _dataStream, startOffset
+                + MFP_YEXT_OFFSET );
+        this.mfp_hMF = LittleEndian.getUShort( _dataStream, startOffset
+                + MFP_HMF_OFFSET );
+
+        this.offset14 = LittleEndian.getByteArray( _dataStream,
+                startOffset + 0x0E, 14 );
+
+        this.dxaGoal = LittleEndian.getShort( _dataStream, startOffset
+                + DXAGOAL_OFFSET );
+        this.dyaGoal = LittleEndian.getShort( _dataStream, startOffset
+                + DYAGOAL_OFFSET );
+
+        this.mx = LittleEndian.getShort( _dataStream, startOffset + MX_OFFSET );
+        this.my = LittleEndian.getShort( _dataStream, startOffset + MY_OFFSET );
+
+        this.dxaCropLeft = LittleEndian.getShort( _dataStream, startOffset
+                + DXACROPLEFT_OFFSET );
+        this.dyaCropTop = LittleEndian.getShort( _dataStream, startOffset
+                + DYACROPTOP_OFFSET );
+        this.dxaCropRight = LittleEndian.getShort( _dataStream, startOffset
+                + DXACROPRIGHT_OFFSET );
+        this.dyaCropBottom = LittleEndian.getShort( _dataStream, startOffset
+                + DYACROPBOTTOM_OFFSET );
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append( "[PICF]\n" );
+        stringBuilder.append( "        lcb           = " ).append( this.lcb )
+                .append( '\n' );
+        stringBuilder.append( "        cbHeader      = " )
+                .append( this.cbHeader ).append( '\n' );
+
+        stringBuilder.append( "        mfp.mm        = " ).append( this.mfp_mm )
+                .append( '\n' );
+        stringBuilder.append( "        mfp.xExt      = " )
+                .append( this.mfp_xExt ).append( '\n' );
+        stringBuilder.append( "        mfp.yExt      = " )
+                .append( this.mfp_yExt ).append( '\n' );
+        stringBuilder.append( "        mfp.hMF       = " )
+                .append( this.mfp_hMF ).append( '\n' );
+
+        stringBuilder.append( "        offset14      = " )
+                .append( Arrays.toString( this.offset14 ) ).append( '\n' );
+        stringBuilder.append( "        dxaGoal       = " )
+                .append( this.dxaGoal ).append( '\n' );
+        stringBuilder.append( "        dyaGoal       = " )
+                .append( this.dyaGoal ).append( '\n' );
+
+        stringBuilder.append( "        dxaCropLeft   = " )
+                .append( this.dxaCropLeft ).append( '\n' );
+        stringBuilder.append( "        dyaCropTop    = " )
+                .append( this.dyaCropTop ).append( '\n' );
+        stringBuilder.append( "        dxaCropRight  = " )
+                .append( this.dxaCropRight ).append( '\n' );
+        stringBuilder.append( "        dyaCropBottom = " )
+                .append( this.dyaCropBottom ).append( '\n' );
+
+        stringBuilder.append( "[/PICF]" );
+        return stringBuilder.toString();
+    }
+}
index 995e8ec0671337e29d728c1260df961389d26f17..b9de16f8dc8f554e4aa75b4ec2caa38ad49632ed 100644 (file)
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.zip.InflaterInputStream;
 
+import org.apache.poi.hwpf.model.PictureDescriptor;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -31,7 +32,7 @@ import org.apache.poi.util.POILogger;
  * Represents embedded picture extracted from Word Document
  * @author Dmitry Romanov
  */
-public final class Picture
+public final class Picture extends PictureDescriptor
 {
   private static final POILogger log = POILogFactory.getLogger(Picture.class);
 
@@ -41,14 +42,6 @@ public final class Picture
   static final int PICT_HEADER_OFFSET = 0x4;
   static final int MFPMM_OFFSET = 0x6;
   static final int PICF_SHAPE_OFFSET = 0xE;
-  static final int DXAGOAL_OFFSET = 0x1C;
-  static final int DYAGOAL_OFFSET = 0x1E;
-  static final int MX_OFFSET = 0x20;
-  static final int MY_OFFSET = 0x22;
-  static final int DXACROPLEFT_OFFSET = 0x24;
-  static final int DYACROPTOP_OFFSET = 0x26;
-  static final int DXACROPRIGHT_OFFSET = 0x28;
-  static final int DYACROPBOTTOM_OFFSET = 0x2A;
   static final int UNKNOWN_HEADER_SIZE = 0x49;
 
   public static final byte[] GIF = new byte[]{'G', 'I', 'F'};
@@ -76,21 +69,13 @@ public final class Picture
   private byte[] rawContent;
   private byte[] content;
   private byte[] _dataStream;
-  private int aspectRatioX;
-  private int aspectRatioY;
   private int height = -1;
   private int width = -1;
 
-  private int dxaGoal = -1;
-  private int dyaGoal = -1;
-
-  private int dxaCropLeft = -1;
-  private int dyaCropTop = -1;
-  private int dxaCropRight = -1;
-  private int dyaCropBottom = -1;
-
   public Picture(int dataBlockStartOfsset, byte[] _dataStream, boolean fillBytes)
   {
+      super (_dataStream, dataBlockStartOfsset);
+
     this._dataStream = _dataStream;
     this.dataBlockStartOfsset = dataBlockStartOfsset;
     this.dataBlockSize = LittleEndian.getInt(_dataStream, dataBlockStartOfsset);
@@ -101,17 +86,6 @@ public final class Picture
 
     }
 
-    this.dxaGoal = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXAGOAL_OFFSET);
-    this.dyaGoal = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYAGOAL_OFFSET);
-
-    this.aspectRatioX = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+MX_OFFSET)/10;
-    this.aspectRatioY = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+MY_OFFSET)/10;
-
-    this.dxaCropLeft = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXACROPLEFT_OFFSET);
-    this.dyaCropTop = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYACROPTOP_OFFSET);
-    this.dxaCropRight = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DXACROPRIGHT_OFFSET);
-    this.dyaCropBottom = LittleEndian.getShort(_dataStream, dataBlockStartOfsset+DYACROPBOTTOM_OFFSET);
-
     if (fillBytes)
     {
       fillImageContent();
@@ -120,6 +94,8 @@ public final class Picture
 
   public Picture(byte[] _dataStream)
   {
+        super();
+
       this._dataStream = _dataStream;
       this.dataBlockStartOfsset = 0;
       this.dataBlockSize = _dataStream.length;
@@ -207,16 +183,39 @@ public final class Picture
 
     /**
      * @return the horizontal aspect ratio for picture provided by user
+     * @deprecated use more precise {@link #getHorizontalScalingFactor()}
      */
-    public int getAspectRatioX() {
-        return aspectRatioX;
+    @Deprecated
+    public int getAspectRatioX()
+    {
+        return mx / 10;
+    }
+
+    /**
+     * @return Horizontal scaling factor supplied by user expressed in .001%
+     *         units
+     */
+    public int getHorizontalScalingFactor()
+    {
+        return mx;
     }
 
     /**
      * @retrn the vertical aspect ratio for picture provided by user
+     * @deprecated use more precise {@link #getVerticalScalingFactor()}
      */
-    public int getAspectRatioY() {
-        return aspectRatioY;
+    @Deprecated
+    public int getAspectRatioY()
+    {
+        return my / 10;
+    }
+
+    /**
+     * @return Vertical scaling factor supplied by user expressed in .001% units
+     */
+    public int getVerticalScalingFactor()
+    {
+        return my;
     }
 
     /**
index 2a08a5a5d95dd1f2ef3d826072c0c37068f359f8..aa50fe2e52206ea8971d3a6865202550ccfa3957 100644 (file)
@@ -29,6 +29,9 @@ import junit.framework.TestCase;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.Picture;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 /**
  * Test cases for {@link WordToHtmlConverter}
@@ -47,13 +50,28 @@ public class TestWordToHtmlConverter extends TestCase
 
     private static String getHtmlText( final String sampleFileName )
             throws Exception
+    {
+        return getHtmlText( sampleFileName, false );
+    }
+
+    private static String getHtmlText( final String sampleFileName,
+            boolean emulatePictureStorage ) throws Exception
     {
         HWPFDocument hwpfDocument = new HWPFDocument( POIDataSamples
                 .getDocumentInstance().openResourceAsStream( sampleFileName ) );
 
-        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
-                DocumentBuilderFactory.newInstance().newDocumentBuilder()
-                        .newDocument() );
+        Document newDocument = DocumentBuilderFactory.newInstance()
+                .newDocumentBuilder().newDocument();
+        WordToHtmlConverter wordToHtmlConverter = !emulatePictureStorage ? new WordToHtmlConverter(
+                newDocument ) : new WordToHtmlConverter( newDocument )
+        {
+            @Override
+            protected void processImage( Element currentBlock, boolean inlined,
+                    Picture picture )
+            {
+                processImage( currentBlock, inlined, picture, "picture.bin" );
+            }
+        };
         wordToHtmlConverter.processDocument( hwpfDocument );
 
         StringWriter stringWriter = new StringWriter();
@@ -130,6 +148,20 @@ public class TestWordToHtmlConverter extends TestCase
         assertContains( result, "<!--Image link to '0.emf' can be here-->" );
     }
 
+    public void testPicture() throws Exception
+    {
+        String result = getHtmlText( "picture.doc", true );
+
+        // picture
+        assertContains( result, "src=\"picture.bin\"" );
+        // visible size
+        assertContains( result, "width:3.1305554in;height:1.7250001in;" );
+        // shift due to crop
+        assertContains( result, "left:-0.09375;top:-0.25694445;" );
+        // size without crop
+        assertContains( result, "width:3.4125in;height:2.325in;" );
+    }
+
     public void testHyperlink() throws Exception
     {
         String result = getHtmlText( "hyperlink.doc" );
index bd2d6a67ed3371f4e44a9fb6ec9bfb14317e03a4..81bf2be56a79f977d682521a8f7b8ee337b0aa78 100644 (file)
@@ -303,6 +303,7 @@ public final class TestPictures extends TestCase {
        assertEquals(0, plain8s);
     }
 
+    @SuppressWarnings( "deprecation" )
     public void testCroppedPictures() {
         HWPFDocument doc = HWPFTestDataSamples.openSampleFile("testCroppedPictures.doc");
         List<Picture> pics = doc.getPicturesTable().getAllPictures();
@@ -312,7 +313,9 @@ public final class TestPictures extends TestCase {
 
         Picture pic1 = pics.get(0);
         assertEquals(27, pic1.getAspectRatioX());
+        assertEquals(270, pic1.getHorizontalScalingFactor());
         assertEquals(27, pic1.getAspectRatioY());
+        assertEquals(271, pic1.getVerticalScalingFactor());
         assertEquals(12000, pic1.getDxaGoal());       // 21.17 cm / 2.54 cm/inch * 72dpi * 20 = 12000
         assertEquals(9000, pic1.getDyaGoal());        // 15.88 cm / 2.54 cm/inch * 72dpi * 20 = 9000
         assertEquals(0, pic1.getDxaCropLeft());
@@ -323,7 +326,9 @@ public final class TestPictures extends TestCase {
         Picture pic2 = pics.get(1);
         System.out.println(pic2.getWidth());
         assertEquals(76, pic2.getAspectRatioX());
+        assertEquals(764, pic2.getHorizontalScalingFactor());
         assertEquals(68, pic2.getAspectRatioY());
+        assertEquals(685, pic2.getVerticalScalingFactor());
         assertEquals(12000, pic2.getDxaGoal());       // 21.17 cm / 2.54 cm/inch * 72dpi * 20 = 12000
         assertEquals(9000, pic2.getDyaGoal());        // 15.88 cm / 2.54 cm/inch * 72dpi * 20 = 9000
         assertEquals(0, pic2.getDxaCropLeft());       // TODO YK: The Picture is cropped but HWPF reads the crop parameters all zeros
diff --git a/test-data/document/picture.doc b/test-data/document/picture.doc
new file mode 100644 (file)
index 0000000..c48038d
Binary files /dev/null and b/test-data/document/picture.doc differ