View | Details | Raw Unified | Return to bug 44937
Collapse All | Expand All

(-)src/scratchpad/src/org/apache/poi/hwpf/model/FSPA.java (+182 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hwpf.model;
19
20
import org.apache.poi.util.BitField;
21
import org.apache.poi.util.BitFieldFactory;
22
import org.apache.poi.util.LittleEndian;
23
24
/**
25
 * File Shape Address structure
26
 * 
27
 * @author Squeeself
28
 */
29
public class FSPA 
30
{
31
    public static final int FSPA_SIZE = 26;
32
    private int spid; // Shape identifier. Used to get data position
33
    private int xaLeft; // Enclosing rectangle
34
    private int yaTop; // Enclosing rectangle
35
    private int xaRight; // Enclosing rectangle
36
    private int yaBottom; // Enclosing rectangle
37
    private short options;
38
        private static BitField fHdr = BitFieldFactory.getInstance(0x0001); // 1 in undo when in header
39
        private static BitField bx = BitFieldFactory.getInstance(0x0006); // x pos relative to anchor CP: 0 - page margin, 1 - top of page, 2 - text, 3 - reserved
40
        private static BitField by = BitFieldFactory.getInstance(0x0018); // y pos relative to anchor CP: ditto
41
        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
42
        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
43
        private static BitField fRcaSimple = BitFieldFactory.getInstance(0x2000); // Overwrites bx if set, forcing rectangle to be page relative
44
        private static BitField fBelowText = BitFieldFactory.getInstance(0x4000); // if true, shape is below text, otherwise above
45
        private static BitField fAnchorLock = BitFieldFactory.getInstance(0x8000); // if true, anchor is locked
46
    private int cTxbx; // Count of textboxes in shape (undo doc only)
47
    
48
    public FSPA()
49
    {
50
    }
51
    
52
    public FSPA(byte[] bytes, int offset)
53
    {
54
        spid = LittleEndian.getInt(bytes, offset);
55
        offset += LittleEndian.INT_SIZE;
56
        xaLeft = LittleEndian.getInt(bytes, offset);
57
        offset += LittleEndian.INT_SIZE;
58
        yaTop = LittleEndian.getInt(bytes, offset);
59
        offset += LittleEndian.INT_SIZE;
60
        xaRight = LittleEndian.getInt(bytes, offset);
61
        offset += LittleEndian.INT_SIZE;
62
        yaBottom = LittleEndian.getInt(bytes, offset);
63
        offset += LittleEndian.INT_SIZE;
64
        options = LittleEndian.getShort(bytes, offset);
65
        offset += LittleEndian.SHORT_SIZE;
66
        cTxbx = LittleEndian.getInt(bytes, offset);
67
    }
68
    
69
    public int getSpid()
70
    {
71
        return spid;
72
    }
73
    
74
    public int getXaLeft()
75
    {
76
        return xaLeft;
77
    }
78
    
79
    public int getYaTop()
80
    {
81
        return yaTop;
82
    }
83
    
84
    public int getXaRight()
85
    {
86
        return xaRight;
87
    }
88
    
89
    public int getYaBottom()
90
    {
91
        return yaBottom;
92
    }
93
    
94
    public boolean isFHdr()
95
    {
96
        return fHdr.isSet(options);
97
    }
98
    
99
    public short getBx()
100
    {
101
        return bx.getShortValue(options);
102
    }
103
    
104
    public short getBy()
105
    {
106
        return by.getShortValue(options);
107
    }
108
    
109
    public short getWr()
110
    {
111
        return wr.getShortValue(options);
112
    }
113
    
114
    public short getWrk()
115
    {
116
        return wrk.getShortValue(options);
117
    }
118
    
119
    public boolean isFRcaSimple()
120
    {
121
        return fRcaSimple.isSet(options);
122
    }
123
    
124
    public boolean isFBelowText()
125
    {
126
        return fBelowText.isSet(options);
127
    }
128
    
129
    public boolean isFAnchorLock()
130
    {
131
        return fAnchorLock.isSet(options);
132
    }
133
    
134
    public int getCTxbx()
135
    {
136
        return cTxbx;
137
    }
138
    
139
    public byte[] toByteArray()
140
    {
141
        int offset = 0;
142
        byte[] buf = new byte[FSPA_SIZE];
143
144
        LittleEndian.putInt(buf, offset, spid);
145
        offset += LittleEndian.INT_SIZE;
146
        LittleEndian.putInt(buf, offset, xaLeft);
147
        offset += LittleEndian.INT_SIZE;
148
        LittleEndian.putInt(buf, offset, yaTop);
149
        offset += LittleEndian.INT_SIZE;
150
        LittleEndian.putInt(buf, offset, xaRight);
151
        offset += LittleEndian.INT_SIZE;
152
        LittleEndian.putInt(buf, offset, yaBottom);
153
        offset += LittleEndian.INT_SIZE;
154
        LittleEndian.putShort(buf, offset, options);
155
        offset += LittleEndian.SHORT_SIZE;
156
        LittleEndian.putInt(buf, offset, cTxbx);
157
        offset += LittleEndian.INT_SIZE;
158
159
        return buf;
160
    }
161
    
162
    public String toString()
163
    {
164
        StringBuffer buf = new StringBuffer();
165
        buf.append("spid: ").append(spid);
166
        buf.append(", xaLeft: ").append(xaLeft);
167
        buf.append(", yaTop: ").append(yaTop);
168
        buf.append(", xaRight: ").append(xaRight);
169
        buf.append(", yaBottom: ").append(yaBottom);
170
        buf.append(", options: ").append(options);
171
            buf.append(" (fHdr: ").append(isFHdr());
172
            buf.append(", bx: ").append(getBx());
173
            buf.append(", by: ").append(getBy());
174
            buf.append(", wr: ").append(getWr());
175
            buf.append(", wrk: ").append(getWrk());
176
            buf.append(", fRcaSimple: ").append(isFRcaSimple());
177
            buf.append(", fBelowText: ").append(isFBelowText());
178
            buf.append(", fAnchorLock: ").append(isFAnchorLock());
179
        buf.append("), cTxbx: ").append(cTxbx);
180
        return buf.toString();
181
    }
182
}
0
  + native
183
  + native
(-)src/scratchpad/src/org/apache/poi/hwpf/model/FSPATable.java (+82 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.hwpf.model;
19
20
import java.util.ArrayList;
21
import java.util.HashMap;
22
import java.util.Iterator;
23
import java.util.List;
24
25
/**
26
 * This class holds all the FSPA (File Shape Address) structures.
27
 * 
28
 * @author Squeeself
29
 */
30
public class FSPATable 
31
{
32
    protected ArrayList shapes = new ArrayList();
33
    protected HashMap cps = new HashMap();
34
    protected List _text;
35
    
36
    public FSPATable(byte[] tableStream, int fcPlcspa, int lcbPlcspa, List tpt)
37
    {
38
        _text = tpt;
39
        // Will be 0 if no drawing objects in document
40
        if (fcPlcspa == 0)
41
            return;
42
        
43
        PlexOfCps plex = new PlexOfCps(tableStream, fcPlcspa, lcbPlcspa, FSPA.FSPA_SIZE);
44
        for (int i=0; i < plex.length(); i++)
45
        {
46
            GenericPropertyNode property = plex.getProperty(i);
47
            FSPA fspa = new FSPA(property.getBytes(), 0);
48
            
49
            shapes.add(fspa);
50
            cps.put(Integer.valueOf(property.getStart()), Integer.valueOf(i));
51
        }
52
    }
53
    
54
    public FSPA getFspaFromCp(int cp)
55
    {
56
        Integer idx = (Integer)cps.get(Integer.valueOf(cp));
57
        if (idx == null)
58
            return null;
59
        return (FSPA)shapes.get(idx.intValue());
60
    }
61
    
62
    public List getShapes()
63
    {
64
        return shapes;
65
    }
66
    
67
    public String toString()
68
    {
69
        StringBuffer buf = new StringBuffer();
70
        buf.append("[FPSA PLC size=").append(shapes.size()).append("]\n");
71
        for (Iterator it = cps.keySet().iterator(); it.hasNext(); )
72
        {
73
            Integer i = (Integer) it.next();
74
            FSPA fspa = (FSPA) shapes.get(((Integer)cps.get(i)).intValue());
75
            buf.append("  [FC: ").append(i.toString()).append("] ");
76
            buf.append(fspa.toString());
77
            buf.append("\n");
78
        }
79
        buf.append("[/FSPA PLC]");
80
        return buf.toString();
81
    }
82
}
0
  + native
83
  + native
(-)src/scratchpad/src/org/apache/poi/hwpf/model/EscherRecordHolder.java (+116 lines)
Line 0 Link Here
1
/*
2
 * To change this template, choose Tools | Templates
3
 * and open the template in the editor.
4
 */
5
6
package org.apache.poi.hwpf.model;
7
8
import java.util.ArrayList;
9
import java.util.Iterator;
10
import java.util.List;
11
import org.apache.poi.ddf.DefaultEscherRecordFactory;
12
import org.apache.poi.ddf.EscherContainerRecord;
13
import org.apache.poi.ddf.EscherRecord;
14
import org.apache.poi.ddf.EscherRecordFactory;
15
16
/**
17
 * Based on AbstractEscherRecordHolder fomr HSSF.
18
 * 
19
 * @author Squeeself
20
 */
21
public class EscherRecordHolder 
22
{
23
    protected ArrayList escherRecords = new ArrayList();
24
    
25
    public EscherRecordHolder()
26
    {
27
        
28
    }
29
    
30
    public EscherRecordHolder(byte[] data, int offset, int size)
31
    {
32
        fillEscherRecords(data, offset, size);
33
    }
34
    
35
    private void fillEscherRecords(byte[] data, int offset, int size)
36
    {
37
        EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
38
        int pos = offset;
39
        while ( pos < offset + size)
40
        {
41
            EscherRecord r = recordFactory.createRecord(data, pos);
42
            escherRecords.add(r);
43
            int bytesRead = r.fillFields(data, pos, recordFactory);
44
            pos += bytesRead + 1; // There is an empty byte between each top-level record in a Word doc
45
        }
46
    }
47
    
48
    public List getEscherRecords()
49
    {
50
        return escherRecords;
51
    }
52
    
53
    public String toString()
54
    {
55
        StringBuffer buffer = new StringBuffer();
56
57
        final String nl = System.getProperty("line.separator");
58
        if (escherRecords.size() == 0)
59
            buffer.append("No Escher Records Decoded" + nl);
60
        for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
61
        {
62
            EscherRecord r = (EscherRecord) iterator.next();
63
            buffer.append(r.toString());
64
        }
65
66
        return buffer.toString();
67
    }
68
    
69
    /**
70
     * If we have a EscherContainerRecord as one of our
71
     *  children (and most top level escher holders do),
72
     *  then return that.
73
     */
74
    public EscherContainerRecord getEscherContainer() {
75
    	for(Iterator it = escherRecords.iterator(); it.hasNext();) {
76
    		Object er = it.next();
77
    		if(er instanceof EscherContainerRecord) {
78
    			return (EscherContainerRecord)er;
79
    		}
80
    	}
81
    	return null;
82
    }
83
84
    /**
85
     * Descends into all our children, returning the
86
     *  first EscherRecord with the given id, or null
87
     *  if none found
88
     */
89
    public EscherRecord findFirstWithId(short id) {
90
    	return findFirstWithId(id, getEscherRecords());
91
    }
92
    private EscherRecord findFirstWithId(short id, List records) {
93
    	// Check at our level
94
    	for(Iterator it = records.iterator(); it.hasNext();) {
95
    		EscherRecord r = (EscherRecord)it.next();
96
    		if(r.getRecordId() == id) {
97
    			return r;
98
    		}
99
    	}
100
    	
101
    	// Then check our children in turn
102
    	for(Iterator it = records.iterator(); it.hasNext();) {
103
    		EscherRecord r = (EscherRecord)it.next();
104
    		if(r.isContainerRecord()) {
105
    			EscherRecord found =
106
    				findFirstWithId(id, r.getChildRecords());
107
    			if(found != null) {
108
    				return found;
109
    			}
110
    		}
111
    	}
112
    	
113
    	// Not found in this lot
114
    	return null;
115
    }
116
}
0
  + native
117
  + native
(-)src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java (-14 / +21 lines)
Lines 65-84 Link Here
65
        int size           = 0;
65
        int size           = 0;
66
66
67
        // Always find 4 two byte entries. Sometimes find 9
67
        // Always find 4 two byte entries. Sometimes find 9
68
        field_1_flag   =  LittleEndian.getShort( data, pos + size );     size += 2;
68
        if (bytesRemaining == 4) // Word format only 4 bytes
69
        field_2_col1   =  LittleEndian.getShort( data, pos + size );     size += 2;
69
        {
70
        field_3_dx1    =  LittleEndian.getShort( data, pos + size );     size += 2;
70
            // Not sure exactly what the format is quite yet, likely a reference to a PLC
71
        field_4_row1   =  LittleEndian.getShort( data, pos + size );     size += 2;
71
        }
72
        if(bytesRemaining >= 18) {
72
        else
73
		    field_5_dy1    =  LittleEndian.getShort( data, pos + size );     size += 2;
73
        {
74
		    field_6_col2   =  LittleEndian.getShort( data, pos + size );     size += 2;
74
            field_1_flag   =  LittleEndian.getShort( data, pos + size );     size += 2;
75
		    field_7_dx2    =  LittleEndian.getShort( data, pos + size );     size += 2;
75
            field_2_col1   =  LittleEndian.getShort( data, pos + size );     size += 2;
76
		    field_8_row2   =  LittleEndian.getShort( data, pos + size );     size += 2;
76
            field_3_dx1    =  LittleEndian.getShort( data, pos + size );     size += 2;
77
		    field_9_dy2    =  LittleEndian.getShort( data, pos + size );     size += 2;
77
            field_4_row1   =  LittleEndian.getShort( data, pos + size );     size += 2;
78
			shortRecord = false;
78
            if(bytesRemaining >= 18) {
79
        } else {
79
                field_5_dy1    =  LittleEndian.getShort( data, pos + size );     size += 2;
80
			shortRecord = true;
80
                field_6_col2   =  LittleEndian.getShort( data, pos + size );     size += 2;
81
		}
81
                field_7_dx2    =  LittleEndian.getShort( data, pos + size );     size += 2;
82
                field_8_row2   =  LittleEndian.getShort( data, pos + size );     size += 2;
83
                field_9_dy2    =  LittleEndian.getShort( data, pos + size );     size += 2;
84
                shortRecord = false;
85
            } else {
86
                shortRecord = true;
87
            }
88
        }
82
        bytesRemaining -= size;
89
        bytesRemaining -= size;
83
        remainingData  =  new byte[bytesRemaining];
90
        remainingData  =  new byte[bytesRemaining];
84
        System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining );
91
        System.arraycopy( data, pos + size, remainingData, 0, bytesRemaining );
(-)src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java (-5 / +22 lines)
Lines 53-62 Link Here
53
  protected FileInformationBlock _fib;
53
  protected FileInformationBlock _fib;
54
54
55
  /** main document stream buffer*/
55
  /** main document stream buffer*/
56
  private byte[] _mainStream;
56
  protected byte[] _mainStream;
57
57
58
  /** table stream buffer*/
58
  /** table stream buffer*/
59
  private byte[] _tableStream;
59
  protected byte[] _tableStream;
60
60
61
  /** data stream buffer*/
61
  /** data stream buffer*/
62
  protected byte[] _dataStream;
62
  protected byte[] _dataStream;
Lines 93-98 Link Here
93
  
93
  
94
  /** Holds pictures table */
94
  /** Holds pictures table */
95
  protected PicturesTable _pictures;
95
  protected PicturesTable _pictures;
96
  
97
  /** Holds FSBA (shape) information */
98
  protected FSPATable _fspa;
99
  
100
  /** Escher Drawing Group information */
101
  protected EscherRecordHolder _dgg;
96
102
97
  protected HWPFDocument()
103
  protected HWPFDocument()
98
  {
104
  {
Lines 204-212 Link Here
204
    {
210
    {
205
        _dataStream = new byte[0];
211
        _dataStream = new byte[0];
206
    }
212
    }
207
    
208
    // read in the pictures stream
209
    _pictures = new PicturesTable(this, _dataStream);
210
213
211
    // get the start of text in the main stream
214
    // get the start of text in the main stream
212
    int fcMin = _fib.getFcMin();
215
    int fcMin = _fib.getFcMin();
Lines 226-231 Link Here
226
      _cbt.adjustForDelete(0, 0, cpMin);
229
      _cbt.adjustForDelete(0, 0, cpMin);
227
      _pbt.adjustForDelete(0, 0, cpMin);
230
      _pbt.adjustForDelete(0, 0, cpMin);
228
    }
231
    }
232
    
233
    // Read FSPA and Escher information
234
    _fspa = new FSPATable(_tableStream, _fib.getFcPlcspaMom(), _fib.getLcbPlcspaMom(), getTextTable().getTextPieces());
235
    
236
    if (_fib.getFcDggInfo() != 0)
237
    {
238
        _dgg = new EscherRecordHolder(_tableStream, _fib.getFcDggInfo(), _fib.getLcbDggInfo());
239
    } else
240
    {
241
        _dgg = new EscherRecordHolder();
242
    }
243
    
244
    // read in the pictures stream
245
    _pictures = new PicturesTable(this, _dataStream, _mainStream, _fspa, _dgg);
229
246
230
    _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, getTextTable().getTextPieces());
247
    _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin, getTextTable().getTextPieces());
231
    _ss = new StyleSheet(_tableStream, _fib.getFcStshf());
248
    _ss = new StyleSheet(_tableStream, _fib.getFcStshf());
(-)src/scratchpad/src/org/apache/poi/hwpf/model/FileInformationBlock.java (+20 lines)
Lines 308-313 Link Here
308
    {
308
    {
309
      return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
309
      return _fieldHandler.getFieldSize(FIBFieldHandler.PLCFFLDMOM);
310
    }
310
    }
311
    
312
    public int getFcPlcspaMom()
313
    {
314
        return _fieldHandler.getFieldOffset(FIBFieldHandler.PLCSPAMOM);
315
    }
316
    
317
    public int getLcbPlcspaMom()
318
    {
319
        return _fieldHandler.getFieldSize(FIBFieldHandler.PLCSPAMOM);
320
    }
321
    
322
    public int getFcDggInfo()
323
    {
324
        return _fieldHandler.getFieldOffset(FIBFieldHandler.DGGINFO);
325
    }
326
    
327
    public int getLcbDggInfo()
328
    {
329
        return _fieldHandler.getFieldSize(FIBFieldHandler.DGGINFO);
330
    }
311
331
312
    public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
332
    public void writeTo (byte[] mainStream, HWPFOutputStream tableStream)
313
      throws IOException
333
      throws IOException
(-)src/scratchpad/src/org/apache/poi/hwpf/model/PicturesTable.java (-3 / +62 lines)
Lines 26-32 Link Here
26
26
27
import java.util.List;
27
import java.util.List;
28
import java.util.ArrayList;
28
import java.util.ArrayList;
29
29
import java.util.Iterator;
30
import org.apache.poi.ddf.DefaultEscherRecordFactory;
31
import org.apache.poi.ddf.EscherBSERecord;
32
import org.apache.poi.ddf.EscherBlipRecord;
33
import org.apache.poi.ddf.EscherRecord;
34
import org.apache.poi.ddf.EscherRecordFactory;
30
35
31
/**
36
/**
32
 * Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
37
 * Holds information about all pictures embedded in Word Document either via "Insert -> Picture -> From File" or via
Lines 57-62 Link Here
57
62
58
  private HWPFDocument _document;
63
  private HWPFDocument _document;
59
  private byte[] _dataStream;
64
  private byte[] _dataStream;
65
  private byte[] _mainStream;
66
  private FSPATable _fspa;
67
  private EscherRecordHolder _dgg;
60
68
61
  /** @link dependency
69
  /** @link dependency
62
   * @stereotype instantiate*/
70
   * @stereotype instantiate*/
Lines 67-76 Link Here
67
   * @param document 
75
   * @param document 
68
   * @param _dataStream
76
   * @param _dataStream
69
   */
77
   */
70
  public PicturesTable(HWPFDocument _document, byte[] _dataStream)
78
  public PicturesTable(HWPFDocument _document, byte[] _dataStream, byte[] _mainStream, FSPATable fspa, EscherRecordHolder dgg)
71
  {
79
  {
72
	this._document = _document;
80
	this._document = _document;
73
    this._dataStream = _dataStream;
81
    this._dataStream = _dataStream;
82
    this._mainStream = _mainStream;
83
    this._fspa = fspa;
84
    this._dgg = dgg;
74
  }
85
  }
75
86
76
  /**
87
  /**
Lines 83-88 Link Here
83
    }
94
    }
84
    return false;
95
    return false;
85
  }
96
  }
97
  
98
  public boolean hasEscherPicture(CharacterRun run) {
99
    if (run.isSpecialCharacter() && !run.isObj() && !run.isOle2() && !run.isData() && run.text().startsWith("\u0008")) {
100
      return true;
101
    }
102
    return false;
103
  }
86
104
87
  /**
105
  /**
88
   * determines whether specified CharacterRun contains reference to a picture
106
   * determines whether specified CharacterRun contains reference to a picture
Lines 122-127 Link Here
122
    }
140
    }
123
    return null;
141
    return null;
124
  }
142
  }
143
  
144
  /**
145
     * Performs a recursive search for pictures in the given list of escher records.
146
     *
147
     * @param escherRecords the escher records.
148
     * @param pictures the list to populate with the pictures.
149
     */
150
    private void searchForPictures(List escherRecords, List pictures)
151
    {
152
        Iterator recordIter = escherRecords.iterator();
153
        while (recordIter.hasNext())
154
        {
155
            Object obj = recordIter.next();
156
            if (obj instanceof EscherRecord)
157
            {
158
                EscherRecord escherRecord = (EscherRecord) obj;
159
160
                if (escherRecord instanceof EscherBSERecord)
161
                {
162
                    EscherBSERecord bse = (EscherBSERecord) escherRecord;
163
                    EscherBlipRecord blip = bse.getBlipRecord();
164
                    if (blip != null)
165
                    {
166
                        pictures.add(new Picture(blip.getPicturedata()));
167
                    }
168
                    else if (bse.getOffset() > 0)
169
                    {
170
                        // Blip stored in delay stream, which in a word doc, is the main stream
171
                        EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
172
                        blip = (EscherBlipRecord) recordFactory.createRecord(_mainStream, bse.getOffset());
173
                        blip.fillFields(_mainStream, bse.getOffset(), recordFactory);
174
                        pictures.add(new Picture(blip.getPicturedata()));
175
                    }
176
                }
177
178
                // Recursive call.
179
                searchForPictures(escherRecord.getChildRecords(), pictures);
180
            }
181
        }
182
    }
125
183
126
  /**
184
  /**
127
   * Not all documents have all the images concatenated in the data stream
185
   * Not all documents have all the images concatenated in the data stream
Lines 136-142 Link Here
136
    for (int i = 0; i < range.numCharacterRuns(); i++) {
194
    for (int i = 0; i < range.numCharacterRuns(); i++) {
137
    	CharacterRun run = range.getCharacterRun(i);
195
    	CharacterRun run = range.getCharacterRun(i);
138
    	String text = run.text();
196
    	String text = run.text();
139
    	int j = text.charAt(0);
140
    	Picture picture = extractPicture(run, false);
197
    	Picture picture = extractPicture(run, false);
141
    	if (picture != null) {
198
    	if (picture != null) {
142
    		pictures.add(picture);
199
    		pictures.add(picture);
Lines 142-147 Link Here
142
    		pictures.add(picture);
199
    		pictures.add(picture);
143
    	}
200
    	}
144
	}
201
	}
202
    
203
    searchForPictures(_dgg.getEscherRecords(), pictures);
145
204
146
    return pictures;
205
    return pictures;
147
  }
206
  }
(-)src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java (+9 lines)
Lines 98-103 Link Here
98
      fillImageContent();
98
      fillImageContent();
99
    }
99
    }
100
  }
100
  }
101
  
102
  public Picture(byte[] _dataStream)
103
  {
104
      this._dataStream = _dataStream;
105
      this.dataBlockStartOfsset = 0;
106
      this.dataBlockSize = _dataStream.length;
107
      this.pictureBytesStartOffset = 0;
108
      this.size = _dataStream.length;
109
  }
101
110
102
  private void fillWidthHeight()
111
  private void fillWidthHeight()
103
  {
112
  {
(-)src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java (-1 / +20 lines)
Lines 35-40 Link Here
35
	private String docAFile;
35
	private String docAFile;
36
	private String docBFile;
36
	private String docBFile;
37
	private String docCFile;
37
	private String docCFile;
38
    private String docDFile;
38
	
39
	
39
	private String imgAFile;
40
	private String imgAFile;
40
	private String imgBFile;
41
	private String imgBFile;
Lines 39-44 Link Here
39
	private String imgAFile;
40
	private String imgAFile;
40
	private String imgBFile;
41
	private String imgBFile;
41
	private String imgCFile;
42
	private String imgCFile;
43
    private String imgDFile;
42
	
44
	
43
	protected void setUp() throws Exception {
45
	protected void setUp() throws Exception {
44
		String dirname = System.getProperty("HWPF.testdata.path");
46
		String dirname = System.getProperty("HWPF.testdata.path");
Lines 46-51 Link Here
46
		docAFile = dirname + "/testPictures.doc";
48
		docAFile = dirname + "/testPictures.doc";
47
		docBFile = dirname + "/two_images.doc";
49
		docBFile = dirname + "/two_images.doc";
48
		docCFile = dirname + "/vector_image.doc";
50
		docCFile = dirname + "/vector_image.doc";
51
        docDFile = dirname + "/GaiaTest.doc";
49
		
52
		
50
		imgAFile = dirname + "/simple_image.jpg";
53
		imgAFile = dirname + "/simple_image.jpg";
51
		imgBFile = dirname + "/simple_image.png";
54
		imgBFile = dirname + "/simple_image.png";
Lines 50-55 Link Here
50
		imgAFile = dirname + "/simple_image.jpg";
53
		imgAFile = dirname + "/simple_image.jpg";
51
		imgBFile = dirname + "/simple_image.png";
54
		imgBFile = dirname + "/simple_image.png";
52
		imgCFile = dirname + "/vector_image.emf";
55
		imgCFile = dirname + "/vector_image.emf";
56
        imgDFile = dirname + "/GaiaTestImg.png";
53
	}
57
	}
54
	
58
	
55
	/**
59
	/**
Lines 126-132 Link Here
126
		assertEquals(picBytes.length, pic.getContent().length);
130
		assertEquals(picBytes.length, pic.getContent().length);
127
		assertBytesSame(picBytes, pic.getContent());
131
		assertBytesSame(picBytes, pic.getContent());
128
	}
132
	}
129
	
133
    
134
    public void testEscherDrawing() throws Exception
135
    {
136
        HWPFDocument docD = new HWPFDocument(new FileInputStream(docDFile));
137
        List allPictures = docD.getPicturesTable().getAllPictures();
138
        
139
        assertEquals(1, allPictures.size());
140
        
141
        Picture pic = (Picture) allPictures.get(0);
142
        assertNotNull(pic);
143
        byte[] picD = readFile(imgDFile);
144
        
145
        assertEquals(picD.length, pic.getContent().length);
146
        
147
        assertBytesSame(picD, pic.getContent());
148
    }
130
	
149
	
131
	private void assertBytesSame(byte[] a, byte[] b) {
150
	private void assertBytesSame(byte[] a, byte[] b) {
132
		assertEquals(a.length, b.length);
151
		assertEquals(a.length, b.length);

Return to bug 44937