blob: d6fab4169a0a044e4ca1dc45d393a1d0ab3e42c9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_filter.hxx"
#include "eschesdo.hxx"
#include <svx/svdxcgv.hxx>
#include <svx/svdomedia.hxx>
#include <svx/xflftrit.hxx>
#include <filter/msfilter/escherex.hxx>
#include <svx/unoapi.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdoashp.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdmodel.hxx>
#include <editeng/outlobj.hxx>
#include <vcl/gradient.hxx>
#include <vcl/graph.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/svapp.hxx>
#include <vcl/wrkwin.hxx>
#include <tools/stream.hxx>
#include <tools/zcodec.hxx>
#include <svx/svdopath.hxx>
#include <stdlib.h>
#include <svtools/filter.hxx>
#include "svx/EnhancedCustomShapeTypeNames.hxx"
#include "svx/EnhancedCustomShapeGeometry.hxx"
#include <svx/EnhancedCustomShapeFunctionParser.hxx>
#include "svx/EnhancedCustomShape2d.hxx"
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/awt/GradientStyle.hpp>
#include <com/sun/star/awt/RasterOperation.hpp>
#include <com/sun/star/awt/Gradient.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/LineJoint.hpp>
#include <com/sun/star/drawing/LineCap.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineDash.hpp>
#include <com/sun/star/drawing/BezierPoint.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/ConnectorType.hpp>
#include <com/sun/star/drawing/ConnectionType.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/PolygonFlags.hpp>
#include <com/sun/star/text/WritingMode.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/text/XSimpleText.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <com/sun/star/drawing/TextFitToSizeType.hpp>
#include <vcl/hatch.hxx>
#include <com/sun/star/awt/XGraphics.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/drawing/ColorMode.hpp>
#include <com/sun/star/drawing/Position3D.hpp>
#include <com/sun/star/drawing/Direction3D.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/localfilehelper.hxx>
#include <comphelper/extract.hxx>
#include <toolkit/unohlp.hxx>
#include <vcl/virdev.hxx>
#include <rtl/crc.h>
#include <vos/xception.hxx>
#include <svx/svdlegacy.hxx>
using namespace vos;
using namespace ::rtl;
using namespace ::com::sun::star;
// ---------------------------------------------------------------------------------------------
EscherExContainer::EscherExContainer( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance ) :
rStrm ( rSt )
{
rStrm << (sal_uInt32)( ( 0xf | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
nContPos = rStrm.Tell();
}
EscherExContainer::~EscherExContainer()
{
sal_uInt32 nPos = rStrm.Tell();
sal_uInt32 nSize= nPos - nContPos;
if ( nSize )
{
rStrm.Seek( nContPos - 4 );
rStrm << nSize;
rStrm.Seek( nPos );
}
}
EscherExAtom::EscherExAtom( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance, const sal_uInt8 nVersion ) :
rStrm ( rSt )
{
rStrm << (sal_uInt32)( ( nVersion | ( nInstance << 4 ) ) | ( nRecType << 16 ) ) << (sal_uInt32)0;
nContPos = rStrm.Tell();
}
EscherExAtom::~EscherExAtom()
{
sal_uInt32 nPos = rStrm.Tell();
sal_uInt32 nSize= nPos - nContPos;
if ( nSize )
{
rStrm.Seek( nContPos - 4 );
rStrm << nSize;
rStrm.Seek( nPos );
}
}
// ---------------------------------------------------------------------------------------------
EscherExClientRecord_Base::~EscherExClientRecord_Base()
{
}
EscherExClientAnchor_Base::~EscherExClientAnchor_Base()
{
}
// ---------------------------------------------------------------------------------------------
EscherPropertyContainer::EscherPropertyContainer()
: mpGraphicProvider(0),
mpPicOutStrm(0),
maObjectRange(),
mpSortStruct(0),
mnSortCount(0),
mnSortBufSize(64),
mnCountCount(0),
mnCountSize(0),
mbHasComplexData(false)
{
mpSortStruct = new EscherPropSortStruct[mnSortBufSize];
};
EscherPropertyContainer::EscherPropertyContainer(
EscherGraphicProvider& rGraphProv,
SvStream* pPiOutStrm,
basegfx::B2DRange& rObjectRange) // FillBitmaps or GraphicObjects.
: mpGraphicProvider(&rGraphProv),
mpPicOutStrm(pPiOutStrm),
maObjectRange(rObjectRange),
mpSortStruct(0),
mnSortCount(0),
mnSortBufSize(64),
mnCountCount(0),
mnCountSize(0),
mbHasComplexData(false)
{
mpSortStruct = new EscherPropSortStruct[mnSortBufSize];
}
EscherPropertyContainer::~EscherPropertyContainer()
{
if ( mbHasComplexData )
{
while ( mnSortCount-- )
delete[] mpSortStruct[ mnSortCount ].pBuf;
}
delete[] mpSortStruct;
};
void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, sal_uInt32 nPropValue, bool bBlib )
{
AddOpt( nPropID, bBlib, nPropValue, NULL, 0 );
}
void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, const rtl::OUString& rString )
{
sal_Int32 j, i, nLen = rString.getLength() * 2 + 2;
sal_uInt8* pBuf = new sal_uInt8[ nLen ];
for ( j = i = 0; i < rString.getLength(); i++ )
{
sal_uInt16 nChar = (sal_uInt16)rString[ i ];
pBuf[ j++ ] = (sal_uInt8)nChar;
pBuf[ j++ ] = (sal_uInt8)( nChar >> 8 );
}
pBuf[ j++ ] = 0;
pBuf[ j++ ] = 0;
AddOpt( nPropID, true, nLen, pBuf, nLen );
}
void EscherPropertyContainer::AddOpt( sal_uInt16 nPropID, bool bBlib, sal_uInt32 nPropValue, sal_uInt8* pProp, sal_uInt32 nPropSize )
{
if ( bBlib ) // bBlib is only valid when fComplex = 0
nPropID |= 0x4000;
if ( pProp )
nPropID |= 0x8000; // fComplex = true;
sal_uInt32 i;
for( i = 0; i < mnSortCount; i++ )
{
if ( ( mpSortStruct[ i ].nPropId &~0xc000 ) == ( nPropID &~0xc000 ) ) // pruefen, ob Property nur ersetzt wird
{
mpSortStruct[ i ].nPropId = nPropID;
if ( mpSortStruct[ i ].pBuf )
{
mnCountSize -= mpSortStruct[ i ].nPropSize;
delete[] mpSortStruct[ i ].pBuf;
}
mpSortStruct[ i ].pBuf = pProp;
mpSortStruct[ i ].nPropSize = nPropSize;
mpSortStruct[ i ].nPropValue = nPropValue;
if ( pProp )
mnCountSize += nPropSize;
return;
}
}
mnCountCount++;
mnCountSize += 6;
if ( mnSortCount == mnSortBufSize ) // buffer vergroessern
{
mnSortBufSize <<= 1;
EscherPropSortStruct* pTemp = new EscherPropSortStruct[ mnSortBufSize ];
for( i = 0; i < mnSortCount; i++ )
{
pTemp[ i ] = mpSortStruct[ i ];
}
delete mpSortStruct;
mpSortStruct = pTemp;
}
mpSortStruct[ mnSortCount ].nPropId = nPropID; // property einfuegen
mpSortStruct[ mnSortCount ].pBuf = pProp;
mpSortStruct[ mnSortCount ].nPropSize = nPropSize;
mpSortStruct[ mnSortCount++ ].nPropValue = nPropValue;
if ( pProp )
{
mnCountSize += nPropSize;
mbHasComplexData = true;
}
}
bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, sal_uInt32& rPropValue ) const
{
EscherPropSortStruct aPropStruct;
if ( GetOpt( nPropId, aPropStruct ) )
{
rPropValue = aPropStruct.nPropValue;
return true;
}
return false;
}
bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, EscherPropSortStruct& rPropValue ) const
{
for( sal_uInt32 i = 0; i < mnSortCount; i++ )
{
if ( ( mpSortStruct[ i ].nPropId &~0xc000 ) == ( nPropId &~0xc000 ) )
{
rPropValue = mpSortStruct[ i ];
return true;
}
}
return false;
}
EscherProperties EscherPropertyContainer::GetOpts() const
{
EscherProperties aVector;
for ( sal_uInt32 i = 0; i < mnSortCount; ++i )
aVector.push_back( mpSortStruct[ i ] );
return aVector;
}
extern "C" int __LOADONCALLAPI EscherPropSortFunc( const void* p1, const void* p2 )
{
sal_Int16 nID1 = ((EscherPropSortStruct*)p1)->nPropId &~0xc000;
sal_Int16 nID2 = ((EscherPropSortStruct*)p2)->nPropId &~0xc000;
if( nID1 < nID2 )
return -1;
else if( nID1 > nID2 )
return 1;
else
return 0;
}
void EscherPropertyContainer::Commit( SvStream& rSt, sal_uInt16 nVersion, sal_uInt16 nRecType )
{
rSt << (sal_uInt16)( ( mnCountCount << 4 ) | ( nVersion & 0xf ) ) << nRecType << mnCountSize;
if ( mnSortCount )
{
qsort( mpSortStruct, mnSortCount, sizeof( EscherPropSortStruct ), EscherPropSortFunc );
sal_uInt32 i;
for ( i = 0; i < mnSortCount; i++ )
{
sal_uInt32 nPropValue = mpSortStruct[ i ].nPropValue;
sal_uInt16 nPropId = mpSortStruct[ i ].nPropId;
rSt << nPropId
<< nPropValue;
}
if ( mbHasComplexData )
{
for ( i = 0; i < mnSortCount; i++ )
{
if ( mpSortStruct[ i ].pBuf )
rSt.Write( mpSortStruct[ i ].pBuf, mpSortStruct[ i ].nPropSize );
}
}
}
}
bool EscherPropertyContainer::IsFontWork() const
{
sal_uInt32 nTextPathFlags = 0;
GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
return ( nTextPathFlags & 0x4000 ) != 0;
}
sal_uInt32 EscherPropertyContainer::ImplGetColor( const sal_uInt32 nSOColor, bool bSwap )
{
if ( bSwap )
{
sal_uInt32 nColor = nSOColor & 0xff00; // GRUEN
nColor |= (sal_uInt8)( nSOColor ) << 16; // ROT
nColor |= (sal_uInt8)( nSOColor >> 16 ); // BLAU
return nColor;
}
else
return nSOColor & 0xffffff;
}
sal_uInt32 EscherPropertyContainer::GetGradientColor(
const ::com::sun::star::awt::Gradient* pGradient,
sal_uInt32 nStartColor )
{
sal_uInt32 nIntensity = 100;
Color aColor;
if ( pGradient )
{
if ( nStartColor & 1 )
{
nIntensity = pGradient->StartIntensity;
aColor = pGradient->StartColor;
}
else
{
nIntensity = pGradient->EndIntensity;
aColor = pGradient->EndColor;
}
}
sal_uInt32 nRed = ( ( aColor.GetRed() * nIntensity ) / 100 );
sal_uInt32 nGreen = ( ( aColor.GetGreen() * nIntensity ) / 100 ) << 8;
sal_uInt32 nBlue = ( ( aColor.GetBlue() * nIntensity ) / 100 ) << 16;
return nRed | nGreen | nBlue;
}
void EscherPropertyContainer::CreateGradientProperties(
const ::com::sun::star::awt::Gradient & rGradient )
{
sal_uInt32 nFillType = ESCHER_FillShadeScale;
sal_uInt32 nAngle = 0;
sal_uInt32 nFillFocus = 0;
sal_uInt32 nFillLR = 0;
sal_uInt32 nFillTB = 0;
sal_uInt32 nFirstColor = 0;
bool bWriteFillTo = false;
switch ( rGradient.Style )
{
case ::com::sun::star::awt::GradientStyle_LINEAR :
case ::com::sun::star::awt::GradientStyle_AXIAL :
{
nFillType = ESCHER_FillShadeScale;
nAngle = (rGradient.Angle * 0x10000) / 10;
nFillFocus = (sal::static_int_cast<int>(rGradient.Style) ==
sal::static_int_cast<int>(GradientStyle_LINEAR)) ? 0 : 50;
}
break;
case ::com::sun::star::awt::GradientStyle_RADIAL :
case ::com::sun::star::awt::GradientStyle_ELLIPTICAL :
case ::com::sun::star::awt::GradientStyle_SQUARE :
case ::com::sun::star::awt::GradientStyle_RECT :
{
nFillLR = (rGradient.XOffset * 0x10000) / 100;
nFillTB = (rGradient.YOffset * 0x10000) / 100;
if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
nFillType = ESCHER_FillShadeShape;
else
nFillType = ESCHER_FillShadeCenter;
nFirstColor = 1;
bWriteFillTo = true;
}
break;
case ::com::sun::star::awt::GradientStyle_MAKE_FIXED_SIZE : break;
}
AddOpt( ESCHER_Prop_fillType, nFillType );
AddOpt( ESCHER_Prop_fillAngle, nAngle );
AddOpt( ESCHER_Prop_fillColor, GetGradientColor( &rGradient, nFirstColor ) );
AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( &rGradient, nFirstColor ^ 1 ) );
AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
if ( bWriteFillTo )
{
AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
AddOpt( ESCHER_Prop_fillToTop, nFillTB );
AddOpt( ESCHER_Prop_fillToRight, nFillLR );
AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
}
}
void EscherPropertyContainer::CreateGradientProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet , bool bTransparentGradient)
{
::com::sun::star::uno::Any aAny;
::com::sun::star::awt::Gradient* pGradient = NULL;
sal_uInt32 nFillType = ESCHER_FillShadeScale;
sal_Int32 nAngle = 0;
sal_uInt32 nFillFocus = 0;
sal_uInt32 nFillLR = 0;
sal_uInt32 nFillTB = 0;
sal_uInt32 nFirstColor = 0;//like the control var nChgColors in import logic
bool bWriteFillTo = false;
//Transparency gradient: Means the third setting in transparency page is set
if (bTransparentGradient && EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparenceGradient" ) ), false ) )
{
pGradient = (::com::sun::star::awt::Gradient*)aAny.getValue();
::com::sun::star::uno::Any aAnyTemp;
const rtl::OUString aPropName( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) );
if ( EscherPropertyValueHelper::GetPropertyValue(
aAnyTemp, rXPropSet, aPropName, false ) )
{
::com::sun::star::drawing::FillStyle eFS;
if ( ! ( aAnyTemp >>= eFS ) )
eFS = ::com::sun::star::drawing::FillStyle_SOLID;
//solid and transparency
if ( eFS == ::com::sun::star::drawing::FillStyle_SOLID)
{
if ( EscherPropertyValueHelper::GetPropertyValue(
aAnyTemp, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), false ) )
{
pGradient->StartColor = ImplGetColor( *((sal_uInt32*)aAnyTemp.getValue()), false );
pGradient->EndColor = ImplGetColor( *((sal_uInt32*)aAnyTemp.getValue()), false );
}
}
//gradient and transparency.
else if( eFS == ::com::sun::star::drawing::FillStyle_GRADIENT )
{
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ), false ) )
pGradient = (::com::sun::star::awt::Gradient*)aAny.getValue();
}
}
}
//Not transparency gradient
else if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillGradient" ) ), false ) )
{
pGradient = (::com::sun::star::awt::Gradient*)aAny.getValue();
}
if ( pGradient )
{
switch ( pGradient->Style )
{
case ::com::sun::star::awt::GradientStyle_LINEAR :
case ::com::sun::star::awt::GradientStyle_AXIAL :
{
nFillType = ESCHER_FillShadeScale;
nAngle = pGradient->Angle;
while ( nAngle > 0 ) nAngle -= 3600;
while ( nAngle <= -3600 ) nAngle += 3600;
//Value of the real number = Integral + (Fractional / 65536.0)
nAngle = ( nAngle * 0x10000) / 10;
nFillFocus = (pGradient->Style == ::com::sun::star::awt::GradientStyle_LINEAR) ?
( pGradient->XOffset + pGradient->YOffset )/2 : -50;
if( !nFillFocus )
nFirstColor=nFirstColor ^ 1;
if ( !nAngle )
nFirstColor=nFirstColor ^ 1;
}
break;
case ::com::sun::star::awt::GradientStyle_RADIAL :
case ::com::sun::star::awt::GradientStyle_ELLIPTICAL :
case ::com::sun::star::awt::GradientStyle_SQUARE :
case ::com::sun::star::awt::GradientStyle_RECT :
{
//according to the import logic and rect type fill** value
nFillLR = (pGradient->XOffset * 0x10000) / 100;
nFillTB = (pGradient->YOffset * 0x10000) / 100;
if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
nFillType = ESCHER_FillShadeShape;
else
nFillType = ESCHER_FillShadeCenter;
nFirstColor = 1;
bWriteFillTo = true;
}
break;
default: break;
}
}
AddOpt( ESCHER_Prop_fillType, nFillType );
AddOpt( ESCHER_Prop_fillAngle, nAngle );
AddOpt( ESCHER_Prop_fillColor, GetGradientColor( pGradient, nFirstColor ) );
AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( pGradient, nFirstColor ^ 1 ) );
AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
if ( bWriteFillTo )
{
//according to rect type fillTo** value
if(nFillLR)
{
AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
AddOpt( ESCHER_Prop_fillToRight, nFillLR );
}
if(nFillTB)
{
AddOpt( ESCHER_Prop_fillToTop, nFillTB );
AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
}
}
//Transparency gradient
if (bTransparentGradient && EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparenceGradient" ) ), false ) )
{
pGradient = (::com::sun::star::awt::Gradient*)aAny.getValue();
if ( pGradient )
{
sal_uInt32 nBlue = GetGradientColor( pGradient, nFirstColor ) >> 16;
AddOpt( ESCHER_Prop_fillOpacity,( ( 100 - ( nBlue * 100 / 255 ) ) << 16 ) / 100 );
nBlue = GetGradientColor( pGradient, nFirstColor ^ 1 ) >>16 ;
AddOpt( ESCHER_Prop_fillBackOpacity,( ( 100 - ( nBlue * 100 / 255 ) ) << 16 )/ 100 );
}
}
}
void EscherPropertyContainer::CreateFillProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
bool bEdge , const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
{
if ( rXShape.is() )
{
SdrObject* pObj = GetSdrObjectFromXShape( rXShape );
if ( pObj )
{
SfxItemSet aAttr( pObj->GetMergedItemSet() );
//tranparency with gradient. Means the third setting in transparency page is set
bool bTransparentGradient = ( aAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SFX_ITEM_SET ) &&
( (const XFillFloatTransparenceItem&) aAttr.Get( XATTR_FILLFLOATTRANSPARENCE ) ).IsEnabled();
CreateFillProperties( rXPropSet, bEdge, bTransparentGradient );
}
}
}
void EscherPropertyContainer::CreateFillProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
bool bEdge , bool bTransparentGradient)
{
::com::sun::star::uno::Any aAny;
AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
sal_uInt32 nFillBackColor = 0;
const rtl::OUString aPropName( String( RTL_CONSTASCII_USTRINGPARAM( "FillStyle" ) ) );
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, aPropName, false ) )
{
::com::sun::star::drawing::FillStyle eFS;
if ( ! ( aAny >>= eFS ) )
eFS = ::com::sun::star::drawing::FillStyle_SOLID;
switch( eFS )
{
case ::com::sun::star::drawing::FillStyle_GRADIENT :
{
CreateGradientProperties( rXPropSet , bTransparentGradient );
AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
}
break;
case ::com::sun::star::drawing::FillStyle_BITMAP :
{
CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ), true );
AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
}
break;
case ::com::sun::star::drawing::FillStyle_HATCH :
{
CreateGraphicProperties( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ), true );
}
break;
case ::com::sun::star::drawing::FillStyle_SOLID :
default:
{
if ( bTransparentGradient )
CreateGradientProperties( rXPropSet , bTransparentGradient );
else
{
::com::sun::star::beans::PropertyState ePropState = EscherPropertyValueHelper::GetPropertyState(
rXPropSet, aPropName );
if ( ePropState == ::com::sun::star::beans::PropertyState_DIRECT_VALUE )
AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), false ) )
{
sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
nFillBackColor = nFillColor ^ 0xffffff;
AddOpt( ESCHER_Prop_fillColor, nFillColor );
}
AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
}
break;
}
case ::com::sun::star::drawing::FillStyle_NONE :
AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
break;
}
if ( eFS != ::com::sun::star::drawing::FillStyle_NONE )
{
sal_uInt16 nTransparency = ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillTransparence" ) ), true ) )
? *((sal_Int16*)aAny.getValue() )
: 0;
if ( nTransparency )
AddOpt( ESCHER_Prop_fillOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
}
}
CreateLineProperties( rXPropSet, bEdge );
}
void EscherPropertyContainer::CreateTextProperties(
const uno::Reference< beans::XPropertySet > & rXPropSet, sal_uInt32 nTextId,
const bool bIsCustomShape, const bool bIsTextFrame )
{
uno::Any aAny;
text::WritingMode eWM( text::WritingMode_LR_TB );
drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT );
sal_Int32 nLeft ( 0 );
sal_Int32 nTop ( 0 );
sal_Int32 nRight ( 0 );
sal_Int32 nBottom ( 0 );
// used with normal shapes:
bool bAutoGrowWidth(false);
bool bAutoGrowHeight(false);
// used with ashapes:
bool bWordWrap(false);
bool bAutoGrowSize(false);
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWritingMode" ) ), true ) )
aAny >>= eWM;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ), true ) )
aAny >>= eVA;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), true ) )
aAny >>= eHA;
if ( bIsCustomShape )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextWordWrap" ) ), false ) )
aAny >>= bWordWrap;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), true ) )
aAny >>= bAutoGrowSize;
}
else if ( bIsTextFrame )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowWidth" ) ), true ) )
aAny >>= bAutoGrowWidth;
// i63936 not setting autogrowheight, because otherwise
// the minframeheight of the text will be ignored
//
// if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextAutoGrowHeight" ) ), true ) )
// aAny >>= bAutoGrowHeight;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ) ) )
aAny >>= nLeft;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ) ) )
aAny >>= nTop;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ) ) )
aAny >>= nRight;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ) ) )
aAny >>= nBottom;
/*
if ( rObj.ImplGetPropertyValue(
::rtl::OUString::createFromAscii("TextWritingMode") ) )
{
::com::sun::star::text::WritingMode eMode;
rObj.GetUsrAny() >>= eMode;
switch (eMode)
{
case ::com::sun::star::text::WritingMode_TB_RL:
//Well if it so happens that we are fliped 180 we can use
//this instead.
if (rObj.GetAngle() == 18000)
eFlow = ESCHER_txflBtoT;
else
eFlow = ESCHER_txflTtoBA;
break;
case ::com::sun::star::text::WritingMode_RL_TB:
eDir = ESCHER_txdirRTL;
break;
}
}
*/
ESCHER_AnchorText eAnchor = ESCHER_AnchorTop;
ESCHER_WrapMode eWrapMode = ESCHER_WrapSquare;
sal_uInt32 nTextAttr = 0x40004; // rotate text with shape
if ( eWM == text::WritingMode_TB_RL )
{ // verical writing
switch ( eHA )
{
case drawing::TextHorizontalAdjust_LEFT :
eAnchor = ESCHER_AnchorBottom;
break;
case drawing::TextHorizontalAdjust_CENTER :
eAnchor = ESCHER_AnchorMiddle;
break;
default :
case drawing::TextHorizontalAdjust_BLOCK :
case drawing::TextHorizontalAdjust_RIGHT :
eAnchor = ESCHER_AnchorTop;
break;
}
if ( eVA == drawing::TextVerticalAdjust_CENTER )
{
switch ( eAnchor )
{
case ESCHER_AnchorMiddle :
eAnchor = ESCHER_AnchorMiddleCentered;
break;
case ESCHER_AnchorBottom :
eAnchor = ESCHER_AnchorBottomCentered;
break;
default :
case ESCHER_AnchorTop :
eAnchor = ESCHER_AnchorTopCentered;
break;
}
}
if ( bIsCustomShape )
{
if ( bWordWrap )
eWrapMode = ESCHER_WrapSquare;
else
eWrapMode = ESCHER_WrapNone;
if ( bAutoGrowSize )
nTextAttr |= 0x20002;
}
else
{
if ( bAutoGrowHeight )
eWrapMode = ESCHER_WrapNone;
if ( bAutoGrowWidth )
nTextAttr |= 0x20002;
}
AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA ); // rotate text within shape by 90
}
else
{ // normal from left to right
switch ( eVA )
{
case drawing::TextVerticalAdjust_CENTER :
eAnchor = ESCHER_AnchorMiddle;
break;
case drawing::TextVerticalAdjust_BOTTOM :
eAnchor = ESCHER_AnchorBottom;
break;
default :
case drawing::TextVerticalAdjust_TOP :
eAnchor = ESCHER_AnchorTop;
break;
}
if ( eHA == drawing::TextHorizontalAdjust_CENTER )
{
switch( eAnchor )
{
case ESCHER_AnchorMiddle :
eAnchor = ESCHER_AnchorMiddleCentered;
break;
case ESCHER_AnchorBottom :
eAnchor = ESCHER_AnchorBottomCentered;
break;
case ESCHER_AnchorTop :
eAnchor = ESCHER_AnchorTopCentered;
break;
default: break;
}
}
if ( bIsCustomShape )
{
if ( bWordWrap )
eWrapMode = ESCHER_WrapSquare;
else
eWrapMode = ESCHER_WrapNone;
if ( bAutoGrowSize )
nTextAttr |= 0x20002;
}
else
{
if ( bAutoGrowWidth )
eWrapMode = ESCHER_WrapNone;
if ( bAutoGrowHeight )
nTextAttr |= 0x20002;
}
}
AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
AddOpt( ESCHER_Prop_dyTextBottom, nBottom * 360 );
AddOpt( ESCHER_Prop_WrapText, eWrapMode );
AddOpt( ESCHER_Prop_AnchorText, eAnchor );
AddOpt( ESCHER_Prop_FitTextToShape, nTextAttr );
if ( nTextId )
AddOpt( ESCHER_Prop_lTxid, nTextId );
}
bool EscherPropertyContainer::GetLineArrow( const bool bLineStart,
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
ESCHER_LineEnd& reLineEnd, sal_Int32& rnArrowLength, sal_Int32& rnArrowWidth )
{
static String sLineStart ( RTL_CONSTASCII_USTRINGPARAM( "LineStart" ) );
static String sLineStartName( RTL_CONSTASCII_USTRINGPARAM( "LineStartName" ) );
static String sLineEnd ( RTL_CONSTASCII_USTRINGPARAM( "LineEnd" ) );
static String sLineEndName ( RTL_CONSTASCII_USTRINGPARAM( "LineEndName" ) );
const String sLine ( bLineStart ? sLineStart : sLineEnd );
const String sLineName ( bLineStart ? sLineStartName : sLineEndName );
bool bIsArrow(false);
::com::sun::star::uno::Any aAny;
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, sLine, false ) )
{
PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aAny ) );
if ( aPolyPoly.Count() && aPolyPoly[ 0 ].GetSize() )
{
bIsArrow = true;
reLineEnd = ESCHER_LineArrowEnd;
rnArrowLength = 1;
rnArrowWidth = 1;
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, sLineName, false ) )
{
String aArrowStartName = *(::rtl::OUString*)aAny.getValue();
rtl::OUString aApiName;
sal_Int16 nWhich = bLineStart ? XATTR_LINESTART : XATTR_LINEEND;
SvxUnogetApiNameForItem( nWhich, aArrowStartName, aApiName );
bool bIsMapped(true);
if ( aApiName.getLength() )
{
/* todo:
calculate the best option for ArrowLenght and ArrowWidth
*/
if ( aApiName.equalsAscii( "Arrow concave" ) )
reLineEnd = ESCHER_LineArrowStealthEnd;
else if ( aApiName.equalsAscii( "Square 45" ) )
reLineEnd = ESCHER_LineArrowDiamondEnd;
else if ( aApiName.equalsAscii( "Small Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aApiName.equalsAscii( "Dimension Lines" ) )
{
rnArrowLength = 0;
rnArrowWidth = 2;
reLineEnd = ESCHER_LineArrowOvalEnd;
}
else if ( aApiName.equalsAscii( "Double Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aApiName.equalsAscii( "Rounded short Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aApiName.equalsAscii( "Symmetric Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aApiName.equalsAscii( "Line Arrow" ) )
reLineEnd = ESCHER_LineArrowOpenEnd;
else if ( aApiName.equalsAscii( "Rounded large Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aApiName.equalsAscii( "Circle" ) )
reLineEnd = ESCHER_LineArrowOvalEnd;
else if ( aApiName.equalsAscii( "Square" ) )
reLineEnd = ESCHER_LineArrowDiamondEnd;
else if ( aApiName.equalsAscii( "Arrow" ) )
reLineEnd = ESCHER_LineArrowEnd;
else
bIsMapped = false;
}
if ( !bIsMapped && aArrowStartName.GetTokenCount( ' ' ) == 2 )
{
bool b(true);
String aArrowName( aArrowStartName.GetToken( 0, ' ' ) );
if ( aArrowName.EqualsAscii( "msArrowEnd" ) )
reLineEnd = ESCHER_LineArrowEnd;
else if ( aArrowName.EqualsAscii( "msArrowOpenEnd" ) )
reLineEnd = ESCHER_LineArrowOpenEnd;
else if ( aArrowName.EqualsAscii( "msArrowStealthEnd" ) )
reLineEnd = ESCHER_LineArrowStealthEnd;
else if ( aArrowName.EqualsAscii( "msArrowDiamondEnd" ) )
reLineEnd = ESCHER_LineArrowDiamondEnd;
else if ( aArrowName.EqualsAscii( "msArrowOvalEnd" ) )
reLineEnd = ESCHER_LineArrowOvalEnd;
else
b = false;
// now we have the arrow, and try to determine the arrow size;
if ( b )
{
String aArrowSize( aArrowStartName.GetToken( 1, ' ' ) );
sal_Int32 nArrowSize = aArrowSize.ToInt32();
rnArrowWidth = ( nArrowSize - 1 ) / 3;
rnArrowLength = nArrowSize - ( rnArrowWidth * 3 ) - 1;
}
}
}
}
}
return bIsArrow;
}
void EscherPropertyContainer::CreateLineProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
bool bEdge )
{
::com::sun::star::uno::Any aAny;
sal_uInt32 nLineFlags = 0x80008;
ESCHER_LineEnd eLineEnd;
sal_Int32 nArrowLength;
sal_Int32 nArrowWidth;
bool bSwapLineEnds(false);
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CircleKind" ) ), true ) )
{
::com::sun::star::drawing::CircleKind eCircleKind;
if ( aAny >>= eCircleKind )
{
if ( eCircleKind == ::com::sun::star::drawing::CircleKind_ARC )
bSwapLineEnds = true;
}
}
if ( GetLineArrow( bSwapLineEnds ? false : true, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
{
AddOpt( ESCHER_Prop_lineStartArrowLength, nArrowLength );
AddOpt( ESCHER_Prop_lineStartArrowWidth, nArrowWidth );
AddOpt( ESCHER_Prop_lineStartArrowhead, eLineEnd );
nLineFlags |= 0x100010;
}
if ( GetLineArrow( bSwapLineEnds ? true : false, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
{
AddOpt( ESCHER_Prop_lineEndArrowLength, nArrowLength );
AddOpt( ESCHER_Prop_lineEndArrowWidth, nArrowWidth );
AddOpt( ESCHER_Prop_lineEndArrowhead, eLineEnd );
nLineFlags |= 0x100010;
}
// support LineCaps
if(EscherPropertyValueHelper::GetPropertyValue(aAny, rXPropSet, String(RTL_CONSTASCII_USTRINGPARAM("LineCap")), false))
{
::com::sun::star::drawing::LineCap aLineCap(com::sun::star::drawing::LineCap_BUTT);
if(aAny >>= aLineCap)
{
switch (aLineCap)
{
default: /* com::sun::star::drawing::LineCap_BUTT */
{
AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapFlat);
break;
}
case com::sun::star::drawing::LineCap_ROUND:
{
AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapRound);
break;
}
case com::sun::star::drawing::LineCap_SQUARE:
{
AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapSquare);
break;
}
}
}
}
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineStyle" ) ), false ) )
{
::com::sun::star::drawing::LineStyle eLS;
if ( aAny >>= eLS )
{
switch ( eLS )
{
case ::com::sun::star::drawing::LineStyle_NONE :
AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // 80000
break;
case ::com::sun::star::drawing::LineStyle_DASH :
{
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineDash" ) ), false ) )
{
ESCHER_LineDashing eDash = ESCHER_LineSolid;
::com::sun::star::drawing::LineDash* pLineDash = (::com::sun::star::drawing::LineDash*)aAny.getValue();
sal_Int32 nDistance = pLineDash->Distance << 1;
switch ( pLineDash->Style )
{
case ::com::sun::star::drawing::DashStyle_ROUND :
case ::com::sun::star::drawing::DashStyle_ROUNDRELATIVE :
AddOpt( ESCHER_Prop_lineEndCapStyle, 0 ); // Style Round setzen
break;
default : break;
}
if ( ((!(pLineDash->Dots )) || (!(pLineDash->Dashes )) ) || ( pLineDash->DotLen == pLineDash->DashLen ) )
{
sal_Int32 nLen = pLineDash->DotLen;
if ( pLineDash->Dashes )
nLen = pLineDash->DashLen;
if ( nLen >= nDistance )
eDash = ESCHER_LineLongDashGEL;
else if ( pLineDash->Dots )
eDash = ESCHER_LineDotSys;
else
eDash = ESCHER_LineDashGEL;
}
else // X Y
{
if ( pLineDash->Dots != pLineDash->Dashes )
{
if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
eDash = ESCHER_LineLongDashDotDotGEL;
else
eDash = ESCHER_LineDashDotDotSys;
}
else // X Y Y
{
if ( ( pLineDash->DashLen > nDistance ) || ( pLineDash->DotLen > nDistance ) )
eDash = ESCHER_LineLongDashDotGEL;
else
eDash = ESCHER_LineDashDotGEL;
}
}
AddOpt( ESCHER_Prop_lineDashing, eDash );
}
}
case ::com::sun::star::drawing::LineStyle_SOLID :
default:
{
AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
}
break;
}
}
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineColor" ) ), false ) )
{
sal_uInt32 nLineColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()) );
AddOpt( ESCHER_Prop_lineColor, nLineColor );
AddOpt( ESCHER_Prop_lineBackColor, nLineColor ^ 0xffffff );
}
}
sal_uInt32 nLineSize = ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineWidth" ) ), false ) )
? *((sal_uInt32*)aAny.getValue())
: 0;
if ( nLineSize > 1 )
AddOpt( ESCHER_Prop_lineWidth, nLineSize * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU
ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter;
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineJoint" ) ), true ) )
{
::com::sun::star::drawing::LineJoint eLJ;
if ( aAny >>= eLJ )
{
switch ( eLJ )
{
case com::sun::star::drawing::LineJoint_NONE :
case com::sun::star::drawing::LineJoint_MIDDLE :
case com::sun::star::drawing::LineJoint_BEVEL :
eLineJoin = ESCHER_LineJoinBevel;
break;
default:
case com::sun::star::drawing::LineJoint_MITER :
eLineJoin = ESCHER_LineJoinMiter;
break;
case com::sun::star::drawing::LineJoint_ROUND :
eLineJoin = ESCHER_LineJoinRound;
break;
}
}
}
AddOpt( ESCHER_Prop_lineJoinStyle, eLineJoin );
if ( EscherPropertyValueHelper::GetPropertyValue(
aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "LineTransparence" ) ), true ) )
{
sal_Int16 nTransparency = 0;
if ( aAny >>= nTransparency )
AddOpt( ESCHER_Prop_lineOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
}
if ( bEdge == false )
{
AddOpt( ESCHER_Prop_fFillOK, 0x1001 );
AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
}
}
static Size lcl_SizeToEmu(Size aPrefSize, MapMode aPrefMapMode)
{
Size aRetSize;
if (aPrefMapMode == MAP_PIXEL)
aRetSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM );
else
aRetSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM );
return aRetSize;
}
void EscherPropertyContainer::ImplCreateGraphicAttributes( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
sal_uInt32 nBlibId, bool bCreateCroppingAttributes )
{
::com::sun::star::uno::Any aAny;
sal_uInt32 nPicFlags = 0;
::com::sun::star::drawing::ColorMode eColorMode( ::com::sun::star::drawing::ColorMode_STANDARD );
sal_Int16 nLuminance = 0;
sal_Int32 nContrast = 0;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicColorMode" ) ) ) )
aAny >>= eColorMode;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustLuminance" ) ) ) )
aAny >>= nLuminance;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustContrast" ) ) ) )
{
sal_Int16 nC = sal_Int16();
aAny >>= nC;
nContrast = nC;
}
if ( eColorMode == ::com::sun::star::drawing::ColorMode_WATERMARK )
{
eColorMode = ::com::sun::star::drawing::ColorMode_STANDARD;
nLuminance += 70;
if ( nLuminance > 100 )
nLuminance = 100;
nContrast -= 70;
if ( nContrast < -100 )
nContrast = -100;
}
if ( eColorMode == ::com::sun::star::drawing::ColorMode_GREYS )
nPicFlags |= 0x40004;
else if ( eColorMode == ::com::sun::star::drawing::ColorMode_MONO )
nPicFlags |= 0x60006;
if ( nContrast )
{
nContrast += 100;
if ( nContrast == 100)
nContrast = 0x10000;
else if ( nContrast < 100 )
{
nContrast *= 0x10000;
nContrast /= 100;
}
else if ( nContrast < 200 )
nContrast = ( 100 * 0x10000 ) / ( 200 - nContrast );
else
nContrast = 0x7fffffff;
AddOpt( ESCHER_Prop_pictureContrast, nContrast );
}
if ( nLuminance )
AddOpt( ESCHER_Prop_pictureBrightness, nLuminance * 327 );
if ( nPicFlags )
AddOpt( ESCHER_Prop_pictureActive, nPicFlags );
if ( bCreateCroppingAttributes && mpGraphicProvider )
{
Size aPrefSize;
MapMode aPrefMapMode;
if ( mpGraphicProvider->GetPrefSize( nBlibId, aPrefSize, aPrefMapMode ) )
{
Size aCropSize(lcl_SizeToEmu(aPrefSize, aPrefMapMode));
if ( aCropSize.Width() && aCropSize.Height() )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicCrop" ) ) ) )
{
::com::sun::star::text::GraphicCrop aGraphCrop;
if ( aAny >>= aGraphCrop )
{
if ( aGraphCrop.Left )
{
sal_uInt32 nLeft = ( aGraphCrop.Left * 65536 ) / aCropSize.Width();
AddOpt( ESCHER_Prop_cropFromLeft, nLeft );
}
if ( aGraphCrop.Top )
{
sal_uInt32 nTop = ( aGraphCrop.Top * 65536 ) / aCropSize.Height();
AddOpt( ESCHER_Prop_cropFromTop, nTop );
}
if ( aGraphCrop.Right )
{
sal_uInt32 nRight = ( aGraphCrop.Right * 65536 ) / aCropSize.Width();
AddOpt( ESCHER_Prop_cropFromRight, nRight );
}
if ( aGraphCrop.Bottom )
{
sal_uInt32 nBottom = ( aGraphCrop.Bottom * 65536 ) / aCropSize.Height();
AddOpt( ESCHER_Prop_cropFromBottom, nBottom );
}
}
}
}
}
}
}
bool EscherPropertyContainer::CreateShapeProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
{
uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
if ( aXPropSet.is() )
{
bool bVal(false);
::com::sun::star::uno::Any aAny;
sal_uInt32 nShapeAttr = 0;
EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) ), true );
if ( aAny >>= bVal )
{
if ( !bVal )
nShapeAttr |= 0x20002; // set fHidden = true
}
EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) ), true );
if ( aAny >>= bVal )
{
if ( !bVal )
nShapeAttr |= 0x10000; // set fPrint = false;
}
if ( nShapeAttr )
AddOpt( ESCHER_Prop_fPrint, nShapeAttr );
}
return true;
}
bool EscherPropertyContainer::CreateOLEGraphicProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
{
bool bRetValue(false);
if ( rXShape.is() )
{
// SJ: leaving unoapi, because currently there is
SdrOle2Obj* pSdrOLE2(dynamic_cast< SdrOle2Obj* >(GetSdrObjectFromXShape(rXShape)));
if(pSdrOLE2) // no access to the native graphic object
{
Graphic* pGraphic = pSdrOLE2->GetGraphic();
if ( pGraphic )
{
GraphicObject aGraphicObject( *pGraphic );
bRetValue = CreateGraphicProperties( rXShape,aGraphicObject );
// End
}
}
}
return bRetValue;
}
bool EscherPropertyContainer::CreateGraphicProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ,const GraphicObject& rGraphicObj )
{
bool bRetValue(false);
ByteString aUniqueId( rGraphicObj.GetUniqueID() );
if ( aUniqueId.Len() )
{
AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
if ( mpGraphicProvider && mpPicOutStrm && !maObjectRange.isEmpty() && aXPropSet.is() )
{
::com::sun::star::uno::Any aAny;
::com::sun::star::awt::Rectangle* pVisArea = NULL;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "VisibleArea" ) ) ) )
{
pVisArea = new ::com::sun::star::awt::Rectangle;
aAny >>= (*pVisArea);
}
const basegfx::B2DRange aRange(0.0, 0.0, maObjectRange.getWidth(), maObjectRange.getHeight());
const sal_uInt32 nBlibId(mpGraphicProvider->GetBlibID(*mpPicOutStrm, aUniqueId, aRange, pVisArea, NULL));
if ( nBlibId )
{
AddOpt( ESCHER_Prop_pib, nBlibId, true );
ImplCreateGraphicAttributes( aXPropSet, nBlibId, false );
bRetValue = true;
}
delete pVisArea;
}
}
return bRetValue;
}
bool EscherPropertyContainer::CreateMediaGraphicProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
{
bool bRetValue(false);
if ( rXShape.is() )
{
// SJ: leaving unoapi, because currently there is no access to the native graphic object
SdrMediaObj* pSdrMediaObj = dynamic_cast< SdrMediaObj* >(GetSdrObjectFromXShape(rXShape));
if(pSdrMediaObj)
{
GraphicObject aGraphicObject(pSdrMediaObj->getGraphic());
bRetValue = CreateGraphicProperties(rXShape, aGraphicObject);
}
}
return bRetValue;
}
bool EscherPropertyContainer::ImplCreateEmbeddedBmp( const ByteString& rUniqueId )
{
if( rUniqueId.Len() > 0 )
{
EscherGraphicProvider aProvider;
SvMemoryStream aMemStrm;
const basegfx::B2DRange aRange(0.0, 0.0, 1.0, 1.0);
if(aProvider.GetBlibID(aMemStrm, rUniqueId, aRange))
{
// grab BLIP from stream and insert directly as complex property
// ownership of stream memory goes to complex property
aMemStrm.ObjectOwnsMemory( false );
sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
AddOpt( ESCHER_Prop_fillBlip, true, nSize, pBuf, nSize );
return true;
}
}
return false;
}
bool EscherPropertyContainer::CreateEmbeddedBitmapProperties(
const ::rtl::OUString& rBitmapUrl, ::com::sun::star::drawing::BitmapMode eBitmapMode )
{
bool bRetValue(false);
String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
String aBmpUrl( rBitmapUrl );
xub_StrLen nIndex = aBmpUrl.Search( aVndUrl, 0 );
if( nIndex != STRING_NOTFOUND )
{
// note: += ist not defined for xub_StrLen -> conversion to int and back to xub_StrLen
nIndex = nIndex + aVndUrl.Len();
if( aBmpUrl.Len() > nIndex )
{
ByteString aUniqueId( aBmpUrl, nIndex, aBmpUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
if( bRetValue )
{
// bitmap mode property
bool bRepeat = eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT;
AddOpt( ESCHER_Prop_fillType, bRepeat ? ESCHER_FillTexture : ESCHER_FillPicture );
}
}
}
return bRetValue;
}
namespace {
GraphicObject lclDrawHatch(
const ::com::sun::star::drawing::Hatch& rHatch,
const Color& rBackColor,
bool bFillBackground,
const basegfx::B2DRange& rRange)
{
if(!rRange.isEmpty())
{
// #121183# For hatch, do no longer create a bitmap with the fixed size of 28x28 pixels. Also
// do not create a bitmap in page size, that would explode file sizes (and have no good quality).
// Better use a MetaFile graphic in page size; thus we have good quality due to vector format and
// no bit file sizes.
VirtualDevice aOut;
GDIMetaFile aMtf;
const Rectangle aRect(
basegfx::fround(rRange.getMinX()), basegfx::fround(rRange.getMinY()),
basegfx::fround(rRange.getMaxX()), basegfx::fround(rRange.getMaxY()));
aOut.SetOutputSizePixel(Size(2, 2));
aOut.EnableOutput(false);
aOut.SetMapMode(MapMode(MAP_100TH_MM));
aMtf.Clear();
aMtf.Record(&aOut);
aOut.SetLineColor();
if(bFillBackground)
{
aOut.SetFillColor(rBackColor);
aOut.DrawRect(aRect);
}
else
{
aOut.SetFillColor();
}
aOut.DrawHatch(
PolyPolygon(aRect),
Hatch((HatchStyle)rHatch.Style,
Color(rHatch.Color),
rHatch.Distance,
(sal_uInt16)rHatch.Angle));
aMtf.Stop();
aMtf.WindStart();
aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM));
aMtf.SetPrefSize(aRect.GetSize());
return GraphicObject(Graphic(aMtf));
}
return GraphicObject();
}
} // namespace
bool EscherPropertyContainer::CreateEmbeddedHatchProperties( const ::com::sun::star::drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
{
const basegfx::B2DRange aRange(maObjectRange.isEmpty() ? basegfx::B2DRange(0.0, 0.0, 28000.0, 21000.0) : maObjectRange);
GraphicObject aGraphicObject = lclDrawHatch(rHatch, rBackColor, bFillBackground, aRange);
ByteString aUniqueId = aGraphicObject.GetUniqueID();
bool bRetValue = ImplCreateEmbeddedBmp( aUniqueId );
if ( bRetValue )
AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
return bRetValue;
}
bool EscherPropertyContainer::CreateGraphicProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
const String& rSource, const bool bCreateFillBitmap, const bool bCreateCroppingAttributes,
const bool bFillBitmapModeAllowed )
{
bool bRetValue(false);
bool bCreateFillStyles(false);
bool bMirrored(false);
bool bRotate(true);
sal_uInt16 nAngle = 0;
GraphicAttr* pGraphicAttr = NULL;
GraphicObject aGraphicObject;
String aGraphicUrl;
ByteString aUniqueId;
bool bIsGraphicMtf(false);
// #121074#
sal_Int16 nTransparency(0);
sal_Int16 nRed(0);
sal_Int16 nGreen(0);
sal_Int16 nBlue(0);
double fGamma(1.0);
::com::sun::star::drawing::BitmapMode eBitmapMode( ::com::sun::star::drawing::BitmapMode_NO_REPEAT );
::com::sun::star::uno::Any aAny;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, rSource ) )
{
if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ) )
{
::com::sun::star::uno::Sequence<sal_uInt8> aSeq = *(::com::sun::star::uno::Sequence<sal_uInt8>*)aAny.getValue();
const sal_uInt8* pAry = aSeq.getArray();
sal_uInt32 nAryLen = aSeq.getLength();
// the metafile is already rotated
bRotate = false;
if ( pAry && nAryLen )
{
Graphic aGraphic;
SvMemoryStream aTemp( (void*)pAry, nAryLen, STREAM_READ );
sal_uInt32 nErrCode = GraphicConverter::Import( aTemp, aGraphic, CVT_WMF );
if ( nErrCode == ERRCODE_NONE )
{
aGraphicObject = aGraphic;
aUniqueId = aGraphicObject.GetUniqueID();
bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
}
}
}
else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ) )
{
::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap >xBitmap;
if ( ::cppu::extractInterface( xBitmap, aAny ) )
{
::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp;
if ( aAny >>= xBmp )
{
BitmapEx aBitmapEx( VCLUnoHelper::GetBitmap( xBmp ) );
Graphic aGraphic( aBitmapEx );
aGraphicObject = aGraphic;
aUniqueId = aGraphicObject.GetUniqueID();
bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
}
}
}
else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapURL" ) ) )
{
aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
}
else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) )
{
aGraphicUrl = *(::rtl::OUString*)aAny.getValue();
bCreateFillStyles = true;
}
else if ( rSource == String( RTL_CONSTASCII_USTRINGPARAM( "FillHatch" ) ) )
{
::com::sun::star::drawing::Hatch aHatch;
if ( aAny >>= aHatch )
{
Color aBackColor;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillColor" ) ), false ) )
{
aBackColor = ImplGetColor( *((sal_uInt32*)aAny.getValue()), false );
}
bool bFillBackground = false;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBackground" ) ), true ) )
{
aAny >>= bFillBackground;
}
const basegfx::B2DRange aRange(
basegfx::B2DTuple(0.0, 0.0),
maObjectRange.isEmpty() ?
basegfx::B2DTuple(28000.0, 21000.0) :
maObjectRange.getRange());
aGraphicObject = lclDrawHatch(aHatch, aBackColor, bFillBackground, aRange);
aUniqueId = aGraphicObject.GetUniqueID();
eBitmapMode = ::com::sun::star::drawing::BitmapMode_REPEAT;
bIsGraphicMtf = aGraphicObject.GetType() == GRAPHIC_GDIMETAFILE;
}
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "IsMirrored" ) ), true ) )
aAny >>= bMirrored;
// #121074# transparency of graphic is not supported in MS formats, get and apply it
// in the GetTransformedGraphic call in GetBlibID
if(EscherPropertyValueHelper::GetPropertyValue(aAny, rXPropSet, String(RTL_CONSTASCII_USTRINGPARAM("Transparency"))))
{
aAny >>= nTransparency;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustRed" ) ) ) )
{
aAny >>= nRed;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustGreen" ) ) ) )
{
aAny >>= nGreen;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "AdjustBlue" ) ) ) )
{
aAny >>= nBlue;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Gamma" ) ) ) )
{
aAny >>= fGamma;
}
if ( bCreateFillBitmap && bFillBitmapModeAllowed )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapMode" ) ), true ) )
aAny >>= eBitmapMode;
}
else
{
nAngle = bRotate && EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), true )
? (sal_uInt16)( ( *((sal_Int32*)aAny.getValue() ) ) + 5 ) / 10
: 0;
}
if ( aGraphicUrl.Len() )
{
String aVndUrl( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
xub_StrLen nIndex = aGraphicUrl.Search( aVndUrl, 0 );
if ( nIndex != STRING_NOTFOUND )
{
nIndex = nIndex + aVndUrl.Len();
if ( aGraphicUrl.Len() > nIndex )
aUniqueId = ByteString( aGraphicUrl, nIndex, aGraphicUrl.Len() - nIndex, RTL_TEXTENCODING_UTF8 );
}
else
{
// externally, linked graphic? convert to embedded
// one, if transformations are needed. this is because
// everything < msoxp cannot even handle rotated
// bitmaps.
// And check whether the graphic link target is
// actually supported by mso.
INetURLObject aTmp( aGraphicUrl );
GraphicDescriptor aDescriptor(aTmp);
aDescriptor.Detect();
const sal_uInt16 nFormat = aDescriptor.GetFileFormat();
// can MSO handle it?
if ( bMirrored || nAngle || nTransparency || nRed || nGreen || nBlue || (1.0 != fGamma) ||
(nFormat != GFF_BMP &&
nFormat != GFF_GIF &&
nFormat != GFF_JPG &&
nFormat != GFF_PNG &&
nFormat != GFF_TIF &&
nFormat != GFF_PCT &&
nFormat != GFF_WMF &&
nFormat != GFF_EMF) )
{
SvStream* pIn = ::utl::UcbStreamHelper::CreateStream(
aTmp.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
if ( pIn )
{
Graphic aGraphic;
sal_uInt32 nErrCode = GraphicConverter::Import( *pIn, aGraphic );
if ( nErrCode == ERRCODE_NONE )
{
// no.
aGraphicObject = aGraphic;
aUniqueId = aGraphicObject.GetUniqueID();
}
// else: simply keep the graphic link
delete pIn;
}
}
if ( !aUniqueId.Len() )
{
if ( mpGraphicProvider )
{
const rtl::OUString& rBaseURI( mpGraphicProvider->GetBaseURI() );
INetURLObject aBaseURI( rBaseURI );
if( aBaseURI.GetProtocol() == aTmp.GetProtocol() )
{
rtl::OUString aRelUrl( INetURLObject::GetRelURL( rBaseURI, aGraphicUrl,
INetURLObject::WAS_ENCODED, INetURLObject::DECODE_TO_IURI, RTL_TEXTENCODING_UTF8, INetURLObject::FSYS_DETECT ) );
if ( aRelUrl.getLength() )
aGraphicUrl = aRelUrl;
}
}
}
}
}
if ( aGraphicUrl.Len() || aUniqueId.Len() )
{
if(bMirrored || nTransparency || nRed || nGreen || nBlue || (1.0 != fGamma))
{
pGraphicAttr = new GraphicAttr;
if(bMirrored)
{
pGraphicAttr->SetMirrorFlags(BMP_MIRROR_HORZ);
}
// #121074#
if(nTransparency)
{
pGraphicAttr->SetTransparency((nTransparency * 255) / 100);
}
if(nRed)
{
pGraphicAttr->SetChannelR(nRed);
}
if(nGreen)
{
pGraphicAttr->SetChannelG(nGreen);
}
if(nBlue)
{
pGraphicAttr->SetChannelB(nBlue);
}
if(1.0 != fGamma)
{
pGraphicAttr->SetGamma(fGamma);
}
}
if(nAngle && bIsGraphicMtf)
{
AddOpt( ESCHER_Prop_Rotation, ( ( ((sal_Int32)nAngle << 16 ) / 10 ) + 0x8000 ) &~ 0xffff );
}
if ( eBitmapMode == ::com::sun::star::drawing::BitmapMode_REPEAT )
{
sal_Int32 nSizeX = 0,nSizeY = 0,nOffsetX = 0,nOffsetY = 0,nPosOffsetX = 0,nPosOffsetY = 0;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapSizeX" ) ), true ) )
{
aAny >>= nSizeX;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapSizeY" ) ), true ) )
{
aAny >>= nSizeY;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapOffsetX" ) ), true ) )
{
aAny >>= nOffsetX;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapOffsetY" ) ), true ) )
{
aAny >>= nOffsetY;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapPositionOffsetX" ) ), true ) )
{
aAny >>= nPosOffsetX;
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillBitmapPositionOffsetY" ) ), true ) )
{
aAny >>= nPosOffsetY;
}
if(nSizeX == -100 && nSizeY == -100 && nOffsetX == 0 && nOffsetY == 0 && nPosOffsetX == 0 && nPosOffsetY == 0)
AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
else
AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
}
else
AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
if(aUniqueId.Len() && !maObjectRange.isEmpty())
{
// write out embedded graphic
if(mpGraphicProvider && mpPicOutStrm)
{
const basegfx::B2DRange aRange(0.0, 0.0, maObjectRange.getWidth(), maObjectRange.getHeight());
const sal_uInt32 nBlibId(mpGraphicProvider->GetBlibID(*mpPicOutStrm, aUniqueId, aRange, NULL, pGraphicAttr));
if ( nBlibId )
{
if(bCreateFillBitmap)
{
AddOpt(ESCHER_Prop_fillBlip, nBlibId, true);
}
else
{
AddOpt( ESCHER_Prop_pib, nBlibId, true );
ImplCreateGraphicAttributes( rXPropSet, nBlibId, bCreateCroppingAttributes );
}
bRetValue = true;
}
}
else
{
EscherGraphicProvider aProvider;
SvMemoryStream aMemStrm;
const basegfx::B2DRange aRange(0.0, 0.0, maObjectRange.getWidth(), maObjectRange.getHeight());
if(aProvider.GetBlibID(aMemStrm, aUniqueId, aRange, NULL, pGraphicAttr))
{
// grab BLIP from stream and insert directly as complex property
// ownership of stream memory goes to complex property
aMemStrm.ObjectOwnsMemory( false );
sal_uInt8* pBuf = (sal_uInt8*) aMemStrm.GetData();
sal_uInt32 nSize = aMemStrm.Seek( STREAM_SEEK_TO_END );
AddOpt( ESCHER_Prop_fillBlip, true, nSize, pBuf, nSize );
bRetValue = true;
}
}
}
// write out link to graphic
else
{
OSL_ASSERT(aGraphicUrl.Len());
AddOpt( ESCHER_Prop_pibName, aGraphicUrl );
sal_uInt32 nPibFlags=0;
GetOpt( ESCHER_Prop_pibFlags, nPibFlags );
AddOpt( ESCHER_Prop_pibFlags,
ESCHER_BlipFlagLinkToFile|ESCHER_BlipFlagFile|ESCHER_BlipFlagDoNotSave | nPibFlags );
}
}
}
delete pGraphicAttr;
if ( bCreateFillStyles )
CreateFillProperties( rXPropSet, true );
return bRetValue;
}
PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape )
{
PolyPolygon aRetPolyPoly;
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
::com::sun::star::uno::Any aAny( rXShape->queryInterface(
::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
String sPolygon ( RTL_CONSTASCII_USTRINGPARAM( "Polygon" ) );
if ( aAny >>= aXPropSet )
{
bool bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygonBezier, true );
if ( !bHasProperty )
bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolyPolygon, true );
if ( !bHasProperty )
bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sPolygon, true );
if ( bHasProperty )
aRetPolyPoly = GetPolyPolygon( aAny );
}
return aRetPolyPoly;
}
PolyPolygon EscherPropertyContainer::GetPolyPolygon( const ::com::sun::star::uno::Any& rAny )
{
bool bNoError(true);
Polygon aPolygon;
PolyPolygon aPolyPolygon;
if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PolyPolygonBezierCoords* ) 0 ) )
{
::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon
= (::com::sun::star::drawing::PolyPolygonBezierCoords*)rAny.getValue();
sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->Coordinates.getLength();
// Zeiger auf innere sequences holen
::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray();
::com::sun::star::drawing::FlagSequence* pOuterFlags = pSourcePolyPolygon->Flags.getArray();
bNoError = pOuterSequence && pOuterFlags;
if ( bNoError )
{
sal_uInt16 a, b, nInnerSequenceCount;
::com::sun::star::awt::Point* pArray;
// dies wird ein Polygon set
for ( a = 0; a < nOuterSequenceCount; a++ )
{
::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++;
bNoError = pInnerSequence && pInnerFlags;
if ( bNoError )
{
// Zeiger auf Arrays holen
pArray = pInnerSequence->getArray();
::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
if ( pArray && pFlags )
{
nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
aPolygon = Polygon( nInnerSequenceCount );
for( b = 0; b < nInnerSequenceCount; b++)
{
PolyFlags ePolyFlags( *( (PolyFlags*)pFlags++ ) );
::com::sun::star::awt::Point aPoint( (::com::sun::star::awt::Point)*(pArray++) );
aPolygon[ b ] = Point( aPoint.X, aPoint.Y );
aPolygon.SetFlags( b, ePolyFlags );
if ( ePolyFlags == POLY_CONTROL )
continue;
}
aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
}
}
}
}
}
else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequenceSequence* ) 0 ) )
{
::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon
= (::com::sun::star::drawing::PointSequenceSequence*)rAny.getValue();
sal_uInt16 nOuterSequenceCount = (sal_uInt16)pSourcePolyPolygon->getLength();
// Zeiger auf innere sequences holen
::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
bNoError = pOuterSequence != NULL;
if ( bNoError )
{
sal_uInt16 a, b, nInnerSequenceCount;
// dies wird ein Polygon set
for( a = 0; a < nOuterSequenceCount; a++ )
{
::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
bNoError = pInnerSequence != NULL;
if ( bNoError )
{
// Zeiger auf Arrays holen
::com::sun::star::awt::Point* pArray =
pInnerSequence->getArray();
if ( pArray != NULL )
{
nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
aPolygon = Polygon( nInnerSequenceCount );
for( b = 0; b < nInnerSequenceCount; b++)
{
aPolygon[ b ] = Point( pArray->X, pArray->Y );
pArray++;
}
aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
}
}
}
}
}
else if ( rAny.getValueType() == ::getCppuType( ( const ::com::sun::star::drawing::PointSequence* ) 0 ) )
{
::com::sun::star::drawing::PointSequence* pInnerSequence =
(::com::sun::star::drawing::PointSequence*)rAny.getValue();
bNoError = pInnerSequence != NULL;
if ( bNoError )
{
sal_uInt16 a, nInnerSequenceCount;
// Zeiger auf Arrays holen
::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
if ( pArray != NULL )
{
nInnerSequenceCount = (sal_uInt16)pInnerSequence->getLength();
aPolygon = Polygon( nInnerSequenceCount );
for( a = 0; a < nInnerSequenceCount; a++)
{
aPolygon[ a ] = Point( pArray->X, pArray->Y );
pArray++;
}
aPolyPolygon.Insert( aPolygon, POLYPOLY_APPEND );
}
}
}
return aPolyPolygon;
}
bool EscherPropertyContainer::CreatePolygonProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
sal_uInt32 nFlags,
bool bBezier,
::com::sun::star::awt::Rectangle& rGeoRect,
Polygon* pPolygon )
{
static String sPolyPolygonBezier( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) );
static String sPolyPolygon ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) );
bool bRetValue(true);
bool bLine(nFlags & ESCHER_CREATEPOLYGON_LINE);
PolyPolygon aPolyPolygon;
if ( pPolygon )
aPolyPolygon.Insert( *pPolygon, POLYPOLY_APPEND );
else
{
::com::sun::star::uno::Any aAny;
bRetValue = EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
( bBezier ) ? sPolyPolygonBezier : sPolyPolygon, true );
if ( bRetValue )
{
aPolyPolygon = GetPolyPolygon( aAny );
bRetValue = aPolyPolygon.Count() != 0;
}
}
if ( bRetValue )
{
if ( bLine )
{
if ( ( aPolyPolygon.Count() == 1 ) && ( aPolyPolygon[ 0 ].GetSize() == 2 ) )
{
const Polygon& rPoly = aPolyPolygon[ 0 ];
rGeoRect = ::com::sun::star::awt::Rectangle(
rPoly[ 0 ].X(),
rPoly[ 0 ].Y(),
rPoly[ 1 ].X() - rPoly[ 0 ].X(),
rPoly[ 1 ].Y() - rPoly[ 0 ].Y() );
}
else
bRetValue = false;
}
else
{
Polygon aPolygon;
sal_uInt16 i, j, k, nPoints, nBezPoints, nPolyCount = aPolyPolygon.Count();
const Rectangle aRect( aPolyPolygon.GetBoundRect() );
rGeoRect = ::com::sun::star::awt::Rectangle( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight() );
for ( nBezPoints = nPoints = i = 0; i < nPolyCount; i++ )
{
k = aPolyPolygon[ i ].GetSize();
nPoints = nPoints + k;
for ( j = 0; j < k; j++ )
{
if ( aPolyPolygon[ i ].GetFlags( j ) != POLY_CONTROL )
nBezPoints++;
}
}
sal_uInt32 nVerticesBufSize = ( nPoints << 2 ) + 6;
sal_uInt8* pVerticesBuf = new sal_uInt8[ nVerticesBufSize ];
sal_uInt32 nSegmentBufSize = ( ( nBezPoints << 2 ) + 8 );
if ( nPolyCount > 1 )
nSegmentBufSize += ( nPolyCount << 1 );
sal_uInt8* pSegmentBuf = new sal_uInt8[ nSegmentBufSize ];
sal_uInt8* pPtr = pVerticesBuf;
*pPtr++ = (sal_uInt8)( nPoints ); // Little endian
*pPtr++ = (sal_uInt8)( nPoints >> 8 );
*pPtr++ = (sal_uInt8)( nPoints );
*pPtr++ = (sal_uInt8)( nPoints >> 8 );
*pPtr++ = (sal_uInt8)0xf0;
*pPtr++ = (sal_uInt8)0xff;
for ( j = 0; j < nPolyCount; j++ )
{
aPolygon = aPolyPolygon[ j ];
nPoints = aPolygon.GetSize();
for ( i = 0; i < nPoints; i++ ) // Punkte aus Polygon in Buffer schreiben
{
Point aPoint = aPolygon[ i ];
aPoint.X() -= rGeoRect.X;
aPoint.Y() -= rGeoRect.Y;
*pPtr++ = (sal_uInt8)( aPoint.X() );
*pPtr++ = (sal_uInt8)( aPoint.X() >> 8 );
*pPtr++ = (sal_uInt8)( aPoint.Y() );
*pPtr++ = (sal_uInt8)( aPoint.Y() >> 8 );
}
}
pPtr = pSegmentBuf;
*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 1 );
*pPtr++ = (sal_uInt8)( ( nSegmentBufSize - 6 ) >> 9 );
*pPtr++ = (sal_uInt8)2;
*pPtr++ = (sal_uInt8)0;
for ( j = 0; j < nPolyCount; j++ )
{
*pPtr++ = 0x0; // Polygon start
*pPtr++ = 0x40;
aPolygon = aPolyPolygon[ j ];
nPoints = aPolygon.GetSize();
for ( i = 0; i < nPoints; i++ ) // Polyflags in Buffer schreiben
{
*pPtr++ = 0;
if ( bBezier )
*pPtr++ = 0xb3;
else
*pPtr++ = 0xac;
if ( ( i + 1 ) != nPoints )
{
*pPtr++ = 1;
if ( aPolygon.GetFlags( i + 1 ) == POLY_CONTROL )
{
*pPtr++ = 0x20;
i += 2;
}
else
*pPtr++ = 0;
}
}
if ( nPolyCount > 1 )
{
*pPtr++ = 1; // end of polygon
*pPtr++ = 0x60;
}
}
*pPtr++ = 0;
*pPtr++ = 0x80;
AddOpt( ESCHER_Prop_geoRight, rGeoRect.Width );
AddOpt( ESCHER_Prop_geoBottom, rGeoRect.Height );
AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
AddOpt( ESCHER_Prop_pVertices, true, nVerticesBufSize - 6, (sal_uInt8*)pVerticesBuf, nVerticesBufSize );
AddOpt( ESCHER_Prop_pSegmentInfo, true, nSegmentBufSize, (sal_uInt8*)pSegmentBuf, nSegmentBufSize );
}
}
return bRetValue;
}
/*
in MS,the connector including 9 types :
"straightConnector1",
"bentConnector2","bentConnector3","bentConnector4","bentConnector5"
"curvedConnector2","curvedConnector3","curvedConnector4","curvedConnector5"
in AOO,including 4 types:"standard","lines","line","curve"
when save as MS file, the connector must be convert to corresponding type.
"line" and "lines" <-> "straightConnector1"
"standard" <-> "bentConnector2-5"
"curve" <-> "curvedConnector2-5"
*/
sal_Int32 lcl_GetAdjustValueCount( const XPolygon& rPoly )
{
int nRet = 0;
switch ( rPoly.GetSize() )
{
case 2 :
case 3:
nRet = 0;
break;
case 4:
nRet = 1;
break;
case 5:
nRet = 2;
break;
default:
if ( rPoly.GetSize()>=6 )
nRet = 3;
break;
}
return nRet;
}
/*
Adjust value decide the position which connector should turn a corner
*/
sal_Int32 lcl_GetConnectorAdjustValue ( const XPolygon& rPoly, sal_uInt16 nIndex )
{
sal_uInt16 k = rPoly.GetSize();
OSL_ASSERT ( k >= ( 3 + nIndex ) );
Point aPt;
Point aStart = rPoly[0];
Point aEnd = rPoly[k-1];
if ( aEnd.Y() == aStart.Y() )
aEnd.Y() = aStart.Y() +4;
if ( aEnd.X() == aStart.X() )
aEnd.X() = aStart.X() +4;
bool bVertical((0 == rPoly[1].X() - aStart.X()));
//vertical and horizon alternate
if ( nIndex%2 == 1 ) bVertical = !bVertical;
aPt = rPoly[ nIndex + 1];
sal_Int32 nAdjustValue;
if ( bVertical )
nAdjustValue = ( aPt.Y()-aStart.Y())* 21600 /(aEnd.Y()-aStart.Y());
else
nAdjustValue = ( aPt.X()-aStart.X() )* 21600 /(aEnd.X()-aStart.X());
return nAdjustValue;
}
void lcl_Rotate(sal_Int32 nAngle, Point center, Point& pt)
{
while ( nAngle<0)
nAngle +=36000;
while (nAngle>=36000)
nAngle -=36000;
int cs, sn;
switch (nAngle)
{
case 0:
cs =1;
sn =0;
break;
case 9000:
cs =0;
sn =1;
break;
case 18000:
cs = -1;
sn = 0;
break;
case 27000:
cs = 0;
sn = -1;
break;
default:
return;
break;
}
sal_Int32 x0 =pt.X()-center.X();
sal_Int32 y0 =pt.Y()-center.Y();
pt.X()=center.X()+ x0*cs-y0*sn;
pt.Y()=center.Y()+ y0*cs+x0*sn;
}
/*
FlipV defines that the shape will be flipped vertically about the center of its bounding box.
Generally, draw the connector from top to bottom, from left to right when meet the adjust value,
but when (X1>X2 or Y1>Y2),the draw director must be reverse, FlipV or FlipH should be set to true.
*/
bool lcl_GetAngle(Polygon &rPoly,sal_uInt16& rShapeFlags,sal_Int32& nAngle )
{
Point aStart = rPoly[0];
Point aEnd = rPoly[rPoly.GetSize()-1];
nAngle = ( rPoly[1].X() == aStart.X() ) ? 9000: 0 ;
Point p1(aStart.X(),aStart.Y());
Point p2(aEnd.X(),aEnd.Y());
if ( nAngle )
{
Point center((aEnd.X()+aStart.X())>>1,(aEnd.Y()+aStart.Y())>>1);
lcl_Rotate(-nAngle, center,p1);
lcl_Rotate(-nAngle, center,p2);
}
if ( p1.X() > p2.X() )
{
if ( nAngle )
rShapeFlags |= SHAPEFLAG_FLIPV;
else
rShapeFlags |= SHAPEFLAG_FLIPH;
}
if ( p1.Y() > p2.Y() )
{
if ( nAngle )
rShapeFlags |= SHAPEFLAG_FLIPH;
else
rShapeFlags |= SHAPEFLAG_FLIPV;
}
if ( (rShapeFlags&SHAPEFLAG_FLIPH) && (rShapeFlags&SHAPEFLAG_FLIPV) )
{
rShapeFlags &= ~( SHAPEFLAG_FLIPH | SHAPEFLAG_FLIPV );
nAngle +=18000;
}
if ( nAngle )
{
// Set angle properties
nAngle *= 655;
nAngle += 0x8000;
nAngle &=~0xffff; // nAngle auf volle Gradzahl runden
return true;
}
return false;
}
bool EscherPropertyContainer::CreateConnectorProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape,
EscherSolverContainer& rSolverContainer, ::com::sun::star::awt::Rectangle& rGeoRect,
sal_uInt16& rShapeType, sal_uInt16& rShapeFlags )
{
static String sEdgeKind ( RTL_CONSTASCII_USTRINGPARAM( "EdgeKind" ) );
static String sEdgeStartPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartPoint" ) );
static String sEdgeEndPoint ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndPoint" ) );
static String sEdgeStartConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeStartConnection" ) );
static String sEdgeEndConnection ( RTL_CONSTASCII_USTRINGPARAM( "EdgeEndConnection" ) );
static String sEdgePath ( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier") );
bool bRetValue(false);
rShapeType = rShapeFlags = 0;
if ( rXShape.is() )
{
::com::sun::star::awt::Point aStartPoint, aEndPoint;
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > aXPropSet;
::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aShapeA, aShapeB;
::com::sun::star::uno::Any aAny( rXShape->queryInterface( ::getCppuType( (const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >*) 0 ) ));
if ( aAny >>= aXPropSet )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeKind, true ) )
{
::com::sun::star::drawing::ConnectorType eCt;
aAny >>= eCt;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartPoint ) )
{
aStartPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndPoint ) )
{
aEndPoint = *(::com::sun::star::awt::Point*)aAny.getValue();
rShapeFlags = SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT | SHAPEFLAG_CONNECTOR;
rGeoRect = ::com::sun::star::awt::Rectangle( aStartPoint.X, aStartPoint.Y,
( aEndPoint.X - aStartPoint.X ) + 1, ( aEndPoint.Y - aStartPoint.Y ) + 1 );
//set standard's FLIP in below code
if ( eCt != ::com::sun::star::drawing::ConnectorType_STANDARD)
{
if ( rGeoRect.Height < 0 ) // justify
{
rShapeFlags |= SHAPEFLAG_FLIPV;
rGeoRect.Y = aEndPoint.Y;
rGeoRect.Height = -rGeoRect.Height;
}
if ( rGeoRect.Width < 0 )
{
rShapeFlags |= SHAPEFLAG_FLIPH;
rGeoRect.X = aEndPoint.X;
rGeoRect.Width = -rGeoRect.Width;
}
}
sal_uInt32 nAdjustValue1, nAdjustValue2, nAdjustValue3;
nAdjustValue1 = nAdjustValue2 = nAdjustValue3 = 0x2a30;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeStartConnection ) )
aAny >>= aShapeA;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgeEndConnection ) )
aAny >>= aShapeB;
/*
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine1Delta" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine2Delta" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeLine3Delta" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1HorzDist" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode1VertDist" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2HorzDist" ) ) ) )
{
}
if ( ImplGetPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "EdgeNode2VertDist" ) ) ) )
{
}
*/
rSolverContainer.AddConnector( rXShape, aStartPoint, aShapeA, aEndPoint, aShapeB );
switch ( eCt )
{
case ::com::sun::star::drawing::ConnectorType_CURVE :
{
rShapeType = ESCHER_ShpInst_CurvedConnector3;
AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleCurved );
AddOpt( ESCHER_Prop_adjustValue, nAdjustValue1 );
AddOpt( ESCHER_Prop_adjust2Value, -(sal_Int32)nAdjustValue2 );
}
break;
case ::com::sun::star::drawing::ConnectorType_STANDARD :// Connector 2->5
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, sEdgePath ) )
{
PolyPolygon aPolyPolygon = GetPolyPolygon( aAny );
Polygon aPoly;
if ( aPolyPolygon.Count() > 0 )
{
AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
aPoly = aPolyPolygon[ 0 ];
sal_Int32 nAdjCount = lcl_GetAdjustValueCount( aPoly );
rShapeType = ( sal_uInt16 )( ESCHER_ShpInst_BentConnector2 + nAdjCount);
for ( sal_Int32 i = 0 ; i < nAdjCount; ++ i)
AddOpt( (sal_uInt16) ( ESCHER_Prop_adjustValue+i) , lcl_GetConnectorAdjustValue( aPoly, i ) );
bRetValue = true;
}
sal_Int32 nAngle=0;
if (lcl_GetAngle(aPoly,rShapeFlags,nAngle ))
{
AddOpt( ESCHER_Prop_Rotation, nAngle );
}
}
else
{
rShapeType = ESCHER_ShpInst_BentConnector3;
AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
}
}
break;
default:
case ::com::sun::star::drawing::ConnectorType_LINE :
case ::com::sun::star::drawing::ConnectorType_LINES : // Connector 2->5
{
rShapeType = ESCHER_ShpInst_StraightConnector1;
AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleStraight );
}
break;
}
CreateLineProperties( aXPropSet, false );
bRetValue = true;
}
}
}
}
}
return bRetValue;
}
bool EscherPropertyContainer::CreateShadowProperties(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet )
{
::com::sun::star::uno::Any aAny;
bool bHasShadow(false); // shadow is possible only if at least a fillcolor, linecolor or graphic is set
sal_uInt32 nLineFlags = 0; // default : shape has no line
sal_uInt32 nFillFlags = 0x10; // shape is filled
GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
GetOpt( ESCHER_Prop_fNoFillHitTest, nFillFlags );
sal_uInt32 nDummy;
bool bGraphic = GetOpt( DFF_Prop_pib, nDummy ) || GetOpt( DFF_Prop_pibName, nDummy ) || GetOpt( DFF_Prop_pibFlags, nDummy );
sal_uInt32 nShadowFlags = 0x20000;
if ( ( nLineFlags & 8 ) || ( nFillFlags & 0x10 ) || bGraphic )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "Shadow" ) ), true ) )
{
if ( aAny >>= bHasShadow )
{
if ( bHasShadow )
{
nShadowFlags |= 2;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "ShadowColor" ) ), false ) )
AddOpt( ESCHER_Prop_shadowColor, ImplGetColor( *((sal_uInt32*)aAny.getValue()) ) );
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "ShadowXDistance" ) ), false ) )
AddOpt( ESCHER_Prop_shadowOffsetX, *((sal_Int32*)aAny.getValue()) * 360 );
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "ShadowYDistance" ) ), false ) )
AddOpt( ESCHER_Prop_shadowOffsetY, *((sal_Int32*)aAny.getValue()) * 360 );
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "ShadowTransparence" ) ), false ) )
AddOpt( ESCHER_Prop_shadowOpacity, 0x10000 - (((sal_uInt32)*((sal_uInt16*)aAny.getValue())) * 655 ) );
}
}
}
}
AddOpt( ESCHER_Prop_fshadowObscured, nShadowFlags );
return bHasShadow;
}
// ---------------------------------------------------------------------------------------------
sal_Int32 EscherPropertyContainer::GetValueForEnhancedCustomShapeParameter( const ::com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter,
const std::vector< sal_Int32 >& rEquationOrder, bool bAdjustTrans )
{
sal_Int32 nValue = 0;
if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
{
double fValue;
if ( rParameter.Value >>= fValue )
nValue = (sal_Int32)fValue;
}
else
rParameter.Value >>= nValue;
switch( rParameter.Type )
{
case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
{
OSL_ASSERT((sal_uInt32)nValue < rEquationOrder.size());
if ( (sal_uInt32)nValue < rEquationOrder.size() )
{
nValue = (sal_uInt16)rEquationOrder[ nValue ];
nValue |= (sal_uInt32)0x80000000;
}
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT:
{
if(bAdjustTrans)
{
sal_uInt32 nAdjustValue = 0;
bool bGot = GetOpt((sal_uInt16)( DFF_Prop_adjustValue + nValue ), nAdjustValue);
if(bGot) nValue = (sal_Int32)nAdjustValue;
}
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
default:
break;
/* not sure if it is allowed to set following values
(but they are not yet used)
case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
*/
}
return nValue;
}
bool GetValueForEnhancedCustomShapeHandleParameter( sal_Int32& nRetValue, const com::sun::star::drawing::EnhancedCustomShapeParameter& rParameter )
{
bool bSpecial(false);
nRetValue = 0;
if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
{
double fValue;
if ( rParameter.Value >>= fValue )
nRetValue = (sal_Int32)fValue;
}
else
rParameter.Value >>= nRetValue;
switch( rParameter.Type )
{
case com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION :
{
nRetValue += 3;
bSpecial = true;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
{
nRetValue += 0x100;
bSpecial = true;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::TOP :
case com::sun::star::drawing::EnhancedCustomShapeParameterType::LEFT :
{
nRetValue = 0;
bSpecial = true;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::RIGHT :
case com::sun::star::drawing::EnhancedCustomShapeParameterType::BOTTOM :
{
nRetValue = 1;
bSpecial = true;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeParameterType::NORMAL :
{
}
break;
}
return bSpecial;
}
void ConvertEnhancedCustomShapeEquation( SdrObjCustomShape* pCustoShape,
std::vector< EnhancedCustomShapeEquation >& rEquations, std::vector< sal_Int32 >& rEquationOrder )
{
if ( pCustoShape )
{
uno::Sequence< rtl::OUString > sEquationSource;
const rtl::OUString sEquations( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)(const SdrCustomShapeGeometryItem&)
pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
const uno::Any* pAny = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sEquations );
if ( pAny )
*pAny >>= sEquationSource;
sal_Int32 nEquationSourceCount = sEquationSource.getLength();
if ( nEquationSourceCount && (nEquationSourceCount <= 128) )
{
sal_Int32 i;
for ( i = 0; i < nEquationSourceCount; i++ )
{
EnhancedCustomShape2d aCustoShape2d( pCustoShape );
try
{
::boost::shared_ptr< EnhancedCustomShape::ExpressionNode > aExpressNode(
EnhancedCustomShape::FunctionParser::parseFunction( sEquationSource[ i ], aCustoShape2d ) );
com::sun::star::drawing::EnhancedCustomShapeParameter aPara( aExpressNode->fillNode( rEquations, NULL, 0 ) );
if ( aPara.Type != com::sun::star::drawing::EnhancedCustomShapeParameterType::EQUATION )
{
EnhancedCustomShapeEquation aEquation;
aEquation.nOperation = 0;
EnhancedCustomShape::FillEquationParameter( aPara, 0, aEquation );
rEquations.push_back( aEquation );
}
}
catch ( EnhancedCustomShape::ParseError& )
{
EnhancedCustomShapeEquation aEquation; // ups, we should not be here,
aEquation.nOperation = 0; // creating a default equation with value 1
aEquation.nPara[ 0 ] = 1; // hoping that this will not break anything
rEquations.push_back( aEquation );
}
catch ( ... )
{
EnhancedCustomShapeEquation aEquation; // #i112309# EnhancedCustomShape::Parse error
aEquation.nOperation = 0; // not catched on linux platform
aEquation.nPara[ 0 ] = 1;
rEquations.push_back( aEquation );
}
rEquationOrder.push_back( rEquations.size() - 1 );
}
// now updating our old equation indices, they are marked with a bit in the hiword of nOperation
std::vector< EnhancedCustomShapeEquation >::iterator aIter( rEquations.begin() );
std::vector< EnhancedCustomShapeEquation >::iterator aEnd ( rEquations.end() );
while( aIter != aEnd )
{
sal_Int32 nMask = 0x20000000;
for( i = 0; i < 3; i++ )
{
if ( aIter->nOperation & nMask )
{
aIter->nOperation ^= nMask;
const sal_Int32 nIndex(aIter->nPara[ i ] & 0x3ff);
// #124661# check index access, there are cases where this is out of bound leading
// to errors up to crashes when executed
if(nIndex < rEquationOrder.size())
{
aIter->nPara[ i ] = rEquationOrder[ nIndex ] | 0x400;
}
else
{
OSL_ENSURE(false, "Attempted out of bound access to rEquationOrder of CustomShape (!)");
}
}
nMask <<= 1;
}
aIter++;
}
}
}
}
bool EscherPropertyContainer::IsDefaultObject( SdrObjCustomShape* pCustoShape , const MSO_SPT eShapeType )
{
bool bIsDefaultObject(false);
switch(eShapeType)
{
//if the custom shape is not default shape of ppt, return sal_Fasle;
case mso_sptTearDrop:
return bIsDefaultObject;
default:
break;
}
if ( pCustoShape )
{
if ( pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_EQUATIONS )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_VIEWBOX )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_PATH )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_GLUEPOINTS )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_SEGMENTS )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHX )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_STRETCHY )
// && pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_HANDLES )
&& pCustoShape->IsDefaultGeometry( SdrObjCustomShape::DEFAULT_TEXTFRAMES ) )
bIsDefaultObject = true;
}
return bIsDefaultObject;
}
void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted )
{
const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType );
if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
{
sal_Int32 k, nkCount = pDefCustomShape->nHandles;
const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
for ( k = 0; k < nkCount; k++, pData++ )
{
if ( pData->nFlags & MSDFF_HANDLE_FLAGS_POLAR )
{
if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k );
}
}
}
}
bool EscherPropertyContainer::GetAdjustmentValue( const com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue )
{
if ( rkProp.State != beans::PropertyState_DIRECT_VALUE )
return false;
bool bUseFixedFloat(nAdjustmentsWhichNeedsToBeConverted & (1 << nIndex));
if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
{
double fValue(0.0);
rkProp.Value >>= fValue;
if ( bUseFixedFloat )
fValue *= 65536.0;
nValue = (sal_Int32)fValue;
}
else
{
rkProp.Value >>= nValue;
if ( bUseFixedFloat )
nValue <<= 16;
}
return true;
}
void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape )
{
uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
if ( aXPropSet.is() )
{
SdrObjCustomShape* pCustoShape = (SdrObjCustomShape*)GetSdrObjectFromXShape( rXShape );
if ( !pCustoShape ) return;
const rtl::OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
uno::Sequence< beans::PropertyValue > aGeoPropSeq;
if ( aGeoPropSet >>= aGeoPropSeq )
{
const rtl::OUString sViewBox ( RTL_CONSTASCII_USTRINGPARAM( "ViewBox" ) );
const rtl::OUString sTextRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "TextRotateAngle" ) );
const rtl::OUString sExtrusion ( RTL_CONSTASCII_USTRINGPARAM( "Extrusion" ) );
const rtl::OUString sEquations ( RTL_CONSTASCII_USTRINGPARAM( "Equations" ) );
const rtl::OUString sPath ( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
const rtl::OUString sTextPath ( RTL_CONSTASCII_USTRINGPARAM( "TextPath" ) );
const rtl::OUString sHandles ( RTL_CONSTASCII_USTRINGPARAM( "Handles" ) );
const rtl::OUString sAdjustmentValues ( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) );
bool bHasAdjustmentValuesProp = false;
uno::Any aAdjustmentValuesProp;
bool bHasPathCoordinatesProp = false;
uno::Any aPathCoordinatesProp;
sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0;
uno::Sequence< beans::PropertyValues > aHandlesPropSeq;
bool bPredefinedHandlesUsed(true);
bool bIsDefaultObject(IsDefaultObject(pCustoShape, eShapeType));
// convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation >
std::vector< EnhancedCustomShapeEquation > aEquations;
std::vector< sal_Int32 > aEquationOrder;
ConvertEnhancedCustomShapeEquation( pCustoShape, aEquations, aEquationOrder );
sal_Int32 i, nCount = aGeoPropSeq.getLength();
for ( i = 0; i < nCount; i++ )
{
const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
if ( rProp.Name.equals( sViewBox ) )
{
if ( !bIsDefaultObject )
{
awt::Rectangle aViewBox;
if ( rProp.Value >>= aViewBox )
{
AddOpt( DFF_Prop_geoLeft, aViewBox.X );
AddOpt( DFF_Prop_geoTop, aViewBox.Y );
AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width );
AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height );
}
}
}
else if ( rProp.Name.equals( sTextRotateAngle ) )
{
double f = 0, fTextRotateAngle;
if ( rProp.Value >>= f )
{
fTextRotateAngle = fmod( f, 360.0 );
if ( fTextRotateAngle < 0 )
fTextRotateAngle = 360 + fTextRotateAngle;
if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) )
AddOpt( DFF_Prop_cdirFont, mso_cdir90 );
else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) )
AddOpt( DFF_Prop_cdirFont, mso_cdir180 );
else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) )
AddOpt( DFF_Prop_cdirFont, mso_cdir270 );
}
}
else if ( rProp.Name.equals( sExtrusion ) )
{
uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
if ( rProp.Value >>= aExtrusionPropSeq )
{
sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags;
sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags;
nLightFaceFlagsOrg = nLightFaceFlags = 0x000001;
nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e;
if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) )
nLightFaceFlagsOrg = nLightFaceFlags;
if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) )
nFillHarshFlagsOrg = nFillHarshFlags;
sal_Int32 r, nrCount = aExtrusionPropSeq.getLength();
for ( r = 0; r < nrCount; r++ )
{
const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ];
const rtl::OUString sExtrusionBrightness ( RTL_CONSTASCII_USTRINGPARAM( "Brightness" ) );
const rtl::OUString sExtrusionDepth ( RTL_CONSTASCII_USTRINGPARAM( "Depth" ) );
const rtl::OUString sExtrusionDiffusion ( RTL_CONSTASCII_USTRINGPARAM( "Diffusion" ) );
const rtl::OUString sExtrusionNumberOfLineSegments ( RTL_CONSTASCII_USTRINGPARAM( "NumberOfLineSegments" ) );
const rtl::OUString sExtrusionLightFace ( RTL_CONSTASCII_USTRINGPARAM( "LightFace" ) );
const rtl::OUString sExtrusionFirstLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightHarsh" ) );
const rtl::OUString sExtrusionSecondLightHarsh ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightHarsh" ) );
const rtl::OUString sExtrusionFirstLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightLevel" ) );
const rtl::OUString sExtrusionSecondLightLevel ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightLevel" ) );
const rtl::OUString sExtrusionFirstLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "FirstLightDirection" ) );
const rtl::OUString sExtrusionSecondLightDirection ( RTL_CONSTASCII_USTRINGPARAM( "SecondLightDirection" ) );
const rtl::OUString sExtrusionMetal ( RTL_CONSTASCII_USTRINGPARAM( "Metal" ) );
const rtl::OUString sExtrusionShadeMode ( RTL_CONSTASCII_USTRINGPARAM( "ShadeMode" ) );
const rtl::OUString sExtrusionRotateAngle ( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) );
const rtl::OUString sExtrusionRotationCenter ( RTL_CONSTASCII_USTRINGPARAM( "RotationCenter" ) );
const rtl::OUString sExtrusionShininess ( RTL_CONSTASCII_USTRINGPARAM( "Shininess" ) );
const rtl::OUString sExtrusionSkew ( RTL_CONSTASCII_USTRINGPARAM( "Skew" ) );
const rtl::OUString sExtrusionSpecularity ( RTL_CONSTASCII_USTRINGPARAM( "Specularity" ) );
const rtl::OUString sExtrusionProjectionMode ( RTL_CONSTASCII_USTRINGPARAM( "ProjectionMode" ) );
const rtl::OUString sExtrusionViewPoint ( RTL_CONSTASCII_USTRINGPARAM( "ViewPoint" ) );
const rtl::OUString sExtrusionOrigin ( RTL_CONSTASCII_USTRINGPARAM( "Origin" ) );
const rtl::OUString sExtrusionColor ( RTL_CONSTASCII_USTRINGPARAM( "Color" ) );
if ( rrProp.Name.equals( sExtrusion ) )
{
sal_Bool bExtrusionOn = sal_Bool();
if ( rrProp.Value >>= bExtrusionOn )
{
nLightFaceFlags |= 0x80000;
if ( bExtrusionOn )
nLightFaceFlags |= 8;
else
nLightFaceFlags &=~8;
}
}
else if ( rrProp.Name.equals( sExtrusionBrightness ) )
{
double fExtrusionBrightness = 0;
if ( rrProp.Value >>= fExtrusionBrightness )
AddOpt( DFF_Prop_c3DAmbientIntensity, (sal_Int32)( fExtrusionBrightness * 655.36 ) );
}
else if ( rrProp.Name.equals( sExtrusionDepth ) )
{
double fDepth = 0;
double fFraction = 0;
com::sun::star::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
{
double fForeDepth = fDepth * fFraction;
double fBackDepth = fDepth - fForeDepth;
fBackDepth *= 360.0;
AddOpt( DFF_Prop_c3DExtrudeBackward, (sal_Int32)fBackDepth );
if ( fForeDepth != 0.0 )
{
fForeDepth *= 360.0;
AddOpt( DFF_Prop_c3DExtrudeForward, (sal_Int32)fForeDepth );
}
}
}
else if ( rrProp.Name.equals( sExtrusionDiffusion ) )
{
double fExtrusionDiffusion = 0;
if ( rrProp.Value >>= fExtrusionDiffusion )
AddOpt( DFF_Prop_c3DDiffuseAmt, (sal_Int32)( fExtrusionDiffusion * 655.36 ) );
}
else if ( rrProp.Name.equals( sExtrusionNumberOfLineSegments ) )
{
sal_Int32 nExtrusionNumberOfLineSegments = 0;
if ( rrProp.Value >>= nExtrusionNumberOfLineSegments )
AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments );
}
else if ( rrProp.Name.equals( sExtrusionLightFace ) )
{
sal_Bool bExtrusionLightFace = sal_Bool();
if ( rrProp.Value >>= bExtrusionLightFace )
{
nLightFaceFlags |= 0x10000;
if ( bExtrusionLightFace )
nLightFaceFlags |= 1;
else
nLightFaceFlags &=~1;
}
}
else if ( rrProp.Name.equals( sExtrusionFirstLightHarsh ) )
{
sal_Bool bExtrusionFirstLightHarsh = sal_Bool();
if ( rrProp.Value >>= bExtrusionFirstLightHarsh )
{
nFillHarshFlags |= 0x20000;
if ( bExtrusionFirstLightHarsh )
nFillHarshFlags |= 2;
else
nFillHarshFlags &=~2;
}
}
else if ( rrProp.Name.equals( sExtrusionSecondLightHarsh ) )
{
sal_Bool bExtrusionSecondLightHarsh = sal_Bool();
if ( rrProp.Value >>= bExtrusionSecondLightHarsh )
{
nFillHarshFlags |= 0x10000;
if ( bExtrusionSecondLightHarsh )
nFillHarshFlags |= 1;
else
nFillHarshFlags &=~1;
}
}
else if ( rrProp.Name.equals( sExtrusionFirstLightLevel ) )
{
double fExtrusionFirstLightLevel = 0;
if ( rrProp.Value >>= fExtrusionFirstLightLevel )
AddOpt( DFF_Prop_c3DKeyIntensity, (sal_Int32)( fExtrusionFirstLightLevel * 655.36 ) );
}
else if ( rrProp.Name.equals( sExtrusionSecondLightLevel ) )
{
double fExtrusionSecondLightLevel = 0;
if ( rrProp.Value >>= fExtrusionSecondLightLevel )
AddOpt( DFF_Prop_c3DFillIntensity, (sal_Int32)( fExtrusionSecondLightLevel * 655.36 ) );
}
else if ( rrProp.Name.equals( sExtrusionFirstLightDirection ) )
{
drawing::Direction3D aExtrusionFirstLightDirection;
if ( rrProp.Value >>= aExtrusionFirstLightDirection )
{
AddOpt( DFF_Prop_c3DKeyX, (sal_Int32)aExtrusionFirstLightDirection.DirectionX );
AddOpt( DFF_Prop_c3DKeyY, (sal_Int32)aExtrusionFirstLightDirection.DirectionY );
AddOpt( DFF_Prop_c3DKeyZ, (sal_Int32)aExtrusionFirstLightDirection.DirectionZ );
}
}
else if ( rrProp.Name.equals( sExtrusionSecondLightDirection ) )
{
drawing::Direction3D aExtrusionSecondLightPosition;
if ( rrProp.Value >>= aExtrusionSecondLightPosition )
{
AddOpt( DFF_Prop_c3DFillX, (sal_Int32)aExtrusionSecondLightPosition.DirectionX );
AddOpt( DFF_Prop_c3DFillY, (sal_Int32)aExtrusionSecondLightPosition.DirectionY );
AddOpt( DFF_Prop_c3DFillZ, (sal_Int32)aExtrusionSecondLightPosition.DirectionZ );
}
}
else if ( rrProp.Name.equals( sExtrusionMetal ) )
{
sal_Bool bExtrusionMetal = sal_Bool();
if ( rrProp.Value >>= bExtrusionMetal )
{
nLightFaceFlags |= 0x40000;
if ( bExtrusionMetal )
nLightFaceFlags |= 4;
else
nLightFaceFlags &=~4;
}
}
else if ( rrProp.Name.equals( sExtrusionShadeMode ) )
{
drawing::ShadeMode eExtrusionShadeMode;
if ( rrProp.Value >>= eExtrusionShadeMode )
{
sal_uInt32 nRenderMode;
switch( eExtrusionShadeMode )
{
default:
case drawing::ShadeMode_FLAT :
case drawing::ShadeMode_PHONG :
case drawing::ShadeMode_SMOOTH :
nRenderMode = mso_FullRender;
break;
case drawing::ShadeMode_DRAFT :
{
nRenderMode = mso_Wireframe;
}
break;
}
AddOpt( DFF_Prop_c3DRenderMode, nRenderMode );
}
}
else if ( rrProp.Name.equals( sExtrusionRotateAngle ) )
{
double fExtrusionAngleX = 0;
double fExtrusionAngleY = 0;
com::sun::star::drawing::EnhancedCustomShapeParameterPair aRotateAnglePair;
if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) )
{
fExtrusionAngleX *= 65536;
fExtrusionAngleY *= 65536;
AddOpt( DFF_Prop_c3DXRotationAngle, (sal_Int32)fExtrusionAngleX );
AddOpt( DFF_Prop_c3DYRotationAngle, (sal_Int32)fExtrusionAngleY );
}
}
else if ( rrProp.Name.equals( sExtrusionRotationCenter ) )
{
drawing::Direction3D aExtrusionRotationCenter;
if ( rrProp.Value >>= aExtrusionRotationCenter )
{
AddOpt( DFF_Prop_c3DRotationCenterX, (sal_Int32)( aExtrusionRotationCenter.DirectionX * 360.0 ) );
AddOpt( DFF_Prop_c3DRotationCenterY, (sal_Int32)( aExtrusionRotationCenter.DirectionY * 360.0 ) );
AddOpt( DFF_Prop_c3DRotationCenterZ, (sal_Int32)( aExtrusionRotationCenter.DirectionZ * 360.0 ) );
nFillHarshFlags &=~8; // don't use AutoRotationCenter;
}
}
else if ( rrProp.Name.equals( sExtrusionShininess ) )
{
double fExtrusionShininess = 0;
if ( rrProp.Value >>= fExtrusionShininess )
AddOpt( DFF_Prop_c3DShininess, (sal_Int32)( fExtrusionShininess * 655.36 ) );
}
else if ( rrProp.Name.equals( sExtrusionSkew ) )
{
double fSkewAmount = 0;
double fSkewAngle = 0;
com::sun::star::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) )
{
AddOpt( DFF_Prop_c3DSkewAmount, (sal_Int32)fSkewAmount );
AddOpt( DFF_Prop_c3DSkewAngle, (sal_Int32)( fSkewAngle * 65536 ) );
}
}
else if ( rrProp.Name.equals( sExtrusionSpecularity ) )
{
double fExtrusionSpecularity = 0;
if ( rrProp.Value >>= fExtrusionSpecularity )
AddOpt( DFF_Prop_c3DSpecularAmt, (sal_Int32)( fExtrusionSpecularity * 1333 ) );
}
else if ( rrProp.Name.equals( sExtrusionProjectionMode ) )
{
drawing::ProjectionMode eExtrusionProjectionMode;
if ( rrProp.Value >>= eExtrusionProjectionMode )
{
nFillHarshFlags |= 0x40000;
if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL )
nFillHarshFlags |= 4;
else
nFillHarshFlags &=~4;
}
}
else if ( rrProp.Name.equals( sExtrusionViewPoint ) )
{
drawing::Position3D aExtrusionViewPoint;
if ( rrProp.Value >>= aExtrusionViewPoint )
{
aExtrusionViewPoint.PositionX *= 360.0;
aExtrusionViewPoint.PositionY *= 360.0;
aExtrusionViewPoint.PositionZ *= 360.0;
AddOpt( DFF_Prop_c3DXViewpoint, (sal_Int32)aExtrusionViewPoint.PositionX );
AddOpt( DFF_Prop_c3DYViewpoint, (sal_Int32)aExtrusionViewPoint.PositionY );
AddOpt( DFF_Prop_c3DZViewpoint, (sal_Int32)aExtrusionViewPoint.PositionZ );
}
}
else if ( rrProp.Name.equals( sExtrusionOrigin ) )
{
double fExtrusionOriginX = 0;
double fExtrusionOriginY = 0;
com::sun::star::drawing::EnhancedCustomShapeParameterPair aOriginPair;
if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) )
{
AddOpt( DFF_Prop_c3DOriginX, (sal_Int32)( fExtrusionOriginX * 65536 ) );
AddOpt( DFF_Prop_c3DOriginY, (sal_Int32)( fExtrusionOriginY * 65536 ) );
}
}
else if ( rrProp.Name.equals( sExtrusionColor ) )
{
sal_Bool bExtrusionColor = sal_Bool();
if ( rrProp.Value >>= bExtrusionColor )
{
nLightFaceFlags |= 0x20000;
if ( bExtrusionColor )
{
nLightFaceFlags |= 2;
uno::Any aFillColor2;
if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet,
String( RTL_CONSTASCII_USTRINGPARAM( "FillColor2" ) ), true ) )
{
sal_uInt32 nFillColor = ImplGetColor( *((sal_uInt32*)aFillColor2.getValue()) );
AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor );
}
}
else
nLightFaceFlags &=~2;
}
}
}
if ( nLightFaceFlags != nLightFaceFlagsOrg )
AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags );
if ( nFillHarshFlags != nFillHarshFlagsOrg )
AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags );
}
}
else if ( rProp.Name.equals( sEquations ) )
{
if ( !bIsDefaultObject )
{
sal_uInt16 nElements = (sal_uInt16)aEquations.size();
if ( nElements )
{
sal_uInt16 nElementSize = 8;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
std::vector< EnhancedCustomShapeEquation >::const_iterator aIter( aEquations.begin() );
std::vector< EnhancedCustomShapeEquation >::const_iterator aEnd ( aEquations.end() );
while( aIter != aEnd )
{
aOut << (sal_uInt16)aIter->nOperation
<< (sal_Int16)aIter->nPara[ 0 ]
<< (sal_Int16)aIter->nPara[ 1 ]
<< (sal_Int16)aIter->nPara[ 2 ];
aIter++;
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_pFormulas, true, nStreamSize - 6, pBuf, nStreamSize );
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_pFormulas, true, 0, pBuf, 0 );
}
}
}
else if ( rProp.Name.equals( sPath ) )
{
uno::Sequence< beans::PropertyValue > aPathPropSeq;
if ( rProp.Value >>= aPathPropSeq )
{
sal_uInt32 nPathFlags, nPathFlagsOrg;
nPathFlagsOrg = nPathFlags = 0x39;
if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) )
nPathFlagsOrg = nPathFlags;
sal_Int32 r, nrCount = aPathPropSeq.getLength();
for ( r = 0; r < nrCount; r++ )
{
const beans::PropertyValue& rrProp = aPathPropSeq[ r ];
const rtl::OUString sPathExtrusionAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ExtrusionAllowed" ) );
const rtl::OUString sPathConcentricGradientFillAllowed ( RTL_CONSTASCII_USTRINGPARAM( "ConcentricGradientFillAllowed" ) );
const rtl::OUString sPathTextPathAllowed ( RTL_CONSTASCII_USTRINGPARAM( "TextPathAllowed" ) );
const rtl::OUString sPathCoordinates ( RTL_CONSTASCII_USTRINGPARAM( "Coordinates" ) );
const rtl::OUString sPathGluePoints ( RTL_CONSTASCII_USTRINGPARAM( "GluePoints" ) );
const rtl::OUString sPathGluePointType ( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
const rtl::OUString sPathSegments ( RTL_CONSTASCII_USTRINGPARAM( "Segments" ) );
const rtl::OUString sPathStretchX ( RTL_CONSTASCII_USTRINGPARAM( "StretchX" ) );
const rtl::OUString sPathStretchY ( RTL_CONSTASCII_USTRINGPARAM( "StretchY" ) );
const rtl::OUString sPathTextFrames ( RTL_CONSTASCII_USTRINGPARAM( "TextFrames" ) );
if ( rrProp.Name.equals( sPathExtrusionAllowed ) )
{
sal_Bool bExtrusionAllowed = sal_Bool();
if ( rrProp.Value >>= bExtrusionAllowed )
{
nPathFlags |= 0x100000;
if ( bExtrusionAllowed )
nPathFlags |= 16;
else
nPathFlags &=~16;
}
}
else if ( rrProp.Name.equals( sPathConcentricGradientFillAllowed ) )
{
sal_Bool bConcentricGradientFillAllowed = sal_Bool();
if ( rrProp.Value >>= bConcentricGradientFillAllowed )
{
nPathFlags |= 0x20000;
if ( bConcentricGradientFillAllowed )
nPathFlags |= 2;
else
nPathFlags &=~2;
}
}
else if ( rrProp.Name.equals( sPathTextPathAllowed ) )
{
sal_Bool bTextPathAllowed = sal_Bool();
if ( rrProp.Value >>= bTextPathAllowed )
{
nPathFlags |= 0x40000;
if ( bTextPathAllowed )
nPathFlags |= 4;
else
nPathFlags &=~4;
}
}
else if ( rrProp.Name.equals( sPathCoordinates ) )
{
if ( !bIsDefaultObject )
{
aPathCoordinatesProp = rrProp.Value;
bHasPathCoordinatesProp = true;
}
}
else if ( rrProp.Name.equals( sPathGluePoints ) )
{
if ( !bIsDefaultObject )
{
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
if ( rrProp.Value >>= aGluePoints )
{
// creating the vertices
sal_uInt16 nElements = (sal_uInt16)aGluePoints.getLength();
if ( nElements )
{
sal_uInt16 j, nElementSize = 8;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
for( j = 0; j < nElements; j++ )
{
sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder );
sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder );
aOut << X
<< Y;
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_connectorPoints, true, nStreamSize - 6, pBuf, nStreamSize ); // -6
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_connectorPoints, true, 0, pBuf, 0 );
}
}
}
}
else if ( rrProp.Name.equals( sPathGluePointType ) )
{
sal_Int16 nGluePointType = sal_Int16();
if ( rrProp.Value >>= nGluePointType )
AddOpt( DFF_Prop_connectorType, (sal_uInt16)nGluePointType );
}
else if ( rrProp.Name.equals( sPathSegments ) )
{
if ( !bIsDefaultObject )
{
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment > aSegments;
if ( rrProp.Value >>= aSegments )
{
// creating seginfo
if ( (sal_uInt16)aSegments.getLength() )
{
sal_uInt16 j, nElements = (sal_uInt16)aSegments.getLength();
sal_uInt16 nElementSize = 2;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
for ( j = 0; j < nElements; j++ )
{
sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count;
switch( aSegments[ j ].Command )
{
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
{
nVal = 0x4000;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
{
nVal |= 0x2000;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
{
nVal = 0x6001;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
{
nVal = 0x8000;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
{
nVal = 0xaa00;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
{
nVal = 0xab00;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
{
nVal *= 3;
nVal |= 0xa100;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
{
nVal *= 3;
nVal |= 0xa200;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
{
nVal <<= 2;
nVal |= 0xa300;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC :
{
nVal <<= 2;
nVal |= 0xa400;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
{
nVal <<= 2;
nVal |= 0xa500;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
{
nVal <<= 2;
nVal |= 0xa600;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
{
nVal |= 0xa700;
}
break;
case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
{
nVal |= 0xa800;
}
break;
}
aOut << nVal;
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_pSegmentInfo, false, nStreamSize - 6, pBuf, nStreamSize );
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_pSegmentInfo, true, 0, pBuf, 0 );
}
}
}
}
else if ( rrProp.Name.equals( sPathStretchX ) )
{
if ( !bIsDefaultObject )
{
sal_Int32 nStretchX = 0;
if ( rrProp.Value >>= nStretchX )
AddOpt( DFF_Prop_stretchPointX, nStretchX );
}
}
else if ( rrProp.Name.equals( sPathStretchY ) )
{
if ( !bIsDefaultObject )
{
sal_Int32 nStretchY = 0;
if ( rrProp.Value >>= nStretchY )
AddOpt( DFF_Prop_stretchPointY, nStretchY );
}
}
else if ( rrProp.Name.equals( sPathTextFrames ) )
{
if ( !bIsDefaultObject )
{
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
if ( rrProp.Value >>= aPathTextFrames )
{
if ( (sal_uInt16)aPathTextFrames.getLength() )
{
sal_uInt16 j, nElements = (sal_uInt16)aPathTextFrames.getLength();
sal_uInt16 nElementSize = 16;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
for ( j = 0; j < nElements; j++ )
{
sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder );
sal_Int32 nTop = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder );
sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder );
sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder );
aOut << nLeft
<< nTop
<< nRight
<< nBottom;
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_textRectangles, true, nStreamSize - 6, pBuf, nStreamSize );
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_textRectangles, true, 0, pBuf, 0 );
}
}
}
}
}
if ( nPathFlags != nPathFlagsOrg )
AddOpt( DFF_Prop_fFillOK, nPathFlags );
}
}
else if ( rProp.Name.equals( sTextPath ) )
{
uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
if ( rProp.Value >>= aTextPathPropSeq )
{
sal_uInt32 nTextPathFlagsOrg, nTextPathFlags;
nTextPathFlagsOrg = nTextPathFlags = 0xffff1000; // default
if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) )
nTextPathFlagsOrg = nTextPathFlags;
sal_Int32 r, nrCount = aTextPathPropSeq.getLength();
for ( r = 0; r < nrCount; r++ )
{
const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ];
const rtl::OUString sTextPathMode ( RTL_CONSTASCII_USTRINGPARAM( "TextPathMode" ) );
const rtl::OUString sTextPathScaleX ( RTL_CONSTASCII_USTRINGPARAM( "ScaleX" ) );
const rtl::OUString sSameLetterHeights ( RTL_CONSTASCII_USTRINGPARAM( "SameLetterHeights" ) );
if ( rrProp.Name.equals( sTextPath ) )
{
sal_Bool bTextPathOn = sal_Bool();
if ( rrProp.Value >>= bTextPathOn )
{
nTextPathFlags |= 0x40000000;
if ( bTextPathOn )
{
nTextPathFlags |= 0x4000;
sal_uInt32 nPathFlags = 0x39;
GetOpt( DFF_Prop_fFillOK, nPathFlags ); // SJ: can be removed if we are supporting the TextPathAllowed property in XML
nPathFlags |= 0x40004;
AddOpt( DFF_Prop_fFillOK, nPathFlags );
}
else
nTextPathFlags &=~0x4000;
}
}
else if ( rrProp.Name.equals( sTextPathMode ) )
{
com::sun::star::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
if ( rrProp.Value >>= eTextPathMode )
{
nTextPathFlags |= 0x05000000;
nTextPathFlags &=~0x500; // TextPathMode_NORMAL
if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_PATH )
nTextPathFlags |= 0x100;
else if ( eTextPathMode == com::sun::star::drawing::EnhancedCustomShapeTextPathMode_SHAPE )
nTextPathFlags |= 0x500;
}
}
else if ( rrProp.Name.equals( sTextPathScaleX ) )
{
sal_Bool bTextPathScaleX = sal_Bool();
if ( rrProp.Value >>= bTextPathScaleX )
{
nTextPathFlags |= 0x00400000;
if ( bTextPathScaleX )
nTextPathFlags |= 0x40;
else
nTextPathFlags &=~0x40;
}
}
else if ( rrProp.Name.equals( sSameLetterHeights ) )
{
sal_Bool bSameLetterHeights = sal_Bool();
if ( rrProp.Value >>= bSameLetterHeights )
{
nTextPathFlags |= 0x00800000;
if ( bSameLetterHeights )
nTextPathFlags |= 0x80;
else
nTextPathFlags &=~0x80;
}
}
}
if ( nTextPathFlags & 0x4000 ) // Is FontWork ?
{
// FontWork Text
rtl::OUString aText;
uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY );
if ( xText.is() )
aText = xText->getString();
if ( !aText.getLength() )
aText = ::rtl::OUString::createFromAscii( "your text" ); // todo: moving into a resource
AddOpt( DFF_Prop_gtextUNICODE, aText );
// FontWork Font
rtl::OUString aFontName;
const rtl::OUString sCharFontName ( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) );
uno::Any aAny = aXPropSet->getPropertyValue( sCharFontName );
aAny >>= aFontName;
if ( !aFontName.getLength() )
aFontName = ::rtl::OUString::createFromAscii( "Arial Black" );
AddOpt( DFF_Prop_gtextFont, aFontName );
sal_Int16 nCharScaleWidth = 100;
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharScaleWidth" ) ), true ) )
{
if ( aAny >>= nCharScaleWidth )
{
if ( nCharScaleWidth != 100 )
{
sal_Int32 nVal = nCharScaleWidth * 655;
AddOpt( DFF_Prop_gtextSpacing, nVal );
}
}
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) ), true ) )
{
float fCharHeight = 0.0;
if ( aAny >>= fCharHeight )
{
sal_Int32 nTextSize = static_cast< sal_Int32 > ( fCharHeight * 65536 );
AddOpt(ESCHER_Prop_gtextSize, nTextSize);
}
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharKerning" ) ), true ) )
{
sal_Int16 nCharKerning = sal_Int16();
if ( aAny >>= nCharKerning )
{
nTextPathFlags |= 0x10000000;
if ( nCharKerning )
nTextPathFlags |= 0x1000;
else
nTextPathFlags &=~0x1000;
}
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharPosture" ) ), true ) )
{
awt::FontSlant eFontSlant;
if ( aAny >>= eFontSlant )
{
nTextPathFlags |= 0x100010;
if ( eFontSlant != awt::FontSlant_NONE )
nTextPathFlags |= 0x10;
else
nTextPathFlags &=~0x10;
}
}
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) ), true ) )
{
float fFontWidth = 0;
if ( aAny >>= fFontWidth )
{
nTextPathFlags |= 0x200020;
if ( fFontWidth > awt::FontWeight::NORMAL )
nTextPathFlags |= 0x20;
else
nTextPathFlags &=~0x20;
}
}
//export gTextAlign attr
if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "TextHorizontalAdjust" ) ), true ) )
{
MSO_GeoTextAlign gTextAlign = mso_alignTextCenter;
// SdrFitToSizeType eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT );
aAny >>= eHA;
switch( eHA )
{
case drawing::TextHorizontalAdjust_LEFT :
gTextAlign = mso_alignTextLeft;
break;
case drawing::TextHorizontalAdjust_CENTER:
gTextAlign = mso_alignTextCenter;
break;
case drawing::TextHorizontalAdjust_RIGHT:
gTextAlign = mso_alignTextRight;
break;
case drawing::TextHorizontalAdjust_BLOCK:
{
SdrFitToSizeType eFTS( ((SdrTextFitToSizeTypeItem&)pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
if ( eFTS == SDRTEXTFIT_ALLLINES)
{
gTextAlign = mso_alignTextStretch;
}
else
{
gTextAlign = mso_alignTextWordJust;
}
break;
}
default:
break;
}
AddOpt(DFF_Prop_gtextAlign,gTextAlign);
}
}
if((nTextPathFlags & 0x4000) != 0) //Is Font work
{
OutlinerParaObject* pOutlinerParaObject = pCustoShape->GetOutlinerParaObject();
if ( pOutlinerParaObject && pOutlinerParaObject->IsVertical() )
nTextPathFlags |= 0x2000;
}
if ( nTextPathFlags != nTextPathFlagsOrg )
AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
}
}
else if ( rProp.Name.equals( sHandles ) )
{
if ( !bIsDefaultObject )
{
bPredefinedHandlesUsed = false;
if ( rProp.Value >>= aHandlesPropSeq )
{
sal_uInt16 nElements = (sal_uInt16)aHandlesPropSeq.getLength();
if ( nElements )
{
const rtl::OUString sHandle ( RTL_CONSTASCII_USTRINGPARAM( "Handle" ) );
sal_uInt16 k, j, nElementSize = 36;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
for ( k = 0; k < nElements; k++ )
{
sal_uInt32 nFlags = 0;
sal_Int32 nXPosition = 0;
sal_Int32 nYPosition = 0;
sal_Int32 nXMap = 0;
sal_Int32 nYMap = 0;
sal_Int32 nXRangeMin = 0x80000000;
sal_Int32 nXRangeMax = 0x7fffffff;
sal_Int32 nYRangeMin = 0x80000000;
sal_Int32 nYRangeMax = 0x7fffffff;
const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ];
for ( j = 0; j < rPropSeq.getLength(); j++ )
{
const beans::PropertyValue& rPropVal = rPropSeq[ j ];
const rtl::OUString sPosition ( RTL_CONSTASCII_USTRINGPARAM( "Position" ) );
const rtl::OUString sMirroredX ( RTL_CONSTASCII_USTRINGPARAM( "MirroredX" ) );
const rtl::OUString sMirroredY ( RTL_CONSTASCII_USTRINGPARAM( "MirroredY" ) );
const rtl::OUString sSwitched ( RTL_CONSTASCII_USTRINGPARAM( "Switched" ) );
const rtl::OUString sPolar ( RTL_CONSTASCII_USTRINGPARAM( "Polar" ) );
// const rtl::OUString sMap ( RTL_CONSTASCII_USTRINGPARAM( "Map" ) );
const rtl::OUString sRadiusRangeMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMinimum" ) );
const rtl::OUString sRadiusRangeMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RadiusRangeMaximum" ) );
const rtl::OUString sRangeXMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMinimum" ) );
const rtl::OUString sRangeXMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeXMaximum" ) );
const rtl::OUString sRangeYMinimum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMinimum" ) );
const rtl::OUString sRangeYMaximum ( RTL_CONSTASCII_USTRINGPARAM( "RangeYMaximum" ) );
if ( rPropVal.Name.equals( sPosition ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameterPair aPosition;
if ( rPropVal.Value >>= aPosition )
{
GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First );
GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second );
}
}
else if ( rPropVal.Name.equals( sMirroredX ) )
{
sal_Bool bMirroredX = sal_Bool();
if ( rPropVal.Value >>= bMirroredX )
{
if ( bMirroredX )
nFlags |= 1;
}
}
else if ( rPropVal.Name.equals( sMirroredY ) )
{
sal_Bool bMirroredY = sal_Bool();
if ( rPropVal.Value >>= bMirroredY )
{
if ( bMirroredY )
nFlags |= 2;
}
}
else if ( rPropVal.Name.equals( sSwitched ) )
{
sal_Bool bSwitched = sal_Bool();
if ( rPropVal.Value >>= bSwitched )
{
if ( bSwitched )
nFlags |= 4;
}
}
else if ( rPropVal.Name.equals( sPolar ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameterPair aPolar;
if ( rPropVal.Value >>= aPolar )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) )
nFlags |= 0x800;
if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) )
nFlags |= 0x1000;
nFlags |= 8;
}
}
/* seems not to be used.
else if ( rPropVal.Name.equals( sMap ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameterPair aMap;
if ( rPropVal.Value >>= aMap )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aMap.First ) )
nFlags |= 0x800;
if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aMap.Second ) )
nFlags |= 0x1000;
nFlags |= 0x10;
}
}
*/
else if ( rPropVal.Name.equals( sRadiusRangeMinimum ) )
{
nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not
nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this
com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
if ( rPropVal.Value >>= aRadiusRangeMinimum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) )
nFlags |= 0x80;
nFlags |= 0x2000;
}
}
else if ( rPropVal.Name.equals( sRadiusRangeMaximum ) )
{
nYRangeMin = (sal_Int32)0xff4c0000; // the range of angles seems to be a not
nYRangeMax = (sal_Int32)0x00b40000; // used feature, so we are defaulting this
com::sun::star::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
if ( rPropVal.Value >>= aRadiusRangeMaximum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) )
nFlags |= 0x100;
nFlags |= 0x2000;
}
}
else if ( rPropVal.Name.equals( sRangeXMinimum ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
if ( rPropVal.Value >>= aXRangeMinimum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) )
nFlags |= 0x80;
nFlags |= 0x20;
}
}
else if ( rPropVal.Name.equals( sRangeXMaximum ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
if ( rPropVal.Value >>= aXRangeMaximum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) )
nFlags |= 0x100;
nFlags |= 0x20;
}
}
else if ( rPropVal.Name.equals( sRangeYMinimum ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
if ( rPropVal.Value >>= aYRangeMinimum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) )
nFlags |= 0x200;
nFlags |= 0x20;
}
}
else if ( rPropVal.Name.equals( sRangeYMaximum ) )
{
com::sun::star::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
if ( rPropVal.Value >>= aYRangeMaximum )
{
if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) )
nFlags |= 0x400;
nFlags |= 0x20;
}
}
}
aOut << nFlags
<< nXPosition
<< nYPosition
<< nXMap
<< nYMap
<< nXRangeMin
<< nXRangeMax
<< nYRangeMin
<< nYRangeMax;
if ( nFlags & 8 )
nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) );
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_Handles, true, nStreamSize - 6, pBuf, nStreamSize );
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_Handles, true, 0, pBuf, 0 );
}
}
}
}
else if ( rProp.Name.equals( sAdjustmentValues ) )
{
// it is required, that the information which handle is polar has already be read,
// so we are able to change the polar value to a fixed float
aAdjustmentValuesProp = rProp.Value;
bHasAdjustmentValuesProp = true;
}
}
if ( bHasAdjustmentValuesProp )
{
uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
if ( aAdjustmentValuesProp >>= aAdjustmentSeq )
{
if ( bPredefinedHandlesUsed )
LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength();
for ( k = 0; k < nAdjustmentValues; k++ )
if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
AddOpt( (sal_uInt16)( DFF_Prop_adjustValue + k ), (sal_uInt32)nValue );
}
}
if( bHasPathCoordinatesProp )
{
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
if ( aPathCoordinatesProp >>= aCoordinates )
{
// creating the vertices
if ( (sal_uInt16)aCoordinates.getLength() )
{
sal_uInt16 j, nElements = (sal_uInt16)aCoordinates.getLength();
sal_uInt16 nElementSize = 8;
sal_uInt32 nStreamSize = nElementSize * nElements + 6;
SvMemoryStream aOut( nStreamSize );
aOut << nElements
<< nElements
<< nElementSize;
for( j = 0; j < nElements; j++ )
{
sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder, true );
sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder, true );
aOut << X
<< Y;
}
sal_uInt8* pBuf = new sal_uInt8[ nStreamSize ];
memcpy( pBuf, aOut.GetData(), nStreamSize );
AddOpt( DFF_Prop_pVertices, true, nStreamSize - 6, pBuf, nStreamSize ); // -6
}
else
{
sal_uInt8* pBuf = new sal_uInt8[ 1 ];
AddOpt( DFF_Prop_pVertices, true, 0, pBuf, 0 );
}
}
}
}
}
}
// ---------------------------------------------------------------------------------------------
MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, rtl::OUString& rShapeType )
{
MSO_SPT eShapeType = mso_sptNil;
uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
if ( aXPropSet.is() )
{
try
{
const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM ( "CustomShapeGeometry" ) );
uno::Any aGeoPropSet = aXPropSet->getPropertyValue( sCustomShapeGeometry );
uno::Sequence< beans::PropertyValue > aGeoPropSeq;
if ( aGeoPropSet >>= aGeoPropSeq )
{
sal_Int32 i, nCount = aGeoPropSeq.getLength();
for ( i = 0; i < nCount; i++ )
{
const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
if ( rProp.Name.equalsAscii( "Type" ) )
{
if ( rProp.Value >>= rShapeType )
eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType );
}
}
}
}
catch( ::com::sun::star::uno::Exception& )
{
}
}
return eShapeType;
}
// ---------------------------------------------------------------------------------------------
//Implement for form control export
bool EscherPropertyContainer::CreateBlipPropertiesforOLEControl(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape)
{
SdrObject* pShape = GetSdrObjectFromXShape( rXShape );
if ( pShape )
{
Graphic aGraphic(GetObjGraphic(*pShape));
GraphicObject aGraphicObject = aGraphic;
ByteString aUniqueId = aGraphicObject.GetUniqueID();
if ( aUniqueId.Len() )
{
if(mpGraphicProvider && mpPicOutStrm && !maObjectRange.isEmpty())
{
const basegfx::B2DRange aRange(0.0, 0.0, maObjectRange.getWidth(), maObjectRange.getHeight());
const sal_uInt32 nBlibId(mpGraphicProvider->GetBlibID(*mpPicOutStrm, aUniqueId, aRange, NULL));
if ( nBlibId )
{
AddOpt( ESCHER_Prop_pib, nBlibId, true );
ImplCreateGraphicAttributes( rXPropSet, nBlibId, false );
return true;
}
}
}
}
return false;
}
EscherPersistTable::EscherPersistTable()
{
}
// ---------------------------------------------------------------------------------------------
EscherPersistTable::~EscherPersistTable()
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
delete (EscherPersistEntry*)pPtr;
}
// ---------------------------------------------------------------------------------------------
bool EscherPersistTable::PtIsID( sal_uInt32 nID )
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
return true;
}
return false;
}
// ---------------------------------------------------------------------------------------------
void EscherPersistTable::PtInsert( sal_uInt32 nID, sal_uInt32 nOfs )
{
maPersistTable.Insert( new EscherPersistEntry( nID, nOfs ) );
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherPersistTable::PtDelete( sal_uInt32 nID )
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
{
// sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
delete (EscherPersistEntry*) maPersistTable.Remove();
}
}
return 0;
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherPersistTable::PtGetOffsetByID( sal_uInt32 nID )
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
return ((EscherPersistEntry*)pPtr)->mnOffset;
}
return 0;
};
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherPersistTable::PtReplace( sal_uInt32 nID, sal_uInt32 nOfs )
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
{
sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
return nRetValue;
}
}
return 0;
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherPersistTable::PtReplaceOrInsert( sal_uInt32 nID, sal_uInt32 nOfs )
{
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
if ( ((EscherPersistEntry*)pPtr)->mnID == nID )
{
sal_uInt32 nRetValue = ((EscherPersistEntry*)pPtr)->mnOffset;
((EscherPersistEntry*)pPtr)->mnOffset = nOfs;
return nRetValue;
}
}
PtInsert( nID, nOfs );
return 0;
}
bool EscherPropertyValueHelper::GetPropertyValue(
::com::sun::star::uno::Any& rAny,
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
const String& rString,
bool bTestPropertyAvailability )
{
bool bRetValue(true);
if ( bTestPropertyAvailability )
{
bRetValue = false;
try
{
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
aXPropSetInfo( rXPropSet->getPropertySetInfo() );
if ( aXPropSetInfo.is() )
bRetValue = aXPropSetInfo->hasPropertyByName( rString );
}
catch( ::com::sun::star::uno::Exception& )
{
bRetValue = false;
}
}
if ( bRetValue )
{
try
{
rAny = rXPropSet->getPropertyValue( rString );
if ( !rAny.hasValue() )
bRetValue = false;
}
catch( ::com::sun::star::uno::Exception& )
{
bRetValue = false;
}
}
return bRetValue;
}
// ---------------------------------------------------------------------------------------------
::com::sun::star::beans::PropertyState EscherPropertyValueHelper::GetPropertyState(
const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > & rXPropSet,
const String& rPropertyName )
{
::com::sun::star::beans::PropertyState eRetValue = ::com::sun::star::beans::PropertyState_AMBIGUOUS_VALUE;
try
{
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState > aXPropState
( rXPropSet, ::com::sun::star::uno::UNO_QUERY );
if ( aXPropState.is() )
eRetValue = aXPropState->getPropertyState( rPropertyName );
}
catch( ::com::sun::star::uno::Exception& )
{
//...
}
return eRetValue;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const ByteString& rId,
const GraphicAttr* pGraphicAttr ) :
mnPictureOffset ( nPictureOffset ),
mnRefCount ( 1 ),
mnSizeExtra ( 0 ),
maPrefSize ( rObject.GetPrefSize() ),
maPrefMapMode ( rObject.GetPrefMapMode() ),
mbIsEmpty ( true )
{
mbIsNativeGraphicPossible = ( pGraphicAttr == NULL );
meBlibType = UNKNOWN;
mnSize = 0;
sal_uInt32 nLen = rId.Len();
const sal_Char* pData = rId.GetBuffer();
GraphicType eType( rObject.GetType() );
if ( nLen && pData && ( eType != GRAPHIC_NONE ) )
{
mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen );
mnIdentifier[ 1 ] = 0;
if ( pGraphicAttr )
{
if ( pGraphicAttr->IsSpecialDrawMode()
|| pGraphicAttr->IsMirrored()
|| pGraphicAttr->IsCropped()
|| pGraphicAttr->IsRotated()
|| pGraphicAttr->IsTransparent()
|| pGraphicAttr->IsAdjusted() )
{
SvMemoryStream aSt( sizeof( GraphicAttr ) );
aSt << static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode())
<< static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags())
<< pGraphicAttr->GetLeftCrop()
<< pGraphicAttr->GetTopCrop()
<< pGraphicAttr->GetRightCrop()
<< pGraphicAttr->GetBottomCrop()
<< pGraphicAttr->GetRotation()
<< pGraphicAttr->GetLuminance()
<< pGraphicAttr->GetContrast()
<< pGraphicAttr->GetChannelR()
<< pGraphicAttr->GetChannelG()
<< pGraphicAttr->GetChannelB()
<< pGraphicAttr->GetGamma()
<< static_cast< sal_Bool >(pGraphicAttr->IsInvert())
<< pGraphicAttr->GetTransparency();
mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() );
}
else
mbIsNativeGraphicPossible = true;
}
sal_uInt32 i, nTmp, n1, n2;
n1 = n2 = 0;
for ( i = 0; i < nLen; i++ )
{
nTmp = n2 >> 28; // rotating 4 bit
n2 <<= 4;
n2 |= n1 >> 28;
n1 <<= 4;
n1 |= nTmp;
n1 ^= *pData++ - '0';
}
mnIdentifier[ 2 ] = n1;
mnIdentifier[ 3 ] = n2;
mbIsEmpty = false;
}
};
// ---------------------------------------------------------------------------------------------
void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, bool bWritePictureOffset, sal_uInt32 nResize )
{
sal_uInt32 nPictureOffset = ( bWritePictureOffset ) ? mnPictureOffset : 0;
rSt << (sal_uInt32)( ( ESCHER_BSE << 16 ) | ( ( (sal_uInt16)meBlibType << 4 ) | 2 ) )
<< (sal_uInt32)( 36 + nResize )
<< (sal_uInt8)meBlibType;
switch ( meBlibType )
{
case EMF :
case WMF : // EMF/WMF auf OS2 zu Pict Konvertieren
rSt << (sal_uInt8)PICT;
break;
default:
rSt << (sal_uInt8)meBlibType;
};
rSt.Write( &mnIdentifier[ 0 ], 16 );
rSt << (sal_uInt16)0
<< (sal_uInt32)( mnSize + mnSizeExtra )
<< mnRefCount
<< nPictureOffset
<< (sal_uInt32)0;
}
// ---------------------------------------------------------------------------------------------
EscherBlibEntry::~EscherBlibEntry()
{
};
// ---------------------------------------------------------------------------------------------
bool EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const
{
for ( int i = 0; i < 3; i++ )
{
if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] )
return false;
}
return true;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
EscherGraphicProvider::EscherGraphicProvider( sal_uInt32 nFlags ) :
mnFlags ( nFlags ),
mpBlibEntrys ( NULL ),
mnBlibBufSize ( 0 ),
mnBlibEntrys ( 0 )
{
}
EscherGraphicProvider::~EscherGraphicProvider()
{
for ( sal_uInt32 i = 0; i < mnBlibEntrys; delete mpBlibEntrys[ i++ ] ) ;
delete[] mpBlibEntrys;
}
void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset )
{
for( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
{
EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
pBlibEntry->mnPictureOffset += nOffset;
}
}
sal_uInt32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry )
{
if ( mnBlibBufSize == mnBlibEntrys )
{
mnBlibBufSize += 64;
EscherBlibEntry** pTemp = new EscherBlibEntry*[ mnBlibBufSize ];
for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
{
pTemp[ i ] = mpBlibEntrys[ i ];
}
delete[] mpBlibEntrys;
mpBlibEntrys = pTemp;
}
mpBlibEntrys[ mnBlibEntrys++ ] = p_EscherBlibEntry;
return mnBlibEntrys;
}
sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream* pMergePicStreamBSE ) const
{
sal_uInt32 nSize = 44 * mnBlibEntrys + 8;
if ( pMergePicStreamBSE )
{
for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
nSize += mpBlibEntrys[ i ]->mnSize + mpBlibEntrys[ i ]->mnSizeExtra;
}
return nSize;
}
bool EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt,
sal_uInt32 nBlipId, bool bWritePictureOffSet, sal_uInt32 nResize)
{
if (nBlipId > mnBlibEntrys || nBlipId == 0)
return false;
mpBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, bWritePictureOffSet, nResize);
return true;
}
void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE )
{
sal_uInt32 nSize = GetBlibStoreContainerSize( pMergePicStreamBSE );
if ( nSize )
{
rSt << (sal_uInt32)( ( ESCHER_BstoreContainer << 16 ) | 0x1f )
<< (sal_uInt32)( nSize - 8 );
if ( pMergePicStreamBSE )
{
sal_uInt32 i, nBlipSize, nOldPos = pMergePicStreamBSE->Tell();
const sal_uInt32 nBuf = 0x40000; // 256KB buffer
sal_uInt8* pBuf = new sal_uInt8[ nBuf ];
for ( i = 0; i < mnBlibEntrys; i++ )
{
EscherBlibEntry* pBlibEntry = mpBlibEntrys[ i ];
ESCHER_BlibType nBlibType = pBlibEntry->meBlibType;
nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra;
pBlibEntry->WriteBlibEntry( rSt, false, nBlipSize );
// BLIP
pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset );
sal_uInt16 n16;
// record version and instance
*pMergePicStreamBSE >> n16;
rSt << n16;
// record type
*pMergePicStreamBSE >> n16;
rSt << sal_uInt16( ESCHER_BlipFirst + nBlibType );
DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherGraphicProvider::WriteBlibStoreContainer: BLIP record types differ" );
sal_uInt32 n32;
// record size
*pMergePicStreamBSE >> n32;
nBlipSize -= 8;
rSt << nBlipSize;
DBG_ASSERT( nBlipSize == n32, "EscherGraphicProvider::WriteBlibStoreContainer: BLIP sizes differ" );
// record
while ( nBlipSize )
{
sal_uInt32 nBytes = ( nBlipSize > nBuf ? nBuf : nBlipSize );
pMergePicStreamBSE->Read( pBuf, nBytes );
rSt.Write( pBuf, nBytes );
nBlipSize -= nBytes;
}
}
delete[] pBuf;
pMergePicStreamBSE->Seek( nOldPos );
}
else
{
for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
mpBlibEntrys[ i ]->WriteBlibEntry( rSt, true );
}
}
}
bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode )
{
bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mnBlibEntrys );
if ( bInRange )
{
EscherBlibEntry* pEntry = mpBlibEntrys[ nBlibId - 1 ];
rPrefSize = pEntry->maPrefSize;
rPrefMapMode = pEntry->maPrefMapMode;
}
return bInRange;
}
sal_uInt32 EscherGraphicProvider::GetBlibID(
SvStream& rPicOutStrm,
const ByteString& rId,
const basegfx::B2DRange& /*rObjectRange*/,
const com::sun::star::awt::Rectangle* pVisArea,
const GraphicAttr* pGraphicAttr )
{
sal_uInt32 nBlibId = 0;
GraphicObject aGraphicObject( rId );
EscherBlibEntry* p_EscherBlibEntry = new EscherBlibEntry( rPicOutStrm.Tell(), aGraphicObject, rId, pGraphicAttr );
if ( !p_EscherBlibEntry->IsEmpty() )
{
for ( sal_uInt32 i = 0; i < mnBlibEntrys; i++ )
{
if ( *( mpBlibEntrys[ i ] ) == *p_EscherBlibEntry )
{
mpBlibEntrys[ i ]->mnRefCount++;
delete p_EscherBlibEntry;
return i + 1;
}
}
bool bUseNativeGraphic( false );
Graphic aGraphic( aGraphicObject.GetTransformedGraphic( pGraphicAttr ) );
GfxLink aGraphicLink;
SvMemoryStream aStream;
const sal_uInt8* pGraphicAry = NULL;
if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsLink() )
{
aGraphicLink = aGraphic.GetLink();
p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize();
pGraphicAry = aGraphicLink.GetData();
if ( p_EscherBlibEntry->mnSize && pGraphicAry )
{
switch ( aGraphicLink.GetType() )
{
case GFX_LINK_TYPE_NATIVE_JPG : p_EscherBlibEntry->meBlibType = PEG; break;
case GFX_LINK_TYPE_NATIVE_PNG : p_EscherBlibEntry->meBlibType = PNG; break;
// #15508# added BMP type for better exports; need to check this
// checked - does not work that way, so keep out for now. It may
// work somehow with direct DIB data, but that would need to be checked
// carefully
// for more comments please check RtfAttributeOutput::FlyFrameGraphic
//
// case GFX_LINK_TYPE_NATIVE_BMP : p_EscherBlibEntry->meBlibType = DIB; break;
case GFX_LINK_TYPE_NATIVE_WMF :
{
if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) )
{
if ( ( pGraphicAry[ 0x28 ] == 0x20 ) && ( pGraphicAry[ 0x29 ] == 0x45 ) // check the magic
&& ( pGraphicAry[ 0x2a ] == 0x4d ) && ( pGraphicAry[ 0x2b ] == 0x46 ) ) // number ( emf detection )
{
p_EscherBlibEntry->meBlibType = EMF;
}
else
{
p_EscherBlibEntry->meBlibType = WMF;
if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd )
&& ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) )
{ // we have to get rid of the metafileheader
pGraphicAry += 22;
p_EscherBlibEntry->mnSize -= 22;
}
}
}
}
break;
default: break;
}
if ( p_EscherBlibEntry->meBlibType != UNKNOWN )
bUseNativeGraphic = true;
}
}
if ( !bUseNativeGraphic )
{
GraphicType eGraphicType = aGraphic.GetType();
if ( ( eGraphicType == GRAPHIC_BITMAP ) || ( eGraphicType == GRAPHIC_GDIMETAFILE ) )
{
sal_uInt32 nErrCode;
if ( !aGraphic.IsAnimated() )
// !EMF nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_WMF );
nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GRAPHIC_BITMAP ) ? CVT_PNG : CVT_EMF );
else
{ // to store a animation, a gif has to be included into the msOG chunk of a png #I5583#
GraphicFilter* pFilter = GraphicFilter::GetGraphicFilter();
SvMemoryStream aGIFStream;
ByteString aVersion( "MSOFFICE9.0" );
aGIFStream.Write( aVersion.GetBuffer(), aVersion.Len() );
nErrCode = pFilter->ExportGraphic( aGraphic, String(), aGIFStream,
pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "GIF" ) ) ), NULL );
com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aFilterData( 1 );
com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence( 1 );
sal_uInt32 nGIFSreamLen = aGIFStream.Tell();
com::sun::star::uno::Sequence< sal_Int8 > aGIFSeq( nGIFSreamLen );
sal_Int8* pSeq = aGIFSeq.getArray();
aGIFStream.Seek( STREAM_SEEK_TO_BEGIN );
aGIFStream.Read( pSeq, nGIFSreamLen );
com::sun::star::beans::PropertyValue aChunkProp, aFilterProp;
aChunkProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "msOG" ) );
aChunkProp.Value <<= aGIFSeq;
aAdditionalChunkSequence[ 0 ] = aChunkProp;
aFilterProp.Name = String( RTL_CONSTASCII_USTRINGPARAM( "AdditionalChunks" ) );
aFilterProp.Value <<= aAdditionalChunkSequence;
aFilterData[ 0 ] = aFilterProp;
nErrCode = pFilter->ExportGraphic( aGraphic, String(), aStream,
pFilter->GetExportFormatNumberForShortName( String( RTL_CONSTASCII_USTRINGPARAM( "PNG" ) ) ), &aFilterData );
}
if ( nErrCode == ERRCODE_NONE )
{
// !EMF p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : WMF;
p_EscherBlibEntry->meBlibType = ( eGraphicType == GRAPHIC_BITMAP ) ? PNG : EMF;
aStream.Seek( STREAM_SEEK_TO_END );
p_EscherBlibEntry->mnSize = aStream.Tell();
pGraphicAry = (sal_uInt8*)aStream.GetData();
if ( p_EscherBlibEntry->meBlibType == WMF ) // the fileheader is not used
{
p_EscherBlibEntry->mnSize -= 22;
pGraphicAry += 22;
}
}
}
}
ESCHER_BlibType eBlibType = p_EscherBlibEntry->meBlibType;
if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) )
{
sal_uInt32 nExtra, nAtomSize = 0;
sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize;
if ( mnFlags & _E_GRAPH_PROV_USE_INSTANCES )
{
rPicOutStrm << (sal_uInt32)( 0x7f90000 | (sal_uInt16)( mnBlibEntrys << 4 ) )
<< (sal_uInt32)0;
nAtomSize = rPicOutStrm.Tell();
if ( eBlibType == PNG )
rPicOutStrm << (sal_uInt16)0x0606;
else if ( eBlibType == WMF )
rPicOutStrm << (sal_uInt16)0x0403;
else if ( eBlibType == EMF )
rPicOutStrm << (sal_uInt16)0x0402;
else if ( eBlibType == PEG )
rPicOutStrm << (sal_uInt16)0x0505;
}
if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) ) // || ( eBlibType == DIB )) // #15508#
{
nExtra = 17;
p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
// #15508# type see SvxMSDffManager::GetBLIPDirect (checked, does not work this way)
// see RtfAttributeOutput::FlyFrameGraphic for more comments
// maybe it would work with direct DIB data, but that would need thorough testing
if( eBlibType == PNG )
{
nInstance = 0xf01e6e00;
}
else // if( eBlibType == PEG )
{
nInstance = 0xf01d46a0;
}
//else // eBlibType == DIB
//{
// nInstance = 0xf01d7A80;
//}
// #15508#
//nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0;
rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
rPicOutStrm << (sal_uInt8)0xff;
rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
}
else
{
ZCodec aZCodec( 0x8000, 0x8000 );
aZCodec.BeginCompression();
SvMemoryStream aDestStrm;
aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize );
aZCodec.EndCompression();
aDestStrm.Seek( STREAM_SEEK_TO_END );
p_EscherBlibEntry->mnSize = aDestStrm.Tell();
pGraphicAry = (sal_uInt8*)aDestStrm.GetData();
if ( p_EscherBlibEntry->mnSize && pGraphicAry )
{
nExtra = eBlibType == WMF ? 0x42 : 0x32; // !EMF -> no change
p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40; // !EMF -> no change
rPicOutStrm << nInstance << (sal_uInt32)( p_EscherBlibEntry->mnSize + nExtra );
if ( eBlibType == WMF ) // !EMF -> no change
rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
rPicOutStrm.Write( p_EscherBlibEntry->mnIdentifier, 16 );
/*
##913##
For Word the stored size of the graphic is critical the
metafile boundaries must match the actual graphics
boundaries, and the width and height must be in EMU's
If you don't do it this way then objects edited in the
msoffice app may show strange behaviour as the size jumps
around, and the original size and scaling factor in word
will be a very strange figure
*/
sal_uInt32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width();
sal_uInt32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height();
sal_uInt32 nWidth, nHeight;
if ( pVisArea )
{
nWidth = pVisArea->Width * 360;
nHeight = pVisArea->Height * 360;
}
else
{
Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode));
nWidth = aPrefSize.Width() * 360;
nHeight = aPrefSize.Height() * 360;
}
rPicOutStrm << nUncompressedSize // WMFSize without FileHeader
<< (sal_Int32)0 // da die Originalgroesse des WMF's (ohne FileHeader)
<< (sal_Int32)0 // nicht mehr feststellbar ist, schreiben wir 10cm / x
<< nPrefWidth
<< nPrefHeight
<< nWidth
<< nHeight
<< p_EscherBlibEntry->mnSize
<< (sal_uInt16)0xfe00; // compression Flags
rPicOutStrm.Write( pGraphicAry, p_EscherBlibEntry->mnSize );
}
}
if ( nAtomSize )
{
sal_uInt32 nPos = rPicOutStrm.Tell();
rPicOutStrm.Seek( nAtomSize - 4 );
rPicOutStrm << (sal_uInt32)( nPos - nAtomSize );
rPicOutStrm.Seek( nPos );
}
nBlibId = ImplInsertBlib( p_EscherBlibEntry ), p_EscherBlibEntry = NULL;
}
}
if ( p_EscherBlibEntry )
delete p_EscherBlibEntry;
return nBlibId;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
struct EscherConnectorRule
{
sal_uInt32 nRuleId;
sal_uInt32 nShapeA; // SPID of shape A
sal_uInt32 nShapeB; // SPID of shape B
sal_uInt32 nShapeC; // SPID of connector shape
sal_uInt32 ncptiA; // Connection site Index of shape A
sal_uInt32 ncptiB; // Connection site Index of shape B
};
struct EscherShapeListEntry
{
::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > aXShape;
sal_uInt32 n_EscherId;
EscherShapeListEntry( const ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape > & rShape, sal_uInt32 nId ) :
aXShape ( rShape ),
n_EscherId ( nId ) {}
};
sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const Polygon& rPoly, const ::com::sun::star::awt::Point& rPoint )
{
sal_uInt16 nCount = rPoly.GetSize();
sal_uInt16 nClosest = nCount;
double fDist = (sal_uInt32)0xffffffff;
while( nCount-- )
{
double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() );
if ( fDistance < fDist )
{
nClosest = nCount;
fDist = fDistance;
}
}
return nClosest;
};
// ---------------------------------------------------------------------------------------------
// bei Rechtecken bei Ellipsen bei Polygonen
//
// nRule = 0 ->Top 0 ->Top nRule = Index auf ein (Poly)Polygon Punkt
// 1 ->Left 2 ->Left
// 2 ->Bottom 4 ->Bottom
// 3 ->Right 6 ->Right
sal_uInt32 EscherConnectorListEntry::GetConnectorRule( bool bFirst )
{
sal_uInt32 nRule = 0;
::com::sun::star::uno::Any aAny;
::com::sun::star::awt::Point aRefPoint( ( bFirst ) ? maPointA : maPointB );
::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >
aXShape( ( bFirst ) ? mXConnectToA : mXConnectToB );
String aString( (::rtl::OUString)aXShape->getShapeType() );
ByteString aType( aString, RTL_TEXTENCODING_UTF8 );
aType.Erase( 0, 13 ); // removing "com.sun.star."
sal_uInt16 nPos = aType.Search( "Shape" );
aType.Erase( nPos, 5 );
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
aPropertySet( aXShape, ::com::sun::star::uno::UNO_QUERY );
if ( aType == "drawing.PolyPolygon" || aType == "drawing.PolyLine" )
{
if ( aPropertySet.is() )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygon" ) ) ) )
{
::com::sun::star::drawing::PointSequenceSequence* pSourcePolyPolygon =
(::com::sun::star::drawing::PointSequenceSequence*)aAny.getValue();
sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength();
::com::sun::star::drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
if ( pOuterSequence )
{
sal_Int32 a, b, nIndex = 0;
sal_uInt32 nDistance = 0xffffffff;
for( a = 0; a < nOuterSequenceCount; a++ )
{
::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
if ( pInnerSequence )
{
::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
if ( pArray )
{
for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ )
{
sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
if ( nDist < nDistance )
{
nRule = nIndex;
nDistance = nDist;
}
}
}
}
}
}
}
}
}
else if ( ( aType == "drawing.OpenBezier" ) || ( aType == "drawing.OpenFreeHand" ) || ( aType == "drawing.PolyLinePath" )
|| ( aType == "drawing.ClosedBezier" ) || ( aType == "drawing.ClosedFreeHand" ) || ( aType == "drawing.PolyPolygonPath" ) )
{
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >
aPropertySet2( aXShape, ::com::sun::star::uno::UNO_QUERY );
if ( aPropertySet2.is() )
{
if ( EscherPropertyValueHelper::GetPropertyValue( aAny,
aPropertySet2, String( RTL_CONSTASCII_USTRINGPARAM( "PolyPolygonBezier" ) ) ) )
{
::com::sun::star::drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
(::com::sun::star::drawing::PolyPolygonBezierCoords*)aAny.getValue();
sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength();
// Zeiger auf innere sequences holen
::com::sun::star::drawing::PointSequence* pOuterSequence =
pSourcePolyPolygon->Coordinates.getArray();
::com::sun::star::drawing::FlagSequence* pOuterFlags =
pSourcePolyPolygon->Flags.getArray();
if ( pOuterSequence && pOuterFlags )
{
sal_Int32 a, b, nIndex = 0;
sal_uInt32 nDistance = 0xffffffff;
for ( a = 0; a < nOuterSequenceCount; a++ )
{
::com::sun::star::drawing::PointSequence* pInnerSequence = pOuterSequence++;
::com::sun::star::drawing::FlagSequence* pInnerFlags = pOuterFlags++;
if ( pInnerSequence && pInnerFlags )
{
::com::sun::star::awt::Point* pArray = pInnerSequence->getArray();
::com::sun::star::drawing::PolygonFlags* pFlags = pInnerFlags->getArray();
if ( pArray && pFlags )
{
for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ )
{
PolyFlags ePolyFlags = *( (PolyFlags*)pFlags++ );
if ( ePolyFlags == POLY_CONTROL )
continue;
sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y );
if ( nDist < nDistance )
{
nRule = nIndex;
nDistance = nDist;
}
nIndex++;
}
}
}
}
}
}
}
}
else
{
bool bRectangularConnection = true;
if ( aType == "drawing.Custom" )
{
SdrObjCustomShape* pCustoShape( dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape( aXShape ) ) );
if ( pCustoShape )
{
SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)pCustoShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
const rtl::OUString sPath( RTL_CONSTASCII_USTRINGPARAM( "Path" ) );
const rtl::OUString sType( RTL_CONSTASCII_USTRINGPARAM ( "Type" ) );
const rtl::OUString sGluePointType( RTL_CONSTASCII_USTRINGPARAM( "GluePointType" ) );
rtl::OUString sShapeType;
uno::Any* pType = rGeometryItem.GetPropertyValueByName( sType );
if ( pType )
*pType >>= sShapeType;
MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
uno::Any* pGluePointType = ((SdrCustomShapeGeometryItem&)rGeometryItem).GetPropertyValueByName( sPath, sGluePointType );
sal_Int16 nGluePointType = sal_Int16();
if ( !( pGluePointType &&
( *pGluePointType >>= nGluePointType ) ) )
nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::CUSTOM )
{
const sdr::glue::GluePointProvider& rProvider = pCustoShape->GetGluePointProvider();
const sdr::glue::GluePointVector aGluePointVector(rProvider.getUserGluePointVector());
if(aGluePointVector.size())
{
Polygon aPoly;
for(sal_uInt32 a(0); a < aGluePointVector.size(); a++)
{
const sdr::glue::GluePoint* pCandidate = aGluePointVector[a];
if(pCandidate)
{
const basegfx::B2DPoint aPt(pCustoShape->getSdrObjectTransformation() * pCandidate->getUnitPosition());
aPoly.Insert(POLY_APPEND, Point(basegfx::fround(aPt.getX()), basegfx::fround(aPt.getY())));
}
else
{
OSL_ENSURE(false, "Got sdr::glue::GluePointVector with empty entries (!)");
}
}
nRule = GetClosestPoint( aPoly, aRefPoint );
bRectangularConnection = false;
}
}
else if ( nGluePointType == com::sun::star::drawing::EnhancedCustomShapeGluePointType::SEGMENTS )
{
SdrPathObj* pPoly = dynamic_cast< SdrPathObj* >(pCustoShape->DoConvertToPolygonObject(true, true));
if ( pPoly )
{
sal_Int16 a, b, nIndex = 0;
sal_uInt32 nDistance = 0xffffffff;
// #i74631# use explicit constructor here. Also XPolyPolygon is not necessary,
// reducing to PolyPolygon
const PolyPolygon aPolyPoly(pPoly->getB2DPolyPolygonInObjectCoordinates());
for ( a = 0; a < aPolyPoly.Count(); a++ )
{
const Polygon& rPoly = aPolyPoly.GetObject( a );
for ( b = 0; b < rPoly.GetSize(); b++ )
{
if ( rPoly.GetFlags( b ) != POLY_NORMAL )
continue;
const Point& rPt = rPoly[ b ];
sal_uInt32 nDist = (sal_uInt32)hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() );
if ( nDist < nDistance )
{
nRule = nIndex;
nDistance = nDist;
}
nIndex++;
}
}
if ( nDistance != 0xffffffff )
bRectangularConnection = false;
}
}
}
}
if ( bRectangularConnection )
{
::com::sun::star::awt::Point aPoint( aXShape->getPosition() );
::com::sun::star::awt::Size aSize( aXShape->getSize() );
Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
Point aCenter( aRect.Center() );
Polygon aPoly( 4 );
aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() );
aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() );
aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() );
aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() );
sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny,
aPropertySet, String( RTL_CONSTASCII_USTRINGPARAM( "RotateAngle" ) ), true ) )
? *((sal_Int32*)aAny.getValue() )
: 0;
if ( nAngle )
aPoly.Rotate( aRect.TopLeft(), (sal_uInt16)( ( nAngle + 5 ) / 10 ) );
nRule = GetClosestPoint( aPoly, aRefPoint );
if ( aType == "drawing.Ellipse" )
nRule <<= 1; // In PPT hat eine Ellipse 8 M?glichkeiten sich zu connecten
}
}
return nRule;
}
EscherSolverContainer::~EscherSolverContainer()
{
void* pP;
for( pP = maShapeList.First(); pP; pP = maShapeList.Next() )
delete (EscherShapeListEntry*)pP;
for( pP = maConnectorList.First(); pP; pP = maConnectorList.Next() )
delete (EscherConnectorListEntry*)pP;
}
void EscherSolverContainer::AddShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape, sal_uInt32 nId )
{
maShapeList.Insert( new EscherShapeListEntry( rXShape, nId ), LIST_APPEND );
}
void EscherSolverContainer::AddConnector( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConnector,
const ::com::sun::star::awt::Point& rPA,
::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConA,
const ::com::sun::star::awt::Point& rPB,
::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rConB )
{
maConnectorList.Insert( new EscherConnectorListEntry( rConnector, rPA, rConA, rPB, rConB ), LIST_APPEND );
}
sal_uInt32 EscherSolverContainer::GetShapeId( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > & rXShape ) const
{
for ( EscherShapeListEntry* pPtr = (EscherShapeListEntry*)((List&)maShapeList).First();
pPtr; pPtr = (EscherShapeListEntry*)((List&)maShapeList).Next() )
{
if ( rXShape == pPtr->aXShape )
return ( pPtr->n_EscherId );
}
return 0;
}
void EscherSolverContainer::WriteSolver( SvStream& rStrm )
{
sal_uInt32 nCount = maConnectorList.Count();
if ( nCount )
{
sal_uInt32 nRecHdPos, nCurrentPos, nSize;
rStrm << (sal_uInt16)( ( nCount << 4 ) | 0xf ) // open an ESCHER_SolverContainer
<< (sal_uInt16)ESCHER_SolverContainer //
<< (sal_uInt32)0; //
nRecHdPos = rStrm.Tell() - 4;
EscherConnectorRule aConnectorRule;
aConnectorRule.nRuleId = 2;
for ( EscherConnectorListEntry* pPtr = (EscherConnectorListEntry*)maConnectorList.First();
pPtr; pPtr = (EscherConnectorListEntry*)maConnectorList.Next() )
{
aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff;
aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector );
aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA );
aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB );
if ( aConnectorRule.nShapeC )
{
if ( aConnectorRule.nShapeA )
aConnectorRule.ncptiA = pPtr->GetConnectorRule( true );
if ( aConnectorRule.nShapeB )
aConnectorRule.ncptiB = pPtr->GetConnectorRule( false );
}
rStrm << (sal_uInt32)( ( ESCHER_ConnectorRule << 16 ) | 1 ) // atom hd
<< (sal_uInt32)24 //
<< aConnectorRule.nRuleId
<< aConnectorRule.nShapeA
<< aConnectorRule.nShapeB
<< aConnectorRule.nShapeC
<< aConnectorRule.ncptiA
<< aConnectorRule.ncptiB;
aConnectorRule.nRuleId += 2;
}
nCurrentPos = rStrm.Tell(); // close the ESCHER_SolverContainer
nSize = ( nCurrentPos - nRecHdPos ) - 4;//
rStrm.Seek( nRecHdPos ); //
rStrm << nSize; //
rStrm.Seek( nCurrentPos ); //
}
}
// ---------------------------------------------------------------------------------------------
EscherExGlobal::EscherExGlobal( sal_uInt32 nGraphicProvFlags ) :
EscherGraphicProvider( nGraphicProvFlags ),
mpPicStrm( 0 ),
mbHasDggCont( false ),
mbPicStrmQueried( false )
{
}
EscherExGlobal::~EscherExGlobal()
{
}
sal_uInt32 EscherExGlobal::GenerateDrawingId()
{
// new drawing starts a new cluster in the cluster table (cluster identifiers are one-based)
sal_uInt32 nClusterId = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
// drawing identifiers are one-based
sal_uInt32 nDrawingId = static_cast< sal_uInt32 >( maDrawingInfos.size() + 1 );
// prepare new entries in the tables
maClusterTable.push_back( ClusterEntry( nDrawingId ) );
maDrawingInfos.push_back( DrawingInfo( nClusterId ) );
// return the new drawing identifier
return nDrawingId;
}
sal_uInt32 EscherExGlobal::GenerateShapeId( sal_uInt32 nDrawingId, bool bIsInSpgr )
{
// drawing identifier is one-based
size_t nDrawingIdx = nDrawingId - 1;
OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GenerateShapeId - invalid drawing ID" );
if( nDrawingIdx >= maDrawingInfos.size() )
return 0;
DrawingInfo& rDrawingInfo = maDrawingInfos[ nDrawingIdx ];
// cluster identifier in drawing info struct is one-based
ClusterEntry* pClusterEntry = &maClusterTable[ rDrawingInfo.mnClusterId - 1 ];
// check cluster overflow, create new cluster entry
if( pClusterEntry->mnNextShapeId == DFF_DGG_CLUSTER_SIZE )
{
// start a new cluster in the cluster table
maClusterTable.push_back( ClusterEntry( nDrawingId ) );
pClusterEntry = &maClusterTable.back();
// new size of maClusterTable is equal to one-based identifier of the new cluster
rDrawingInfo.mnClusterId = static_cast< sal_uInt32 >( maClusterTable.size() );
}
// build shape identifier from cluster identifier and next free cluster shape identifier
rDrawingInfo.mnLastShapeId = static_cast< sal_uInt32 >( rDrawingInfo.mnClusterId * DFF_DGG_CLUSTER_SIZE + pClusterEntry->mnNextShapeId );
// update free shape identifier in cluster entry
++pClusterEntry->mnNextShapeId;
/* Old code has counted the shapes only, if we are in a SPGRCONTAINER. Is
this really intended? Maybe it's always true... */
if( bIsInSpgr )
++rDrawingInfo.mnShapeCount;
// return the new shape identifier
return rDrawingInfo.mnLastShapeId;
}
sal_uInt32 EscherExGlobal::GetDrawingShapeCount( sal_uInt32 nDrawingId ) const
{
size_t nDrawingIdx = nDrawingId - 1;
OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetDrawingShapeCount - invalid drawing ID" );
return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnShapeCount : 0;
}
sal_uInt32 EscherExGlobal::GetLastShapeId( sal_uInt32 nDrawingId ) const
{
size_t nDrawingIdx = nDrawingId - 1;
OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetLastShapeId - invalid drawing ID" );
return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnLastShapeId : 0;
}
sal_uInt32 EscherExGlobal::GetDggAtomSize() const
{
// 8 bytes header, 16 bytes fixed DGG data, 8 bytes for each cluster
return static_cast< sal_uInt32 >( 24 + 8 * maClusterTable.size() );
}
void EscherExGlobal::WriteDggAtom( SvStream& rStrm ) const
{
sal_uInt32 nDggSize = GetDggAtomSize();
// write the DGG record header (do not include the 8 bytes of the header in the data size)
rStrm << static_cast< sal_uInt32 >( ESCHER_Dgg << 16 ) << static_cast< sal_uInt32 >( nDggSize - 8 );
// claculate and write the fixed DGG data
sal_uInt32 nShapeCount = 0;
sal_uInt32 nLastShapeId = 0;
for( DrawingInfoVector::const_iterator aIt = maDrawingInfos.begin(), aEnd = maDrawingInfos.end(); aIt != aEnd; ++aIt )
{
nShapeCount += aIt->mnShapeCount;
nLastShapeId = ::std::max( nLastShapeId, aIt->mnLastShapeId );
}
// the non-existing cluster with index #0 is counted too
sal_uInt32 nClusterCount = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
sal_uInt32 nDrawingCount = static_cast< sal_uInt32 >( maDrawingInfos.size() );
rStrm << nLastShapeId << nClusterCount << nShapeCount << nDrawingCount;
// write the cluster table
for( ClusterTable::const_iterator aIt = maClusterTable.begin(), aEnd = maClusterTable.end(); aIt != aEnd; ++aIt )
rStrm << aIt->mnDrawingId << aIt->mnNextShapeId;
}
SvStream* EscherExGlobal::QueryPictureStream()
{
if( !mbPicStrmQueried )
{
mpPicStrm = ImplQueryPictureStream();
mbPicStrmQueried = true;
}
return mpPicStrm;
}
SvStream* EscherExGlobal::ImplQueryPictureStream()
{
return 0;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
EscherEx::EscherEx( const EscherExGlobalRef& rxGlobal, SvStream& rOutStrm ) :
mxGlobal ( rxGlobal ),
mpOutStrm ( &rOutStrm ),
mnGroupLevel ( 0 ),
mnHellLayerId ( USHRT_MAX ),
mbEscherSpgr ( false ),
mbEscherDg ( false )
{
mnStrmStartOfs = mpOutStrm->Tell();
mpImplEscherExSdr.reset( new ImplEscherExSdr( *this ) );
}
EscherEx::~EscherEx()
{
}
// ---------------------------------------------------------------------------------------------
void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ )
{
if ( mxGlobal->HasDggContainer() )
{
// store the current stream position at ESCHER_Persist_CurrentPosition key
PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() );
if ( DoSeek( ESCHER_Persist_Dgg ) )
{
/* The DGG record is still not written. ESCHER_Persist_Dgg seeks
to the place where the complete record has to be inserted. */
InsertAtCurrentPos( mxGlobal->GetDggAtomSize(), false );
mxGlobal->WriteDggAtom( *mpOutStrm );
if ( mxGlobal->HasGraphics() )
{
/* Calculate the total size of the BSTORECONTAINER including
all BSE records containing the picture data contained in
the passed in pPicStreamMergeBSE. */
sal_uInt32 nBSCSize = mxGlobal->GetBlibStoreContainerSize( pPicStreamMergeBSE );
if ( nBSCSize > 0 )
{
InsertAtCurrentPos( nBSCSize, false );
mxGlobal->WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE );
}
}
/* Forget the stream position stored for the DGG which is invalid
after the call to InsertAtCurrentPos() anyway. */
PtDelete( ESCHER_Persist_Dgg );
}
// seek to initial position (may be different due to inserted DGG and BLIPs)
mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) );
}
}
// ---------------------------------------------------------------------------------------------
void EscherEx::InsertAtCurrentPos( sal_uInt32 nBytes, bool bExpandEndOfAtom )
{
sal_uInt32 nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell();
sal_uInt8* pBuf;
// Persist table anpassen
for ( void* pPtr = maPersistTable.First(); pPtr; pPtr = maPersistTable.Next() )
{
sal_uInt32 nOfs = ((EscherPersistEntry*)pPtr)->mnOffset;
if ( nOfs >= nCurPos )
((EscherPersistEntry*)pPtr)->mnOffset += nBytes;
}
// container und atom sizes anpassen
mpOutStrm->Seek( mnStrmStartOfs );
while ( mpOutStrm->Tell() < nCurPos )
{
*mpOutStrm >> nType >> nSize;
sal_uInt32 nEndOfRecord = mpOutStrm->Tell() + nSize;
bool bContainer = (nType & 0x0F) == 0x0F;
/* Expand the record, if the insertion position is inside, or if the
position is at the end of a container (expands always), or at the
end of an atom and bExpandEndOfAtom is set. */
if ( (nCurPos < nEndOfRecord) || ((nCurPos == nEndOfRecord) && (bContainer || bExpandEndOfAtom)) )
{
mpOutStrm->SeekRel( -4 );
*mpOutStrm << (sal_uInt32)( nSize + nBytes );
if ( !bContainer )
mpOutStrm->SeekRel( nSize );
}
else
mpOutStrm->SeekRel( nSize );
}
std::vector< sal_uInt32 >::iterator aIter( mOffsets.begin() );
std::vector< sal_uInt32 >::iterator aEnd( mOffsets.end() );
while( aIter != aEnd )
{
if ( *aIter > nCurPos )
*aIter += nBytes;
aIter++;
}
mpOutStrm->Seek( STREAM_SEEK_TO_END );
nSource = mpOutStrm->Tell();
nToCopy = nSource - nCurPos; // Stream um nBytes vergroessern
pBuf = new sal_uInt8[ 0x40000 ]; // 256KB Buffer
while ( nToCopy )
{
nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
nToCopy -= nBufSize;
nSource -= nBufSize;
mpOutStrm->Seek( nSource );
mpOutStrm->Read( pBuf, nBufSize );
mpOutStrm->Seek( nSource + nBytes );
mpOutStrm->Write( pBuf, nBufSize );
}
delete[] pBuf;
mpOutStrm->Seek( nCurPos );
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::SeekBehindRecHeader( sal_uInt16 nRecType )
{
sal_uInt32 nOldPos, nStreamEnd, nType, nSize;
nOldPos = mpOutStrm->Tell();
nStreamEnd = mpOutStrm->Seek( STREAM_SEEK_TO_END );
mpOutStrm->Seek( nOldPos );
while ( mpOutStrm->Tell() < nStreamEnd )
{
*mpOutStrm >> nType >> nSize;
if ( ( nType >> 16 ) == nRecType )
return true;
if ( ( nType & 0xf ) != 0xf )
mpOutStrm->SeekRel( nSize );
}
mpOutStrm->Seek( nOldPos );
return false;
}
// ---------------------------------------------------------------------------------------------
void EscherEx::InsertPersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
{
PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset );
}
void EscherEx::ReplacePersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
{
PtReplace( ESCHER_Persist_PrivateEntry | nKey, nOffset );
}
sal_uInt32 EscherEx::GetPersistOffset( sal_uInt32 nKey )
{
return PtGetOffsetByID( ESCHER_Persist_PrivateEntry | nKey );
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::DoSeek( sal_uInt32 nKey )
{
sal_uInt32 nPos = PtGetOffsetByID( nKey );
if ( nPos )
mpOutStrm->Seek( nPos );
else
{
if (! PtIsID( nKey ) )
return false;
mpOutStrm->Seek( 0 );
}
return true;
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::SeekToPersistOffset( sal_uInt32 nKey )
{
return DoSeek( ESCHER_Persist_PrivateEntry | nKey );
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::InsertAtPersistOffset( sal_uInt32 nKey, sal_uInt32 nValue )
{
sal_uInt32 nOldPos = mpOutStrm->Tell();
bool bRetValue(SeekToPersistOffset(nKey));
if ( bRetValue )
{
*mpOutStrm << nValue;
mpOutStrm->Seek( nOldPos );
}
return bRetValue;
}
// ---------------------------------------------------------------------------------------------
void EscherEx::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
{
*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | 0xf ) << nEscherContainer << (sal_uInt32)0;
mOffsets.push_back( mpOutStrm->Tell() - 4 );
mRecTypes.push_back( nEscherContainer );
switch( nEscherContainer )
{
case ESCHER_DggContainer :
{
mxGlobal->SetDggContainer();
mnCurrentDg = 0;
/* Remember the current position as start position of the DGG
record and BSTORECONTAINER, but do not write them actually.
This will be done later in Flush() when the number of drawings,
the size and contents of the FIDCL cluster table, and the size
of the BLIP container are known. */
PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() );
}
break;
case ESCHER_DgContainer :
{
if ( mxGlobal->HasDggContainer() )
{
if ( !mbEscherDg )
{
mbEscherDg = true;
mnCurrentDg = mxGlobal->GenerateDrawingId();
AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
*mpOutStrm << (sal_uInt32)0 // The number of shapes in this drawing
<< (sal_uInt32)0; // The last MSOSPID given to an SP in this DG
}
}
}
break;
case ESCHER_SpgrContainer :
{
if ( mbEscherDg )
{
mbEscherSpgr = true;
}
}
break;
case ESCHER_SpContainer :
{
}
break;
default:
break;
}
}
// ---------------------------------------------------------------------------------------------
void EscherEx::CloseContainer()
{
sal_uInt32 nSize, nPos = mpOutStrm->Tell();
nSize = ( nPos - mOffsets.back() ) - 4;
mpOutStrm->Seek( mOffsets.back() );
*mpOutStrm << nSize;
switch( mRecTypes.back() )
{
case ESCHER_DgContainer :
{
if ( mbEscherDg )
{
mbEscherDg = false;
if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
*mpOutStrm << mxGlobal->GetDrawingShapeCount( mnCurrentDg ) << mxGlobal->GetLastShapeId( mnCurrentDg );
}
}
break;
case ESCHER_SpgrContainer :
{
if ( mbEscherSpgr )
{
mbEscherSpgr = false;
}
}
break;
default:
break;
}
mOffsets.pop_back();
mRecTypes.pop_back();
mpOutStrm->Seek( nPos );
}
// ---------------------------------------------------------------------------------------------
void EscherEx::BeginAtom()
{
mnCountOfs = mpOutStrm->Tell();
*mpOutStrm << (sal_uInt32)0 << (sal_uInt32)0; // record header wird spaeter geschrieben
}
// ---------------------------------------------------------------------------------------------
void EscherEx::EndAtom( sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
{
sal_uInt32 nOldPos = mpOutStrm->Tell();
mpOutStrm->Seek( mnCountOfs );
sal_uInt32 nSize = nOldPos - mnCountOfs;
*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << (sal_uInt32)( nSize - 8 );
mpOutStrm->Seek( nOldPos );
}
// ---------------------------------------------------------------------------------------------
void EscherEx::AddAtom( sal_uInt32 nAtomSize, sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
{
*mpOutStrm << (sal_uInt16)( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ) << nRecType << nAtomSize;
}
// ---------------------------------------------------------------------------------------------
void EscherEx::AddChildAnchor(
const basegfx::B2DRange& rObjectRange)
{
AddAtom( 16, ESCHER_ChildAnchor );
*mpOutStrm << (sal_Int32)basegfx::fround(rObjectRange.getMinX())
<< (sal_Int32)basegfx::fround(rObjectRange.getMinY())
<< (sal_Int32)basegfx::fround(rObjectRange.getMaxX())
<< (sal_Int32)basegfx::fround(rObjectRange.getMaxY());
}
// ---------------------------------------------------------------------------------------------
void EscherEx::AddClientAnchor(
const basegfx::B2DRange& rObjectRange)
{
AddAtom( 8, ESCHER_ClientAnchor );
// Askes SJ, here it is CORRECT to first write Y, then X (!)
// Do NOT change this, it's NOT a typo (!)
*mpOutStrm << (sal_Int16)basegfx::fround(rObjectRange.getMinY())
<< (sal_Int16)basegfx::fround(rObjectRange.getMinX())
<< (sal_Int16)basegfx::fround(rObjectRange.getMaxX())
<< (sal_Int16)basegfx::fround(rObjectRange.getMaxY());
}
// ---------------------------------------------------------------------------------------------
EscherExHostAppData* EscherEx::EnterAdditionalTextGroup()
{
return NULL;
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherEx::EnterGroup(
const String& rShapeName,
const basegfx::B2DRange* pObjectRange)
{
basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
if(pObjectRange)
{
aObjectRange = *pObjectRange;
}
OpenContainer( ESCHER_SpgrContainer );
OpenContainer( ESCHER_SpContainer );
AddAtom( 16, ESCHER_Spgr, 1 );
PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel,
mpOutStrm->Tell() );
*mpOutStrm << (sal_Int32)basegfx::fround(aObjectRange.getMinX()) // Bounding box fuer die Gruppierten shapes an die sie attached werden
<< (sal_Int32)basegfx::fround(aObjectRange.getMinY())
<< (sal_Int32)basegfx::fround(aObjectRange.getMaxX())
<< (sal_Int32)basegfx::fround(aObjectRange.getMaxY());
sal_uInt32 nShapeId = GenerateShapeId();
if ( !mnGroupLevel )
AddShape( ESCHER_ShpInst_Min, 5, nShapeId ); // Flags: Group | Patriarch
else
{
AddShape( ESCHER_ShpInst_Min, 0x201, nShapeId ); // Flags: Group | HaveAnchor
EscherPropertyContainer aPropOpt;
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 );
aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
// #i51348# shape name
if( rShapeName.Len() > 0 )
aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName );
Commit( aPropOpt, aObjectRange );
if ( mnGroupLevel > 1 )
AddChildAnchor( aObjectRange );
EscherExHostAppData* pAppData = mpImplEscherExSdr->ImplGetHostData();
if( pAppData )
{
if ( mnGroupLevel <= 1 )
pAppData->WriteClientAnchor( *this, aObjectRange );
pAppData->WriteClientData( *this );
}
}
CloseContainer(); // ESCHER_SpContainer
mnGroupLevel++;
return nShapeId;
}
sal_uInt32 EscherEx::EnterGroup(
const basegfx::B2DRange* pObjectRange)
{
return EnterGroup( String::EmptyString(), pObjectRange );
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::SetGroupSnapPositionAndScale(
sal_uInt32 nGroupLevel,
const basegfx::B2DRange& rObjectRange)
{
bool bRetValue(false);
if ( nGroupLevel )
{
sal_uInt32 nCurrentPos = mpOutStrm->Tell();
if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) )
{
*mpOutStrm << (sal_Int32)basegfx::fround(rObjectRange.getMinX()) // Bounding box fuer die Gruppierten shapes an die sie attached werden
<< (sal_Int32)basegfx::fround(rObjectRange.getMinY())
<< (sal_Int32)basegfx::fround(rObjectRange.getMaxX())
<< (sal_Int32)basegfx::fround(rObjectRange.getMaxY());
mpOutStrm->Seek( nCurrentPos );
}
}
return bRetValue;
}
// ---------------------------------------------------------------------------------------------
bool EscherEx::SetGroupLogicPositionAndScale(
sal_uInt32 nGroupLevel,
const basegfx::B2DRange& rObjectRange)
{
bool bRetValue(false);
if ( nGroupLevel )
{
sal_uInt32 nCurrentPos = mpOutStrm->Tell();
if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) )
{
*mpOutStrm << (sal_Int16)basegfx::fround(rObjectRange.getMinX())
<< (sal_Int16)basegfx::fround(rObjectRange.getMinY())
<< (sal_Int16)basegfx::fround(rObjectRange.getMaxX())
<< (sal_Int16)basegfx::fround(rObjectRange.getMaxY());
mpOutStrm->Seek( nCurrentPos );
}
}
return bRetValue;
}
// ---------------------------------------------------------------------------------------------
void EscherEx::LeaveGroup()
{
--mnGroupLevel;
PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel );
PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel );
CloseContainer();
}
// ---------------------------------------------------------------------------------------------
void EscherEx::AddShape( sal_uInt32 nShpInstance, sal_uInt32 nFlags, sal_uInt32 nShapeID )
{
AddAtom( 8, ESCHER_Sp, 2, nShpInstance );
if ( !nShapeID )
nShapeID = GenerateShapeId();
if ( nFlags ^ 1 ) // is this a group shape ?
{ // if not
if ( mnGroupLevel > 1 )
nFlags |= 2; // this not a topmost shape
}
*mpOutStrm << nShapeID << nFlags;
}
// ---------------------------------------------------------------------------------------------
void EscherEx::Commit(
EscherPropertyContainer& rProps,
const basegfx::B2DRange& /*rObjectRange*/)
{
rProps.Commit( GetStream() );
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherEx::GetColor( const sal_uInt32 nSOColor, bool bSwap )
{
if ( bSwap )
{
sal_uInt32 nColor = nSOColor & 0xff00; // GRUEN
nColor |= (sal_uInt8)( nSOColor ) << 16; // ROT
nColor |= (sal_uInt8)( nSOColor >> 16 ); // BLAU
return nColor;
}
else
return nSOColor & 0xffffff;
}
// ---------------------------------------------------------------------------------------------
sal_uInt32 EscherEx::GetColor( const Color& rSOColor, bool bSwap )
{
sal_uInt32 nColor = ( rSOColor.GetRed() << 16 );
nColor |= ( rSOColor.GetGreen() << 8 );
nColor |= rSOColor.GetBlue();
if ( !bSwap )
nColor = GetColor( nColor, true );
return nColor;
}
// ---------------------------------------------------------------------------------------------