406 lines
17 KiB
C++
406 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "oox/drawingml/customshapeproperties.hxx"
|
|
#include "oox/helper/helper.hxx"
|
|
#include "oox/helper/propertymap.hxx"
|
|
#include "oox/helper/propertyset.hxx"
|
|
#include "oox/token/tokenmap.hxx"
|
|
#include <com/sun/star/awt/Rectangle.hpp>
|
|
#include <com/sun/star/awt/Size.hpp>
|
|
#include <com/sun/star/beans/XMultiPropertySet.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/graphic/XGraphicTransformer.hpp>
|
|
#include <com/sun/star/drawing/XShape.hpp>
|
|
#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
|
|
#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
|
|
|
|
using rtl::OUString;
|
|
using namespace ::oox::core;
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::graphic;
|
|
using namespace ::com::sun::star::drawing;
|
|
|
|
# define USS(x) OUStringToOString( x, RTL_TEXTENCODING_UTF8 ).getStr()
|
|
|
|
namespace oox { namespace drawingml {
|
|
|
|
CustomShapeProperties::CustomShapeProperties()
|
|
: mnShapePresetType ( -1 )
|
|
, mbMirroredX ( sal_False )
|
|
, mbMirroredY ( sal_False )
|
|
, mnArcNum ( 0 )
|
|
{
|
|
}
|
|
CustomShapeProperties::~CustomShapeProperties()
|
|
{
|
|
}
|
|
|
|
::rtl::OUString CustomShapeProperties::getShapePresetTypeName() const
|
|
{
|
|
return StaticTokenMap::get().getUnicodeTokenName( mnShapePresetType );
|
|
}
|
|
|
|
sal_Int32 CustomShapeProperties::SetCustomShapeGuideValue( std::vector< CustomShapeGuide >& rGuideList, const CustomShapeGuide& rGuide )
|
|
{
|
|
sal_uInt32 nIndex = 0;
|
|
for( ; nIndex < rGuideList.size(); nIndex++ )
|
|
{
|
|
if ( rGuideList[ nIndex ].maName == rGuide.maName )
|
|
break;
|
|
}
|
|
if ( nIndex == rGuideList.size() )
|
|
rGuideList.push_back( rGuide );
|
|
return static_cast< sal_Int32 >( nIndex );
|
|
}
|
|
|
|
// returns the index into the guidelist for a given formula name,
|
|
// if the return value is < 0 then the guide value could not be found
|
|
sal_Int32 CustomShapeProperties::GetCustomShapeGuideValue( const std::vector< CustomShapeGuide >& rGuideList, const rtl::OUString& rFormulaName )
|
|
{
|
|
// traverse the list from the end, because guide names can be reused
|
|
// and current is the last one
|
|
// see a1 guide in gear6 custom shape preset as example
|
|
sal_Int32 nIndex = static_cast< sal_Int32 >( rGuideList.size() ) - 1;
|
|
for( ; nIndex >= 0; nIndex-- )
|
|
{
|
|
if ( rGuideList[ nIndex ].maName == rFormulaName )
|
|
break;
|
|
}
|
|
|
|
return nIndex;
|
|
}
|
|
|
|
CustomShapeProperties::PresetsMap CustomShapeProperties::maPresetsMap;
|
|
|
|
static OUString GetConnectorShapeType( sal_Int32 nType )
|
|
{
|
|
OSL_TRACE("GetConnectorShapeType preset: %d %d", nType, XML_straightConnector1);
|
|
|
|
OUString sType;
|
|
switch( nType )
|
|
{
|
|
case XML_straightConnector1: {
|
|
static const OUString sStraightConnector1 = CREATE_OUSTRING( "mso-spt32" );
|
|
sType = sStraightConnector1;
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
return sType;
|
|
}
|
|
|
|
|
|
void CustomShapeProperties::pushToPropSet( const ::oox::core::FilterBase& /* rFilterBase */,
|
|
const Reference < XPropertySet >& xPropSet, const Reference < XShape > & xShape )
|
|
{
|
|
if ( mnShapePresetType >= 0 )
|
|
{
|
|
OSL_TRACE("preset: %d", mnShapePresetType);
|
|
|
|
if (maPresetsMap.empty())
|
|
initializePresetsMap();
|
|
|
|
PropertyMap aPropertyMap;
|
|
PropertySet aPropSet( xPropSet );
|
|
|
|
OUString sConnectorShapeType = GetConnectorShapeType( mnShapePresetType );
|
|
|
|
if (sConnectorShapeType.getLength() > 0)
|
|
{
|
|
OSL_TRACE("connector shape: %s (%d)", USS(sConnectorShapeType), mnShapePresetType);
|
|
//const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY );
|
|
Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY );
|
|
if( xDefaulter.is() ) {
|
|
xDefaulter->createCustomShapeDefaults( sConnectorShapeType );
|
|
aPropertyMap[ PROP_Type ] <<= Any( sConnectorShapeType );
|
|
}
|
|
}
|
|
else if (maPresetsMap.find(mnShapePresetType) != maPresetsMap.end())
|
|
{
|
|
OSL_TRACE("found property map for preset: %s (%d)", USS(getShapePresetTypeName()), mnShapePresetType);
|
|
|
|
CustomShapeProvider *pProvider = maPresetsMap[ mnShapePresetType ];
|
|
if (pProvider)
|
|
aPropertyMap = pProvider->getProperties();
|
|
#ifdef DEBUG
|
|
aPropertyMap.dumpCode();
|
|
#endif
|
|
}
|
|
|
|
aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX );
|
|
aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY );
|
|
aPropertyMap[ PROP_TextPreRotateAngle ] <<= Any( mnTextRotateAngle );
|
|
Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence();
|
|
aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq );
|
|
|
|
if ( maAdjustmentGuideList.size() )
|
|
{
|
|
const OUString sType = CREATE_OUSTRING( "Type" );
|
|
const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) );
|
|
uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry );
|
|
uno::Sequence< beans::PropertyValue > aGeoPropSeq;
|
|
if ( aGeoPropSet >>= aGeoPropSeq )
|
|
{
|
|
sal_Int32 i, nCount = aGeoPropSeq.getLength();
|
|
for ( i = 0; i < nCount; i++ )
|
|
{
|
|
const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) );
|
|
if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) )
|
|
{
|
|
uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
|
|
if ( aGeoPropSeq[ i ].Value >>= aAdjustmentSeq )
|
|
{
|
|
std::vector< CustomShapeGuide >::const_iterator aIter( maAdjustmentGuideList.begin() );
|
|
while( aIter != maAdjustmentGuideList.end() )
|
|
{
|
|
if ( (*aIter).maName.getLength() > 3 )
|
|
{
|
|
sal_Int32 nAdjustmentIndex = (*aIter).maName.copy( 3 ).toInt32() - 1;
|
|
if ( ( nAdjustmentIndex >= 0 ) && ( nAdjustmentIndex < aAdjustmentSeq.getLength() ) )
|
|
{
|
|
EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
|
|
aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32();
|
|
aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
|
|
aAdjustmentSeq[ nAdjustmentIndex ] = aAdjustmentVal;
|
|
}
|
|
} else if ( aAdjustmentSeq.getLength() > 0 ) {
|
|
EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
|
|
aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32();
|
|
aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
|
|
aAdjustmentSeq[ 0 ] = aAdjustmentVal;
|
|
}
|
|
aIter++;
|
|
}
|
|
aGeoPropSeq[ i ].Value <<= aAdjustmentSeq;
|
|
xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) );
|
|
}
|
|
}
|
|
else if ( aGeoPropSeq[ i ].Name.equals( sType ) )
|
|
{
|
|
if ( sConnectorShapeType.getLength() > 0 )
|
|
aGeoPropSeq[ i ].Value <<= sConnectorShapeType;
|
|
else
|
|
aGeoPropSeq[ i ].Value <<= CREATE_OUSTRING( "ooxml-CustomShape" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 i;
|
|
PropertyMap aPropertyMap;
|
|
aPropertyMap[ PROP_Type ] <<= CREATE_OUSTRING( "ooxml-non-primitive" );
|
|
aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX );
|
|
aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY );
|
|
awt::Size aSize;
|
|
awt::Rectangle aViewBox( 0, 0, aSize.Width * 360, aSize.Height * 360 );
|
|
aPropertyMap[ PROP_ViewBox ] <<= aViewBox;
|
|
|
|
Sequence< EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( maAdjustmentGuideList.size() );
|
|
for ( i = 0; i < maAdjustmentGuideList.size(); i++ )
|
|
{
|
|
EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
|
|
aAdjustmentVal.Value <<= maAdjustmentGuideList[ i ].maFormula.toInt32();
|
|
aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
|
|
aAdjustmentValues[ i ] = aAdjustmentVal;
|
|
}
|
|
aPropertyMap[ PROP_AdjustmentValues ] <<= aAdjustmentValues;
|
|
|
|
PropertyMap aPath;
|
|
|
|
Sequence< EnhancedCustomShapeSegment > aSegments( maSegments.size() );
|
|
for ( i = 0; i < maSegments.size(); i++ )
|
|
aSegments[ i ] = maSegments[ i ];
|
|
aPath[ PROP_Segments ] <<= aSegments;
|
|
|
|
if ( maTextRect.has() ) {
|
|
Sequence< EnhancedCustomShapeTextFrame > aTextFrames(1);
|
|
aTextFrames[0].TopLeft.First = maTextRect.get().l;
|
|
aTextFrames[0].TopLeft.Second = maTextRect.get().t;
|
|
aTextFrames[0].BottomRight.First = maTextRect.get().r;
|
|
aTextFrames[0].BottomRight.Second = maTextRect.get().b;
|
|
aPath[ PROP_TextFrames ] <<= aTextFrames;
|
|
}
|
|
|
|
sal_uInt32 j, k, nParameterPairs = 0;
|
|
for ( i = 0; i < maPath2DList.size(); i++ )
|
|
nParameterPairs += maPath2DList[ i ].parameter.size();
|
|
|
|
Sequence< EnhancedCustomShapeParameterPair > aParameterPairs( nParameterPairs );
|
|
for ( i = 0, k = 0; i < maPath2DList.size(); i++ )
|
|
for ( j = 0; j < maPath2DList[ i ].parameter.size(); j++ )
|
|
aParameterPairs[ k++ ] = maPath2DList[ i ].parameter[ j ];
|
|
aPath[ PROP_Coordinates ] <<= aParameterPairs;
|
|
|
|
if ( maPath2DList.size() )
|
|
{
|
|
sal_Bool bAllZero = sal_True;
|
|
for ( i=0; i < maPath2DList.size(); i++ )
|
|
{
|
|
if ( maPath2DList[i].w || maPath2DList[i].h ) {
|
|
bAllZero = sal_False;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !bAllZero ) {
|
|
Sequence< awt::Size > aSubViewSize( maPath2DList.size() );
|
|
for ( i=0; i < maPath2DList.size(); i++ )
|
|
{
|
|
aSubViewSize[i].Width = static_cast< sal_Int32 >( maPath2DList[i].w );
|
|
aSubViewSize[i].Height = static_cast< sal_Int32 >( maPath2DList[i].h );
|
|
OSL_TRACE("set subpath %d size: %d x %d", i, maPath2DList[i].w, maPath2DList[i].h);
|
|
}
|
|
aPath[ PROP_SubViewSize ] <<= aSubViewSize;
|
|
}
|
|
}
|
|
|
|
Sequence< PropertyValue > aPathSequence = aPath.makePropertyValueSequence();
|
|
aPropertyMap[ PROP_Path ] <<= aPathSequence;
|
|
|
|
Sequence< rtl::OUString > aEquations( maGuideList.size() );
|
|
for ( i = 0; i < maGuideList.size(); i++ )
|
|
aEquations[ i ] = maGuideList[ i ].maFormula;
|
|
aPropertyMap[ PROP_Equations ] <<= aEquations;
|
|
|
|
Sequence< PropertyValues > aHandles( maAdjustHandleList.size() );
|
|
for ( i = 0; i < maAdjustHandleList.size(); i++ )
|
|
{
|
|
PropertyMap aHandle;
|
|
// maAdjustmentHandle[ i ].gdRef1 ... maAdjustmentHandle[ i ].gdRef2 ... :(
|
|
// gdRef1 && gdRef2 -> we do not offer such reference, so it is difficult
|
|
// to determine the correct adjustment handle that should be updated with the adjustment
|
|
// position. here is the solution: the adjustment value that is used within the position
|
|
// has to be updated, in case the position is a formula the first usage of a
|
|
// adjustment value is decisive
|
|
if ( maAdjustHandleList[ i ].polar )
|
|
{
|
|
aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos;
|
|
if ( maAdjustHandleList[ i ].min1.has() )
|
|
aHandle[ PROP_RadiusRangeMinimum ] <<= maAdjustHandleList[ i ].min1.get();
|
|
if ( maAdjustHandleList[ i ].max1.has() )
|
|
aHandle[ PROP_RadiusRangeMaximum ] <<= maAdjustHandleList[ i ].max1.get();
|
|
|
|
/* TODO: AngleMin & AngleMax
|
|
if ( maAdjustHandleList[ i ].min2.has() )
|
|
aHandle[ PROP_ ] = maAdjustHandleList[ i ].min2.get();
|
|
if ( maAdjustHandleList[ i ].max2.has() )
|
|
aHandle[ PROP_ ] = maAdjustHandleList[ i ].max2.get();
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos;
|
|
if ( maAdjustHandleList[ i ].gdRef1.has() )
|
|
{
|
|
// TODO: PROP_RefX and PROP_RefY are not yet part of our file format,
|
|
// so the handles will not work after save/reload
|
|
sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef1.get() );
|
|
if ( nIndex >= 0 )
|
|
aHandle[ PROP_RefX ] <<= nIndex;
|
|
}
|
|
if ( maAdjustHandleList[ i ].gdRef2.has() )
|
|
{
|
|
sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef2.get() );
|
|
if ( nIndex >= 0 )
|
|
aHandle[ PROP_RefY ] <<= nIndex;
|
|
}
|
|
if ( maAdjustHandleList[ i ].min1.has() )
|
|
aHandle[ PROP_RangeXMinimum ] <<= maAdjustHandleList[ i ].min1.get();
|
|
if ( maAdjustHandleList[ i ].max1.has() )
|
|
aHandle[ PROP_RangeXMaximum ] <<= maAdjustHandleList[ i ].max1.get();
|
|
if ( maAdjustHandleList[ i ].min2.has() )
|
|
aHandle[ PROP_RangeYMinimum ] <<= maAdjustHandleList[ i ].min2.get();
|
|
if ( maAdjustHandleList[ i ].max2.has() )
|
|
aHandle[ PROP_RangeYMaximum ] <<= maAdjustHandleList[ i ].max2.get();
|
|
}
|
|
aHandles[ i ] = aHandle.makePropertyValueSequence();
|
|
}
|
|
aPropertyMap[ PROP_Handles ] <<= aHandles;
|
|
|
|
#ifdef DEBUG
|
|
OSL_TRACE("==cscode== begin");
|
|
aPropertyMap.dumpCode();
|
|
OSL_TRACE("==cscode== end");
|
|
#endif
|
|
// converting the vector to a sequence
|
|
Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence();
|
|
PropertySet aPropSet( xPropSet );
|
|
aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq );
|
|
}
|
|
}
|
|
|
|
Any CustomShapeProvider::createStringSequence( size_t nStrings, const char **pStrings )
|
|
{
|
|
Sequence< OUString > aStringSequence( nStrings );
|
|
for (size_t i = 0; i < nStrings; i++)
|
|
aStringSequence[i] = ::rtl::OUString::intern(
|
|
pStrings[i], strlen( pStrings[i] ),
|
|
RTL_TEXTENCODING_ASCII_US );
|
|
return makeAny( aStringSequence );
|
|
}
|
|
|
|
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeSegment >
|
|
CustomShapeProvider::createSegmentSequence( size_t nElems, const sal_uInt16 *pValues )
|
|
{
|
|
Sequence< EnhancedCustomShapeSegment > aSequence( (nElems + 1) / 2 );
|
|
for (size_t i = 0, j = 0; i < nElems / 2; i++)
|
|
{
|
|
aSequence[i].Command = pValues[j++];
|
|
aSequence[i].Count = pValues[j++];
|
|
}
|
|
return aSequence;
|
|
}
|
|
|
|
com::sun::star::drawing::EnhancedCustomShapeParameterPair
|
|
CustomShapeProvider::createParameterPair( const ParameterPairData *pData )
|
|
{
|
|
EnhancedCustomShapeParameterPair aParameterPair;
|
|
aParameterPair.First.Type = pData->nFirstType;
|
|
aParameterPair.First.Value = makeAny(pData->nFirstValue);
|
|
aParameterPair.Second.Type = pData->nSecondType;
|
|
aParameterPair.Second.Value = makeAny(pData->nSecondValue);
|
|
return aParameterPair;
|
|
}
|
|
|
|
com::sun::star::uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeParameterPair >
|
|
CustomShapeProvider::createParameterPairSequence( size_t nElems, const ParameterPairData *pData )
|
|
{
|
|
Sequence< EnhancedCustomShapeParameterPair > aSequence( nElems );
|
|
for (size_t i = 0; i < nElems; i++)
|
|
aSequence[i] = createParameterPair( pData + i );
|
|
return aSequence;
|
|
}
|
|
|
|
} }
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|