xref: /aoo41x/main/oox/source/xls/drawingmanager.cxx (revision 79aad27f)
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