1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/xls/drawingmanager.hxx"
25
26 #include <com/sun/star/awt/Rectangle.hpp>
27 #include <com/sun/star/drawing/CircleKind.hpp>
28 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
29 #include <com/sun/star/drawing/PolygonKind.hpp>
30 #include <com/sun/star/drawing/XShapes.hpp>
31 #include "oox/core/filterbase.hxx"
32 #include "oox/drawingml/fillproperties.hxx"
33 #include "oox/drawingml/lineproperties.hxx"
34 #include "oox/drawingml/shapepropertymap.hxx"
35 #include "oox/helper/containerhelper.hxx"
36 #include "oox/token/tokens.hxx"
37 #include "oox/xls/biffinputstream.hxx"
38 #include "oox/xls/unitconverter.hxx"
39
40 namespace oox {
41 namespace xls {
42
43 // ============================================================================
44
45 using namespace ::com::sun::star::awt;
46 using namespace ::com::sun::star::drawing;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::uno;
49 using namespace ::oox::drawingml;
50
51 using ::rtl::OUString;
52
53 // ============================================================================
54
55 namespace {
56
57 // OBJ record -----------------------------------------------------------------
58
59 const sal_uInt16 BIFF_OBJTYPE_GROUP = 0;
60 const sal_uInt16 BIFF_OBJTYPE_LINE = 1;
61 const sal_uInt16 BIFF_OBJTYPE_RECTANGLE = 2;
62 const sal_uInt16 BIFF_OBJTYPE_OVAL = 3;
63 const sal_uInt16 BIFF_OBJTYPE_ARC = 4;
64 const sal_uInt16 BIFF_OBJTYPE_CHART = 5;
65 const sal_uInt16 BIFF_OBJTYPE_TEXT = 6;
66 const sal_uInt16 BIFF_OBJTYPE_BUTTON = 7;
67 const sal_uInt16 BIFF_OBJTYPE_PICTURE = 8;
68 const sal_uInt16 BIFF_OBJTYPE_POLYGON = 9; // new in BIFF4
69 const sal_uInt16 BIFF_OBJTYPE_CHECKBOX = 11; // new in BIFF5
70 const sal_uInt16 BIFF_OBJTYPE_OPTIONBUTTON = 12;
71 const sal_uInt16 BIFF_OBJTYPE_EDIT = 13;
72 const sal_uInt16 BIFF_OBJTYPE_LABEL = 14;
73 const sal_uInt16 BIFF_OBJTYPE_DIALOG = 15;
74 const sal_uInt16 BIFF_OBJTYPE_SPIN = 16;
75 const sal_uInt16 BIFF_OBJTYPE_SCROLLBAR = 17;
76 const sal_uInt16 BIFF_OBJTYPE_LISTBOX = 18;
77 const sal_uInt16 BIFF_OBJTYPE_GROUPBOX = 19;
78 const sal_uInt16 BIFF_OBJTYPE_DROPDOWN = 20;
79 const sal_uInt16 BIFF_OBJTYPE_NOTE = 25; // new in BIFF8
80 const sal_uInt16 BIFF_OBJTYPE_DRAWING = 30;
81 const sal_uInt16 BIFF_OBJTYPE_UNKNOWN = 0xFFFF; // for internal use only
82
83 const sal_uInt16 BIFF_OBJ_HIDDEN = 0x0100;
84 const sal_uInt16 BIFF_OBJ_VISIBLE = 0x0200;
85 const sal_uInt16 BIFF_OBJ_PRINTABLE = 0x0400;
86
87 // line formatting ------------------------------------------------------------
88
89 const sal_uInt8 BIFF_OBJ_LINE_AUTOCOLOR = 64;
90
91 const sal_uInt8 BIFF_OBJ_LINE_SOLID = 0;
92 const sal_uInt8 BIFF_OBJ_LINE_DASH = 1;
93 const sal_uInt8 BIFF_OBJ_LINE_DOT = 2;
94 const sal_uInt8 BIFF_OBJ_LINE_DASHDOT = 3;
95 const sal_uInt8 BIFF_OBJ_LINE_DASHDOTDOT = 4;
96 const sal_uInt8 BIFF_OBJ_LINE_MEDTRANS = 5;
97 const sal_uInt8 BIFF_OBJ_LINE_DARKTRANS = 6;
98 const sal_uInt8 BIFF_OBJ_LINE_LIGHTTRANS = 7;
99 const sal_uInt8 BIFF_OBJ_LINE_NONE = 255;
100
101 const sal_uInt8 BIFF_OBJ_LINE_HAIR = 0;
102 const sal_uInt8 BIFF_OBJ_LINE_THIN = 1;
103 const sal_uInt8 BIFF_OBJ_LINE_MEDIUM = 2;
104 const sal_uInt8 BIFF_OBJ_LINE_THICK = 3;
105
106 const sal_uInt8 BIFF_OBJ_LINE_AUTO = 0x01;
107
108 const sal_uInt8 BIFF_OBJ_ARROW_NONE = 0;
109 const sal_uInt8 BIFF_OBJ_ARROW_OPEN = 1;
110 const sal_uInt8 BIFF_OBJ_ARROW_FILLED = 2;
111 const sal_uInt8 BIFF_OBJ_ARROW_OPENBOTH = 3;
112 const sal_uInt8 BIFF_OBJ_ARROW_FILLEDBOTH = 4;
113
114 const sal_uInt8 BIFF_OBJ_ARROW_NARROW = 0;
115 const sal_uInt8 BIFF_OBJ_ARROW_MEDIUM = 1;
116 const sal_uInt8 BIFF_OBJ_ARROW_WIDE = 2;
117
118 const sal_uInt8 BIFF_OBJ_LINE_TL = 0;
119 const sal_uInt8 BIFF_OBJ_LINE_TR = 1;
120 const sal_uInt8 BIFF_OBJ_LINE_BR = 2;
121 const sal_uInt8 BIFF_OBJ_LINE_BL = 3;
122
123 const sal_uInt8 BIFF_OBJ_ARC_TR = 0;
124 const sal_uInt8 BIFF_OBJ_ARC_TL = 1;
125 const sal_uInt8 BIFF_OBJ_ARC_BL = 2;
126 const sal_uInt8 BIFF_OBJ_ARC_BR = 3;
127
128 const sal_uInt16 BIFF_OBJ_POLY_CLOSED = 0x0100;
129
130 // fill formatting ------------------------------------------------------------
131
132 const sal_uInt8 BIFF_OBJ_FILL_AUTOCOLOR = 65;
133
134 const sal_uInt8 BIFF_OBJ_PATT_NONE = 0;
135 const sal_uInt8 BIFF_OBJ_PATT_SOLID = 1;
136
137 const sal_uInt8 BIFF_OBJ_FILL_AUTO = 0x01;
138
139 // text formatting ------------------------------------------------------------
140
141 const sal_uInt8 BIFF_OBJ_HOR_LEFT = 1;
142 const sal_uInt8 BIFF_OBJ_HOR_CENTER = 2;
143 const sal_uInt8 BIFF_OBJ_HOR_RIGHT = 3;
144 const sal_uInt8 BIFF_OBJ_HOR_JUSTIFY = 4;
145
146 const sal_uInt8 BIFF_OBJ_VER_TOP = 1;
147 const sal_uInt8 BIFF_OBJ_VER_CENTER = 2;
148 const sal_uInt8 BIFF_OBJ_VER_BOTTOM = 3;
149 const sal_uInt8 BIFF_OBJ_VER_JUSTIFY = 4;
150
151 const sal_uInt16 BIFF_OBJ_ORIENT_NONE = 0;
152 const sal_uInt16 BIFF_OBJ_ORIENT_STACKED = 1; /// Stacked top to bottom.
153 const sal_uInt16 BIFF_OBJ_ORIENT_90CCW = 2; /// 90 degr. counterclockwise.
154 const sal_uInt16 BIFF_OBJ_ORIENT_90CW = 3; /// 90 degr. clockwise.
155
156 const sal_uInt16 BIFF_OBJ_TEXT_AUTOSIZE = 0x0080;
157 const sal_uInt16 BIFF_OBJ_TEXT_LOCKED = 0x0200;
158
159 const sal_Int32 BIFF_OBJ_TEXT_MARGIN = 20000; /// Automatic text margin (EMUs).
160
161 // BIFF8 OBJ sub records ------------------------------------------------------
162
163 const sal_uInt16 BIFF_OBJCMO_PRINTABLE = 0x0010; /// Object printable.
164 const sal_uInt16 BIFF_OBJCMO_AUTOLINE = 0x2000; /// Automatic line formatting.
165 const sal_uInt16 BIFF_OBJCMO_AUTOFILL = 0x4000; /// Automatic fill formatting.
166
167 // ----------------------------------------------------------------------------
168
operator >>(BiffInputStream & rStrm,ShapeAnchor & rAnchor)169 inline BiffInputStream& operator>>( BiffInputStream& rStrm, ShapeAnchor& rAnchor )
170 {
171 rAnchor.importBiffAnchor( rStrm );
172 return rStrm;
173 }
174
175 } // namespace
176
177 // ============================================================================
178 // Model structures for BIFF OBJ record data
179 // ============================================================================
180
BiffObjLineModel()181 BiffObjLineModel::BiffObjLineModel() :
182 mnColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
183 mnStyle( BIFF_OBJ_LINE_SOLID ),
184 mnWidth( BIFF_OBJ_LINE_HAIR ),
185 mbAuto( true )
186 {
187 }
188
isVisible() const189 bool BiffObjLineModel::isVisible() const
190 {
191 return mbAuto || (mnStyle != BIFF_OBJ_LINE_NONE);
192 }
193
operator >>(BiffInputStream & rStrm,BiffObjLineModel & rModel)194 BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjLineModel& rModel )
195 {
196 sal_uInt8 nFlags;
197 rStrm >> rModel.mnColorIdx >> rModel.mnStyle >> rModel.mnWidth >> nFlags;
198 rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_LINE_AUTO );
199 return rStrm;
200 }
201
202 // ============================================================================
203
BiffObjFillModel()204 BiffObjFillModel::BiffObjFillModel() :
205 mnBackColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
206 mnPattColorIdx( BIFF_OBJ_FILL_AUTOCOLOR ),
207 mnPattern( BIFF_OBJ_PATT_SOLID ),
208 mbAuto( true )
209 {
210 }
211
isFilled() const212 bool BiffObjFillModel::isFilled() const
213 {
214 return mbAuto || (mnPattern != BIFF_OBJ_PATT_NONE);
215 }
216
operator >>(BiffInputStream & rStrm,BiffObjFillModel & rModel)217 BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjFillModel& rModel )
218 {
219 sal_uInt8 nFlags;
220 rStrm >> rModel.mnBackColorIdx >> rModel.mnPattColorIdx >> rModel.mnPattern >> nFlags;
221 rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_FILL_AUTO );
222 return rStrm;
223 }
224
225 // ============================================================================
226
BiffObjTextModel()227 BiffObjTextModel::BiffObjTextModel() :
228 mnTextLen( 0 ),
229 mnFormatSize( 0 ),
230 mnLinkSize( 0 ),
231 mnDefFontId( 0 ),
232 mnFlags( 0 ),
233 mnOrientation( BIFF_OBJ_ORIENT_NONE ),
234 mnButtonFlags( 0 ),
235 mnShortcut( 0 ),
236 mnShortcutEA( 0 )
237 {
238 }
239
readObj3(BiffInputStream & rStrm)240 void BiffObjTextModel::readObj3( BiffInputStream& rStrm )
241 {
242 rStrm >> mnTextLen;
243 rStrm.skip( 2 );
244 rStrm >> mnFormatSize >> mnDefFontId;
245 rStrm.skip( 2 );
246 rStrm >> mnFlags >> mnOrientation;
247 rStrm.skip( 8 );
248 }
249
readObj5(BiffInputStream & rStrm)250 void BiffObjTextModel::readObj5( BiffInputStream& rStrm )
251 {
252 rStrm >> mnTextLen;
253 rStrm.skip( 2 );
254 rStrm >> mnFormatSize >> mnDefFontId;
255 rStrm.skip( 2 );
256 rStrm >> mnFlags >> mnOrientation;
257 rStrm.skip( 2 );
258 rStrm >> mnLinkSize;
259 rStrm.skip( 2 );
260 rStrm >> mnButtonFlags >> mnShortcut >> mnShortcutEA;
261 }
262
readTxo8(BiffInputStream & rStrm)263 void BiffObjTextModel::readTxo8( BiffInputStream& rStrm )
264 {
265 rStrm >> mnFlags >> mnOrientation >> mnButtonFlags >> mnShortcut >> mnShortcutEA >> mnTextLen >> mnFormatSize;
266 }
267
getHorAlign() const268 sal_uInt8 BiffObjTextModel::getHorAlign() const
269 {
270 return extractValue< sal_uInt8 >( mnFlags, 1, 3 );
271 }
272
getVerAlign() const273 sal_uInt8 BiffObjTextModel::getVerAlign() const
274 {
275 return extractValue< sal_uInt8 >( mnFlags, 4, 3 );
276 }
277
278 // ============================================================================
279 // BIFF drawing objects
280 // ============================================================================
281
BiffDrawingObjectContainer()282 BiffDrawingObjectContainer::BiffDrawingObjectContainer()
283 {
284 }
285
append(const BiffDrawingObjectRef & rxDrawingObj)286 void BiffDrawingObjectContainer::append( const BiffDrawingObjectRef& rxDrawingObj )
287 {
288 maObjects.push_back( rxDrawingObj );
289 }
290
insertGrouped(const BiffDrawingObjectRef & rxDrawingObj)291 void BiffDrawingObjectContainer::insertGrouped( const BiffDrawingObjectRef& rxDrawingObj )
292 {
293 if( !maObjects.empty() )
294 if( BiffGroupObject* pGroupObj = dynamic_cast< BiffGroupObject* >( maObjects.back().get() ) )
295 if( pGroupObj->tryInsert( rxDrawingObj ) )
296 return;
297 maObjects.push_back( rxDrawingObj );
298 }
299
convertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle * pParentRect) const300 void BiffDrawingObjectContainer::convertAndInsert( BiffDrawingBase& rDrawing, const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
301 {
302 maObjects.forEachMem( &BiffDrawingObjectBase::convertAndInsert, ::boost::ref( rDrawing ), ::boost::cref( rxShapes ), pParentRect );
303 }
304
305 // ============================================================================
306
BiffDrawingObjectBase(const WorksheetHelper & rHelper)307 BiffDrawingObjectBase::BiffDrawingObjectBase( const WorksheetHelper& rHelper ) :
308 WorksheetHelper( rHelper ),
309 maAnchor( rHelper ),
310 mnDffShapeId( 0 ),
311 mnDffFlags( 0 ),
312 mnObjId( BIFF_OBJ_INVALID_ID ),
313 mnObjType( BIFF_OBJTYPE_UNKNOWN ),
314 mbHasAnchor( false ),
315 mbHidden( false ),
316 mbVisible( true ),
317 mbPrintable( true ),
318 mbAreaObj( false ),
319 mbAutoMargin( true ),
320 mbSimpleMacro( true ),
321 mbProcessShape( true ),
322 mbInsertShape( true ),
323 mbCustomDff( false )
324 {
325 }
326
~BiffDrawingObjectBase()327 BiffDrawingObjectBase::~BiffDrawingObjectBase()
328 {
329 }
330
importObjBiff3(const WorksheetHelper & rHelper,BiffInputStream & rStrm)331 /*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff3( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
332 {
333 BiffDrawingObjectRef xDrawingObj;
334
335 if( rStrm.getRemaining() >= 30 )
336 {
337 sal_uInt16 nObjType;
338 rStrm.skip( 4 );
339 rStrm >> nObjType;
340 switch( nObjType )
341 {
342 case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
343 case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
344 case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
345 case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
346 case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
347 #if 0
348 case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
349 case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
350 case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
351 case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
352 #endif
353 default:
354 #if 0
355 OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff3 - unknown object type" );
356 #endif
357 xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
358 }
359 }
360
361 xDrawingObj->importObjBiff3( rStrm );
362 return xDrawingObj;
363 }
364
importObjBiff4(const WorksheetHelper & rHelper,BiffInputStream & rStrm)365 /*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff4( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
366 {
367 BiffDrawingObjectRef xDrawingObj;
368
369 if( rStrm.getRemaining() >= 30 )
370 {
371 sal_uInt16 nObjType;
372 rStrm.skip( 4 );
373 rStrm >> nObjType;
374 switch( nObjType )
375 {
376 case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
377 case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
378 case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
379 case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
380 case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
381 case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
382 #if 0
383 case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
384 case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
385 case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
386 case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
387 #endif
388 default:
389 #if 0
390 OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff4 - unknown object type" );
391 #endif
392 xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
393 }
394 }
395
396 xDrawingObj->importObjBiff4( rStrm );
397 return xDrawingObj;
398 }
399
importObjBiff5(const WorksheetHelper & rHelper,BiffInputStream & rStrm)400 /*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff5( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
401 {
402 BiffDrawingObjectRef xDrawingObj;
403
404 if( rStrm.getRemaining() >= 34 )
405 {
406 sal_uInt16 nObjType;
407 rStrm.skip( 4 );
408 rStrm >> nObjType;
409 switch( nObjType )
410 {
411 case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
412 case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
413 case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
414 case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
415 case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
416 case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
417 #if 0
418 case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
419 case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
420 case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
421 case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
422 case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
423 case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
424 case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
425 case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
426 case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
427 case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
428 case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
429 case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
430 case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
431 case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
432 #endif
433 default:
434 #if 0
435 OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff5 - unknown object type" );
436 #endif
437 xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
438 }
439 }
440
441 xDrawingObj->importObjBiff5( rStrm );
442 return xDrawingObj;
443 }
444
importObjBiff8(const WorksheetHelper & rHelper,BiffInputStream & rStrm)445 /*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff8( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
446 {
447 BiffDrawingObjectRef xDrawingObj;
448
449 if( rStrm.getRemaining() >= 10 )
450 {
451 sal_uInt16 nSubRecId, nSubRecSize, nObjType;
452 rStrm >> nSubRecId >> nSubRecSize >> nObjType;
453 OSL_ENSURE( nSubRecId == BIFF_ID_OBJCMO, "BiffDrawingObjectBase::importObjBiff8 - OBJCMO subrecord expected" );
454 if( (nSubRecId == BIFF_ID_OBJCMO) && (nSubRecSize >= 6) )
455 {
456 switch( nObjType )
457 {
458 #if 0
459 // in BIFF8, all simple objects support text
460 case BIFF_OBJTYPE_LINE:
461 case BIFF_OBJTYPE_ARC:
462 xDrawingObj.reset( new XclImpTextObj( rHelper ) );
463 // lines and arcs may be 2-dimensional
464 xDrawingObj->setAreaObj( false );
465 break;
466
467 // in BIFF8, all simple objects support text
468 case BIFF_OBJTYPE_RECTANGLE:
469 case BIFF_OBJTYPE_OVAL:
470 case BIFF_OBJTYPE_POLYGON:
471 case BIFF_OBJTYPE_DRAWING:
472 case BIFF_OBJTYPE_TEXT:
473 xDrawingObj.reset( new XclImpTextObj( rHelper ) );
474 break;
475 #endif
476
477 case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
478 #if 0
479 case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
480 case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
481 case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
482 case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
483 case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
484 case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
485 case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
486 case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
487 case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
488 case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
489 case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
490 case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
491 case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
492 case BIFF_OBJTYPE_NOTE: xDrawingObj.reset( new XclImpNoteObj( rHelper ) ); break;
493 #endif
494
495 default:
496 #if 0
497 OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff8 - unknown object type" );
498 #endif
499 xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
500 }
501 }
502 }
503
504 xDrawingObj->importObjBiff8( rStrm );
505 return xDrawingObj;
506 }
507
convertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle * pParentRect) const508 Reference< XShape > BiffDrawingObjectBase::convertAndInsert( BiffDrawingBase& rDrawing,
509 const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
510 {
511 Reference< XShape > xShape;
512 if( rxShapes.is() && mbProcessShape && !mbHidden ) // TODO: support for hidden objects?
513 {
514 // base class 'ShapeAnchor' calculates the shape rectangle in 1/100 mm
515 // in BIFF3-BIFF5, all shapes have absolute anchor (also children of group shapes)
516 Rectangle aShapeRect = maAnchor.calcAnchorRectHmm( getDrawPageSize() );
517
518 // convert the shape, if the calculated rectangle is not empty
519 bool bHasWidth = aShapeRect.Width > 0;
520 bool bHasHeight = aShapeRect.Height > 0;
521 if( mbAreaObj ? (bHasWidth && bHasHeight) : (bHasWidth || bHasHeight) )
522 {
523 xShape = implConvertAndInsert( rDrawing, rxShapes, aShapeRect );
524 /* Notify the drawing that a new shape has been inserted (but not
525 for children of group shapes). For convenience, pass the
526 rectangle that contains position and size of the shape. */
527 if( !pParentRect && xShape.is() )
528 rDrawing.notifyShapeInserted( xShape, aShapeRect );
529 }
530 }
531 return xShape;
532 }
533
534 // protected ------------------------------------------------------------------
535
readNameBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen)536 void BiffDrawingObjectBase::readNameBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen )
537 {
538 maObjName = OUString();
539 if( nNameLen > 0 )
540 {
541 // name length field is repeated before the name
542 maObjName = rStrm.readByteStringUC( false, getTextEncoding() );
543 // skip padding byte for word boundaries
544 rStrm.alignToBlock( 2 );
545 }
546 }
547
readMacroBiff3(BiffInputStream & rStrm,sal_uInt16 nMacroSize)548 void BiffDrawingObjectBase::readMacroBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
549 {
550 maMacroName = OUString();
551 rStrm.skip( nMacroSize );
552 // skip padding byte for word boundaries, not contained in nMacroSize
553 rStrm.alignToBlock( 2 );
554 }
555
readMacroBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)556 void BiffDrawingObjectBase::readMacroBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
557 {
558 maMacroName = OUString();
559 rStrm.skip( nMacroSize );
560 }
561
readMacroBiff5(BiffInputStream & rStrm,sal_uInt16 nMacroSize)562 void BiffDrawingObjectBase::readMacroBiff5( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
563 {
564 maMacroName = OUString();
565 rStrm.skip( nMacroSize );
566 }
567
readMacroBiff8(BiffInputStream & rStrm)568 void BiffDrawingObjectBase::readMacroBiff8( BiffInputStream& rStrm )
569 {
570 maMacroName = OUString();
571 if( rStrm.getRemaining() > 6 )
572 {
573 // macro is stored in a tNameXR token containing a link to a defined name
574 sal_uInt16 nFmlaSize;
575 rStrm >> nFmlaSize;
576 rStrm.skip( 4 );
577 OSL_ENSURE( nFmlaSize == 7, "BiffDrawingObjectBase::readMacroBiff8 - unexpected formula size" );
578 if( nFmlaSize == 7 )
579 {
580 sal_uInt8 nTokenId;
581 sal_uInt16 nExtLinkId, nExtNameId;
582 rStrm >> nTokenId >> nExtLinkId >> nExtNameId;
583 #if 0
584 OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
585 "BiffDrawingObjectBase::readMacroBiff8 - tNameXR token expected" );
586 if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
587 maMacroName = GetLinkManager().GetMacroName( nExtLinkId, nExtNameId );
588 #endif
589 }
590 }
591 }
592
convertLineProperties(ShapePropertyMap & rPropMap,const BiffObjLineModel & rLineModel,sal_uInt16 nArrows) const593 void BiffDrawingObjectBase::convertLineProperties( ShapePropertyMap& rPropMap, const BiffObjLineModel& rLineModel, sal_uInt16 nArrows ) const
594 {
595 if( rLineModel.mbAuto )
596 {
597 BiffObjLineModel aAutoModel;
598 aAutoModel.mbAuto = false;
599 convertLineProperties( rPropMap, aAutoModel, nArrows );
600 return;
601 }
602
603 /* Convert line formatting to DrawingML line formatting and let the
604 DrawingML code do the hard work. */
605 LineProperties aLineProps;
606
607 if( rLineModel.mnStyle == BIFF_OBJ_LINE_NONE )
608 {
609 aLineProps.maLineFill.moFillType = XML_noFill;
610 }
611 else
612 {
613 aLineProps.maLineFill.moFillType = XML_solidFill;
614 aLineProps.maLineFill.maFillColor.setPaletteClr( rLineModel.mnColorIdx );
615 aLineProps.moLineCompound = XML_sng;
616 aLineProps.moLineCap = XML_flat;
617 aLineProps.moLineJoint = XML_round;
618
619 // line width: use 0.35 mm per BIFF line width step
620 sal_Int32 nLineWidth = 0;
621 switch( rLineModel.mnWidth )
622 {
623 default:
624 case BIFF_OBJ_LINE_HAIR: nLineWidth = 0; break;
625 case BIFF_OBJ_LINE_THIN: nLineWidth = 20; break;
626 case BIFF_OBJ_LINE_MEDIUM: nLineWidth = 40; break;
627 case BIFF_OBJ_LINE_THICK: nLineWidth = 60; break;
628 }
629 aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( convertHmmToEmu( nLineWidth ), 0, SAL_MAX_INT32 );
630
631 // dash style and transparency
632 switch( rLineModel.mnStyle )
633 {
634 default:
635 case BIFF_OBJ_LINE_SOLID:
636 aLineProps.moPresetDash = XML_solid;
637 break;
638 case BIFF_OBJ_LINE_DASH:
639 aLineProps.moPresetDash = XML_lgDash;
640 break;
641 case BIFF_OBJ_LINE_DOT:
642 aLineProps.moPresetDash = XML_dot;
643 break;
644 case BIFF_OBJ_LINE_DASHDOT:
645 aLineProps.moPresetDash = XML_lgDashDot;
646 break;
647 case BIFF_OBJ_LINE_DASHDOTDOT:
648 aLineProps.moPresetDash = XML_lgDashDotDot;
649 break;
650 case BIFF_OBJ_LINE_MEDTRANS:
651 aLineProps.moPresetDash = XML_solid;
652 aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 50 * PER_PERCENT );
653 break;
654 case BIFF_OBJ_LINE_DARKTRANS:
655 aLineProps.moPresetDash = XML_solid;
656 aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 75 * PER_PERCENT );
657 break;
658 case BIFF_OBJ_LINE_LIGHTTRANS:
659 aLineProps.moPresetDash = XML_solid;
660 aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 25 * PER_PERCENT );
661 break;
662 }
663
664 // line ends
665 bool bLineStart = false;
666 bool bLineEnd = false;
667 bool bFilled = false;
668 switch( extractValue< sal_uInt8 >( nArrows, 0, 4 ) )
669 {
670 case BIFF_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
671 case BIFF_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
672 case BIFF_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
673 case BIFF_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
674 }
675 if( bLineStart || bLineEnd )
676 {
677 // arrow type (open or closed)
678 sal_Int32 nArrowType = bFilled ? XML_triangle : XML_arrow;
679 aLineProps.maStartArrow.moArrowType = bLineStart ? nArrowType : XML_none;
680 aLineProps.maEndArrow.moArrowType = bLineEnd ? nArrowType : XML_none;
681
682 // arrow width
683 sal_Int32 nArrowWidth = XML_med;
684 switch( extractValue< sal_uInt8 >( nArrows, 4, 4 ) )
685 {
686 case BIFF_OBJ_ARROW_NARROW: nArrowWidth = XML_sm; break;
687 case BIFF_OBJ_ARROW_MEDIUM: nArrowWidth = XML_med; break;
688 case BIFF_OBJ_ARROW_WIDE: nArrowWidth = XML_lg; break;
689 }
690 aLineProps.maStartArrow.moArrowWidth = aLineProps.maEndArrow.moArrowWidth = nArrowWidth;
691
692 // arrow length
693 sal_Int32 nArrowLength = XML_med;
694 switch( extractValue< sal_uInt8 >( nArrows, 8, 4 ) )
695 {
696 case BIFF_OBJ_ARROW_NARROW: nArrowLength = XML_sm; break;
697 case BIFF_OBJ_ARROW_MEDIUM: nArrowLength = XML_med; break;
698 case BIFF_OBJ_ARROW_WIDE: nArrowLength = XML_lg; break;
699 }
700 aLineProps.maStartArrow.moArrowLength = aLineProps.maEndArrow.moArrowLength = nArrowLength;
701 }
702 }
703
704 aLineProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
705 }
706
convertFillProperties(ShapePropertyMap & rPropMap,const BiffObjFillModel & rFillModel) const707 void BiffDrawingObjectBase::convertFillProperties( ShapePropertyMap& rPropMap, const BiffObjFillModel& rFillModel ) const
708 {
709 if( rFillModel.mbAuto )
710 {
711 BiffObjFillModel aAutoModel;
712 aAutoModel.mbAuto = false;
713 convertFillProperties( rPropMap, aAutoModel );
714 return;
715 }
716
717 /* Convert fill formatting to DrawingML fill formatting and let the
718 DrawingML code do the hard work. */
719 FillProperties aFillProps;
720
721 if( rFillModel.mnPattern == BIFF_OBJ_PATT_NONE )
722 {
723 aFillProps.moFillType = XML_noFill;
724 }
725 else
726 {
727 const sal_Int32 spnPatternPresets[] = {
728 XML_TOKEN_INVALID, XML_TOKEN_INVALID, XML_pct50, XML_pct50, XML_pct25,
729 XML_dkHorz, XML_dkVert, XML_dkDnDiag, XML_dkUpDiag, XML_smCheck, XML_trellis,
730 XML_ltHorz, XML_ltVert, XML_ltDnDiag, XML_ltUpDiag, XML_smGrid, XML_diagCross,
731 XML_pct20, XML_pct10 };
732 sal_Int32 nPatternPreset = STATIC_ARRAY_SELECT( spnPatternPresets, rFillModel.mnPattern, XML_TOKEN_INVALID );
733 if( nPatternPreset == XML_TOKEN_INVALID )
734 {
735 aFillProps.moFillType = XML_solidFill;
736 aFillProps.maFillColor.setPaletteClr( rFillModel.mnPattColorIdx );
737 }
738 else
739 {
740 aFillProps.moFillType = XML_pattFill;
741 aFillProps.maPatternProps.maPattFgColor.setPaletteClr( rFillModel.mnPattColorIdx );
742 aFillProps.maPatternProps.maPattBgColor.setPaletteClr( rFillModel.mnBackColorIdx );
743 aFillProps.maPatternProps.moPattPreset = nPatternPreset;
744 }
745 #if 0
746 static const sal_uInt8 sppnPatterns[][ 8 ] =
747 {
748 { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
749 { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
750 { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
751 { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
752 { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
753 { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
754 { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
755 { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
756 { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
757 { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
758 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
759 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
760 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
761 { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
762 { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
763 { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
764 { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
765 };
766 const sal_uInt8* const pnPattern = sppnPatterns[ ::std::min< size_t >( rFillData.mnPattern - 2, STATIC_ARRAY_SIZE( sppnPatterns ) ) ];
767 // create 2-colored 8x8 DIB
768 SvMemoryStream aMemStrm;
769 // { 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }
770 aMemStrm << sal_uInt32( 12 ) << sal_Int16( 8 ) << sal_Int16( 8 ) << sal_uInt16( 1 ) << sal_uInt16( 1 );
771 aMemStrm << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF );
772 aMemStrm << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 );
773 for( size_t nIdx = 0; nIdx < 8; ++nIdx )
774 aMemStrm << sal_uInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
775 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
776 Bitmap aBitmap;
777 aBitmap.Read( aMemStrm, FALSE );
778 XOBitmap aXOBitmap( aBitmap );
779 aXOBitmap.Bitmap2Array();
780 aXOBitmap.SetBitmapType( XBITMAP_8X8 );
781 if( aXOBitmap.GetBackgroundColor().GetColor() == COL_BLACK )
782 ::std::swap( aPattColor, aBackColor );
783 aXOBitmap.SetPixelColor( aPattColor );
784 aXOBitmap.SetBackgroundColor( aBackColor );
785 rSdrObj.SetMergedItem( XFillStyleItem( XFILL_BITMAP ) );
786 rSdrObj.SetMergedItem( XFillBitmapItem( EMPTY_STRING, aXOBitmap ) );
787 #endif
788 }
789
790 aFillProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
791 }
792
convertFrameProperties(ShapePropertyMap &,sal_uInt16) const793 void BiffDrawingObjectBase::convertFrameProperties( ShapePropertyMap& /*rPropMap*/, sal_uInt16 /*nFrameFlags*/ ) const
794 {
795 }
796
implReadObjBiff3(BiffInputStream &,sal_uInt16)797 void BiffDrawingObjectBase::implReadObjBiff3( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
798 {
799 }
800
implReadObjBiff4(BiffInputStream &,sal_uInt16)801 void BiffDrawingObjectBase::implReadObjBiff4( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
802 {
803 }
804
implReadObjBiff5(BiffInputStream &,sal_uInt16,sal_uInt16)805 void BiffDrawingObjectBase::implReadObjBiff5( BiffInputStream& /*rStrm*/, sal_uInt16 /*nNameLen*/, sal_uInt16 /*nMacroSize*/ )
806 {
807 }
808
implReadObjBiff8SubRec(BiffInputStream &,sal_uInt16,sal_uInt16)809 void BiffDrawingObjectBase::implReadObjBiff8SubRec( BiffInputStream& /*rStrm*/, sal_uInt16 /*nSubRecId*/, sal_uInt16 /*nSubRecSize*/ )
810 {
811 }
812
813 // private --------------------------------------------------------------------
814
importObjBiff3(BiffInputStream & rStrm)815 void BiffDrawingObjectBase::importObjBiff3( BiffInputStream& rStrm )
816 {
817 // back to offset 4 (ignore object count field)
818 rStrm.seek( 4 );
819
820 sal_uInt16 nObjFlags, nMacroSize;
821 rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
822 rStrm.skip( 2 );
823
824 mbHasAnchor = true;
825 mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
826 mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
827 implReadObjBiff3( rStrm, nMacroSize );
828 }
829
importObjBiff4(BiffInputStream & rStrm)830 void BiffDrawingObjectBase::importObjBiff4( BiffInputStream& rStrm )
831 {
832 // back to offset 4 (ignore object count field)
833 rStrm.seek( 4 );
834
835 sal_uInt16 nObjFlags, nMacroSize;
836 rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
837 rStrm.skip( 2 );
838
839 mbHasAnchor = true;
840 mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
841 mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
842 mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
843 implReadObjBiff4( rStrm, nMacroSize );
844 }
845
importObjBiff5(BiffInputStream & rStrm)846 void BiffDrawingObjectBase::importObjBiff5( BiffInputStream& rStrm )
847 {
848 // back to offset 4 (ignore object count field)
849 rStrm.seek( 4 );
850
851 sal_uInt16 nObjFlags, nMacroSize, nNameLen;
852 rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
853 rStrm.skip( 2 );
854 rStrm >> nNameLen;
855 rStrm.skip( 2 );
856
857 mbHasAnchor = true;
858 mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
859 mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
860 mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
861 implReadObjBiff5( rStrm, nNameLen, nMacroSize );
862 }
863
importObjBiff8(BiffInputStream & rStrm)864 void BiffDrawingObjectBase::importObjBiff8( BiffInputStream& rStrm )
865 {
866 // back to beginning
867 rStrm.seekToStart();
868
869 bool bLoop = true;
870 while( bLoop && (rStrm.getRemaining() >= 4) )
871 {
872 sal_uInt16 nSubRecId, nSubRecSize;
873 rStrm >> nSubRecId >> nSubRecSize;
874 sal_Int64 nStrmPos = rStrm.tell();
875 // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
876 nSubRecSize = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nSubRecSize, rStrm.getRemaining() ) );
877
878 switch( nSubRecId )
879 {
880 case BIFF_ID_OBJCMO:
881 OSL_ENSURE( rStrm.tell() == 4, "BiffDrawingObjectBase::importObjBiff8 - unexpected OBJCMO subrecord" );
882 if( (rStrm.tell() == 4) && (nSubRecSize >= 6) )
883 {
884 sal_uInt16 nObjFlags;
885 rStrm >> mnObjType >> mnObjId >> nObjFlags;
886 mbPrintable = getFlag( nObjFlags, BIFF_OBJCMO_PRINTABLE );
887 }
888 break;
889 case BIFF_ID_OBJMACRO:
890 readMacroBiff8( rStrm );
891 break;
892 case BIFF_ID_OBJEND:
893 bLoop = false;
894 break;
895 default:
896 implReadObjBiff8SubRec( rStrm, nSubRecId, nSubRecSize );
897 }
898
899 // seek to end of subrecord
900 rStrm.seek( nStrmPos + nSubRecSize );
901 }
902
903 /* Call doReadObj8SubRec() with BIFF_ID_OBJEND for further stream
904 processing (e.g. charts), even if the OBJEND subrecord is missing. */
905 implReadObjBiff8SubRec( rStrm, BIFF_ID_OBJEND, 0 );
906
907 /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
908 IMGDATA record following the OBJ record (but they use the image data
909 stored in DFF). The IMGDATA record may be continued by several CONTINUE
910 records. But the last CONTINUE record may be in fact an MSODRAWING
911 record that contains the DFF data of the next drawing object! So we
912 have to skip just enough CONTINUE records to look at the next
913 MSODRAWING/CONTINUE record. */
914 if( (rStrm.getNextRecId() == BIFF3_ID_IMGDATA) && rStrm.startNextRecord() )
915 {
916 rStrm.skip( 4 );
917 sal_Int64 nDataSize = rStrm.readuInt32();
918 nDataSize -= rStrm.getRemaining();
919 // skip following CONTINUE records until IMGDATA ends
920 while( (nDataSize > 0) && (rStrm.getNextRecId() == BIFF_ID_CONT) && rStrm.startNextRecord() )
921 {
922 OSL_ENSURE( nDataSize >= rStrm.getRemaining(), "BiffDrawingObjectBase::importObjBiff8 - CONTINUE too long" );
923 nDataSize -= ::std::min( rStrm.getRemaining(), nDataSize );
924 }
925 OSL_ENSURE( nDataSize == 0, "BiffDrawingObjectBase::importObjBiff8 - missing CONTINUE records" );
926 // next record may be MSODRAWING or CONTINUE or anything else
927 }
928 }
929
930 // ============================================================================
931
BiffPlaceholderObject(const WorksheetHelper & rHelper)932 BiffPlaceholderObject::BiffPlaceholderObject( const WorksheetHelper& rHelper ) :
933 BiffDrawingObjectBase( rHelper )
934 {
935 setProcessShape( false );
936 }
937
implConvertAndInsert(BiffDrawingBase &,const Reference<XShapes> &,const Rectangle &) const938 Reference< XShape > BiffPlaceholderObject::implConvertAndInsert( BiffDrawingBase& /*rDrawing*/,
939 const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const
940 {
941 return Reference< XShape >();
942 }
943
944 // ============================================================================
945
BiffGroupObject(const WorksheetHelper & rHelper)946 BiffGroupObject::BiffGroupObject( const WorksheetHelper& rHelper ) :
947 BiffDrawingObjectBase( rHelper ),
948 mnFirstUngrouped( BIFF_OBJ_INVALID_ID )
949 {
950 }
951
tryInsert(const BiffDrawingObjectRef & rxDrawingObj)952 bool BiffGroupObject::tryInsert( const BiffDrawingObjectRef& rxDrawingObj )
953 {
954 if( rxDrawingObj->getObjId() == mnFirstUngrouped )
955 return false;
956 // insert into own list or into nested group
957 maChildren.insertGrouped( rxDrawingObj );
958 return true;
959 }
960
implReadObjBiff3(BiffInputStream & rStrm,sal_uInt16 nMacroSize)961 void BiffGroupObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
962 {
963 rStrm.skip( 4 );
964 rStrm >> mnFirstUngrouped;
965 rStrm.skip( 16 );
966 readMacroBiff3( rStrm, nMacroSize );
967 }
968
implReadObjBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)969 void BiffGroupObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
970 {
971 rStrm.skip( 4 );
972 rStrm >> mnFirstUngrouped;
973 rStrm.skip( 16 );
974 readMacroBiff4( rStrm, nMacroSize );
975 }
976
implReadObjBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen,sal_uInt16 nMacroSize)977 void BiffGroupObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
978 {
979 rStrm.skip( 4 );
980 rStrm >> mnFirstUngrouped;
981 rStrm.skip( 16 );
982 readNameBiff5( rStrm, nNameLen );
983 readMacroBiff5( rStrm, nMacroSize );
984 }
985
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const986 Reference< XShape > BiffGroupObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
987 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
988 {
989 Reference< XShape > xGroupShape;
990 if( !maChildren.empty() ) try
991 {
992 xGroupShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect );
993 Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
994 maChildren.convertAndInsert( rDrawing, xChildShapes, &rShapeRect );
995 // no child shape has been created - delete the group shape
996 if( !xChildShapes->hasElements() )
997 {
998 rxShapes->remove( xGroupShape );
999 xGroupShape.clear();
1000 }
1001 }
1002 catch( Exception& )
1003 {
1004 }
1005 return xGroupShape;
1006 }
1007
1008 // ============================================================================
1009
BiffLineObject(const WorksheetHelper & rHelper)1010 BiffLineObject::BiffLineObject( const WorksheetHelper& rHelper ) :
1011 BiffDrawingObjectBase( rHelper ),
1012 mnArrows( 0 ),
1013 mnStartPoint( BIFF_OBJ_LINE_TL )
1014 {
1015 setAreaObj( false );
1016 }
1017
implReadObjBiff3(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1018 void BiffLineObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1019 {
1020 rStrm >> maLineModel >> mnArrows >> mnStartPoint;
1021 rStrm.skip( 1 );
1022 readMacroBiff3( rStrm, nMacroSize );
1023 }
1024
implReadObjBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1025 void BiffLineObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1026 {
1027 rStrm >> maLineModel >> mnArrows >> mnStartPoint;
1028 rStrm.skip( 1 );
1029 readMacroBiff4( rStrm, nMacroSize );
1030 }
1031
implReadObjBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen,sal_uInt16 nMacroSize)1032 void BiffLineObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1033 {
1034 rStrm >> maLineModel >> mnArrows >> mnStartPoint;
1035 rStrm.skip( 1 );
1036 readNameBiff5( rStrm, nNameLen );
1037 readMacroBiff5( rStrm, nMacroSize );
1038 }
1039
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1040 Reference< XShape > BiffLineObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
1041 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1042 {
1043 ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
1044 convertLineProperties( aPropMap, maLineModel, mnArrows );
1045
1046 // create the line polygon
1047 PointSequenceSequence aPoints( 1 );
1048 aPoints[ 0 ].realloc( 2 );
1049 Point& rBeg = aPoints[ 0 ][ 0 ];
1050 Point& rEnd = aPoints[ 0 ][ 1 ];
1051 sal_Int32 nL = rShapeRect.X;
1052 sal_Int32 nT = rShapeRect.Y;
1053 sal_Int32 nR = rShapeRect.X + ::std::max< sal_Int32 >( rShapeRect.Width - 1, 0 );
1054 sal_Int32 nB = rShapeRect.Y + ::std::max< sal_Int32 >( rShapeRect.Height - 1, 0 );
1055 switch( mnStartPoint )
1056 {
1057 default:
1058 case BIFF_OBJ_LINE_TL: rBeg.X = nL; rBeg.Y = nT; rEnd.X = nR; rEnd.Y = nB; break;
1059 case BIFF_OBJ_LINE_TR: rBeg.X = nR; rBeg.Y = nT; rEnd.X = nL; rEnd.Y = nB; break;
1060 case BIFF_OBJ_LINE_BR: rBeg.X = nR; rBeg.Y = nB; rEnd.X = nL; rEnd.Y = nT; break;
1061 case BIFF_OBJ_LINE_BL: rBeg.X = nL; rBeg.Y = nB; rEnd.X = nR; rEnd.Y = nT; break;
1062 }
1063 aPropMap.setProperty( PROP_PolyPolygon, aPoints );
1064 aPropMap.setProperty( PROP_PolygonKind, PolygonKind_LINE );
1065
1066 // create the shape
1067 Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.LineShape" ), rxShapes, rShapeRect );
1068 PropertySet( xShape ).setProperties( aPropMap );
1069 return xShape;
1070 }
1071
1072 // ============================================================================
1073
BiffRectObject(const WorksheetHelper & rHelper)1074 BiffRectObject::BiffRectObject( const WorksheetHelper& rHelper ) :
1075 BiffDrawingObjectBase( rHelper ),
1076 mnFrameFlags( 0 )
1077 {
1078 setAreaObj( true );
1079 }
1080
readFrameData(BiffInputStream & rStrm)1081 void BiffRectObject::readFrameData( BiffInputStream& rStrm )
1082 {
1083 rStrm >> maFillModel >> maLineModel >> mnFrameFlags;
1084 }
1085
convertRectProperties(ShapePropertyMap & rPropMap) const1086 void BiffRectObject::convertRectProperties( ShapePropertyMap& rPropMap ) const
1087 {
1088 convertLineProperties( rPropMap, maLineModel );
1089 convertFillProperties( rPropMap, maFillModel );
1090 convertFrameProperties( rPropMap, mnFrameFlags );
1091 }
1092
implReadObjBiff3(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1093 void BiffRectObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1094 {
1095 readFrameData( rStrm );
1096 readMacroBiff3( rStrm, nMacroSize );
1097 }
1098
implReadObjBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1099 void BiffRectObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1100 {
1101 readFrameData( rStrm );
1102 readMacroBiff4( rStrm, nMacroSize );
1103 }
1104
implReadObjBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen,sal_uInt16 nMacroSize)1105 void BiffRectObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1106 {
1107 readFrameData( rStrm );
1108 readNameBiff5( rStrm, nNameLen );
1109 readMacroBiff5( rStrm, nMacroSize );
1110 }
1111
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1112 Reference< XShape > BiffRectObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
1113 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1114 {
1115 ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
1116 convertRectProperties( aPropMap );
1117
1118 Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ), rxShapes, rShapeRect );
1119 PropertySet( xShape ).setProperties( aPropMap );
1120 return xShape;
1121 }
1122
1123 // ============================================================================
1124
BiffOvalObject(const WorksheetHelper & rHelper)1125 BiffOvalObject::BiffOvalObject( const WorksheetHelper& rHelper ) :
1126 BiffRectObject( rHelper )
1127 {
1128 }
1129
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1130 Reference< XShape > BiffOvalObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
1131 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1132 {
1133 ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
1134 convertRectProperties( aPropMap );
1135
1136 Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, rShapeRect );
1137 PropertySet( xShape ).setProperties( aPropMap );
1138 return xShape;
1139 }
1140
1141 // ============================================================================
1142
BiffArcObject(const WorksheetHelper & rHelper)1143 BiffArcObject::BiffArcObject( const WorksheetHelper& rHelper ) :
1144 BiffDrawingObjectBase( rHelper ),
1145 mnQuadrant( BIFF_OBJ_ARC_TR )
1146 {
1147 setAreaObj( false ); // arc may be 2-dimensional
1148 }
1149
implReadObjBiff3(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1150 void BiffArcObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1151 {
1152 rStrm >> maFillModel >> maLineModel >> mnQuadrant;
1153 rStrm.skip( 1 );
1154 readMacroBiff3( rStrm, nMacroSize );
1155 }
1156
implReadObjBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1157 void BiffArcObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1158 {
1159 rStrm >> maFillModel >> maLineModel >> mnQuadrant;
1160 rStrm.skip( 1 );
1161 readMacroBiff4( rStrm, nMacroSize );
1162 }
1163
implReadObjBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen,sal_uInt16 nMacroSize)1164 void BiffArcObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1165 {
1166 rStrm >> maFillModel >> maLineModel >> mnQuadrant;
1167 rStrm.skip( 1 );
1168 readNameBiff5( rStrm, nNameLen );
1169 readMacroBiff5( rStrm, nMacroSize );
1170 }
1171
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1172 Reference< XShape > BiffArcObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
1173 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1174 {
1175 ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
1176 convertLineProperties( aPropMap, maLineModel );
1177 convertFillProperties( aPropMap, maFillModel );
1178
1179 /* Simulate arc objects with ellipse sections. While the original arc
1180 object uses the entire object rectangle, only one quarter of the
1181 ellipse shape will be visible. Thus, the size of the ellipse shape
1182 needs to be extended and its position adjusted according to the visible
1183 quadrant. */
1184 Rectangle aNewRect( rShapeRect.X, rShapeRect.Y, rShapeRect.Width * 2, rShapeRect.Height * 2 );
1185 long nStartAngle = 0;
1186 switch( mnQuadrant )
1187 {
1188 default:
1189 case BIFF_OBJ_ARC_TR: nStartAngle = 0; aNewRect.X -= rShapeRect.Width; break;
1190 case BIFF_OBJ_ARC_TL: nStartAngle = 9000; break;
1191 case BIFF_OBJ_ARC_BL: nStartAngle = 18000; aNewRect.Y -= rShapeRect.Height; break;
1192 case BIFF_OBJ_ARC_BR: nStartAngle = 27000; aNewRect.X -= rShapeRect.Width; aNewRect.Y -= rShapeRect.Height; break;
1193 }
1194 long nEndAngle = (nStartAngle + 9000) % 36000;
1195 aPropMap.setProperty( PROP_CircleKind, maFillModel.isFilled() ? CircleKind_SECTION : CircleKind_ARC );
1196 aPropMap.setProperty( PROP_CircleStartAngle, nStartAngle );
1197 aPropMap.setProperty( PROP_CircleEndAngle, nEndAngle );
1198
1199 // create the shape
1200 Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, aNewRect );
1201 PropertySet( xShape ).setProperties( aPropMap );
1202 return xShape;
1203 }
1204
1205 // ============================================================================
1206
BiffPolygonObject(const WorksheetHelper & rHelper)1207 BiffPolygonObject::BiffPolygonObject( const WorksheetHelper& rHelper ) :
1208 BiffRectObject( rHelper ),
1209 mnPolyFlags( 0 ),
1210 mnPointCount( 0 )
1211 {
1212 setAreaObj( false ); // polygon may be 2-dimensional
1213 }
1214
implReadObjBiff4(BiffInputStream & rStrm,sal_uInt16 nMacroSize)1215 void BiffPolygonObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
1216 {
1217 readFrameData( rStrm );
1218 rStrm >> mnPolyFlags;
1219 rStrm.skip( 10 );
1220 rStrm >> mnPointCount;
1221 rStrm.skip( 8 );
1222 readMacroBiff4( rStrm, nMacroSize );
1223 importCoordList( rStrm );
1224 }
1225
implReadObjBiff5(BiffInputStream & rStrm,sal_uInt16 nNameLen,sal_uInt16 nMacroSize)1226 void BiffPolygonObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1227 {
1228 readFrameData( rStrm );
1229 rStrm >> mnPolyFlags;
1230 rStrm.skip( 10 );
1231 rStrm >> mnPointCount;
1232 rStrm.skip( 8 );
1233 readNameBiff5( rStrm, nNameLen );
1234 readMacroBiff5( rStrm, nMacroSize );
1235 importCoordList( rStrm );
1236 }
1237
1238 namespace {
1239
lclGetPolyPoint(const Rectangle & rAnchorRect,const Point & rPoint)1240 Point lclGetPolyPoint( const Rectangle& rAnchorRect, const Point& rPoint )
1241 {
1242 // polygon coordinates are given in 1/16384 of shape size
1243 return Point(
1244 rAnchorRect.X + static_cast< sal_Int32 >( rAnchorRect.Width * getLimitedValue< double >( static_cast< double >( rPoint.X ) / 16384.0, 0.0, 1.0 ) + 0.5 ),
1245 rAnchorRect.Y + static_cast< sal_Int32 >( rAnchorRect.Height * getLimitedValue< double >( static_cast< double >( rPoint.Y ) / 16384.0, 0.0, 1.0 ) + 0.5 ) );
1246 }
1247
1248 } // namespace
1249
implConvertAndInsert(BiffDrawingBase & rDrawing,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1250 Reference< XShape > BiffPolygonObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
1251 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1252 {
1253 Reference< XShape > xShape;
1254 if( maCoords.size() >= 2 )
1255 {
1256 ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
1257 convertRectProperties( aPropMap );
1258
1259 // create the polygon
1260 PointVector aPolygon;
1261 for( PointVector::const_iterator aIt = maCoords.begin(), aEnd = maCoords.end(); aIt != aEnd; ++aIt )
1262 aPolygon.push_back( lclGetPolyPoint( rShapeRect, *aIt ) );
1263 // close polygon if specified
1264 if( getFlag( mnPolyFlags, BIFF_OBJ_POLY_CLOSED ) && ((maCoords.front().X != maCoords.back().X) || (maCoords.front().Y != maCoords.back().Y)) )
1265 aPolygon.push_back( aPolygon.front() );
1266 PointSequenceSequence aPoints( 1 );
1267 aPoints[ 0 ] = ContainerHelper::vectorToSequence( aPolygon );
1268 aPropMap.setProperty( PROP_PolyPolygon, aPoints );
1269
1270 // create the shape
1271 OUString aService = maFillModel.isFilled() ?
1272 CREATE_OUSTRING( "com.sun.star.drawing.PolyPolygonShape" ) :
1273 CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" );
1274 xShape = rDrawing.createAndInsertXShape( aService, rxShapes, rShapeRect );
1275 PropertySet( xShape ).setProperties( aPropMap );
1276 }
1277 return xShape;
1278 }
1279
importCoordList(BiffInputStream & rStrm)1280 void BiffPolygonObject::importCoordList( BiffInputStream& rStrm )
1281 {
1282 if( (rStrm.getNextRecId() == BIFF_ID_COORDLIST) && rStrm.startNextRecord() )
1283 {
1284 OSL_ENSURE( rStrm.getRemaining() / 4 == mnPointCount, "BiffPolygonObject::importCoordList - wrong polygon point count" );
1285 while( rStrm.getRemaining() >= 4 )
1286 {
1287 sal_uInt16 nX, nY;
1288 rStrm >> nX >> nY;
1289 maCoords.push_back( Point( nX, nY ) );
1290 }
1291 }
1292 }
1293
1294 // ============================================================================
1295 // BIFF drawing page
1296 // ============================================================================
1297
BiffDrawingBase(const WorksheetHelper & rHelper,const Reference<XDrawPage> & rxDrawPage)1298 BiffDrawingBase::BiffDrawingBase( const WorksheetHelper& rHelper, const Reference< XDrawPage >& rxDrawPage ) :
1299 WorksheetHelper( rHelper ),
1300 mxDrawPage( rxDrawPage )
1301 {
1302 }
1303
importObj(BiffInputStream & rStrm)1304 void BiffDrawingBase::importObj( BiffInputStream& rStrm )
1305 {
1306 BiffDrawingObjectRef xDrawingObj;
1307
1308 #if 0
1309 /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
1310 records. In this case, the OBJ records are in BIFF5 format. Do a sanity
1311 check here that there is no DFF data loaded before. */
1312 DBG_ASSERT( maDffStrm.Tell() == 0, "BiffDrawingBase::importObj - unexpected DFF stream data, OBJ will be ignored" );
1313 if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
1314 #else
1315 switch( getBiff() )
1316 #endif
1317 {
1318 case BIFF3:
1319 xDrawingObj = BiffDrawingObjectBase::importObjBiff3( *this, rStrm );
1320 break;
1321 case BIFF4:
1322 xDrawingObj = BiffDrawingObjectBase::importObjBiff4( *this, rStrm );
1323 break;
1324 case BIFF5:
1325 // TODO: add BIFF8 when DFF is supported
1326 // case BIFF8:
1327 xDrawingObj = BiffDrawingObjectBase::importObjBiff5( *this, rStrm );
1328 break;
1329 default:;
1330 }
1331
1332 if( xDrawingObj.get() )
1333 {
1334 // insert into maRawObjs or into the last open group object
1335 maRawObjs.insertGrouped( xDrawingObj );
1336 // to be able to find objects by ID
1337 maObjMapId[ xDrawingObj->getObjId() ] = xDrawingObj;
1338 }
1339 }
1340
setSkipObj(sal_uInt16 nObjId)1341 void BiffDrawingBase::setSkipObj( sal_uInt16 nObjId )
1342 {
1343 /* Store identifiers of objects to be skipped in a separate list (the OBJ
1344 record may not be read yet). In the finalization phase, all objects
1345 registered here will be skipped. */
1346 maSkipObjs.push_back( nObjId );
1347 }
1348
finalizeImport()1349 void BiffDrawingBase::finalizeImport()
1350 {
1351 Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY );
1352 OSL_ENSURE( xShapes.is(), "BiffDrawingBase::finalizeImport - no shapes container" );
1353 if( !xShapes.is() )
1354 return;
1355
1356 // process list of objects to be skipped
1357 for( BiffObjIdVector::const_iterator aIt = maSkipObjs.begin(), aEnd = maSkipObjs.end(); aIt != aEnd; ++aIt )
1358 if( BiffDrawingObjectBase* pDrawingObj = maObjMapId.get( *aIt ).get() )
1359 pDrawingObj->setProcessShape( false );
1360
1361 // process drawing objects without DFF data
1362 maRawObjs.convertAndInsert( *this, xShapes );
1363 }
1364
createAndInsertXShape(const OUString & rService,const Reference<XShapes> & rxShapes,const Rectangle & rShapeRect) const1365 Reference< XShape > BiffDrawingBase::createAndInsertXShape( const OUString& rService,
1366 const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
1367 {
1368 OSL_ENSURE( rService.getLength() > 0, "BiffDrawingBase::createAndInsertXShape - missing UNO shape service name" );
1369 OSL_ENSURE( rxShapes.is(), "BiffDrawingBase::createAndInsertXShape - missing XShapes container" );
1370 Reference< XShape > xShape;
1371 if( (rService.getLength() > 0) && rxShapes.is() ) try
1372 {
1373 xShape.set( getBaseFilter().getModelFactory()->createInstance( rService ), UNO_QUERY_THROW );
1374 // insert shape into passed shape collection (maybe drawpage or group shape)
1375 rxShapes->add( xShape );
1376 xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
1377 xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
1378 }
1379 catch( Exception& )
1380 {
1381 }
1382 OSL_ENSURE( xShape.is(), "BiffDrawingBase::createAndInsertXShape - cannot instanciate shape object" );
1383 return xShape;
1384 }
1385
1386 // protected ------------------------------------------------------------------
1387
appendRawObject(const BiffDrawingObjectRef & rxDrawingObj)1388 void BiffDrawingBase::appendRawObject( const BiffDrawingObjectRef& rxDrawingObj )
1389 {
1390 OSL_ENSURE( rxDrawingObj.get(), "BiffDrawingBase::appendRawObject - unexpected empty object reference" );
1391 maRawObjs.append( rxDrawingObj );
1392 }
1393
1394 // ============================================================================
1395
BiffSheetDrawing(const WorksheetHelper & rHelper)1396 BiffSheetDrawing::BiffSheetDrawing( const WorksheetHelper& rHelper ) :
1397 BiffDrawingBase( rHelper, rHelper.getDrawPage() )
1398 {
1399 }
1400
notifyShapeInserted(const Reference<XShape> &,const Rectangle & rShapeRect)1401 void BiffSheetDrawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const Rectangle& rShapeRect )
1402 {
1403 // collect all shape positions in the WorksheetHelper base class
1404 extendShapeBoundingBox( rShapeRect );
1405 }
1406
1407 // ============================================================================
1408
1409 } // namespace xls
1410 } // namespace oox
1411