summaryrefslogtreecommitdiff
path: root/oox/source/xls/drawingmanager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/xls/drawingmanager.cxx')
-rwxr-xr-xoox/source/xls/drawingmanager.cxx1414
1 files changed, 1414 insertions, 0 deletions
diff --git a/oox/source/xls/drawingmanager.cxx b/oox/source/xls/drawingmanager.cxx
new file mode 100755
index 000000000000..efba6824c8ac
--- /dev/null
+++ b/oox/source/xls/drawingmanager.cxx
@@ -0,0 +1,1414 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/xls/drawingmanager.hxx"
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PolygonKind.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include "oox/core/filterbase.hxx"
+#include "oox/drawingml/fillproperties.hxx"
+#include "oox/drawingml/lineproperties.hxx"
+#include "oox/drawingml/shapepropertymap.hxx"
+#include "oox/helper/containerhelper.hxx"
+#include "oox/token/tokens.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/unitconverter.hxx"
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::oox::drawingml;
+
+using ::rtl::OUString;
+
+// ============================================================================
+
+namespace {
+
+// OBJ record -----------------------------------------------------------------
+
+const sal_uInt16 BIFF_OBJTYPE_GROUP = 0;
+const sal_uInt16 BIFF_OBJTYPE_LINE = 1;
+const sal_uInt16 BIFF_OBJTYPE_RECTANGLE = 2;
+const sal_uInt16 BIFF_OBJTYPE_OVAL = 3;
+const sal_uInt16 BIFF_OBJTYPE_ARC = 4;
+const sal_uInt16 BIFF_OBJTYPE_CHART = 5;
+const sal_uInt16 BIFF_OBJTYPE_TEXT = 6;
+const sal_uInt16 BIFF_OBJTYPE_BUTTON = 7;
+const sal_uInt16 BIFF_OBJTYPE_PICTURE = 8;
+const sal_uInt16 BIFF_OBJTYPE_POLYGON = 9; // new in BIFF4
+const sal_uInt16 BIFF_OBJTYPE_CHECKBOX = 11; // new in BIFF5
+const sal_uInt16 BIFF_OBJTYPE_OPTIONBUTTON = 12;
+const sal_uInt16 BIFF_OBJTYPE_EDIT = 13;
+const sal_uInt16 BIFF_OBJTYPE_LABEL = 14;
+const sal_uInt16 BIFF_OBJTYPE_DIALOG = 15;
+const sal_uInt16 BIFF_OBJTYPE_SPIN = 16;
+const sal_uInt16 BIFF_OBJTYPE_SCROLLBAR = 17;
+const sal_uInt16 BIFF_OBJTYPE_LISTBOX = 18;
+const sal_uInt16 BIFF_OBJTYPE_GROUPBOX = 19;
+const sal_uInt16 BIFF_OBJTYPE_DROPDOWN = 20;
+const sal_uInt16 BIFF_OBJTYPE_NOTE = 25; // new in BIFF8
+const sal_uInt16 BIFF_OBJTYPE_DRAWING = 30;
+const sal_uInt16 BIFF_OBJTYPE_UNKNOWN = 0xFFFF; // for internal use only
+
+const sal_uInt16 BIFF_OBJ_HIDDEN = 0x0100;
+const sal_uInt16 BIFF_OBJ_VISIBLE = 0x0200;
+const sal_uInt16 BIFF_OBJ_PRINTABLE = 0x0400;
+
+// line formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_LINE_AUTOCOLOR = 64;
+
+const sal_uInt8 BIFF_OBJ_LINE_SOLID = 0;
+const sal_uInt8 BIFF_OBJ_LINE_DASH = 1;
+const sal_uInt8 BIFF_OBJ_LINE_DOT = 2;
+const sal_uInt8 BIFF_OBJ_LINE_DASHDOT = 3;
+const sal_uInt8 BIFF_OBJ_LINE_DASHDOTDOT = 4;
+const sal_uInt8 BIFF_OBJ_LINE_MEDTRANS = 5;
+const sal_uInt8 BIFF_OBJ_LINE_DARKTRANS = 6;
+const sal_uInt8 BIFF_OBJ_LINE_LIGHTTRANS = 7;
+const sal_uInt8 BIFF_OBJ_LINE_NONE = 255;
+
+const sal_uInt8 BIFF_OBJ_LINE_HAIR = 0;
+const sal_uInt8 BIFF_OBJ_LINE_THIN = 1;
+const sal_uInt8 BIFF_OBJ_LINE_MEDIUM = 2;
+const sal_uInt8 BIFF_OBJ_LINE_THICK = 3;
+
+const sal_uInt8 BIFF_OBJ_LINE_AUTO = 0x01;
+
+const sal_uInt8 BIFF_OBJ_ARROW_NONE = 0;
+const sal_uInt8 BIFF_OBJ_ARROW_OPEN = 1;
+const sal_uInt8 BIFF_OBJ_ARROW_FILLED = 2;
+const sal_uInt8 BIFF_OBJ_ARROW_OPENBOTH = 3;
+const sal_uInt8 BIFF_OBJ_ARROW_FILLEDBOTH = 4;
+
+const sal_uInt8 BIFF_OBJ_ARROW_NARROW = 0;
+const sal_uInt8 BIFF_OBJ_ARROW_MEDIUM = 1;
+const sal_uInt8 BIFF_OBJ_ARROW_WIDE = 2;
+
+const sal_uInt8 BIFF_OBJ_LINE_TL = 0;
+const sal_uInt8 BIFF_OBJ_LINE_TR = 1;
+const sal_uInt8 BIFF_OBJ_LINE_BR = 2;
+const sal_uInt8 BIFF_OBJ_LINE_BL = 3;
+
+const sal_uInt8 BIFF_OBJ_ARC_TR = 0;
+const sal_uInt8 BIFF_OBJ_ARC_TL = 1;
+const sal_uInt8 BIFF_OBJ_ARC_BL = 2;
+const sal_uInt8 BIFF_OBJ_ARC_BR = 3;
+
+const sal_uInt16 BIFF_OBJ_POLY_CLOSED = 0x0100;
+
+// fill formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_FILL_AUTOCOLOR = 65;
+
+const sal_uInt8 BIFF_OBJ_PATT_NONE = 0;
+const sal_uInt8 BIFF_OBJ_PATT_SOLID = 1;
+
+const sal_uInt8 BIFF_OBJ_FILL_AUTO = 0x01;
+
+// text formatting ------------------------------------------------------------
+
+const sal_uInt8 BIFF_OBJ_HOR_LEFT = 1;
+const sal_uInt8 BIFF_OBJ_HOR_CENTER = 2;
+const sal_uInt8 BIFF_OBJ_HOR_RIGHT = 3;
+const sal_uInt8 BIFF_OBJ_HOR_JUSTIFY = 4;
+
+const sal_uInt8 BIFF_OBJ_VER_TOP = 1;
+const sal_uInt8 BIFF_OBJ_VER_CENTER = 2;
+const sal_uInt8 BIFF_OBJ_VER_BOTTOM = 3;
+const sal_uInt8 BIFF_OBJ_VER_JUSTIFY = 4;
+
+const sal_uInt16 BIFF_OBJ_ORIENT_NONE = 0;
+const sal_uInt16 BIFF_OBJ_ORIENT_STACKED = 1; /// Stacked top to bottom.
+const sal_uInt16 BIFF_OBJ_ORIENT_90CCW = 2; /// 90 degr. counterclockwise.
+const sal_uInt16 BIFF_OBJ_ORIENT_90CW = 3; /// 90 degr. clockwise.
+
+const sal_uInt16 BIFF_OBJ_TEXT_AUTOSIZE = 0x0080;
+const sal_uInt16 BIFF_OBJ_TEXT_LOCKED = 0x0200;
+
+const sal_Int32 BIFF_OBJ_TEXT_MARGIN = 20000; /// Automatic text margin (EMUs).
+
+// BIFF8 OBJ sub records ------------------------------------------------------
+
+const sal_uInt16 BIFF_OBJCMO_PRINTABLE = 0x0010; /// Object printable.
+const sal_uInt16 BIFF_OBJCMO_AUTOLINE = 0x2000; /// Automatic line formatting.
+const sal_uInt16 BIFF_OBJCMO_AUTOFILL = 0x4000; /// Automatic fill formatting.
+
+// ----------------------------------------------------------------------------
+
+inline BiffInputStream& operator>>( BiffInputStream& rStrm, ShapeAnchor& rAnchor )
+{
+ rAnchor.importBiffAnchor( rStrm );
+ return rStrm;
+}
+
+} // namespace
+
+// ============================================================================
+// Model structures for BIFF OBJ record data
+// ============================================================================
+
+BiffObjLineModel::BiffObjLineModel() :
+ mnColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
+ mnStyle( BIFF_OBJ_LINE_SOLID ),
+ mnWidth( BIFF_OBJ_LINE_HAIR ),
+ mbAuto( true )
+{
+}
+
+bool BiffObjLineModel::isVisible() const
+{
+ return mbAuto || (mnStyle != BIFF_OBJ_LINE_NONE);
+}
+
+BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjLineModel& rModel )
+{
+ sal_uInt8 nFlags;
+ rStrm >> rModel.mnColorIdx >> rModel.mnStyle >> rModel.mnWidth >> nFlags;
+ rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_LINE_AUTO );
+ return rStrm;
+}
+
+// ============================================================================
+
+BiffObjFillModel::BiffObjFillModel() :
+ mnBackColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ),
+ mnPattColorIdx( BIFF_OBJ_FILL_AUTOCOLOR ),
+ mnPattern( BIFF_OBJ_PATT_SOLID ),
+ mbAuto( true )
+{
+}
+
+bool BiffObjFillModel::isFilled() const
+{
+ return mbAuto || (mnPattern != BIFF_OBJ_PATT_NONE);
+}
+
+BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjFillModel& rModel )
+{
+ sal_uInt8 nFlags;
+ rStrm >> rModel.mnBackColorIdx >> rModel.mnPattColorIdx >> rModel.mnPattern >> nFlags;
+ rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_FILL_AUTO );
+ return rStrm;
+}
+
+// ============================================================================
+
+BiffObjTextModel::BiffObjTextModel() :
+ mnTextLen( 0 ),
+ mnFormatSize( 0 ),
+ mnLinkSize( 0 ),
+ mnDefFontId( 0 ),
+ mnFlags( 0 ),
+ mnOrientation( BIFF_OBJ_ORIENT_NONE ),
+ mnButtonFlags( 0 ),
+ mnShortcut( 0 ),
+ mnShortcutEA( 0 )
+{
+}
+
+void BiffObjTextModel::readObj3( BiffInputStream& rStrm )
+{
+ rStrm >> mnTextLen;
+ rStrm.skip( 2 );
+ rStrm >> mnFormatSize >> mnDefFontId;
+ rStrm.skip( 2 );
+ rStrm >> mnFlags >> mnOrientation;
+ rStrm.skip( 8 );
+}
+
+void BiffObjTextModel::readObj5( BiffInputStream& rStrm )
+{
+ rStrm >> mnTextLen;
+ rStrm.skip( 2 );
+ rStrm >> mnFormatSize >> mnDefFontId;
+ rStrm.skip( 2 );
+ rStrm >> mnFlags >> mnOrientation;
+ rStrm.skip( 2 );
+ rStrm >> mnLinkSize;
+ rStrm.skip( 2 );
+ rStrm >> mnButtonFlags >> mnShortcut >> mnShortcutEA;
+}
+
+void BiffObjTextModel::readTxo8( BiffInputStream& rStrm )
+{
+ rStrm >> mnFlags >> mnOrientation >> mnButtonFlags >> mnShortcut >> mnShortcutEA >> mnTextLen >> mnFormatSize;
+}
+
+sal_uInt8 BiffObjTextModel::getHorAlign() const
+{
+ return extractValue< sal_uInt8 >( mnFlags, 1, 3 );
+}
+
+sal_uInt8 BiffObjTextModel::getVerAlign() const
+{
+ return extractValue< sal_uInt8 >( mnFlags, 4, 3 );
+}
+
+// ============================================================================
+// BIFF drawing objects
+// ============================================================================
+
+BiffDrawingObjectContainer::BiffDrawingObjectContainer()
+{
+}
+
+void BiffDrawingObjectContainer::append( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ maObjects.push_back( rxDrawingObj );
+}
+
+void BiffDrawingObjectContainer::insertGrouped( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ if( !maObjects.empty() )
+ if( BiffGroupObject* pGroupObj = dynamic_cast< BiffGroupObject* >( maObjects.back().get() ) )
+ if( pGroupObj->tryInsert( rxDrawingObj ) )
+ return;
+ maObjects.push_back( rxDrawingObj );
+}
+
+void BiffDrawingObjectContainer::convertAndInsert( BiffDrawingBase& rDrawing, const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
+{
+ maObjects.forEachMem( &BiffDrawingObjectBase::convertAndInsert, ::boost::ref( rDrawing ), ::boost::cref( rxShapes ), pParentRect );
+}
+
+// ============================================================================
+
+BiffDrawingObjectBase::BiffDrawingObjectBase( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ maAnchor( rHelper ),
+ mnDffShapeId( 0 ),
+ mnDffFlags( 0 ),
+ mnObjId( BIFF_OBJ_INVALID_ID ),
+ mnObjType( BIFF_OBJTYPE_UNKNOWN ),
+ mbHasAnchor( false ),
+ mbHidden( false ),
+ mbVisible( true ),
+ mbPrintable( true ),
+ mbAreaObj( false ),
+ mbAutoMargin( true ),
+ mbSimpleMacro( true ),
+ mbProcessShape( true ),
+ mbInsertShape( true ),
+ mbCustomDff( false )
+{
+}
+
+BiffDrawingObjectBase::~BiffDrawingObjectBase()
+{
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff3( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 30 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff3 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff3( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff4( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 30 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff4 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff4( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff5( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 34 )
+ {
+ sal_uInt16 nObjType;
+ rStrm.skip( 4 );
+ rStrm >> nObjType;
+ switch( nObjType )
+ {
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break;
+ case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
+#endif
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff5 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+
+ xDrawingObj->importObjBiff5( rStrm );
+ return xDrawingObj;
+}
+
+/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff8( const WorksheetHelper& rHelper, BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+ if( rStrm.getRemaining() >= 10 )
+ {
+ sal_uInt16 nSubRecId, nSubRecSize, nObjType;
+ rStrm >> nSubRecId >> nSubRecSize >> nObjType;
+ OSL_ENSURE( nSubRecId == BIFF_ID_OBJCMO, "BiffDrawingObjectBase::importObjBiff8 - OBJCMO subrecord expected" );
+ if( (nSubRecId == BIFF_ID_OBJCMO) && (nSubRecSize >= 6) )
+ {
+ switch( nObjType )
+ {
+#if 0
+ // in BIFF8, all simple objects support text
+ case BIFF_OBJTYPE_LINE:
+ case BIFF_OBJTYPE_ARC:
+ xDrawingObj.reset( new XclImpTextObj( rHelper ) );
+ // lines and arcs may be 2-dimensional
+ xDrawingObj->setAreaObj( false );
+ break;
+
+ // in BIFF8, all simple objects support text
+ case BIFF_OBJTYPE_RECTANGLE:
+ case BIFF_OBJTYPE_OVAL:
+ case BIFF_OBJTYPE_POLYGON:
+ case BIFF_OBJTYPE_DRAWING:
+ case BIFF_OBJTYPE_TEXT:
+ xDrawingObj.reset( new XclImpTextObj( rHelper ) );
+ break;
+#endif
+
+ case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break;
+#if 0
+ case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break;
+ case BIFF_OBJTYPE_NOTE: xDrawingObj.reset( new XclImpNoteObj( rHelper ) ); break;
+#endif
+
+ default:
+#if 0
+ OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff8 - unknown object type" );
+#endif
+ xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) );
+ }
+ }
+ }
+
+ xDrawingObj->importObjBiff8( rStrm );
+ return xDrawingObj;
+}
+
+Reference< XShape > BiffDrawingObjectBase::convertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const
+{
+ Reference< XShape > xShape;
+ if( rxShapes.is() && mbProcessShape && !mbHidden ) // TODO: support for hidden objects?
+ {
+ // base class 'ShapeAnchor' calculates the shape rectangle in 1/100 mm
+ // in BIFF3-BIFF5, all shapes have absolute anchor (also children of group shapes)
+ Rectangle aShapeRect = maAnchor.calcAnchorRectHmm( getDrawPageSize() );
+
+ // convert the shape, if the calculated rectangle is not empty
+ bool bHasWidth = aShapeRect.Width > 0;
+ bool bHasHeight = aShapeRect.Height > 0;
+ if( mbAreaObj ? (bHasWidth && bHasHeight) : (bHasWidth || bHasHeight) )
+ {
+ xShape = implConvertAndInsert( rDrawing, rxShapes, aShapeRect );
+ /* Notify the drawing that a new shape has been inserted (but not
+ for children of group shapes). For convenience, pass the
+ rectangle that contains position and size of the shape. */
+ if( !pParentRect && xShape.is() )
+ rDrawing.notifyShapeInserted( xShape, aShapeRect );
+ }
+ }
+ return xShape;
+}
+
+// protected ------------------------------------------------------------------
+
+void BiffDrawingObjectBase::readNameBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen )
+{
+ maObjName = OUString();
+ if( nNameLen > 0 )
+ {
+ // name length field is repeated before the name
+ maObjName = rStrm.readByteStringUC( false, getTextEncoding() );
+ // skip padding byte for word boundaries
+ rStrm.alignToBlock( 2 );
+ }
+}
+
+void BiffDrawingObjectBase::readMacroBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+ // skip padding byte for word boundaries, not contained in nMacroSize
+ rStrm.alignToBlock( 2 );
+}
+
+void BiffDrawingObjectBase::readMacroBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+}
+
+void BiffDrawingObjectBase::readMacroBiff5( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ maMacroName = OUString();
+ rStrm.skip( nMacroSize );
+}
+
+void BiffDrawingObjectBase::readMacroBiff8( BiffInputStream& rStrm )
+{
+ maMacroName = OUString();
+ if( rStrm.getRemaining() > 6 )
+ {
+ // macro is stored in a tNameXR token containing a link to a defined name
+ sal_uInt16 nFmlaSize;
+ rStrm >> nFmlaSize;
+ rStrm.skip( 4 );
+ OSL_ENSURE( nFmlaSize == 7, "BiffDrawingObjectBase::readMacroBiff8 - unexpected formula size" );
+ if( nFmlaSize == 7 )
+ {
+ sal_uInt8 nTokenId;
+ sal_uInt16 nExtLinkId, nExtNameId;
+ rStrm >> nTokenId >> nExtLinkId >> nExtNameId;
+#if 0
+ OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
+ "BiffDrawingObjectBase::readMacroBiff8 - tNameXR token expected" );
+ if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
+ maMacroName = GetLinkManager().GetMacroName( nExtLinkId, nExtNameId );
+#endif
+ }
+ }
+}
+
+void BiffDrawingObjectBase::convertLineProperties( ShapePropertyMap& rPropMap, const BiffObjLineModel& rLineModel, sal_uInt16 nArrows ) const
+{
+ if( rLineModel.mbAuto )
+ {
+ BiffObjLineModel aAutoModel;
+ aAutoModel.mbAuto = false;
+ convertLineProperties( rPropMap, aAutoModel, nArrows );
+ return;
+ }
+
+ /* Convert line formatting to DrawingML line formatting and let the
+ DrawingML code do the hard work. */
+ LineProperties aLineProps;
+
+ if( rLineModel.mnStyle == BIFF_OBJ_LINE_NONE )
+ {
+ aLineProps.maLineFill.moFillType = XML_noFill;
+ }
+ else
+ {
+ aLineProps.maLineFill.moFillType = XML_solidFill;
+ aLineProps.maLineFill.maFillColor.setPaletteClr( rLineModel.mnColorIdx );
+ aLineProps.moLineCompound = XML_sng;
+ aLineProps.moLineCap = XML_flat;
+ aLineProps.moLineJoint = XML_round;
+
+ // line width: use 0.35 mm per BIFF line width step
+ sal_Int32 nLineWidth = 0;
+ switch( rLineModel.mnWidth )
+ {
+ default:
+ case BIFF_OBJ_LINE_HAIR: nLineWidth = 0; break;
+ case BIFF_OBJ_LINE_THIN: nLineWidth = 20; break;
+ case BIFF_OBJ_LINE_MEDIUM: nLineWidth = 40; break;
+ case BIFF_OBJ_LINE_THICK: nLineWidth = 60; break;
+ }
+ aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( convertHmmToEmu( nLineWidth ), 0, SAL_MAX_INT32 );
+
+ // dash style and transparency
+ switch( rLineModel.mnStyle )
+ {
+ default:
+ case BIFF_OBJ_LINE_SOLID:
+ aLineProps.moPresetDash = XML_solid;
+ break;
+ case BIFF_OBJ_LINE_DASH:
+ aLineProps.moPresetDash = XML_lgDash;
+ break;
+ case BIFF_OBJ_LINE_DOT:
+ aLineProps.moPresetDash = XML_dot;
+ break;
+ case BIFF_OBJ_LINE_DASHDOT:
+ aLineProps.moPresetDash = XML_lgDashDot;
+ break;
+ case BIFF_OBJ_LINE_DASHDOTDOT:
+ aLineProps.moPresetDash = XML_lgDashDotDot;
+ break;
+ case BIFF_OBJ_LINE_MEDTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 50 * PER_PERCENT );
+ break;
+ case BIFF_OBJ_LINE_DARKTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 75 * PER_PERCENT );
+ break;
+ case BIFF_OBJ_LINE_LIGHTTRANS:
+ aLineProps.moPresetDash = XML_solid;
+ aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 25 * PER_PERCENT );
+ break;
+ }
+
+ // line ends
+ bool bLineStart = false;
+ bool bLineEnd = false;
+ bool bFilled = false;
+ switch( extractValue< sal_uInt8 >( nArrows, 0, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
+ case BIFF_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
+ case BIFF_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
+ case BIFF_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
+ }
+ if( bLineStart || bLineEnd )
+ {
+ // arrow type (open or closed)
+ sal_Int32 nArrowType = bFilled ? XML_triangle : XML_arrow;
+ aLineProps.maStartArrow.moArrowType = bLineStart ? nArrowType : XML_none;
+ aLineProps.maEndArrow.moArrowType = bLineEnd ? nArrowType : XML_none;
+
+ // arrow width
+ sal_Int32 nArrowWidth = XML_med;
+ switch( extractValue< sal_uInt8 >( nArrows, 4, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_NARROW: nArrowWidth = XML_sm; break;
+ case BIFF_OBJ_ARROW_MEDIUM: nArrowWidth = XML_med; break;
+ case BIFF_OBJ_ARROW_WIDE: nArrowWidth = XML_lg; break;
+ }
+ aLineProps.maStartArrow.moArrowWidth = aLineProps.maEndArrow.moArrowWidth = nArrowWidth;
+
+ // arrow length
+ sal_Int32 nArrowLength = XML_med;
+ switch( extractValue< sal_uInt8 >( nArrows, 8, 4 ) )
+ {
+ case BIFF_OBJ_ARROW_NARROW: nArrowLength = XML_sm; break;
+ case BIFF_OBJ_ARROW_MEDIUM: nArrowLength = XML_med; break;
+ case BIFF_OBJ_ARROW_WIDE: nArrowLength = XML_lg; break;
+ }
+ aLineProps.maStartArrow.moArrowLength = aLineProps.maEndArrow.moArrowLength = nArrowLength;
+ }
+ }
+
+ aLineProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
+}
+
+void BiffDrawingObjectBase::convertFillProperties( ShapePropertyMap& rPropMap, const BiffObjFillModel& rFillModel ) const
+{
+ if( rFillModel.mbAuto )
+ {
+ BiffObjFillModel aAutoModel;
+ aAutoModel.mbAuto = false;
+ convertFillProperties( rPropMap, aAutoModel );
+ return;
+ }
+
+ /* Convert fill formatting to DrawingML fill formatting and let the
+ DrawingML code do the hard work. */
+ FillProperties aFillProps;
+
+ if( rFillModel.mnPattern == BIFF_OBJ_PATT_NONE )
+ {
+ aFillProps.moFillType = XML_noFill;
+ }
+ else
+ {
+ const sal_Int32 spnPatternPresets[] = {
+ XML_TOKEN_INVALID, XML_TOKEN_INVALID, XML_pct50, XML_pct50, XML_pct25,
+ XML_dkHorz, XML_dkVert, XML_dkDnDiag, XML_dkUpDiag, XML_smCheck, XML_trellis,
+ XML_ltHorz, XML_ltVert, XML_ltDnDiag, XML_ltUpDiag, XML_smGrid, XML_diagCross,
+ XML_pct20, XML_pct10 };
+ sal_Int32 nPatternPreset = STATIC_ARRAY_SELECT( spnPatternPresets, rFillModel.mnPattern, XML_TOKEN_INVALID );
+ if( nPatternPreset == XML_TOKEN_INVALID )
+ {
+ aFillProps.moFillType = XML_solidFill;
+ aFillProps.maFillColor.setPaletteClr( rFillModel.mnPattColorIdx );
+ }
+ else
+ {
+ aFillProps.moFillType = XML_pattFill;
+ aFillProps.maPatternProps.maPattFgColor.setPaletteClr( rFillModel.mnPattColorIdx );
+ aFillProps.maPatternProps.maPattBgColor.setPaletteClr( rFillModel.mnBackColorIdx );
+ aFillProps.maPatternProps.moPattPreset = nPatternPreset;
+ }
+#if 0
+ static const sal_uInt8 sppnPatterns[][ 8 ] =
+ {
+ { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
+ { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
+ { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
+ { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
+ { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
+ { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
+ { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
+ { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
+ { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
+ { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
+ { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
+ { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
+ { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
+ { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
+ { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
+ { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
+ { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
+ };
+ const sal_uInt8* const pnPattern = sppnPatterns[ ::std::min< size_t >( rFillData.mnPattern - 2, STATIC_ARRAY_SIZE( sppnPatterns ) ) ];
+ // create 2-colored 8x8 DIB
+ SvMemoryStream aMemStrm;
+// { 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }
+ aMemStrm << sal_uInt32( 12 ) << sal_Int16( 8 ) << sal_Int16( 8 ) << sal_uInt16( 1 ) << sal_uInt16( 1 );
+ aMemStrm << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF );
+ aMemStrm << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 );
+ for( size_t nIdx = 0; nIdx < 8; ++nIdx )
+ aMemStrm << sal_uInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
+ aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
+ Bitmap aBitmap;
+ aBitmap.Read( aMemStrm, FALSE );
+ XOBitmap aXOBitmap( aBitmap );
+ aXOBitmap.Bitmap2Array();
+ aXOBitmap.SetBitmapType( XBITMAP_8X8 );
+ if( aXOBitmap.GetBackgroundColor().GetColor() == COL_BLACK )
+ ::std::swap( aPattColor, aBackColor );
+ aXOBitmap.SetPixelColor( aPattColor );
+ aXOBitmap.SetBackgroundColor( aBackColor );
+ rSdrObj.SetMergedItem( XFillStyleItem( XFILL_BITMAP ) );
+ rSdrObj.SetMergedItem( XFillBitmapItem( EMPTY_STRING, aXOBitmap ) );
+#endif
+ }
+
+ aFillProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() );
+}
+
+void BiffDrawingObjectBase::convertFrameProperties( ShapePropertyMap& /*rPropMap*/, sal_uInt16 /*nFrameFlags*/ ) const
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff3( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff4( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff5( BiffInputStream& /*rStrm*/, sal_uInt16 /*nNameLen*/, sal_uInt16 /*nMacroSize*/ )
+{
+}
+
+void BiffDrawingObjectBase::implReadObjBiff8SubRec( BiffInputStream& /*rStrm*/, sal_uInt16 /*nSubRecId*/, sal_uInt16 /*nSubRecSize*/ )
+{
+}
+
+// private --------------------------------------------------------------------
+
+void BiffDrawingObjectBase::importObjBiff3( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ implReadObjBiff3( rStrm, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff4( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
+ implReadObjBiff4( rStrm, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff5( BiffInputStream& rStrm )
+{
+ // back to offset 4 (ignore object count field)
+ rStrm.seek( 4 );
+
+ sal_uInt16 nObjFlags, nMacroSize, nNameLen;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize;
+ rStrm.skip( 2 );
+ rStrm >> nNameLen;
+ rStrm.skip( 2 );
+
+ mbHasAnchor = true;
+ mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN );
+ mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE );
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE );
+ implReadObjBiff5( rStrm, nNameLen, nMacroSize );
+}
+
+void BiffDrawingObjectBase::importObjBiff8( BiffInputStream& rStrm )
+{
+ // back to beginning
+ rStrm.seekToStart();
+
+ bool bLoop = true;
+ while( bLoop && (rStrm.getRemaining() >= 4) )
+ {
+ sal_uInt16 nSubRecId, nSubRecSize;
+ rStrm >> nSubRecId >> nSubRecSize;
+ sal_Int64 nStrmPos = rStrm.tell();
+ // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
+ nSubRecSize = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nSubRecSize, rStrm.getRemaining() ) );
+
+ switch( nSubRecId )
+ {
+ case BIFF_ID_OBJCMO:
+ OSL_ENSURE( rStrm.tell() == 4, "BiffDrawingObjectBase::importObjBiff8 - unexpected OBJCMO subrecord" );
+ if( (rStrm.tell() == 4) && (nSubRecSize >= 6) )
+ {
+ sal_uInt16 nObjFlags;
+ rStrm >> mnObjType >> mnObjId >> nObjFlags;
+ mbPrintable = getFlag( nObjFlags, BIFF_OBJCMO_PRINTABLE );
+ }
+ break;
+ case BIFF_ID_OBJMACRO:
+ readMacroBiff8( rStrm );
+ break;
+ case BIFF_ID_OBJEND:
+ bLoop = false;
+ break;
+ default:
+ implReadObjBiff8SubRec( rStrm, nSubRecId, nSubRecSize );
+ }
+
+ // seek to end of subrecord
+ rStrm.seek( nStrmPos + nSubRecSize );
+ }
+
+ /* Call doReadObj8SubRec() with BIFF_ID_OBJEND for further stream
+ processing (e.g. charts), even if the OBJEND subrecord is missing. */
+ implReadObjBiff8SubRec( rStrm, BIFF_ID_OBJEND, 0 );
+
+ /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
+ IMGDATA record following the OBJ record (but they use the image data
+ stored in DFF). The IMGDATA record may be continued by several CONTINUE
+ records. But the last CONTINUE record may be in fact an MSODRAWING
+ record that contains the DFF data of the next drawing object! So we
+ have to skip just enough CONTINUE records to look at the next
+ MSODRAWING/CONTINUE record. */
+ if( (rStrm.getNextRecId() == BIFF3_ID_IMGDATA) && rStrm.startNextRecord() )
+ {
+ rStrm.skip( 4 );
+ sal_Int64 nDataSize = rStrm.readuInt32();
+ nDataSize -= rStrm.getRemaining();
+ // skip following CONTINUE records until IMGDATA ends
+ while( (nDataSize > 0) && (rStrm.getNextRecId() == BIFF_ID_CONT) && rStrm.startNextRecord() )
+ {
+ OSL_ENSURE( nDataSize >= rStrm.getRemaining(), "BiffDrawingObjectBase::importObjBiff8 - CONTINUE too long" );
+ nDataSize -= ::std::min( rStrm.getRemaining(), nDataSize );
+ }
+ OSL_ENSURE( nDataSize == 0, "BiffDrawingObjectBase::importObjBiff8 - missing CONTINUE records" );
+ // next record may be MSODRAWING or CONTINUE or anything else
+ }
+}
+
+// ============================================================================
+
+BiffPlaceholderObject::BiffPlaceholderObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper )
+{
+ setProcessShape( false );
+}
+
+Reference< XShape > BiffPlaceholderObject::implConvertAndInsert( BiffDrawingBase& /*rDrawing*/,
+ const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const
+{
+ return Reference< XShape >();
+}
+
+// ============================================================================
+
+BiffGroupObject::BiffGroupObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnFirstUngrouped( BIFF_OBJ_INVALID_ID )
+{
+}
+
+bool BiffGroupObject::tryInsert( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ if( rxDrawingObj->getObjId() == mnFirstUngrouped )
+ return false;
+ // insert into own list or into nested group
+ maChildren.insertGrouped( rxDrawingObj );
+ return true;
+}
+
+void BiffGroupObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffGroupObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffGroupObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm.skip( 4 );
+ rStrm >> mnFirstUngrouped;
+ rStrm.skip( 16 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffGroupObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ Reference< XShape > xGroupShape;
+ if( !maChildren.empty() ) try
+ {
+ xGroupShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect );
+ Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
+ maChildren.convertAndInsert( rDrawing, xChildShapes, &rShapeRect );
+ // no child shape has been created - delete the group shape
+ if( !xChildShapes->hasElements() )
+ {
+ rxShapes->remove( xGroupShape );
+ xGroupShape.clear();
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ return xGroupShape;
+}
+
+// ============================================================================
+
+BiffLineObject::BiffLineObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnArrows( 0 ),
+ mnStartPoint( BIFF_OBJ_LINE_TL )
+{
+ setAreaObj( false );
+}
+
+void BiffLineObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffLineObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffLineObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm >> maLineModel >> mnArrows >> mnStartPoint;
+ rStrm.skip( 1 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffLineObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertLineProperties( aPropMap, maLineModel, mnArrows );
+
+ // create the line polygon
+ PointSequenceSequence aPoints( 1 );
+ aPoints[ 0 ].realloc( 2 );
+ Point& rBeg = aPoints[ 0 ][ 0 ];
+ Point& rEnd = aPoints[ 0 ][ 1 ];
+ sal_Int32 nL = rShapeRect.X;
+ sal_Int32 nT = rShapeRect.Y;
+ sal_Int32 nR = rShapeRect.X + ::std::max< sal_Int32 >( rShapeRect.Width - 1, 0 );
+ sal_Int32 nB = rShapeRect.Y + ::std::max< sal_Int32 >( rShapeRect.Height - 1, 0 );
+ switch( mnStartPoint )
+ {
+ default:
+ case BIFF_OBJ_LINE_TL: rBeg.X = nL; rBeg.Y = nT; rEnd.X = nR; rEnd.Y = nB; break;
+ case BIFF_OBJ_LINE_TR: rBeg.X = nR; rBeg.Y = nT; rEnd.X = nL; rEnd.Y = nB; break;
+ case BIFF_OBJ_LINE_BR: rBeg.X = nR; rBeg.Y = nB; rEnd.X = nL; rEnd.Y = nT; break;
+ case BIFF_OBJ_LINE_BL: rBeg.X = nL; rBeg.Y = nB; rEnd.X = nR; rEnd.Y = nT; break;
+ }
+ aPropMap.setProperty( PROP_PolyPolygon, aPoints );
+ aPropMap.setProperty( PROP_PolygonKind, PolygonKind_LINE );
+
+ // create the shape
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.LineShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffRectObject::BiffRectObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnFrameFlags( 0 )
+{
+ setAreaObj( true );
+}
+
+void BiffRectObject::readFrameData( BiffInputStream& rStrm )
+{
+ rStrm >> maFillModel >> maLineModel >> mnFrameFlags;
+}
+
+void BiffRectObject::convertRectProperties( ShapePropertyMap& rPropMap ) const
+{
+ convertLineProperties( rPropMap, maLineModel );
+ convertFillProperties( rPropMap, maFillModel );
+ convertFrameProperties( rPropMap, mnFrameFlags );
+}
+
+void BiffRectObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffRectObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffRectObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffRectObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffOvalObject::BiffOvalObject( const WorksheetHelper& rHelper ) :
+ BiffRectObject( rHelper )
+{
+}
+
+Reference< XShape > BiffOvalObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffArcObject::BiffArcObject( const WorksheetHelper& rHelper ) :
+ BiffDrawingObjectBase( rHelper ),
+ mnQuadrant( BIFF_OBJ_ARC_TR )
+{
+ setAreaObj( false ); // arc may be 2-dimensional
+}
+
+void BiffArcObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readMacroBiff3( rStrm, nMacroSize );
+}
+
+void BiffArcObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readMacroBiff4( rStrm, nMacroSize );
+}
+
+void BiffArcObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ rStrm >> maFillModel >> maLineModel >> mnQuadrant;
+ rStrm.skip( 1 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+}
+
+Reference< XShape > BiffArcObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertLineProperties( aPropMap, maLineModel );
+ convertFillProperties( aPropMap, maFillModel );
+
+ /* Simulate arc objects with ellipse sections. While the original arc
+ object uses the entire object rectangle, only one quarter of the
+ ellipse shape will be visible. Thus, the size of the ellipse shape
+ needs to be extended and its position adjusted according to the visible
+ quadrant. */
+ Rectangle aNewRect( rShapeRect.X, rShapeRect.Y, rShapeRect.Width * 2, rShapeRect.Height * 2 );
+ long nStartAngle = 0;
+ switch( mnQuadrant )
+ {
+ default:
+ case BIFF_OBJ_ARC_TR: nStartAngle = 0; aNewRect.X -= rShapeRect.Width; break;
+ case BIFF_OBJ_ARC_TL: nStartAngle = 9000; break;
+ case BIFF_OBJ_ARC_BL: nStartAngle = 18000; aNewRect.Y -= rShapeRect.Height; break;
+ case BIFF_OBJ_ARC_BR: nStartAngle = 27000; aNewRect.X -= rShapeRect.Width; aNewRect.Y -= rShapeRect.Height; break;
+ }
+ long nEndAngle = (nStartAngle + 9000) % 36000;
+ aPropMap.setProperty( PROP_CircleKind, maFillModel.isFilled() ? CircleKind_SECTION : CircleKind_ARC );
+ aPropMap.setProperty( PROP_CircleStartAngle, nStartAngle );
+ aPropMap.setProperty( PROP_CircleEndAngle, nEndAngle );
+
+ // create the shape
+ Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, aNewRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ return xShape;
+}
+
+// ============================================================================
+
+BiffPolygonObject::BiffPolygonObject( const WorksheetHelper& rHelper ) :
+ BiffRectObject( rHelper ),
+ mnPolyFlags( 0 ),
+ mnPointCount( 0 )
+{
+ setAreaObj( false ); // polygon may be 2-dimensional
+}
+
+void BiffPolygonObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ rStrm >> mnPolyFlags;
+ rStrm.skip( 10 );
+ rStrm >> mnPointCount;
+ rStrm.skip( 8 );
+ readMacroBiff4( rStrm, nMacroSize );
+ importCoordList( rStrm );
+}
+
+void BiffPolygonObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
+{
+ readFrameData( rStrm );
+ rStrm >> mnPolyFlags;
+ rStrm.skip( 10 );
+ rStrm >> mnPointCount;
+ rStrm.skip( 8 );
+ readNameBiff5( rStrm, nNameLen );
+ readMacroBiff5( rStrm, nMacroSize );
+ importCoordList( rStrm );
+}
+
+namespace {
+
+Point lclGetPolyPoint( const Rectangle& rAnchorRect, const Point& rPoint )
+{
+ // polygon coordinates are given in 1/16384 of shape size
+ return Point(
+ rAnchorRect.X + static_cast< sal_Int32 >( rAnchorRect.Width * getLimitedValue< double >( static_cast< double >( rPoint.X ) / 16384.0, 0.0, 1.0 ) + 0.5 ),
+ rAnchorRect.Y + static_cast< sal_Int32 >( rAnchorRect.Height * getLimitedValue< double >( static_cast< double >( rPoint.Y ) / 16384.0, 0.0, 1.0 ) + 0.5 ) );
+}
+
+} // namespace
+
+Reference< XShape > BiffPolygonObject::implConvertAndInsert( BiffDrawingBase& rDrawing,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ Reference< XShape > xShape;
+ if( maCoords.size() >= 2 )
+ {
+ ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() );
+ convertRectProperties( aPropMap );
+
+ // create the polygon
+ PointVector aPolygon;
+ for( PointVector::const_iterator aIt = maCoords.begin(), aEnd = maCoords.end(); aIt != aEnd; ++aIt )
+ aPolygon.push_back( lclGetPolyPoint( rShapeRect, *aIt ) );
+ // close polygon if specified
+ if( getFlag( mnPolyFlags, BIFF_OBJ_POLY_CLOSED ) && ((maCoords.front().X != maCoords.back().X) || (maCoords.front().Y != maCoords.back().Y)) )
+ aPolygon.push_back( aPolygon.front() );
+ PointSequenceSequence aPoints( 1 );
+ aPoints[ 0 ] = ContainerHelper::vectorToSequence( aPolygon );
+ aPropMap.setProperty( PROP_PolyPolygon, aPoints );
+
+ // create the shape
+ OUString aService = maFillModel.isFilled() ?
+ CREATE_OUSTRING( "com.sun.star.drawing.PolyPolygonShape" ) :
+ CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" );
+ xShape = rDrawing.createAndInsertXShape( aService, rxShapes, rShapeRect );
+ PropertySet( xShape ).setProperties( aPropMap );
+ }
+ return xShape;
+}
+
+void BiffPolygonObject::importCoordList( BiffInputStream& rStrm )
+{
+ if( (rStrm.getNextRecId() == BIFF_ID_COORDLIST) && rStrm.startNextRecord() )
+ {
+ OSL_ENSURE( rStrm.getRemaining() / 4 == mnPointCount, "BiffPolygonObject::importCoordList - wrong polygon point count" );
+ while( rStrm.getRemaining() >= 4 )
+ {
+ sal_uInt16 nX, nY;
+ rStrm >> nX >> nY;
+ maCoords.push_back( Point( nX, nY ) );
+ }
+ }
+}
+
+// ============================================================================
+// BIFF drawing page
+// ============================================================================
+
+BiffDrawingBase::BiffDrawingBase( const WorksheetHelper& rHelper, const Reference< XDrawPage >& rxDrawPage ) :
+ WorksheetHelper( rHelper ),
+ mxDrawPage( rxDrawPage )
+{
+}
+
+void BiffDrawingBase::importObj( BiffInputStream& rStrm )
+{
+ BiffDrawingObjectRef xDrawingObj;
+
+#if 0
+ /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
+ records. In this case, the OBJ records are in BIFF5 format. Do a sanity
+ check here that there is no DFF data loaded before. */
+ DBG_ASSERT( maDffStrm.Tell() == 0, "BiffDrawingBase::importObj - unexpected DFF stream data, OBJ will be ignored" );
+ if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
+#else
+ switch( getBiff() )
+#endif
+ {
+ case BIFF3:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff3( *this, rStrm );
+ break;
+ case BIFF4:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff4( *this, rStrm );
+ break;
+ case BIFF5:
+// TODO: add BIFF8 when DFF is supported
+// case BIFF8:
+ xDrawingObj = BiffDrawingObjectBase::importObjBiff5( *this, rStrm );
+ break;
+ default:;
+ }
+
+ if( xDrawingObj.get() )
+ {
+ // insert into maRawObjs or into the last open group object
+ maRawObjs.insertGrouped( xDrawingObj );
+ // to be able to find objects by ID
+ maObjMapId[ xDrawingObj->getObjId() ] = xDrawingObj;
+ }
+}
+
+void BiffDrawingBase::setSkipObj( sal_uInt16 nObjId )
+{
+ /* Store identifiers of objects to be skipped in a separate list (the OBJ
+ record may not be read yet). In the finalization phase, all objects
+ registered here will be skipped. */
+ maSkipObjs.push_back( nObjId );
+}
+
+void BiffDrawingBase::finalizeImport()
+{
+ Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY );
+ OSL_ENSURE( xShapes.is(), "BiffDrawingBase::finalizeImport - no shapes container" );
+ if( !xShapes.is() )
+ return;
+
+ // process list of objects to be skipped
+ for( BiffObjIdVector::const_iterator aIt = maSkipObjs.begin(), aEnd = maSkipObjs.end(); aIt != aEnd; ++aIt )
+ if( BiffDrawingObjectBase* pDrawingObj = maObjMapId.get( *aIt ).get() )
+ pDrawingObj->setProcessShape( false );
+
+ // process drawing objects without DFF data
+ maRawObjs.convertAndInsert( *this, xShapes );
+}
+
+Reference< XShape > BiffDrawingBase::createAndInsertXShape( const OUString& rService,
+ const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
+{
+ OSL_ENSURE( rService.getLength() > 0, "BiffDrawingBase::createAndInsertXShape - missing UNO shape service name" );
+ OSL_ENSURE( rxShapes.is(), "BiffDrawingBase::createAndInsertXShape - missing XShapes container" );
+ Reference< XShape > xShape;
+ if( (rService.getLength() > 0) && rxShapes.is() ) try
+ {
+ xShape.set( getBaseFilter().getModelFactory()->createInstance( rService ), UNO_QUERY_THROW );
+ // insert shape into passed shape collection (maybe drawpage or group shape)
+ rxShapes->add( xShape );
+ xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
+ xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
+ }
+ catch( Exception& )
+ {
+ }
+ OSL_ENSURE( xShape.is(), "BiffDrawingBase::createAndInsertXShape - cannot instanciate shape object" );
+ return xShape;
+}
+
+// protected ------------------------------------------------------------------
+
+void BiffDrawingBase::appendRawObject( const BiffDrawingObjectRef& rxDrawingObj )
+{
+ OSL_ENSURE( rxDrawingObj.get(), "BiffDrawingBase::appendRawObject - unexpected empty object reference" );
+ maRawObjs.append( rxDrawingObj );
+}
+
+// ============================================================================
+
+BiffSheetDrawing::BiffSheetDrawing( const WorksheetHelper& rHelper ) :
+ BiffDrawingBase( rHelper, rHelper.getDrawPage() )
+{
+}
+
+void BiffSheetDrawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const Rectangle& rShapeRect )
+{
+ // collect all shape positions in the WorksheetHelper base class
+ extendShapeBoundingBox( rShapeRect );
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox