]> source.dussan.org Git - poi.git/commitdiff
add initial code for office drawings (and pictures saved as such drawings)
authorSergey Vladimirov <sergey@apache.org>
Thu, 28 Jul 2011 13:46:57 +0000 (13:46 +0000)
committerSergey Vladimirov <sergey@apache.org>
Thu, 28 Jul 2011 13:46:57 +0000 (13:46 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1151845 13f79535-47bb-0310-9956-ffa450edef68

17 files changed:
src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordUtils.java
src/scratchpad/src/org/apache/poi/hwpf/dev/HWPFLister.java
src/scratchpad/src/org/apache/poi/hwpf/model/FIBFieldHandler.java
src/scratchpad/src/org/apache/poi/hwpf/model/FSPA.java
src/scratchpad/src/org/apache/poi/hwpf/model/FSPADocumentPart.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/model/FSPATable.java
src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java
src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/ShapesTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawing.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawings.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawingsImpl.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Shape.java
src/types/definitions/fspa_type.xml [new file with mode: 0644]

index b426be0e687d6e1268696a96986754ebff6f1ffc..b2d46604594fd7a738f60a456b2440b939cd65cb 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.poi.hwpf.model.CPSplitCalculator;
 import org.apache.poi.hwpf.model.ComplexFileTable;
 import org.apache.poi.hwpf.model.DocumentProperties;
 import org.apache.poi.hwpf.model.EscherRecordHolder;
+import org.apache.poi.hwpf.model.FSPADocumentPart;
 import org.apache.poi.hwpf.model.FSPATable;
 import org.apache.poi.hwpf.model.FieldsTables;
 import org.apache.poi.hwpf.model.FontTable;
@@ -57,6 +58,8 @@ import org.apache.poi.hwpf.usermodel.FieldsImpl;
 import org.apache.poi.hwpf.usermodel.HWPFList;
 import org.apache.poi.hwpf.usermodel.Notes;
 import org.apache.poi.hwpf.usermodel.NotesImpl;
+import org.apache.poi.hwpf.usermodel.OfficeDrawings;
+import org.apache.poi.hwpf.usermodel.OfficeDrawingsImpl;
 import org.apache.poi.hwpf.usermodel.Range;
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -99,18 +102,28 @@ public final class HWPFDocument extends HWPFDocumentCore
   /** Holds the revision mark authors for this document. */
   protected RevisionMarkAuthorTable _rmat;
 
-  /** Holds pictures table */
-  protected PicturesTable _pictures;
+  /** Holds FSBA (shape) information */
+  private FSPATable _fspaHeaders;
 
   /** Holds FSBA (shape) information */
-  protected FSPATable _fspa;
+  private FSPATable _fspaMain;
 
   /** Escher Drawing Group information */
-  protected EscherRecordHolder _dgg;
+  protected EscherRecordHolder _escherRecordHolder;
+
+  /** Holds pictures table */
+  protected PicturesTable _pictures;
 
   /** Holds Office Art objects */
+  @Deprecated
   protected ShapesTable _officeArts;
   
+  /** Holds Office Art objects */
+  protected OfficeDrawingsImpl _officeDrawingsHeaders;
+
+  /** Holds Office Art objects */
+  protected OfficeDrawingsImpl _officeDrawingsMain;
+
   /** Holds the bookmarks tables */
   protected BookmarksTables _bookmarksTables;
 
@@ -276,22 +289,30 @@ public final class HWPFDocument extends HWPFDocumentCore
                     0 ) ) );
         }
 
-    // Read FSPA and Escher information
-    _fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(), _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
+        // Read FSPA and Escher information
+        // _fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(),
+        // _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
+        _fspaHeaders = new FSPATable( _tableStream, _fib,
+                FSPADocumentPart.HEADER );
+        _fspaMain = new FSPATable( _tableStream, _fib, FSPADocumentPart.MAIN );
 
     if (_fib.getFcDggInfo() != 0)
     {
-        _dgg = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
+        _escherRecordHolder = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
     } else
     {
-        _dgg = new EscherRecordHolder();
+        _escherRecordHolder = new EscherRecordHolder();
     }
 
     // read in the pictures stream
-    _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg);
+    _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspaMain, _escherRecordHolder);
     // And the art shapes stream
     _officeArts = new ShapesTable(_tableStream, _fib);
 
+    // And escher pictures
+    _officeDrawingsHeaders = new OfficeDrawingsImpl( _fspaHeaders, _escherRecordHolder );
+    _officeDrawingsMain = new OfficeDrawingsImpl( _fspaMain , _escherRecordHolder);
+
     _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, _tpt, _cpSplit);
     _ss = new StyleSheet(_tableStream, _fib.getFcStshf());
     _ft = new FontTable(_tableStream, _fib.getFcSttbfffn(), _fib.getLcbSttbfffn());
@@ -498,13 +519,31 @@ public final class HWPFDocument extends HWPFDocumentCore
          return _pictures;
   }
 
-  /**
-   * @return ShapesTable object, that is able to extract office are shapes from this document
-   */
-  public ShapesTable getShapesTable() {
-         return _officeArts;
+  public EscherRecordHolder getEscherRecordHolder() {
+      return _escherRecordHolder;
   }
 
+    /**
+     * @return ShapesTable object, that is able to extract office are shapes
+     *         from this document
+     * @deprecated use {@link #getOfficeDrawingsMain()} instead
+     */
+    @Deprecated
+    public ShapesTable getShapesTable()
+    {
+        return _officeArts;
+    }
+
+    public OfficeDrawings getOfficeDrawingsHeaders()
+    {
+        return _officeDrawingsHeaders;
+    }
+
+    public OfficeDrawings getOfficeDrawingsMain()
+    {
+        return _officeDrawingsMain;
+    }
+
     /**
      * @return user-friendly interface to access document bookmarks
      */
index 45e29a4a8a59c7e31350ba039bb2d9bb619a9f78..b65e8cf713d529e4b5fa2c790f1abee0fd912fd1 100644 (file)
@@ -38,6 +38,7 @@ import org.apache.poi.hwpf.usermodel.Bookmark;
 import org.apache.poi.hwpf.usermodel.CharacterRun;
 import org.apache.poi.hwpf.usermodel.Field;
 import org.apache.poi.hwpf.usermodel.Notes;
+import org.apache.poi.hwpf.usermodel.OfficeDrawing;
 import org.apache.poi.hwpf.usermodel.Paragraph;
 import org.apache.poi.hwpf.usermodel.Picture;
 import org.apache.poi.hwpf.usermodel.Range;
@@ -65,6 +66,8 @@ public abstract class AbstractWordConverter
 
     private static final byte SPECCHAR_AUTONUMBERED_FOOTNOTE_REFERENCE = 2;
 
+    private static final byte SPECCHAR_DRAWN_OBJECT = 8;
+
     private static final char UNICODECHAR_NONBREAKING_HYPHEN = '\u2011';
 
     private static final char UNICODECHAR_ZERO_WIDTH_SPACE = '\u200b';
@@ -381,6 +384,13 @@ public abstract class AbstractWordConverter
                     processNoteAnchor( doc, characterRun, block );
                     continue;
                 }
+                if ( text.charAt( 0 ) == SPECCHAR_DRAWN_OBJECT
+                        && ( document instanceof HWPFDocument ) )
+                {
+                    HWPFDocument doc = (HWPFDocument) document;
+                    processDrawnObject( doc, characterRun, block );
+                    continue;
+                }
             }
 
             if ( text.getBytes()[0] == FIELD_BEGIN_MARK )
@@ -565,6 +575,23 @@ public abstract class AbstractWordConverter
         }
     }
 
+    protected void processDrawnObject( HWPFDocument doc,
+            CharacterRun characterRun, Element block )
+    {
+        // main?
+        OfficeDrawing officeDrawing = doc.getOfficeDrawingsMain()
+                .getOfficeDrawingAt( characterRun.getStartOffset() );
+        if ( officeDrawing == null )
+        {
+            logger.log( POILogger.WARN, "Characters #" + characterRun
+                    + " references missing drawn object" );
+            return;
+        }
+
+        // TODO: do something :)
+
+    }
+
     protected abstract void processEndnoteAutonumbered( HWPFDocument doc,
             int noteIndex, Element block, Range endnoteTextRange );
 
index 5e4dc654269920229d881f575465c6fa7d7a3718..8ed299f4ed59b4bcb5fc89f7cb81a9fed643e6df 100644 (file)
@@ -23,9 +23,6 @@ import java.io.InputStream;
 import java.util.Set;
 import java.util.TreeSet;
 
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
 import org.apache.poi.hwpf.HWPFDocument;
 import org.apache.poi.hwpf.HWPFDocumentCore;
 import org.apache.poi.hwpf.HWPFOldDocument;
@@ -39,6 +36,8 @@ import org.apache.poi.hwpf.usermodel.TableCell;
 import org.apache.poi.hwpf.usermodel.TableRow;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
@@ -387,6 +386,8 @@ public class AbstractWordUtils
     {
         switch ( languageCode )
         {
+        case 1024:
+            return EMPTY;
         case 1033:
             return "en-us";
         case 1049:
@@ -396,7 +397,7 @@ public class AbstractWordUtils
         default:
             logger.log( POILogger.WARN, "Uknown or unmapped language code: ",
                     Integer.valueOf( languageCode ) );
-            return "";
+            return EMPTY;
         }
     }
 
index 15917978562326efe447dd69742d52ce92d585a1..5aacf2edff4ba901e68ff737d32c93eab1f5a586 100644 (file)
@@ -43,6 +43,7 @@ import org.apache.poi.hwpf.sprm.SprmOperation;
 import org.apache.poi.hwpf.usermodel.Bookmark;
 import org.apache.poi.hwpf.usermodel.Bookmarks;
 import org.apache.poi.hwpf.usermodel.Field;
+import org.apache.poi.hwpf.usermodel.OfficeDrawing;
 import org.apache.poi.hwpf.usermodel.Paragraph;
 import org.apache.poi.hwpf.usermodel.Picture;
 import org.apache.poi.hwpf.usermodel.Range;
@@ -97,7 +98,9 @@ public final class HWPFLister
                             + "\t\t[--chpx] [--chpxProperties] [--chpxSprms]\n"
                             + "\t\t[--papx] [--papxProperties]\n"
                             + "\t\t[--paragraphs] [--paragraphsSprms] [--paragraphsText]\n"
-                            + "\t\t[--bookmarks]\n" +"\t\t[--fields]\n" + "\t\t[--pictures]\n"
+                            + "\t\t[--bookmarks]\n" + "\t\t[--escher]\n"
+                            + "\t\t[--fields]\n" + "\t\t[--pictures]\n"
+                            + "\t\t[--officeDrawings]\n"
                             + "\t\t[--writereadback]\n" );
             System.exit( 1 );
         }
@@ -117,8 +120,10 @@ public final class HWPFLister
         boolean outputPapxProperties = false;
 
         boolean outputBookmarks = false;
+        boolean outputEscher = false;
         boolean outputFields = false;
         boolean outputPictures = false;
+        boolean outputOfficeDrawings = false;
 
         boolean writereadback = false;
 
@@ -150,8 +155,12 @@ public final class HWPFLister
 
             if ( "--bookmarks".equals( arg ) )
                 outputBookmarks = true;
+            if ( "--eschaer".equals( arg ) )
+                outputEscher = true;
             if ( "--fields".equals( arg ) )
                 outputFields = true;
+            if ( "--officeDrawings".equals( arg ) )
+                outputOfficeDrawings = true;
             if ( "--pictures".equals( arg ) )
                 outputPictures = true;
 
@@ -200,12 +209,24 @@ public final class HWPFLister
             lister.dumpBookmarks();
         }
 
+        if ( outputEscher )
+        {
+            System.out.println( "== ESCHER PROPERTIES ==" );
+            lister.dumpEscher();
+        }
+
         if ( outputFields )
         {
             System.out.println( "== FIELDS ==" );
             lister.dumpFields();
         }
 
+        if ( outputOfficeDrawings )
+        {
+            System.out.println( "== OFFICE DRAWINGS ==" );
+            lister.dumpOfficeDrawings();
+        }
+
         if ( outputPictures )
         {
             System.out.println( "== PICTURES ==" );
@@ -323,6 +344,17 @@ public final class HWPFLister
         }
     }
 
+    private void dumpEscher()
+    {
+        if ( _doc instanceof HWPFOldDocument )
+        {
+            System.out.println( "Word 95 not supported so far" );
+            return;
+        }
+        System.out.println( ( (HWPFDocument) _doc ).getEscherRecordHolder() );
+
+    }
+
     public void dumpFIB()
     {
         FileInformationBlock fib = _doc.getFileInformationBlock();
@@ -350,71 +382,88 @@ public final class HWPFLister
         }
     }
 
+    private void dumpOfficeDrawings()
+    {
+        if ( !( _doc instanceof HWPFDocument ) )
+        {
+            System.out.println( "Word 95 not supported so far" );
+            return;
+        }
+
+        HWPFDocument document = (HWPFDocument) _doc;
+
+            System.out.println( "=== Document part: MAIN ===" );
+            for ( OfficeDrawing officeDrawing : document.getOfficeDrawingsMain().getOfficeDrawings() )
+            {
+                System.out.println( officeDrawing );
+            }
+    }
+
     public void dumpPapx( boolean withProperties ) throws Exception
     {
-//        if ( _doc instanceof HWPFDocument )
-//        {
-//            System.out.println( "binary PAP pages " );
-//
-//            HWPFDocument doc = (HWPFDocument) _doc;
-//
-//            java.lang.reflect.Field fMainStream = HWPFDocumentCore.class
-//                    .getDeclaredField( "_mainStream" );
-//            fMainStream.setAccessible( true );
-//            byte[] mainStream = (byte[]) fMainStream.get( _doc );
-//
-//            PlexOfCps binTable = new PlexOfCps( doc.getTableStream(), doc
-//                    .getFileInformationBlock().getFcPlcfbtePapx(), doc
-//                    .getFileInformationBlock().getLcbPlcfbtePapx(), 4 );
-//
-//            List<PAPX> papxs = new ArrayList<PAPX>();
-//
-//            int length = binTable.length();
-//            for ( int x = 0; x < length; x++ )
-//            {
-//                GenericPropertyNode node = binTable.getProperty( x );
-//
-//                int pageNum = LittleEndian.getInt( node.getBytes() );
-//                int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE
-//                        * pageNum;
-//
-//                PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(
-//                        mainStream, doc.getDataStream(), pageOffset,
-//                        doc.getTextTable() );
-//
-//                System.out.println( "* PFKP: " + pfkp );
-//
-//                for ( PAPX papx : pfkp.getPAPXs() )
-//                {
-//                    System.out.println( "** " + papx );
-//                    papxs.add( papx );
-//                    if ( papx != null && true )
-//                    {
-//                        SprmIterator sprmIt = new SprmIterator(
-//                                papx.getGrpprl(), 2 );
-//                        while ( sprmIt.hasNext() )
-//                        {
-//                            SprmOperation sprm = sprmIt.next();
-//                            System.out.println( "*** " + sprm.toString() );
-//                        }
-//                    }
-//
-//                }
-//            }
-//
-//            Collections.sort( papxs );
-//            System.out.println( "* Sorted by END" );
-//            for ( PAPX papx : papxs )
-//            {
-//                System.out.println( "** " + papx );
-//                SprmIterator sprmIt = new SprmIterator( papx.getGrpprl(), 2 );
-//                while ( sprmIt.hasNext() )
-//                {
-//                    SprmOperation sprm = sprmIt.next();
-//                    System.out.println( "*** " + sprm.toString() );
-//                }
-//            }
-//        }
+        // if ( _doc instanceof HWPFDocument )
+        // {
+        // System.out.println( "binary PAP pages " );
+        //
+        // HWPFDocument doc = (HWPFDocument) _doc;
+        //
+        // java.lang.reflect.Field fMainStream = HWPFDocumentCore.class
+        // .getDeclaredField( "_mainStream" );
+        // fMainStream.setAccessible( true );
+        // byte[] mainStream = (byte[]) fMainStream.get( _doc );
+        //
+        // PlexOfCps binTable = new PlexOfCps( doc.getTableStream(), doc
+        // .getFileInformationBlock().getFcPlcfbtePapx(), doc
+        // .getFileInformationBlock().getLcbPlcfbtePapx(), 4 );
+        //
+        // List<PAPX> papxs = new ArrayList<PAPX>();
+        //
+        // int length = binTable.length();
+        // for ( int x = 0; x < length; x++ )
+        // {
+        // GenericPropertyNode node = binTable.getProperty( x );
+        //
+        // int pageNum = LittleEndian.getInt( node.getBytes() );
+        // int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE
+        // * pageNum;
+        //
+        // PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(
+        // mainStream, doc.getDataStream(), pageOffset,
+        // doc.getTextTable() );
+        //
+        // System.out.println( "* PFKP: " + pfkp );
+        //
+        // for ( PAPX papx : pfkp.getPAPXs() )
+        // {
+        // System.out.println( "** " + papx );
+        // papxs.add( papx );
+        // if ( papx != null && true )
+        // {
+        // SprmIterator sprmIt = new SprmIterator(
+        // papx.getGrpprl(), 2 );
+        // while ( sprmIt.hasNext() )
+        // {
+        // SprmOperation sprm = sprmIt.next();
+        // System.out.println( "*** " + sprm.toString() );
+        // }
+        // }
+        //
+        // }
+        // }
+        //
+        // Collections.sort( papxs );
+        // System.out.println( "* Sorted by END" );
+        // for ( PAPX papx : papxs )
+        // {
+        // System.out.println( "** " + papx );
+        // SprmIterator sprmIt = new SprmIterator( papx.getGrpprl(), 2 );
+        // while ( sprmIt.hasNext() )
+        // {
+        // SprmOperation sprm = sprmIt.next();
+        // System.out.println( "*** " + sprm.toString() );
+        // }
+        // }
+        // }
 
         // for ( PAPX papx : _doc.getParagraphTable().getParagraphs() )
         // {
index 69232d9dd18d687fb7e4b0cad507977e51662703..ec43bea1ea62bf1954de069a9025f29d2385dc31 100644 (file)
@@ -80,7 +80,8 @@ public final class FIBFieldHandler
   public static final int PLCDOAHDR = 39;
     // 474 == 0x01DA; 478 == 0x01DE
     public static final int PLCSPAMOM = 40;
-  public static final int PLCSPAHDR = 41;
+    // 482 == 0x01E2; 490 == 0x01E6
+    public static final int PLCSPAHDR = 41;
     public static final int PLCFATNBKF = 42;
     // 498 == 0x01F2; 502 == 0x01F6
     public static final int PLCFATNBKL = 43;
index 2f683589d1de3971b0993d5ac42010ac04c19547..d914f82e285ebc7c1850c20f3b23e38e6c59914b 100644 (file)
 
 package org.apache.poi.hwpf.model;
 
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.hwpf.model.types.FSPAAbstractType;
+import org.apache.poi.util.Internal;
 
 /**
  * File Shape Address structure
- *
+ * 
  * @author Squeeself
  */
-public final class FSPA
+@Internal
+public final class FSPA extends FSPAAbstractType
 {
-    public static final int FSPA_SIZE = 26;
-    private int spid; // Shape identifier. Used to get data position
-    private int xaLeft; // Enclosing rectangle
-    private int yaTop; // Enclosing rectangle
-    private int xaRight; // Enclosing rectangle
-    private int yaBottom; // Enclosing rectangle
-    private short options;
-        private static BitField fHdr = BitFieldFactory.getInstance(0x0001); // 1 in undo when in header
-        private static BitField bx = BitFieldFactory.getInstance(0x0006); // x pos relative to anchor CP: 0 - page margin, 1 - top of page, 2 - text, 3 - reserved
-        private static BitField by = BitFieldFactory.getInstance(0x0018); // y pos relative to anchor CP: ditto
-        private static BitField wr = BitFieldFactory.getInstance(0x01E0); // Text wrapping mode: 0 - like 2 w/o absolute, 1 - no text next to shape, 2 - wrap around absolute object, 3 - wrap as if no object, 4 - wrap tightly around object, 5 - wrap tightly, allow holes, 6-15 - reserved
-        private static BitField wrk = BitFieldFactory.getInstance(0x1E00); // Text wrapping mode type (for modes 2&4): 0 - wrap both sides, 1 - wrap only left, 2 - wrap only right, 3 - wrap largest side
-        private static BitField fRcaSimple = BitFieldFactory.getInstance(0x2000); // Overwrites bx if set, forcing rectangle to be page relative
-        private static BitField fBelowText = BitFieldFactory.getInstance(0x4000); // if true, shape is below text, otherwise above
-        private static BitField fAnchorLock = BitFieldFactory.getInstance(0x8000); // if true, anchor is locked
-    private int cTxbx; // Count of textboxes in shape (undo doc only)
+    @Deprecated
+    public static final int FSPA_SIZE = getSize(); // 26
 
     public FSPA()
     {
     }
 
-    public FSPA(byte[] bytes, int offset)
+    public FSPA( byte[] bytes, int offset )
     {
-        spid = LittleEndian.getInt(bytes, offset);
-        offset += LittleEndian.INT_SIZE;
-        xaLeft = LittleEndian.getInt(bytes, offset);
-        offset += LittleEndian.INT_SIZE;
-        yaTop = LittleEndian.getInt(bytes, offset);
-        offset += LittleEndian.INT_SIZE;
-        xaRight = LittleEndian.getInt(bytes, offset);
-        offset += LittleEndian.INT_SIZE;
-        yaBottom = LittleEndian.getInt(bytes, offset);
-        offset += LittleEndian.INT_SIZE;
-        options = LittleEndian.getShort(bytes, offset);
-        offset += LittleEndian.SHORT_SIZE;
-        cTxbx = LittleEndian.getInt(bytes, offset);
-    }
-
-    public int getSpid()
-    {
-        return spid;
-    }
-
-    public int getXaLeft()
-    {
-        return xaLeft;
-    }
-
-    public int getYaTop()
-    {
-        return yaTop;
-    }
-
-    public int getXaRight()
-    {
-        return xaRight;
-    }
-
-    public int getYaBottom()
-    {
-        return yaBottom;
-    }
-
-    public boolean isFHdr()
-    {
-        return fHdr.isSet(options);
-    }
-
-    public short getBx()
-    {
-        return bx.getShortValue(options);
-    }
-
-    public short getBy()
-    {
-        return by.getShortValue(options);
-    }
-
-    public short getWr()
-    {
-        return wr.getShortValue(options);
-    }
-
-    public short getWrk()
-    {
-        return wrk.getShortValue(options);
-    }
-
-    public boolean isFRcaSimple()
-    {
-        return fRcaSimple.isSet(options);
-    }
-
-    public boolean isFBelowText()
-    {
-        return fBelowText.isSet(options);
-    }
-
-    public boolean isFAnchorLock()
-    {
-        return fAnchorLock.isSet(options);
-    }
-
-    public int getCTxbx()
-    {
-        return cTxbx;
+        fillFields( bytes, offset );
     }
 
     public byte[] toByteArray()
     {
-        int offset = 0;
         byte[] buf = new byte[FSPA_SIZE];
-
-        LittleEndian.putInt(buf, offset, spid);
-        offset += LittleEndian.INT_SIZE;
-        LittleEndian.putInt(buf, offset, xaLeft);
-        offset += LittleEndian.INT_SIZE;
-        LittleEndian.putInt(buf, offset, yaTop);
-        offset += LittleEndian.INT_SIZE;
-        LittleEndian.putInt(buf, offset, xaRight);
-        offset += LittleEndian.INT_SIZE;
-        LittleEndian.putInt(buf, offset, yaBottom);
-        offset += LittleEndian.INT_SIZE;
-        LittleEndian.putShort(buf, offset, options);
-        offset += LittleEndian.SHORT_SIZE;
-        LittleEndian.putInt(buf, offset, cTxbx);
-        offset += LittleEndian.INT_SIZE;
-
+        serialize( buf, 0 );
         return buf;
     }
 
-    public String toString()
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append("spid: ").append(spid);
-        buf.append(", xaLeft: ").append(xaLeft);
-        buf.append(", yaTop: ").append(yaTop);
-        buf.append(", xaRight: ").append(xaRight);
-        buf.append(", yaBottom: ").append(yaBottom);
-        buf.append(", options: ").append(options);
-            buf.append(" (fHdr: ").append(isFHdr());
-            buf.append(", bx: ").append(getBx());
-            buf.append(", by: ").append(getBy());
-            buf.append(", wr: ").append(getWr());
-            buf.append(", wrk: ").append(getWrk());
-            buf.append(", fRcaSimple: ").append(isFRcaSimple());
-            buf.append(", fBelowText: ").append(isFBelowText());
-            buf.append(", fAnchorLock: ").append(isFAnchorLock());
-        buf.append("), cTxbx: ").append(cTxbx);
-        return buf.toString();
-    }
 }
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/FSPADocumentPart.java b/src/scratchpad/src/org/apache/poi/hwpf/model/FSPADocumentPart.java
new file mode 100644 (file)
index 0000000..53ce9db
--- /dev/null
@@ -0,0 +1,19 @@
+package org.apache.poi.hwpf.model;
+
+public enum FSPADocumentPart {
+    HEADER( FIBFieldHandler.PLCSPAHDR ),
+
+    MAIN( FIBFieldHandler.PLCSPAMOM );
+
+    private final int fibFieldsField;
+
+    private FSPADocumentPart( final int fibHandlerField )
+    {
+        this.fibFieldsField = fibHandlerField;
+    }
+
+    public int getFibFieldsField()
+    {
+        return fibFieldsField;
+    }
+}
index 40a4fb944690a9513314fda03ccb124d56768161..c192b3ef5c44c64f7d13f46523f3db0ab0a6c3e4 100644 (file)
 package org.apache.poi.hwpf.model;
 
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.poi.util.Internal;
+
 /**
  * This class holds all the FSPA (File Shape Address) structures.
- *
+ * 
  * @author Squeeself
  */
+@Internal
 public final class FSPATable
 {
-    private final List<FSPA> _shapes = new ArrayList<FSPA>();
-    private final Map<Integer, Integer> _shapeIndexesByPropertyStart = new HashMap<Integer, Integer>();
-    private final List<TextPiece> _text;
 
-    public FSPATable(byte[] tableStream, int fcPlcspa, int lcbPlcspa, List<TextPiece> tpt)
+    private final Map<Integer, GenericPropertyNode> _byStart = new LinkedHashMap<Integer, GenericPropertyNode>();
+
+    public FSPATable( byte[] tableStream, FileInformationBlock fib,
+            FSPADocumentPart part )
+    {
+        int offset = fib.getFSPAPlcfOffset( part );
+        int length = fib.getFSPAPlcfLength( part );
+
+        PlexOfCps plex = new PlexOfCps( tableStream, offset, length,
+                FSPA.getSize() );
+        for ( int i = 0; i < plex.length(); i++ )
+        {
+            GenericPropertyNode property = plex.getProperty( i );
+            _byStart.put( Integer.valueOf( property.getStart() ), property );
+        }
+    }
+
+    @Deprecated
+    public FSPATable( byte[] tableStream, int fcPlcspa, int lcbPlcspa,
+            List<TextPiece> tpt )
     {
-        _text = tpt;
         // Will be 0 if no drawing objects in document
-        if (fcPlcspa == 0)
+        if ( fcPlcspa == 0 )
             return;
 
-        PlexOfCps plex = new PlexOfCps(tableStream, fcPlcspa, lcbPlcspa, FSPA.FSPA_SIZE);
-        for (int i=0; i < plex.length(); i++)
+        PlexOfCps plex = new PlexOfCps( tableStream, fcPlcspa, lcbPlcspa,
+                FSPA.FSPA_SIZE );
+        for ( int i = 0; i < plex.length(); i++ )
         {
-            GenericPropertyNode property = plex.getProperty(i);
-            FSPA fspa = new FSPA(property.getBytes(), 0);
-
-            _shapes.add(fspa);
-            _shapeIndexesByPropertyStart.put(Integer.valueOf(property.getStart()), Integer.valueOf(i));
+            GenericPropertyNode property = plex.getProperty( i );
+            _byStart.put( Integer.valueOf( property.getStart() ), property );
         }
     }
 
-    public FSPA getFspaFromCp(int cp)
+    public FSPA getFspaFromCp( int cp )
     {
-        Integer idx = _shapeIndexesByPropertyStart.get(Integer.valueOf(cp));
-        if (idx == null) {
+        GenericPropertyNode propertyNode = _byStart.get( Integer.valueOf( cp ) );
+        if ( propertyNode == null )
+        {
             return null;
         }
-        return _shapes.get(idx.intValue());
+        return new FSPA( propertyNode.getBytes(), 0 );
     }
 
     public FSPA[] getShapes()
     {
-        FSPA[] result = new FSPA[_shapes.size()];
-        _shapes.toArray(result);
-        return result;
+        List<FSPA> result = new ArrayList<FSPA>( _byStart.size() );
+        for ( GenericPropertyNode propertyNode : _byStart.values() )
+        {
+            result.add( new FSPA( propertyNode.getBytes(), 0 ) );
+        }
+        return result.toArray( new FSPA[result.size()] );
     }
 
     public String toString()
     {
         StringBuffer buf = new StringBuffer();
-        buf.append("[FPSA PLC size=").append(_shapes.size()).append("]\n");
+        buf.append( "[FPSA PLC size=" ).append( _byStart.size() )
+                .append( "]\n" );
 
-        for (Map.Entry<Integer, Integer> entry: _shapeIndexesByPropertyStart.entrySet()) {
+        for ( Map.Entry<Integer, GenericPropertyNode> entry : _byStart
+                .entrySet() )
+        {
             Integer i = entry.getKey();
-            FSPA fspa = _shapes.get((entry.getValue()).intValue());
-            buf.append("  [FC: ").append(i.toString()).append("] ");
-            buf.append(fspa.toString());
-            buf.append("\n");
+            buf.append( "  " ).append( i.toString() ).append( " => \t" );
+
+            try
+            {
+                FSPA fspa = getFspaFromCp( i.intValue() );
+                buf.append( fspa.toString() );
+            }
+            catch ( Exception exc )
+            {
+                buf.append( exc.getMessage() );
+            }
+            buf.append( "\n" );
         }
-        buf.append("[/FSPA PLC]");
+        buf.append( "[/FSPA PLC]" );
         return buf.toString();
     }
 }
index f574d0939b105371d87fdfda4756218b370feced..60a22ab1b76811ed33085b14f2f81c4f878feb30 100644 (file)
@@ -849,11 +849,34 @@ public final class FileInformationBlock extends FIBAbstractType
         _fieldHandler.setFieldSize( FIBFieldHandler.PLCFFLDTXBX, size );
     }
 
+
+    public int getFSPAPlcfOffset( FSPADocumentPart part )
+    {
+        return _fieldHandler.getFieldOffset( part.getFibFieldsField() );
+    }
+
+    public int getFSPAPlcfLength( FSPADocumentPart part )
+    {
+        return _fieldHandler.getFieldSize( part.getFibFieldsField() );
+    }
+
+    public void setFSPAPlcfOffset( FSPADocumentPart part, int offset )
+    {
+        _fieldHandler.setFieldOffset( part.getFibFieldsField(), offset );
+    }
+
+    public void setFSPAPlcfLength( FSPADocumentPart part, int length )
+    {
+        _fieldHandler.setFieldSize( part.getFibFieldsField(), length );
+    }
+
+    @Deprecated
     public int getFcPlcspaMom()
     {
         return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
     }
 
+    @Deprecated
     public int getLcbPlcspaMom()
     {
         return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
index f904b6141b3707a93ef55cf6ba2263fd2c3f678a..cce3526e459d31d0642b702e4c1b53b5ec529bb9 100644 (file)
 
 package org.apache.poi.hwpf.model;
 
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.hwpf.usermodel.CharacterRun;
-import org.apache.poi.hwpf.usermodel.Picture;
-import org.apache.poi.hwpf.usermodel.Range;
-
-import java.util.List;
 import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.poi.ddf.DefaultEscherRecordFactory;
 import org.apache.poi.ddf.EscherBSERecord;
 import org.apache.poi.ddf.EscherBlipRecord;
 import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.ddf.EscherRecordFactory;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.CharacterRun;
+import org.apache.poi.hwpf.usermodel.Picture;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.util.LittleEndian;
 
 /**
  * Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
@@ -61,7 +61,9 @@ public final class PicturesTable
   private HWPFDocument _document;
   private byte[] _dataStream;
   private byte[] _mainStream;
+  @Deprecated
   private FSPATable _fspa;
+  @Deprecated
   private EscherRecordHolder _dgg;
 
   /** @link dependency
@@ -73,6 +75,7 @@ public final class PicturesTable
    * @param _document
    * @param _dataStream
    */
+  @Deprecated
   public PicturesTable(HWPFDocument _document, byte[] _dataStream, byte[] _mainStream, FSPATable fspa, EscherRecordHolder dgg)
   {
     this._document = _document;
@@ -82,6 +85,14 @@ public final class PicturesTable
     this._dgg = dgg;
   }
 
+    public PicturesTable( HWPFDocument _document, byte[] _dataStream,
+            byte[] _mainStream )
+    {
+        this._document = _document;
+        this._dataStream = _dataStream;
+        this._mainStream = _mainStream;
+    }
+
   /**
    * determines whether specified CharacterRun contains reference to a picture
    * @param run
index 3d42b8866b42d171c8721a61b2861e7b2d0f577e..5428215133c065944160a7d176c56e086c3e0f30 100644 (file)
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.poi.hwpf.usermodel.Shape;
 
+@Deprecated
 public final class ShapesTable {
         private List<Shape> _shapes;
         private List<Shape> _shapesVisibili;  //holds visible shapes
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java b/src/scratchpad/src/org/apache/poi/hwpf/model/types/FSPAAbstractType.java
new file mode 100644 (file)
index 0000000..a3a916d
--- /dev/null
@@ -0,0 +1,411 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.hwpf.model.types;\r
+\r
+\r
+import org.apache.poi.util.BitField;\r
+import org.apache.poi.util.Internal;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+/**\r
+ * File Shape Address (FSPA).\r
+ * <p>\r
+ * Class and fields descriptions are quoted from Microsoft Office Word 97-2007\r
+ * Binary File Format\r
+ * \r
+ * <p>\r
+ * NOTE: This source is automatically generated please do not modify this file.\r
+ * Either subclass or remove the record in src/types/definitions.\r
+ * <p>\r
+ * This class is internal. It content or properties may change without notice\r
+ * due to changes in our knowledge of internal Microsoft Word binary structures.\r
+ * \r
+ * @author Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary\r
+ *         File Format Specification [*.doc]\r
+ */\r
+@Internal\r
+public abstract class FSPAAbstractType\r
+{\r
+\r
+    protected int field_1_spid;\r
+    protected int field_2_xaLeft;\r
+    protected int field_3_yaTop;\r
+    protected int field_4_xaRight;\r
+    protected int field_5_yaBottom;\r
+    protected short field_6_flags;\r
+    /**/private static BitField fHdr = new BitField(0x0001);\r
+    /**/private static BitField bx = new BitField(0x0006);\r
+    /**/private static BitField by = new BitField(0x0018);\r
+    /**/private static BitField wr = new BitField(0x01E0);\r
+    /**/private static BitField wrk = new BitField(0x1E00);\r
+    /**/private static BitField fRcaSimple = new BitField(0x2000);\r
+    /**/private static BitField fBelowText = new BitField(0x4000);\r
+    /**/private static BitField fAnchorLock = new BitField(0x8000);\r
+    protected int field_7_cTxbx;\r
+\r
+    protected FSPAAbstractType()\r
+    {\r
+    }\r
+\r
+    protected void fillFields( byte[] data, int offset )\r
+    {\r
+        field_1_spid                   = LittleEndian.getInt(data, 0x0 + offset);\r
+        field_2_xaLeft                 = LittleEndian.getInt(data, 0x4 + offset);\r
+        field_3_yaTop                  = LittleEndian.getInt(data, 0x8 + offset);\r
+        field_4_xaRight                = LittleEndian.getInt(data, 0xc + offset);\r
+        field_5_yaBottom               = LittleEndian.getInt(data, 0x10 + offset);\r
+        field_6_flags                  = LittleEndian.getShort(data, 0x14 + offset);\r
+        field_7_cTxbx                  = LittleEndian.getInt(data, 0x16 + offset);\r
+    }\r
+\r
+    public void serialize( byte[] data, int offset )\r
+    {\r
+        LittleEndian.putInt(data, 0x0 + offset, field_1_spid);\r
+        LittleEndian.putInt(data, 0x4 + offset, field_2_xaLeft);\r
+        LittleEndian.putInt(data, 0x8 + offset, field_3_yaTop);\r
+        LittleEndian.putInt(data, 0xc + offset, field_4_xaRight);\r
+        LittleEndian.putInt(data, 0x10 + offset, field_5_yaBottom);\r
+        LittleEndian.putShort(data, 0x14 + offset, (short)field_6_flags);\r
+        LittleEndian.putInt(data, 0x16 + offset, field_7_cTxbx);\r
+    }\r
+\r
+    /**\r
+     * Size of record\r
+     */\r
+    public static int getSize()\r
+    {\r
+        return 0 + 4 + 4 + 4 + 4 + 4 + 2 + 4;\r
+    }\r
+\r
+    public String toString()\r
+    {\r
+        StringBuilder builder = new StringBuilder();\r
+        builder.append("[FSPA]\n");\r
+        builder.append("    .spid                 = ");\r
+        builder.append(" (").append(getSpid()).append(" )\n");\r
+        builder.append("    .xaLeft               = ");\r
+        builder.append(" (").append(getXaLeft()).append(" )\n");\r
+        builder.append("    .yaTop                = ");\r
+        builder.append(" (").append(getYaTop()).append(" )\n");\r
+        builder.append("    .xaRight              = ");\r
+        builder.append(" (").append(getXaRight()).append(" )\n");\r
+        builder.append("    .yaBottom             = ");\r
+        builder.append(" (").append(getYaBottom()).append(" )\n");\r
+        builder.append("    .flags                = ");\r
+        builder.append(" (").append(getFlags()).append(" )\n");\r
+        builder.append("         .fHdr                     = ").append(isFHdr()).append('\n');\r
+        builder.append("         .bx                       = ").append(getBx()).append('\n');\r
+        builder.append("         .by                       = ").append(getBy()).append('\n');\r
+        builder.append("         .wr                       = ").append(getWr()).append('\n');\r
+        builder.append("         .wrk                      = ").append(getWrk()).append('\n');\r
+        builder.append("         .fRcaSimple               = ").append(isFRcaSimple()).append('\n');\r
+        builder.append("         .fBelowText               = ").append(isFBelowText()).append('\n');\r
+        builder.append("         .fAnchorLock              = ").append(isFAnchorLock()).append('\n');\r
+        builder.append("    .cTxbx                = ");\r
+        builder.append(" (").append(getCTxbx()).append(" )\n");\r
+\r
+        builder.append("[/FSPA]\n");\r
+        return builder.toString();\r
+    }\r
+\r
+    /**\r
+     * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape.\r
+     */\r
+    @Internal\r
+    public int getSpid()\r
+    {\r
+        return field_1_spid;\r
+    }\r
+\r
+    /**\r
+     * Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape.\r
+     */\r
+    @Internal\r
+    public void setSpid( int field_1_spid )\r
+    {\r
+        this.field_1_spid = field_1_spid;\r
+    }\r
+\r
+    /**\r
+     * Left of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public int getXaLeft()\r
+    {\r
+        return field_2_xaLeft;\r
+    }\r
+\r
+    /**\r
+     * Left of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public void setXaLeft( int field_2_xaLeft )\r
+    {\r
+        this.field_2_xaLeft = field_2_xaLeft;\r
+    }\r
+\r
+    /**\r
+     * Top of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public int getYaTop()\r
+    {\r
+        return field_3_yaTop;\r
+    }\r
+\r
+    /**\r
+     * Top of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public void setYaTop( int field_3_yaTop )\r
+    {\r
+        this.field_3_yaTop = field_3_yaTop;\r
+    }\r
+\r
+    /**\r
+     * Right of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public int getXaRight()\r
+    {\r
+        return field_4_xaRight;\r
+    }\r
+\r
+    /**\r
+     * Right of rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public void setXaRight( int field_4_xaRight )\r
+    {\r
+        this.field_4_xaRight = field_4_xaRight;\r
+    }\r
+\r
+    /**\r
+     * Bottom of the rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public int getYaBottom()\r
+    {\r
+        return field_5_yaBottom;\r
+    }\r
+\r
+    /**\r
+     * Bottom of the rectangle enclosing shape relative to the origin of the shape.\r
+     */\r
+    @Internal\r
+    public void setYaBottom( int field_5_yaBottom )\r
+    {\r
+        this.field_5_yaBottom = field_5_yaBottom;\r
+    }\r
+\r
+    /**\r
+     * Get the flags field for the FSPA record.\r
+     */\r
+    @Internal\r
+    public short getFlags()\r
+    {\r
+        return field_6_flags;\r
+    }\r
+\r
+    /**\r
+     * Set the flags field for the FSPA record.\r
+     */\r
+    @Internal\r
+    public void setFlags( short field_6_flags )\r
+    {\r
+        this.field_6_flags = field_6_flags;\r
+    }\r
+\r
+    /**\r
+     * Count of textboxes in shape (undo doc only).\r
+     */\r
+    @Internal\r
+    public int getCTxbx()\r
+    {\r
+        return field_7_cTxbx;\r
+    }\r
+\r
+    /**\r
+     * Count of textboxes in shape (undo doc only).\r
+     */\r
+    @Internal\r
+    public void setCTxbx( int field_7_cTxbx )\r
+    {\r
+        this.field_7_cTxbx = field_7_cTxbx;\r
+    }\r
+\r
+    /**\r
+     * Sets the fHdr field value.\r
+     * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc)\r
+     */\r
+    @Internal\r
+    public void setFHdr( boolean value )\r
+    {\r
+        field_6_flags = (short)fHdr.setBoolean(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc)\r
+     * @return  the fHdr field value.\r
+     */\r
+    @Internal\r
+    public boolean isFHdr()\r
+    {\r
+        return fHdr.isSet(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the bx field value.\r
+     * X position of shape relative to anchor CP\r
+     */\r
+    @Internal\r
+    public void setBx( byte value )\r
+    {\r
+        field_6_flags = (short)bx.setValue(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * X position of shape relative to anchor CP\r
+     * @return  the bx field value.\r
+     */\r
+    @Internal\r
+    public byte getBx()\r
+    {\r
+        return ( byte )bx.getValue(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the by field value.\r
+     * Y position of shape relative to anchor CP\r
+     */\r
+    @Internal\r
+    public void setBy( byte value )\r
+    {\r
+        field_6_flags = (short)by.setValue(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * Y position of shape relative to anchor CP\r
+     * @return  the by field value.\r
+     */\r
+    @Internal\r
+    public byte getBy()\r
+    {\r
+        return ( byte )by.getValue(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the wr field value.\r
+     * Text wrapping mode\r
+     */\r
+    @Internal\r
+    public void setWr( byte value )\r
+    {\r
+        field_6_flags = (short)wr.setValue(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * Text wrapping mode\r
+     * @return  the wr field value.\r
+     */\r
+    @Internal\r
+    public byte getWr()\r
+    {\r
+        return ( byte )wr.getValue(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the wrk field value.\r
+     * Text wrapping mode type (valid only for wrapping modes 2 and 4\r
+     */\r
+    @Internal\r
+    public void setWrk( byte value )\r
+    {\r
+        field_6_flags = (short)wrk.setValue(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * Text wrapping mode type (valid only for wrapping modes 2 and 4\r
+     * @return  the wrk field value.\r
+     */\r
+    @Internal\r
+    public byte getWrk()\r
+    {\r
+        return ( byte )wrk.getValue(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the fRcaSimple field value.\r
+     * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative.\r
+     */\r
+    @Internal\r
+    public void setFRcaSimple( boolean value )\r
+    {\r
+        field_6_flags = (short)fRcaSimple.setBoolean(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative.\r
+     * @return  the fRcaSimple field value.\r
+     */\r
+    @Internal\r
+    public boolean isFRcaSimple()\r
+    {\r
+        return fRcaSimple.isSet(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the fBelowText field value.\r
+     * \r
+     */\r
+    @Internal\r
+    public void setFBelowText( boolean value )\r
+    {\r
+        field_6_flags = (short)fBelowText.setBoolean(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * \r
+     * @return  the fBelowText field value.\r
+     */\r
+    @Internal\r
+    public boolean isFBelowText()\r
+    {\r
+        return fBelowText.isSet(field_6_flags);\r
+    }\r
+\r
+    /**\r
+     * Sets the fAnchorLock field value.\r
+     * \r
+     */\r
+    @Internal\r
+    public void setFAnchorLock( boolean value )\r
+    {\r
+        field_6_flags = (short)fAnchorLock.setBoolean(field_6_flags, value);\r
+    }\r
+\r
+    /**\r
+     * \r
+     * @return  the fAnchorLock field value.\r
+     */\r
+    @Internal\r
+    public boolean isFAnchorLock()\r
+    {\r
+        return fAnchorLock.isSet(field_6_flags);\r
+    }\r
+\r
+}  // END OF CLASS\r
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawing.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawing.java
new file mode 100644 (file)
index 0000000..20e3cc5
--- /dev/null
@@ -0,0 +1,31 @@
+package org.apache.poi.hwpf.usermodel;
+
+public interface OfficeDrawing
+{
+    /**
+     * Shape Identifier
+     */
+    int getShapeId();
+
+    /**
+     * Left of rectangle enclosing shape relative to the origin of the shape
+     */
+    int getRectangleLeft();
+
+    /**
+     * Top of rectangle enclosing shape relative to the origin of the shape
+     */
+    int getRectangleTop();
+
+    /**
+     * Right of rectangle enclosing shape relative to the origin of the shape
+     */
+    int getRectangleRight();
+
+    /**
+     * Bottom of the rectangle enclosing shape relative to the origin of the
+     * shape
+     */
+    int getRectangleBottom();
+
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawings.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawings.java
new file mode 100644 (file)
index 0000000..672d5e1
--- /dev/null
@@ -0,0 +1,10 @@
+package org.apache.poi.hwpf.usermodel;
+
+import java.util.Collection;
+
+public interface OfficeDrawings
+{
+    OfficeDrawing getOfficeDrawingAt( int characterPosition );
+
+    Collection<OfficeDrawing> getOfficeDrawings();
+}
diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawingsImpl.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/OfficeDrawingsImpl.java
new file mode 100644 (file)
index 0000000..933821c
--- /dev/null
@@ -0,0 +1,79 @@
+package org.apache.poi.hwpf.usermodel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.poi.hwpf.model.EscherRecordHolder;
+import org.apache.poi.hwpf.model.FSPA;
+import org.apache.poi.hwpf.model.FSPATable;
+
+public class OfficeDrawingsImpl implements OfficeDrawings
+{
+    private final EscherRecordHolder _escherRecordHolder;
+    private final FSPATable _fspaTable;
+
+    public OfficeDrawingsImpl( FSPATable fspaTable,
+            EscherRecordHolder escherRecordHolder )
+    {
+        this._fspaTable = fspaTable;
+        this._escherRecordHolder = escherRecordHolder;
+    }
+
+    private OfficeDrawing getOfficeDrawing( final FSPA fspa )
+    {
+        return new OfficeDrawing()
+        {
+            public int getRectangleBottom()
+            {
+                return fspa.getYaBottom();
+            }
+
+            public int getRectangleLeft()
+            {
+                return fspa.getXaLeft();
+            }
+
+            public int getRectangleRight()
+            {
+                return fspa.getXaRight();
+            }
+
+            public int getRectangleTop()
+            {
+                return fspa.getYaTop();
+            }
+
+            public int getShapeId()
+            {
+                return fspa.getSpid();
+            }
+
+            @Override
+            public String toString()
+            {
+                return "OfficeDrawingImpl: " + fspa.toString();
+            }
+        };
+    }
+
+    public OfficeDrawing getOfficeDrawingAt( int characterPosition )
+    {
+        final FSPA fspa = _fspaTable.getFspaFromCp( characterPosition );
+        if ( fspa == null )
+            return null;
+
+        return getOfficeDrawing( fspa );
+    }
+
+    public Collection<OfficeDrawing> getOfficeDrawings()
+    {
+        List<OfficeDrawing> result = new ArrayList<OfficeDrawing>();
+        for ( FSPA fspa : _fspaTable.getShapes() )
+        {
+            result.add( getOfficeDrawing( fspa ) );
+        }
+        return Collections.unmodifiableList( result );
+    }
+}
index aecc0d3461c41ff926596c7bd373b670f41635c2..3d3e136316dea43cef187754b21ef22a317ccc2f 100644 (file)
@@ -20,6 +20,10 @@ package org.apache.poi.hwpf.usermodel;
 import org.apache.poi.hwpf.model.GenericPropertyNode;
 import org.apache.poi.util.LittleEndian;
 
+/**
+ * @deprecated Use {@link OfficeDrawing} instead
+ */
+@Deprecated
 public final class Shape {
         int _id, _left, _right, _top, _bottom;
         /**
diff --git a/src/types/definitions/fspa_type.xml b/src/types/definitions/fspa_type.xml
new file mode 100644 (file)
index 0000000..42e464a
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<!--
+    ====================================================================
+    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.
+    ====================================================================
+-->
+<record fromfile="true" name="FSPA" package="org.apache.poi.hwpf.model.types">
+    <suffix>AbstractType</suffix>
+    <extends>HDFType</extends>
+    <description>File Shape Address (FSPA). &lt;p&gt;Class and fields descriptions are quoted from
+        Microsoft Office Word 97-2007 Binary File Format
+    </description>
+    <author>Sergey Vladimirov; according to Microsoft Office Word 97-2007 Binary File Format
+        Specification [*.doc]
+    </author>
+    <fields>
+        <field type="int" size="4" name="spid"
+            description="Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape"/>
+        <field type="int" size="4" name="xaLeft"
+            description="Left of rectangle enclosing shape relative to the origin of the shape"/>
+        <field type="int" size="4" name="yaTop"
+            description="Top of rectangle enclosing shape relative to the origin of the shape"/>
+        <field type="int" size="4" name="xaRight"
+            description="Right of rectangle enclosing shape relative to the origin of the shape"/>
+        <field type="int" size="4" name="yaBottom"
+            description="Bottom of the rectangle enclosing shape relative to the origin of the shape"/>
+        <field type="short" size="2" name="flags">
+            <bit number="0" mask="0x0001" name="fHdr"
+                description="1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc)"/>
+            <bit number="1" mask="0x0006" name="bx" description="X position of shape relative to anchor CP">
+                <const type="byte" value="0" name="PAGEMARGIN" description="relative to page margin"/>
+                <const type="byte" value="1" name="PAGETOP" description="relative to top of page"/>
+                <const type="byte" value="2" name="TEXT"
+                    description="relative to text (column for horizontal text; paragraph for vertical text)"/>
+                <const type="byte" value="3" name="RESERVED" description="reserved for future use"/>
+            </bit>
+            <bit number="2" mask="0x0018" name="by" description="Y position of shape relative to anchor CP">
+                <const type="byte" value="0" name="PAGEMARGIN" description="relative to page margin"/>
+                <const type="byte" value="1" name="PAGETOP" description="relative to top of page"/>
+                <const type="byte" value="2" name="TEXT"
+                    description="relative to text (paragraph for horizontal text; column for vertical text)"/>
+            </bit>
+            <bit number="3" mask="0x01E0" name="wr" description="Text wrapping mode">
+                <const type="byte" value="0" name="AROUNDABSOLUTENR"
+                    description="like 2, but doesn‘t require absolute object"/>
+                <const type="byte" value="1" name="NOTEXTNEXTTO" description="no text next to shape"/>
+                <const type="byte" value="2" name="AROUNDABSOLUTE" description="wrap around absolute object"/>
+                <const type="byte" value="3" name="NOOBJECT" description="wrap as if no object present"/>
+                <const type="byte" value="4" name="TIGHTLY" description="wrap tightly around object"/>
+                <const type="byte" value="5" name="TIGHTLYWITHHOLES" description="wrap tightly, but allow holes"/>
+            </bit>
+            <bit number="4" mask="0x1E00" name="wrk"
+                description="Text wrapping mode type (valid only for wrapping modes 2 and 4"/>
+            <bit number="5" mask="0x2000" name="fRcaSimple"
+                description="When set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative."/>
+            <bit number="6" mask="0x4000" name="fBelowText"/>
+            <bit number="7" mask="0x8000" name="fAnchorLock"/>
+        </field>
+        <field type="int" size="4" name="cTxbx" description="Count of textboxes in shape (undo doc only)"/>
+    </fields>
+</record>