diff options
author | Daniel Rentz [dr] <daniel.rentz@oracle.com> | 2011-01-04 18:51:14 +0100 |
---|---|---|
committer | Daniel Rentz [dr] <daniel.rentz@oracle.com> | 2011-01-04 18:51:14 +0100 |
commit | c15fb91736dfb70247d864267290d0053a05267c (patch) | |
tree | 0fe4b29ce3091812bda56cbccdf137594f067f3f /oox/source/xls | |
parent | 673e27f14bbf6ebd8e72c4715f7b34dcc6310519 (diff) |
dr78: oox - import of BIFF3-BIFF5 drawing objects - first bits
Diffstat (limited to 'oox/source/xls')
-rwxr-xr-x | oox/source/xls/drawingbase.cxx | 327 | ||||
-rw-r--r-- | oox/source/xls/drawingfragment.cxx | 362 | ||||
-rwxr-xr-x | oox/source/xls/drawingmanager.cxx | 979 | ||||
-rw-r--r-- | oox/source/xls/makefile.mk | 2 | ||||
-rw-r--r-- | oox/source/xls/worksheetfragment.cxx | 6 | ||||
-rw-r--r-- | oox/source/xls/worksheethelper.cxx | 146 |
6 files changed, 1412 insertions, 410 deletions
diff --git a/oox/source/xls/drawingbase.cxx b/oox/source/xls/drawingbase.cxx new file mode 100755 index 000000000000..c7a901ead30a --- /dev/null +++ b/oox/source/xls/drawingbase.cxx @@ -0,0 +1,327 @@ +/************************************************************************* + * + * 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/drawingbase.hxx" + +#include <com/sun/star/awt/Rectangle.hpp> +#include "oox/core/namespaces.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/xls/unitconverter.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::table; +using namespace ::oox::drawingml; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +/** Converts the passed 32-bit integer value from 1/100 mm to EMUs. */ +inline sal_Int64 lclHmmToEmu( sal_Int32 nValue ) +{ + return (nValue < 0) ? -1 : convertHmmToEmu( nValue ); +} + +/** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */ +inline sal_Int32 lclEmuToHmm( sal_Int64 nValue ) +{ + return (nValue < 0) ? -1 : convertEmuToHmm( nValue ); +} + +/** Reads the cell anchor model from a BIFF or DFF stream. */ +BinaryInputStream& operator>>( BinaryInputStream& rStrm, CellAnchorModel& rModel ) +{ + // all members are given as 16-bit unsigned values + rModel.mnCol = rStrm.readuInt16(); + rModel.mnColOffset = rStrm.readuInt16(); + rModel.mnRow = rStrm.readuInt16(); + rModel.mnRowOffset = rStrm.readuInt16(); + return rStrm; +} + +} // namespace + +// ============================================================================ + +CellAnchorModel::CellAnchorModel() : + mnCol( -1 ), + mnRow( -1 ), + mnColOffset( 0 ), + mnRowOffset( 0 ) +{ +} + +// ---------------------------------------------------------------------------- + +AnchorClientDataModel::AnchorClientDataModel() : + mbLocksWithSheet( true ), + mbPrintsWithSheet( true ) +{ +} + +// ============================================================================ + +ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + meAnchorType( ANCHOR_INVALID ), + meCellAnchorType( CELLANCHOR_EMU ), + mnEditAs( XML_twoCell ) +{ +} + +void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( nElement ) + { + case XDR_TOKEN( absoluteAnchor ): + meAnchorType = ANCHOR_ABSOLUTE; + break; + case XDR_TOKEN( oneCellAnchor ): + meAnchorType = ANCHOR_ONECELL; + break; + case XDR_TOKEN( twoCellAnchor ): + meAnchorType = ANCHOR_TWOCELL; + mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell ); + break; + default: + OSL_ENSURE( false, "ShapeAnchor::importAnchor - unexpected element" ); + } + meCellAnchorType = CELLANCHOR_EMU; +} + +void ShapeAnchor::importPos( const AttributeList& rAttribs ) +{ + OSL_ENSURE( meAnchorType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" ); + maPos.X = rAttribs.getHyper( XML_x, 0 ); + maPos.Y = rAttribs.getHyper( XML_y, 0 ); +} + +void ShapeAnchor::importExt( const AttributeList& rAttribs ) +{ + OSL_ENSURE( (meAnchorType == ANCHOR_ABSOLUTE) || (meAnchorType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" ); + maSize.Width = rAttribs.getHyper( XML_cx, 0 ); + maSize.Height = rAttribs.getHyper( XML_cy, 0 ); +} + +void ShapeAnchor::importClientData( const AttributeList& rAttribs ) +{ + maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true ); + maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true ); +} + +void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) +{ + CellAnchorModel* pCellAnchor = 0; + switch( nParentContext ) + { + case XDR_TOKEN( from ): + OSL_ENSURE( (meAnchorType == ANCHOR_ONECELL) || (meAnchorType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" ); + pCellAnchor = &maFrom; + break; + case XDR_TOKEN( to ): + OSL_ENSURE( meAnchorType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" ); + pCellAnchor = &maTo; + break; + default: + OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected parent element" ); + } + if( pCellAnchor ) switch( nElement ) + { + case XDR_TOKEN( col ): pCellAnchor->mnCol = rValue.toInt32(); break; + case XDR_TOKEN( row ): pCellAnchor->mnRow = rValue.toInt32(); break; + case XDR_TOKEN( colOff ): pCellAnchor->mnColOffset = rValue.toInt64(); break; + case XDR_TOKEN( rowOff ): pCellAnchor->mnRowOffset = rValue.toInt64(); break; + default: OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected element" ); + } +} + +void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) +{ + meAnchorType = ANCHOR_TWOCELL; /// VML uses two-cell anchors only + meCellAnchorType = CELLANCHOR_PIXEL; /// VML uses screen pixels for offset values + + ::std::vector< OUString > aTokens; + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() ); + + OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" ); + if( aTokens.size() >= 8 ) + { + maFrom.mnCol = aTokens[ 0 ].toInt32(); + maFrom.mnColOffset = aTokens[ 1 ].toInt32(); + maFrom.mnRow = aTokens[ 2 ].toInt32(); + maFrom.mnRowOffset = aTokens[ 3 ].toInt32(); + maTo.mnCol = aTokens[ 4 ].toInt32(); + maTo.mnColOffset = aTokens[ 5 ].toInt32(); + maTo.mnRow = aTokens[ 6 ].toInt32(); + maTo.mnRowOffset = aTokens[ 7 ].toInt32(); + } +} + +void ShapeAnchor::importBiffAnchor( BinaryInputStream& rStrm ) +{ + meAnchorType = ANCHOR_TWOCELL; /// BIFF/DFF use two-cell anchors only + meCellAnchorType = CELLANCHOR_COLROW; /// BIFF/DFF use fraction of column/row for offset values + rStrm >> maFrom >> maTo; +} + +EmuRectangle ShapeAnchor::calcAnchorRectEmu( const Size& rPageSizeHmm ) const +{ + AddressConverter& rAddrConv = getAddressConverter(); + const UnitConverter& rUnitConv = getUnitConverter(); + + EmuSize aPageSize( lclHmmToEmu( rPageSizeHmm.Width ), lclHmmToEmu( rPageSizeHmm.Height ) ); + EmuRectangle aAnchorRect( -1, -1, -1, -1 ); + + // calculate shape position + switch( meAnchorType ) + { + case ANCHOR_ABSOLUTE: + OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maPos.isValid() && (maPos.X < aPageSize.Width) && (maPos.Y < aPageSize.Height) ) + aAnchorRect.setPos( maPos ); + break; + case ANCHOR_ONECELL: + case ANCHOR_TWOCELL: + OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) + { + EmuPoint aPoint = calcCellAnchorEmu( maFrom ); + if( (aPoint.X < aPageSize.Width) && (aPoint.Y < aPageSize.Height) ) + aAnchorRect.setPos( aPoint ); + } + break; + case ANCHOR_INVALID: + OSL_ENSURE( false, "ShapeAnchor::calcAnchorRectEmu - invalid anchor" ); + break; + } + + // calculate shape size + if( (aAnchorRect.X >= 0) && (aAnchorRect.Y >= 0) ) switch( meAnchorType ) + { + case ANCHOR_ABSOLUTE: + case ANCHOR_ONECELL: + OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid size" ); + if( maSize.isValid() ) + { + aAnchorRect.Width = ::std::min< sal_Int64 >( maSize.Width, aPageSize.Width - aAnchorRect.X ); + aAnchorRect.Height = ::std::min< sal_Int64 >( maSize.Height, aPageSize.Height - aAnchorRect.Y ); + } + break; + case ANCHOR_TWOCELL: + OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maTo.isValid() ) + { + /* Pass a valid cell address to calcCellAnchorEmu(), otherwise + nothing useful is returned, even if either row or column is valid. */ + CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); + CellAnchorModel aValidTo = maTo; + aValidTo.mnCol = aToCell.Column; + aValidTo.mnRow = aToCell.Row; + EmuPoint aPoint = calcCellAnchorEmu( aValidTo ); + // width (if column index is valid, use the calculated offset, otherwise stretch to maximum available X position) + aAnchorRect.Width = aPageSize.Width - aAnchorRect.X; + if( aToCell.Column == maTo.mnCol ) + aAnchorRect.Width = ::std::min< sal_Int64 >( aPoint.X - aAnchorRect.X + 1, aAnchorRect.Width ); + // height (if row index is valid, use the calculated offset, otherwise stretch to maximum available Y position) + aAnchorRect.Height = aPageSize.Height - aAnchorRect.Y; + if( aToCell.Row == maTo.mnRow ) + aAnchorRect.Height = ::std::min< sal_Int64 >( aPoint.Y - aAnchorRect.Y + 1, aAnchorRect.Height ); + } + break; + case ANCHOR_INVALID: + break; + } + + // add 0.75 mm (27,000 EMUs) in X direction to correct display error + if( aAnchorRect.X >= 0 ) + aAnchorRect.X += 27000; + // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error + if( aAnchorRect.Y >= 9000 ) + aAnchorRect.Y -= 9000; + + return aAnchorRect; +} + +Rectangle ShapeAnchor::calcAnchorRectHmm( const Size& rPageSizeHmm ) const +{ + EmuRectangle aAnchorRect = calcAnchorRectEmu( rPageSizeHmm ); + return Rectangle( lclEmuToHmm( aAnchorRect.X ), lclEmuToHmm( aAnchorRect.Y ), lclEmuToHmm( aAnchorRect.Width ), lclEmuToHmm( aAnchorRect.Height ) ); +} + +// private -------------------------------------------------------------------- + +EmuPoint ShapeAnchor::calcCellAnchorEmu( const CellAnchorModel& rModel ) const +{ + // calculate position of top-left edge of the cell + Point aPoint = getCellPosition( rModel.mnCol, rModel.mnRow ); + EmuPoint aEmuPoint( lclHmmToEmu( aPoint.X ), lclHmmToEmu( aPoint.Y ) ); + + // add the offset inside the cell + switch( meCellAnchorType ) + { + case CELLANCHOR_EMU: + aEmuPoint.X += rModel.mnColOffset; + aEmuPoint.Y += rModel.mnRowOffset; + break; + + case CELLANCHOR_PIXEL: + { + const UnitConverter& rUnitConv = getUnitConverter(); + aEmuPoint.X += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnColOffset ), UNIT_SCREENX, UNIT_EMU ) ); + aEmuPoint.Y += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnRowOffset ), UNIT_SCREENY, UNIT_EMU ) ); + } + break; + + case CELLANCHOR_COLROW: + { + Size aCellSize = getCellSize( rModel.mnCol, rModel.mnRow ); + EmuSize aEmuSize( lclHmmToEmu( aCellSize.Width ), lclHmmToEmu( aCellSize.Height ) ); + // X offset is given in 1/1024 of column width + aEmuPoint.X += static_cast< sal_Int64 >( aEmuSize.Width * getLimitedValue< double >( static_cast< double >( rModel.mnColOffset ) / 1024.0, 0.0, 1.0 ) + 0.5 ); + // Y offset is given in 1/256 of row height + aEmuPoint.Y += static_cast< sal_Int64 >( aEmuSize.Height * getLimitedValue< double >( static_cast< double >( rModel.mnRowOffset ) / 256.0, 0.0, 1.0 ) + 0.5 ); + } + break; + } + + return aEmuPoint; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/drawingfragment.cxx b/oox/source/xls/drawingfragment.cxx index 172530692923..45e311aea4a2 100644 --- a/oox/source/xls/drawingfragment.cxx +++ b/oox/source/xls/drawingfragment.cxx @@ -67,6 +67,9 @@ using ::com::sun::star::table::CellAddress; using ::com::sun::star::table::CellRangeAddress; using ::oox::core::ContextHandlerRef; using ::oox::drawingml::ConnectorShapeContext; +using ::oox::drawingml::EmuPoint; +using ::oox::drawingml::EmuRectangle; +using ::oox::drawingml::EmuSize; using ::oox::drawingml::GraphicalObjectFrameContext; using ::oox::drawingml::GraphicShapeContext; using ::oox::drawingml::Shape; @@ -80,352 +83,11 @@ namespace xls { // ============================================================================ -namespace { - -/** Converts the passed 64-bit integer value from the passed unit to EMUs. */ -sal_Int64 lclCalcEmu( const UnitConverter& rUnitConv, sal_Int64 nValue, Unit eFromUnit ) -{ - return (eFromUnit == UNIT_EMU) ? nValue : - static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( nValue ), eFromUnit, UNIT_EMU ) + 0.5 ); -} - -} // namespace - -// ============================================================================ - -AnchorCellModel::AnchorCellModel() : - mnCol( -1 ), - mnRow( -1 ), - mnColOffset( 0 ), - mnRowOffset( 0 ) -{ -} - -// ---------------------------------------------------------------------------- - -AnchorClientDataModel::AnchorClientDataModel() : - mbLocksWithSheet( true ), - mbPrintsWithSheet( true ) -{ -} - -// ============================================================================ - -ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) : - WorksheetHelper( rHelper ), - meType( ANCHOR_INVALID ), - mnEditAs( XML_twoCell ) -{ -} - -void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ) -{ - switch( nElement ) - { - case XDR_TOKEN( absoluteAnchor ): - meType = ANCHOR_ABSOLUTE; - break; - case XDR_TOKEN( oneCellAnchor ): - meType = ANCHOR_ONECELL; - break; - case XDR_TOKEN( twoCellAnchor ): - meType = ANCHOR_TWOCELL; - mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell ); - break; - default: - OSL_ENSURE( false, "ShapeAnchor::importAnchor - unexpected element" ); - } -} - -void ShapeAnchor::importPos( const AttributeList& rAttribs ) -{ - OSL_ENSURE( meType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" ); - maPos.X = rAttribs.getHyper( XML_x, 0 ); - maPos.Y = rAttribs.getHyper( XML_y, 0 ); -} - -void ShapeAnchor::importExt( const AttributeList& rAttribs ) -{ - OSL_ENSURE( (meType == ANCHOR_ABSOLUTE) || (meType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" ); - maSize.Width = rAttribs.getHyper( XML_cx, 0 ); - maSize.Height = rAttribs.getHyper( XML_cy, 0 ); -} - -void ShapeAnchor::importClientData( const AttributeList& rAttribs ) -{ - maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true ); - maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true ); -} - -void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) -{ - AnchorCellModel* pAnchorCell = 0; - switch( nParentContext ) - { - case XDR_TOKEN( from ): - OSL_ENSURE( (meType == ANCHOR_ONECELL) || (meType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" ); - pAnchorCell = &maFrom; - break; - case XDR_TOKEN( to ): - OSL_ENSURE( meType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" ); - pAnchorCell = &maTo; - break; - default: - OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected parent element" ); - } - if( pAnchorCell ) switch( nElement ) - { - case XDR_TOKEN( col ): pAnchorCell->mnCol = rValue.toInt32(); break; - case XDR_TOKEN( row ): pAnchorCell->mnRow = rValue.toInt32(); break; - case XDR_TOKEN( colOff ): pAnchorCell->mnColOffset = rValue.toInt64(); break; - case XDR_TOKEN( rowOff ): pAnchorCell->mnRowOffset = rValue.toInt64(); break; - default: OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected element" ); - } -} - -void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) -{ - meType = ANCHOR_VML; - - ::std::vector< OUString > aTokens; - sal_Int32 nIndex = 0; - while( nIndex >= 0 ) - aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() ); - - OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" ); - if( aTokens.size() >= 8 ) - { - maFrom.mnCol = aTokens[ 0 ].toInt32(); - maFrom.mnColOffset = aTokens[ 1 ].toInt32(); - maFrom.mnRow = aTokens[ 2 ].toInt32(); - maFrom.mnRowOffset = aTokens[ 3 ].toInt32(); - maTo.mnCol = aTokens[ 4 ].toInt32(); - maTo.mnColOffset = aTokens[ 5 ].toInt32(); - maTo.mnRow = aTokens[ 6 ].toInt32(); - maTo.mnRowOffset = aTokens[ 7 ].toInt32(); - } -} - -bool ShapeAnchor::isValidAnchor() const -{ - bool bValid = false; - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::isValidAnchor - invalid position" ); - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" ); - bValid = maPos.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0); - break; - case ANCHOR_ONECELL: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" ); - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" ); - bValid = maFrom.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0); - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" ); - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::isValidAnchor - invalid to position" ); - bValid = maFrom.isValid() && maTo.isValid() && - ((maFrom.mnCol < maTo.mnCol) || ((maFrom.mnCol == maTo.mnCol) && (maFrom.mnColOffset < maTo.mnColOffset))) && - ((maFrom.mnRow < maTo.mnRow) || ((maFrom.mnRow == maTo.mnRow) && (maFrom.mnRowOffset < maTo.mnRowOffset))); - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::isValidAnchor - invalid anchor" ); - break; - } - return bValid; -} - -Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorSizeModel& rEmuSheetSize ) const -{ - AddressConverter& rAddrConv = getAddressConverter(); - UnitConverter& rUnitConv = getUnitConverter(); - Rectangle aApiLoc( -1, -1, -1, -1 ); - Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; - Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; - - // calculate shape position - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maPos.isValid() && (maPos.X < rEmuSheetSize.Width) && (maPos.Y < rEmuSheetSize.Height) ) - { - aApiLoc.X = rUnitConv.scaleToMm100( static_cast< double >( maPos.X ), UNIT_EMU ); - aApiLoc.Y = rUnitConv.scaleToMm100( static_cast< double >( maPos.Y ), UNIT_EMU ); - } - break; - case ANCHOR_ONECELL: - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) - { - Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - aApiLoc.X = aPoint.X + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnColOffset ), eUnitX ); - aApiLoc.Y = aPoint.Y + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnRowOffset ), eUnitY ); - } - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::calcApiLocation - invalid anchor" ); - break; - } - - // calculate shape size - if( (aApiLoc.X >= 0) && (aApiLoc.Y >= 0) ) switch( meType ) - { - case ANCHOR_ABSOLUTE: - case ANCHOR_ONECELL: - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcApiLocation - invalid size" ); - if( maSize.isValid() ) - { - aApiLoc.Width = ::std::min< sal_Int32 >( - rUnitConv.scaleToMm100( static_cast< double >( maSize.Width ), UNIT_EMU ), - rApiSheetSize.Width - aApiLoc.X ); - aApiLoc.Height = ::std::min< sal_Int32 >( - rUnitConv.scaleToMm100( static_cast< double >( maSize.Height ), UNIT_EMU ), - rApiSheetSize.Height - aApiLoc.Y ); - } - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maTo.isValid() ) - { - /* Pass a valid cell address to getCellPosition(), otherwise - nothing is returned, even if either row or column is valid. */ - CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); - Point aPoint = getCellPosition( aToCell.Column, aToCell.Row ); - // width - aApiLoc.Width = rApiSheetSize.Width - aApiLoc.X; - if( aToCell.Column == maTo.mnCol ) - { - aPoint.X += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnColOffset ), eUnitX ); - aApiLoc.Width = ::std::min< sal_Int32 >( aPoint.X - aApiLoc.X + 1, aApiLoc.Width ); - } - // height - aApiLoc.Height = rApiSheetSize.Height - aApiLoc.Y; - if( aToCell.Row == maTo.mnRow ) - { - aPoint.Y += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnRowOffset ), eUnitY ); - aApiLoc.Height = ::std::min< sal_Int32 >( aPoint.Y - aApiLoc.Y + 1, aApiLoc.Height ); - } - } - break; - case ANCHOR_INVALID: - break; - } - - return aApiLoc; -} - -Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) const -{ - AddressConverter& rAddrConv = getAddressConverter(); - UnitConverter& rUnitConv = getUnitConverter(); - - Size aSheetSize( - getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Width, 0, SAL_MAX_INT32 ), - getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Height, 0, SAL_MAX_INT32 ) ); - Rectangle aLoc( -1, -1, -1, -1 ); - Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; - Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; - - // calculate shape position - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maPos.isValid() && (maPos.X < aSheetSize.Width) && (maPos.Y < aSheetSize.Height) ) - { - aLoc.X = static_cast< sal_Int32 >( maPos.X ); - aLoc.Y = static_cast< sal_Int32 >( maPos.Y ); - } - break; - case ANCHOR_ONECELL: - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) - { - Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnColOffset, eUnitX ); - sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnRowOffset, eUnitY ); - if( (nX < aSheetSize.Width) && (nY < aSheetSize.Height) ) - { - aLoc.X = static_cast< sal_Int32 >( nX ); - aLoc.Y = static_cast< sal_Int32 >( nY ); - } - } - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::calcEmuLocation - invalid anchor" ); - break; - } - - // calculate shape size - if( (aLoc.X >= 0) && (aLoc.Y >= 0) ) switch( meType ) - { - case ANCHOR_ABSOLUTE: - case ANCHOR_ONECELL: - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcEmuLocation - invalid size" ); - if( maSize.isValid() ) - { - aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Width, aSheetSize.Width - aLoc.X ) ); - aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Height, aSheetSize.Height - aLoc.Y ) ); - } - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maTo.isValid() ) - { - /* Pass a valid cell address to getCellPosition(), otherwise - nothing is returned, even if either row or column is valid. */ - CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); - Point aPoint = getCellPosition( aToCell.Column, aToCell.Row ); - sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ); - sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ); - // width - aLoc.Width = aSheetSize.Width - aLoc.X; - if( aToCell.Column == maTo.mnCol ) - { - nX += lclCalcEmu( rUnitConv, maTo.mnColOffset, eUnitX ); - aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nX - aLoc.X + 1, aLoc.Width ) ); - } - // height - aLoc.Height = aSheetSize.Height - aLoc.Y; - if( aToCell.Row == maTo.mnRow ) - { - nY += lclCalcEmu( rUnitConv, maTo.mnRowOffset, eUnitY ); - aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nY - aLoc.Y + 1, aLoc.Height ) ); - } - } - break; - case ANCHOR_INVALID: - break; - } - - // add 0.75 mm (27,000 EMUs) in X direction to correct display error - if( aLoc.X >= 0 ) - aLoc.X += 27000; - // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error - if( aLoc.Y >= 9000 ) - aLoc.Y -= 9000; - - return aLoc; -} - -// ============================================================================ - OoxDrawingFragment::OoxDrawingFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : OoxWorksheetFragmentBase( rHelper, rFragmentPath ), mxDrawPage( rHelper.getDrawPage(), UNO_QUERY ) { OSL_ENSURE( mxDrawPage.is(), "OoxDrawingFragment::OoxDrawingFragment - missing drawing page" ); - maApiSheetSize = getDrawPageSize(); - maEmuSheetSize.Width = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Width, UNIT_EMU ) ); - maEmuSheetSize.Height = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Height, UNIT_EMU ) ); } // oox.core.ContextHandler2Helper interface ----------------------------------- @@ -507,14 +169,20 @@ void OoxDrawingFragment::onEndElement( const OUString& rChars ) case XDR_TOKEN( absoluteAnchor ): case XDR_TOKEN( oneCellAnchor ): case XDR_TOKEN( twoCellAnchor ): - if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() && mxAnchor->isValidAnchor() ) + if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() ) { - Rectangle aShapeRect = mxAnchor->calcEmuLocation( maEmuSheetSize ); - if( (aShapeRect.X >= 0) && (aShapeRect.Y >= 0) && (aShapeRect.Width >= 0) && (aShapeRect.Height >= 0) ) + EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( getDrawPageSize() ); + if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) ) { - mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, &aShapeRect ); + // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle) + Rectangle aShapeRectEmu32( + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) ); + mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, &aShapeRectEmu32 ); // collect all shape positions in the WorksheetHelper base class - extendShapeBoundingBox( aShapeRect ); + extendShapeBoundingBox( aShapeRectEmu32 ); } } mxShape.reset(); @@ -577,7 +245,7 @@ bool VmlDrawing::convertShapeClientAnchor( Rectangle& orShapeRect, const OUStrin return false; ShapeAnchor aAnchor( *this ); aAnchor.importVmlAnchor( rShapeAnchor ); - orShapeRect = aAnchor.calcApiLocation( getDrawPageSize(), AnchorSizeModel() ); + orShapeRect = aAnchor.calcAnchorRectHmm( getDrawPageSize() ); return (orShapeRect.Width >= 0) && (orShapeRect.Height >= 0); } diff --git a/oox/source/xls/drawingmanager.cxx b/oox/source/xls/drawingmanager.cxx new file mode 100755 index 000000000000..16e5ceddd27d --- /dev/null +++ b/oox/source/xls/drawingmanager.cxx @@ -0,0 +1,979 @@ +/************************************************************************* + * + * 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/XShapes.hpp> +#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_OBJ_INVALID_ID = 0; + +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; + +// 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 ), + mnAuto( BIFF_OBJ_LINE_AUTO ) +{ +} + +bool BiffObjLineModel::isAuto() const +{ + return getFlag( mnAuto, BIFF_OBJ_LINE_AUTO ); +} + +bool BiffObjLineModel::isVisible() const +{ + return isAuto() || (mnStyle != BIFF_OBJ_LINE_NONE); +} + +BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjLineModel& rModel ) +{ + return rStrm >> rModel.mnColorIdx >> rModel.mnStyle >> rModel.mnWidth >> rModel.mnAuto; +} + +// ============================================================================ + +BiffObjFillModel::BiffObjFillModel() : + mnBackColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ), + mnPattColorIdx( BIFF_OBJ_FILL_AUTOCOLOR ), + mnPattern( BIFF_OBJ_PATT_SOLID ), + mnAuto( BIFF_OBJ_FILL_AUTO ) +{ +} + +bool BiffObjFillModel::isAuto() const +{ + return getFlag( mnAuto, BIFF_OBJ_FILL_AUTO ); +} + +bool BiffObjFillModel::isFilled() const +{ + return isAuto() || (mnPattern != BIFF_OBJ_PATT_NONE); +} + +BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjFillModel& rModel ) +{ + return rStrm >> rModel.mnBackColorIdx >> rModel.mnPattColorIdx >> rModel.mnPattern >> rModel.mnAuto; +} + +// ============================================================================ + +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 ), + mnObjId( BIFF_OBJ_INVALID_ID ), + mnObjType( BIFF_OBJTYPE_UNKNOWN ), + mnDffShapeId( 0 ), + mnDffFlags( 0 ), + 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; +#if 0 + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new XclImpArcObj( rHelper ) ); break; + 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: + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff3 - unknown object type" ); + 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; +#if 0 + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new XclImpArcObj( rHelper ) ); break; + 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_POLYGON: xDrawingObj.reset( new XclImpPolygonObj( rHelper ) ); break; +#endif + default: + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff4 - unknown object type" ); + 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; +#if 0 + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new XclImpArcObj( rHelper ) ); break; + 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_POLYGON: xDrawingObj.reset( new XclImpPolygonObj( 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: + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff5 - unknown object type" ); + 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: + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff8 - unknown object type" ); + 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 + 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::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 +{ + return Reference< XShape >(); +} + +// ============================================================================ + +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 +{ + return rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.LineShape" ), rxShapes, rShapeRect ); +} + +// ============================================================================ + +BiffRectObject::BiffRectObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ), + mnFrameFlags( 0 ) +{ + setAreaObj( true ); +} + +void BiffRectObject::readFrameData( BiffInputStream& rStrm ) +{ + rStrm >> maFillModel >> maLineModel >> 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 +{ + return rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ), rxShapes, rShapeRect ); +} + +// ============================================================================ + +BiffOvalObject::BiffOvalObject( const WorksheetHelper& rHelper ) : + BiffRectObject( rHelper ) +{ +} + +Reference< XShape > BiffOvalObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + return rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, rShapeRect ); +} + +// ============================================================================ +// 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: + 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 + { + Reference< XMultiServiceFactory > xFactory( getDocumentFactory(), UNO_SET_THROW ); + xShape.set( xFactory->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 diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk index b5ede953bbfe..493575a408a8 100644 --- a/oox/source/xls/makefile.mk +++ b/oox/source/xls/makefile.mk @@ -55,7 +55,9 @@ SLOFILES = \ $(SLO)$/condformatcontext.obj \ $(SLO)$/connectionsfragment.obj \ $(SLO)$/defnamesbuffer.obj \ + $(SLO)$/drawingbase.obj \ $(SLO)$/drawingfragment.obj \ + $(SLO)$/drawingmanager.obj \ $(SLO)$/excelchartconverter.obj \ $(SLO)$/excelfilter.obj \ $(SLO)$/excelhandlers.obj \ diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx index bee58fdbaff3..9a8fa57f68cb 100644 --- a/oox/source/xls/worksheetfragment.cxx +++ b/oox/source/xls/worksheetfragment.cxx @@ -36,6 +36,7 @@ #include "oox/xls/commentsfragment.hxx" #include "oox/xls/condformatcontext.hxx" #include "oox/xls/drawingfragment.hxx" +#include "oox/xls/drawingmanager.hxx" #include "oox/xls/externallinkbuffer.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/pivottablebuffer.hxx" @@ -772,6 +773,7 @@ bool BiffWorksheetFragment::importFragment() SheetViewSettings& rSheetViewSett = getSheetViewSettings(); CondFormatBuffer& rCondFormats = getCondFormats(); PageSettings& rPageSett = getPageSettings(); + BiffSheetDrawing& rDrawing = getBiffDrawing(); // process all record in this sheet fragment while( mrStrm.startNextRecord() && (mrStrm.getRecId() != BIFF_ID_EOF) ) @@ -831,6 +833,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_DEFCOLWIDTH: importDefColWidth(); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break; + case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( mrStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( mrStrm ); break; @@ -846,6 +849,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_COLINFO: importColInfo(); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break; + case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( mrStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( mrStrm ); break; @@ -863,6 +867,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight(); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( mrStrm ); break; case BIFF_ID_MERGEDCELLS: importMergedCells(); break; // #i62300# also in BIFF5 + case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( mrStrm ); break; case BIFF_ID_PTDEFINITION: importPTDefinition(); break; @@ -889,6 +894,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_HYPERLINK: importHyperlink(); break; case BIFF_ID_LABELRANGES: importLabelRanges(); break; case BIFF_ID_MERGEDCELLS: importMergedCells(); break; +// case BIFF_ID_OBJ: rDrawing.importObj( mrStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( mrStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( mrStrm ); break; case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( mrStrm ); break; diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx index d2d42f2be369..626d3b962ceb 100644 --- a/oox/source/xls/worksheethelper.cxx +++ b/oox/source/xls/worksheethelper.cxx @@ -62,6 +62,7 @@ #include "oox/xls/commentsbuffer.hxx" #include "oox/xls/condformatbuffer.hxx" #include "oox/xls/drawingfragment.hxx" +#include "oox/xls/drawingmanager.hxx" #include "oox/xls/formulaparser.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/sharedformulabuffer.hxx" @@ -396,7 +397,7 @@ public: /** Returns the XDrawPage interface of the draw page of the current sheet. */ Reference< XDrawPage > getDrawPage() const; /** Returns the size of the entire drawing page in 1/100 mm. */ - Size getDrawPageSize() const; + const Size& getDrawPageSize() const; /** Returns the absolute position of the top-left corner of the cell in 1/100 mm. */ Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const; @@ -404,7 +405,7 @@ public: Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const; /** Returns the address of the cell that contains the passed point in 1/100 mm. */ - CellAddress getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const; + CellAddress getCellAddressFromPosition( const Point& rPosition ) const; /** Returns the cell range address that contains the passed rectangle in 1/100 mm. */ CellRangeAddress getCellRangeFromRectangle( const Rectangle& rRect ) const; @@ -420,8 +421,10 @@ public: inline PageSettings& getPageSettings() { return maPageSett; } /** Returns the view settings for this sheet. */ inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; } - /** Returns the VML drawing page for this sheet (OOX only!). */ + /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only). */ inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; } + /** Returns the BIFF drawing page for this sheet (BIFF2-BIFF8 only). */ + inline BiffSheetDrawing& getBiffDrawing() const { return *mxBiffDrawing; } /** Changes the current sheet type. */ inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; } @@ -543,13 +546,6 @@ private: /** Merges the passed merged range and updates right/bottom cell borders. */ void finalizeMergedRange( const CellRangeAddress& rRange ); - /** Imports the drawing layer of the sheet (DrawingML part). */ - void finalizeDrawing(); - /** Imports the drawing layer of the sheet (VML part). */ - void finalizeVmlDrawing(); - /** Extends the used cell area with the area used by drawing objects. */ - void finalizeUsedArea(); - /** Converts column properties for all columns in the sheet. */ void convertColumns(); /** Converts column properties. */ @@ -565,8 +561,12 @@ private: /** Groups columns or rows for the given range. */ void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows ); + /** Imports the drawings of the sheet (DML, VML, DFF) and updates the used area. */ + void finalizeDrawings(); + private: - typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; + typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; + typedef ::std::auto_ptr< BiffSheetDrawing > BiffSheetDrawingPtr; const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells. const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells. @@ -592,8 +592,10 @@ private: PageSettings maPageSett; /// Page/print settings for this sheet. SheetViewSettings maSheetViewSett; /// View settings for this sheet. VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes. + BiffSheetDrawingPtr mxBiffDrawing; /// Collection of all BIFF/DFF shapes. OUString maDrawingPath; /// Path to DrawingML fragment. OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment. + Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm. Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings. ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing. @@ -645,8 +647,17 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, ISegmentProgressBar maDefRowModel.mbCollapsed = false; // buffers - if( getFilterType() == FILTER_OOX ) - mxVmlDrawing.reset( new VmlDrawing( *this ) ); + switch( getFilterType() ) + { + case FILTER_OOX: + mxVmlDrawing.reset( new VmlDrawing( *this ) ); + break; + case FILTER_BIFF: + mxBiffDrawing.reset( new BiffSheetDrawing( *this ) ); + break; + case FILTER_UNKNOWN: + break; + } // prepare progress bars if( mxProgressBar.get() ) @@ -771,12 +782,10 @@ Reference< XDrawPage > WorksheetData::getDrawPage() const return xDrawPage; } -Size WorksheetData::getDrawPageSize() const +const Size& WorksheetData::getDrawPageSize() const { - Size aSize; - PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) ); - aRangeProp.getProperty( aSize, PROP_Size ); - return aSize; + OSL_ENSURE( (maDrawPageSize.Width > 0) && (maDrawPageSize.Height > 0), "WorksheetData::getDrawPageSize - called too early, size invalid" ); + return maDrawPageSize; } Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const @@ -864,7 +873,7 @@ bool lclUpdateInterval( sal_Int32& rnBegAddr, sal_Int32& rnMidAddr, sal_Int32& r } // namespace -CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const +CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition ) const { // starting cell address and its position in drawing layer (top-left edge) sal_Int32 nBegCol = 0; @@ -874,7 +883,7 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c // end cell address and its position in drawing layer (bottom-right edge) sal_Int32 nEndCol = mrMaxApiPos.Column + 1; sal_Int32 nEndRow = mrMaxApiPos.Row + 1; - Point aEndPos( rDrawPageSize.Width, rDrawPageSize.Height ); + Point aEndPos( maDrawPageSize.Width, maDrawPageSize.Height ); // starting point for interval search sal_Int32 nMidCol, nMidRow; @@ -902,10 +911,9 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRect ) const { - Size aPageSize = getDrawPageSize(); - CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ), aPageSize ); + CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ) ); Point aBotRight( rRect.X + rRect.Width, rRect.Y + rRect.Height ); - CellAddress aEndAddr = getCellAddressFromPosition( aBotRight, aPageSize ); + CellAddress aEndAddr = getCellAddressFromPosition( aBotRight ); bool bMultiCols = aStartAddr.Column < aEndAddr.Column; bool bMultiRows = aStartAddr.Row < aEndAddr.Row; if( bMultiCols || bMultiRows ) @@ -1171,10 +1179,7 @@ void WorksheetData::finalizeWorksheetImport() convertColumns(); convertRows(); lclUpdateProgressBar( mxFinalProgress, 0.75 ); - finalizeDrawing(); - finalizeVmlDrawing(); - maComments.finalizeImport(); // after VML drawing - finalizeUsedArea(); // after DML and VML drawing + finalizeDrawings(); lclUpdateProgressBar( mxFinalProgress, 1.0 ); // reset current sheet index in global data @@ -1561,42 +1566,6 @@ void WorksheetData::finalizeMergedRange( const CellRangeAddress& rRange ) } } -void WorksheetData::finalizeDrawing() -{ - OSL_ENSURE( (getFilterType() == FILTER_OOX) || (maDrawingPath.getLength() == 0), - "WorksheetData::finalizeDrawing - unexpected DrawingML path" ); - if( (getFilterType() == FILTER_OOX) && (maDrawingPath.getLength() > 0) ) - importOoxFragment( new OoxDrawingFragment( *this, maDrawingPath ) ); -} - -void WorksheetData::finalizeVmlDrawing() -{ - OSL_ENSURE( (getFilterType() == FILTER_OOX) || (maVmlDrawingPath.getLength() == 0), - "WorksheetData::finalizeVmlDrawing - unexpected VML path" ); - if( (getFilterType() == FILTER_OOX) && (maVmlDrawingPath.getLength() > 0) ) - importOoxFragment( new OoxVmlDrawingFragment( *this, maVmlDrawingPath ) ); -} - -void WorksheetData::finalizeUsedArea() -{ - /* Extend used area of the sheet by cells covered with drawing objects. - Needed if the imported document is inserted as "OLE object from file" - and thus does not provide an OLE size property by itself. */ - if( (maShapeBoundingBox.Width > 0) || (maShapeBoundingBox.Height > 0) ) - extendUsedArea( getCellRangeFromRectangle( maShapeBoundingBox ) ); - - // if no used area is set, default to A1 - if( maUsedArea.StartColumn > maUsedArea.EndColumn ) - maUsedArea.StartColumn = maUsedArea.EndColumn = 0; - if( maUsedArea.StartRow > maUsedArea.EndRow ) - maUsedArea.StartRow = maUsedArea.EndRow = 0; - - /* Register the used area of this sheet in global view settings. The - global view settings will set the visible area if this document is an - embedded OLE object. */ - getViewSettings().setSheetUsedArea( maUsedArea ); -} - void WorksheetData::convertColumns() { sal_Int32 nNextCol = 0; @@ -1761,6 +1730,52 @@ void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastC } } +void WorksheetData::finalizeDrawings() +{ + // calculate the current drawing page size (after rows/columns are imported) + PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) ); + aRangeProp.getProperty( maDrawPageSize, PROP_Size ); + + switch( getFilterType() ) + { + case FILTER_OOX: + // import DML and VML + if( maDrawingPath.getLength() > 0 ) + importOoxFragment( new OoxDrawingFragment( *this, maDrawingPath ) ); + if( maVmlDrawingPath.getLength() > 0 ) + importOoxFragment( new OoxVmlDrawingFragment( *this, maVmlDrawingPath ) ); + break; + + case FILTER_BIFF: + // convert BIFF3-BIFF5 drawing objects, or import and convert DFF stream + getBiffDrawing().finalizeImport(); + break; + + case FILTER_UNKNOWN: + break; + } + + // comments (after callout shapes have been imported from VML/DFF) + maComments.finalizeImport(); + + /* Extend used area of the sheet by cells covered with drawing objects. + Needed if the imported document is inserted as "OLE object from file" + and thus does not provide an OLE size property by itself. */ + if( (maShapeBoundingBox.Width > 0) || (maShapeBoundingBox.Height > 0) ) + extendUsedArea( getCellRangeFromRectangle( maShapeBoundingBox ) ); + + // if no used area is set, default to A1 + if( maUsedArea.StartColumn > maUsedArea.EndColumn ) + maUsedArea.StartColumn = maUsedArea.EndColumn = 0; + if( maUsedArea.StartRow > maUsedArea.EndRow ) + maUsedArea.StartRow = maUsedArea.EndRow = 0; + + /* Register the used area of this sheet in global view settings. The + global view settings will set the visible area if this document is an + embedded OLE object. */ + getViewSettings().setSheetUsedArea( maUsedArea ); +} + // ============================================================================ // ============================================================================ @@ -1957,6 +1972,11 @@ VmlDrawing& WorksheetHelper::getVmlDrawing() const return mrSheetData.getVmlDrawing(); } +BiffSheetDrawing& WorksheetHelper::getBiffDrawing() const +{ + return mrSheetData.getBiffDrawing(); +} + void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText ) const { OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" ); |