diff options
Diffstat (limited to 'oox/source/drawingml')
101 files changed, 21205 insertions, 0 deletions
diff --git a/oox/source/drawingml/chart/axiscontext.cxx b/oox/source/drawingml/chart/axiscontext.cxx new file mode 100644 index 000000000000..e590bf1c64cb --- /dev/null +++ b/oox/source/drawingml/chart/axiscontext.cxx @@ -0,0 +1,320 @@ +/************************************************************************* + * + * 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/chart/axiscontext.hxx" + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/chart/axismodel.hxx" +#include "oox/drawingml/chart/titlecontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandlerRef; +using ::oox::core::ContextHandler2Helper; +using ::rtl::OUString; + +// ============================================================================ + +AxisDispUnitsContext::AxisDispUnitsContext( ContextHandler2Helper& rParent, AxisDispUnitsModel& rModel ) : + ContextBase< AxisDispUnitsModel >( rParent, rModel ) +{ +} + +AxisDispUnitsContext::~AxisDispUnitsContext() +{ +} + +ContextHandlerRef AxisDispUnitsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( dispUnits ): + switch( nElement ) + { + case C_TOKEN( builtInUnit ): + mrModel.mnBuiltInUnit = rAttribs.getToken( XML_val, XML_thousands ); + return 0; + case C_TOKEN( custUnit ): + mrModel.mfCustomUnit = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( dispUnitsLbl ): + return this; + } + break; + + case C_TOKEN( dispUnitsLbl ): + switch( nElement ) + { + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( tx ): + return new TextContext( *this, mrModel.mxText.create() ); + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +AxisContextBase::AxisContextBase( ContextHandler2Helper& rParent, AxisModel& rModel ) : + ContextBase< AxisModel >( rParent, rModel ) +{ +} + +AxisContextBase::~AxisContextBase() +{ +} + +ContextHandlerRef AxisContextBase::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( catAx ): + case C_TOKEN( dateAx ): + case C_TOKEN( serAx ): + case C_TOKEN( valAx ): + switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.mnAxisId = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( crossAx ): + mrModel.mnCrossAxisId = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( crosses ): + mrModel.mnCrossMode = rAttribs.getToken( XML_val, XML_autoZero ); + return 0; + case C_TOKEN( crossesAt ): + mrModel.mofCrossesAt = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( delete ): + // default is 'false', not 'true' as specified + mrModel.mbDeleted = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( majorGridlines ): + return new ShapePrWrapperContext( *this, mrModel.mxMajorGridLines.create() ); + case C_TOKEN( majorTickMark ): + // default is 'out', not 'cross' as specified + mrModel.mnMajorTickMark = rAttribs.getToken( XML_val, XML_out ); + return 0; + case C_TOKEN( minorGridlines ): + return new ShapePrWrapperContext( *this, mrModel.mxMinorGridLines.create() ); + case C_TOKEN( minorTickMark ): + // default is 'none', not 'cross' as specified + mrModel.mnMinorTickMark = rAttribs.getToken( XML_val, XML_none ); + return 0; + case C_TOKEN( numFmt ): + mrModel.maNumberFormat.setAttributes( rAttribs ); + return 0; + case C_TOKEN( scaling ): + return this; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( tickLblPos ): + mrModel.mnTickLabelPos = rAttribs.getToken( XML_val, XML_nextTo ); + return 0; + case C_TOKEN( title ): + return new TitleContext( *this, mrModel.mxTitle.create() ); + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + } + break; + + case C_TOKEN( scaling ): + switch( nElement ) + { + case C_TOKEN( logBase ): + mrModel.mofLogBase = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( max ): + mrModel.mofMax = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( min ): + mrModel.mofMin = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( orientation ): + mrModel.mnOrientation = rAttribs.getToken( XML_val, XML_minMax ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +CatAxisContext::CatAxisContext( ContextHandler2Helper& rParent, AxisModel& rModel ) : + AxisContextBase( rParent, rModel ) +{ +} + +CatAxisContext::~CatAxisContext() +{ +} + +ContextHandlerRef CatAxisContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( auto ): + // default is 'false', not 'true' as specified + mrModel.mbAuto = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( axPos ): + mrModel.mnAxisPos = rAttribs.getToken( XML_val, XML_TOKEN_INVALID ); + return 0; + case C_TOKEN( lblAlgn ): + mrModel.mnLabelAlign = rAttribs.getToken( XML_val, XML_ctr ); + return 0; + case C_TOKEN( lblOffset ): + mrModel.mnLabelOffset = rAttribs.getInteger( XML_val, 100 ); + return 0; + case C_TOKEN( noMultiLvlLbl ): + // default is 'false', not 'true' as specified + mrModel.mbNoMultiLevel = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( tickLblSkip ): + mrModel.mnTickLabelSkip = rAttribs.getInteger( XML_val, 0 ); + return 0; + case C_TOKEN( tickMarkSkip ): + mrModel.mnTickMarkSkip = rAttribs.getInteger( XML_val, 0 ); + return 0; + } + return AxisContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +DateAxisContext::DateAxisContext( ContextHandler2Helper& rParent, AxisModel& rModel ) : + AxisContextBase( rParent, rModel ) +{ +} + +DateAxisContext::~DateAxisContext() +{ +} + +ContextHandlerRef DateAxisContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( auto ): + // default is 'false', not 'true' as specified + mrModel.mbAuto = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( baseTimeUnit ): + mrModel.monBaseTimeUnit = rAttribs.getToken( XML_val, XML_days ); + return 0; + case C_TOKEN( lblOffset ): + mrModel.mnLabelOffset = rAttribs.getInteger( XML_val, 100 ); + return 0; + case C_TOKEN( majorTimeUnit ): + mrModel.mnMajorTimeUnit = rAttribs.getToken( XML_val, XML_days ); + return 0; + case C_TOKEN( majorUnit ): + mrModel.mofMajorUnit = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( minorTimeUnit ): + mrModel.mnMinorTimeUnit = rAttribs.getToken( XML_val, XML_days ); + return 0; + case C_TOKEN( minorUnit ): + mrModel.mofMinorUnit = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + } + return AxisContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +SerAxisContext::SerAxisContext( ContextHandler2Helper& rParent, AxisModel& rModel ) : + AxisContextBase( rParent, rModel ) +{ +} + +SerAxisContext::~SerAxisContext() +{ +} + +ContextHandlerRef SerAxisContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( tickLblSkip ): + mrModel.mnTickLabelSkip = rAttribs.getInteger( XML_val, 0 ); + return 0; + case C_TOKEN( tickMarkSkip ): + mrModel.mnTickMarkSkip = rAttribs.getInteger( XML_val, 0 ); + return 0; + } + return AxisContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +ValAxisContext::ValAxisContext( ContextHandler2Helper& rParent, AxisModel& rModel ) : + AxisContextBase( rParent, rModel ) +{ +} + +ValAxisContext::~ValAxisContext() +{ +} + +ContextHandlerRef ValAxisContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( crossBetween ): + mrModel.mnCrossBetween = rAttribs.getToken( XML_val, XML_between ); + return 0; + case C_TOKEN( dispUnits ): + return new AxisDispUnitsContext( *this, mrModel.mxDispUnits.create() ); + case C_TOKEN( majorUnit ): + mrModel.mofMajorUnit = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( minorUnit ): + mrModel.mofMinorUnit = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + } + return AxisContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/axisconverter.cxx b/oox/source/drawingml/chart/axisconverter.cxx new file mode 100644 index 000000000000..18dc00b9d866 --- /dev/null +++ b/oox/source/drawingml/chart/axisconverter.cxx @@ -0,0 +1,365 @@ +/************************************************************************* + * + * 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/chart/axisconverter.hxx" + +#include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> +#include <com/sun/star/chart/ChartAxisLabelPosition.hpp> +#include <com/sun/star/chart/ChartAxisMarkPosition.hpp> +#include <com/sun/star/chart/ChartAxisPosition.hpp> +#include <com/sun/star/chart/TimeInterval.hpp> +#include <com/sun/star/chart/TimeUnit.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/TickmarkStyle.hpp> +#include <com/sun/star/chart2/XAxis.hpp> +#include <com/sun/star/chart2/XCoordinateSystem.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include "oox/drawingml/chart/axismodel.hxx" +#include "oox/drawingml/chart/titleconverter.hxx" +#include "oox/drawingml/chart/typegroupconverter.hxx" +#include "oox/drawingml/lineproperties.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +inline void lclSetValueOrClearAny( Any& orAny, const OptValue< double >& rofValue ) +{ + if( rofValue.has() ) orAny <<= rofValue.get(); else orAny.clear(); +} + +bool lclIsLogarithmicScale( const AxisModel& rAxisModel ) +{ + return rAxisModel.mofLogBase.has() && (2.0 <= rAxisModel.mofLogBase.get()) && (rAxisModel.mofLogBase.get() <= 1000.0); +} + +sal_Int32 lclGetApiTimeUnit( sal_Int32 nTimeUnit ) +{ + using namespace ::com::sun::star::chart; + switch( nTimeUnit ) + { + case XML_days: return TimeUnit::DAY; + case XML_months: return TimeUnit::MONTH; + case XML_years: return TimeUnit::YEAR; + default: OSL_ENSURE( false, "lclGetApiTimeUnit - unexpected time unit" ); + } + return TimeUnit::DAY; +} + +void lclConvertTimeInterval( Any& orInterval, const OptValue< double >& rofUnit, sal_Int32 nTimeUnit ) +{ + if( rofUnit.has() && (1.0 <= rofUnit.get()) && (rofUnit.get() <= SAL_MAX_INT32) ) + orInterval <<= ::com::sun::star::chart::TimeInterval( static_cast< sal_Int32 >( rofUnit.get() ), lclGetApiTimeUnit( nTimeUnit ) ); + else + orInterval.clear(); +} + +::com::sun::star::chart::ChartAxisLabelPosition lclGetLabelPosition( sal_Int32 nToken ) +{ + using namespace ::com::sun::star::chart; + switch( nToken ) + { + case XML_high: return ChartAxisLabelPosition_OUTSIDE_END; + case XML_low: return ChartAxisLabelPosition_OUTSIDE_START; + case XML_nextTo: return ChartAxisLabelPosition_NEAR_AXIS; + } + return ChartAxisLabelPosition_NEAR_AXIS; +} + +sal_Int32 lclGetTickMark( sal_Int32 nToken ) +{ + using namespace ::com::sun::star::chart2::TickmarkStyle; + switch( nToken ) + { + case XML_in: return INNER; + case XML_out: return OUTER; + case XML_cross: return INNER | OUTER; + } + return NONE; +} + +} // namespace + +// ============================================================================ + +AxisConverter::AxisConverter( const ConverterRoot& rParent, AxisModel& rModel ) : + ConverterBase< AxisModel >( rParent, rModel ) +{ +} + +AxisConverter::~AxisConverter() +{ +} + +void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCoordSystem, + TypeGroupConverter& rTypeGroup, const AxisModel* pCrossingAxis, sal_Int32 nAxesSetIdx, sal_Int32 nAxisIdx ) +{ + Reference< XAxis > xAxis; + try + { + namespace cssc = ::com::sun::star::chart; + namespace cssc2 = ::com::sun::star::chart2; + + const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo(); + ObjectFormatter& rFormatter = getFormatter(); + + // create the axis object (always) + xAxis.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Axis" ) ), UNO_QUERY_THROW ); + PropertySet aAxisProp( xAxis ); + // #i58688# axis enabled + aAxisProp.setProperty( PROP_Show, !mrModel.mbDeleted ); + + // axis line, tick, and gridline properties --------------------------- + + // show axis labels + aAxisProp.setProperty( PROP_DisplayLabels, mrModel.mnTickLabelPos != XML_none ); + aAxisProp.setProperty( PROP_LabelPosition, lclGetLabelPosition( mrModel.mnTickLabelPos ) ); + // no X axis line in radar charts + if( (nAxisIdx == API_X_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_RADAR) ) + mrModel.mxShapeProp.getOrCreate().getLineProperties().maLineFill.moFillType = XML_noFill; + // axis line and tick label formatting + rFormatter.convertFormatting( aAxisProp, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_AXIS ); + // tick label rotation + rFormatter.convertTextRotation( aAxisProp, mrModel.mxTextProp, true ); + + // tick mark style + aAxisProp.setProperty( PROP_MajorTickmarks, lclGetTickMark( mrModel.mnMajorTickMark ) ); + aAxisProp.setProperty( PROP_MinorTickmarks, lclGetTickMark( mrModel.mnMinorTickMark ) ); + aAxisProp.setProperty( PROP_MarkPosition, cssc::ChartAxisMarkPosition_AT_AXIS ); + + // main grid + PropertySet aGridProp( xAxis->getGridProperties() ); + aGridProp.setProperty( PROP_Show, mrModel.mxMajorGridLines.is() ); + if( mrModel.mxMajorGridLines.is() ) + rFormatter.convertFrameFormatting( aGridProp, mrModel.mxMajorGridLines, OBJECTTYPE_MAJORGRIDLINE ); + + // sub grid + Sequence< Reference< XPropertySet > > aSubGridPropSeq = xAxis->getSubGridProperties(); + if( aSubGridPropSeq.hasElements() ) + { + PropertySet aSubGridProp( aSubGridPropSeq[ 0 ] ); + aSubGridProp.setProperty( PROP_Show, mrModel.mxMinorGridLines.is() ); + if( mrModel.mxMinorGridLines.is() ) + rFormatter.convertFrameFormatting( aSubGridProp, mrModel.mxMinorGridLines, OBJECTTYPE_MINORGRIDLINE ); + } + + // axis type and X axis categories ------------------------------------ + + ScaleData aScaleData = xAxis->getScaleData(); + // set axis type + switch( nAxisIdx ) + { + case API_X_AXIS: + if( rTypeInfo.mbCategoryAxis ) + { + OSL_ENSURE( (mrModel.mnTypeId == C_TOKEN( catAx )) || (mrModel.mnTypeId == C_TOKEN( dateAx )), + "AxisConverter::convertFromModel - unexpected axis model type (must: c:catAx or c:dateAx)" ); + bool bDateAxis = mrModel.mnTypeId == C_TOKEN( dateAx ); + /* Chart2 requires axis type CATEGORY for automatic + category/date axis (even if it is a date axis + currently). */ + aScaleData.AxisType = (bDateAxis && !mrModel.mbAuto) ? cssc2::AxisType::DATE : cssc2::AxisType::CATEGORY; + aScaleData.AutoDateAxis = mrModel.mbAuto; + aScaleData.Categories = rTypeGroup.createCategorySequence(); + } + else + { + OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" ); + aScaleData.AxisType = cssc2::AxisType::REALNUMBER; + } + break; + case API_Y_AXIS: + OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( valAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:valAx)" ); + aScaleData.AxisType = rTypeGroup.isPercent() ? cssc2::AxisType::PERCENT : cssc2::AxisType::REALNUMBER; + break; + case API_Z_AXIS: + OSL_ENSURE( mrModel.mnTypeId == C_TOKEN( serAx ), "AxisConverter::convertFromModel - unexpected axis model type (must: c:serAx)" ); + OSL_ENSURE( rTypeGroup.isDeep3dChart(), "AxisConverter::convertFromModel - series axis not supported by this chart type" ); + aScaleData.AxisType = cssc2::AxisType::SERIES; + break; + } + + // axis scaling and increment ----------------------------------------- + + switch( aScaleData.AxisType ) + { + case cssc2::AxisType::CATEGORY: + case cssc2::AxisType::SERIES: + case cssc2::AxisType::DATE: + { + /* Determine date axis type from XML type identifier, and not + via aScaleData.AxisType, as this value sticks to CATEGORY + for automatic category/date axes). */ + if( mrModel.mnTypeId == C_TOKEN( dateAx ) ) + { + // scaling algorithm + aScaleData.Scaling.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.LinearScaling" ) ), UNO_QUERY ); + // min/max + lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin ); + lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax ); + // major/minor increment + lclConvertTimeInterval( aScaleData.TimeIncrement.MajorTimeInterval, mrModel.mofMajorUnit, mrModel.mnMajorTimeUnit ); + lclConvertTimeInterval( aScaleData.TimeIncrement.MinorTimeInterval, mrModel.mofMinorUnit, mrModel.mnMinorTimeUnit ); + // base time unit + if( mrModel.monBaseTimeUnit.has() ) + aScaleData.TimeIncrement.TimeResolution <<= lclGetApiTimeUnit( mrModel.monBaseTimeUnit.get() ); + else + aScaleData.TimeIncrement.TimeResolution.clear(); + } + else + { + // do not overlap text unless all labels are visible + aAxisProp.setProperty( PROP_TextOverlap, mrModel.mnTickLabelSkip == 1 ); + // do not break text into several lines + aAxisProp.setProperty( PROP_TextBreak, false ); + // do not stagger labels in two lines + aAxisProp.setProperty( PROP_ArrangeOrder, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE ); + //! TODO #i58731# show n-th category + } + } + break; + case cssc2::AxisType::REALNUMBER: + case cssc2::AxisType::PERCENT: + { + // scaling algorithm + bool bLogScale = lclIsLogarithmicScale( mrModel ); + OUString aScalingService = bLogScale ? + CREATE_OUSTRING( "com.sun.star.chart2.LogarithmicScaling" ) : + CREATE_OUSTRING( "com.sun.star.chart2.LinearScaling" ); + aScaleData.Scaling.set( createInstance( aScalingService ), UNO_QUERY ); + // min/max + lclSetValueOrClearAny( aScaleData.Minimum, mrModel.mofMin ); + lclSetValueOrClearAny( aScaleData.Maximum, mrModel.mofMax ); + // major increment + IncrementData& rIncrementData = aScaleData.IncrementData; + if( mrModel.mofMajorUnit.has() && aScaleData.Scaling.is() ) + rIncrementData.Distance <<= aScaleData.Scaling->doScaling( mrModel.mofMajorUnit.get() ); + else + lclSetValueOrClearAny( rIncrementData.Distance, mrModel.mofMajorUnit ); + // minor increment + Sequence< SubIncrement >& rSubIncrementSeq = rIncrementData.SubIncrements; + rSubIncrementSeq.realloc( 1 ); + Any& rIntervalCount = rSubIncrementSeq[ 0 ].IntervalCount; + rIntervalCount.clear(); + if( bLogScale ) + { + if( mrModel.mofMinorUnit.has() ) + rIntervalCount <<= sal_Int32( 9 ); + } + else if( mrModel.mofMajorUnit.has() && mrModel.mofMinorUnit.has() && (0.0 < mrModel.mofMinorUnit.get()) && (mrModel.mofMinorUnit.get() <= mrModel.mofMajorUnit.get()) ) + { + double fCount = mrModel.mofMajorUnit.get() / mrModel.mofMinorUnit.get() + 0.5; + if( (1.0 <= fCount) && (fCount < 1001.0) ) + rIntervalCount <<= static_cast< sal_Int32 >( fCount ); + } + } + break; + default: + OSL_ENSURE( false, "AxisConverter::convertFromModel - unknown axis type" ); + } + + /* Do not set a value to the Origin member anymore (already done via + new axis properties 'CrossoverPosition' and 'CrossoverValue'). */ + aScaleData.Origin.clear(); + + // axis orientation --------------------------------------------------- + + // #i85167# pie/donut charts need opposite direction at Y axis + // #i87747# radar charts need opposite direction at X axis + bool bMirrorDirection = + ((nAxisIdx == API_Y_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE)) || + ((nAxisIdx == API_X_AXIS) && (rTypeInfo.meTypeCategory == TYPECATEGORY_RADAR)); + bool bReverse = (mrModel.mnOrientation == XML_maxMin) != bMirrorDirection; + aScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL; + + // write back scaling data + xAxis->setScaleData( aScaleData ); + + // number format ------------------------------------------------------ + + if( (aScaleData.AxisType == cssc2::AxisType::REALNUMBER) || (aScaleData.AxisType == cssc2::AxisType::PERCENT) ) + getFormatter().convertNumberFormat( aAxisProp, mrModel.maNumberFormat ); + + // position of crossing axis ------------------------------------------ + + bool bManualCrossing = mrModel.mofCrossesAt.has(); + cssc::ChartAxisPosition eAxisPos = cssc::ChartAxisPosition_VALUE; + if( !bManualCrossing ) switch( mrModel.mnCrossMode ) + { + case XML_min: eAxisPos = cssc::ChartAxisPosition_START; break; + case XML_max: eAxisPos = cssc::ChartAxisPosition_END; break; + case XML_autoZero: eAxisPos = cssc::ChartAxisPosition_VALUE; break; + } + aAxisProp.setProperty( PROP_CrossoverPosition, eAxisPos ); + + // calculate automatic origin depending on scaling mode of crossing axis + bool bCrossingLogScale = pCrossingAxis && lclIsLogarithmicScale( *pCrossingAxis ); + double fCrossingPos = bManualCrossing ? mrModel.mofCrossesAt.get() : (bCrossingLogScale ? 1.0 : 0.0); + aAxisProp.setProperty( PROP_CrossoverValue, fCrossingPos ); + + // axis title --------------------------------------------------------- + + // in radar charts, title objects may exist, but are not shown + if( mrModel.mxTitle.is() && (rTypeGroup.getTypeInfo().meTypeCategory != TYPECATEGORY_RADAR) ) + { + Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW ); + TitleConverter aTitleConv( *this, *mrModel.mxTitle ); + aTitleConv.convertFromModel( xTitled, CREATE_OUSTRING( "Axis Title" ), OBJECTTYPE_AXISTITLE, nAxesSetIdx, nAxisIdx ); + } + } + catch( Exception& ) + { + } + + if( xAxis.is() && rxCoordSystem.is() ) try + { + // insert axis into coordinate system + rxCoordSystem->setAxisByDimension( nAxisIdx, xAxis, nAxesSetIdx ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "AxisConverter::convertFromModel - cannot insert axis into coordinate system" ); + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/axismodel.cxx b/oox/source/drawingml/chart/axismodel.cxx new file mode 100644 index 000000000000..c1bec6c1e1be --- /dev/null +++ b/oox/source/drawingml/chart/axismodel.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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/chart/axismodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +AxisDispUnitsModel::AxisDispUnitsModel() : + mfCustomUnit( 0.0 ), + mnBuiltInUnit( XML_TOKEN_INVALID ) +{ +} + +AxisDispUnitsModel::~AxisDispUnitsModel() +{ +} + +// ============================================================================ + +AxisModel::AxisModel( sal_Int32 nTypeId ) : + mnAxisId( -1 ), + mnAxisPos( XML_TOKEN_INVALID ), + mnCrossAxisId( -1 ), + mnCrossBetween( XML_between ), + mnCrossMode( XML_autoZero ), + mnLabelAlign( XML_ctr ), + mnLabelOffset( 100 ), + mnMajorTickMark( XML_out ), + mnMajorTimeUnit( XML_days ), + mnMinorTickMark( XML_none ), + mnMinorTimeUnit( XML_days ), + mnOrientation( XML_minMax ), + mnTickLabelPos( XML_nextTo ), + mnTickLabelSkip( 0 ), + mnTickMarkSkip( 0 ), + mnTypeId( nTypeId ), + mbAuto( false ), + mbDeleted( false ), + mbNoMultiLevel( false ) +{ +} + +AxisModel::~AxisModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartcontextbase.cxx b/oox/source/drawingml/chart/chartcontextbase.cxx new file mode 100644 index 000000000000..69c1f2622b46 --- /dev/null +++ b/oox/source/drawingml/chart/chartcontextbase.cxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * 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/chart/chartcontextbase.hxx" + +#include "oox/drawingml/chart/modelbase.hxx" +#include "oox/drawingml/shapepropertiescontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; + +// ============================================================================ + +ShapePrWrapperContext::ShapePrWrapperContext( ContextHandler2Helper& rParent, Shape& rModel ) : + ContextBase< Shape >( rParent, rModel ) +{ +} + +ShapePrWrapperContext::~ShapePrWrapperContext() +{ +} + +ContextHandlerRef ShapePrWrapperContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + return (isRootElement() && (nElement == C_TOKEN( spPr ))) ? new ShapePropertiesContext( *this, mrModel ) : 0; +} + +// ============================================================================ + +LayoutContext::LayoutContext( ContextHandler2Helper& rParent, LayoutModel& rModel ) : + ContextBase< LayoutModel >( rParent, rModel ) +{ +} + +LayoutContext::~LayoutContext() +{ +} + +ContextHandlerRef LayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( layout ): + switch( nElement ) + { + case C_TOKEN( manualLayout ): + mrModel.mbAutoLayout = false; + return this; + } + break; + + case C_TOKEN( manualLayout ): + switch( nElement ) + { + case C_TOKEN( x ): + mrModel.mfX = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( y ): + mrModel.mfY = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( w ): + mrModel.mfW = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( h ): + mrModel.mfH = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( xMode ): + mrModel.mnXMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( yMode ): + mrModel.mnYMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( wMode ): + mrModel.mnWMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( hMode ): + mrModel.mnHMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( layoutTarget ): + mrModel.mnTarget = rAttribs.getToken( XML_val, XML_outer ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartconverter.cxx b/oox/source/drawingml/chart/chartconverter.cxx new file mode 100644 index 000000000000..02672088c763 --- /dev/null +++ b/oox/source/drawingml/chart/chartconverter.cxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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/chart/chartconverter.hxx" + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include "oox/drawingml/chart/chartspaceconverter.hxx" +#include "oox/drawingml/chart/chartspacemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; + +using ::oox::core::XmlFilterBase; +using ::rtl::OUString; + +// ============================================================================ + +ChartConverter::ChartConverter() +{ +} + +ChartConverter::~ChartConverter() +{ +} + +void ChartConverter::convertFromModel( XmlFilterBase& rFilter, + ChartSpaceModel& rChartModel, const Reference< XChartDocument >& rxChartDoc, + const Reference< XShapes >& rxExternalPage, const Point& rChartPos, const Size& rChartSize ) +{ + OSL_ENSURE( rxChartDoc.is(), "ChartConverter::convertFromModel - missing chart document" ); + if( rxChartDoc.is() ) + { + ConverterRoot aConvBase( rFilter, *this, rChartModel, rxChartDoc, rChartSize ); + ChartSpaceConverter aSpaceConv( aConvBase, rChartModel ); + aSpaceConv.convertFromModel( rxExternalPage, rChartPos ); + } +} + +void ChartConverter::createDataProvider( const Reference< XChartDocument >& rxChartDoc ) +{ + try + { + if( !rxChartDoc->hasInternalDataProvider() ) + rxChartDoc->createInternalDataProvider( sal_False ); + } + catch( Exception& ) + { + } +} + +Reference< XDataSequence > ChartConverter::createDataSequence( const Reference< XDataProvider >&, const DataSequenceModel& ) +{ + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartdrawingfragment.cxx b/oox/source/drawingml/chart/chartdrawingfragment.cxx new file mode 100644 index 000000000000..03c634453e8b --- /dev/null +++ b/oox/source/drawingml/chart/chartdrawingfragment.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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/chart/chartdrawingfragment.hxx" + +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/shapecontext.hxx" +#include "oox/drawingml/shapegroupcontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::oox::core; + +using ::rtl::OUString; + +// ============================================================================ + +ShapeAnchor::ShapeAnchor( bool bRelSize ) : + mbRelSize( bRelSize ) +{ +} + +void ShapeAnchor::importExt( const AttributeList& rAttribs ) +{ + OSL_ENSURE( !mbRelSize, "ShapeAnchor::importExt - unexpected 'cdr:ext' element" ); + maSize.Width = rAttribs.getHyper( XML_cx, 0 ); + maSize.Height = rAttribs.getHyper( XML_cy, 0 ); +} + +void ShapeAnchor::setPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) +{ + AnchorPosModel* pAnchorPos = 0; + switch( nParentContext ) + { + case CDR_TOKEN( from ): + pAnchorPos = &maFrom; + break; + case CDR_TOKEN( to ): + OSL_ENSURE( mbRelSize, "ShapeAnchor::setPos - unexpected 'cdr:to' element" ); + pAnchorPos = &maTo; + break; + default: + OSL_ENSURE( false, "ShapeAnchor::setPos - unexpected parent element" ); + } + if( pAnchorPos ) switch( nElement ) + { + case CDR_TOKEN( x ): pAnchorPos->mfX = rValue.toDouble(); break; + case CDR_TOKEN( y ): pAnchorPos->mfY = rValue.toDouble(); break; + default: OSL_ENSURE( false, "ShapeAnchor::setPos - unexpected element" ); + } +} + +Rectangle ShapeAnchor::calcEmuLocation( const EmuRectangle& rEmuChartRect ) const +{ + Rectangle aLoc( -1, -1, -1, -1 ); + + OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid from position" ); + OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcEmuLocation - invalid to/size" ); + if( maFrom.isValid() && (mbRelSize ? maTo.isValid() : maSize.isValid()) ) + { + // calculate shape position + aLoc.X = getLimitedValue< sal_Int32, double >( maFrom.mfX * rEmuChartRect.Width, 0, SAL_MAX_INT32 ); + aLoc.Y = getLimitedValue< sal_Int32, double >( maFrom.mfY * rEmuChartRect.Height, 0, SAL_MAX_INT32 ); + + // calculate shape size + if( mbRelSize ) + { + aLoc.Width = getLimitedValue< sal_Int32, double >( maTo.mfX * rEmuChartRect.Width, 0, SAL_MAX_INT32 ) - aLoc.X; + if( aLoc.Width < 0 ) + { + aLoc.X += aLoc.Width; + aLoc.Width *= -1; + } + aLoc.Height = getLimitedValue< sal_Int32, double >( maTo.mfY * rEmuChartRect.Height, 0, SAL_MAX_INT32 ) - aLoc.Y; + if( aLoc.Height < 0 ) + { + aLoc.Y += aLoc.Height; + aLoc.Height *= -1; + } + } + else + { + aLoc.Width = getLimitedValue< sal_Int32, sal_Int64 >( maSize.Width, 0, SAL_MAX_INT32 ); + aLoc.Height = getLimitedValue< sal_Int32, sal_Int64 >( maSize.Height, 0, SAL_MAX_INT32 ); + } + } + + return aLoc; +} +// ============================================================================ + +ChartDrawingFragment::ChartDrawingFragment( XmlFilterBase& rFilter, + const OUString& rFragmentPath, const Reference< XShapes >& rxDrawPage, + const Size& rChartSize, const Point& rShapesOffset, bool bOleSupport ) : + FragmentHandler2( rFilter, rFragmentPath ), + mxDrawPage( rxDrawPage ), + mbOleSupport( bOleSupport ) +{ + maEmuChartRect.X = static_cast< sal_Int64 >( rShapesOffset.X ) * 360; + maEmuChartRect.Y = static_cast< sal_Int64 >( rShapesOffset.Y ) * 360; + maEmuChartRect.Width = static_cast< sal_Int64 >( rChartSize.Width ) * 360; + maEmuChartRect.Height = static_cast< sal_Int64 >( rChartSize.Height ) * 360; +} + +ChartDrawingFragment::~ChartDrawingFragment() +{ +} + +ContextHandlerRef ChartDrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case XML_ROOT_CONTEXT: + if( nElement == C_TOKEN( userShapes ) ) return this; + break; + + case C_TOKEN( userShapes ): + switch( nElement ) + { + case CDR_TOKEN( absSizeAnchor ): + mxAnchor.reset( new ShapeAnchor( false ) ); + return this; + case CDR_TOKEN( relSizeAnchor ): + mxAnchor.reset( new ShapeAnchor( true ) ); + return this; + } + break; + + case CDR_TOKEN( absSizeAnchor ): + case CDR_TOKEN( relSizeAnchor ): + switch( nElement ) + { + case CDR_TOKEN( sp ): + mxShape.reset( new Shape( "com.sun.star.drawing.CustomShape" ) ); + return new ShapeContext( *this, ShapePtr(), mxShape ); + case CDR_TOKEN( cxnSp ): + mxShape.reset( new Shape( "com.sun.star.drawing.ConnectorShape" ) ); + return new ConnectorShapeContext( *this, ShapePtr(), mxShape ); + case CDR_TOKEN( pic ): + mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ); + return new GraphicShapeContext( *this, ShapePtr(), mxShape ); + case CDR_TOKEN( graphicFrame ): + if( !mbOleSupport ) + return 0; + mxShape.reset( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ); + return new GraphicalObjectFrameContext( *this, ShapePtr(), mxShape, true ); + case CDR_TOKEN( grpSp ): + mxShape.reset( new Shape( "com.sun.star.drawing.GroupShape" ) ); + return new ShapeGroupContext( *this, ShapePtr(), mxShape ); + + case CDR_TOKEN( from ): + case CDR_TOKEN( to ): + return this; + + case CDR_TOKEN( ext ): + if( mxAnchor.get() ) mxAnchor->importExt( rAttribs ); + return 0; + } + break; + + case CDR_TOKEN( from ): + case CDR_TOKEN( to ): + switch( nElement ) + { + case CDR_TOKEN( x ): + case CDR_TOKEN( y ): + return this; // collect value in onEndElement() + } + break; + } + return 0; +} + +void ChartDrawingFragment::onCharacters( const OUString& rChars ) +{ + if( isCurrentElement( CDR_TOKEN( x ), CDR_TOKEN( y ) ) && mxAnchor.get() ) + mxAnchor->setPos( getCurrentElement(), getParentElement(), rChars ); +} + +void ChartDrawingFragment::onEndElement() +{ + if( isCurrentElement( CDR_TOKEN( absSizeAnchor ), CDR_TOKEN( relSizeAnchor ) ) ) + { + if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() ) + { + Rectangle aLoc = mxAnchor->calcEmuLocation( maEmuChartRect ); + if( (aLoc.X >= 0) && (aLoc.Y >= 0) && (aLoc.Width >= 0) && (aLoc.Height >= 0) ) + mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, &aLoc ); + } + mxShape.reset(); + mxAnchor.reset(); + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartspaceconverter.cxx b/oox/source/drawingml/chart/chartspaceconverter.cxx new file mode 100644 index 000000000000..bfcad1b43d04 --- /dev/null +++ b/oox/source/drawingml/chart/chartspaceconverter.cxx @@ -0,0 +1,229 @@ +/************************************************************************* + * + * 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/chart/chartspaceconverter.hxx" + +#include <com/sun/star/chart/MissingValueTreatment.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/chart/chartconverter.hxx" +#include "oox/drawingml/chart/chartdrawingfragment.hxx" +#include "oox/drawingml/chart/chartspacemodel.hxx" +#include "oox/drawingml/chart/plotareaconverter.hxx" +#include "oox/drawingml/chart/titleconverter.hxx" + +using ::rtl::OUString; +using ::com::sun::star::awt::Point; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::makeAny; +using ::com::sun::star::util::XNumberFormatsSupplier; +using ::com::sun::star::drawing::XDrawPageSupplier; +using ::com::sun::star::drawing::XShapes; +using ::com::sun::star::chart2::XDiagram; +using ::com::sun::star::chart2::XTitled; +using ::com::sun::star::chart2::data::XDataReceiver; +using ::com::sun::star::beans::XPropertySet; + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +using ::rtl::OUString; + +// ============================================================================ + +ChartSpaceConverter::ChartSpaceConverter( const ConverterRoot& rParent, ChartSpaceModel& rModel ) : + ConverterBase< ChartSpaceModel >( rParent, rModel ) +{ +} + +ChartSpaceConverter::~ChartSpaceConverter() +{ +} + +void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExternalPage, const Point& rChartPos ) +{ + /* create data provider (virtual function in the ChartConverter class, + derived converters may create an external data provider) */ + getChartConverter().createDataProvider( getChartDocument() ); + + // attach number formatter of container document to data receiver + try + { + Reference< XDataReceiver > xDataRec( getChartDocument(), UNO_QUERY_THROW ); + Reference< XNumberFormatsSupplier > xNumFmtSupp( getFilter().getModel(), UNO_QUERY_THROW ); + xDataRec->attachNumberFormatsSupplier( xNumFmtSupp ); + } + catch( Exception& ) + { + } + + // formatting of the chart background + PropertySet aBackPropSet( getChartDocument()->getPageBackground() ); + getFormatter().convertFrameFormatting( aBackPropSet, mrModel.mxShapeProp, OBJECTTYPE_CHARTSPACE ); + + // convert plot area (container of all chart type groups) + PlotAreaConverter aPlotAreaConv( *this, mrModel.mxPlotArea.getOrCreate() ); + aPlotAreaConv.convertFromModel( mrModel.mxView3D.getOrCreate() ); + + // plot area converter has created the diagram object + Reference< XDiagram > xDiagram = getChartDocument()->getFirstDiagram(); + + // convert wall and floor formatting in 3D charts + if( xDiagram.is() && aPlotAreaConv.isWall3dChart() ) + { + WallFloorConverter aFloorConv( *this, mrModel.mxFloor.getOrCreate() ); + aFloorConv.convertFromModel( xDiagram, OBJECTTYPE_FLOOR ); + + WallFloorConverter aWallConv( *this, mrModel.mxBackWall.getOrCreate() ); + aWallConv.convertFromModel( xDiagram, OBJECTTYPE_WALL ); + } + + // chart title + if( !mrModel.mbAutoTitleDel ) try + { + /* If the title model is missing, but the chart shows exactly one + series, the series title is shown as chart title. */ + OUString aAutoTitle = aPlotAreaConv.getAutomaticTitle(); + if( mrModel.mxTitle.is() || (aAutoTitle.getLength() > 0) ) + { + if( aAutoTitle.getLength() == 0 ) + aAutoTitle = CREATE_OUSTRING( "Chart Title" ); + Reference< XTitled > xTitled( getChartDocument(), UNO_QUERY_THROW ); + TitleConverter aTitleConv( *this, mrModel.mxTitle.getOrCreate() ); + aTitleConv.convertFromModel( xTitled, aAutoTitle, OBJECTTYPE_CHARTTITLE ); + } + } + catch( Exception& ) + { + } + + // legend + if( xDiagram.is() && mrModel.mxLegend.is() ) + { + LegendConverter aLegendConv( *this, *mrModel.mxLegend ); + aLegendConv.convertFromModel( xDiagram ); + } + + // treatment of missing values + if( xDiagram.is() ) + { + using namespace ::com::sun::star::chart::MissingValueTreatment; + sal_Int32 nMissingValues = LEAVE_GAP; + switch( mrModel.mnDispBlanksAs ) + { + case XML_gap: nMissingValues = LEAVE_GAP; break; + case XML_zero: nMissingValues = USE_ZERO; break; + case XML_span: nMissingValues = CONTINUE; break; + } + PropertySet aDiaProp( xDiagram ); + aDiaProp.setProperty( PROP_MissingValueTreatment, nMissingValues ); + } + + /* Following all conversions needing the old Chart1 API that involves full + initialization of the chart view. */ + namespace cssc = ::com::sun::star::chart; + Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY ); + if( xChart1Doc.is() ) + { + /* Set the IncludeHiddenCells property via the old API as only this + ensures that the data provider and all created sequences get this + flag correctly. */ + PropertySet aDiaProp( xChart1Doc->getDiagram() ); + aDiaProp.setProperty( PROP_IncludeHiddenCells, !mrModel.mbPlotVisOnly ); + + // plot area position and size + aPlotAreaConv.convertPositionFromModel(); + + // positions of main title and all axis titles + convertTitlePositions(); + } + + // embedded drawing shapes + if( mrModel.maDrawingPath.getLength() > 0 ) try + { + /* Get the internal draw page of the chart document, if no external + drawing page has been passed. */ + Reference< XShapes > xShapes; + Point aShapesOffset( 0, 0 ); + if( rxExternalPage.is() ) + { + xShapes = rxExternalPage; + // offset for embedded shapes to move them inside the chart area + aShapesOffset = rChartPos; + } + else + { + Reference< XDrawPageSupplier > xDrawPageSupp( getChartDocument(), UNO_QUERY_THROW ); + xShapes.set( xDrawPageSupp->getDrawPage(), UNO_QUERY_THROW ); + } + + /* If an external drawing page is passed, all embedded shapes will be + inserted there (used e.g. with 'chart sheets' in spreadsheet + documents). In this case, all types of shapes including OLE objects + are supported. If the shapes are inserted into the internal chart + drawing page instead, it is not possible to embed OLE objects. */ + bool bOleSupport = rxExternalPage.is(); + + // now, xShapes is not null anymore + getFilter().importFragment( new ChartDrawingFragment( + getFilter(), mrModel.maDrawingPath, xShapes, getChartSize(), aShapesOffset, bOleSupport ) ); + } + catch( Exception& ) + { + } + + // pivot chart + if ( mrModel.mbPivotChart ) + { + PropertySet aProps( getChartDocument() ); + aProps.setProperty( PROP_DisableDataTableDialog , true ); + aProps.setProperty( PROP_DisableComplexChartTypes , true ); + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartspacefragment.cxx b/oox/source/drawingml/chart/chartspacefragment.cxx new file mode 100644 index 000000000000..06da27c02d01 --- /dev/null +++ b/oox/source/drawingml/chart/chartspacefragment.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * 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/chart/chartspacefragment.hxx" + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/chart/chartspacemodel.hxx" +#include "oox/drawingml/chart/plotareacontext.hxx" +#include "oox/drawingml/chart/titlecontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::oox::core; + +using ::rtl::OUString; + +// ============================================================================ + +ChartSpaceFragment::ChartSpaceFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, ChartSpaceModel& rModel ) : + FragmentBase< ChartSpaceModel >( rFilter, rFragmentPath, rModel ) +{ +} + +ChartSpaceFragment::~ChartSpaceFragment() +{ +} + +ContextHandlerRef ChartSpaceFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case XML_ROOT_CONTEXT: + switch( nElement ) + { + case C_TOKEN( chartSpace ): + return this; + } + break; + + case C_TOKEN( chartSpace ): + switch( nElement ) + { + case C_TOKEN( chart ): + return this; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( style ): + mrModel.mnStyle = rAttribs.getInteger( XML_val, 2 ); + return 0; + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + case C_TOKEN( userShapes ): + mrModel.maDrawingPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + return 0; + case C_TOKEN( pivotSource ): + mrModel.mbPivotChart = true; + return 0; + } + break; + + case C_TOKEN( chart ): + switch( nElement ) + { + case C_TOKEN( autoTitleDeleted ): + // default is 'false', not 'true' as specified + mrModel.mbAutoTitleDel = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( backWall ): + return new WallFloorContext( *this, mrModel.mxBackWall.create() ); + case C_TOKEN( dispBlanksAs ): + mrModel.mnDispBlanksAs = rAttribs.getToken( XML_val, XML_zero ); + return 0; + case C_TOKEN( floor ): + return new WallFloorContext( *this, mrModel.mxFloor.create() ); + case C_TOKEN( legend ): + return new LegendContext( *this, mrModel.mxLegend.create() ); + case C_TOKEN( plotArea ): + return new PlotAreaContext( *this, mrModel.mxPlotArea.create() ); + case C_TOKEN( plotVisOnly ): + // default is 'false', not 'true' as specified + mrModel.mbPlotVisOnly = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( showDLblsOverMax ): + // default is 'false', not 'true' as specified + mrModel.mbShowLabelsOverMax = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( sideWall ): + return new WallFloorContext( *this, mrModel.mxSideWall.create() ); + case C_TOKEN( title ): + return new TitleContext( *this, mrModel.mxTitle.create() ); + case C_TOKEN( view3D ): + return new View3DContext( *this, mrModel.mxView3D.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/chartspacemodel.cxx b/oox/source/drawingml/chart/chartspacemodel.cxx new file mode 100644 index 000000000000..7f86448c8d08 --- /dev/null +++ b/oox/source/drawingml/chart/chartspacemodel.cxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * 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/chart/chartspacemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +ChartSpaceModel::ChartSpaceModel() : + mnDispBlanksAs( XML_gap ), // not zero as specified + mnStyle( 2 ), + mbAutoTitleDel( false ), + mbPlotVisOnly( false ), + mbShowLabelsOverMax( false ), + mbPivotChart( false ) +{ +} + +ChartSpaceModel::~ChartSpaceModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/converterbase.cxx b/oox/source/drawingml/chart/converterbase.cxx new file mode 100644 index 000000000000..7e601ff016af --- /dev/null +++ b/oox/source/drawingml/chart/converterbase.cxx @@ -0,0 +1,439 @@ +/************************************************************************* + * + * 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/chart/converterbase.hxx" + +#include <com/sun/star/chart/XAxisXSupplier.hpp> +#include <com/sun/star/chart/XAxisYSupplier.hpp> +#include <com/sun/star/chart/XAxisZSupplier.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <tools/solar.h> // for F_PI180 +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/theme.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +namespace cssc = ::com::sun::star::chart; + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +using ::oox::core::XmlFilterBase; +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +struct TitleKey : public ::std::pair< ObjectType, ::std::pair< sal_Int32, sal_Int32 > > +{ + inline explicit TitleKey( ObjectType eObjType, sal_Int32 nMainIdx = -1, sal_Int32 nSubIdx = -1 ) + { first = eObjType; second.first = nMainIdx; second.second = nSubIdx; } +}; + +// ---------------------------------------------------------------------------- + +/** A helper structure to store all data related to title objects. Needed for + the conversion of manual title positions that needs the old Chart1 API. + */ +struct TitleLayoutInfo +{ + typedef Reference< XShape > (*GetShapeFunc)( const Reference< cssc::XChartDocument >& ); + + Reference< XTitle > mxTitle; /// The API title object. + ModelRef< LayoutModel > mxLayout; /// The layout model, if existing. + GetShapeFunc mpGetShape; /// Helper function to receive the title shape. + + inline explicit TitleLayoutInfo() : mpGetShape( 0 ) {} + + void convertTitlePos( + ConverterRoot& rRoot, + const Reference< cssc::XChartDocument >& rxChart1Doc ); +}; + +void TitleLayoutInfo::convertTitlePos( ConverterRoot& rRoot, const Reference< cssc::XChartDocument >& rxChart1Doc ) +{ + if( mxTitle.is() && mpGetShape ) try + { + // try to get the title shape + Reference< XShape > xTitleShape( mpGetShape( rxChart1Doc ), UNO_SET_THROW ); + // get title rotation angle, needed for correction of position of top-left edge + double fAngle = 0.0; + PropertySet aTitleProp( mxTitle ); + aTitleProp.getProperty( fAngle, PROP_TextRotation ); + // convert the position + LayoutModel& rLayout = mxLayout.getOrCreate(); + LayoutConverter aLayoutConv( rRoot, rLayout ); + aLayoutConv.convertFromModel( xTitleShape, fAngle ); + } + catch( Exception& ) + { + } +} + +// ---------------------------------------------------------------------------- + +/* The following local functions implement getting the XShape interface of all + supported title objects (chart and axes). This needs some effort due to the + design of the old Chart1 API used to access these objects. */ + +/** A code fragment that returns a shape object from the passed shape supplier + using the specified interface function. Checks a boolean property first. */ +#define OOX_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \ + PropertySet aPropSet( shape_supplier ); \ + if( shape_supplier.is() && aPropSet.getBoolProperty( PROP_##property_name ) ) \ + return shape_supplier->supplier_func(); \ + return Reference< XShape >(); \ + +/** Implements a function returning the drawing shape of an axis title, if + existing, using the specified API interface and its function. */ +#define OOX_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \ +Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \ +{ \ + Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \ + OOX_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \ +} + +/** Returns the drawing shape of the main title, if existing. */ +Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc ) +{ + OOX_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle ) +} + +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle ) + +#undef OOX_DEFINEFUNC_GETAXISTITLESHAPE +#undef OOX_IMPLEMENT_GETTITLESHAPE + +} // namespace + +// ============================================================================ + +struct ConverterData +{ + typedef ::std::map< TitleKey, TitleLayoutInfo > TitleMap; + + ObjectFormatter maFormatter; + TitleMap maTitles; + XmlFilterBase& mrFilter; + ChartConverter& mrConverter; + Reference< XChartDocument > mxDoc; + Size maSize; + + explicit ConverterData( + XmlFilterBase& rFilter, + ChartConverter& rChartConverter, + const ChartSpaceModel& rChartModel, + const Reference< XChartDocument >& rxChartDoc, + const Size& rChartSize ); + ~ConverterData(); +}; + +// ---------------------------------------------------------------------------- + +ConverterData::ConverterData( + XmlFilterBase& rFilter, + ChartConverter& rChartConverter, + const ChartSpaceModel& rChartModel, + const Reference< XChartDocument >& rxChartDoc, + const Size& rChartSize ) : + maFormatter( rFilter, rxChartDoc, rChartModel ), + mrFilter( rFilter ), + mrConverter( rChartConverter ), + mxDoc( rxChartDoc ), + maSize( rChartSize ) +{ + OSL_ENSURE( mxDoc.is(), "ConverterData::ConverterData - missing chart document" ); + // lock the model to suppress internal updates during conversion + try + { + Reference< XModel > xModel( mxDoc, UNO_QUERY_THROW ); + xModel->lockControllers(); + } + catch( Exception& ) + { + } + + // prepare conversion of title positions + maTitles[ TitleKey( OBJECTTYPE_CHARTTITLE ) ].mpGetShape = lclGetMainTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetXAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetYAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Z_AXIS ) ].mpGetShape = lclGetZAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetSecXAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetSecYAxisTitleShape; +} + +ConverterData::~ConverterData() +{ + // unlock the model + try + { + Reference< XModel > xModel( mxDoc, UNO_QUERY_THROW ); + xModel->unlockControllers(); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +ConverterRoot::ConverterRoot( + XmlFilterBase& rFilter, + ChartConverter& rChartConverter, + const ChartSpaceModel& rChartModel, + const Reference< XChartDocument >& rxChartDoc, + const Size& rChartSize ) : + mxData( new ConverterData( rFilter, rChartConverter, rChartModel, rxChartDoc, rChartSize ) ) +{ +} + +ConverterRoot::~ConverterRoot() +{ +} + +Reference< XInterface > ConverterRoot::createInstance( const OUString& rServiceName ) const +{ + Reference< XInterface > xInt; + try + { + xInt = mxData->mrFilter.getServiceFactory()->createInstance( rServiceName ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xInt.is(), "ConverterRoot::createInstance - cannot create instance" ); + return xInt; +} + +XmlFilterBase& ConverterRoot::getFilter() const +{ + return mxData->mrFilter; +} + +ChartConverter& ConverterRoot::getChartConverter() const +{ + return mxData->mrConverter; +} + +Reference< XChartDocument > ConverterRoot::getChartDocument() const +{ + return mxData->mxDoc; +} + +const Size& ConverterRoot::getChartSize() const +{ + return mxData->maSize; +} + +ObjectFormatter& ConverterRoot::getFormatter() const +{ + return mxData->maFormatter; +} + +void ConverterRoot::registerTitleLayout( const Reference< XTitle >& rxTitle, + const ModelRef< LayoutModel >& rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) +{ + OSL_ENSURE( rxTitle.is(), "ConverterRoot::registerTitleLayout - missing title object" ); + TitleLayoutInfo& rTitleInfo = mxData->maTitles[ TitleKey( eObjType, nMainIdx, nSubIdx ) ]; + OSL_ENSURE( rTitleInfo.mpGetShape, "ConverterRoot::registerTitleLayout - invalid title key" ); + rTitleInfo.mxTitle = rxTitle; + rTitleInfo.mxLayout = rxLayout; +} + +void ConverterRoot::convertTitlePositions() +{ + try + { + Reference< cssc::XChartDocument > xChart1Doc( mxData->mxDoc, UNO_QUERY_THROW ); + for( ConverterData::TitleMap::iterator aIt = mxData->maTitles.begin(), aEnd = mxData->maTitles.end(); aIt != aEnd; ++aIt ) + aIt->second.convertTitlePos( *this, xChart1Doc ); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +namespace { + +/** Returns a position value in the chart area in 1/100 mm. */ +sal_Int32 lclCalcPosition( sal_Int32 nChartSize, double fPos, sal_Int32 nPosMode ) +{ + switch( nPosMode ) + { + case XML_edge: // absolute start position as factor of chart size + return getLimitedValue< sal_Int32, double >( nChartSize * fPos + 0.5, 0, nChartSize ); + case XML_factor: // position relative to object default position + OSL_ENSURE( false, "lclCalcPosition - relative positioning not supported" ); + return -1; + }; + + OSL_ENSURE( false, "lclCalcPosition - unknown positioning mode" ); + return -1; +} + +/** Returns a size value in the chart area in 1/100 mm. */ +sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_Int32 nSizeMode ) +{ + sal_Int32 nValue = getLimitedValue< sal_Int32, double >( nChartSize * fSize + 0.5, 0, nChartSize ); + switch( nSizeMode ) + { + case XML_factor: // passed value is width/height + return nValue; + case XML_edge: // passed value is right/bottom position + return nValue - nPos + 1; + }; + + OSL_ENSURE( false, "lclCalcSize - unknown size mode" ); + return -1; +} + +/** Returns a relative size value in the chart area. */ +double lclCalcRelSize( double fPos, double fSize, sal_Int32 nSizeMode ) +{ + switch( nSizeMode ) + { + case XML_factor: // passed value is width/height + break; + case XML_edge: // passed value is right/bottom position + fSize -= fPos; + break; + default: + OSL_ENSURE( false, "lclCalcRelSize - unknown size mode" ); + fSize = 0.0; + }; + return getLimitedValue< double, double >( fSize, 0.0, 1.0 - fPos ); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +LayoutConverter::LayoutConverter( const ConverterRoot& rParent, LayoutModel& rModel ) : + ConverterBase< LayoutModel >( rParent, rModel ) +{ +} + +LayoutConverter::~LayoutConverter() +{ +} + +bool LayoutConverter::calcAbsRectangle( Rectangle& orRect ) const +{ + if( !mrModel.mbAutoLayout ) + { + const Size& rChartSize = getChartSize(); + orRect.X = lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode ); + orRect.Y = lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode ); + if( (orRect.X >= 0) && (orRect.Y >= 0) ) + { + orRect.Width = lclCalcSize( orRect.X, rChartSize.Width, mrModel.mfW, mrModel.mnWMode ); + orRect.Height = lclCalcSize( orRect.Y, rChartSize.Height, mrModel.mfH, mrModel.mnHMode ); + return (orRect.Width > 0) && (orRect.Height > 0); + } + } + return false; +} + +bool LayoutConverter::convertFromModel( PropertySet& rPropSet ) +{ + if( !mrModel.mbAutoLayout && + (mrModel.mnXMode == XML_edge) && (mrModel.mfX >= 0.0) && + (mrModel.mnYMode == XML_edge) && (mrModel.mfY >= 0.0) ) + { + RelativePosition aPos( + getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ), + getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ), + Alignment_TOP_LEFT ); + rPropSet.setProperty( PROP_RelativePosition, aPos ); + + RelativeSize aSize( + lclCalcRelSize( aPos.Primary, mrModel.mfW, mrModel.mnWMode ), + lclCalcRelSize( aPos.Secondary, mrModel.mfH, mrModel.mnHMode ) ); + if( (aSize.Primary > 0.0) && (aSize.Secondary > 0.0) ) + { + rPropSet.setProperty( PROP_RelativeSize, aSize ); + return true; + } + } + return false; +} + +bool LayoutConverter::convertFromModel( const Reference< XShape >& rxShape, double fRotationAngle ) +{ + if( !mrModel.mbAutoLayout ) + { + const Size& rChartSize = getChartSize(); + Point aShapePos( + lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode ), + lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode ) ); + if( (aShapePos.X >= 0) && (aShapePos.Y >= 0) ) + { + // the call to XShape.getSize() may recalc the chart view + Size aShapeSize = rxShape->getSize(); + // rotated shapes need special handling... + double fSin = fabs( sin( fRotationAngle * F_PI180 ) ); + // add part of height to X direction, if title is rotated down + if( fRotationAngle > 180.0 ) + aShapePos.X += static_cast< sal_Int32 >( fSin * aShapeSize.Height + 0.5 ); + // add part of width to Y direction, if title is rotated up + else if( fRotationAngle > 0.0 ) + aShapePos.Y += static_cast< sal_Int32 >( fSin * aShapeSize.Width + 0.5 ); + // set the resulting position at the shape + rxShape->setPosition( aShapePos ); + return true; + } + } + return false; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/datasourcecontext.cxx b/oox/source/drawingml/chart/datasourcecontext.cxx new file mode 100644 index 000000000000..a044dd67018d --- /dev/null +++ b/oox/source/drawingml/chart/datasourcecontext.cxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * 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/chart/datasourcecontext.hxx" + +#include "oox/drawingml/chart/datasourcemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; +using ::rtl::OUString; + +// ============================================================================ + +DoubleSequenceContext::DoubleSequenceContext( ContextHandler2Helper& rParent, DataSequenceModel& rModel ) : + DataSequenceContextBase( rParent, rModel ), + mnPtIndex( -1 ) +{ +} + +DoubleSequenceContext::~DoubleSequenceContext() +{ +} + +ContextHandlerRef DoubleSequenceContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( numRef ): + switch( nElement ) + { + case C_TOKEN( f ): + case C_TOKEN( numCache ): + return this; + } + break; + + case C_TOKEN( numCache ): + case C_TOKEN( numLit ): + switch( nElement ) + { + case C_TOKEN( formatCode ): + return this; + case C_TOKEN( ptCount ): + mrModel.mnPointCount = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( pt ): + mnPtIndex = rAttribs.getInteger( XML_idx, -1 ); + return this; + } + break; + + case C_TOKEN( pt ): + switch( nElement ) + { + case C_TOKEN( v ): + return this; + } + break; + } + return 0; +} + +void DoubleSequenceContext::onCharacters( const OUString& rChars ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( f ): + mrModel.maFormula = rChars; + break; + case C_TOKEN( formatCode ): + mrModel.maFormatCode = rChars; + break; + case C_TOKEN( v ): + if( mnPtIndex >= 0 ) + mrModel.maData[ mnPtIndex ] <<= rChars.toDouble(); + break; + } +} + +// ============================================================================ + +StringSequenceContext::StringSequenceContext( ContextHandler2Helper& rParent, DataSequenceModel& rModel ) : + DataSequenceContextBase( rParent, rModel ) +{ +} + +StringSequenceContext::~StringSequenceContext() +{ +} + +ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( multiLvlStrRef ): + switch( nElement ) + { + case C_TOKEN( f ): + return this; + } + break; + + case C_TOKEN( strRef ): + switch( nElement ) + { + case C_TOKEN( f ): + case C_TOKEN( strCache ): + return this; + } + break; + + case C_TOKEN( strCache ): + case C_TOKEN( strLit ): + switch( nElement ) + { + case C_TOKEN( ptCount ): + mrModel.mnPointCount = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( pt ): + mnPtIndex = rAttribs.getInteger( XML_idx, -1 ); + return this; + } + break; + + case C_TOKEN( pt ): + switch( nElement ) + { + case C_TOKEN( v ): + return this; + } + break; + } + return 0; +} + +void StringSequenceContext::onCharacters( const OUString& rChars ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( f ): + mrModel.maFormula = rChars; + break; + case C_TOKEN( v ): + if( mnPtIndex >= 0 ) + mrModel.maData[ mnPtIndex ] <<= rChars; + break; + } +} + +// ============================================================================ + +DataSourceContext::DataSourceContext( ContextHandler2Helper& rParent, DataSourceModel& rModel ) : + ContextBase< DataSourceModel >( rParent, rModel ) +{ +} + +DataSourceContext::~DataSourceContext() +{ +} + +ContextHandlerRef DataSourceContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( cat ): + case C_TOKEN( xVal ): + switch( nElement ) + { + case C_TOKEN( multiLvlStrRef ): + case C_TOKEN( strLit ): + case C_TOKEN( strRef ): + OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" ); + return new StringSequenceContext( *this, mrModel.mxDataSeq.create() ); + + case C_TOKEN( numLit ): + case C_TOKEN( numRef ): + OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" ); + return new DoubleSequenceContext( *this, mrModel.mxDataSeq.create() ); + } + break; + + case C_TOKEN( plus ): + case C_TOKEN( minus ): + case C_TOKEN( val ): + case C_TOKEN( yVal ): + case C_TOKEN( bubbleSize ): + switch( nElement ) + { + case C_TOKEN( numLit ): + case C_TOKEN( numRef ): + OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" ); + return new DoubleSequenceContext( *this, mrModel.mxDataSeq.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/datasourceconverter.cxx b/oox/source/drawingml/chart/datasourceconverter.cxx new file mode 100644 index 000000000000..c68a6cbe4adf --- /dev/null +++ b/oox/source/drawingml/chart/datasourceconverter.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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/chart/datasourceconverter.hxx" + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include "oox/drawingml/chart/chartconverter.hxx" +#include "oox/drawingml/chart/datasourcemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +DataSequenceConverter::DataSequenceConverter( const ConverterRoot& rParent, DataSequenceModel& rModel ) : + ConverterBase< DataSequenceModel >( rParent, rModel ) +{ +} + +DataSequenceConverter::~DataSequenceConverter() +{ +} + +Reference< XDataSequence > DataSequenceConverter::createDataSequence( const OUString& rRole ) +{ + // create data sequence from data source model (virtual call at chart converter) + Reference< XDataSequence > xDataSeq = getChartConverter().createDataSequence( getChartDocument()->getDataProvider(), mrModel ); + + // set sequence role + PropertySet aSeqProp( xDataSeq ); + aSeqProp.setProperty( PROP_Role, rRole ); + + return xDataSeq; +} + +// ============================================================================ + +DataSourceConverter::DataSourceConverter( const ConverterRoot& rParent, DataSourceModel& rModel ) : + ConverterBase< DataSourceModel >( rParent, rModel ) +{ +} + +DataSourceConverter::~DataSourceConverter() +{ +} + +Reference< XDataSequence > DataSourceConverter::createDataSequence( const OUString& rRole ) +{ + Reference< XDataSequence > xDataSeq; + if( mrModel.mxDataSeq.is() ) + { + DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq ); + xDataSeq = aDataSeqConv.createDataSequence( rRole ); + } + return xDataSeq; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/datasourcemodel.cxx b/oox/source/drawingml/chart/datasourcemodel.cxx new file mode 100644 index 000000000000..aad5a1bff959 --- /dev/null +++ b/oox/source/drawingml/chart/datasourcemodel.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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/chart/datasourcemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +DataSequenceModel::DataSequenceModel() : + mnPointCount( -1 ) +{ +} + +DataSequenceModel::~DataSequenceModel() +{ +} + +// ============================================================================ + +DataSourceModel::DataSourceModel() +{ +} + +DataSourceModel::~DataSourceModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/makefile.mk b/oox/source/drawingml/chart/makefile.mk new file mode 100644 index 000000000000..84762e6a2540 --- /dev/null +++ b/oox/source/drawingml/chart/makefile.mk @@ -0,0 +1,74 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=oox +TARGET=chart +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/axiscontext.obj \ + $(SLO)$/axisconverter.obj \ + $(SLO)$/axismodel.obj \ + $(SLO)$/chartcontextbase.obj \ + $(SLO)$/chartconverter.obj \ + $(SLO)$/chartdrawingfragment.obj \ + $(SLO)$/chartspaceconverter.obj \ + $(SLO)$/chartspacefragment.obj \ + $(SLO)$/chartspacemodel.obj \ + $(SLO)$/converterbase.obj \ + $(SLO)$/datasourcecontext.obj \ + $(SLO)$/datasourceconverter.obj \ + $(SLO)$/datasourcemodel.obj \ + $(SLO)$/modelbase.obj \ + $(SLO)$/objectformatter.obj \ + $(SLO)$/plotareacontext.obj \ + $(SLO)$/plotareaconverter.obj \ + $(SLO)$/plotareamodel.obj \ + $(SLO)$/seriescontext.obj \ + $(SLO)$/seriesconverter.obj \ + $(SLO)$/seriesmodel.obj \ + $(SLO)$/titlecontext.obj \ + $(SLO)$/titleconverter.obj \ + $(SLO)$/titlemodel.obj \ + $(SLO)$/typegroupcontext.obj \ + $(SLO)$/typegroupconverter.obj \ + $(SLO)$/typegroupmodel.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/chart/modelbase.cxx b/oox/source/drawingml/chart/modelbase.cxx new file mode 100644 index 000000000000..f32a118c5589 --- /dev/null +++ b/oox/source/drawingml/chart/modelbase.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * 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/chart/modelbase.hxx" + +#include "oox/helper/attributelist.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::rtl::OUString; + +// ============================================================================ + +NumberFormat::NumberFormat() : + mbSourceLinked( true ) +{ +} + +void NumberFormat::setAttributes( const AttributeList& rAttribs ) +{ + maFormatCode = rAttribs.getString( XML_formatCode, OUString() ); + // default is 'false', not 'true' as specified + mbSourceLinked = rAttribs.getBool( XML_sourceLinked, false ); +} + +// ============================================================================ + +LayoutModel::LayoutModel() : + mfX( 0.0 ), + mfY( 0.0 ), + mfW( 0.0 ), + mfH( 0.0 ), + mnXMode( XML_factor ), + mnYMode( XML_factor ), + mnWMode( XML_factor ), + mnHMode( XML_factor ), + mnTarget( XML_outer ), + mbAutoLayout( true ) +{ +} + +LayoutModel::~LayoutModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx new file mode 100644 index 000000000000..f6d441ded650 --- /dev/null +++ b/oox/source/drawingml/chart/objectformatter.cxx @@ -0,0 +1,1208 @@ +/************************************************************************* + * + * 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/chart/objectformatter.hxx" + +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <osl/thread.h> +#include <rtl/strbuf.hxx> +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/textbody.hxx" +#include "oox/drawingml/textparagraph.hxx" +#include "oox/drawingml/theme.hxx" +#include "oox/drawingml/chart/chartspacemodel.hxx" +#include "oox/helper/modelobjecthelper.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +using ::oox::core::XmlFilterBase; +using ::rtl::OStringBuffer; +using ::rtl::OUString; +using ::rtl::OUStringToOString; + +// ============================================================================ + +namespace { + +struct AutoFormatPatternEntry +{ + sal_Int32 mnColorToken; /// Theme color token. + sal_Int32 mnModToken; /// Color modification token. + sal_Int32 mnModValue; /// Color modification value. +}; + +#define AUTOFORMAT_PATTERN_COLOR( color_token ) \ + { color_token, XML_TOKEN_INVALID, 0 } + +#define AUTOFORMAT_PATTERN_COLORMOD( color_token, mod_token, mod_value ) \ + { color_token, mod_token, mod_value } + +#define AUTOFORMAT_PATTERN_END() \ + AUTOFORMAT_PATTERN_COLOR( XML_TOKEN_INVALID ) + +static const AutoFormatPatternEntry spAutoFormatPattern1[] = +{ + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 88500 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 55000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 78000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 92500 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 70000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 30000 ), + AUTOFORMAT_PATTERN_END() +}; + +static const AutoFormatPatternEntry spAutoFormatPattern2[] = +{ + AUTOFORMAT_PATTERN_COLOR( XML_accent1 ), + AUTOFORMAT_PATTERN_COLOR( XML_accent2 ), + AUTOFORMAT_PATTERN_COLOR( XML_accent3 ), + AUTOFORMAT_PATTERN_COLOR( XML_accent4 ), + AUTOFORMAT_PATTERN_COLOR( XML_accent5 ), + AUTOFORMAT_PATTERN_COLOR( XML_accent6 ), + AUTOFORMAT_PATTERN_END() +}; + +static const AutoFormatPatternEntry spAutoFormatPattern3[] = +{ + AUTOFORMAT_PATTERN_COLORMOD( XML_accent1, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_accent2, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_accent3, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_accent4, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_accent5, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_accent6, XML_shade, 50000 ), + AUTOFORMAT_PATTERN_END() +}; + +static const AutoFormatPatternEntry spAutoFormatPattern4[] = +{ + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 5000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 55000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 78000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 15000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 70000 ), + AUTOFORMAT_PATTERN_COLORMOD( XML_dk1, XML_tint, 30000 ), + AUTOFORMAT_PATTERN_END() +}; + +#undef AUTOFORMAT_PATTERN_COLOR +#undef AUTOFORMAT_PATTERN_COLORMOD +#undef AUTOFORMAT_PATTERN_END + +// ---------------------------------------------------------------------------- + +struct AutoFormatEntry +{ + sal_Int32 mnFirstStyleIdx; /// First chart style index. + sal_Int32 mnLastStyleIdx; /// Last chart style index. + sal_Int32 mnThemedIdx; /// Themed style index. + sal_Int32 mnColorToken; /// Theme color token. + sal_Int32 mnModToken; /// Color modification token. + sal_Int32 mnModValue; /// Color modification value. + sal_Int32 mnRelLineWidth; /// Relative line width (percent). + const AutoFormatPatternEntry* mpPattern;/// Color cycling pattern for data series. + bool mbFadedColor; /// True = Faded color for data series. +}; + +#define AUTOFORMAT_COLOR( first, last, themed_style, color_token ) \ + { first, last, themed_style, color_token, XML_TOKEN_INVALID, 0, 100, 0, false } + +#define AUTOFORMAT_ACCENTS( first, themed_style ) \ + AUTOFORMAT_COLOR( first, first, themed_style, XML_accent1 ), \ + AUTOFORMAT_COLOR( first + 1, first + 1, themed_style, XML_accent2 ), \ + AUTOFORMAT_COLOR( first + 2, first + 2, themed_style, XML_accent3 ), \ + AUTOFORMAT_COLOR( first + 3, first + 3, themed_style, XML_accent4 ), \ + AUTOFORMAT_COLOR( first + 4, first + 4, themed_style, XML_accent5 ), \ + AUTOFORMAT_COLOR( first + 5, first + 5, themed_style, XML_accent6 ) + +#define AUTOFORMAT_COLORMOD( first, last, themed_style, color_token, mod_token, mod_value ) \ + { first, last, themed_style, color_token, mod_token, mod_value, 100, 0, false } + +#define AUTOFORMAT_ACCENTSMOD( first, themed_style, mod_token, mod_value ) \ + AUTOFORMAT_COLORMOD( first, first, themed_style, XML_accent1, mod_token, mod_value ), \ + AUTOFORMAT_COLORMOD( first + 1, first + 1, themed_style, XML_accent2, mod_token, mod_value ), \ + AUTOFORMAT_COLORMOD( first + 2, first + 2, themed_style, XML_accent3, mod_token, mod_value ), \ + AUTOFORMAT_COLORMOD( first + 3, first + 3, themed_style, XML_accent4, mod_token, mod_value ), \ + AUTOFORMAT_COLORMOD( first + 4, first + 4, themed_style, XML_accent5, mod_token, mod_value ), \ + AUTOFORMAT_COLORMOD( first + 5, first + 5, themed_style, XML_accent6, mod_token, mod_value ) + +#define AUTOFORMAT_PATTERN( first, last, themed_style, line_width, pattern ) \ + { first, last, themed_style, XML_TOKEN_INVALID, XML_TOKEN_INVALID, 0, line_width, pattern, false } + +#define AUTOFORMAT_FADED( first, last, themed_style, color_token, line_width ) \ + { first, last, themed_style, color_token, XML_TOKEN_INVALID, 0, line_width, 0, true } + +#define AUTOFORMAT_FADEDACCENTS( first, themed_style, line_width ) \ + AUTOFORMAT_FADED( first, first, themed_style, XML_accent1, line_width ), \ + AUTOFORMAT_FADED( first + 1, first + 1, themed_style, XML_accent2, line_width ), \ + AUTOFORMAT_FADED( first + 2, first + 2, themed_style, XML_accent3, line_width ), \ + AUTOFORMAT_FADED( first + 3, first + 3, themed_style, XML_accent4, line_width ), \ + AUTOFORMAT_FADED( first + 4, first + 4, themed_style, XML_accent5, line_width ), \ + AUTOFORMAT_FADED( first + 5, first + 5, themed_style, XML_accent6, line_width ) + +#define AUTOFORMAT_INVISIBLE( first, last ) \ + AUTOFORMAT_COLOR( first, last, -1, XML_TOKEN_INVALID ) + +#define AUTOFORMAT_END() \ + AUTOFORMAT_INVISIBLE( -1, -1 ) + +static const AutoFormatEntry spNoFormats[] = +{ + AUTOFORMAT_INVISIBLE( 1, 48 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spChartSpaceLines[] = +{ + AUTOFORMAT_COLORMOD( 1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ), + AUTOFORMAT_COLORMOD( 33, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ), + // 41...48: no line, same as Chart2 + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spChartSpaceFills[] = +{ + AUTOFORMAT_COLOR( 1, 32, THEMED_STYLE_SUBTLE, XML_bg1 ), + AUTOFORMAT_COLOR( 33, 40, THEMED_STYLE_SUBTLE, XML_lt1 ), + AUTOFORMAT_COLOR( 41, 48, THEMED_STYLE_SUBTLE, XML_dk1 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spPlotArea2dFills[] = +{ + AUTOFORMAT_COLOR( 1, 32, THEMED_STYLE_SUBTLE, XML_bg1 ), + AUTOFORMAT_COLORMOD( 33, 34, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 20000 ), + AUTOFORMAT_ACCENTSMOD( 35, THEMED_STYLE_SUBTLE, XML_tint, 20000 ), // tint not documented!? + AUTOFORMAT_COLORMOD( 41, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spFloorLines[] = +{ + AUTOFORMAT_COLORMOD( 1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ), + AUTOFORMAT_COLORMOD( 33, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ), + // 41...48: no line, same as Chart2 + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spWallFloorFills[] = +{ + AUTOFORMAT_INVISIBLE( 1, 32 ), + AUTOFORMAT_COLORMOD( 33, 34, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 20000 ), + AUTOFORMAT_ACCENTSMOD( 35, THEMED_STYLE_SUBTLE, XML_tint, 20000 ), // tint not documented!? + AUTOFORMAT_COLORMOD( 41, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spAxisLines[] = +{ + AUTOFORMAT_COLORMOD( 1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ), // tint not documented!? + AUTOFORMAT_COLORMOD( 33, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ), // tint not documented!? + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spMajorGridLines[] = +{ + AUTOFORMAT_COLORMOD( 1, 32, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 75000 ), // tint not documented!? + AUTOFORMAT_COLORMOD( 33, 48, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 75000 ), // tint not documented!? + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spMinorGridLines[] = +{ + AUTOFORMAT_COLORMOD( 1, 40, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 50000 ), + AUTOFORMAT_COLORMOD( 41, 48, THEMED_STYLE_SUBTLE, XML_tx1, XML_tint, 90000 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spOtherLines[] = +{ + AUTOFORMAT_COLOR( 1, 32, THEMED_STYLE_SUBTLE, XML_tx1 ), + AUTOFORMAT_COLOR( 33, 34, THEMED_STYLE_SUBTLE, XML_dk1 ), + AUTOFORMAT_COLORMOD( 35, 40, THEMED_STYLE_SUBTLE, XML_dk1, XML_shade, 25000 ), + AUTOFORMAT_COLOR( 41, 48, THEMED_STYLE_SUBTLE, XML_lt1 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spLinearSeriesLines[] = +{ + AUTOFORMAT_PATTERN( 1, 1, THEMED_STYLE_SUBTLE, 300, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 2, 2, THEMED_STYLE_SUBTLE, 300, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 3, THEMED_STYLE_SUBTLE, 300 ), + AUTOFORMAT_PATTERN( 9, 9, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 10, 10, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 11, THEMED_STYLE_SUBTLE, 500 ), + AUTOFORMAT_PATTERN( 17, 17, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 18, 18, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 19, THEMED_STYLE_SUBTLE, 500 ), + AUTOFORMAT_PATTERN( 25, 25, THEMED_STYLE_SUBTLE, 700, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 26, 26, THEMED_STYLE_SUBTLE, 700, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 27, THEMED_STYLE_SUBTLE, 700 ), + AUTOFORMAT_PATTERN( 33, 33, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 34, 34, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 35, THEMED_STYLE_SUBTLE, 500 ), + AUTOFORMAT_PATTERN( 41, 42, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern4 ), + AUTOFORMAT_PATTERN( 42, 42, THEMED_STYLE_SUBTLE, 500, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 43, THEMED_STYLE_SUBTLE, 500 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spFilledSeriesLines[] = +{ + AUTOFORMAT_INVISIBLE( 1, 8 ), + AUTOFORMAT_COLOR( 9, 16, THEMED_STYLE_SUBTLE, XML_lt1 ), + AUTOFORMAT_INVISIBLE( 17, 32 ), + AUTOFORMAT_COLORMOD( 33, 33, THEMED_STYLE_SUBTLE, XML_dk1, XML_shade, 50000 ), + AUTOFORMAT_PATTERN( 34, 34, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern3 ), + AUTOFORMAT_ACCENTSMOD( 35, THEMED_STYLE_SUBTLE, XML_shade, 50000 ), + AUTOFORMAT_INVISIBLE( 41, 48 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spFilledSeries2dFills[] = +{ + AUTOFORMAT_PATTERN( 1, 1, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 2, 2, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 3, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 9, 9, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 10, 10, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 11, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 17, 17, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 18, 18, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 19, THEMED_STYLE_INTENSE, 100 ), + AUTOFORMAT_PATTERN( 25, 25, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 26, 26, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 27, THEMED_STYLE_INTENSE, 100 ), + AUTOFORMAT_PATTERN( 33, 33, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 34, 34, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 35, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 41, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern4 ), + AUTOFORMAT_PATTERN( 42, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 43, THEMED_STYLE_INTENSE, 100 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spFilledSeries3dFills[] = +{ + AUTOFORMAT_PATTERN( 1, 1, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 2, 2, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 3, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 9, 9, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 10, 10, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 11, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 17, 17, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 18, 18, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 19, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 25, 25, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 26, 26, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 27, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 33, 33, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern1 ), + AUTOFORMAT_PATTERN( 34, 34, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 35, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_PATTERN( 41, 42, THEMED_STYLE_SUBTLE, 100, spAutoFormatPattern4 ), + AUTOFORMAT_PATTERN( 42, 42, THEMED_STYLE_INTENSE, 100, spAutoFormatPattern2 ), + AUTOFORMAT_FADEDACCENTS( 43, THEMED_STYLE_SUBTLE, 100 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spFilledSeriesEffects[] = +{ + // 1...8: no effect, same as Chart2 + AUTOFORMAT_COLOR( 9, 16, THEMED_STYLE_SUBTLE, XML_dk1 ), + AUTOFORMAT_COLOR( 17, 24, THEMED_STYLE_MODERATE, XML_dk1 ), + AUTOFORMAT_COLOR( 25, 32, THEMED_STYLE_INTENSE, XML_dk1 ), + // 33...40: no effect, same as Chart2 + AUTOFORMAT_COLOR( 41, 48, THEMED_STYLE_INTENSE, XML_dk1 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spUpDownBarLines[] = +{ + AUTOFORMAT_COLOR( 1, 16, THEMED_STYLE_SUBTLE, XML_tx1 ), + AUTOFORMAT_INVISIBLE( 17, 32 ), + AUTOFORMAT_COLOR( 33, 34, THEMED_STYLE_SUBTLE, XML_dk1 ), + AUTOFORMAT_ACCENTSMOD( 35, THEMED_STYLE_SUBTLE, XML_shade, 25000 ), + AUTOFORMAT_INVISIBLE( 41, 48 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spUpBarFills[] = +{ + AUTOFORMAT_COLORMOD( 1, 1, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 2, 2, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 5000 ), + AUTOFORMAT_ACCENTSMOD( 3, THEMED_STYLE_SUBTLE, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 9, 9, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 10, 10, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 5000 ), + AUTOFORMAT_ACCENTSMOD( 11, THEMED_STYLE_SUBTLE, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 17, 17, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 18, 18, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 5000 ), + AUTOFORMAT_ACCENTSMOD( 19, THEMED_STYLE_INTENSE, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 25, 25, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ), + AUTOFORMAT_COLORMOD( 26, 26, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 5000 ), + AUTOFORMAT_ACCENTSMOD( 27, THEMED_STYLE_INTENSE, XML_tint, 25000 ), + AUTOFORMAT_COLOR( 33, 40, THEMED_STYLE_SUBTLE, XML_lt1 ), + AUTOFORMAT_COLORMOD( 41, 41, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 25000 ), + AUTOFORMAT_COLOR( 42, 42, THEMED_STYLE_INTENSE, XML_lt1 ), + AUTOFORMAT_ACCENTSMOD( 43, THEMED_STYLE_INTENSE, XML_tint, 25000 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spDownBarFills[] = +{ + AUTOFORMAT_COLORMOD( 1, 1, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLORMOD( 2, 2, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_ACCENTSMOD( 3, THEMED_STYLE_SUBTLE, XML_shade, 25000 ), + AUTOFORMAT_COLORMOD( 9, 9, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLORMOD( 10, 10, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_ACCENTSMOD( 11, THEMED_STYLE_SUBTLE, XML_shade, 25000 ), + AUTOFORMAT_COLORMOD( 17, 17, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLORMOD( 18, 18, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_ACCENTSMOD( 19, THEMED_STYLE_INTENSE, XML_shade, 25000 ), + AUTOFORMAT_COLORMOD( 25, 25, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLORMOD( 26, 26, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_ACCENTSMOD( 27, THEMED_STYLE_INTENSE, XML_shade, 25000 ), + AUTOFORMAT_COLORMOD( 33, 33, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLORMOD( 34, 34, THEMED_STYLE_SUBTLE, XML_dk1, XML_tint, 95000 ), + AUTOFORMAT_ACCENTSMOD( 27, THEMED_STYLE_SUBTLE, XML_shade, 25000 ), + AUTOFORMAT_COLORMOD( 41, 41, THEMED_STYLE_INTENSE, XML_dk1, XML_tint, 85000 ), + AUTOFORMAT_COLOR( 42, 42, THEMED_STYLE_INTENSE, XML_dk1 ), + AUTOFORMAT_ACCENTSMOD( 43, THEMED_STYLE_INTENSE, XML_shade, 25000 ), + AUTOFORMAT_END() +}; + +static const AutoFormatEntry spUpDownBarEffects[] = +{ + // 1...8: no effect, same as Chart2 + AUTOFORMAT_COLOR( 9, 16, THEMED_STYLE_SUBTLE, XML_dk1 ), + AUTOFORMAT_COLOR( 17, 24, THEMED_STYLE_MODERATE, XML_dk1 ), + AUTOFORMAT_COLOR( 25, 32, THEMED_STYLE_INTENSE, XML_dk1 ), + // 33...40: no effect, same as Chart2 + AUTOFORMAT_COLOR( 41, 48, THEMED_STYLE_INTENSE, XML_dk1 ), + AUTOFORMAT_END() +}; + +#undef AUTOFORMAT_COLOR +#undef AUTOFORMAT_ACCENTS +#undef AUTOFORMAT_COLORMOD +#undef AUTOFORMAT_ACCENTSMOD +#undef AUTOFORMAT_PATTERN +#undef AUTOFORMAT_FADED +#undef AUTOFORMAT_FADEDACCENTS +#undef AUTOFORMAT_INVISIBLE +#undef AUTOFORMAT_END + +const AutoFormatEntry* lclGetAutoFormatEntry( const AutoFormatEntry* pEntries, sal_Int32 nStyle ) +{ + for( ; pEntries && (pEntries->mnFirstStyleIdx >= 0); ++pEntries ) + if( (pEntries->mnFirstStyleIdx <= nStyle) && (nStyle <= pEntries->mnLastStyleIdx) ) + return pEntries; + return 0; +} + +// ---------------------------------------------------------------------------- + +struct AutoTextEntry +{ + sal_Int32 mnFirstStyleIdx; /// First chart style index. + sal_Int32 mnLastStyleIdx; /// Last chart style index. + sal_Int32 mnThemedFont; /// Themed font (minor/major). + sal_Int32 mnColorToken; /// Theme color token. + sal_Int32 mnDefFontSize; /// Default font size (1/100 points). + sal_Int32 mnRelFontSize; /// Font size relative to chart global font (percent). + bool mbBold; /// True = bold font. +}; + +#define AUTOTEXT_COLOR( first, last, themed_font, color_token, def_font_size, rel_font_size, bold ) \ + { first, last, themed_font, color_token, def_font_size, rel_font_size, bold } + +#define AUTOTEXT_END() \ + AUTOTEXT_COLOR( -1, -1, XML_none, XML_TOKEN_INVALID, 1000, 100, false ) + +static const AutoTextEntry spChartTitleTexts[] = +{ + AUTOTEXT_COLOR( 1, 40, XML_minor, XML_tx1, 1800, 120, true ), + AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1800, 120, true ), + AUTOTEXT_END() +}; + +static const AutoTextEntry spAxisTitleTexts[] = +{ + AUTOTEXT_COLOR( 1, 40, XML_minor, XML_tx1, 1000, 100, true ), + AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1000, 100, true ), + AUTOTEXT_END() +}; + +static const AutoTextEntry spOtherTexts[] = +{ + AUTOTEXT_COLOR( 1, 40, XML_minor, XML_tx1, 1000, 100, false ), + AUTOTEXT_COLOR( 41, 48, XML_minor, XML_lt1, 1000, 100, false ), + AUTOTEXT_END() +}; + +#undef AUTOTEXT_COLOR +#undef AUTOTEXT_END + +const AutoTextEntry* lclGetAutoTextEntry( const AutoTextEntry* pEntries, sal_Int32 nStyle ) +{ + for( ; pEntries && (pEntries->mnFirstStyleIdx >= 0); ++pEntries ) + if( (pEntries->mnFirstStyleIdx <= nStyle) && (nStyle <= pEntries->mnLastStyleIdx) ) + return pEntries; + return 0; +} + +// ---------------------------------------------------------------------------- + +/** Enumerates different sets of property names for chart object formatting. */ +enum PropertyType +{ + PROPERTYTYPE_COMMON, /// Common objects, no special handling. + PROPERTYTYPE_LINEARSERIES, /// Specific to linear data series. + PROPERTYTYPE_FILLEDSERIES /// Specific to filled data series. +}; + +/** Contains information about formatting of a specific chart object type. */ +struct ObjectTypeFormatEntry +{ + ObjectType meObjType; /// Object type for automatic format. + PropertyType mePropType; /// Property type for property names. + const AutoFormatEntry* mpAutoLines; /// Automatic line formatting for all chart styles. + const AutoFormatEntry* mpAutoFills; /// Automatic fill formatting for all chart styles. + const AutoFormatEntry* mpAutoEffects; /// Automatic effect formatting for all chart styles. + const AutoTextEntry* mpAutoTexts; /// Automatic text attributes for all chart styles. + bool mbIsFrame; /// True = object is a frame, false = object is a line. +}; + +#define TYPEFORMAT_FRAME( obj_type, prop_type, auto_texts, auto_lines, auto_fills, auto_effects ) \ + { obj_type, prop_type, auto_lines, auto_fills, auto_effects, auto_texts, true } + +#define TYPEFORMAT_LINE( obj_type, prop_type, auto_texts, auto_lines ) \ + { obj_type, prop_type, auto_lines, 0, 0, auto_texts, false } + +static const ObjectTypeFormatEntry spObjTypeFormatEntries[] = +{ + // object type property type auto text auto line auto fill auto effect + TYPEFORMAT_FRAME( OBJECTTYPE_CHARTSPACE, PROPERTYTYPE_COMMON, 0, spChartSpaceLines, spChartSpaceFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_CHARTTITLE, PROPERTYTYPE_COMMON, spChartTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_LEGEND, PROPERTYTYPE_COMMON, spOtherTexts, spNoFormats, spNoFormats, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA2D, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, spPlotArea2dFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA3D, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_WALL, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, spWallFloorFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_FLOOR, PROPERTYTYPE_COMMON, 0, spFloorLines, spWallFloorFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_AXIS, PROPERTYTYPE_COMMON, spOtherTexts, spAxisLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_AXISTITLE, PROPERTYTYPE_COMMON, spAxisTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_AXISUNIT, PROPERTYTYPE_COMMON, spAxisTitleTexts, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_MAJORGRIDLINE, PROPERTYTYPE_COMMON, 0, spMajorGridLines ), + TYPEFORMAT_LINE( OBJECTTYPE_MINORGRIDLINE, PROPERTYTYPE_COMMON, 0, spMinorGridLines ), + TYPEFORMAT_LINE( OBJECTTYPE_LINEARSERIES2D, PROPERTYTYPE_LINEARSERIES, 0, spLinearSeriesLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES2D, PROPERTYTYPE_FILLEDSERIES, 0, spFilledSeriesLines, spFilledSeries2dFills, spFilledSeriesEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES3D, PROPERTYTYPE_FILLEDSERIES, 0, spFilledSeriesLines, spFilledSeries3dFills, spFilledSeriesEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_DATALABEL, PROPERTYTYPE_COMMON, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_TRENDLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_TRENDLINELABEL, PROPERTYTYPE_COMMON, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_ERRORBAR, PROPERTYTYPE_COMMON, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_SERLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_LEADERLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_DROPLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_HILOLINE, PROPERTYTYPE_LINEARSERIES, 0, spOtherLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_UPBAR, PROPERTYTYPE_COMMON, 0, spUpDownBarLines, spUpBarFills, spUpDownBarEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_DOWNBAR, PROPERTYTYPE_COMMON, 0, spUpDownBarLines, spDownBarFills, spUpDownBarEffects ), + TYPEFORMAT_LINE( OBJECTTYPE_DATATABLE, PROPERTYTYPE_COMMON, spOtherTexts, spChartSpaceLines ) +}; + +#undef TYPEFORMAT_FRAME +#undef TYPEFORMAT_LINE +// ---------------------------------------------------------------------------- + +void lclConvertPictureOptions( FillProperties& orFillProps, const PictureOptionsModel& rPicOptions ) +{ + bool bStacked = (rPicOptions.mnPictureFormat == XML_stack) || (rPicOptions.mnPictureFormat == XML_stackScale); + orFillProps.maBlipProps.moBitmapMode = bStacked ? XML_tile : XML_stretch; +} + +// ---------------------------------------------------------------------------- + +const sal_Int32 spnCommonLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; +const sal_Int32 spnLinearLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; +const sal_Int32 spnFilledLineIds[ LineId_END ] = { PROP_BorderStyle, PROP_BorderWidth, PROP_BorderColor, PROP_BorderTransparency, PROP_BorderDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; + +const sal_Int32 spnCommonFillIds[ FillId_END ] = { PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; +const sal_Int32 spnFilledFillIds[ FillId_END ] = { PROP_FillStyle, PROP_Color, PROP_Transparency, PROP_GradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; + +} // namespace + +// ============================================================================ + +struct ObjectFormatterData; + +// ---------------------------------------------------------------------------- + +class DetailFormatterBase +{ +public: + explicit DetailFormatterBase( + ObjectFormatterData& rData, + const AutoFormatEntry* pAutoFormatEntry ); + explicit DetailFormatterBase( + ObjectFormatterData& rData, + const AutoTextEntry* pAutoTextEntry ); + +protected: + /** Returns the placeholder color which may depend on the passed series index. */ + sal_Int32 getPhColor( sal_Int32 nSeriesIdx ) const; + +private: + /** Resolves and returns the scheme color with the passed transformation. */ + sal_Int32 getSchemeColor( sal_Int32 nColorToken, sal_Int32 nModToken, sal_Int32 nModValue ) const; + +protected: + typedef ::std::vector< sal_Int32 > ColorPatternVec; + + ObjectFormatterData& mrData; /// Shared formatter data. + sal_Int32 mnPhClr; /// RGB placeholder color for themed style. + ColorPatternVec maColorPattern; /// Different cycling colors for data series. +}; + +// ---------------------------------------------------------------------------- + +class LineFormatter : public DetailFormatterBase +{ +public: + explicit LineFormatter( + ObjectFormatterData& rData, + const AutoFormatEntry* pAutoFormatEntry, + PropertyType ePropType ); + + /** Converts line formatting to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const ModelRef< Shape >& rxShapeProp, + sal_Int32 nSeriesIdx ); + +private: + LinePropertiesPtr mxAutoLine; /// Automatic line properties. + LinePropertyIds& mrLinePropIds; /// Property identifiers for border/line formatting. +}; + +// ---------------------------------------------------------------------------- + +class FillFormatter : public DetailFormatterBase +{ +public: + explicit FillFormatter( + ObjectFormatterData& rData, + const AutoFormatEntry* pAutoFormatEntry, + PropertyType ePropType ); + + /** Converts area formatting to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const ModelRef< Shape >& rxShapeProp, + const PictureOptionsModel* pPicOptions, + sal_Int32 nSeriesIdx ); + +private: + FillPropertiesPtr mxAutoFill; /// Automatic fill properties. + FillPropertyIds& mrFillPropIds; /// Property identifiers for fill formatting. +}; + +// ---------------------------------------------------------------------------- + +class EffectFormatter : public DetailFormatterBase +{ +public: + explicit EffectFormatter( + ObjectFormatterData& rData, + const AutoFormatEntry* pAutoFormatEntry, + PropertyType ePropType ); + + /** Converts effect formatting to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const ModelRef< Shape >& rxShapeProp, + sal_Int32 nSeriesIdx ); +}; + +// ---------------------------------------------------------------------------- + +class TextFormatter : public DetailFormatterBase +{ +public: + explicit TextFormatter( + ObjectFormatterData& rData, + const AutoTextEntry* pAutoTextEntry, + const ModelRef< TextBody >& rxGlobalTextProp ); + + /** Converts text formatting to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const TextCharacterProperties* pTextProps ); + /** Converts text formatting to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const ModelRef< TextBody >& rxTextProp ); + +private: + TextCharacterPropertiesPtr mxAutoText; /// Automatic text properties. +}; + +// ---------------------------------------------------------------------------- + +/** Formatter for a specific object type. */ +class ObjectTypeFormatter +{ +public: + explicit ObjectTypeFormatter( + ObjectFormatterData& rData, + const ObjectTypeFormatEntry& rEntry, + const ChartSpaceModel& rChartSpace ); + + /** Sets frame formatting properties to the passed property set. */ + void convertFrameFormatting( + PropertySet& rPropSet, + const ModelRef< Shape >& rxShapeProp, + const PictureOptionsModel* pPicOptions, + sal_Int32 nSeriesIdx ); + + /** Sets text formatting properties to the passed property set. */ + void convertTextFormatting( + PropertySet& rPropSet, + const ModelRef< TextBody >& rxTextProp ); + + /** Sets frame/text formatting properties to the passed property set. */ + void convertFormatting( + PropertySet& rPropSet, + const ModelRef< Shape >& rxShapeProp, + const ModelRef< TextBody >& rxTextProp ); + + /** Sets text formatting properties to the passed property set. */ + void convertTextFormatting( + PropertySet& rPropSet, + const TextCharacterProperties& rTextProps ); + + /** Sets automatic line properties to the passed property set. */ + void convertAutomaticLine( + PropertySet& rPropSet, + sal_Int32 nSeriesIdx ); + + /** Sets automatic fill properties to the passed property set. */ + void convertAutomaticFill( + PropertySet& rPropSet, + sal_Int32 nSeriesIdx ); + +private: + LineFormatter maLineFormatter; /// Converter for line formatting. + FillFormatter maFillFormatter; /// Converter for fill formatting. + EffectFormatter maEffectFormatter; /// Converter for effect formatting. + TextFormatter maTextFormatter; /// Converter for text formatting. + const ObjectTypeFormatEntry& mrEntry; /// Additional settings. +}; + +// ---------------------------------------------------------------------------- + +struct ObjectFormatterData +{ + typedef RefMap< ObjectType, ObjectTypeFormatter > ObjectTypeFormatterMap; + + const XmlFilterBase& mrFilter; /// Base filter object. + ObjectTypeFormatterMap maTypeFormatters; /// Formatters for all types of objects in a chart. + ModelObjectHelper maModelObjHelper; /// Helper for named drawing formatting (dashes, gradients, bitmaps). + LinePropertyIds maCommonLineIds; /// Property identifiers for common border formatting. + LinePropertyIds maLinearLineIds; /// Property identifiers for line formatting of linear series. + LinePropertyIds maFilledLineIds; /// Property identifiers for line formatting of filled series. + FillPropertyIds maCommonFillIds; /// Property identifiers for common area fill. + FillPropertyIds maFilledFillIds; /// Property identifiers for area fill of filled series. + Reference< XNumberFormats > mxNumFmts; /// Number formats collection of container document. + Reference< XNumberFormatTypes > mxNumTypes; /// Number format types collection of container document. + Locale maEnUsLocale; /// Locale struct containing en-US. + Locale maFromLocale; /// Empty locale struct. + sal_Int32 mnMaxSeriesIdx; /// Maximum series index used for color cycling/fading. + + explicit ObjectFormatterData( + const XmlFilterBase& rFilter, + const Reference< XChartDocument >& rxChartDoc, + const ChartSpaceModel& rChartSpace ); + + ObjectTypeFormatter* getTypeFormatter( ObjectType eObjType ); + + LinePropertyIds& getLinePropertyIds( PropertyType ePropType ); + FillPropertyIds& getFillPropertyIds( PropertyType ePropType ); +}; + +// ============================================================================ + +DetailFormatterBase::DetailFormatterBase( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry ) : + mrData( rData ), + mnPhClr( -1 ) +{ + if( pAutoFormatEntry ) + { + if( pAutoFormatEntry->mpPattern ) + { + // prepare multi-color pattern + for( const AutoFormatPatternEntry* pPatternEntry = pAutoFormatEntry->mpPattern; pPatternEntry->mnColorToken != XML_TOKEN_INVALID; ++pPatternEntry ) + maColorPattern.push_back( getSchemeColor( pPatternEntry->mnColorToken, pPatternEntry->mnModToken, pPatternEntry->mnModValue ) ); + } + else if( pAutoFormatEntry->mnColorToken != XML_TOKEN_INVALID ) + { + // prepare color or single-color pattern (color fading) + mnPhClr = getSchemeColor( pAutoFormatEntry->mnColorToken, pAutoFormatEntry->mnModToken, pAutoFormatEntry->mnModValue ); + if( pAutoFormatEntry->mbFadedColor ) + maColorPattern.push_back( mnPhClr ); + } + } +} + +DetailFormatterBase::DetailFormatterBase( ObjectFormatterData& rData, const AutoTextEntry* pAutoTextEntry ) : + mrData( rData ), + mnPhClr( -1 ) +{ + if( pAutoTextEntry && (pAutoTextEntry->mnColorToken != XML_TOKEN_INVALID) ) + mnPhClr = getSchemeColor( pAutoTextEntry->mnColorToken, XML_TOKEN_INVALID, 0 ); +} + +sal_Int32 DetailFormatterBase::getPhColor( sal_Int32 nSeriesIdx ) const +{ + if( maColorPattern.empty() || (mrData.mnMaxSeriesIdx < 0) || (nSeriesIdx < 0) ) + return mnPhClr; + + /* Apply tint/shade depending on the cycle index. The colors of leading + series are darkened (color shade), the colors of trailing series are + lightened (color tint). Shade/tint is applied in an exclusive range of + -70% to 70%. + + Example 1: 3 data series using single-color shading with accent color 1 + (e.g. automatic chart style #3). Shade/tint is applied per series. + Shade/tint changes in steps of 140%/(<series_count+1) = 140%/4 = 35%, + starting at -70%: + Step 1: -70% -> Not used. + Step 2: -35% -> Series 1 has 35% shade of accent color 1. + Step 3: 0% -> Series 2 has pure accent color 1. + Step 4: 35% -> Series 3 has 35% tint of accent color 1. + Step 5: 70% -> Not used. + + Example 2: 20 data series using accent color pattern (e.g. automatic + chart style #2). Each color cycle has a size of 6 series (accent colors + 1 to 6). Shade/tint is applied per color cycle. + Cycle #1: Series 1...6 are based on accent colors 1 to 6. + Cycle #2: Series 7...12 are based on accent colors 1 to 6. + Cycle #3: Series 13...18 are based on accent colors 1 to 6. + Cycle #4: Series 19...20 are based on accent colors 1 to 2. + Shade/tint changes in steps of 140%/(cycle_count+1) = 140%/5 = 28%, + starting at -70%: + Step 1: -70% -> Not used. + Step 2: -42% -> Cycle #1 has 42% shade of accent colors 1...6 + step 3: -14% -> Cycle #2 has 14% shade of accent colors 1...6 + step 4: 14% -> Cycle #3 has 14% tint of accent colors 1...6 + step 5: 42% -> Cycle #4 has 42% tint of accent colors 1...6 + step 6: 70% -> Not used. + */ + sal_Int32 nPhClr = maColorPattern[ static_cast< size_t >( nSeriesIdx % maColorPattern.size() ) ]; + size_t nCycleIdx = static_cast< size_t >( nSeriesIdx / maColorPattern.size() ); + size_t nMaxCycleIdx = static_cast< size_t >( mrData.mnMaxSeriesIdx / maColorPattern.size() ); + double fShadeTint = static_cast< double >( nCycleIdx + 1 ) / (nMaxCycleIdx + 2) * 1.4 - 0.7; + if( fShadeTint != 0.0 ) + { + Color aColor; + aColor.setSrgbClr( nPhClr ); + aColor.addChartTintTransformation( fShadeTint ); + nPhClr = aColor.getColor( mrData.mrFilter.getGraphicHelper() ); + } + + return nPhClr; +} + +sal_Int32 DetailFormatterBase::getSchemeColor( sal_Int32 nColorToken, sal_Int32 nModToken, sal_Int32 nModValue ) const +{ + Color aColor; + aColor.setSchemeClr( nColorToken ); + if( nModToken != XML_TOKEN_INVALID ) + aColor.addTransformation( nModToken, nModValue ); + return aColor.getColor( mrData.mrFilter.getGraphicHelper() ); +} + +// ============================================================================ + +LineFormatter::LineFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType ePropType ) : + DetailFormatterBase( rData, pAutoFormatEntry ), + mrLinePropIds( rData.getLinePropertyIds( ePropType ) ) +{ + if( pAutoFormatEntry ) + { + mxAutoLine.reset( new LineProperties ); + mxAutoLine->maLineFill.moFillType = XML_noFill; + if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() ) + if( const LineProperties* pLineProps = pTheme->getLineStyle( pAutoFormatEntry->mnThemedIdx ) ) + *mxAutoLine = *pLineProps; + // change line width according to chart auto style + if( mxAutoLine->moLineWidth.has() ) + mxAutoLine->moLineWidth = mxAutoLine->moLineWidth.get() * pAutoFormatEntry->mnRelLineWidth / 100; + } +} + +void LineFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ) +{ + LineProperties aLineProps; + if( mxAutoLine.get() ) + aLineProps.assignUsed( *mxAutoLine ); + if( rxShapeProp.is() ) + aLineProps.assignUsed( rxShapeProp->getLineProperties() ); + aLineProps.pushToPropSet( rPropSet, mrData.maModelObjHelper, mrData.mrFilter.getGraphicHelper(), mrLinePropIds, getPhColor( nSeriesIdx ) ); +} + +// ============================================================================ + +FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType ePropType ) : + DetailFormatterBase( rData, pAutoFormatEntry ), + mrFillPropIds( rData.getFillPropertyIds( ePropType ) ) +{ + if( pAutoFormatEntry ) + { + mxAutoFill.reset( new FillProperties ); + mxAutoFill->moFillType = XML_noFill; + if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() ) + if( const FillProperties* pFillProps = pTheme->getFillStyle( pAutoFormatEntry->mnThemedIdx ) ) + *mxAutoFill = *pFillProps; + } +} + +void FillFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) +{ + FillProperties aFillProps; + if( mxAutoFill.get() ) + aFillProps.assignUsed( *mxAutoFill ); + if( rxShapeProp.is() ) + aFillProps.assignUsed( rxShapeProp->getFillProperties() ); + if( pPicOptions ) + lclConvertPictureOptions( aFillProps, *pPicOptions ); + aFillProps.pushToPropSet( rPropSet, mrData.maModelObjHelper, mrData.mrFilter.getGraphicHelper(), mrFillPropIds, 0, getPhColor( nSeriesIdx ) ); +} + +// ============================================================================ + +EffectFormatter::EffectFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType /*ePropType*/ ) : + DetailFormatterBase( rData, pAutoFormatEntry ) +{ +} + +void EffectFormatter::convertFormatting( PropertySet& /*rPropSet*/, const ModelRef< Shape >& /*rxShapeProp*/, sal_Int32 /*nSeriesIdx*/ ) +{ +} + +// ============================================================================ + +namespace { + +const TextCharacterProperties* lclGetTextProperties( const ModelRef< TextBody >& rxTextProp ) +{ + return (rxTextProp.is() && !rxTextProp->getParagraphs().empty()) ? + &rxTextProp->getParagraphs().front()->getProperties().getTextCharacterProperties() : 0; +} + +} // namespace + +TextFormatter::TextFormatter( ObjectFormatterData& rData, const AutoTextEntry* pAutoTextEntry, const ModelRef< TextBody >& rxGlobalTextProp ) : + DetailFormatterBase( rData, pAutoTextEntry ) +{ + if( pAutoTextEntry ) + { + mxAutoText.reset( new TextCharacterProperties ); + if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() ) + if( const TextCharacterProperties* pTextProps = pTheme->getFontStyle( pAutoTextEntry->mnThemedFont ) ) + *mxAutoText = *pTextProps; + sal_Int32 nTextColor = getPhColor( -1 ); + if( nTextColor >= 0 ) + mxAutoText->maCharColor.setSrgbClr( nTextColor ); + mxAutoText->moHeight = pAutoTextEntry->mnDefFontSize; + mxAutoText->moBold = pAutoTextEntry->mbBold; + + if( const TextCharacterProperties* pTextProps = lclGetTextProperties( rxGlobalTextProp ) ) + { + mxAutoText->assignUsed( *pTextProps ); + if( pTextProps->moHeight.has() ) + mxAutoText->moHeight = pTextProps->moHeight.get() * pAutoTextEntry->mnRelFontSize / 100; + } + } +} + +void TextFormatter::convertFormatting( PropertySet& rPropSet, const TextCharacterProperties* pTextProps ) +{ + TextCharacterProperties aTextProps; + if( mxAutoText.get() ) + aTextProps.assignUsed( *mxAutoText ); + if( pTextProps ) + aTextProps.assignUsed( *pTextProps ); + aTextProps.pushToPropSet( rPropSet, mrData.mrFilter ); +} + +void TextFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp ) +{ + convertFormatting( rPropSet, lclGetTextProperties( rxTextProp ) ); +} + +// ============================================================================ + +ObjectTypeFormatter::ObjectTypeFormatter( ObjectFormatterData& rData, const ObjectTypeFormatEntry& rEntry, const ChartSpaceModel& rChartSpace ) : + maLineFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoLines, rChartSpace.mnStyle ), rEntry.mePropType ), + maFillFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoFills, rChartSpace.mnStyle ), rEntry.mePropType ), + maEffectFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoEffects, rChartSpace.mnStyle ), rEntry.mePropType ), + maTextFormatter( rData, lclGetAutoTextEntry( rEntry.mpAutoTexts, rChartSpace.mnStyle ), rChartSpace.mxTextProp ), + mrEntry( rEntry ) +{ +} + +void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) +{ + maLineFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); + if( mrEntry.mbIsFrame ) + maFillFormatter.convertFormatting( rPropSet, rxShapeProp, pPicOptions, nSeriesIdx ); + maEffectFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); +} + +void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp ) +{ + maTextFormatter.convertFormatting( rPropSet, rxTextProp ); +} + +void ObjectTypeFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const ModelRef< TextBody >& rxTextProp ) +{ + convertFrameFormatting( rPropSet, rxShapeProp, 0, -1 ); + convertTextFormatting( rPropSet, rxTextProp ); +} + +void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const TextCharacterProperties& rTextProps ) +{ + maTextFormatter.convertFormatting( rPropSet, &rTextProps ); +} + +void ObjectTypeFormatter::convertAutomaticLine( PropertySet& rPropSet, sal_Int32 nSeriesIdx ) +{ + ModelRef< Shape > xShapeProp; + maLineFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); + maEffectFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); +} + +void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 nSeriesIdx ) +{ + ModelRef< Shape > xShapeProp; + maFillFormatter.convertFormatting( rPropSet, xShapeProp, 0, nSeriesIdx ); + maEffectFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); +} + +// ============================================================================ + +ObjectFormatterData::ObjectFormatterData( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) : + mrFilter( rFilter ), + maModelObjHelper( Reference< XMultiServiceFactory >( rxChartDoc, UNO_QUERY ) ), + maCommonLineIds( spnCommonLineIds, true, false ), + maLinearLineIds( spnLinearLineIds, true, false ), + maFilledLineIds( spnFilledLineIds, true, false ), + maCommonFillIds( spnCommonFillIds, true, true ), + maFilledFillIds( spnFilledFillIds, true, true ), + maEnUsLocale( CREATE_OUSTRING( "en" ), CREATE_OUSTRING( "US" ), OUString() ), + mnMaxSeriesIdx( -1 ) +{ + const ObjectTypeFormatEntry* pEntryEnd = STATIC_ARRAY_END( spObjTypeFormatEntries ); + for( const ObjectTypeFormatEntry* pEntry = spObjTypeFormatEntries; pEntry != pEntryEnd; ++pEntry ) + maTypeFormatters[ pEntry->meObjType ].reset( new ObjectTypeFormatter( *this, *pEntry, rChartSpace ) ); + + try + { + Reference< XNumberFormatsSupplier > xNumFmtsSupp( mrFilter.getModel(), UNO_QUERY_THROW ); + mxNumFmts = xNumFmtsSupp->getNumberFormats(); + mxNumTypes.set( mxNumFmts, UNO_QUERY ); + } + catch( Exception& ) + { + } + OSL_ENSURE( mxNumFmts.is() && mxNumTypes.is(), "ObjectFormatterData::ObjectFormatterData - cannot get number formats" ); +} + +ObjectTypeFormatter* ObjectFormatterData::getTypeFormatter( ObjectType eObjType ) +{ + OSL_ENSURE( maTypeFormatters.has( eObjType ), "ObjectFormatterData::getTypeFormatter - unknown object type" ); + return maTypeFormatters.get( eObjType ).get(); +} + +LinePropertyIds& ObjectFormatterData::getLinePropertyIds( PropertyType ePropType ) +{ + switch( ePropType ) + { + case PROPERTYTYPE_COMMON: return maCommonLineIds; + case PROPERTYTYPE_LINEARSERIES: return maLinearLineIds; + case PROPERTYTYPE_FILLEDSERIES: return maFilledLineIds; + } + return maCommonLineIds; +} + +FillPropertyIds& ObjectFormatterData::getFillPropertyIds( PropertyType ePropType ) +{ + switch( ePropType ) + { + case PROPERTYTYPE_COMMON: return maCommonFillIds; + case PROPERTYTYPE_LINEARSERIES: return maCommonFillIds; + case PROPERTYTYPE_FILLEDSERIES: return maFilledFillIds; + } + return maCommonFillIds; +} + +// ============================================================================ + +ObjectFormatter::ObjectFormatter( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) : + mxData( new ObjectFormatterData( rFilter, rxChartDoc, rChartSpace ) ) +{ +} + +ObjectFormatter::~ObjectFormatter() +{ +} + +void ObjectFormatter::setMaxSeriesIndex( sal_Int32 nMaxSeriesIdx ) +{ + mxData->mnMaxSeriesIdx = nMaxSeriesIdx; +} + +sal_Int32 ObjectFormatter::getMaxSeriesIndex() const +{ + return mxData->mnMaxSeriesIdx; +} + +void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, ObjectType eObjType, sal_Int32 nSeriesIdx ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertFrameFormatting( rPropSet, rxShapeProp, 0, nSeriesIdx ); +} + +void ObjectFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel& rPicOptions, ObjectType eObjType, sal_Int32 nSeriesIdx ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertFrameFormatting( rPropSet, rxShapeProp, &rPicOptions, nSeriesIdx ); +} + +void ObjectFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertTextFormatting( rPropSet, rxTextProp ); +} + +void ObjectFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertFormatting( rPropSet, rxShapeProp, rxTextProp ); +} + +void ObjectFormatter::convertTextFormatting( PropertySet& rPropSet, const TextCharacterProperties& rTextProps, ObjectType eObjType ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertTextFormatting( rPropSet, rTextProps ); +} + +void ObjectFormatter::convertTextRotation( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp, bool bSupportsStacked ) +{ + if( rxTextProp.is() ) + { + bool bStacked = false; + if( bSupportsStacked ) + { + sal_Int32 nVert = rxTextProp->getTextProperties().moVert.get( XML_horz ); + bStacked = (nVert == XML_wordArtVert) || (nVert == XML_wordArtVertRtl); + rPropSet.setProperty( PROP_StackCharacters, bStacked ); + } + + /* Chart2 expects rotation angle as double value in range of [0,360). + OOXML counts clockwise, Chart2 counts counterclockwise. */ + double fAngle = static_cast< double >( bStacked ? 0 : rxTextProp->getTextProperties().moRotation.get( 0 ) ); + fAngle = getDoubleIntervalValue< double >( -fAngle / 60000.0, 0.0, 360.0 ); + rPropSet.setProperty( PROP_TextRotation, fAngle ); + } +} + +void ObjectFormatter::convertNumberFormat( PropertySet& rPropSet, const NumberFormat& rNumberFormat, bool bPercentFormat ) +{ + if( mxData->mxNumFmts.is() ) + { + sal_Int32 nPropId = bPercentFormat ? PROP_PercentageNumberFormat : PROP_NumberFormat; + if( rNumberFormat.mbSourceLinked || (rNumberFormat.maFormatCode.getLength() == 0) ) + { + rPropSet.setProperty( nPropId, Any() ); + } + else try + { + sal_Int32 nIndex = rNumberFormat.maFormatCode.equalsIgnoreAsciiCaseAscii( "general" ) ? + mxData->mxNumTypes->getStandardIndex( mxData->maFromLocale ) : + mxData->mxNumFmts->addNewConverted( rNumberFormat.maFormatCode, mxData->maEnUsLocale, mxData->maFromLocale ); + if( nIndex >= 0 ) + rPropSet.setProperty( nPropId, nIndex ); + } + catch( Exception& ) + { + OSL_ENSURE( false, + OStringBuffer( "ObjectFormatter::convertNumberFormat - cannot create number format '" ). + append( OUStringToOString( rNumberFormat.maFormatCode, osl_getThreadTextEncoding() ) ).append( '\'' ).getStr() ); + } + } +} + +void ObjectFormatter::convertAutomaticLine( PropertySet& rPropSet, ObjectType eObjType, sal_Int32 nSeriesIdx ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertAutomaticLine( rPropSet, nSeriesIdx ); +} + +void ObjectFormatter::convertAutomaticFill( PropertySet& rPropSet, ObjectType eObjType, sal_Int32 nSeriesIdx ) +{ + if( ObjectTypeFormatter* pFormat = mxData->getTypeFormatter( eObjType ) ) + pFormat->convertAutomaticFill( rPropSet, nSeriesIdx ); +} + +/*static*/ bool ObjectFormatter::isAutomaticLine( const ModelRef< Shape >& rxShapeProp ) +{ + return !rxShapeProp || !rxShapeProp->getLineProperties().maLineFill.moFillType.has(); +} + +/*static*/ bool ObjectFormatter::isAutomaticFill( const ModelRef< Shape >& rxShapeProp ) +{ + return !rxShapeProp || !rxShapeProp->getFillProperties().moFillType.has(); +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/plotareacontext.cxx b/oox/source/drawingml/chart/plotareacontext.cxx new file mode 100644 index 000000000000..17c6487b59b4 --- /dev/null +++ b/oox/source/drawingml/chart/plotareacontext.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * 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/chart/plotareacontext.hxx" + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/chart/axiscontext.hxx" +#include "oox/drawingml/chart/plotareamodel.hxx" +#include "oox/drawingml/chart/seriescontext.hxx" +#include "oox/drawingml/chart/titlecontext.hxx" +#include "oox/drawingml/chart/typegroupcontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; + +// ============================================================================ + +View3DContext::View3DContext( ContextHandler2Helper& rParent, View3DModel& rModel ) : + ContextBase< View3DModel >( rParent, rModel ) +{ +} + +View3DContext::~View3DContext() +{ +} + +ContextHandlerRef View3DContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( view3D ): + switch( nElement ) + { + case C_TOKEN( depthPercent ): + mrModel.mnDepthPercent = rAttribs.getInteger( XML_val, 100 ); + return 0; + case C_TOKEN( hPercent ): + mrModel.monHeightPercent = rAttribs.getInteger( XML_val, 100 ); + return 0; + case C_TOKEN( perspective ): + mrModel.mnPerspective = rAttribs.getInteger( XML_val, 30 ); + return 0; + case C_TOKEN( rAngAx ): + // default is 'false', not 'true' as specified + mrModel.mbRightAngled = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( rotX ): + // default value dependent on chart type + mrModel.monRotationX = rAttribs.getInteger( XML_val ); + return 0; + case C_TOKEN( rotY ): + // default value dependent on chart type + mrModel.monRotationY = rAttribs.getInteger( XML_val ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +WallFloorContext::WallFloorContext( ContextHandler2Helper& rParent, WallFloorModel& rModel ) : + ContextBase< WallFloorModel >( rParent, rModel ) +{ +} + +WallFloorContext::~WallFloorContext() +{ +} + +ContextHandlerRef WallFloorContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( backWall ): + case C_TOKEN( floor ): + case C_TOKEN( sideWall ): + switch( nElement ) + { + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +PlotAreaContext::PlotAreaContext( ContextHandler2Helper& rParent, PlotAreaModel& rModel ) : + ContextBase< PlotAreaModel >( rParent, rModel ) +{ +} + +PlotAreaContext::~PlotAreaContext() +{ +} + +ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( plotArea ): + switch( nElement ) + { + case C_TOKEN( area3DChart ): + case C_TOKEN( areaChart ): + return new AreaTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( bar3DChart ): + case C_TOKEN( barChart ): + return new BarTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( bubbleChart ): + return new BubbleTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( line3DChart ): + case C_TOKEN( lineChart ): + case C_TOKEN( stockChart ): + return new LineTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( doughnutChart ): + case C_TOKEN( ofPieChart ): + case C_TOKEN( pie3DChart ): + case C_TOKEN( pieChart ): + return new PieTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( radarChart ): + return new RadarTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( scatterChart ): + return new ScatterTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + case C_TOKEN( surface3DChart ): + case C_TOKEN( surfaceChart ): + return new SurfaceTypeGroupContext( *this, mrModel.maTypeGroups.create( nElement ) ); + + case C_TOKEN( catAx ): + return new CatAxisContext( *this, mrModel.maAxes.create( nElement ) ); + case C_TOKEN( dateAx ): + return new DateAxisContext( *this, mrModel.maAxes.create( nElement ) ); + case C_TOKEN( serAx ): + return new SerAxisContext( *this, mrModel.maAxes.create( nElement ) ); + case C_TOKEN( valAx ): + return new ValAxisContext( *this, mrModel.maAxes.create( nElement ) ); + + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/plotareaconverter.cxx b/oox/source/drawingml/chart/plotareaconverter.cxx new file mode 100644 index 000000000000..78379ae855bd --- /dev/null +++ b/oox/source/drawingml/chart/plotareaconverter.cxx @@ -0,0 +1,452 @@ +/************************************************************************* + * + * 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/chart/plotareaconverter.hxx" + +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XDiagramPositioning.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> +#include <com/sun/star/drawing/Direction3D.hpp> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <com/sun/star/drawing/ShadeMode.hpp> +#include "oox/drawingml/chart/axisconverter.hxx" +#include "oox/drawingml/chart/plotareamodel.hxx" +#include "oox/drawingml/chart/typegroupconverter.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +/** Axes set model. This is a helper for the plot area converter collecting all + type groups and axes of the primary or secondary axes set. */ +struct AxesSetModel +{ + typedef ModelVector< TypeGroupModel > TypeGroupVector; + typedef ModelMap< sal_Int32, AxisModel > AxisMap; + + TypeGroupVector maTypeGroups; /// All type groups containing data series. + AxisMap maAxes; /// All axes mapped by API axis type. + + inline explicit AxesSetModel() {} + inline ~AxesSetModel() {} +}; + +// ============================================================================ + +/** Axes set converter. This is a helper class for the plot area converter. */ +class AxesSetConverter : public ConverterBase< AxesSetModel > +{ +public: + explicit AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ); + virtual ~AxesSetConverter(); + + /** Converts the axes set model to a chart2 diagram. Returns an automatic + chart title from a single series title, if possible. */ + void convertFromModel( + const Reference< XDiagram >& rxDiagram, + View3DModel& rView3DModel, + sal_Int32 nAxesSetIdx, + bool bSupportsVaryColorsByPoint ); + + /** Returns the automatic chart title if the axes set contains only one series. */ + inline const ::rtl::OUString& getAutomaticTitle() const { return maAutoTitle; } + /** Returns true, if the chart is three-dimensional. */ + inline bool is3dChart() const { return mb3dChart; } + /** Returns true, if chart type supports wall and floor format in 3D mode. */ + inline bool isWall3dChart() const { return mbWall3dChart; } + /** Returns true, if chart is a pie chart or doughnut chart. */ + inline bool isPieChart() const { return mbPieChart; } + +private: + ::rtl::OUString maAutoTitle; + bool mb3dChart; + bool mbWall3dChart; + bool mbPieChart; +}; + +// ---------------------------------------------------------------------------- + +AxesSetConverter::AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ) : + ConverterBase< AxesSetModel >( rParent, rModel ), + mb3dChart( false ), + mbWall3dChart( false ), + mbPieChart( false ) +{ +} + +AxesSetConverter::~AxesSetConverter() +{ +} + +ModelRef< AxisModel > lclGetOrCreateAxis( const AxesSetModel::AxisMap& rFromAxes, sal_Int32 nAxisIdx, sal_Int32 nDefTypeId ) +{ + ModelRef< AxisModel > xAxis = rFromAxes.get( nAxisIdx ); + if( !xAxis ) + xAxis.create( nDefTypeId ).mbDeleted = true; // missing axis is invisible + return xAxis; +} + +void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, + View3DModel& rView3DModel, sal_Int32 nAxesSetIdx, bool bSupportsVaryColorsByPoint ) +{ + // create type group converter objects for all type groups + typedef RefVector< TypeGroupConverter > TypeGroupConvVector; + TypeGroupConvVector aTypeGroups; + for( AxesSetModel::TypeGroupVector::iterator aIt = mrModel.maTypeGroups.begin(), aEnd = mrModel.maTypeGroups.end(); aIt != aEnd; ++aIt ) + aTypeGroups.push_back( TypeGroupConvVector::value_type( new TypeGroupConverter( *this, **aIt ) ) ); + + OSL_ENSURE( !aTypeGroups.empty(), "AxesSetConverter::convertFromModel - no type groups in axes set" ); + if( !aTypeGroups.empty() ) try + { + // first type group needed for coordinate system and axis conversion + TypeGroupConverter& rFirstTypeGroup = *aTypeGroups.front(); + + // get automatic chart title, if there is only one type group + if( aTypeGroups.size() == 1 ) + maAutoTitle = rFirstTypeGroup.getSingleSeriesTitle(); + + /* Create a coordinate system. For now, all type groups from all axes sets + have to be inserted into one coordinate system. Later, chart2 should + support using one coordinate system for each axes set. */ + Reference< XCoordinateSystem > xCoordSystem; + Reference< XCoordinateSystemContainer > xCoordSystemCont( rxDiagram, UNO_QUERY_THROW ); + Sequence< Reference< XCoordinateSystem > > aCoordSystems = xCoordSystemCont->getCoordinateSystems(); + if( aCoordSystems.hasElements() ) + { + OSL_ENSURE( aCoordSystems.getLength() == 1, "AxesSetConverter::convertFromModel - too many coordinate systems" ); + xCoordSystem = aCoordSystems[ 0 ]; + OSL_ENSURE( xCoordSystem.is(), "AxesSetConverter::convertFromModel - invalid coordinate system" ); + } + else + { + xCoordSystem = rFirstTypeGroup.createCoordinateSystem(); + if( xCoordSystem.is() ) + xCoordSystemCont->addCoordinateSystem( xCoordSystem ); + } + + // 3D view settings + mb3dChart = rFirstTypeGroup.is3dChart(); + mbWall3dChart = rFirstTypeGroup.isWall3dChart(); + mbPieChart = rFirstTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE; + if( mb3dChart ) + { + View3DConverter aView3DConv( *this, rView3DModel ); + aView3DConv.convertFromModel( rxDiagram, rFirstTypeGroup ); + } + + /* Convert all chart type groups. Each type group will add its series + to the data provider attached to the chart document. */ + if( xCoordSystem.is() ) + { + // convert all axes (create missing axis models) + ModelRef< AxisModel > xXAxis = lclGetOrCreateAxis( mrModel.maAxes, API_X_AXIS, rFirstTypeGroup.getTypeInfo().mbCategoryAxis ? C_TOKEN( catAx ) : C_TOKEN( valAx ) ); + ModelRef< AxisModel > xYAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Y_AXIS, C_TOKEN( valAx ) ); + + AxisConverter aXAxisConv( *this, *xXAxis ); + aXAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, xYAxis.get(), nAxesSetIdx, API_X_AXIS ); + AxisConverter aYAxisConv( *this, *xYAxis ); + aYAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, xXAxis.get(), nAxesSetIdx, API_Y_AXIS ); + + if( rFirstTypeGroup.isDeep3dChart() ) + { + ModelRef< AxisModel > xZAxis = lclGetOrCreateAxis( mrModel.maAxes, API_Z_AXIS, C_TOKEN( serAx ) ); + AxisConverter aZAxisConv( *this, *xZAxis ); + aZAxisConv.convertFromModel( xCoordSystem, rFirstTypeGroup, 0, nAxesSetIdx, API_Z_AXIS ); + } + + // convert all chart type groups, this converts all series data and formatting + for( TypeGroupConvVector::iterator aTIt = aTypeGroups.begin(), aTEnd = aTypeGroups.end(); aTIt != aTEnd; ++aTIt ) + (*aTIt)->convertFromModel( rxDiagram, xCoordSystem, nAxesSetIdx, bSupportsVaryColorsByPoint ); + } + } + catch( Exception& ) + { + } +} + +} // namespace + +// ============================================================================ + +View3DConverter::View3DConverter( const ConverterRoot& rParent, View3DModel& rModel ) : + ConverterBase< View3DModel >( rParent, rModel ) +{ +} + +View3DConverter::~View3DConverter() +{ +} + +void View3DConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, TypeGroupConverter& rTypeGroup ) +{ + namespace cssd = ::com::sun::star::drawing; + PropertySet aPropSet( rxDiagram ); + + sal_Int32 nRotationY = 0; + sal_Int32 nRotationX = 0; + bool bRightAngled = false; + sal_Int32 nAmbientColor = 0; + sal_Int32 nLightColor = 0; + + if( rTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE ) + { + // Y rotation used as 'first pie slice angle' in 3D pie charts + rTypeGroup.convertPieRotation( aPropSet, mrModel.monRotationY.get( 0 ) ); + // X rotation a.k.a. elevation (map OOXML [0..90] to Chart2 [-90,0]) + nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.get( 15 ), 0, 90 ) - 90; + // no right-angled axes in pie charts + bRightAngled = false; + // ambient color (Gray 30%) + nAmbientColor = 0xB3B3B3; + // light color (Gray 70%) + nLightColor = 0x4C4C4C; + } + else // 3D bar/area/line charts + { + // Y rotation (OOXML [0..359], Chart2 [-179,180]) + nRotationY = mrModel.monRotationY.get( 20 ); + // X rotation a.k.a. elevation (OOXML [-90..90], Chart2 [-179,180]) + nRotationX = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.monRotationX.get( 15 ), -90, 90 ); + // right-angled axes + bRightAngled = mrModel.mbRightAngled; + // ambient color (Gray 20%) + nAmbientColor = 0xCCCCCC; + // light color (Gray 60%) + nLightColor = 0x666666; + } + + // Y rotation (map OOXML [0..359] to Chart2 [-179,180]) + nRotationY %= 360; + if( nRotationY > 180 ) nRotationY -= 360; + /* Perspective (map OOXML [0..200] to Chart2 [0,100]). Seems that MSO 2007 is + buggy here, the XML plugin of MSO 2003 writes the correct perspective in + the range from 0 to 100. We will emulate the wrong behaviour of MSO 2007. */ + sal_Int32 nPerspective = getLimitedValue< sal_Int32, sal_Int32 >( mrModel.mnPerspective / 2, 0, 100 ); + // projection mode (parallel axes, if right-angled, #i90360# or if perspective is at 0%) + bool bParallel = bRightAngled || (nPerspective == 0); + cssd::ProjectionMode eProjMode = bParallel ? cssd::ProjectionMode_PARALLEL : cssd::ProjectionMode_PERSPECTIVE; + + // set rotation properties + aPropSet.setProperty( PROP_RotationVertical, nRotationY ); + aPropSet.setProperty( PROP_RotationHorizontal, nRotationX ); + aPropSet.setProperty( PROP_Perspective, nPerspective ); + aPropSet.setProperty( PROP_RightAngledAxes, bRightAngled ); + aPropSet.setProperty( PROP_D3DScenePerspective, eProjMode ); + + // set light settings + aPropSet.setProperty( PROP_D3DSceneShadeMode, cssd::ShadeMode_FLAT ); + aPropSet.setProperty( PROP_D3DSceneAmbientColor, nAmbientColor ); + aPropSet.setProperty( PROP_D3DSceneLightOn1, false ); + aPropSet.setProperty( PROP_D3DSceneLightOn2, true ); + aPropSet.setProperty( PROP_D3DSceneLightColor2, nLightColor ); + aPropSet.setProperty( PROP_D3DSceneLightDirection2, cssd::Direction3D( 0.2, 0.4, 1.0 ) ); +} + +// ============================================================================ + +WallFloorConverter::WallFloorConverter( const ConverterRoot& rParent, WallFloorModel& rModel ) : + ConverterBase< WallFloorModel >( rParent, rModel ) +{ +} + +WallFloorConverter::~WallFloorConverter() +{ +} + +void WallFloorConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, ObjectType eObjType ) +{ + if( rxDiagram.is() ) + { + PropertySet aPropSet; + switch( eObjType ) + { + case OBJECTTYPE_FLOOR: aPropSet.set( rxDiagram->getFloor() ); break; + case OBJECTTYPE_WALL: aPropSet.set( rxDiagram->getWall() ); break; + default: OSL_ENSURE( false, "WallFloorConverter::convertFromModel - invalid object type" ); + } + if( aPropSet.is() ) + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType ); + } +} + +// ============================================================================ + +PlotAreaConverter::PlotAreaConverter( const ConverterRoot& rParent, PlotAreaModel& rModel ) : + ConverterBase< PlotAreaModel >( rParent, rModel ), + mb3dChart( false ), + mbWall3dChart( false ), + mbPieChart( false ) +{ +} + +PlotAreaConverter::~PlotAreaConverter() +{ +} + +void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel ) +{ + /* Create the diagram object and attach it to the chart document. One + diagram is used to carry all coordinate systems and data series. */ + Reference< XDiagram > xDiagram; + try + { + xDiagram.set( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Diagram" ) ), UNO_QUERY_THROW ); + getChartDocument()->setFirstDiagram( xDiagram ); + } + catch( Exception& ) + { + } + + // store all axis models in a map, keyed by axis identifier + typedef ModelMap< sal_Int32, AxisModel > AxisMap; + AxisMap aAxisMap; + for( PlotAreaModel::AxisVector::iterator aAIt = mrModel.maAxes.begin(), aAEnd = mrModel.maAxes.end(); aAIt != aAEnd; ++aAIt ) + { + PlotAreaModel::AxisVector::value_type xAxis = *aAIt; + OSL_ENSURE( xAxis->mnAxisId >= 0, "PlotAreaConverter::convertFromModel - invalid axis identifier" ); + OSL_ENSURE( !aAxisMap.has( xAxis->mnAxisId ), "PlotAreaConverter::convertFromModel - axis identifiers not unique" ); + if( xAxis->mnAxisId >= 0 ) + aAxisMap[ xAxis->mnAxisId ] = xAxis; + } + + // group the type group models into different axes sets + typedef ModelVector< AxesSetModel > AxesSetVector; + AxesSetVector aAxesSets; + sal_Int32 nMaxSeriesIdx = -1; + for( PlotAreaModel::TypeGroupVector::iterator aTIt = mrModel.maTypeGroups.begin(), aTEnd = mrModel.maTypeGroups.end(); aTIt != aTEnd; ++aTIt ) + { + PlotAreaModel::TypeGroupVector::value_type xTypeGroup = *aTIt; + if( !xTypeGroup->maSeries.empty() ) + { + // try to find a compatible axes set for the type group + AxesSetModel* pAxesSet = 0; + for( AxesSetVector::iterator aASIt = aAxesSets.begin(), aASEnd = aAxesSets.end(); !pAxesSet && (aASIt != aASEnd); ++aASIt ) + if( (*aASIt)->maTypeGroups.front()->maAxisIds == xTypeGroup->maAxisIds ) + pAxesSet = aASIt->get(); + + // not possible to insert into an existing axes set -> start a new axes set + if( !pAxesSet ) + { + pAxesSet = &aAxesSets.create(); + // find axis models used by the type group + const TypeGroupModel::AxisIdVector& rAxisIds = xTypeGroup->maAxisIds; + if( rAxisIds.size() >= 1 ) + pAxesSet->maAxes[ API_X_AXIS ] = aAxisMap.get( rAxisIds[ 0 ] ); + if( rAxisIds.size() >= 2 ) + pAxesSet->maAxes[ API_Y_AXIS ] = aAxisMap.get( rAxisIds[ 1 ] ); + if( rAxisIds.size() >= 3 ) + pAxesSet->maAxes[ API_Z_AXIS ] = aAxisMap.get( rAxisIds[ 2 ] ); + } + + // insert the type group model + pAxesSet->maTypeGroups.push_back( xTypeGroup ); + + // collect the maximum series index for automatic series formatting + for( TypeGroupModel::SeriesVector::iterator aSIt = xTypeGroup->maSeries.begin(), aSEnd = xTypeGroup->maSeries.end(); aSIt != aSEnd; ++aSIt ) + nMaxSeriesIdx = ::std::max( nMaxSeriesIdx, (*aSIt)->mnIndex ); + } + } + getFormatter().setMaxSeriesIndex( nMaxSeriesIdx ); + + // varying point colors only for single series in single chart type + bool bSupportsVaryColorsByPoint = mrModel.maTypeGroups.size() == 1; + + // convert all axes sets + for( AxesSetVector::iterator aASBeg = aAxesSets.begin(), aASIt = aASBeg, aASEnd = aAxesSets.end(); aASIt != aASEnd; ++aASIt ) + { + AxesSetConverter aAxesSetConv( *this, **aASIt ); + sal_Int32 nAxesSetIdx = static_cast< sal_Int32 >( aASIt - aASBeg ); + aAxesSetConv.convertFromModel( xDiagram, rView3DModel, nAxesSetIdx, bSupportsVaryColorsByPoint ); + if( nAxesSetIdx == 0 ) + { + maAutoTitle = aAxesSetConv.getAutomaticTitle(); + mb3dChart = aAxesSetConv.is3dChart(); + mbWall3dChart = aAxesSetConv.isWall3dChart(); + mbPieChart = aAxesSetConv.isPieChart(); + } + else + { + maAutoTitle = OUString(); + } + } + + // plot area formatting + if( xDiagram.is() && !mb3dChart ) + { + PropertySet aPropSet( xDiagram->getWall() ); + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_PLOTAREA2D ); + } +} + +void PlotAreaConverter::convertPositionFromModel() +{ + LayoutModel& rLayout = mrModel.mxLayout.getOrCreate(); + LayoutConverter aLayoutConv( *this, rLayout ); + Rectangle aDiagramRect; + if( aLayoutConv.calcAbsRectangle( aDiagramRect ) ) try + { + namespace cssc = ::com::sun::star::chart; + Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY_THROW ); + Reference< cssc::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW ); + // for pie charts, always set inner plot area size to exclude the data labels as Excel does + sal_Int32 nTarget = (mbPieChart && (rLayout.mnTarget == XML_outer)) ? XML_inner : rLayout.mnTarget; + switch( nTarget ) + { + case XML_inner: + xPositioning->setDiagramPositionExcludingAxes( aDiagramRect ); + break; + case XML_outer: + xPositioning->setDiagramPositionIncludingAxes( aDiagramRect ); + break; + default: + OSL_ENSURE( false, "PlotAreaConverter::convertPositionFromModel - unknown positioning target" ); + } + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/plotareamodel.cxx b/oox/source/drawingml/chart/plotareamodel.cxx new file mode 100644 index 000000000000..324186526cc6 --- /dev/null +++ b/oox/source/drawingml/chart/plotareamodel.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * 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/chart/plotareamodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +View3DModel::View3DModel() : + mnDepthPercent( 100 ), + mnPerspective( 30 ), + mbRightAngled( false ) +{ +} + +View3DModel::~View3DModel() +{ +} + +// ============================================================================ + +WallFloorModel::WallFloorModel() +{ +} + +WallFloorModel::~WallFloorModel() +{ +} + +// ============================================================================ + +PlotAreaModel::PlotAreaModel() +{ +} + +PlotAreaModel::~PlotAreaModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/chart/seriescontext.cxx b/oox/source/drawingml/chart/seriescontext.cxx new file mode 100644 index 000000000000..014ca51e869d --- /dev/null +++ b/oox/source/drawingml/chart/seriescontext.cxx @@ -0,0 +1,754 @@ +/************************************************************************* + * + * 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/chart/seriescontext.hxx" + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/chart/datasourcecontext.hxx" +#include "oox/drawingml/chart/seriesmodel.hxx" +#include "oox/drawingml/chart/titlecontext.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2; +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +ContextHandlerRef lclDataLabelSharedCreateContext( ContextHandler2& rContext, + sal_Int32 nElement, const AttributeList& rAttribs, DataLabelModelBase& orModel ) +{ + if( rContext.isRootElement() ) switch( nElement ) + { + case C_TOKEN( delete ): + // default is 'false', not 'true' as specified + orModel.mbDeleted = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( dLblPos ): + orModel.monLabelPos = rAttribs.getToken( XML_val, XML_TOKEN_INVALID ); + return 0; + case C_TOKEN( numFmt ): + orModel.maNumberFormat.setAttributes( rAttribs ); + return 0; + case C_TOKEN( showBubbleSize ): + orModel.mobShowBubbleSize = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( showCatName ): + orModel.mobShowCatName = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( showLegendKey ): + orModel.mobShowLegendKey = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( showPercent ): + orModel.mobShowPercent = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( showSerName ): + orModel.mobShowSerName = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( showVal ): + orModel.mobShowVal = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( separator ): + // collect separator text in onCharacters() + return &rContext; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( rContext, orModel.mxShapeProp.create() ); + case C_TOKEN( txPr ): + return new TextBodyContext( rContext, orModel.mxTextProp.create() ); + } + return 0; +} + +void lclDataLabelSharedCharacters( ContextHandler2& rContext, const OUString& rChars, DataLabelModelBase& orModel ) +{ + if( rContext.isCurrentElement( C_TOKEN( separator ) ) ) + orModel.moaSeparator = rChars; +} + +} // namespace + +// ============================================================================ + +DataLabelContext::DataLabelContext( ContextHandler2Helper& rParent, DataLabelModel& rModel ) : + ContextBase< DataLabelModel >( rParent, rModel ) +{ +} + +DataLabelContext::~DataLabelContext() +{ +} + +ContextHandlerRef DataLabelContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( idx ): + mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + case C_TOKEN( tx ): + return new TextContext( *this, mrModel.mxText.create() ); + } + return lclDataLabelSharedCreateContext( *this, nElement, rAttribs, mrModel ); +} + +void DataLabelContext::onCharacters( const OUString& rChars ) +{ + lclDataLabelSharedCharacters( *this, rChars, mrModel ); +} + +// ============================================================================ + +DataLabelsContext::DataLabelsContext( ContextHandler2Helper& rParent, DataLabelsModel& rModel ) : + ContextBase< DataLabelsModel >( rParent, rModel ) +{ +} + +DataLabelsContext::~DataLabelsContext() +{ +} + +ContextHandlerRef DataLabelsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( dLbl ): + return new DataLabelContext( *this, mrModel.maPointLabels.create() ); + case C_TOKEN( leaderLines ): + return new ShapePrWrapperContext( *this, mrModel.mxLeaderLines.create() ); + case C_TOKEN( showLeaderLines ): + // default is 'false', not 'true' as specified + mrModel.mbShowLeaderLines = rAttribs.getBool( XML_val, false ); + return 0; + } + return lclDataLabelSharedCreateContext( *this, nElement, rAttribs, mrModel ); +} + +void DataLabelsContext::onCharacters( const OUString& rChars ) +{ + lclDataLabelSharedCharacters( *this, rChars, mrModel ); +} + +// ============================================================================ + +PictureOptionsContext::PictureOptionsContext( ContextHandler2Helper& rParent, PictureOptionsModel& rModel ) : + ContextBase< PictureOptionsModel >( rParent, rModel ) +{ +} + +PictureOptionsContext::~PictureOptionsContext() +{ +} + +ContextHandlerRef PictureOptionsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( applyToEnd ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToEnd = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( applyToFront ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToFront = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( applyToSides ): + // default is 'false', not 'true' as specified + mrModel.mbApplyToSides = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( pictureFormat ): + mrModel.mnPictureFormat = rAttribs.getToken( XML_val, XML_stretch ); + return 0; + case C_TOKEN( pictureStackUnit ): + mrModel.mfStackUnit = rAttribs.getDouble( XML_val, 1.0 ); + return 0; + } + return 0; +} + +// ============================================================================ + +ErrorBarContext::ErrorBarContext( ContextHandler2Helper& rParent, ErrorBarModel& rModel ) : + ContextBase< ErrorBarModel >( rParent, rModel ) +{ +} + +ErrorBarContext::~ErrorBarContext() +{ +} + +ContextHandlerRef ErrorBarContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( errBarType ): + mrModel.mnTypeId = rAttribs.getToken( XML_val, XML_both ); + return 0; + case C_TOKEN( errDir ): + mrModel.mnDirection = rAttribs.getToken( XML_val, XML_TOKEN_INVALID ); + return 0; + case C_TOKEN( errValType ): + mrModel.mnValueType = rAttribs.getToken( XML_val, XML_fixedVal ); + return 0; + case C_TOKEN( minus ): + return new DataSourceContext( *this, mrModel.maSources.create( ErrorBarModel::MINUS ) ); + case C_TOKEN( noEndCap ): + // default is 'false', not 'true' as specified + mrModel.mbNoEndCap = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( plus ): + return new DataSourceContext( *this, mrModel.maSources.create( ErrorBarModel::PLUS ) ); + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( val ): + mrModel.mfValue = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + } + return 0; +} + +// ============================================================================ + +TrendlineLabelContext::TrendlineLabelContext( ContextHandler2Helper& rParent, TrendlineLabelModel& rModel ) : + ContextBase< TrendlineLabelModel >( rParent, rModel ) +{ +} + +TrendlineLabelContext::~TrendlineLabelContext() +{ +} + +ContextHandlerRef TrendlineLabelContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + case C_TOKEN( numFmt ): + mrModel.maNumberFormat.setAttributes( rAttribs ); + return 0; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( tx ): + return new TextContext( *this, mrModel.mxText.create() ); + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + } + return 0; +} + +// ============================================================================ + +TrendlineContext::TrendlineContext( ContextHandler2Helper& rParent, TrendlineModel& rModel ) : + ContextBase< TrendlineModel >( rParent, rModel ) +{ +} + +TrendlineContext::~TrendlineContext() +{ +} + +ContextHandlerRef TrendlineContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( backward ): + mrModel.mfBackward = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( dispEq ): + // default is 'false', not 'true' as specified + mrModel.mbDispEquation = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( dispRSqr ): + // default is 'false', not 'true' as specified + mrModel.mbDispRSquared = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( forward ): + mrModel.mfForward = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( intercept ): + mrModel.mfIntercept = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( name ): + return this; // collect name in onCharacters() + case C_TOKEN( order ): + mrModel.mnOrder = rAttribs.getInteger( XML_val, 2 ); + return 0; + case C_TOKEN( period ): + mrModel.mnPeriod = rAttribs.getInteger( XML_val, 2 ); + return 0; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( trendlineLbl ): + return new TrendlineLabelContext( *this, mrModel.mxLabel.create() ); + case C_TOKEN( trendlineType ): + mrModel.mnTypeId = rAttribs.getToken( XML_val, XML_linear ); + return 0; + } + return 0; +} + +void TrendlineContext::onCharacters( const OUString& rChars ) +{ + if( isCurrentElement( C_TOKEN( name ) ) ) + mrModel.maName = rChars; +} + +// ============================================================================ + +DataPointContext::DataPointContext( ContextHandler2Helper& rParent, DataPointModel& rModel ) : + ContextBase< DataPointModel >( rParent, rModel ) +{ +} + +DataPointContext::~DataPointContext() +{ +} + +ContextHandlerRef DataPointContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( dPt ): + switch( nElement ) + { + case C_TOKEN( bubble3D ): + mrModel.mobBubble3d = rAttribs.getBool( XML_val ); + return 0; + case C_TOKEN( explosion ): + // if the 'val' attribute is missing, series explosion remains unchanged + mrModel.monExplosion = rAttribs.getInteger( XML_val ); + return 0; + case C_TOKEN( idx ): + mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( invertIfNegative ): + // default is 'false', not 'true' as specified (value not derived from series!) + mrModel.mbInvertNeg = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( marker ): + return this; + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + } + break; + + case C_TOKEN( marker ): + switch( nElement ) + { + case C_TOKEN( size ): + mrModel.monMarkerSize = rAttribs.getInteger( XML_val, 5 ); + return 0; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxMarkerProp.create() ); + case C_TOKEN( symbol ): + mrModel.monMarkerSymbol = rAttribs.getToken( XML_val, XML_none ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +SeriesContextBase::SeriesContextBase( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + ContextBase< SeriesModel >( rParent, rModel ) +{ +} + +SeriesContextBase::~SeriesContextBase() +{ +} + +ContextHandlerRef SeriesContextBase::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( idx ): + mrModel.mnIndex = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( order ): + mrModel.mnOrder = rAttribs.getInteger( XML_val, -1 ); + return 0; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + case C_TOKEN( tx ): + return new TextContext( *this, mrModel.mxText.create() ); + } + break; + + case C_TOKEN( marker ): + switch( nElement ) + { + case C_TOKEN( size ): + mrModel.mnMarkerSize = rAttribs.getInteger( XML_val, 5 ); + return 0; + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxMarkerProp.create() ); + case C_TOKEN( symbol ): + mrModel.mnMarkerSymbol = rAttribs.getToken( XML_val, XML_none ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +AreaSeriesContext::AreaSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +AreaSeriesContext::~AreaSeriesContext() +{ +} + +ContextHandlerRef AreaSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( errBars ): + return new ErrorBarContext( *this, mrModel.maErrorBars.create() ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( trendline ): + return new TrendlineContext( *this, mrModel.maTrendlines.create() ); + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +BarSeriesContext::BarSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +BarSeriesContext::~BarSeriesContext() +{ +} + +ContextHandlerRef BarSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( errBars ): + return new ErrorBarContext( *this, mrModel.maErrorBars.create() ); + case C_TOKEN( invertIfNegative ): + // default is 'false', not 'true' as specified + mrModel.mbInvertNeg = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( pictureOptions ): + return new PictureOptionsContext( *this, mrModel.mxPicOptions.create() ); + case C_TOKEN( shape ): + // missing attribute does not change shape type to 'box' as specified + mrModel.monShape = rAttribs.getToken( XML_val ); + return 0; + case C_TOKEN( trendline ): + return new TrendlineContext( *this, mrModel.maTrendlines.create() ); + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +BubbleSeriesContext::BubbleSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +BubbleSeriesContext::~BubbleSeriesContext() +{ +} + +ContextHandlerRef BubbleSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( bubble3D ): + // default is 'false', not 'true' as specified + mrModel.mbBubble3d = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( bubbleSize ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::POINTS ) ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( errBars ): + return new ErrorBarContext( *this, mrModel.maErrorBars.create() ); + case C_TOKEN( invertIfNegative ): + // default is 'false', not 'true' as specified + mrModel.mbInvertNeg = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( trendline ): + return new TrendlineContext( *this, mrModel.maTrendlines.create() ); + case C_TOKEN( xVal ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( yVal ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +LineSeriesContext::LineSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +LineSeriesContext::~LineSeriesContext() +{ +} + +ContextHandlerRef LineSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( errBars ): + return new ErrorBarContext( *this, mrModel.maErrorBars.create() ); + case C_TOKEN( marker ): + return this; + case C_TOKEN( smooth ): + // default is 'false', not 'true' as specified + mrModel.mbSmooth = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( trendline ): + return new TrendlineContext( *this, mrModel.maTrendlines.create() ); + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +PieSeriesContext::PieSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +PieSeriesContext::~PieSeriesContext() +{ +} + +ContextHandlerRef PieSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( explosion ): + mrModel.mnExplosion = rAttribs.getInteger( XML_val, 0 ); + return 0; + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +RadarSeriesContext::RadarSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +RadarSeriesContext::~RadarSeriesContext() +{ +} + +ContextHandlerRef RadarSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( marker ): + return this; + case C_TOKEN( smooth ): + // default is 'false', not 'true' as specified + mrModel.mbSmooth = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +ScatterSeriesContext::ScatterSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +ScatterSeriesContext::~ScatterSeriesContext() +{ +} + +ContextHandlerRef ScatterSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dPt ): + return new DataPointContext( *this, mrModel.maPoints.create() ); + case C_TOKEN( errBars ): + return new ErrorBarContext( *this, mrModel.maErrorBars.create() ); + case C_TOKEN( marker ): + return this; + case C_TOKEN( smooth ): + // default is 'false', not 'true' as specified + mrModel.mbSmooth = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( trendline ): + return new TrendlineContext( *this, mrModel.maTrendlines.create() ); + case C_TOKEN( xVal ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( yVal ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +SurfaceSeriesContext::SurfaceSeriesContext( ContextHandler2Helper& rParent, SeriesModel& rModel ) : + SeriesContextBase( rParent, rModel ) +{ +} + +SurfaceSeriesContext::~SurfaceSeriesContext() +{ +} + +ContextHandlerRef SurfaceSeriesContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( ser ): + switch( nElement ) + { + case C_TOKEN( cat ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::CATEGORIES ) ); + case C_TOKEN( val ): + return new DataSourceContext( *this, mrModel.maSources.create( SeriesModel::VALUES ) ); + } + break; + } + return SeriesContextBase::onCreateContext( nElement, rAttribs ); +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx new file mode 100644 index 000000000000..b9eaee5c01be --- /dev/null +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -0,0 +1,619 @@ +/************************************************************************* + * + * 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/chart/seriesconverter.hxx" + +#include <com/sun/star/chart/DataLabelPlacement.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> +#include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/chart2/XRegressionCurve.hpp> +#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include "oox/drawingml/chart/datasourceconverter.hxx" +#include "oox/drawingml/chart/seriesmodel.hxx" +#include "oox/drawingml/chart/titleconverter.hxx" +#include "oox/drawingml/chart/typegroupconverter.hxx" +#include "oox/drawingml/chart/typegroupmodel.hxx" +#include "oox/helper/containerhelper.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +Reference< XLabeledDataSequence > lclCreateLabeledDataSequence( + const ConverterRoot& rParent, + DataSourceModel* pValues, const OUString& rRole, + TextModel* pTitle = 0 ) +{ + // create data sequence for values + Reference< XDataSequence > xValueSeq; + if( pValues ) + { + DataSourceConverter aSourceConv( rParent, *pValues ); + xValueSeq = aSourceConv.createDataSequence( rRole ); + } + + // create data sequence for title + Reference< XDataSequence > xTitleSeq; + if( pTitle ) + { + TextConverter aTextConv( rParent, *pTitle ); + xTitleSeq = aTextConv.createDataSequence( CREATE_OUSTRING( "label" ) ); + } + + // create the labeled data sequence, if values or title are present + Reference< XLabeledDataSequence > xLabeledSeq; + if( xValueSeq.is() || xTitleSeq.is() ) + { + xLabeledSeq.set( rParent.createInstance( CREATE_OUSTRING( "com.sun.star.chart2.data.LabeledDataSequence" ) ), UNO_QUERY ); + if( xLabeledSeq.is() ) + { + xLabeledSeq->setValues( xValueSeq ); + xLabeledSeq->setLabel( xTitleSeq ); + } + } + return xLabeledSeq; +} + +void lclConvertLabelFormatting( PropertySet& rPropSet, ObjectFormatter& rFormatter, + const DataLabelModelBase& rDataLabel, const TypeGroupConverter& rTypeGroup, bool bDataSeriesLabel ) +{ + const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo(); + + /* Excel 2007 does not change the series setting for a single data point, + if none of some specific elements occur. But only one existing element + in a data point will reset most other of these elements from the series + (e.g.: series has <c:showVal>, data point has <c:showCatName>, this + will reset <c:showVal> for this point, unless <c:showVal> is repeated + in the data point). The elements <c:layout>, <c:numberFormat>, + <c:spPr>, <c:tx>, and <c:txPr> are not affected at all. */ + bool bHasAnyElement = + rDataLabel.moaSeparator.has() || rDataLabel.monLabelPos.has() || + rDataLabel.mobShowCatName.has() || rDataLabel.mobShowLegendKey.has() || + rDataLabel.mobShowPercent.has() || rDataLabel.mobShowSerName.has() || + rDataLabel.mobShowVal.has(); + + bool bShowValue = !rDataLabel.mbDeleted && rDataLabel.mobShowVal.get( false ); + bool bShowPercent = !rDataLabel.mbDeleted && rDataLabel.mobShowPercent.get( false ) && (rTypeInfo.meTypeCategory == TYPECATEGORY_PIE); + bool bShowCateg = !rDataLabel.mbDeleted && rDataLabel.mobShowCatName.get( false ); + bool bShowSymbol = !rDataLabel.mbDeleted && rDataLabel.mobShowLegendKey.get( false ); + + // type of attached label + if( bHasAnyElement || rDataLabel.mbDeleted ) + { + DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); + rPropSet.setProperty( PROP_Label, aPointLabel ); + } + + if( !rDataLabel.mbDeleted ) + { + // data label number format (percentage format wins over value format) + rFormatter.convertNumberFormat( rPropSet, rDataLabel.maNumberFormat, bShowPercent ); + + // data label text formatting (frame formatting not supported by Chart2) + rFormatter.convertTextFormatting( rPropSet, rDataLabel.mxTextProp, OBJECTTYPE_DATALABEL ); + rFormatter.convertTextRotation( rPropSet, rDataLabel.mxTextProp, false ); + + // data label separator (do not overwrite series separator, if no explicit point separator is present) + if( bDataSeriesLabel || rDataLabel.moaSeparator.has() ) + rPropSet.setProperty( PROP_LabelSeparator, rDataLabel.moaSeparator.get( CREATE_OUSTRING( "; " ) ) ); + + // data label placement (do not overwrite series placement, if no explicit point placement is present) + if( bDataSeriesLabel || rDataLabel.monLabelPos.has() ) + { + namespace csscd = ::com::sun::star::chart::DataLabelPlacement; + sal_Int32 nPlacement = rTypeInfo.mnDefLabelPos; + switch( rDataLabel.monLabelPos.get( XML_TOKEN_INVALID ) ) + { + case XML_outEnd: nPlacement = csscd::OUTSIDE; break; + case XML_inEnd: nPlacement = csscd::INSIDE; break; + case XML_ctr: nPlacement = csscd::CENTER; break; + case XML_inBase: nPlacement = csscd::NEAR_ORIGIN; break; + case XML_t: nPlacement = csscd::TOP; break; + case XML_b: nPlacement = csscd::BOTTOM; break; + case XML_l: nPlacement = csscd::LEFT; break; + case XML_r: nPlacement = csscd::RIGHT; break; + case XML_bestFit: nPlacement = csscd::AVOID_OVERLAP; break; + } + rPropSet.setProperty( PROP_LabelPlacement, nPlacement ); + } + } +} + +} // namespace + +// ============================================================================ + +DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) : + ConverterBase< DataLabelModel >( rParent, rModel ) +{ +} + +DataLabelConverter::~DataLabelConverter() +{ +} + +void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup ) +{ + if( rxDataSeries.is() ) try + { + PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) ); + lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, false ); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +DataLabelsConverter::DataLabelsConverter( const ConverterRoot& rParent, DataLabelsModel& rModel ) : + ConverterBase< DataLabelsModel >( rParent, rModel ) +{ +} + +DataLabelsConverter::~DataLabelsConverter() +{ +} + +void DataLabelsConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, const TypeGroupConverter& rTypeGroup ) +{ + if( !mrModel.mbDeleted ) + { + PropertySet aPropSet( rxDataSeries ); + lclConvertLabelFormatting( aPropSet, getFormatter(), mrModel, rTypeGroup, true ); + } + + // data point label settings + for( DataLabelsModel::DataLabelVector::iterator aIt = mrModel.maPointLabels.begin(), aEnd = mrModel.maPointLabels.end(); aIt != aEnd; ++aIt ) + { + DataLabelConverter aLabelConv( *this, **aIt ); + aLabelConv.convertFromModel( rxDataSeries, rTypeGroup ); + } +} + +// ============================================================================ + +ErrorBarConverter::ErrorBarConverter( const ConverterRoot& rParent, ErrorBarModel& rModel ) : + ConverterBase< ErrorBarModel >( rParent, rModel ) +{ +} + +ErrorBarConverter::~ErrorBarConverter() +{ +} + +void ErrorBarConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries ) +{ + bool bShowPos = (mrModel.mnTypeId == XML_plus) || (mrModel.mnTypeId == XML_both); + bool bShowNeg = (mrModel.mnTypeId == XML_minus) || (mrModel.mnTypeId == XML_both); + if( bShowPos || bShowNeg ) try + { + Reference< XPropertySet > xErrorBar( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.ErrorBar" ) ), UNO_QUERY_THROW ); + PropertySet aBarProp( xErrorBar ); + + // plus/minus bars + aBarProp.setProperty( PROP_ShowPositiveError, bShowPos ); + aBarProp.setProperty( PROP_ShowNegativeError, bShowNeg ); + + // type of displayed error + namespace cssc = ::com::sun::star::chart; + switch( mrModel.mnValueType ) + { + case XML_cust: + { + // #i87806# manual error bars + aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::FROM_DATA ); + // attach data sequences to erorr bar + Reference< XDataSink > xDataSink( xErrorBar, UNO_QUERY ); + if( xDataSink.is() ) + { + // create vector of all value sequences + ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec; + // add positive values + if( bShowPos ) + { + Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::PLUS ); + if( xValueSeq.is() ) + aLabeledSeqVec.push_back( xValueSeq ); + } + // add negative values + if( bShowNeg ) + { + Reference< XLabeledDataSequence > xValueSeq = createLabeledDataSequence( ErrorBarModel::MINUS ); + if( xValueSeq.is() ) + aLabeledSeqVec.push_back( xValueSeq ); + } + // attach labeled data sequences to series + if( aLabeledSeqVec.empty() ) + xErrorBar.clear(); + else + xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) ); + } + } + break; + case XML_fixedVal: + aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::ABSOLUTE ); + aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue ); + aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue ); + break; + case XML_percentage: + aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::RELATIVE ); + aBarProp.setProperty( PROP_PositiveError, mrModel.mfValue ); + aBarProp.setProperty( PROP_NegativeError, mrModel.mfValue ); + break; + case XML_stdDev: + aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_DEVIATION ); + aBarProp.setProperty( PROP_Weight, mrModel.mfValue ); + break; + case XML_stdErr: + aBarProp.setProperty( PROP_ErrorBarStyle, cssc::ErrorBarStyle::STANDARD_ERROR ); + break; + default: + OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - unknown error bar type" ); + xErrorBar.clear(); + } + + // error bar formatting + getFormatter().convertFrameFormatting( aBarProp, mrModel.mxShapeProp, OBJECTTYPE_ERRORBAR ); + + if( xErrorBar.is() ) + { + PropertySet aSeriesProp( rxDataSeries ); + switch( mrModel.mnDirection ) + { + case XML_x: aSeriesProp.setProperty( PROP_ErrorBarX, xErrorBar ); break; + case XML_y: aSeriesProp.setProperty( PROP_ErrorBarY, xErrorBar ); break; + default: OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - invalid error bar direction" ); + } + } + } + catch( Exception& ) + { + OSL_ENSURE( false, "ErrorBarConverter::convertFromModel - error while creating error bars" ); + } +} + +// private -------------------------------------------------------------------- + +Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( ErrorBarModel::SourceType eSourceType ) +{ + OUString aRole; + switch( eSourceType ) + { + case ErrorBarModel::PLUS: + switch( mrModel.mnDirection ) + { + case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-positive" ); break; + case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-positive" ); break; + } + break; + case ErrorBarModel::MINUS: + switch( mrModel.mnDirection ) + { + case XML_x: aRole = CREATE_OUSTRING( "error-bars-x-negative" ); break; + case XML_y: aRole = CREATE_OUSTRING( "error-bars-y-negative" ); break; + } + break; + } + OSL_ENSURE( aRole.getLength() > 0, "ErrorBarConverter::createLabeledDataSequence - invalid error bar direction" ); + return lclCreateLabeledDataSequence( *this, mrModel.maSources.get( eSourceType ).get(), aRole ); +} + +// ============================================================================ + +TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) : + ConverterBase< TrendlineLabelModel >( rParent, rModel ) +{ +} + +TrendlineLabelConverter::~TrendlineLabelConverter() +{ +} + +void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet ) +{ + // formatting + getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL ); +} + +// ============================================================================ + +TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) : + ConverterBase< TrendlineModel >( rParent, rModel ) +{ +} + +TrendlineConverter::~TrendlineConverter() +{ +} + +void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries ) +{ + try + { + // trend line type + OUString aServiceName; + switch( mrModel.mnTypeId ) + { + case XML_exp: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.ExponentialRegressionCurve" ); break; + case XML_linear: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LinearRegressionCurve" ); break; + case XML_log: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.LogarithmicRegressionCurve" ); break; + case XML_movingAvg: /* #i66819# moving average trendlines not supported */ break; + case XML_poly: /* #i20819# polynomial trendlines not supported */ break; + case XML_power: aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.PotentialRegressionCurve" ); break; + default: OSL_ENSURE( false, "TrendlineConverter::convertFromModel - unknown trendline type" ); + } + if( aServiceName.getLength() > 0 ) + { + Reference< XRegressionCurve > xRegCurve( createInstance( aServiceName ), UNO_QUERY_THROW ); + PropertySet aPropSet( xRegCurve ); + + // trendline formatting + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, OBJECTTYPE_TRENDLINE ); + + // #i83100# show equation and correlation coefficient + PropertySet aLabelProp( xRegCurve->getEquationProperties() ); + aLabelProp.setProperty( PROP_ShowEquation, mrModel.mbDispEquation ); + aLabelProp.setProperty( PROP_ShowCorrelationCoefficient, mrModel.mbDispRSquared ); + + // #i83100# formatting of the equation text box + if( mrModel.mbDispEquation || mrModel.mbDispRSquared ) + { + TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() ); + aLabelConv.convertFromModel( aLabelProp ); + } + + // unsupported: #i5085# manual trendline size + // unsupported: #i34093# manual crossing point + + Reference< XRegressionCurveContainer > xRegCurveCont( rxDataSeries, UNO_QUERY_THROW ); + xRegCurveCont->addRegressionCurve( xRegCurve ); + } + } + catch( Exception& ) + { + OSL_ENSURE( false, "TrendlineConverter::convertFromModel - error while creating trendline" ); + } +} + +// ============================================================================ + +DataPointConverter::DataPointConverter( const ConverterRoot& rParent, DataPointModel& rModel ) : + ConverterBase< DataPointModel >( rParent, rModel ) +{ +} + +DataPointConverter::~DataPointConverter() +{ +} + +void DataPointConverter::convertFromModel( const Reference< XDataSeries >& rxDataSeries, + const TypeGroupConverter& rTypeGroup, const SeriesModel& rSeries ) +{ + try + { + PropertySet aPropSet( rxDataSeries->getDataPointByIndex( mrModel.mnIndex ) ); + + // data point marker + if( mrModel.monMarkerSymbol.differsFrom( rSeries.mnMarkerSymbol ) || mrModel.monMarkerSize.differsFrom( rSeries.mnMarkerSize ) ) + rTypeGroup.convertMarker( aPropSet, mrModel.monMarkerSymbol.get( rSeries.mnMarkerSymbol ), mrModel.monMarkerSize.get( rSeries.mnMarkerSize ) ); + + // data point pie explosion + if( mrModel.monExplosion.differsFrom( rSeries.mnExplosion ) ) + rTypeGroup.convertPieExplosion( aPropSet, mrModel.monExplosion.get() ); + + // point formatting + if( mrModel.mxShapeProp.is() ) + { + if( rTypeGroup.getTypeInfo().mbPictureOptions ) + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); + else + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, rTypeGroup.getSeriesObjectType(), rSeries.mnIndex ); + } + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +SeriesConverter::SeriesConverter( const ConverterRoot& rParent, SeriesModel& rModel ) : + ConverterBase< SeriesModel >( rParent, rModel ) +{ +} + +SeriesConverter::~SeriesConverter() +{ +} + +Reference< XLabeledDataSequence > SeriesConverter::createCategorySequence( const OUString& rRole ) +{ + return createLabeledDataSequence( SeriesModel::CATEGORIES, rRole, false ); +} + +Reference< XLabeledDataSequence > SeriesConverter::createValueSequence( const OUString& rRole ) +{ + return createLabeledDataSequence( SeriesModel::VALUES, rRole, true ); +} + +Reference< XDataSeries > SeriesConverter::createDataSeries( const TypeGroupConverter& rTypeGroup, bool bVaryColorsByPoint ) +{ + const TypeGroupInfo& rTypeInfo = rTypeGroup.getTypeInfo(); + + // create the data series object + Reference< XDataSeries > xDataSeries( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.DataSeries" ) ), UNO_QUERY ); + PropertySet aSeriesProp( xDataSeries ); + + // attach data and title sequences to series + sal_Int32 nDataPointCount = 0; + Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY ); + if( xDataSink.is() ) + { + // create vector of all value sequences + ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec; + // add Y values + Reference< XLabeledDataSequence > xYValueSeq = createValueSequence( CREATE_OUSTRING( "values-y" ) ); + if( xYValueSeq.is() ) + { + aLabeledSeqVec.push_back( xYValueSeq ); + Reference< XDataSequence > xValues = xYValueSeq->getValues(); + if( xValues.is() ) + nDataPointCount = xValues->getData().getLength(); + } + // add X values of scatter and bubble charts + if( !rTypeInfo.mbCategoryAxis ) + { + Reference< XLabeledDataSequence > xXValueSeq = createCategorySequence( CREATE_OUSTRING( "values-x" ) ); + if( xXValueSeq.is() ) + aLabeledSeqVec.push_back( xXValueSeq ); + // add size values of bubble charts + if( rTypeInfo.meTypeId == TYPEID_BUBBLE ) + { + Reference< XLabeledDataSequence > xSizeValueSeq = createLabeledDataSequence( SeriesModel::POINTS, CREATE_OUSTRING( "values-size" ), true ); + if( xSizeValueSeq.is() ) + aLabeledSeqVec.push_back( xSizeValueSeq ); + } + } + // attach labeled data sequences to series + if( !aLabeledSeqVec.empty() ) + xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) ); + } + + // error bars + for( SeriesModel::ErrorBarVector::iterator aIt = mrModel.maErrorBars.begin(), aEnd = mrModel.maErrorBars.end(); aIt != aEnd; ++aIt ) + { + ErrorBarConverter aErrorBarConv( *this, **aIt ); + aErrorBarConv.convertFromModel( xDataSeries ); + } + + // trendlines + for( SeriesModel::TrendlineVector::iterator aIt = mrModel.maTrendlines.begin(), aEnd = mrModel.maTrendlines.end(); aIt != aEnd; ++aIt ) + { + TrendlineConverter aTrendlineConv( *this, **aIt ); + aTrendlineConv.convertFromModel( xDataSeries ); + } + + // data point markers + rTypeGroup.convertMarker( aSeriesProp, mrModel.mnMarkerSymbol, mrModel.mnMarkerSize ); +#if OOX_CHART_SMOOTHED_PER_SERIES + // #i66858# smoothed series lines + rTypeGroup.convertLineSmooth( aSeriesProp, mrModel.mbSmooth ); +#endif + // 3D bar style (not possible to set at chart type -> set at all series) + rTypeGroup.convertBarGeometry( aSeriesProp, mrModel.monShape.get( rTypeGroup.getModel().mnShape ) ); + // pie explosion (restricted to [0%,100%] in Chart2) + rTypeGroup.convertPieExplosion( aSeriesProp, mrModel.mnExplosion ); + + // series formatting + ObjectFormatter& rFormatter = getFormatter(); + ObjectType eObjType = rTypeGroup.getSeriesObjectType(); + if( rTypeInfo.mbPictureOptions ) + rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, mrModel.mxPicOptions.getOrCreate(), eObjType, mrModel.mnIndex ); + else + rFormatter.convertFrameFormatting( aSeriesProp, mrModel.mxShapeProp, eObjType, mrModel.mnIndex ); + + // set the (unused) property default value used by the Chart2 templates (true for pie/doughnut charts) + bool bIsPie = rTypeInfo.meTypeCategory == TYPECATEGORY_PIE; + aSeriesProp.setProperty( PROP_VaryColorsByPoint, bIsPie ); + + // own area formatting for every data point (TODO: varying line color not supported) + // #i91271# always set area formatting for every point in pie/doughnut charts to override their automatic point formatting + if( bIsPie || (bVaryColorsByPoint && rTypeGroup.isSeriesFrameFormat() && ObjectFormatter::isAutomaticFill( mrModel.mxShapeProp )) ) + { + /* Set the series point number as color cycle size at the object + formatter to get correct start-shade/end-tint. TODO: in doughnut + charts, the sizes of the series may vary, need to use the maximum + point count of all series. */ + sal_Int32 nOldMax = rFormatter.getMaxSeriesIndex(); + if( bVaryColorsByPoint ) + rFormatter.setMaxSeriesIndex( nDataPointCount - 1 ); + for( sal_Int32 nIndex = 0; nIndex < nDataPointCount; ++nIndex ) + { + try + { + PropertySet aPointProp( xDataSeries->getDataPointByIndex( nIndex ) ); + rFormatter.convertAutomaticFill( aPointProp, eObjType, bVaryColorsByPoint ? nIndex : mrModel.mnIndex ); + } + catch( Exception& ) + { + } + } + rFormatter.setMaxSeriesIndex( nOldMax ); + } + + // data point settings + for( SeriesModel::DataPointVector::iterator aIt = mrModel.maPoints.begin(), aEnd = mrModel.maPoints.end(); aIt != aEnd; ++aIt ) + { + DataPointConverter aPointConv( *this, **aIt ); + aPointConv.convertFromModel( xDataSeries, rTypeGroup, mrModel ); + } + + /* Series data label settings. If and only if the series does not contain + a c:dLbls element, then the c:dLbls element of the parent chart type is + used (data label settings of the parent chart type are *not* merged + into own existing data label settings). */ + ModelRef< DataLabelsModel > xLabels = mrModel.mxLabels.is() ? mrModel.mxLabels : rTypeGroup.getModel().mxLabels; + if( xLabels.is() ) + { + DataLabelsConverter aLabelsConv( *this, *xLabels ); + aLabelsConv.convertFromModel( xDataSeries, rTypeGroup ); + } + + return xDataSeries; +} + +// private -------------------------------------------------------------------- + +Reference< XLabeledDataSequence > SeriesConverter::createLabeledDataSequence( + SeriesModel::SourceType eSourceType, const OUString& rRole, bool bUseTextLabel ) +{ + DataSourceModel* pValues = mrModel.maSources.get( eSourceType ).get(); + TextModel* pTitle = bUseTextLabel ? mrModel.mxText.get() : 0; + return lclCreateLabeledDataSequence( *this, pValues, rRole, pTitle ); +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/seriesmodel.cxx b/oox/source/drawingml/chart/seriesmodel.cxx new file mode 100644 index 000000000000..417d250caf77 --- /dev/null +++ b/oox/source/drawingml/chart/seriesmodel.cxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * 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/chart/seriesmodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +DataLabelModelBase::DataLabelModelBase() : + mbDeleted( false ) +{ +} + +DataLabelModelBase::~DataLabelModelBase() +{ +} + +// ============================================================================ + +DataLabelModel::DataLabelModel() : + mnIndex( -1 ) +{ +} + +DataLabelModel::~DataLabelModel() +{ +} + +// ============================================================================ + +DataLabelsModel::DataLabelsModel() : + mbShowLeaderLines( false ) +{ +} + +DataLabelsModel::~DataLabelsModel() +{ +} + +// ============================================================================ + +PictureOptionsModel::PictureOptionsModel() : + mfStackUnit( 1.0 ), + mnPictureFormat( XML_stretch ), + mbApplyToFront( false ), + mbApplyToSides( false ), + mbApplyToEnd( false ) +{ +} + +PictureOptionsModel::~PictureOptionsModel() +{ +} + +// ============================================================================ + +ErrorBarModel::ErrorBarModel() : + mfValue( 0.0 ), + mnDirection( XML_y ), + mnTypeId( XML_both ), + mnValueType( XML_fixedVal ), + mbNoEndCap( false ) +{ +} + +ErrorBarModel::~ErrorBarModel() +{ +} + +// ============================================================================ + +TrendlineLabelModel::TrendlineLabelModel() +{ +} + +TrendlineLabelModel::~TrendlineLabelModel() +{ +} + +// ============================================================================ + +TrendlineModel::TrendlineModel() : + mnOrder( 2 ), + mnPeriod( 2 ), + mnTypeId( XML_linear ), + mbDispEquation( false ), + mbDispRSquared( false ) +{ +} + +TrendlineModel::~TrendlineModel() +{ +} + +// ============================================================================ + +DataPointModel::DataPointModel() : + mnIndex( -1 ), + mbInvertNeg( false ) +{ +} + +DataPointModel::~DataPointModel() +{ +} + +// ============================================================================ + +SeriesModel::SeriesModel() : + mnExplosion( 0 ), + mnIndex( -1 ), + mnMarkerSize( 5 ), + mnMarkerSymbol( XML_auto ), + mnOrder( -1 ), + mbBubble3d( false ), + mbInvertNeg( false ), + mbSmooth( false ) +{ +} + +SeriesModel::~SeriesModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/titlecontext.cxx b/oox/source/drawingml/chart/titlecontext.cxx new file mode 100644 index 000000000000..cc2b7ace0e72 --- /dev/null +++ b/oox/source/drawingml/chart/titlecontext.cxx @@ -0,0 +1,159 @@ +/************************************************************************* + * + * 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/chart/titlecontext.hxx" + +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/chart/datasourcecontext.hxx" +#include "oox/drawingml/chart/titlemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; +using ::rtl::OUString; + +// ============================================================================ + +TextContext::TextContext( ContextHandler2Helper& rParent, TextModel& rModel ) : + ContextBase< TextModel >( rParent, rModel ) +{ +} + +TextContext::~TextContext() +{ +} + +ContextHandlerRef TextContext::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + // this context handler is used for <c:tx> and embedded <c:v> elements + if( isCurrentElement( C_TOKEN( tx ) ) ) switch( nElement ) + { + case C_TOKEN( rich ): + return new TextBodyContext( *this, mrModel.mxTextBody.create() ); + + case C_TOKEN( strRef ): + OSL_ENSURE( !mrModel.mxDataSeq, "TextContext::onCreateContext - multiple data sequences" ); + return new StringSequenceContext( *this, mrModel.mxDataSeq.create() ); + + case C_TOKEN( v ): + OSL_ENSURE( !mrModel.mxDataSeq, "TextContext::onCreateContext - multiple data sequences" ); + return this; // collect value in onCharacters() + } + return 0; +} + +void TextContext::onCharacters( const OUString& rChars ) +{ + // store as single string sequence element + if( isCurrentElement( C_TOKEN( v ) ) ) + mrModel.mxDataSeq.create().maData[ 0 ] <<= rChars; +} + +// ============================================================================ + +TitleContext::TitleContext( ContextHandler2Helper& rParent, TitleModel& rModel ) : + ContextBase< TitleModel >( rParent, rModel ) +{ +} + +TitleContext::~TitleContext() +{ +} + +ContextHandlerRef TitleContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // this context handler is used for <c:title> only + switch( nElement ) + { + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + + case C_TOKEN( overlay ): + // default is 'false', not 'true' as specified + mrModel.mbOverlay = rAttribs.getBool( XML_val, false ); + return 0; + + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + + case C_TOKEN( tx ): + return new TextContext( *this, mrModel.mxText.create() ); + + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + } + return 0; +} + +// ============================================================================ + +LegendContext::LegendContext( ContextHandler2Helper& rParent, LegendModel& rModel ) : + ContextBase< LegendModel >( rParent, rModel ) +{ +} + +LegendContext::~LegendContext() +{ +} + +ContextHandlerRef LegendContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + // this context handler is used for <c:legend> only + switch( nElement ) + { + case C_TOKEN( layout ): + return new LayoutContext( *this, mrModel.mxLayout.create() ); + + case C_TOKEN( legendPos ): + mrModel.mnPosition = rAttribs.getToken( XML_val, XML_r ); + return 0; + + case C_TOKEN( overlay ): + // default is 'false', not 'true' as specified + mrModel.mbOverlay = rAttribs.getBool( XML_val, false ); + return 0; + + case C_TOKEN( spPr ): + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); + + case C_TOKEN( txPr ): + return new TextBodyContext( *this, mrModel.mxTextProp.create() ); + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/titleconverter.cxx b/oox/source/drawingml/chart/titleconverter.cxx new file mode 100644 index 000000000000..8163241e5a31 --- /dev/null +++ b/oox/source/drawingml/chart/titleconverter.cxx @@ -0,0 +1,259 @@ +/************************************************************************* + * + * 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/chart/titleconverter.hxx" + +#include <com/sun/star/chart/ChartLegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> +#include <com/sun/star/chart2/XFormattedString.hpp> +#include <com/sun/star/chart2/XLegend.hpp> +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include "oox/drawingml/textbody.hxx" +#include "oox/drawingml/textparagraph.hxx" +#include "oox/drawingml/chart/datasourceconverter.hxx" +#include "oox/drawingml/chart/titlemodel.hxx" +#include "oox/helper/containerhelper.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::uno; + +using ::oox::core::XmlFilterBase; +using ::rtl::OUString; + +// ============================================================================ + +TextConverter::TextConverter( const ConverterRoot& rParent, TextModel& rModel ) : + ConverterBase< TextModel >( rParent, rModel ) +{ +} + +TextConverter::~TextConverter() +{ +} + +Reference< XDataSequence > TextConverter::createDataSequence( const OUString& rRole ) +{ + Reference< XDataSequence > xDataSeq; + if( mrModel.mxDataSeq.is() ) + { + DataSequenceConverter aDataSeqConv( *this, *mrModel.mxDataSeq ); + xDataSeq = aDataSeqConv.createDataSequence( rRole ); + } + return xDataSeq; +} + +Sequence< Reference< XFormattedString > > TextConverter::createStringSequence( + const OUString& rDefaultText, const ModelRef< TextBody >& rxTextProp, ObjectType eObjType ) +{ + OSL_ENSURE( !mrModel.mxDataSeq || !mrModel.mxTextBody, "TextConverter::createStringSequence - linked string and rich text found" ); + ::std::vector< Reference< XFormattedString > > aStringVec; + if( mrModel.mxTextBody.is() ) + { + // rich-formatted text objects can be created, but currently Chart2 is not able to show them + const TextParagraphVector& rTextParas = mrModel.mxTextBody->getParagraphs(); + for( TextParagraphVector::const_iterator aPIt = rTextParas.begin(), aPEnd = rTextParas.end(); aPIt != aPEnd; ++aPIt ) + { + const TextParagraph& rTextPara = **aPIt; + const TextCharacterProperties& rParaProps = rTextPara.getProperties().getTextCharacterProperties(); + for( TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt ) + { + const TextRun& rTextRun = **aRIt; + bool bAddNewLine = (aRIt + 1 == aREnd) && (aPIt + 1 != aPEnd); + Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, rTextRun.getText(), bAddNewLine ); + PropertySet aPropSet( xFmtStr ); + TextCharacterProperties aRunProps( rParaProps ); + aRunProps.assignUsed( rTextRun.getTextCharacterProperties() ); + getFormatter().convertTextFormatting( aPropSet, aRunProps, eObjType ); + } + } + } + else + { + OUString aString; + // try to create string from linked data + if( mrModel.mxDataSeq.is() && !mrModel.mxDataSeq->maData.empty() ) + mrModel.mxDataSeq->maData.begin()->second >>= aString; + // no linked string -> fall back to default string + if( aString.getLength() == 0 ) + aString = rDefaultText; + + // create formatted string object + if( aString.getLength() > 0 ) + { + Reference< XFormattedString > xFmtStr = appendFormattedString( aStringVec, aString, false ); + PropertySet aPropSet( xFmtStr ); + getFormatter().convertTextFormatting( aPropSet, rxTextProp, eObjType ); + } + } + + return ContainerHelper::vectorToSequence( aStringVec ); +} + +Reference< XFormattedString > TextConverter::appendFormattedString( + ::std::vector< Reference< XFormattedString > >& orStringVec, const OUString& rString, bool bAddNewLine ) const +{ + Reference< XFormattedString > xFmtStr; + try + { + xFmtStr.set( ConverterRoot::createInstance( CREATE_OUSTRING( "com.sun.star.chart2.FormattedString" ) ), UNO_QUERY_THROW ); + xFmtStr->setString( bAddNewLine ? (rString + OUString( sal_Unicode( '\n' ) )) : rString ); + orStringVec.push_back( xFmtStr ); + } + catch( Exception& ) + { + } + return xFmtStr; +} + +// ============================================================================ + +TitleConverter::TitleConverter( const ConverterRoot& rParent, TitleModel& rModel ) : + ConverterBase< TitleModel >( rParent, rModel ) +{ +} + +TitleConverter::~TitleConverter() +{ +} + +void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) +{ + if( rxTitled.is() ) + { + // create the formatted strings + TextModel& rText = mrModel.mxText.getOrCreate(); + TextConverter aTextConv( *this, rText ); + Sequence< Reference< XFormattedString > > aStringSeq = aTextConv.createStringSequence( rAutoTitle, mrModel.mxTextProp, eObjType ); + if( aStringSeq.hasElements() ) try + { + // create the title object and set the string data + Reference< XTitle > xTitle( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Title" ) ), UNO_QUERY_THROW ); + xTitle->setText( aStringSeq ); + rxTitled->setTitleObject( xTitle ); + + // frame formatting (text formatting already done in TextConverter::createStringSequence()) + PropertySet aPropSet( xTitle ); + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxShapeProp, eObjType ); + + // frame rotation + OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" ); + ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody; + getFormatter().convertTextRotation( aPropSet, xTextProp, true ); + + // register the title and layout data for conversion of position + registerTitleLayout( xTitle, mrModel.mxLayout, eObjType, nMainIdx, nSubIdx ); + } + catch( Exception& ) + { + } + } +} + +// ============================================================================ + +LegendConverter::LegendConverter( const ConverterRoot& rParent, LegendModel& rModel ) : + ConverterBase< LegendModel >( rParent, rModel ) +{ +} + +LegendConverter::~LegendConverter() +{ +} + +void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) +{ + if( rxDiagram.is() ) try + { + namespace cssc = ::com::sun::star::chart; + namespace cssc2 = ::com::sun::star::chart2; + + // create the legend + Reference< XLegend > xLegend( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Legend" ) ), UNO_QUERY_THROW ); + rxDiagram->setLegend( xLegend ); + PropertySet aPropSet( xLegend ); + aPropSet.setProperty( PROP_Show, true ); + + // legend formatting + getFormatter().convertFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_LEGEND ); + + // predefined legend position and expansion + cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_CUSTOM; + cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM; + switch( mrModel.mnPosition ) + { + case XML_l: + eLegendPos = cssc2::LegendPosition_LINE_START; + eLegendExpand = cssc::ChartLegendExpansion_HIGH; + break; + case XML_r: + case XML_tr: // top-right not supported + eLegendPos = cssc2::LegendPosition_LINE_END; + eLegendExpand = cssc::ChartLegendExpansion_HIGH; + break; + case XML_t: + eLegendPos = cssc2::LegendPosition_PAGE_START; + eLegendExpand = cssc::ChartLegendExpansion_WIDE; + break; + case XML_b: + eLegendPos = cssc2::LegendPosition_PAGE_END; + eLegendExpand = cssc::ChartLegendExpansion_WIDE; + break; + } + + // manual positioning and size + if( mrModel.mxLayout.get() ) + { + LayoutConverter aLayoutConv( *this, *mrModel.mxLayout ); + // manual size needs ChartLegendExpansion_CUSTOM + if( aLayoutConv.convertFromModel( aPropSet ) ) + eLegendExpand = cssc::ChartLegendExpansion_CUSTOM; + } + + // set position and expansion properties + aPropSet.setProperty( PROP_AnchorPosition, eLegendPos ); + aPropSet.setProperty( PROP_Expansion, eLegendExpand ); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/titlemodel.cxx b/oox/source/drawingml/chart/titlemodel.cxx new file mode 100644 index 000000000000..d1dc2c664e8f --- /dev/null +++ b/oox/source/drawingml/chart/titlemodel.cxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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/chart/titlemodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +TextModel::TextModel() +{ +} + +TextModel::~TextModel() +{ +} + +// ============================================================================ + +TitleModel::TitleModel() : + mbOverlay( false ) +{ +} + +TitleModel::~TitleModel() +{ +} + +// ============================================================================ + +LegendModel::LegendModel() : + mnPosition( XML_r ), + mbOverlay( false ) +{ +} + +LegendModel::~LegendModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/typegroupcontext.cxx b/oox/source/drawingml/chart/typegroupcontext.cxx new file mode 100644 index 000000000000..781b2665d6f1 --- /dev/null +++ b/oox/source/drawingml/chart/typegroupcontext.cxx @@ -0,0 +1,404 @@ +/************************************************************************* + * + * 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/chart/typegroupcontext.hxx" + +#include "oox/drawingml/chart/seriescontext.hxx" +#include "oox/drawingml/chart/typegroupmodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using ::oox::core::ContextHandler2Helper; +using ::oox::core::ContextHandlerRef; + +// ============================================================================ + +UpDownBarsContext::UpDownBarsContext( ContextHandler2Helper& rParent, UpDownBarsModel& rModel ) : + ContextBase< UpDownBarsModel >( rParent, rModel ) +{ +} + +UpDownBarsContext::~UpDownBarsContext() +{ +} + +ContextHandlerRef UpDownBarsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( upDownBars ): + switch( nElement ) + { + case C_TOKEN( downBars ): + return new ShapePrWrapperContext( *this, mrModel.mxDownBars.create() ); + case C_TOKEN( gapWidth ): + mrModel.mnGapWidth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( upBars ): + return new ShapePrWrapperContext( *this, mrModel.mxUpBars.create() ); + } + break; + } + return 0; +} + +// ============================================================================ + +AreaTypeGroupContext::AreaTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +AreaTypeGroupContext::~AreaTypeGroupContext() +{ +} + +ContextHandlerRef AreaTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dropLines ): + return new ShapePrWrapperContext( *this, mrModel.mxDropLines.create() ); + case C_TOKEN( gapDepth ): + mrModel.mnGapDepth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( grouping ): + mrModel.mnGrouping = rAttribs.getToken( XML_val, XML_standard ); + return 0; + case C_TOKEN( ser ): + return new AreaSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +BarTypeGroupContext::BarTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +BarTypeGroupContext::~BarTypeGroupContext() +{ +} + +ContextHandlerRef BarTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( barDir ): + mrModel.mnBarDir = rAttribs.getToken( XML_val, XML_col ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( gapDepth ): + mrModel.mnGapDepth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( gapWidth ): + mrModel.mnGapWidth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( grouping ): + // default is 'standard', not 'clustered' as specified + mrModel.mnGrouping = rAttribs.getToken( XML_val, XML_standard ); + return 0; + case C_TOKEN( overlap ): + mrModel.mnOverlap = rAttribs.getInteger( XML_val, 0 ); + return 0; + case C_TOKEN( ser ): + return new BarSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( serLines ): + return new ShapePrWrapperContext( *this, mrModel.mxSerLines.create() ); + case C_TOKEN( shape ): + mrModel.mnShape = rAttribs.getToken( XML_val, XML_box ); + return 0; + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +BubbleTypeGroupContext::BubbleTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +BubbleTypeGroupContext::~BubbleTypeGroupContext() +{ +} + +ContextHandlerRef BubbleTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( bubble3D ): + // default is 'false', not 'true' as specified + mrModel.mbBubble3d = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( bubbleScale ): + mrModel.mnBubbleScale = rAttribs.getInteger( XML_val, 100 ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( ser ): + return new BubbleSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( showNegBubbles ): + // default is 'false', not 'true' as specified + mrModel.mbShowNegBubbles = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( sizeRepresents ): + mrModel.mnSizeRepresents = rAttribs.getToken( XML_val, XML_area ); + return 0; + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +LineTypeGroupContext::LineTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +LineTypeGroupContext::~LineTypeGroupContext() +{ +} + +ContextHandlerRef LineTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( dropLines ): + return new ShapePrWrapperContext( *this, mrModel.mxDropLines.create() ); + case C_TOKEN( gapDepth ): + mrModel.mnGapDepth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( grouping ): + mrModel.mnGrouping = rAttribs.getToken( XML_val, XML_standard ); + return 0; + case C_TOKEN( hiLowLines ): + return new ShapePrWrapperContext( *this, mrModel.mxHiLowLines.create() ); + case C_TOKEN( marker ): + // default is 'false', not 'true' as specified + mrModel.mbShowMarker = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( ser ): + return new LineSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( smooth ): + // default is 'false', not 'true' as specified + mrModel.mbSmooth = rAttribs.getBool( XML_val, false ); + return 0; + case C_TOKEN( upDownBars ): + return new UpDownBarsContext( *this, mrModel.mxUpDownBars.create() ); + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +PieTypeGroupContext::PieTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +PieTypeGroupContext::~PieTypeGroupContext() +{ +} + +ContextHandlerRef PieTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( firstSliceAng ): + mrModel.mnFirstAngle = rAttribs.getInteger( XML_val, 0 ); + return 0; + case C_TOKEN( gapWidth ): + mrModel.mnGapWidth = rAttribs.getInteger( XML_val, 150 ); + return 0; + case C_TOKEN( holeSize ): + mrModel.mnHoleSize = rAttribs.getInteger( XML_val, 10 ); + return 0; + case C_TOKEN( ofPieType ): + mrModel.mnOfPieType = rAttribs.getToken( XML_val, XML_pie ); + return 0; + case C_TOKEN( secondPieSize ): + mrModel.mnSecondPieSize = rAttribs.getInteger( XML_val, 75 ); + return 0; + case C_TOKEN( ser ): + return new PieSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( serLines ): + return new ShapePrWrapperContext( *this, mrModel.mxSerLines.create() ); + case C_TOKEN( splitPos ): + mrModel.mfSplitPos = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( splitType ): + mrModel.mnSplitType = rAttribs.getToken( XML_val, XML_auto ); + return 0; + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +RadarTypeGroupContext::RadarTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +RadarTypeGroupContext::~RadarTypeGroupContext() +{ +} + +ContextHandlerRef RadarTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( radarStyle ): + mrModel.mnRadarStyle = rAttribs.getToken( XML_val, XML_standard ); + return 0; + case C_TOKEN( ser ): + return new RadarSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +ScatterTypeGroupContext::ScatterTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +ScatterTypeGroupContext::~ScatterTypeGroupContext() +{ +} + +ContextHandlerRef ScatterTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( dLbls ): + return new DataLabelsContext( *this, mrModel.mxLabels.create() ); + case C_TOKEN( scatterStyle ): + mrModel.mnScatterStyle = rAttribs.getInteger( XML_val, XML_marker ); + return 0; + case C_TOKEN( ser ): + return new ScatterSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( varyColors ): + // default is 'false', not 'true' as specified + mrModel.mbVaryColors = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +SurfaceTypeGroupContext::SurfaceTypeGroupContext( ContextHandler2Helper& rParent, TypeGroupModel& rModel ) : + TypeGroupContextBase( rParent, rModel ) +{ +} + +SurfaceTypeGroupContext::~SurfaceTypeGroupContext() +{ +} + +ContextHandlerRef SurfaceTypeGroupContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( isRootElement() ) switch( nElement ) + { + case C_TOKEN( axId ): + mrModel.maAxisIds.push_back( rAttribs.getInteger( XML_val, -1 ) ); + return 0; + case C_TOKEN( ser ): + return new SurfaceSeriesContext( *this, mrModel.maSeries.create() ); + case C_TOKEN( wireframe ): + // default is 'false', not 'true' as specified + mrModel.mbWireframe = rAttribs.getBool( XML_val, false ); + return 0; + } + return 0; +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/typegroupconverter.cxx b/oox/source/drawingml/chart/typegroupconverter.cxx new file mode 100644 index 000000000000..6c0d3660a670 --- /dev/null +++ b/oox/source/drawingml/chart/typegroupconverter.cxx @@ -0,0 +1,566 @@ +/************************************************************************* + * + * 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/chart/typegroupconverter.hxx" + +#include <com/sun/star/chart/DataLabelPlacement.hpp> +#include <com/sun/star/chart2/CurveStyle.hpp> +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/chart2/StackingDirection.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XCoordinateSystem.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/chart/seriesconverter.hxx" +#include "oox/drawingml/chart/typegroupmodel.hxx" +#include "oox/helper/containerhelper.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::chart2; +using namespace ::com::sun::star::chart2::data; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +// chart type service names +const sal_Char SERVICE_CHART2_AREA[] = "com.sun.star.chart2.AreaChartType"; +const sal_Char SERVICE_CHART2_CANDLE[] = "com.sun.star.chart2.CandleStickChartType"; +const sal_Char SERVICE_CHART2_COLUMN[] = "com.sun.star.chart2.ColumnChartType"; +const sal_Char SERVICE_CHART2_LINE[] = "com.sun.star.chart2.LineChartType"; +const sal_Char SERVICE_CHART2_NET[] = "com.sun.star.chart2.NetChartType"; +const sal_Char SERVICE_CHART2_FILLEDNET[] = "com.sun.star.chart2.FilledNetChartType"; +const sal_Char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType"; +const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType"; +const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType"; +const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo + +namespace csscd = ::com::sun::star::chart::DataLabelPlacement; + +static const TypeGroupInfo spTypeInfos[] = +{ + // type-id type-category service varied-point-color default label pos comb2d supp3d polar area2d 1stvis xcateg swap stack revers betw picopt + { TYPEID_BAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true }, + { TYPEID_HORBAR, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, false, true, false, true, false, true, true, true, false, true, true }, + { TYPEID_LINE, TYPECATEGORY_LINE, SERVICE_CHART2_LINE, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, true, false, true, false, true, false }, + { TYPEID_AREA, TYPECATEGORY_LINE, SERVICE_CHART2_AREA, VARPOINTMODE_NONE, csscd::CENTER, true, true, false, true, false, true, false, true, true, false, false }, + { TYPEID_STOCK, TYPECATEGORY_LINE, SERVICE_CHART2_CANDLE, VARPOINTMODE_NONE, csscd::RIGHT, true, false, false, false, false, true, false, true, false, true, false }, + { TYPEID_RADARLINE, TYPECATEGORY_RADAR, SERVICE_CHART2_NET, VARPOINTMODE_SINGLE, csscd::TOP, false, false, true, false, false, true, false, false, false, false, false }, + { TYPEID_RADARAREA, TYPECATEGORY_RADAR, SERVICE_CHART2_FILLEDNET, VARPOINTMODE_NONE, csscd::TOP, false, false, true, true, false, true, false, false, true, false, false }, + { TYPEID_PIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false }, + { TYPEID_DOUGHNUT, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, false, true, false, false, false, false, false }, + { TYPEID_OFPIE, TYPECATEGORY_PIE, SERVICE_CHART2_PIE, VARPOINTMODE_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, true, false, false, false, false, false }, + { TYPEID_SCATTER, TYPECATEGORY_SCATTER, SERVICE_CHART2_SCATTER, VARPOINTMODE_SINGLE, csscd::RIGHT, true, true, false, false, false, false, false, false, false, false, false }, + { TYPEID_BUBBLE, TYPECATEGORY_SCATTER, SERVICE_CHART2_BUBBLE, VARPOINTMODE_SINGLE, csscd::RIGHT, false, false, false, true, false, false, false, false, false, false, false }, + { TYPEID_SURFACE, TYPECATEGORY_SURFACE, SERVICE_CHART2_SURFACE, VARPOINTMODE_NONE, csscd::RIGHT, false, true, false, true, false, true, false, false, false, false, false } +}; + +static const TypeGroupInfo saUnknownTypeInfo = + { TYPEID_UNKNOWN, TYPECATEGORY_BAR, SERVICE_CHART2_COLUMN, VARPOINTMODE_SINGLE, csscd::OUTSIDE, true, true, false, true, false, true, false, true, false, true, true }; + +const TypeGroupInfo& lclGetTypeInfoFromTypeId( TypeId eTypeId ) +{ + const TypeGroupInfo* pEnd = STATIC_ARRAY_END( spTypeInfos ); + for( const TypeGroupInfo* pIt = spTypeInfos; pIt != pEnd; ++pIt ) + if( pIt->meTypeId == eTypeId ) + return *pIt; + OSL_ENSURE( eTypeId == TYPEID_UNKNOWN, "lclGetTypeInfoFromTypeId - unexpected chart type identifier" ); + return saUnknownTypeInfo; +} + +} // namespace + +// ============================================================================ + +UpDownBarsConverter::UpDownBarsConverter( const ConverterRoot& rParent, UpDownBarsModel& rModel ) : + ConverterBase< UpDownBarsModel >( rParent, rModel ) +{ +} + +UpDownBarsConverter::~UpDownBarsConverter() +{ +} + +void UpDownBarsConverter::convertFromModel( const Reference< XChartType >& rxChartType ) +{ + PropertySet aTypeProp( rxChartType ); + + // upbar format + Reference< XPropertySet > xWhitePropSet; + if( aTypeProp.getProperty( xWhitePropSet, PROP_WhiteDay ) ) + { + PropertySet aPropSet( xWhitePropSet ); + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxUpBars, OBJECTTYPE_UPBAR ); + } + + // downbar format + Reference< XPropertySet > xBlackPropSet; + if( aTypeProp.getProperty( xBlackPropSet, PROP_BlackDay ) ) + { + PropertySet aPropSet( xBlackPropSet ); + getFormatter().convertFrameFormatting( aPropSet, mrModel.mxDownBars, OBJECTTYPE_DOWNBAR ); + } +} + +// ============================================================================ + +TypeGroupConverter::TypeGroupConverter( const ConverterRoot& rParent, TypeGroupModel& rModel ) : + ConverterBase< TypeGroupModel >( rParent, rModel ), + mb3dChart( false ) +{ + TypeId eTypeId = TYPEID_UNKNOWN; + switch( mrModel.mnTypeId ) + { +#define ENSURE_AXESCOUNT( min, max ) OSL_ENSURE( (min <= (int)mrModel.maAxisIds.size()) && ((int)mrModel.maAxisIds.size() <= max), "TypeGroupConverter::TypeGroupConverter - invalid axes count" ) + case C_TOKEN( area3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_AREA; mb3dChart = true; break; + case C_TOKEN( areaChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_AREA; mb3dChart = false; break; + case C_TOKEN( bar3DChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_BAR; mb3dChart = true; break; + case C_TOKEN( barChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BAR; mb3dChart = false; break; + case C_TOKEN( bubbleChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_BUBBLE; mb3dChart = false; break; + case C_TOKEN( doughnutChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_DOUGHNUT; mb3dChart = false; break; + case C_TOKEN( line3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_LINE; mb3dChart = true; break; + case C_TOKEN( lineChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_LINE; mb3dChart = false; break; + case C_TOKEN( ofPieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_OFPIE; mb3dChart = false; break; + case C_TOKEN( pie3DChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = true; break; + case C_TOKEN( pieChart ): ENSURE_AXESCOUNT( 0, 0 ); eTypeId = TYPEID_PIE; mb3dChart = false; break; + case C_TOKEN( radarChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_RADARLINE; mb3dChart = false; break; + case C_TOKEN( scatterChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_SCATTER; mb3dChart = false; break; + case C_TOKEN( stockChart ): ENSURE_AXESCOUNT( 2, 2 ); eTypeId = TYPEID_STOCK; mb3dChart = false; break; + case C_TOKEN( surface3DChart ): ENSURE_AXESCOUNT( 3, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break; + case C_TOKEN( surfaceChart ): ENSURE_AXESCOUNT( 2, 3 ); eTypeId = TYPEID_SURFACE; mb3dChart = true; break; // 3D bar chart from all surface charts + default: OSL_ENSURE( false, "TypeGroupConverter::TypeGroupConverter - unknown chart type" ); +#undef ENSURE_AXESCOUNT + } + + // special handling for some chart types + switch( eTypeId ) + { + case TYPEID_BAR: + if( mrModel.mnBarDir == XML_bar ) + eTypeId = TYPEID_HORBAR; + break; + case TYPEID_RADARLINE: + if( mrModel.mnRadarStyle == XML_filled ) + eTypeId = TYPEID_RADARAREA; + break; + case TYPEID_SURFACE: + // create a deep 3D bar chart from surface charts + mrModel.mnGrouping = XML_standard; + break; + default:; + } + + // set the chart type info struct for the current chart type + maTypeInfo = lclGetTypeInfoFromTypeId( eTypeId ); +} + +TypeGroupConverter::~TypeGroupConverter() +{ +} + +bool TypeGroupConverter::isStacked() const +{ + return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_stacked); +} + +bool TypeGroupConverter::isPercent() const +{ + return maTypeInfo.mbSupportsStacking && (mrModel.mnGrouping == XML_percentStacked); +} + +bool TypeGroupConverter::is3dChart() const +{ + return mb3dChart; +} + +bool TypeGroupConverter::isWall3dChart() const +{ + return mb3dChart && (maTypeInfo.meTypeCategory != TYPECATEGORY_PIE); +} + +bool TypeGroupConverter::isDeep3dChart() const +{ + return isWall3dChart() && (mrModel.mnGrouping == XML_standard); +} + +bool TypeGroupConverter::isSeriesFrameFormat() const +{ + return mb3dChart || maTypeInfo.mbSeriesIsFrame2d; +} + +ObjectType TypeGroupConverter::getSeriesObjectType() const +{ + return mb3dChart ? OBJECTTYPE_FILLEDSERIES3D : + (maTypeInfo.mbSeriesIsFrame2d ? OBJECTTYPE_FILLEDSERIES2D : OBJECTTYPE_LINEARSERIES2D); +} + +bool TypeGroupConverter::isReverseSeries() const +{ + return maTypeInfo.mbReverseSeries && !mb3dChart && !isStacked() && !isPercent(); +} + +OUString TypeGroupConverter::getSingleSeriesTitle() const +{ + OUString aSeriesTitle; + if( !mrModel.maSeries.empty() && (maTypeInfo.mbSingleSeriesVis || (mrModel.maSeries.size() == 1)) ) + if( const TextModel* pText = mrModel.maSeries.front()->mxText.get() ) + if( const DataSequenceModel* pDataSeq = pText->mxDataSeq.get() ) + if( !pDataSeq->maData.empty() ) + pDataSeq->maData.begin()->second >>= aSeriesTitle; + return aSeriesTitle; +} + +Reference< XCoordinateSystem > TypeGroupConverter::createCoordinateSystem() +{ + // find service name for coordinate system + OUString aServiceName; + if( maTypeInfo.mbPolarCoordSystem ) + { + if( mb3dChart ) + aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.PolarCoordinateSystem3d" ); + else + aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.PolarCoordinateSystem2d" ); + } + else + { + if( mb3dChart ) + aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.CartesianCoordinateSystem3d" ); + else + aServiceName = CREATE_OUSTRING( "com.sun.star.chart2.CartesianCoordinateSystem2d" ); + } + + // create the coordinate system object + Reference< XCoordinateSystem > xCoordSystem( createInstance( aServiceName ), UNO_QUERY ); + + // swap X and Y axis + if( maTypeInfo.mbSwappedAxesSet ) + { + PropertySet aPropSet( xCoordSystem ); + aPropSet.setProperty( PROP_SwapXAndYAxis, true ); + } + + return xCoordSystem; +} + +Reference< XLabeledDataSequence > TypeGroupConverter::createCategorySequence() +{ + Reference< XLabeledDataSequence > xLabeledSeq; + /* Find first existing category sequence. The bahaviour of Excel 2007 is + different to Excel 2003, which always used the category sequence of the + first series, even if it was empty. */ + for( TypeGroupModel::SeriesVector::iterator aIt = mrModel.maSeries.begin(), aEnd = mrModel.maSeries.end(); !xLabeledSeq.is() && (aIt != aEnd); ++aIt ) + { + if( (*aIt)->maSources.has( SeriesModel::CATEGORIES ) ) + { + SeriesConverter aSeriesConv( *this, **aIt ); + xLabeledSeq = aSeriesConv.createCategorySequence( CREATE_OUSTRING( "categories" ) ); + } + } + return xLabeledSeq; +} + +void TypeGroupConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, + const Reference< XCoordinateSystem >& rxCoordSystem, + sal_Int32 nAxesSetIdx, bool bSupportsVaryColorsByPoint ) +{ + try + { + // create the chart type object + OUString aService = OUString::createFromAscii( maTypeInfo.mpcServiceName ); + Reference< XChartType > xChartType( createInstance( aService ), UNO_QUERY_THROW ); + + // additional properties + PropertySet aDiaProp( rxDiagram ); + PropertySet aTypeProp( xChartType ); + switch( maTypeInfo.meTypeCategory ) + { + case TYPECATEGORY_BAR: + { + Sequence< sal_Int32 > aInt32Seq( 2 ); + aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnOverlap; + aTypeProp.setProperty( PROP_OverlapSequence, aInt32Seq ); + aInt32Seq[ 0 ] = aInt32Seq[ 1 ] = mrModel.mnGapWidth; + aTypeProp.setProperty( PROP_GapwidthSequence, aInt32Seq ); + } + break; + case TYPECATEGORY_PIE: + { + aTypeProp.setProperty( PROP_UseRings, maTypeInfo.meTypeId == TYPEID_DOUGHNUT ); + /* #i85166# starting angle of first pie slice. 3D pie charts + use Y rotation setting in view3D element. Of-pie charts do + not support pie rotation. */ + if( !is3dChart() && (maTypeInfo.meTypeId != TYPEID_OFPIE) ) + convertPieRotation( aDiaProp, mrModel.mnFirstAngle ); + } + break; + default:; + } + + // create converter objects for all series models + typedef RefVector< SeriesConverter > SeriesConvVector; + SeriesConvVector aSeries; + for( TypeGroupModel::SeriesVector::iterator aIt = mrModel.maSeries.begin(), aEnd = mrModel.maSeries.end(); aIt != aEnd; ++aIt ) + aSeries.push_back( SeriesConvVector::value_type( new SeriesConverter( *this, **aIt ) ) ); + + // reverse series order for some unstacked 2D chart types + if( isReverseSeries() ) + ::std::reverse( aSeries.begin(), aSeries.end() ); + + // decide whether to use varying colors for each data point + bool bVaryColorsByPoint = bSupportsVaryColorsByPoint && mrModel.mbVaryColors; + switch( maTypeInfo.meVarPointMode ) + { + case VARPOINTMODE_NONE: bVaryColorsByPoint = false; break; + case VARPOINTMODE_SINGLE: bVaryColorsByPoint &= (mrModel.maSeries.size() == 1); break; + case VARPOINTMODE_MULTI: break; + } + + /* Stock chart needs special processing. Create one 'big' series with + data sequences of different roles. */ + if( maTypeInfo.meTypeId == TYPEID_STOCK ) + { + // create the data series object + Reference< XDataSeries > xDataSeries( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.DataSeries" ) ), UNO_QUERY ); + Reference< XDataSink > xDataSink( xDataSeries, UNO_QUERY ); + if( xDataSink.is() ) + { + // create a list of data sequences from all series + ::std::vector< Reference< XLabeledDataSequence > > aLabeledSeqVec; + OSL_ENSURE( aSeries.size() >= 3, "TypeGroupConverter::convertFromModel - too few stock chart series" ); + int nRoleIdx = (aSeries.size() == 3) ? 1 : 0; + for( SeriesConvVector::iterator aIt = aSeries.begin(), aEnd = aSeries.end(); (nRoleIdx < 4) && (aIt != aEnd); ++nRoleIdx, ++aIt ) + { + // create a data sequence with a specific role + OUString aRole; + switch( nRoleIdx ) + { + case 0: aRole = CREATE_OUSTRING( "values-first" ); break; + case 1: aRole = CREATE_OUSTRING( "values-max" ); break; + case 2: aRole = CREATE_OUSTRING( "values-min" ); break; + case 3: aRole = CREATE_OUSTRING( "values-last" ); break; + } + Reference< XLabeledDataSequence > xDataSeq = (*aIt)->createValueSequence( aRole ); + if( xDataSeq.is() ) + aLabeledSeqVec.push_back( xDataSeq ); + } + + // attach labeled data sequences to series and insert series into chart type + xDataSink->setData( ContainerHelper::vectorToSequence( aLabeledSeqVec ) ); + + // formatting of high/low lines + aTypeProp.setProperty( PROP_ShowHighLow, true ); + PropertySet aSeriesProp( xDataSeries ); + if( mrModel.mxHiLowLines.is() ) + getFormatter().convertFrameFormatting( aSeriesProp, mrModel.mxHiLowLines, OBJECTTYPE_HILOLINE ); + else + // hi/low-lines cannot be switched off via "ShowHighLow" property (?) + aSeriesProp.setProperty( PROP_LineStyle, ::com::sun::star::drawing::LineStyle_NONE ); + + // formatting of up/down bars + bool bUpDownBars = mrModel.mxUpDownBars.is(); + aTypeProp.setProperty( PROP_Japanese, bUpDownBars ); + aTypeProp.setProperty( PROP_ShowFirst, bUpDownBars ); + if( bUpDownBars ) + { + UpDownBarsConverter aUpDownConv( *this, *mrModel.mxUpDownBars ); + aUpDownConv.convertFromModel( xChartType ); + } + + // insert the series into the chart type object + insertDataSeries( xChartType, xDataSeries, nAxesSetIdx ); + } + } + else + { + for( SeriesConvVector::iterator aIt = aSeries.begin(), aEnd = aSeries.end(); aIt != aEnd; ++aIt ) + { + SeriesConverter& rSeriesConv = **aIt; + Reference< XDataSeries > xDataSeries = rSeriesConv.createDataSeries( *this, bVaryColorsByPoint ); + insertDataSeries( xChartType, xDataSeries, nAxesSetIdx ); + + /* Excel does not use the value of the c:smooth element of the + chart type to set a default line smoothing for the data + series. Line smoothing is always controlled by the c:smooth + element of the respective data series. If the element in the + data series is missing, line smoothing is off, regardless of + the c:smooth element of the chart type. */ +#if !OOX_CHART_SMOOTHED_PER_SERIES + if( rSeriesConv.getModel().mbSmooth ) + convertLineSmooth( aTypeProp, true ); +#endif + } + } + + // add chart type object to coordinate system + Reference< XChartTypeContainer > xChartTypeCont( rxCoordSystem, UNO_QUERY_THROW ); + xChartTypeCont->addChartType( xChartType ); + + // set existence of bar connector lines at diagram (only in stacked 2D bar charts) + if( mrModel.mxSerLines.is() && !mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) && (isStacked() || isPercent()) ) + aDiaProp.setProperty( PROP_ConnectBars, true ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "TypeGroupConverter::convertFromModel - cannot add chart type" ); + } +} + +void TypeGroupConverter::convertMarker( PropertySet& rPropSet, sal_Int32 nOoxSymbol, sal_Int32 nOoxSize ) const +{ + if( !isSeriesFrameFormat() ) + { + namespace cssc = ::com::sun::star::chart2; + + // symbol style + cssc::Symbol aSymbol; + aSymbol.Style = cssc::SymbolStyle_STANDARD; + switch( nOoxSymbol ) + { + case XML_auto: aSymbol.Style = cssc::SymbolStyle_AUTO; break; + case XML_none: aSymbol.Style = cssc::SymbolStyle_NONE; break; + case XML_square: aSymbol.StandardSymbol = 0; break; // square + case XML_diamond: aSymbol.StandardSymbol = 1; break; // diamond + case XML_triangle: aSymbol.StandardSymbol = 3; break; // arrow up + case XML_x: aSymbol.StandardSymbol = 6; break; // bow tie + case XML_star: aSymbol.StandardSymbol = 7; break; // sand glass + case XML_dot: aSymbol.StandardSymbol = 4; break; // arrow right + case XML_dash: aSymbol.StandardSymbol = 2; break; // arrow down + case XML_circle: aSymbol.StandardSymbol = 4; break; // arrow right + case XML_plus: aSymbol.StandardSymbol = 5; break; // arrow left + } + + // symbol size (points in OOXML, 1/100 mm in Chart2) + sal_Int32 nSize = static_cast< sal_Int32 >( nOoxSize * (2540.0 / 72.0) + 0.5 ); + aSymbol.Size.Width = aSymbol.Size.Height = nSize; + + // set the property + rPropSet.setProperty( PROP_Symbol, aSymbol ); + } +} + +void TypeGroupConverter::convertLineSmooth( PropertySet& rPropSet, bool bOoxSmooth ) const +{ + if( !isSeriesFrameFormat() && (maTypeInfo.meTypeCategory != TYPECATEGORY_RADAR) ) + { + namespace cssc = ::com::sun::star::chart2; + cssc::CurveStyle eCurveStyle = bOoxSmooth ? cssc::CurveStyle_CUBIC_SPLINES : cssc::CurveStyle_LINES; + rPropSet.setProperty( PROP_CurveStyle, eCurveStyle ); + } +} + +void TypeGroupConverter::convertBarGeometry( PropertySet& rPropSet, sal_Int32 nOoxShape ) const +{ + if( mb3dChart && (maTypeInfo.meTypeCategory == TYPECATEGORY_BAR) ) + { + namespace cssc = ::com::sun::star::chart2; + + sal_Int32 nGeom3d = cssc::DataPointGeometry3D::CUBOID; + switch( nOoxShape ) + { + case XML_box: nGeom3d = cssc::DataPointGeometry3D::CUBOID; break; + case XML_cone: nGeom3d = cssc::DataPointGeometry3D::CONE; break; + case XML_coneToMax: nGeom3d = cssc::DataPointGeometry3D::CONE; break; + case XML_cylinder: nGeom3d = cssc::DataPointGeometry3D::CYLINDER; break; + case XML_pyramid: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break; + case XML_pyramidToMax: nGeom3d = cssc::DataPointGeometry3D::PYRAMID; break; + default: OSL_ENSURE( false, "TypeGroupConverter::convertBarGeometry - unknown 3D bar shape type" ); + } + rPropSet.setProperty( PROP_Geometry3D, nGeom3d ); + } +} + +void TypeGroupConverter::convertPieRotation( PropertySet& rPropSet, sal_Int32 nOoxAngle ) const +{ + if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE ) + { + // map OOXML [0,360] clockwise (0deg top) to Chart2 counterclockwise (0deg left) + sal_Int32 nAngle = (450 - nOoxAngle) % 360; + rPropSet.setProperty( PROP_StartingAngle, nAngle ); + } +} + +void TypeGroupConverter::convertPieExplosion( PropertySet& rPropSet, sal_Int32 nOoxExplosion ) const +{ + if( maTypeInfo.meTypeCategory == TYPECATEGORY_PIE ) + { + // pie explosion restricted to 100% in Chart2, set as double in range [0,1] + double fOffset = getLimitedValue< double >( nOoxExplosion / 100.0, 0.0, 1.0 ); + rPropSet.setProperty( PROP_Offset, fOffset ); + } +} + +// private -------------------------------------------------------------------- + +void TypeGroupConverter::insertDataSeries( const Reference< XChartType >& rxChartType, const Reference< XDataSeries >& rxSeries, sal_Int32 nAxesSetIdx ) +{ + if( rxSeries.is() ) + { + PropertySet aSeriesProp( rxSeries ); + + // series stacking mode + namespace cssc = ::com::sun::star::chart2; + cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING; + // stacked overrides deep-3d + if( isStacked() || isPercent() ) + eStacking = cssc::StackingDirection_Y_STACKING; + else if( isDeep3dChart() ) + eStacking = cssc::StackingDirection_Z_STACKING; + aSeriesProp.setProperty( PROP_StackingDirection, eStacking ); + + // additional series properties + aSeriesProp.setProperty( PROP_AttachedAxisIndex, nAxesSetIdx ); + + // insert series into container + try + { + Reference< XDataSeriesContainer > xSeriesCont( rxChartType, UNO_QUERY_THROW ); + xSeriesCont->addDataSeries( rxSeries ); + } + catch( Exception& ) + { + OSL_ENSURE( false, "TypeGroupConverter::insertDataSeries - cannot add data series" ); + } + } +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/chart/typegroupmodel.cxx b/oox/source/drawingml/chart/typegroupmodel.cxx new file mode 100644 index 000000000000..ee5eefc4d163 --- /dev/null +++ b/oox/source/drawingml/chart/typegroupmodel.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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/chart/typegroupmodel.hxx" + +namespace oox { +namespace drawingml { +namespace chart { + +// ============================================================================ + +UpDownBarsModel::UpDownBarsModel() : + mnGapWidth( 150 ) +{ +} + +UpDownBarsModel::~UpDownBarsModel() +{ +} + +// ============================================================================ + +TypeGroupModel::TypeGroupModel( sal_Int32 nTypeId ) : + mfSplitPos( 0.0 ), + mnBarDir( XML_col ), + mnBubbleScale( 100 ), + mnFirstAngle( 0 ), + mnGapDepth( 150 ), + mnGapWidth( 150 ), + mnGrouping( XML_standard ), + mnHoleSize( 10 ), + mnOfPieType( XML_pie ), + mnOverlap( 0 ), + mnRadarStyle( XML_standard ), + mnScatterStyle( XML_marker ), + mnSecondPieSize( 75 ), + mnShape( XML_box ), + mnSizeRepresents( XML_area ), + mnSplitType( XML_auto ), + mnTypeId( nTypeId ), + mbBubble3d( false ), + mbShowMarker( false ), + mbShowNegBubbles( false ), + mbSmooth( false ), + mbVaryColors( false ), + mbWireframe( false ) +{ +} + +TypeGroupModel::~TypeGroupModel() +{ +} + +// ============================================================================ + +} // namespace chart +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/clrscheme.cxx b/oox/source/drawingml/clrscheme.cxx new file mode 100644 index 000000000000..b011cd27b147 --- /dev/null +++ b/oox/source/drawingml/clrscheme.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * 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/clrscheme.hxx" +#include "oox/token/tokens.hxx" + +namespace oox { namespace drawingml { + +sal_Bool ClrMap::getColorMap( sal_Int32& nClrToken ) +{ + sal_Int32 nMapped = 0; + std::map < sal_Int32, sal_Int32 >::const_iterator aIter( maClrMap.find( nClrToken ) ); + if ( aIter != maClrMap.end() ) + nMapped = (*aIter).second; + if ( nMapped ) + { + nClrToken = nMapped; + return sal_True; + } + else + return sal_False; +} + +void ClrMap::setColorMap( sal_Int32 nClrToken, sal_Int32 nMappedClrToken ) +{ + maClrMap[ nClrToken ] = nMappedClrToken; +} + +//----------------------------------------------------------------------------------------- + +ClrScheme::ClrScheme() +{ +} +ClrScheme::~ClrScheme() +{ +} + +sal_Bool ClrScheme::getColor( sal_Int32 nSchemeClrToken, sal_Int32& rColor ) const +{ + switch( nSchemeClrToken ) + { + case XML_bg1 : nSchemeClrToken = XML_lt1; break; + case XML_bg2 : nSchemeClrToken = XML_lt2; break; + case XML_tx1 : nSchemeClrToken = XML_dk1; break; + case XML_tx2 : nSchemeClrToken = XML_dk2; break; + } + std::map < sal_Int32, sal_Int32 >::const_iterator aIter( maClrScheme.find( nSchemeClrToken ) ); + if ( aIter != maClrScheme.end() ) + rColor = (*aIter).second; + return aIter != maClrScheme.end(); +} + +void ClrScheme::setColor( sal_Int32 nSchemeClrToken, sal_Int32 nColor ) +{ + maClrScheme[ nSchemeClrToken ] = nColor; +} + +} } diff --git a/oox/source/drawingml/clrschemecontext.cxx b/oox/source/drawingml/clrschemecontext.cxx new file mode 100644 index 000000000000..fad92dd35c3c --- /dev/null +++ b/oox/source/drawingml/clrschemecontext.cxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * 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/clrschemecontext.hxx" +#include "oox/core/xmlfilterbase.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +static void setClrMap( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, + ClrMap& rClrMap, sal_Int32 nToken ) +{ + if ( xAttributes->hasAttribute( nToken ) ) + { + sal_Int32 nMappedToken = xAttributes->getOptionalValueToken( nToken, 0 ); + rClrMap.setColorMap( nToken, nMappedToken ); + } +} + +clrMapContext::clrMapContext( ContextHandler& rParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, ClrMap& rClrMap ) +: ContextHandler( rParent ) +{ + setClrMap( xAttributes, rClrMap, XML_bg1 ); + setClrMap( xAttributes, rClrMap, XML_tx1 ); + setClrMap( xAttributes, rClrMap, XML_bg2 ); + setClrMap( xAttributes, rClrMap, XML_tx2 ); + setClrMap( xAttributes, rClrMap, XML_accent1 ); + setClrMap( xAttributes, rClrMap, XML_accent2 ); + setClrMap( xAttributes, rClrMap, XML_accent3 ); + setClrMap( xAttributes, rClrMap, XML_accent4 ); + setClrMap( xAttributes, rClrMap, XML_accent5 ); + setClrMap( xAttributes, rClrMap, XML_accent6 ); + setClrMap( xAttributes, rClrMap, XML_hlink ); + setClrMap( xAttributes, rClrMap, XML_folHlink ); +} + +clrSchemeColorContext::clrSchemeColorContext( ContextHandler& rParent, ClrScheme& rClrScheme, sal_Int32 nColorToken ) : + ColorContext( rParent, *this ), + mrClrScheme( rClrScheme ), + mnColorToken( nColorToken ) +{ +} + +clrSchemeColorContext::~clrSchemeColorContext() +{ + mrClrScheme.setColor( mnColorToken, getColor( getFilter().getGraphicHelper() ) ); +} + +clrSchemeContext::clrSchemeContext( ContextHandler& rParent, ClrScheme& rClrScheme ) : + ContextHandler( rParent ), + mrClrScheme( rClrScheme ) +{ +} + +Reference< XFastContextHandler > clrSchemeContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( dk1 ): + case A_TOKEN( lt1 ): + case A_TOKEN( dk2 ): + case A_TOKEN( lt2 ): + case A_TOKEN( accent1 ): + case A_TOKEN( accent2 ): + case A_TOKEN( accent3 ): + case A_TOKEN( accent4 ): + case A_TOKEN( accent5 ): + case A_TOKEN( accent6 ): + case A_TOKEN( hlink ): + case A_TOKEN( folHlink ): + return new clrSchemeColorContext( *this, mrClrScheme, getBaseToken( nElement ) ); + } + return 0; +} + +} } diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx new file mode 100644 index 000000000000..4ff19a4bf987 --- /dev/null +++ b/oox/source/drawingml/color.cxx @@ -0,0 +1,670 @@ +/************************************************************************* + * + * 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/color.hxx" +#include <algorithm> +#include <math.h> +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/token/namespaces.hxx" +#include "oox/token/tokens.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +namespace { + +/** Global storage for predefined color values used in OOXML file formats. */ +struct PresetColorsPool +{ + typedef ::std::vector< sal_Int32 > ColorVector; + + ColorVector maDmlColors; /// Predefined colors in DrawingML, indexed by XML token. + ColorVector maVmlColors; /// Predefined colors in VML, indexed by XML token. + + explicit PresetColorsPool(); +}; + +// ---------------------------------------------------------------------------- + +PresetColorsPool::PresetColorsPool() : + maDmlColors( static_cast< size_t >( XML_TOKEN_COUNT ), API_RGB_TRANSPARENT ), + maVmlColors( static_cast< size_t >( XML_TOKEN_COUNT ), API_RGB_TRANSPARENT ) +{ + // predefined colors in DrawingML (map XML token identifiers to RGB values) + static const sal_Int32 spnDmlColors[] = + { + XML_aliceBlue, 0xF0F8FF, XML_antiqueWhite, 0xFAEBD7, + XML_aqua, 0x00FFFF, XML_aquamarine, 0x7FFFD4, + XML_azure, 0xF0FFFF, XML_beige, 0xF5F5DC, + XML_bisque, 0xFFE4C4, XML_black, 0x000000, + XML_blanchedAlmond, 0xFFEBCD, XML_blue, 0x0000FF, + XML_blueViolet, 0x8A2BE2, XML_brown, 0xA52A2A, + XML_burlyWood, 0xDEB887, XML_cadetBlue, 0x5F9EA0, + XML_chartreuse, 0x7FFF00, XML_chocolate, 0xD2691E, + XML_coral, 0xFF7F50, XML_cornflowerBlue, 0x6495ED, + XML_cornsilk, 0xFFF8DC, XML_crimson, 0xDC143C, + XML_cyan, 0x00FFFF, XML_deepPink, 0xFF1493, + XML_deepSkyBlue, 0x00BFFF, XML_dimGray, 0x696969, + XML_dkBlue, 0x00008B, XML_dkCyan, 0x008B8B, + XML_dkGoldenrod, 0xB8860B, XML_dkGray, 0xA9A9A9, + XML_dkGreen, 0x006400, XML_dkKhaki, 0xBDB76B, + XML_dkMagenta, 0x8B008B, XML_dkOliveGreen, 0x556B2F, + XML_dkOrange, 0xFF8C00, XML_dkOrchid, 0x9932CC, + XML_dkRed, 0x8B0000, XML_dkSalmon, 0xE9967A, + XML_dkSeaGreen, 0x8FBC8B, XML_dkSlateBlue, 0x483D8B, + XML_dkSlateGray, 0x2F4F4F, XML_dkTurquoise, 0x00CED1, + XML_dkViolet, 0x9400D3, XML_dodgerBlue, 0x1E90FF, + XML_firebrick, 0xB22222, XML_floralWhite, 0xFFFAF0, + XML_forestGreen, 0x228B22, XML_fuchsia, 0xFF00FF, + XML_gainsboro, 0xDCDCDC, XML_ghostWhite, 0xF8F8FF, + XML_gold, 0xFFD700, XML_goldenrod, 0xDAA520, + XML_gray, 0x808080, XML_green, 0x008000, + XML_greenYellow, 0xADFF2F, XML_honeydew, 0xF0FFF0, + XML_hotPink, 0xFF69B4, XML_indianRed, 0xCD5C5C, + XML_indigo, 0x4B0082, XML_ivory, 0xFFFFF0, + XML_khaki, 0xF0E68C, XML_lavender, 0xE6E6FA, + XML_lavenderBlush, 0xFFF0F5, XML_lawnGreen, 0x7CFC00, + XML_lemonChiffon, 0xFFFACD, XML_lime, 0x00FF00, + XML_limeGreen, 0x32CD32, XML_linen, 0xFAF0E6, + XML_ltBlue, 0xADD8E6, XML_ltCoral, 0xF08080, + XML_ltCyan, 0xE0FFFF, XML_ltGoldenrodYellow, 0xFAFA78, + XML_ltGray, 0xD3D3D3, XML_ltGreen, 0x90EE90, + XML_ltPink, 0xFFB6C1, XML_ltSalmon, 0xFFA07A, + XML_ltSeaGreen, 0x20B2AA, XML_ltSkyBlue, 0x87CEFA, + XML_ltSlateGray, 0x778899, XML_ltSteelBlue, 0xB0C4DE, + XML_ltYellow, 0xFFFFE0, XML_magenta, 0xFF00FF, + XML_maroon, 0x800000, XML_medAquamarine, 0x66CDAA, + XML_medBlue, 0x0000CD, XML_medOrchid, 0xBA55D3, + XML_medPurple, 0x9370DB, XML_medSeaGreen, 0x3CB371, + XML_medSlateBlue, 0x7B68EE, XML_medSpringGreen, 0x00FA9A, + XML_medTurquoise, 0x48D1CC, XML_medVioletRed, 0xC71585, + XML_midnightBlue, 0x191970, XML_mintCream, 0xF5FFFA, + XML_mistyRose, 0xFFE4E1, XML_moccasin, 0xFFE4B5, + XML_navajoWhite, 0xFFDEAD, XML_navy, 0x000080, + XML_oldLace, 0xFDF5E6, XML_olive, 0x808000, + XML_oliveDrab, 0x6B8E23, XML_orange, 0xFFA500, + XML_orangeRed, 0xFF4500, XML_orchid, 0xDA70D6, + XML_paleGoldenrod, 0xEEE8AA, XML_paleGreen, 0x98FB98, + XML_paleTurquoise, 0xAFEEEE, XML_paleVioletRed, 0xDB7093, + XML_papayaWhip, 0xFFEFD5, XML_peachPuff, 0xFFDAB9, + XML_peru, 0xCD853F, XML_pink, 0xFFC0CB, + XML_plum, 0xDDA0DD, XML_powderBlue, 0xB0E0E6, + XML_purple, 0x800080, XML_red, 0xFF0000, + XML_rosyBrown, 0xBC8F8F, XML_royalBlue, 0x4169E1, + XML_saddleBrown, 0x8B4513, XML_salmon, 0xFA8072, + XML_sandyBrown, 0xF4A460, XML_seaGreen, 0x2E8B57, + XML_seaShell, 0xFFF5EE, XML_sienna, 0xA0522D, + XML_silver, 0xC0C0C0, XML_skyBlue, 0x87CEEB, + XML_slateBlue, 0x6A5ACD, XML_slateGray, 0x708090, + XML_snow, 0xFFFAFA, XML_springGreen, 0x00FF7F, + XML_steelBlue, 0x4682B4, XML_tan, 0xD2B48C, + XML_teal, 0x008080, XML_thistle, 0xD8BFD8, + XML_tomato, 0xFF6347, XML_turquoise, 0x40E0D0, + XML_violet, 0xEE82EE, XML_wheat, 0xF5DEB3, + XML_white, 0xFFFFFF, XML_whiteSmoke, 0xF5F5F5, + XML_yellow, 0xFFFF00, XML_yellowGreen, 0x9ACD32 + }; + for( const sal_Int32* pnEntry = spnDmlColors; pnEntry < STATIC_ARRAY_END( spnDmlColors ); pnEntry += 2 ) + maDmlColors[ static_cast< size_t >( pnEntry[ 0 ] ) ] = pnEntry[ 1 ]; + + // predefined colors in VML (map XML token identifiers to RGB values) + static const sal_Int32 spnVmlColors[] = + { + XML_aqua, 0x00FFFF, XML_black, 0x000000, + XML_blue, 0x0000FF, XML_fuchsia, 0xFF00FF, + XML_gray, 0x808080, XML_green, 0x008000, + XML_lime, 0x00FF00, XML_maroon, 0x800000, + XML_navy, 0x000080, XML_olive, 0x808000, + XML_purple, 0x800080, XML_red, 0xFF0000, + XML_silver, 0xC0C0C0, XML_teal, 0x008080, + XML_white, 0xFFFFFF, XML_yellow, 0xFFFF00 + }; + for( const sal_Int32* pnEntry = spnVmlColors; pnEntry < STATIC_ARRAY_END( spnVmlColors ); pnEntry += 2 ) + maVmlColors[ static_cast< size_t >( pnEntry[ 0 ] ) ] = pnEntry[ 1 ]; +} + +// ---------------------------------------------------------------------------- + +struct StaticPresetColorsPool : public ::rtl::Static< PresetColorsPool, StaticPresetColorsPool > {}; + +// ---------------------------------------------------------------------------- + +const double DEC_GAMMA = 2.3; +const double INC_GAMMA = 1.0 / DEC_GAMMA; + +// ---------------------------------------------------------------------------- + +inline void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, sal_Int32 nRgb ) +{ + ornR = (nRgb >> 16) & 0xFF; + ornG = (nRgb >> 8) & 0xFF; + ornB = nRgb & 0xFF; +} + +inline sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB ) +{ + return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB ); +} + +inline sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp ) +{ + return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 ); +} + +inline sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp ) +{ + return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT ); +} + +inline sal_Int32 lclGamma( sal_Int32 nComp, double fGamma ) +{ + return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 ); +} + +void lclSetValue( sal_Int32& ornValue, sal_Int32 nNew, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (0 <= nNew) && (nNew <= nMax), "lclSetValue - invalid value" ); + if( (0 <= nNew) && (nNew <= nMax) ) + ornValue = nNew; +} + +void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" ); + ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax ); +} + +void lclOffValue( sal_Int32& ornValue, sal_Int32 nOff, sal_Int32 nMax = MAX_PERCENT ) +{ + OSL_ENSURE( (-nMax <= nOff) && (nOff <= nMax), "lclOffValue - invalid offset" ); + ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax ); +} + +} // namespace + +// ============================================================================ + +Color::Color() : + meMode( COLOR_UNUSED ), + mnC1( 0 ), + mnC2( 0 ), + mnC3( 0 ), + mnAlpha( MAX_PERCENT ) +{ +} + +Color::~Color() +{ +} + +/*static*/ sal_Int32 Color::getDmlPresetColor( sal_Int32 nToken, sal_Int32 nDefaultRgb ) +{ + /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be + able to catch the existing vector entries without corresponding XML + token identifier. */ + sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maDmlColors, nToken, API_RGB_TRANSPARENT ); + return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb; +} + +/*static*/ sal_Int32 Color::getVmlPresetColor( sal_Int32 nToken, sal_Int32 nDefaultRgb ) +{ + /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be + able to catch the existing vector entries without corresponding XML + token identifier. */ + sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maVmlColors, nToken, API_RGB_TRANSPARENT ); + return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb; +} + +void Color::setUnused() +{ + meMode = COLOR_UNUSED; +} + +void Color::setSrgbClr( sal_Int32 nRgb ) +{ + OSL_ENSURE( (0 <= nRgb) && (nRgb <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" ); + meMode = COLOR_RGB; + lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb ); +} + +void Color::setScrgbClr( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB ) +{ + OSL_ENSURE( (0 <= nR) && (nR <= MAX_PERCENT), "Color::setScrgbClr - invalid red value" ); + OSL_ENSURE( (0 <= nG) && (nG <= MAX_PERCENT), "Color::setScrgbClr - invalid green value" ); + OSL_ENSURE( (0 <= nB) && (nB <= MAX_PERCENT), "Color::setScrgbClr - invalid blue value" ); + meMode = COLOR_CRGB; + mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nR, 0, MAX_PERCENT ); + mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nG, 0, MAX_PERCENT ); + mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nB, 0, MAX_PERCENT ); +} + +void Color::setHslClr( sal_Int32 nHue, sal_Int32 nSat, sal_Int32 nLum ) +{ + OSL_ENSURE( (0 <= nHue) && (nHue <= MAX_DEGREE), "Color::setHslClr - invalid hue value" ); + OSL_ENSURE( (0 <= nSat) && (nSat <= MAX_PERCENT), "Color::setHslClr - invalid saturation value" ); + OSL_ENSURE( (0 <= nLum) && (nLum <= MAX_PERCENT), "Color::setHslClr - invalid luminance value" ); + meMode = COLOR_HSL; + mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nHue, 0, MAX_DEGREE ); + mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nSat, 0, MAX_PERCENT ); + mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nLum, 0, MAX_PERCENT ); +} + +void Color::setPrstClr( sal_Int32 nToken ) +{ + sal_Int32 nRgbValue = getDmlPresetColor( nToken, API_RGB_TRANSPARENT ); + OSL_ENSURE( nRgbValue >= 0, "Color::setPrstClr - invalid preset color token" ); + if( nRgbValue >= 0 ) + setSrgbClr( nRgbValue ); +} + +void Color::setSchemeClr( sal_Int32 nToken ) +{ + OSL_ENSURE( nToken != XML_TOKEN_INVALID, "Color::setSchemeClr - invalid color token" ); + meMode = (nToken == XML_phClr) ? COLOR_PH : COLOR_SCHEME; + mnC1 = nToken; +} + +void Color::setPaletteClr( sal_Int32 nPaletteIdx ) +{ + OSL_ENSURE( nPaletteIdx >= 0, "Color::setPaletteClr - invalid palette index" ); + meMode = COLOR_PALETTE; + mnC1 = nPaletteIdx; +} + +void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRgb ) +{ + OSL_ENSURE( (-1 <= nLastRgb) && (nLastRgb <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" ); + meMode = COLOR_SYSTEM; + mnC1 = nToken; + mnC2 = nLastRgb; +} + +void Color::addTransformation( sal_Int32 nElement, sal_Int32 nValue ) +{ + /* Execute alpha transformations directly, store other transformations in + a vector, they may depend on a scheme base color which will be resolved + in Color::getColor(). */ + sal_Int32 nToken = getBaseToken( nElement ); + switch( nToken ) + { + case XML_alpha: lclSetValue( mnAlpha, nValue ); break; + case XML_alphaMod: lclModValue( mnAlpha, nValue ); break; + case XML_alphaOff: lclOffValue( mnAlpha, nValue ); break; + default: maTransforms.push_back( Transformation( nToken, nValue ) ); + } +} + +void Color::addChartTintTransformation( double fTint ) +{ + sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT ); + if( nValue < 0 ) + maTransforms.push_back( Transformation( XML_shade, nValue + MAX_PERCENT ) ); + else if( nValue > 0 ) + maTransforms.push_back( Transformation( XML_tint, MAX_PERCENT - nValue ) ); +} + +void Color::addExcelTintTransformation( double fTint ) +{ + sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT ); + maTransforms.push_back( Transformation( XLS_TOKEN( tint ), nValue ) ); +} + +void Color::clearTransformations() +{ + maTransforms.clear(); + clearTransparence(); +} + +void Color::clearTransparence() +{ + mnAlpha = MAX_PERCENT; +} + +sal_Int32 Color::getColor( const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const +{ + /* Special handling for theme style list placeholder colors (state + COLOR_PH), Color::getColor() may be called with different placeholder + colors in the nPhClr parameter. Therefore, the resolved color will not + be stored in this object, thus the state COLOR_FINAL will not be + reached and the transformation container will not be cleared, but the + original COLOR_PH state will be restored instead. */ + bool bIsPh = false; + + switch( meMode ) + { + case COLOR_UNUSED: mnC1 = API_RGB_TRANSPARENT; break; + + case COLOR_RGB: break; // nothing to do + case COLOR_CRGB: break; // nothing to do + case COLOR_HSL: break; // nothing to do + + case COLOR_SCHEME: setResolvedRgb( rGraphicHelper.getSchemeColor( mnC1 ) ); break; + case COLOR_PALETTE: setResolvedRgb( rGraphicHelper.getPaletteColor( mnC1 ) ); break; + case COLOR_SYSTEM: setResolvedRgb( rGraphicHelper.getSystemColor( mnC1, mnC2 ) ); break; + case COLOR_PH: setResolvedRgb( nPhClr ); bIsPh = true; break; + + case COLOR_FINAL: return mnC1; + } + + // if color is UNUSED or turns to UNUSED in setResolvedRgb, do not perform transformations + if( meMode != COLOR_UNUSED ) + { + for( TransformVec::const_iterator aIt = maTransforms.begin(), aEnd = maTransforms.end(); aIt != aEnd; ++aIt ) + { + switch( aIt->mnToken ) + { + case XML_red: toCrgb(); lclSetValue( mnC1, aIt->mnValue ); break; + case XML_redMod: toCrgb(); lclModValue( mnC1, aIt->mnValue ); break; + case XML_redOff: toCrgb(); lclOffValue( mnC1, aIt->mnValue ); break; + case XML_green: toCrgb(); lclSetValue( mnC2, aIt->mnValue ); break; + case XML_greenMod: toCrgb(); lclModValue( mnC2, aIt->mnValue ); break; + case XML_greenOff: toCrgb(); lclOffValue( mnC2, aIt->mnValue ); break; + case XML_blue: toCrgb(); lclSetValue( mnC3, aIt->mnValue ); break; + case XML_blueMod: toCrgb(); lclModValue( mnC3, aIt->mnValue ); break; + case XML_blueOff: toCrgb(); lclOffValue( mnC3, aIt->mnValue ); break; + + case XML_hue: toHsl(); lclSetValue( mnC1, aIt->mnValue, MAX_DEGREE ); break; + case XML_hueMod: toHsl(); lclModValue( mnC1, aIt->mnValue, MAX_DEGREE ); break; + case XML_hueOff: toHsl(); lclOffValue( mnC1, aIt->mnValue, MAX_DEGREE ); break; + case XML_sat: toHsl(); lclSetValue( mnC2, aIt->mnValue ); break; + case XML_satMod: toHsl(); lclModValue( mnC2, aIt->mnValue ); break; + case XML_satOff: toHsl(); lclOffValue( mnC2, aIt->mnValue ); break; + + case XML_lum: + toHsl(); + lclSetValue( mnC3, aIt->mnValue ); + // if color changes to black or white, it will stay gray if luminance changes again + if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0; + break; + case XML_lumMod: + toHsl(); + lclModValue( mnC3, aIt->mnValue ); + // if color changes to black or white, it will stay gray if luminance changes again + if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0; + break; + case XML_lumOff: + toHsl(); + lclOffValue( mnC3, aIt->mnValue ); + // if color changes to black or white, it will stay gray if luminance changes again + if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0; + break; + + case XML_shade: + // shade: 0% = black, 100% = original color + toCrgb(); + OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid shade value" ); + if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) ) + { + double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT; + mnC1 = static_cast< sal_Int32 >( mnC1 * fFactor ); + mnC2 = static_cast< sal_Int32 >( mnC2 * fFactor ); + mnC3 = static_cast< sal_Int32 >( mnC3 * fFactor ); + } + break; + case XML_tint: + // tint: 0% = white, 100% = original color + toCrgb(); + OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" ); + if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) ) + { + double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT; + mnC1 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC1) * fFactor ); + mnC2 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC2) * fFactor ); + mnC3 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC3) * fFactor ); + } + break; + case XLS_TOKEN( tint ): + // Excel tint: move luminance relative to current value + toHsl(); + OSL_ENSURE( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" ); + if( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue < 0) ) + { + // negative: luminance towards 0% (black) + lclModValue( mnC3, aIt->mnValue + MAX_PERCENT ); + } + else if( (0 < aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) ) + { + // positive: luminance towards 100% (white) + mnC3 = MAX_PERCENT - mnC3; + lclModValue( mnC3, MAX_PERCENT - aIt->mnValue ); + mnC3 = MAX_PERCENT - mnC3; + } + break; + + case XML_gray: + // change color to gray, weighted RGB: 22% red, 72% green, 6% blue + toRgb(); + mnC1 = mnC2 = mnC3 = (mnC1 * 22 + mnC2 * 72 + mnC3 * 6) / 100; + break; + + case XML_comp: + // comp: rotate hue by 180 degrees, do not change lum/sat + toHsl(); + (mnC1 += 180 * PER_DEGREE) %= MAX_DEGREE; + break; + case XML_inv: + // invert percentual RGB values + toCrgb(); + mnC1 = MAX_PERCENT - mnC1; + mnC2 = MAX_PERCENT - mnC2; + mnC3 = MAX_PERCENT - mnC3; + break; + + case XML_gamma: + // increase gamma of color + toCrgb(); + mnC1 = lclGamma( mnC1, INC_GAMMA ); + mnC2 = lclGamma( mnC2, INC_GAMMA ); + mnC3 = lclGamma( mnC3, INC_GAMMA ); + break; + case XML_invGamma: + // decrease gamma of color + toCrgb(); + mnC1 = lclGamma( mnC1, DEC_GAMMA ); + mnC2 = lclGamma( mnC2, DEC_GAMMA ); + mnC3 = lclGamma( mnC3, DEC_GAMMA ); + break; + } + } + + // store resulting RGB value in mnC1 + toRgb(); + mnC1 = lclRgbComponentsToRgb( mnC1, mnC2, mnC3 ); + } + else // if( meMode != COLOR_UNUSED ) + { + mnC1 = API_RGB_TRANSPARENT; + } + + meMode = bIsPh ? COLOR_PH : COLOR_FINAL; + if( meMode == COLOR_FINAL ) + maTransforms.clear(); + return mnC1; +} + +bool Color::hasTransparence() const +{ + return mnAlpha < MAX_PERCENT; +} + +sal_Int16 Color::getTransparence() const +{ + return static_cast< sal_Int16 >( (MAX_PERCENT - mnAlpha) / PER_PERCENT ); +} + +// private -------------------------------------------------------------------- + +void Color::setResolvedRgb( sal_Int32 nRgb ) const +{ + meMode = (nRgb < 0) ? COLOR_UNUSED : COLOR_RGB; + lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb ); +} + +void Color::toRgb() const +{ + switch( meMode ) + { + case COLOR_RGB: + // nothing to do + break; + case COLOR_CRGB: + meMode = COLOR_RGB; + mnC1 = lclCrgbCompToRgbComp( lclGamma( mnC1, INC_GAMMA ) ); + mnC2 = lclCrgbCompToRgbComp( lclGamma( mnC2, INC_GAMMA ) ); + mnC3 = lclCrgbCompToRgbComp( lclGamma( mnC3, INC_GAMMA ) ); + break; + case COLOR_HSL: + { + meMode = COLOR_RGB; + double fR = 0.0, fG = 0.0, fB = 0.0; + if( (mnC2 == 0) || (mnC3 == MAX_PERCENT) ) + { + fR = fG = fB = static_cast< double >( mnC3 ) / MAX_PERCENT; + } + else if( mnC3 > 0 ) + { + // base color from hue + double fHue = static_cast< double >( mnC1 ) / MAX_DEGREE * 6.0; // interval [0.0, 6.0) + if( fHue <= 1.0 ) { fR = 1.0; fG = fHue; } // red...yellow + else if( fHue <= 2.0 ) { fR = 2.0 - fHue; fG = 1.0; } // yellow...green + else if( fHue <= 3.0 ) { fG = 1.0; fB = fHue - 2.0; } // green...cyan + else if( fHue <= 4.0 ) { fG = 4.0 - fHue; fB = 1.0; } // cyan...blue + else if( fHue <= 5.0 ) { fR = fHue - 4.0; fB = 1.0; } // blue...magenta + else { fR = 1.0; fB = 6.0 - fHue; } // magenta...red + + // apply saturation + double fSat = static_cast< double >( mnC2 ) / MAX_PERCENT; + fR = (fR - 0.5) * fSat + 0.5; + fG = (fG - 0.5) * fSat + 0.5; + fB = (fB - 0.5) * fSat + 0.5; + + // apply luminance + double fLum = 2.0 * static_cast< double >( mnC3 ) / MAX_PERCENT - 1.0; // interval [-1.0, 1.0] + if( fLum < 0.0 ) + { + double fShade = fLum + 1.0; // interval [0.0, 1.0] (black...full color) + fR *= fShade; + fG *= fShade; + fB *= fShade; + } + else if( fLum > 0.0 ) + { + double fTint = 1.0 - fLum; // interval [0.0, 1.0] (white...full color) + fR = 1.0 - ((1.0 - fR) * fTint); + fG = 1.0 - ((1.0 - fG) * fTint); + fB = 1.0 - ((1.0 - fB) * fTint); + } + } + mnC1 = static_cast< sal_Int32 >( fR * 255.0 + 0.5 ); + mnC2 = static_cast< sal_Int32 >( fG * 255.0 + 0.5 ); + mnC3 = static_cast< sal_Int32 >( fB * 255.0 + 0.5 ); + } + break; + default: + OSL_ENSURE( false, "Color::toRgb - unexpected color mode" ); + } +} + +void Color::toCrgb() const +{ + switch( meMode ) + { + case COLOR_HSL: + toRgb(); + // run through! + case COLOR_RGB: + meMode = COLOR_CRGB; + mnC1 = lclGamma( lclRgbCompToCrgbComp( mnC1 ), DEC_GAMMA ); + mnC2 = lclGamma( lclRgbCompToCrgbComp( mnC2 ), DEC_GAMMA ); + mnC3 = lclGamma( lclRgbCompToCrgbComp( mnC3 ), DEC_GAMMA ); + break; + case COLOR_CRGB: + // nothing to do + break; + default: + OSL_ENSURE( false, "Color::toCrgb - unexpected color mode" ); + } +} + +void Color::toHsl() const +{ + switch( meMode ) + { + case COLOR_CRGB: + toRgb(); + // run through! + case COLOR_RGB: + { + meMode = COLOR_HSL; + double fR = static_cast< double >( mnC1 ) / 255.0; // red [0.0, 1.0] + double fG = static_cast< double >( mnC2 ) / 255.0; // green [0.0, 1.0] + double fB = static_cast< double >( mnC3 ) / 255.0; // blue [0.0, 1.0] + double fMin = ::std::min( ::std::min( fR, fG ), fB ); + double fMax = ::std::max( ::std::max( fR, fG ), fB ); + double fD = fMax - fMin; + + // hue: 0deg = red, 120deg = green, 240deg = blue + if( fD == 0.0 ) // black/gray/white + mnC1 = 0; + else if( fMax == fR ) // magenta...red...yellow + mnC1 = static_cast< sal_Int32 >( ((fG - fB) / fD * 60.0 + 360.0) * PER_DEGREE + 0.5 ) % MAX_DEGREE; + else if( fMax == fG ) // yellow...green...cyan + mnC1 = static_cast< sal_Int32 >( ((fB - fR) / fD * 60.0 + 120.0) * PER_DEGREE + 0.5 ); + else // cyan...blue...magenta + mnC1 = static_cast< sal_Int32 >( ((fR - fG) / fD * 60.0 + 240.0) * PER_DEGREE + 0.5 ); + + // luminance: 0% = black, 50% = full color, 100% = white + mnC3 = static_cast< sal_Int32 >( (fMin + fMax) / 2.0 * MAX_PERCENT + 0.5 ); + + // saturation: 0% = gray, 100% = full color + if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) // black/white + mnC2 = 0; + else if( mnC3 <= 50 * PER_PERCENT ) // dark...full color + mnC2 = static_cast< sal_Int32 >( fD / (fMin + fMax) * MAX_PERCENT + 0.5 ); + else // full color...light + mnC2 = static_cast< sal_Int32 >( fD / (2.0 - fMax - fMin) * MAX_PERCENT + 0.5 ); + } + break; + case COLOR_HSL: + // nothing to do + break; + default: + OSL_ENSURE( false, "Color::toHsl - unexpected color mode" ); + } +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/colorchoicecontext.cxx b/oox/source/drawingml/colorchoicecontext.cxx new file mode 100644 index 000000000000..a909f2f68d0c --- /dev/null +++ b/oox/source/drawingml/colorchoicecontext.cxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * 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/colorchoicecontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/color.hxx" + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::xml::sax::SAXException; +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::xml::sax::XFastContextHandler; +using ::oox::core::ContextHandler; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +ColorValueContext::ColorValueContext( ContextHandler& rParent, Color& rColor ) : + ContextHandler( rParent ), + mrColor( rColor ) +{ +} + +void ColorValueContext::startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) + throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( scrgbClr ): + mrColor.setScrgbClr( + aAttribs.getInteger( XML_r, 0 ), + aAttribs.getInteger( XML_g, 0 ), + aAttribs.getInteger( XML_b, 0 ) ); + break; + + case A_TOKEN( srgbClr ): + mrColor.setSrgbClr( aAttribs.getIntegerHex( XML_val, 0 ) ); + break; + + case A_TOKEN( hslClr ): + mrColor.setHslClr( + aAttribs.getInteger( XML_hue, 0 ), + aAttribs.getInteger( XML_sat, 0 ), + aAttribs.getInteger( XML_lum, 0 ) ); + break; + + case A_TOKEN( sysClr ): + mrColor.setSysClr( + aAttribs.getToken( XML_val, XML_TOKEN_INVALID ), + aAttribs.getIntegerHex( XML_lastClr, -1 ) ); + break; + + case A_TOKEN( schemeClr ): + mrColor.setSchemeClr( aAttribs.getToken( XML_val, XML_TOKEN_INVALID ) ); + break; + + case A_TOKEN( prstClr ): + mrColor.setPrstClr( aAttribs.getToken( XML_val, XML_TOKEN_INVALID ) ); + break; + } +} + +Reference< XFastContextHandler > ColorValueContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( alpha ): + case A_TOKEN( alphaMod ): + case A_TOKEN( alphaOff ): + case A_TOKEN( blue ): + case A_TOKEN( blueMod ): + case A_TOKEN( blueOff ): + case A_TOKEN( hue ): + case A_TOKEN( hueMod ): + case A_TOKEN( hueOff ): + case A_TOKEN( lum ): + case A_TOKEN( lumMod ): + case A_TOKEN( lumOff ): + case A_TOKEN( green ): + case A_TOKEN( greenMod ): + case A_TOKEN( greenOff ): + case A_TOKEN( red ): + case A_TOKEN( redMod ): + case A_TOKEN( redOff ): + case A_TOKEN( sat ): + case A_TOKEN( satMod ): + case A_TOKEN( satOff ): + case A_TOKEN( shade ): + case A_TOKEN( tint ): + mrColor.addTransformation( nElement, aAttribs.getInteger( XML_val, 0 ) ); + break; + case A_TOKEN( comp ): + case A_TOKEN( gamma ): + case A_TOKEN( gray ): + case A_TOKEN( inv ): + case A_TOKEN( invGamma ): + mrColor.addTransformation( nElement ); + break; + } + return 0; +} + +// ============================================================================ + +ColorContext::ColorContext( ContextHandler& rParent, Color& rColor ) : + ContextHandler( rParent ), + mrColor( rColor ) +{ +} + +Reference< XFastContextHandler > ColorContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( scrgbClr ): + case A_TOKEN( srgbClr ): + case A_TOKEN( hslClr ): + case A_TOKEN( sysClr ): + case A_TOKEN( schemeClr ): + case A_TOKEN( prstClr ): + return new ColorValueContext( *this, mrColor ); + } + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/connectorshapecontext.cxx b/oox/source/drawingml/connectorshapecontext.cxx new file mode 100644 index 000000000000..f2840a8d82fa --- /dev/null +++ b/oox/source/drawingml/connectorshapecontext.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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 <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> + +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +ConnectorShapeContext::ConnectorShapeContext( ContextHandler& rParent, + ShapePtr pMasterShapePtr, ShapePtr pGroupShapePtr ) +: ShapeContext( rParent, pMasterShapePtr, pGroupShapePtr ) +{ +} + +ConnectorShapeContext::~ConnectorShapeContext() +{ +} + +Reference< XFastContextHandler > ConnectorShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( getBaseToken( aElementToken ) ) + { + case XML_nvCxnSpPr : + break; + + default: + xRet = ShapeContext::createFastChildContext( aElementToken, xAttribs ); + } + if( !xRet.is() ) + xRet.set( this ); + + + return xRet; +} + +} } diff --git a/oox/source/drawingml/customshapegeometry.cxx b/oox/source/drawingml/customshapegeometry.cxx new file mode 100644 index 000000000000..d0c5c6a2dde2 --- /dev/null +++ b/oox/source/drawingml/customshapegeometry.cxx @@ -0,0 +1,2065 @@ +/************************************************************************* + * + * 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/customshapegeometry.hxx" + +#include <com/sun/star/xml/sax/FastToken.hpp> +#include <comphelper/stl_types.hxx> +#include <hash_map> +#include "oox/helper/helper.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertymap.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +enum FormularCommand +{ + FC_MULDIV = 0, + FC_PLUSMINUS, + FC_PLUSDIV, + FC_IFELSE, + FC_ABS, + FC_AT2, + FC_CAT2, + FC_COS, + FC_MAX, + FC_MIN, + FC_MOD, + FC_PIN, + FC_SAT2, + FC_SIN, + FC_SQRT, + FC_TAN, + FC_VAL, + FC_LAST +}; +struct FormularCommandNameTable +{ + const char* pS; + FormularCommand pE; +}; +static FormularCommandNameTable pFormularCommandNameTable[] = +{ + { "*/", FC_MULDIV }, + { "+-", FC_PLUSMINUS }, + { "+/", FC_PLUSDIV }, + { "ifelse", FC_IFELSE }, + { "abs", FC_ABS }, + { "at2", FC_AT2 }, + { "cat2", FC_CAT2 }, + { "cos", FC_COS }, + { "max", FC_MAX }, + { "min", FC_MIN }, + { "mod", FC_MOD }, + { "pin", FC_PIN }, + { "sat2", FC_SAT2 }, + { "sin", FC_SIN }, + { "sqrt", FC_SQRT }, + { "tan", FC_TAN }, + { "val", FC_VAL } + +}; +typedef std::hash_map< rtl::OUString, FormularCommand, comphelper::UStringHash, comphelper::UStringEqual > FormulaCommandHMap; + +static const FormulaCommandHMap* pCommandHashMap; + +// +rtl::OUString GetFormulaParameter( const EnhancedCustomShapeParameter& rParameter ) +{ + rtl::OUString aRet; + switch( rParameter.Type ) + { + case EnhancedCustomShapeParameterType::NORMAL : + { + if ( rParameter.Value.getValueTypeClass() == TypeClass_DOUBLE ) + { + double fValue = 0.0; + if ( rParameter.Value >>= fValue ) + aRet = rtl::OUString::valueOf( fValue ); + } + else + { + sal_Int32 nValue = 0; + if ( rParameter.Value >>= nValue ) + aRet = rtl::OUString::valueOf( nValue ); + } + } + break; + case EnhancedCustomShapeParameterType::EQUATION : + { + if ( rParameter.Value.getValueTypeClass() == TypeClass_LONG ) + { + sal_Int32 nFormulaIndex; + if ( rParameter.Value >>= nFormulaIndex ) + { + aRet = CREATE_OUSTRING( "?" ) + + rtl::OUString::valueOf( nFormulaIndex ) + + CREATE_OUSTRING( " " ); + } + } + else + { + // ups... we should have an index here and not the formula name + } + } + break; + case EnhancedCustomShapeParameterType::ADJUSTMENT : + { + if ( rParameter.Value.getValueTypeClass() == TypeClass_LONG ) + { + sal_Int32 nAdjustmentIndex; + if ( rParameter.Value >>= nAdjustmentIndex ) + { + aRet = CREATE_OUSTRING( "$" ) + + rtl::OUString::valueOf( nAdjustmentIndex ) + + CREATE_OUSTRING( " " ); + } + } + else + { + // ups... we should have an index here and not the formula name + } + } + break; + case EnhancedCustomShapeParameterType::LEFT : + { + const rtl::OUString sLeft( CREATE_OUSTRING( "left" ) ); + aRet = sLeft; + } + break; + case EnhancedCustomShapeParameterType::TOP : + { + const rtl::OUString sTop( CREATE_OUSTRING( "top" ) ); + aRet = sTop; + } + break; + case EnhancedCustomShapeParameterType::RIGHT : + { + const rtl::OUString sRight( CREATE_OUSTRING( "right" ) ); + aRet = sRight; + } + break; + case EnhancedCustomShapeParameterType::BOTTOM : + { + const rtl::OUString sBottom( CREATE_OUSTRING( "bottom" ) ); + aRet = sBottom; + } + break; + case EnhancedCustomShapeParameterType::XSTRETCH : + { + const rtl::OUString sXStretch( CREATE_OUSTRING( "xstretch" ) ); + aRet = sXStretch; + } + break; + case EnhancedCustomShapeParameterType::YSTRETCH : + { + const rtl::OUString sYStretch( CREATE_OUSTRING( "ystretch" ) ); + aRet = sYStretch; + } + break; + case EnhancedCustomShapeParameterType::HASSTROKE : + { + const rtl::OUString sHasStroke( CREATE_OUSTRING( "hasstroke" ) ); + aRet = sHasStroke; + } + break; + case EnhancedCustomShapeParameterType::HASFILL : + { + const rtl::OUString sHasFill( CREATE_OUSTRING( "hasfill" ) ); + aRet = sHasFill; + } + break; + case EnhancedCustomShapeParameterType::WIDTH : + { + const rtl::OUString sWidth( CREATE_OUSTRING( "width" ) ); + aRet = sWidth; + } + break; + case EnhancedCustomShapeParameterType::HEIGHT : + { + const rtl::OUString sHeight( CREATE_OUSTRING( "height" ) ); + aRet = sHeight; + } + break; + case EnhancedCustomShapeParameterType::LOGWIDTH : + { + const rtl::OUString sLogWidth( CREATE_OUSTRING( "logwidth" ) ); + aRet = sLogWidth; + } + break; + case EnhancedCustomShapeParameterType::LOGHEIGHT : + { + const rtl::OUString sLogHeight( CREATE_OUSTRING( "logheight" ) ); + aRet = sLogHeight; + } + break; + } + return aRet; +} + +// --------------------------------------------------------------------- + +static EnhancedCustomShapeParameter GetAdjCoordinate( CustomShapeProperties& rCustomShapeProperties, const::rtl::OUString& rValue, sal_Bool bNoSymbols ) +{ + com::sun::star::drawing::EnhancedCustomShapeParameter aRet; + if ( rValue.getLength() ) + { + sal_Bool bConstant = sal_True; + sal_Int32 nConstant = 0; + sal_Char nVal = 0; + + // first check if its a constant value + switch( AttributeConversion::decodeToken( rValue ) ) + { + case XML_3cd4 : nConstant = 270 * 60000; break; + case XML_3cd8 : nConstant = 135 * 60000; break; + case XML_5cd8 : nConstant = 225 * 60000; break; + case XML_7cd8 : nConstant = 315 * 60000; break; + case XML_cd2 : nConstant = 180 * 60000; break; + case XML_cd4 : nConstant = 90 * 60000; break; + case XML_cd8 : nConstant = 45 * 60000; break; + + case XML_b : // variable height of the shape defined in spPr + case XML_h : + { + if ( bNoSymbols ) + { + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "height" ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + else + aRet.Type = EnhancedCustomShapeParameterType::HEIGHT; // TODO: HEIGHT needs to be implemented + } + break; + + + case XML_hd8 : // !!PASSTHROUGH INTENDED + nVal += 2; // */ h 1.0 8.0 + case XML_hd6 : // */ h 1.0 6.0 + nVal++; + case XML_hd5 : // */ h 1.0 5.0 + nVal++; + case XML_hd4 : // */ h 1.0 4.0 + nVal += 2; + case XML_hd2 : // */ h 1.0 2.0 + case XML_vc : // */ h 1.0 2.0 + { + nVal += '2'; + + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "height/" ) + rtl::OUString( nVal ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + break; + + case XML_t : + case XML_l : + { + nConstant = 0; + aRet.Type = EnhancedCustomShapeParameterType::NORMAL; + } + break; + + case XML_ls : // longest side: max w h + { + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "max(width,height)" ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + break; + case XML_ss : // shortest side: min w h + { + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "min(width,height)" ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + break; + case XML_ssd8 : // */ ss 1.0 8.0 + nVal += 2; + case XML_ssd6 : // */ ss 1.0 6.0 + nVal += 2; + case XML_ssd4 : // */ ss 1.0 4.0 + nVal += 2; + case XML_ssd2 : // */ ss 1.0 2.0 + { + nVal += '2'; + + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "min(width,height)/" ) + rtl::OUString( nVal ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + break; + + case XML_r : // variable width of the shape defined in spPr + case XML_w : + { + if ( bNoSymbols ) + { + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "width" ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + else + aRet.Type = EnhancedCustomShapeParameterType::WIDTH; + } + break; + + case XML_wd10 : // */ w 1.0 10.0 + nVal += 2; + case XML_wd8 : // */ w 1.0 8.0 + nVal += 2; + case XML_wd6 : // */ w 1.0 6.0 + nVal++; + case XML_wd5 : // */ w 1.0 5.0 + nVal++; + case XML_wd4 : // */ w 1.0 4.0 + nVal += 2; + case XML_hc : // */ w 1.0 2.0 + case XML_wd2 : // */ w 1.0 2.0 + { + nVal += '2'; + + CustomShapeGuide aGuide; + aGuide.maName = rValue; + aGuide.maFormula = CREATE_OUSTRING( "width/" ) + rtl::OUString( nVal ); + + aRet.Value = Any( CustomShapeProperties::SetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), aGuide ) ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + break; + + default: + bConstant = sal_False; + break; + } + if ( bConstant ) + { + if ( nConstant ) + { + aRet.Value = Any( nConstant ); + aRet.Type = EnhancedCustomShapeParameterType::NORMAL; + } + } + else + { + sal_Unicode n = rValue[ 0 ]; + if ( ( n == '+' ) || ( n == '-' ) ) + { + if ( rValue.getLength() > 0 ) + n = rValue[ 1 ]; + } + if ( ( n >= '0' ) && ( n <= '9' ) ) + { // seems to be a ST_Coordinate + aRet.Value = Any( rValue.toInt32() ); + aRet.Type = EnhancedCustomShapeParameterType::NORMAL; + } + else + { + sal_Int32 nGuideIndex = CustomShapeProperties::GetCustomShapeGuideValue( rCustomShapeProperties.getAdjustmentGuideList(), rValue ); + if ( nGuideIndex >= 0 ) + { + aRet.Value = Any( nGuideIndex ); + aRet.Type = EnhancedCustomShapeParameterType::ADJUSTMENT; + } + else + { + nGuideIndex = CustomShapeProperties::GetCustomShapeGuideValue( rCustomShapeProperties.getGuideList(), rValue ); + if ( nGuideIndex >= 0 ) + { + aRet.Value = Any( nGuideIndex ); + aRet.Type = EnhancedCustomShapeParameterType::EQUATION; + } + else + aRet.Value = Any( rValue ); + } + } + } + } + return aRet; +} + +static EnhancedCustomShapeParameter GetAdjAngle( CustomShapeProperties& rCustomShapeProperties, const ::rtl::OUString& rValue ) +{ + EnhancedCustomShapeParameter aAngle( GetAdjCoordinate( rCustomShapeProperties, rValue, sal_True ) ); + if ( aAngle.Type == EnhancedCustomShapeParameterType::NORMAL ) + { + sal_Int32 nValue = 0; + aAngle.Value >>= nValue; + double fValue = ( static_cast< double >( nValue ) / 60000.0 ) * 360.0; + aAngle.Value <<= fValue; + } + return aAngle; +} + +// --------------------------------------------------------------------- +// CT_GeomGuideList +class GeomGuideListContext : public ContextHandler +{ +public: + GeomGuideListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< CustomShapeGuide >& rGuideList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + std::vector< CustomShapeGuide >& mrGuideList; + CustomShapeProperties& mrCustomShapeProperties; +}; + +GeomGuideListContext::GeomGuideListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< CustomShapeGuide >& rGuideList ) +: ContextHandler( rParent ) +, mrGuideList( rGuideList ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +static rtl::OUString convertToOOEquation( CustomShapeProperties& rCustomShapeProperties, const rtl::OUString& rSource ) +{ + if ( !pCommandHashMap ) + { + FormulaCommandHMap* pHM = new FormulaCommandHMap(); + for( sal_Int32 i = 0; i < FC_LAST; i++ ) + (*pHM)[ OUString::createFromAscii( pFormularCommandNameTable[ i ].pS ) ] = pFormularCommandNameTable[ i ].pE; + pCommandHashMap = pHM; + } + + std::vector< rtl::OUString > aTokens; + sal_Int32 nIndex = 0; + do + { + rtl::OUString aToken( rSource.getToken( 0, ' ', nIndex ) ); + if ( aToken.getLength() ) + aTokens.push_back( aToken ); + } + while ( nIndex >= 0 ); + + rtl::OUString aEquation; + if ( aTokens.size() ) + { + sal_Int32 i, nParameters = aTokens.size() - 1; + if ( nParameters > 3 ) + nParameters = 3; + + rtl::OUString sParameters[ 3 ]; + + for ( i = 0; i < nParameters; i++ ) + sParameters[ i ] = GetFormulaParameter( GetAdjCoordinate( rCustomShapeProperties, aTokens[ i + 1 ], sal_False ) ); + + const FormulaCommandHMap::const_iterator aIter( pCommandHashMap->find( aTokens[ 0 ] ) ); + if ( aIter != pCommandHashMap->end() ) + { + switch( aIter->second ) + { + case FC_MULDIV : + { + if ( nParameters == 3 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*" ) + sParameters[ 1 ] + + CREATE_OUSTRING( "/" ) + sParameters[ 2 ]; + } + break; + case FC_PLUSMINUS : + { + if ( nParameters == 3 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "+" ) + sParameters[ 1 ] + + CREATE_OUSTRING( "-" ) + sParameters[ 2 ]; + } + break; + case FC_PLUSDIV : + { + if ( nParameters == 3 ) + aEquation = CREATE_OUSTRING( "(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "+" ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")/" ) + sParameters[ 2 ]; + } + break; + case FC_IFELSE : + { + if ( nParameters == 3 ) + aEquation = CREATE_OUSTRING( "if(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "," ) + + sParameters[ 1 ] + CREATE_OUSTRING( "," ) + sParameters[ 2 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_ABS : + { + if ( nParameters == 1 ) + aEquation = CREATE_OUSTRING( "abs(" ) + sParameters[ 0 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_AT2 : + { + if ( nParameters == 2 ) + aEquation = CREATE_OUSTRING( "atan2(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "," ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_CAT2 : + { + if ( nParameters == 3 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*(cos(arctan(" ) + + sParameters[ 1 ] + CREATE_OUSTRING( "," ) + sParameters[ 2 ] + CREATE_OUSTRING( ")))" ); + } + break; + case FC_COS : + { + if ( nParameters == 2 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*cos(" ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_MAX : + { + if ( nParameters == 2 ) + aEquation = CREATE_OUSTRING( "max(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "," ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_MIN : + { + if ( nParameters == 2 ) + aEquation = CREATE_OUSTRING( "min(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "," ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_MOD : + { + if ( nParameters == 3 ) + aEquation = CREATE_OUSTRING( "sqrt(" ) + + sParameters[ 0 ] + CREATE_OUSTRING( "*" ) + sParameters[ 0 ] + CREATE_OUSTRING( "+" ) + + sParameters[ 1 ] + CREATE_OUSTRING( "*" ) + sParameters[ 1 ] + CREATE_OUSTRING( "+" ) + + sParameters[ 2 ] + CREATE_OUSTRING( "*" ) + sParameters[ 2 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_PIN : + { + if ( nParameters == 3 ) // if(x-y,x,if(y-z,z,y)) + aEquation = CREATE_OUSTRING( "if(" ) + sParameters[ 0 ] + CREATE_OUSTRING( "-" ) + sParameters[ 1 ] + + CREATE_OUSTRING( "," ) + sParameters[ 0 ] + CREATE_OUSTRING( ",if(" ) + sParameters[ 2 ] + + CREATE_OUSTRING( "-" ) + sParameters[ 1 ] + CREATE_OUSTRING( "," ) + sParameters[ 1 ] + + CREATE_OUSTRING( "," ) + sParameters[ 2 ] + CREATE_OUSTRING( "))" ); + } + break; + case FC_SAT2 : + { + if ( nParameters == 3 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*(sin(arctan(" ) + + sParameters[ 1 ] + CREATE_OUSTRING( "," ) + sParameters[ 2 ] + CREATE_OUSTRING( ")))" ); + } + break; + case FC_SIN : + { + if ( nParameters == 2 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*sin(" ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_SQRT : + { + if ( nParameters == 1 ) + aEquation = CREATE_OUSTRING( "sqrt(" ) + sParameters[ 0 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_TAN : + { + if ( nParameters == 2 ) + aEquation = sParameters[ 0 ] + CREATE_OUSTRING( "*tan(" ) + + sParameters[ 1 ] + CREATE_OUSTRING( ")" ); + } + break; + case FC_VAL : + { + if ( nParameters == 1 ) + aEquation = sParameters[ 0 ]; + } + break; + default : + break; + } + } + } + return aEquation; +} + +Reference< XFastContextHandler > GeomGuideListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + if ( aElementToken == A_TOKEN( gd ) ) // CT_GeomGuide + { + CustomShapeGuide aGuide; + aGuide.maName = xAttribs->getOptionalValue( XML_name ); + aGuide.maFormula = convertToOOEquation( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_fmla ) ); + mrGuideList.push_back( aGuide ); + } + return this; +} + +// --------------------------------------------------------------------- + +static const rtl::OUString GetGeomGuideName( const ::rtl::OUString& rValue ) +{ + return rValue; +} + +// --------------------------------------------------------------------- +// CT_AdjPoint2D +class AdjPoint2DContext : public ContextHandler +{ +public: + AdjPoint2DContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ); +}; + +AdjPoint2DContext::AdjPoint2DContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ) +: ContextHandler( rParent ) +{ + rAdjPoint2D.First = GetAdjCoordinate( rCustomShapeProperties, xAttribs->getOptionalValue( XML_x ), sal_True ); + rAdjPoint2D.Second = GetAdjCoordinate( rCustomShapeProperties, xAttribs->getOptionalValue( XML_y ), sal_True ); +} + +// --------------------------------------------------------------------- +// CT_XYAdjustHandle +class XYAdjustHandleContext : public ContextHandler +{ +public: + XYAdjustHandleContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + AdjustHandle& mrAdjustHandle; + CustomShapeProperties& mrCustomShapeProperties; +}; + +XYAdjustHandleContext::XYAdjustHandleContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle ) +: ContextHandler( rParent ) +, mrAdjustHandle( rAdjustHandle ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + const rtl::OUString aEmptyDefault; + AttributeList aAttribs( xAttribs ); + if ( aAttribs.hasAttribute( XML_gdRefX ) ) + { + mrAdjustHandle.gdRef1 = GetGeomGuideName( aAttribs.getString( XML_gdRefX, aEmptyDefault ) ); + } + if ( aAttribs.hasAttribute( XML_minX ) ) + { + mrAdjustHandle.min1 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_minX, aEmptyDefault ), sal_True ); + } + if ( aAttribs.hasAttribute( XML_maxX ) ) + { + mrAdjustHandle.max1 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_maxX, aEmptyDefault ), sal_True ); + } + if ( aAttribs.hasAttribute( XML_gdRefY ) ) + { + mrAdjustHandle.gdRef2 = GetGeomGuideName( aAttribs.getString( XML_gdRefY, aEmptyDefault ) ); + } + if ( aAttribs.hasAttribute( XML_minY ) ) + { + mrAdjustHandle.min2 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_minY, aEmptyDefault ), sal_True ); + } + if ( aAttribs.hasAttribute( XML_maxY ) ) + { + mrAdjustHandle.max2 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_maxY, aEmptyDefault ), sal_True ); + } +} + +Reference< XFastContextHandler > XYAdjustHandleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pos ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, mrAdjustHandle.pos ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_PolarAdjustHandle +class PolarAdjustHandleContext : public ContextHandler +{ +public: + PolarAdjustHandleContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + AdjustHandle& mrAdjustHandle; + CustomShapeProperties& mrCustomShapeProperties; +}; + +PolarAdjustHandleContext::PolarAdjustHandleContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, AdjustHandle& rAdjustHandle ) +: ContextHandler( rParent ) +, mrAdjustHandle( rAdjustHandle ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + const rtl::OUString aEmptyDefault; + AttributeList aAttribs( xAttribs ); + if ( aAttribs.hasAttribute( XML_gdRefR ) ) + { + mrAdjustHandle.gdRef1 = GetGeomGuideName( aAttribs.getString( XML_gdRefR, aEmptyDefault ) ); + } + if ( aAttribs.hasAttribute( XML_minR ) ) + { + mrAdjustHandle.min1 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_minR, aEmptyDefault ), sal_True ); + } + if ( aAttribs.hasAttribute( XML_maxR ) ) + { + mrAdjustHandle.max1 = GetAdjCoordinate( mrCustomShapeProperties, aAttribs.getString( XML_maxR, aEmptyDefault ), sal_True ); + } + if ( aAttribs.hasAttribute( XML_gdRefAng ) ) + { + mrAdjustHandle.gdRef2 = GetGeomGuideName( aAttribs.getString( XML_gdRefAng, aEmptyDefault ) ); + } + if ( aAttribs.hasAttribute( XML_minAng ) ) + { + mrAdjustHandle.min2 = GetAdjAngle( mrCustomShapeProperties, aAttribs.getString( XML_minAng, aEmptyDefault ) ); + } + if ( aAttribs.hasAttribute( XML_maxAng ) ) + { + mrAdjustHandle.max2 = GetAdjAngle( mrCustomShapeProperties, aAttribs.getString( XML_maxAng, aEmptyDefault ) ); + } +} + +Reference< XFastContextHandler > PolarAdjustHandleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pos ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, mrAdjustHandle.pos ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_AdjustHandleList +class AdjustHandleListContext : public ContextHandler +{ +public: + AdjustHandleListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< AdjustHandle >& rAdjustHandleList ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + std::vector< AdjustHandle >& mrAdjustHandleList; + CustomShapeProperties& mrCustomShapeProperties; +}; + +AdjustHandleListContext::AdjustHandleListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< AdjustHandle >& rAdjustHandleList ) +: ContextHandler( rParent ) +, mrAdjustHandleList( rAdjustHandleList ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > AdjustHandleListContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( ahXY ) ) // CT_XYAdjustHandle + { + AdjustHandle aAdjustHandle( sal_False ); + mrAdjustHandleList.push_back( aAdjustHandle ); + xContext = new XYAdjustHandleContext( *this, xAttribs, mrCustomShapeProperties, mrAdjustHandleList.back() ); + } + else if ( aElementToken == A_TOKEN( ahPolar ) ) // CT_PolarAdjustHandle + { + AdjustHandle aAdjustHandle( sal_True ); + mrAdjustHandleList.push_back( aAdjustHandle ); + xContext = new PolarAdjustHandleContext( *this, xAttribs, mrCustomShapeProperties, mrAdjustHandleList.back() ); + } + return xContext; +} + +// --------------------------------------------------------------------- +// CT_ConnectionSite +class ConnectionSiteContext : public ContextHandler +{ +public: + ConnectionSiteContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, ConnectionSite& rConnectionSite ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + ConnectionSite& mrConnectionSite; + CustomShapeProperties& mrCustomShapeProperties; +}; + +ConnectionSiteContext::ConnectionSiteContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, ConnectionSite& rConnectionSite ) +: ContextHandler( rParent ) +, mrConnectionSite( rConnectionSite ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + mrConnectionSite.ang = GetAdjAngle( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_ang ) ); +} + +Reference< XFastContextHandler > ConnectionSiteContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pos ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, mrConnectionSite.pos ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DMoveTo +class Path2DMoveToContext : public ContextHandler +{ +public: + Path2DMoveToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + EnhancedCustomShapeParameterPair& mrAdjPoint2D; + CustomShapeProperties& mrCustomShapeProperties; +}; + +Path2DMoveToContext::Path2DMoveToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ) +: ContextHandler( rParent ) +, mrAdjPoint2D( rAdjPoint2D ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > Path2DMoveToContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pt ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, mrAdjPoint2D ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DLineTo +class Path2DLineToContext : public ContextHandler +{ +public: + Path2DLineToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + EnhancedCustomShapeParameterPair& mrAdjPoint2D; + CustomShapeProperties& mrCustomShapeProperties; +}; + +Path2DLineToContext::Path2DLineToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rAdjPoint2D ) +: ContextHandler( rParent ) +, mrAdjPoint2D( rAdjPoint2D ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > Path2DLineToContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pt ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, mrAdjPoint2D ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DQuadBezierTo +class Path2DQuadBezierToContext : public ContextHandler +{ +public: + Path2DQuadBezierToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, EnhancedCustomShapeParameterPair& rPt1, EnhancedCustomShapeParameterPair& rPt2 ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + EnhancedCustomShapeParameterPair& mrPt1; + EnhancedCustomShapeParameterPair& mrPt2; + int nCount; + CustomShapeProperties& mrCustomShapeProperties; +}; + +Path2DQuadBezierToContext::Path2DQuadBezierToContext( ContextHandler& rParent, + CustomShapeProperties& rCustomShapeProperties, + EnhancedCustomShapeParameterPair& rPt1, + EnhancedCustomShapeParameterPair& rPt2 ) +: ContextHandler( rParent ) +, mrPt1( rPt1 ) +, mrPt2( rPt2 ) +, nCount( 0 ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > Path2DQuadBezierToContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pt ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, nCount++ ? mrPt2 : mrPt1 ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DCubicBezierTo +class Path2DCubicBezierToContext : public ContextHandler +{ +public: + Path2DCubicBezierToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, + EnhancedCustomShapeParameterPair&, EnhancedCustomShapeParameterPair&, EnhancedCustomShapeParameterPair& ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + CustomShapeProperties& mrCustomShapeProperties; + EnhancedCustomShapeParameterPair& mrControlPt1; + EnhancedCustomShapeParameterPair& mrControlPt2; + EnhancedCustomShapeParameterPair& mrEndPt; + int nCount; +}; + +Path2DCubicBezierToContext::Path2DCubicBezierToContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, + EnhancedCustomShapeParameterPair& rControlPt1, + EnhancedCustomShapeParameterPair& rControlPt2, + EnhancedCustomShapeParameterPair& rEndPt ) +: ContextHandler( rParent ) +, mrCustomShapeProperties( rCustomShapeProperties ) +, mrControlPt1( rControlPt1 ) +, mrControlPt2( rControlPt2 ) +, mrEndPt( rEndPt ) +, nCount( 0 ) +{ +} + +Reference< XFastContextHandler > Path2DCubicBezierToContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( pt ) ) + xContext = new AdjPoint2DContext( *this, xAttribs, mrCustomShapeProperties, + nCount++ ? nCount == 2 ? mrControlPt2 : mrEndPt : mrControlPt1 ); // CT_AdjPoint2D + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DContext +class Path2DContext : public ContextHandler +{ +public: + Path2DContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >& rSegments, Path2D& rPath2D ); + virtual ~Path2DContext(); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) + throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + Path2D& mrPath2D; + std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >& mrSegments; + CustomShapeProperties& mrCustomShapeProperties; +}; + +Path2DContext::Path2DContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties, std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >& rSegments, Path2D& rPath2D ) +: ContextHandler( rParent ) +, mrPath2D( rPath2D ) +, mrSegments( rSegments ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + const rtl::OUString aEmptyString; + + AttributeList aAttribs( xAttribs ); + rPath2D.w = aAttribs.getString( XML_w, aEmptyString ).toInt64(); + rPath2D.h = aAttribs.getString( XML_h, aEmptyString ).toInt64(); + rPath2D.fill = aAttribs.getToken( XML_fill, XML_norm ); + rPath2D.stroke = aAttribs.getBool( XML_stroke, sal_True ); + rPath2D.extrusionOk = aAttribs.getBool( XML_extrusionOk, sal_True ); +} + +Path2DContext::~Path2DContext() +{ + EnhancedCustomShapeSegment aNewSegment; + if ( mrPath2D.fill == XML_none ) + { + aNewSegment.Command = EnhancedCustomShapeSegmentCommand::NOFILL; + aNewSegment.Count = 0; + mrSegments.push_back( aNewSegment ); + } + aNewSegment.Command = EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + aNewSegment.Count = 0; + mrSegments.push_back( aNewSegment ); +} + +Reference< XFastContextHandler > Path2DContext::createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xContext; + switch( aElementToken ) + { + case A_TOKEN( close ) : + { + EnhancedCustomShapeSegment aNewSegment; + aNewSegment.Command = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; + aNewSegment.Count = 0; + mrSegments.push_back( aNewSegment ); + } + break; + case A_TOKEN( moveTo ) : + { + EnhancedCustomShapeSegment aNewSegment; + aNewSegment.Command = EnhancedCustomShapeSegmentCommand::MOVETO; + aNewSegment.Count = 1; + mrSegments.push_back( aNewSegment ); + + EnhancedCustomShapeParameterPair aAdjPoint2D; + mrPath2D.parameter.push_back( aAdjPoint2D ); + xContext = new Path2DMoveToContext( *this, mrCustomShapeProperties, mrPath2D.parameter.back() ); + } + break; + case A_TOKEN( lnTo ) : + { + + if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::LINETO ) ) + mrSegments.back().Count++; + else + { + EnhancedCustomShapeSegment aSegment; + aSegment.Command = EnhancedCustomShapeSegmentCommand::LINETO; + aSegment.Count = 1; + mrSegments.push_back( aSegment ); + } + EnhancedCustomShapeParameterPair aAdjPoint2D; + mrPath2D.parameter.push_back( aAdjPoint2D ); + xContext = new Path2DLineToContext( *this, mrCustomShapeProperties, mrPath2D.parameter.back() ); + } + break; + case A_TOKEN( arcTo ) : // CT_Path2DArcTo + { + if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::ARCTO ) ) + mrSegments.back().Count++; + else + { + EnhancedCustomShapeSegment aSegment; + aSegment.Command = EnhancedCustomShapeSegmentCommand::ARCTO; + aSegment.Count = 1; + mrSegments.push_back( aSegment ); + } + EnhancedCustomShapeParameter aWidth = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_wR ), sal_True ); + EnhancedCustomShapeParameter aHeight = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_hR ), sal_True ); + EnhancedCustomShapeParameter aStartAngle = GetAdjAngle( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_stAng ) ); + EnhancedCustomShapeParameter swAngle = GetAdjAngle( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_swAng ) ); + + EnhancedCustomShapeParameterPair aPt1; // TODO: conversion from (wr hr stAng swAng) + EnhancedCustomShapeParameterPair aPt2; // to (x1 y1 x2 y2 x3 y3 x y) needed + EnhancedCustomShapeParameterPair aPt3; + EnhancedCustomShapeParameterPair aPt; + mrPath2D.parameter.push_back( aPt1 ); + mrPath2D.parameter.push_back( aPt2 ); + mrPath2D.parameter.push_back( aPt3 ); + mrPath2D.parameter.push_back( aPt ); + } + break; + case A_TOKEN( quadBezTo ) : + { + if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO ) ) + mrSegments.back().Count++; + else + { + EnhancedCustomShapeSegment aSegment; + aSegment.Command = EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO; + aSegment.Count = 1; + mrSegments.push_back( aSegment ); + } + EnhancedCustomShapeParameterPair aPt1; + EnhancedCustomShapeParameterPair aPt2; + mrPath2D.parameter.push_back( aPt1 ); + mrPath2D.parameter.push_back( aPt2 ); + xContext = new Path2DQuadBezierToContext( *this, mrCustomShapeProperties, + mrPath2D.parameter[ mrPath2D.parameter.size() - 2 ], + mrPath2D.parameter.back() ); + } + break; + case A_TOKEN( cubicBezTo ) : + { + if ( !mrSegments.empty() && ( mrSegments.back().Command == EnhancedCustomShapeSegmentCommand::CURVETO ) ) + mrSegments.back().Count++; + else + { + EnhancedCustomShapeSegment aSegment; + aSegment.Command = EnhancedCustomShapeSegmentCommand::CURVETO; + aSegment.Count = 1; + mrSegments.push_back( aSegment ); + } + EnhancedCustomShapeParameterPair aControlPt1; + EnhancedCustomShapeParameterPair aControlPt2; + EnhancedCustomShapeParameterPair aEndPt; + mrPath2D.parameter.push_back( aControlPt1 ); + mrPath2D.parameter.push_back( aControlPt2 ); + mrPath2D.parameter.push_back( aEndPt ); + xContext = new Path2DCubicBezierToContext( *this, mrCustomShapeProperties, + mrPath2D.parameter[ mrPath2D.parameter.size() - 3 ], + mrPath2D.parameter[ mrPath2D.parameter.size() - 2 ], + mrPath2D.parameter.back() ); + } + break; + } + return xContext; +} + +// --------------------------------------------------------------------- +// CT_Path2DList +class Path2DListContext : public ContextHandler +{ +public: + Path2DListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< EnhancedCustomShapeSegment >& rSegments, + std::vector< Path2D >& rPath2DList ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + + CustomShapeProperties& mrCustomShapeProperties; + std::vector< com::sun::star::drawing::EnhancedCustomShapeSegment >& mrSegments; + std::vector< Path2D >& mrPath2DList; +}; + +Path2DListContext::Path2DListContext( ContextHandler& rParent, CustomShapeProperties& rCustomShapeProperties, std::vector< EnhancedCustomShapeSegment >& rSegments, + std::vector< Path2D >& rPath2DList ) +: ContextHandler( rParent ) +, mrCustomShapeProperties( rCustomShapeProperties ) +, mrSegments( rSegments ) +, mrPath2DList( rPath2DList ) +{ +} + +::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL Path2DListContext::createFastChildContext( sal_Int32 aElementToken, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException) +{ + Reference< XFastContextHandler > xContext; + if ( aElementToken == A_TOKEN( path ) ) + { + Path2D aPath2D; + mrPath2DList.push_back( aPath2D ); + xContext = new Path2DContext( *this, xAttribs, mrCustomShapeProperties, mrSegments, mrPath2DList.back() ); + } + return xContext; +} + +// --------------------------------------------------------------------- + +OUString GetShapeType( sal_Int32 nType ) +{ + OUString sType; + switch( nType ) + { + case XML_lineInv: // TODO + case XML_line: { + static const OUString sLine = CREATE_OUSTRING( "mso-spt20" ); + sType = sLine; + } break; + case XML_triangle: { + static const OUString sTriangle = CREATE_OUSTRING( "isosceles-triangle" ); + sType = sTriangle; + } break; + case XML_rtTriangle: { + static const OUString sRtTriangle = CREATE_OUSTRING( "right-triangle" ); + sType = sRtTriangle; + } break; + case XML_rect: { + static const OUString sRectangle = CREATE_OUSTRING( "rectangle" ); + sType = sRectangle; + } break; + case XML_diamond: { + static const OUString sDiamond = CREATE_OUSTRING( "diamond" ); + sType = sDiamond; + } break; + case XML_parallelogram: { + static const OUString sParallelogram = CREATE_OUSTRING( "parallelogram" ); + sType = sParallelogram; + } break; + case XML_nonIsoscelesTrapezoid: // TODO + case XML_trapezoid: { + static const OUString sTrapezoid = CREATE_OUSTRING( "trapezoid" ); + sType = sTrapezoid; + } break; + case XML_pentagon: { + static const OUString sPentagon = CREATE_OUSTRING( "pentagon" ); + sType = sPentagon; + } break; + case XML_heptagon: // TODO + case XML_hexagon: { + static const OUString sHexagon = CREATE_OUSTRING( "hexagon" ); + sType = sHexagon; + } break; + case XML_decagon: // TODO + case XML_dodecagon: // TODO + case XML_octagon: { + static const OUString sOctagon = CREATE_OUSTRING( "octagon" ); + sType = sOctagon; + } break; + case XML_star4: { + static const OUString sStar4 = CREATE_OUSTRING( "star4" ); + sType = sStar4; + } break; + case XML_star6: // TODO + case XML_star7: // TODO + case XML_star5: { + static const OUString sStar5 = CREATE_OUSTRING( "star5" ); + sType = sStar5; + } break; + case XML_star10: // TODO + case XML_star12: // TODO + case XML_star16: // TODO + case XML_star8: { + static const OUString sStar8 = CREATE_OUSTRING( "star8" ); + sType = sStar8; + } break; + case XML_star32: // TODO + case XML_star24: { + static const OUString sStar24 = CREATE_OUSTRING( "star24" ); + sType = sStar24; + } break; + case XML_round1Rect: // TODO + case XML_round2SameRect: // TODO + case XML_round2DiagRect: // TODO + case XML_snipRoundRect: // TODO + case XML_snip1Rect: // TODO + case XML_snip2SameRect: // TODO + case XML_snip2DiagRect: // TODO + case XML_roundRect: { + static const OUString sRoundRect = CREATE_OUSTRING( "round-rectangle" ); + sType = sRoundRect; + } break; + case XML_plaque: { + static const OUString sPlaque = CREATE_OUSTRING( "mso-spt21" ); + sType = sPlaque; + } break; + case XML_teardrop: // TODO + case XML_ellipse: { + static const OUString sEllipse = CREATE_OUSTRING( "ellipse" ); + sType = sEllipse; + } break; + case XML_homePlate: { + static const OUString sHomePlate = CREATE_OUSTRING( "pentagon-right" ); + sType = sHomePlate; + } break; + case XML_chevron: { + static const OUString sChevron = CREATE_OUSTRING( "chevron" ); + sType = sChevron; + } break; + case XML_pieWedge: // TODO + case XML_pie: // TODO + case XML_blockArc: { + static const OUString sBlockArc = CREATE_OUSTRING( "block-arc" ); + sType = sBlockArc; + } break; + case XML_donut: { + static const OUString sDonut = CREATE_OUSTRING( "ring" ); + sType = sDonut; + } break; + case XML_noSmoking: { + static const OUString sNoSmoking = CREATE_OUSTRING( "forbidden" ); + sType = sNoSmoking; + } break; + case XML_rightArrow: { + static const OUString sRightArrow = CREATE_OUSTRING( "right-arrow" ); + sType = sRightArrow; + } break; + case XML_leftArrow: { + static const OUString sLeftArrow = CREATE_OUSTRING( "left-arrow" ); + sType = sLeftArrow; + } break; + case XML_upArrow: { + static const OUString sUpArrow = CREATE_OUSTRING( "up-arrow" ); + sType = sUpArrow; + } break; + case XML_downArrow: { + static const OUString sDownArrow = CREATE_OUSTRING( "down-arrow" ); + sType = sDownArrow; + } break; + case XML_stripedRightArrow: { + static const OUString sStripedRightArrow = CREATE_OUSTRING( "striped-right-arrow" ); + sType = sStripedRightArrow; + } break; + case XML_notchedRightArrow: { + static const OUString sNotchedRightArrow = CREATE_OUSTRING( "notched-right-arrow" ); + sType = sNotchedRightArrow; + } break; + case XML_bentUpArrow: { + static const OUString sBentUpArrow = CREATE_OUSTRING( "mso-spt90" ); + sType = sBentUpArrow; + } break; + case XML_leftRightArrow: { + static const OUString sLeftRightArrow = CREATE_OUSTRING( "left-right-arrow" ); + sType = sLeftRightArrow; + } break; + case XML_upDownArrow: { + static const OUString sUpDownArrow = CREATE_OUSTRING( "up-down-arrow" ); + sType = sUpDownArrow; + } break; + case XML_leftUpArrow: { + static const OUString sLeftUpArrow = CREATE_OUSTRING( "mso-spt89" ); + sType = sLeftUpArrow; + } break; + case XML_leftRightUpArrow: { + static const OUString sLeftRightUpArrow = CREATE_OUSTRING( "mso-spt182" ); + sType = sLeftRightUpArrow; + } break; + case XML_quadArrow: { + static const OUString sQuadArrow = CREATE_OUSTRING( "quad-arrow" ); + sType = sQuadArrow; + } break; + case XML_leftArrowCallout: { + static const OUString sLeftArrowCallout = CREATE_OUSTRING( "left-arrow-callout" ); + sType = sLeftArrowCallout; + } break; + case XML_rightArrowCallout: { + static const OUString sRightArrowCallout = CREATE_OUSTRING( "right-arrow-callout" ); + sType = sRightArrowCallout; + } break; + case XML_upArrowCallout: { + static const OUString sUpArrowCallout = CREATE_OUSTRING( "up-arrow-callout" ); + sType = sUpArrowCallout; + } break; + case XML_downArrowCallout: { + static const OUString sDownArrowCallout = CREATE_OUSTRING( "down-arrow-callout" ); + sType = sDownArrowCallout; + } break; + case XML_leftRightArrowCallout: { + static const OUString sLeftRightArrowCallout = CREATE_OUSTRING( "left-right-arrow-callout" ); + sType = sLeftRightArrowCallout; + } break; + case XML_upDownArrowCallout: { + static const OUString sUpDownArrowCallout = CREATE_OUSTRING( "up-down-arrow-callout" ); + sType = sUpDownArrowCallout; + } break; + case XML_quadArrowCallout: { + static const OUString sQuadArrowCallout = CREATE_OUSTRING( "quad-arrow-callout" ); + sType = sQuadArrowCallout; + } break; + case XML_bentArrow: { + static const OUString sBentArrow = CREATE_OUSTRING( "mso-spt91" ); + sType = sBentArrow; + } break; + case XML_uturnArrow: { + static const OUString sUTurnArrow = CREATE_OUSTRING( "mso-spt101" ); + sType = sUTurnArrow; + } break; + case XML_leftCircularArrow: // TODO + case XML_leftRightCircularArrow: // TODO + case XML_circularArrow: { + static const OUString sCircularArrow = CREATE_OUSTRING( "circular-arrow" ); + sType = sCircularArrow; + } break; + case XML_curvedRightArrow: { + static const OUString sCurvedRightArrow = CREATE_OUSTRING( "mso-spt102" ); + sType = sCurvedRightArrow; + } break; + case XML_curvedLeftArrow: { + static const OUString sCurvedLeftArrow = CREATE_OUSTRING( "mso-spt103" ); + sType = sCurvedLeftArrow; + } break; + case XML_curvedUpArrow: { + static const OUString sCurvedUpArrow = CREATE_OUSTRING( "mso-spt104" ); + sType = sCurvedUpArrow; + } break; + case XML_swooshArrow: // TODO + case XML_curvedDownArrow: { + static const OUString sCurvedDownArrow = CREATE_OUSTRING( "mso-spt105" ); + sType = sCurvedDownArrow; + } break; + case XML_cube: { + static const OUString sCube = CREATE_OUSTRING( "cube" ); + sType = sCube; + } break; + case XML_can: { + static const OUString sCan = CREATE_OUSTRING( "can" ); + sType = sCan; + } break; + case XML_lightningBolt: { + static const OUString sLightningBolt = CREATE_OUSTRING( "lightning" ); + sType = sLightningBolt; + } break; + case XML_heart: { + static const OUString sHeart = CREATE_OUSTRING( "heart" ); + sType = sHeart; + } break; + case XML_sun: { + static const OUString sSun = CREATE_OUSTRING( "sun" ); + sType = sSun; + } break; + case XML_moon: { + static const OUString sMoon = CREATE_OUSTRING( "moon" ); + sType = sMoon; + } break; + case XML_smileyFace: { + static const OUString sSmileyFace = CREATE_OUSTRING( "smiley" ); + sType = sSmileyFace; + } break; + case XML_irregularSeal1: { + static const OUString sIrregularSeal1 = CREATE_OUSTRING( "mso-spt71" ); + sType = sIrregularSeal1; + } break; + case XML_irregularSeal2: { + static const OUString sIrregularSeal2 = CREATE_OUSTRING( "bang" ); + sType = sIrregularSeal2; + } break; + case XML_foldedCorner: { + static const OUString sFoldedCorner = CREATE_OUSTRING( "paper" ); + sType = sFoldedCorner; + } break; + case XML_bevel: { + static const OUString sBevel = CREATE_OUSTRING( "quad-bevel" ); + sType = sBevel; + } break; + case XML_halfFrame: // TODO + case XML_corner: // TODO + case XML_diagStripe: // TODO + case XML_chord: // TODO + case XML_frame: { + static const OUString sFrame = CREATE_OUSTRING( "mso-spt75" ); + sType = sFrame; + } break; + case XML_arc: { + static const OUString sArc = CREATE_OUSTRING( "mso-spt19" ); + sType = sArc; + } break; + case XML_leftBracket: { + static const OUString sLeftBracket = CREATE_OUSTRING( "left-bracket" ); + sType = sLeftBracket; + } break; + case XML_rightBracket: { + static const OUString sRightBracket = CREATE_OUSTRING( "right-bracket" ); + sType = sRightBracket; + } break; + case XML_leftBrace: { + static const OUString sLeftBrace = CREATE_OUSTRING( "left-brace" ); + sType = sLeftBrace; + } break; + case XML_rightBrace: { + static const OUString sRightBrace = CREATE_OUSTRING( "right-brace" ); + sType = sRightBrace; + } break; + case XML_bracketPair: { + static const OUString sBracketPair = CREATE_OUSTRING( "bracket-pair" ); + sType = sBracketPair; + } break; + case XML_bracePair: { + static const OUString sBracePair = CREATE_OUSTRING( "brace-pair" ); + sType = sBracePair; + } break; + case XML_straightConnector1: { + static const OUString sStraightConnector1 = CREATE_OUSTRING( "mso-spt32" ); + sType = sStraightConnector1; + } break; + case XML_bentConnector2: { + static const OUString sBentConnector2 = CREATE_OUSTRING( "mso-spt33" ); + sType = sBentConnector2; + } break; + case XML_bentConnector3: { + static const OUString sBentConnector3 = CREATE_OUSTRING( "mso-spt34" ); + sType = sBentConnector3; + } break; + case XML_bentConnector4: { + static const OUString sBentConnector4 = CREATE_OUSTRING( "mso-spt35" ); + sType = sBentConnector4; + } break; + case XML_bentConnector5: { + static const OUString sBentConnector5 = CREATE_OUSTRING( "mso-spt36" ); + sType = sBentConnector5; + } break; + case XML_curvedConnector2: { + static const OUString sCurvedConnector2 = CREATE_OUSTRING( "mso-spt37" ); + sType = sCurvedConnector2; + } break; + case XML_curvedConnector3: { + static const OUString sCurvedConnector3 = CREATE_OUSTRING( "mso-spt38" ); + sType = sCurvedConnector3; + } break; + case XML_curvedConnector4: { + static const OUString sCurvedConnector4 = CREATE_OUSTRING( "mso-spt39" ); + sType = sCurvedConnector4; + } break; + case XML_curvedConnector5: { + static const OUString sCurvedConnector5 = CREATE_OUSTRING( "mso-spt40" ); + sType = sCurvedConnector5; + } break; + case XML_callout1: { + static const OUString sCallout1 = CREATE_OUSTRING( "mso-spt41" ); + sType = sCallout1; + } break; + case XML_callout2: { + static const OUString sCallout2 = CREATE_OUSTRING( "mso-spt42" ); + sType = sCallout2; + } break; + case XML_callout3: { + static const OUString sCallout3 = CREATE_OUSTRING( "mso-spt43" ); + sType = sCallout3; + } break; + case XML_accentCallout1: { + static const OUString sAccentCallout1 = CREATE_OUSTRING( "mso-spt44" ); + sType = sAccentCallout1; + } break; + case XML_accentCallout2: { + static const OUString sAccentCallout2 = CREATE_OUSTRING( "mso-spt45" ); + sType = sAccentCallout2; + } break; + case XML_accentCallout3: { + static const OUString sAccentCallout3 = CREATE_OUSTRING( "mso-spt46" ); + sType = sAccentCallout3; + } break; + case XML_borderCallout1: { + static const OUString sBorderCallout1 = CREATE_OUSTRING( "line-callout-1" ); + sType = sBorderCallout1; + } break; + case XML_borderCallout2: { + static const OUString sBorderCallout2 = CREATE_OUSTRING( "line-callout-2" ); + sType = sBorderCallout2; + } break; + case XML_borderCallout3: { + static const OUString sBorderCallout3 = CREATE_OUSTRING( "mso-spt49" ); + sType = sBorderCallout3; + } break; + case XML_accentBorderCallout1: { + static const OUString sAccentBorderCallout1 = CREATE_OUSTRING( "mso-spt50" ); + sType = sAccentBorderCallout1; + } break; + case XML_accentBorderCallout2: { + static const OUString sAccentBorderCallout2 = CREATE_OUSTRING( "mso-spt51" ); + sType = sAccentBorderCallout2; + } break; + case XML_accentBorderCallout3: { + static const OUString sAccentBorderCallout3 = CREATE_OUSTRING( "mso-spt52" ); + sType = sAccentBorderCallout3; + } break; + case XML_wedgeRectCallout: { + static const OUString sWedgeRectCallout = CREATE_OUSTRING( "rectangular-callout" ); + sType = sWedgeRectCallout; + } break; + case XML_wedgeRoundRectCallout: { + static const OUString sWedgeRoundRectCallout = CREATE_OUSTRING( "round-rectangular-callout" ); + sType = sWedgeRoundRectCallout; + } break; + case XML_wedgeEllipseCallout: { + static const OUString sWedgeEllipseCallout = CREATE_OUSTRING( "round-callout" ); + sType = sWedgeEllipseCallout; + } break; + case XML_cloud: // TODO + case XML_cloudCallout: { + static const OUString sCloudCallout = CREATE_OUSTRING( "cloud-callout" ); + sType = sCloudCallout; + } break; + case XML_ribbon: { + static const OUString sRibbon = CREATE_OUSTRING( "mso-spt53" ); + sType = sRibbon; + } break; + case XML_ribbon2: { + static const OUString sRibbon2 = CREATE_OUSTRING( "mso-spt54" ); + sType = sRibbon2; + } break; + case XML_ellipseRibbon: { + static const OUString sEllipseRibbon = CREATE_OUSTRING( "mso-spt107" ); + sType = sEllipseRibbon; + } break; + case XML_leftRightRibbon: // TODO + case XML_ellipseRibbon2: { + static const OUString sEllipseRibbon2 = CREATE_OUSTRING( "mso-spt108" ); + sType = sEllipseRibbon2; + } break; + case XML_verticalScroll: { + static const OUString sVerticalScroll = CREATE_OUSTRING( "vertical-scroll" ); + sType = sVerticalScroll; + } break; + case XML_horizontalScroll: { + static const OUString sHorizontalScroll = CREATE_OUSTRING( "horizontal-scroll" ); + sType = sHorizontalScroll; + } break; + case XML_wave: { + static const OUString sWave = CREATE_OUSTRING( "mso-spt64" ); + sType = sWave; + } break; + case XML_doubleWave: { + static const OUString sDoubleWave = CREATE_OUSTRING( "mso-spt188" ); + sType = sDoubleWave; + } break; + case XML_plus: { + static const OUString sPlus = CREATE_OUSTRING( "cross" ); + sType = sPlus; + } break; + case XML_flowChartProcess: { + static const OUString sFlowChartProcess = CREATE_OUSTRING( "flowchart-process" ); + sType = sFlowChartProcess; + } break; + case XML_flowChartDecision: { + static const OUString sFlowChartDecision = CREATE_OUSTRING( "flowchart-decision" ); + sType = sFlowChartDecision; + } break; + case XML_flowChartInputOutput: { + static const OUString sFlowChartInputOutput = CREATE_OUSTRING( "flowchart-data" ); + sType = sFlowChartInputOutput; + } break; + case XML_flowChartPredefinedProcess: { + static const OUString sFlowChartPredefinedProcess = CREATE_OUSTRING( "flowchart-predefined-process" ); + sType = sFlowChartPredefinedProcess; + } break; + case XML_flowChartInternalStorage: { + static const OUString sFlowChartInternalStorage = CREATE_OUSTRING( "flowchart-internal-storage" ); + sType = sFlowChartInternalStorage; + } break; + case XML_flowChartDocument: { + static const OUString sFlowChartDocument = CREATE_OUSTRING( "flowchart-document" ); + sType = sFlowChartDocument; + } break; + case XML_flowChartMultidocument: { + static const OUString sFlowChartMultidocument = CREATE_OUSTRING( "flowchart-multidocument" ); + sType = sFlowChartMultidocument; + } break; + case XML_flowChartTerminator: { + static const OUString sFlowChartTerminator = CREATE_OUSTRING( "flowchart-terminator" ); + sType = sFlowChartTerminator; + } break; + case XML_flowChartPreparation : { + static const OUString sFlowChartPreparation = CREATE_OUSTRING( "flowchart-preparation" ); + sType = sFlowChartPreparation; + } break; + case XML_flowChartManualInput: { + static const OUString sFlowChartManualInput = CREATE_OUSTRING( "flowchart-manual-input" ); + sType = sFlowChartManualInput; + } break; + case XML_flowChartManualOperation: { + static const OUString sFlowChartManualOperation = CREATE_OUSTRING( "flowchart-manual-operation" ); + sType = sFlowChartManualOperation; + } break; + case XML_flowChartConnector: { + static const OUString sFlowChartConnector = CREATE_OUSTRING( "flowchart-connector" ); + sType = sFlowChartConnector; + } break; + case XML_flowChartPunchedCard: { + static const OUString sFlowChartPunchedCard = CREATE_OUSTRING( "flowchart-card" ); + sType = sFlowChartPunchedCard; + } break; + case XML_flowChartPunchedTape: { + static const OUString sFlowChartPunchedTape = CREATE_OUSTRING( "flowchart-punched-tape" ); + sType = sFlowChartPunchedTape; + } break; + case XML_flowChartSummingJunction: { + static const OUString sFlowChartSummingJunction = CREATE_OUSTRING( "flowchart-summing-junction" ); + sType = sFlowChartSummingJunction; + } break; + case XML_flowChartOr: { + static const OUString sFlowChartOr = CREATE_OUSTRING( "flowchart-or" ); + sType = sFlowChartOr; + } break; + case XML_flowChartCollate: { + static const OUString sFlowChartCollate = CREATE_OUSTRING( "flowchart-collate" ); + sType = sFlowChartCollate; + } break; + case XML_flowChartSort: { + static const OUString sFlowChartSort = CREATE_OUSTRING( "flowchart-sort" ); + sType = sFlowChartSort; + } break; + case XML_flowChartExtract: { + static const OUString sFlowChartExtract = CREATE_OUSTRING( "flowchart-extract" ); + sType = sFlowChartExtract; + } break; + case XML_flowChartMerge: { + static const OUString sFlowChartMerge = CREATE_OUSTRING( "flowchart-merge" ); + sType = sFlowChartMerge; + } break; + case XML_flowChartOfflineStorage: { + static const OUString sFlowChartOfflineStorage = CREATE_OUSTRING( "mso-spt129" ); + sType = sFlowChartOfflineStorage; + } break; + case XML_flowChartOnlineStorage: { + static const OUString sFlowChartOnlineStorage = CREATE_OUSTRING( "flowchart-stored-data" ); + sType = sFlowChartOnlineStorage; + } break; + case XML_flowChartMagneticTape: { + static const OUString sFlowChartMagneticTape = CREATE_OUSTRING( "flowchart-sequential-access" ); + sType = sFlowChartMagneticTape; + } break; + case XML_flowChartMagneticDisk: { + static const OUString sFlowChartMagneticDisk = CREATE_OUSTRING( "flowchart-magnetic-disk" ); + sType = sFlowChartMagneticDisk; + } break; + case XML_flowChartMagneticDrum: { + static const OUString sFlowChartMagneticDrum = CREATE_OUSTRING( "flowchart-direct-access-storage" ); + sType = sFlowChartMagneticDrum; + } break; + case XML_flowChartDisplay: { + static const OUString sFlowChartDisplay = CREATE_OUSTRING( "flowchart-display" ); + sType = sFlowChartDisplay; + } break; + case XML_flowChartDelay: { + static const OUString sFlowChartDelay = CREATE_OUSTRING( "flowchart-delay" ); + sType = sFlowChartDelay; + } break; + case XML_flowChartAlternateProcess: { + static const OUString sFlowChartAlternateProcess = CREATE_OUSTRING( "flowchart-alternate-process" ); + sType = sFlowChartAlternateProcess; + } break; + case XML_flowChartOffpageConnector: { + static const OUString sFlowChartOffpageConnector = CREATE_OUSTRING( "flowchart-off-page-connector" ); + sType = sFlowChartOffpageConnector; + } break; + case XML_actionButtonBlank: { + static const OUString sActionButtonBlank = CREATE_OUSTRING( "mso-spt189" ); + sType = sActionButtonBlank; + } break; + case XML_actionButtonHome: { + static const OUString sActionButtonHome = CREATE_OUSTRING( "mso-spt190" ); + sType = sActionButtonHome; + } break; + case XML_actionButtonHelp: { + static const OUString sActionButtonHelp = CREATE_OUSTRING( "mso-spt191" ); + sType = sActionButtonHelp; + } break; + case XML_actionButtonInformation: { + static const OUString sActionButtonInformation = CREATE_OUSTRING( "mso-spt192" ); + sType = sActionButtonInformation; + } break; + case XML_actionButtonForwardNext: { + static const OUString sActionButtonForwardNext = CREATE_OUSTRING( "mso-spt193" ); + sType = sActionButtonForwardNext; + } break; + case XML_actionButtonBackPrevious: { + static const OUString sActionButtonBackPrevious = CREATE_OUSTRING( "mso-spt194" ); + sType = sActionButtonBackPrevious; + } break; + case XML_actionButtonEnd: { + static const OUString sActionButtonEnd = CREATE_OUSTRING( "mso-spt195" ); + sType = sActionButtonEnd; + } break; + case XML_actionButtonBeginning: { + static const OUString sActionButtonBeginning = CREATE_OUSTRING( "mso-spt196" ); + sType = sActionButtonBeginning; + } break; + case XML_actionButtonReturn: { + static const OUString sActionButtonReturn = CREATE_OUSTRING( "mso-spt197" ); + sType = sActionButtonReturn; + } break; + case XML_actionButtonDocument: { + static const OUString sActionButtonDocument = CREATE_OUSTRING( "mso-spt198" ); + sType = sActionButtonDocument; + } break; + case XML_actionButtonSound: { + static const OUString sActionButtonSound = CREATE_OUSTRING( "mso-spt199" ); + sType = sActionButtonSound; + } break; + case XML_actionButtonMovie: { + static const OUString sActionButtonMovie = CREATE_OUSTRING( "mso-spt200" ); + sType = sActionButtonMovie; + } break; + case XML_gear6: // TODO + case XML_gear9: // TODO + case XML_funnel: // TODO + case XML_mathPlus: // TODO + case XML_mathMinus: // TODO + case XML_mathMultiply: // TODO + case XML_mathDivide: // TODO + case XML_mathEqual: // TODO + case XML_mathNotEqual: // TODO + case XML_cornerTabs: // TODO + case XML_squareTabs: // TODO + case XML_plaqueTabs: // TODO + case XML_chartX: // TODO + case XML_chartStar: // TODO + case XML_chartPlus: { // TODO + static const OUString sRectangle = CREATE_OUSTRING( "rectangle" ); + sType = sRectangle; + } break; + default: + break; + } + return sType; +} + +static OUString GetTextShapeType( sal_Int32 nType ) +{ + OUString sType; + switch( nType ) + { + case XML_textNoShape: // TODO + case XML_textPlain: { + static const OUString sTextPlain = CREATE_OUSTRING( "fontwork-plain-text" ); + sType = sTextPlain; + } break; + case XML_textStop: { + static const OUString sTextStop = CREATE_OUSTRING( "fontwork-stop" ); + sType = sTextStop; + } break; + case XML_textTriangle: { + static const OUString sTextTriangle = CREATE_OUSTRING( "fontwork-triangle-up" ); + sType = sTextTriangle; + } break; + case XML_textTriangleInverted: { + static const OUString sTextTriangleInverted = CREATE_OUSTRING( "fontwork-triangle-down" ); + sType = sTextTriangleInverted; + } break; + case XML_textChevron: { + static const OUString sTextChevron = CREATE_OUSTRING( "fontwork-chevron-up" ); + sType = sTextChevron; + } break; + case XML_textChevronInverted: { + static const OUString sTextChevronInverted = CREATE_OUSTRING( "fontwork-chevron-down" ); + sType = sTextChevronInverted; + } break; + case XML_textRingInside: { + static const OUString sTextRingInside = CREATE_OUSTRING( "mso-spt142" ); + sType = sTextRingInside; + } break; + case XML_textRingOutside: { + static const OUString sTextRingOutside = CREATE_OUSTRING( "mso-spt143" ); + sType = sTextRingOutside; + } break; + case XML_textArchUp: { + static const OUString sTextArchUp = CREATE_OUSTRING( "fontwork-arch-up-curve" ); + sType = sTextArchUp; + } break; + case XML_textArchDown: { + static const OUString sTextArchDown = CREATE_OUSTRING( "fontwork-arch-down-curve" ); + sType = sTextArchDown; + } break; + case XML_textCircle: { + static const OUString sTextCircle = CREATE_OUSTRING( "fontwork-circle-curve" ); + sType = sTextCircle; + } break; + case XML_textButton: { + static const OUString sTextButton = CREATE_OUSTRING( "fontwork-open-circle-curve" ); + sType = sTextButton; + } break; + case XML_textArchUpPour: { + static const OUString sTextArchUpPour = CREATE_OUSTRING( "fontwork-arch-up-pour" ); + sType = sTextArchUpPour; + } break; + case XML_textArchDownPour: { + static const OUString sTextArchDownPour = CREATE_OUSTRING( "fontwork-arch-down-pour" ); + sType = sTextArchDownPour; + } break; + case XML_textCirclePour: { + static const OUString sTextCirclePour = CREATE_OUSTRING( "fontwork-circle-pour" ); + sType = sTextCirclePour; + } break; + case XML_textButtonPour: { + static const OUString sTextButtonPour = CREATE_OUSTRING( "fontwork-open-circle-pour" ); + sType = sTextButtonPour; + } break; + case XML_textCurveUp: { + static const OUString sTextCurveUp = CREATE_OUSTRING( "fontwork-curve-up" ); + sType = sTextCurveUp; + } break; + case XML_textCurveDown: { + static const OUString sTextCurveDown = CREATE_OUSTRING( "fontwork-curve-down" ); + sType = sTextCurveDown; + } break; + case XML_textCanUp: { + static const OUString sTextCanUp = CREATE_OUSTRING( "mso-spt174" ); + sType = sTextCanUp; + } break; + case XML_textCanDown: { + static const OUString sTextCanDown = CREATE_OUSTRING( "mso-spt175" ); + sType = sTextCanDown; + } break; + case XML_textWave1: { + static const OUString sTextWave1 = CREATE_OUSTRING( "fontwork-wave" ); + sType = sTextWave1; + } break; + case XML_textWave2: { + static const OUString sTextWave2 = CREATE_OUSTRING( "mso-spt157" ); + sType = sTextWave2; + } break; + case XML_textDoubleWave1: { + static const OUString sTextDoubleWave1 = CREATE_OUSTRING( "mso-spt158" ); + sType = sTextDoubleWave1; + } break; + case XML_textWave4: { + static const OUString sTextWave4 = CREATE_OUSTRING( "mso-spt159" ); + sType = sTextWave4; + } break; + case XML_textInflate: { + static const OUString sTextInflate = CREATE_OUSTRING( "fontwork-inflate" ); + sType = sTextInflate; + } break; + case XML_textDeflate: { + static const OUString sTextDeflate = CREATE_OUSTRING( "mso-spt161" ); + sType = sTextDeflate; + } break; + case XML_textInflateBottom: { + static const OUString sTextInflateBottom = CREATE_OUSTRING( "mso-spt162" ); + sType = sTextInflateBottom; + } break; + case XML_textDeflateBottom: { + static const OUString sTextDeflateBottom = CREATE_OUSTRING( "mso-spt163" ); + sType = sTextDeflateBottom; + } break; + case XML_textInflateTop: { + static const OUString sTextInflateTop = CREATE_OUSTRING( "mso-spt164" ); + sType = sTextInflateTop; + } break; + case XML_textDeflateTop: { + static const OUString sTextDeflateTop = CREATE_OUSTRING( "mso-spt165" ); + sType = sTextDeflateTop; + } break; + case XML_textDeflateInflate: { + static const OUString sTextDeflateInflate = CREATE_OUSTRING( "mso-spt166" ); + sType = sTextDeflateInflate; + } break; + case XML_textDeflateInflateDeflate: { + static const OUString sTextDeflateInflateDeflate = CREATE_OUSTRING( "mso-spt167" ); + sType = sTextDeflateInflateDeflate; + } break; + case XML_textFadeRight: { + static const OUString sTextFadeRight = CREATE_OUSTRING( "fontwork-fade-right" ); + sType = sTextFadeRight; + } break; + case XML_textFadeLeft: { + static const OUString sTextFadeLeft = CREATE_OUSTRING( "fontwork-fade-left" ); + sType = sTextFadeLeft; + } break; + case XML_textFadeUp: { + static const OUString sTextFadeUp = CREATE_OUSTRING( "fontwork-fade-up" ); + sType = sTextFadeUp; + } break; + case XML_textFadeDown: { + static const OUString sTextFadeDown = CREATE_OUSTRING( "fontwork-fade-down" ); + sType = sTextFadeDown; + } break; + case XML_textSlantUp: { + static const OUString sTextSlantUp = CREATE_OUSTRING( "fontwork-slant-up" ); + sType = sTextSlantUp; + } break; + case XML_textSlantDown: { + static const OUString sTextSlantDown = CREATE_OUSTRING( "fontwork-slant-down" ); + sType = sTextSlantDown; + } break; + case XML_textCascadeUp: { + static const OUString sTextCascadeUp = CREATE_OUSTRING( "fontwork-fade-up-and-right" ); + sType = sTextCascadeUp; + } break; + case XML_textCascadeDown: { + static const OUString sTextCascadeDown = CREATE_OUSTRING( "fontwork-fade-up-and-left" ); + sType = sTextCascadeDown; + } break; + default: + break; + } + return sType; +} + +// --------------------------------------------------------------------- +// CT_CustomGeometry2D +CustomShapeGeometryContext::CustomShapeGeometryContext( ContextHandler& rParent, const Reference< XFastAttributeList >& /* xAttribs */, CustomShapeProperties& rCustomShapeProperties ) +: ContextHandler( rParent ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ +} + +Reference< XFastContextHandler > CustomShapeGeometryContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xContext; + switch( aElementToken ) + { + case A_TOKEN( avLst ): // CT_GeomGuideList adjust value list + xContext = new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() ); + break; + case A_TOKEN( gdLst ): // CT_GeomGuideList guide list + xContext = new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getGuideList() ); + break; + case A_TOKEN( ahLst ): // CT_AdjustHandleList adjust handle list + xContext = new AdjustHandleListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustHandleList() ); + break; + case A_TOKEN( cxnLst ): // CT_ConnectionSiteList connection site list + xContext = this; + break; + case A_TOKEN( rect ): // CT_GeomRectList geometry rect list + { + GeomRect aGeomRect; + aGeomRect.l = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_l ), sal_True ); + aGeomRect.t = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_t ), sal_True ); + aGeomRect.r = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_r ), sal_True ); + aGeomRect.b = GetAdjCoordinate( mrCustomShapeProperties, xAttribs->getOptionalValue( XML_b ), sal_True ); + mrCustomShapeProperties.getTextRect() = aGeomRect; + } + break; + case A_TOKEN( pathLst ): // CT_Path2DList 2d path list + xContext = new Path2DListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getSegments(), mrCustomShapeProperties.getPath2DList() ); + break; + + // from cxnLst: + case A_TOKEN( cxn ): // CT_ConnectionSite + { + ConnectionSite aConnectionSite; + mrCustomShapeProperties.getConnectionSiteList().push_back( aConnectionSite ); + xContext = new ConnectionSiteContext( *this, xAttribs, mrCustomShapeProperties, mrCustomShapeProperties.getConnectionSiteList().back() ); + } + break; + } + return xContext; +} + +// --------------------------------------------------------------------- +// CT_PresetGeometry2D +PresetShapeGeometryContext::PresetShapeGeometryContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties ) +: ContextHandler( rParent ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + OUString sShapeType; + sal_Int32 nShapeType = xAttribs->getOptionalValueToken( XML_prst, FastToken::DONTKNOW ); + if ( nShapeType != FastToken::DONTKNOW ) + sShapeType = GetShapeType( nShapeType ); + OSL_ENSURE( sShapeType.getLength(), "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" ); + mrCustomShapeProperties.setShapePresetType( sShapeType ); +} + +Reference< XFastContextHandler > PresetShapeGeometryContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + if ( aElementToken == A_TOKEN( avLst ) ) + return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() ); + else + return this; +} + +// --------------------------------------------------------------------- +// CT_PresetTextShape +PresetTextShapeContext::PresetTextShapeContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, CustomShapeProperties& rCustomShapeProperties ) +: ContextHandler( rParent ) +, mrCustomShapeProperties( rCustomShapeProperties ) +{ + OUString sShapeType; + sal_Int32 nShapeType = xAttribs->getOptionalValueToken( XML_prst, FastToken::DONTKNOW ); + if ( nShapeType != FastToken::DONTKNOW ) + sShapeType = GetTextShapeType( nShapeType ); + OSL_ENSURE( sShapeType.getLength(), "oox::drawingml::CustomShapeCustomGeometryContext::CustomShapeCustomGeometryContext(), unknown shape type" ); + mrCustomShapeProperties.setShapePresetType( sShapeType ); +} + +Reference< XFastContextHandler > PresetTextShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + if ( aElementToken == A_TOKEN( avLst ) ) + return new GeomGuideListContext( *this, mrCustomShapeProperties, mrCustomShapeProperties.getAdjustmentGuideList() ); + else + return this; +} + +} } diff --git a/oox/source/drawingml/customshapeproperties.cxx b/oox/source/drawingml/customshapeproperties.cxx new file mode 100644 index 000000000000..052fdc5e1dfc --- /dev/null +++ b/oox/source/drawingml/customshapeproperties.cxx @@ -0,0 +1,268 @@ +/************************************************************************* + * + * 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 <com/sun/star/awt/Rectangle.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> + +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; + +namespace oox { namespace drawingml { + +CustomShapeProperties::CustomShapeProperties() +: mbMirroredX ( sal_False ) +, mbMirroredY ( sal_False ) +{ +} +CustomShapeProperties::~CustomShapeProperties() +{ +} + +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 ) +{ + sal_Int32 nIndex = 0; + for( ; nIndex < static_cast< sal_Int32 >( rGuideList.size() ); nIndex++ ) + { + if ( rGuideList[ nIndex ].maName == rFormulaName ) + break; + } + if ( nIndex == static_cast< sal_Int32 >( rGuideList.size() ) ) + nIndex = -1; + return nIndex; +} + +void CustomShapeProperties::apply( const CustomShapePropertiesPtr& /* rSourceCustomShapeProperties */ ) +{ + // not sure if this needs to be implemented +} + +void CustomShapeProperties::pushToPropSet( const ::oox::core::FilterBase& /* rFilterBase */, + const Reference < XPropertySet >& xPropSet, const Reference < XShape > & xShape ) const +{ + if ( maShapePresetType.getLength() ) + { + //const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY ); + Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY ); + if( xDefaulter.is() ) + xDefaulter->createCustomShapeDefaults( maShapePresetType ); + + 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; + } + } + aIter++; + } + aGeoPropSeq[ i ].Value <<= aAdjustmentSeq; + xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) ); + } + } + else if ( aGeoPropSeq[ i ].Name.equals( sType ) ) + { + aGeoPropSeq[ i ].Value <<= maShapePresetType; + } + } + } + } + } + else + { + sal_uInt32 i; + PropertyMap aPropertyMap; + aPropertyMap[ PROP_Type ] <<= CREATE_OUSTRING( "non-primitive" ); + aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX ); + aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY ); + awt::Size aSize( xShape->getSize() ); + awt::Rectangle aViewBox( 0, 0, aSize.Width * 360, aSize.Height * 360 ); + if ( maPath2DList.size() ) + { // TODO: each polygon may have its own size, but I think it is rather been used + // so we are only taking care of the first + if ( maPath2DList[ 0 ].w ) + aViewBox.Width = static_cast< sal_Int32 >( maPath2DList[ 0 ].w ); + if ( maPath2DList[ 0 ].h ) + aViewBox.Height = static_cast< sal_Int32 >( maPath2DList[ 0 ].h ); + } + 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; + + Sequence< rtl::OUString > aEquations( maGuideList.size() ); + for ( i = 0; i < maGuideList.size(); i++ ) + aEquations[ i ] = maGuideList[ i ].maFormula; + aPropertyMap[ PROP_Equations ] <<= aEquations; + + PropertyMap aPath; + Sequence< EnhancedCustomShapeSegment > aSegments( maSegments.size() ); + for ( i = 0; i < maSegments.size(); i++ ) + aSegments[ i ] = maSegments[ i ]; + aPath[ PROP_Segments ] <<= aSegments; + 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; + Sequence< PropertyValue > aPathSequence = aPath.makePropertyValueSequence(); + aPropertyMap[ PROP_Path ] <<= aPathSequence; + + 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 + // adjument 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; + + // converting the vector to a sequence + Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence(); + PropertySet aPropSet( xPropSet ); + aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq ); + } +} + +double CustomShapeProperties::getValue( const std::vector< CustomShapeGuide >& rGuideList, sal_uInt32 nIndex ) const +{ + double fRet = 0.0; + if ( nIndex < rGuideList.size() ) + { + + } + return fRet; +} + +} } diff --git a/oox/source/drawingml/diagram/datamodelcontext.cxx b/oox/source/drawingml/diagram/datamodelcontext.cxx new file mode 100644 index 000000000000..8d81c800b2df --- /dev/null +++ b/oox/source/drawingml/diagram/datamodelcontext.cxx @@ -0,0 +1,334 @@ +/************************************************************************* + * + * 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/diagram/datamodelcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + +// CL_Cxn +class CxnContext + : public ContextHandler +{ +public: + CxnContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, + const dgm::ConnectionPtr & pConnection ) + : ContextHandler( rParent ) + , mpConnection( pConnection ) + { + sal_Int32 nType = xAttribs->getOptionalValueToken( XML_type, XML_parOf ); + pConnection->mnType = nType; + pConnection->msModelId = xAttribs->getOptionalValue( XML_modelId ); + pConnection->msSourceId = xAttribs->getOptionalValue( XML_srcId ); + pConnection->msDestId = xAttribs->getOptionalValue( XML_destId ); + pConnection->msPresId = xAttribs->getOptionalValue( XML_presId ); + pConnection->msSibTransId = xAttribs->getOptionalValue( XML_sibTransId ); + AttributeList attribs( xAttribs ); + pConnection->mnSourceOrder = attribs.getInteger( XML_srcOrd, 0 ); + pConnection->mnDestOrder = attribs.getInteger( XML_destOrd, 0 ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case DGM_TOKEN( extLst ): + return xRet; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } +private: + dgm::ConnectionPtr mpConnection; +}; + + +// CT_CxnList +class CxnListContext + : public ContextHandler +{ +public: + CxnListContext( ContextHandler& rParent, dgm::Connections & aConnections ) + : ContextHandler( rParent ) + , maConnections( aConnections ) + { + } + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case DGM_TOKEN( cxn ): + { + dgm::ConnectionPtr pConnection( new dgm::Connection() ); + maConnections.push_back( pConnection ); + xRet.set( new CxnContext( *this, xAttribs, pConnection ) ); + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::Connections & maConnections; +}; + + + +// CL_Pt +class PtContext + : public ContextHandler +{ +public: + PtContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, + const dgm::PointPtr & pPoint) + : ContextHandler( rParent ) + , mpPoint( pPoint ) + { + mpPoint->setModelId( xAttribs->getOptionalValue( XML_modelId ) ); + // + // the default type is XML_node + sal_Int32 nType = xAttribs->getOptionalValueToken( XML_type, XML_node ); + mpPoint->setType( nType ); + + // ignore the cxnId unless it is this type. See 5.15.3.1.3 in Primer + if( ( nType == XML_parTrans ) || ( nType == XML_sibTrans ) ) + { + mpPoint->setCnxId( xAttribs->getOptionalValue( XML_cxnId ) ); + } + } + + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case DGM_TOKEN( extLst ): + return xRet; + case DGM_TOKEN( prSet ): + // TODO + // CT_ElemPropSet + break; + case DGM_TOKEN( spPr ): + OSL_TRACE( "shape props for point"); + xRet = new ShapePropertiesContext( *this, *mpPoint->getShape() ); + break; + case DGM_TOKEN( t ): + { + OSL_TRACE( "shape text body for point"); + TextBodyPtr xTextBody( new TextBody ); + mpPoint->getShape()->setTextBody( xTextBody ); + xRet = new TextBodyContext( *this, *xTextBody ); + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::PointPtr mpPoint; +}; + + + +// CT_PtList +class PtListContext + : public ContextHandler +{ +public: + PtListContext( ContextHandler& rParent, dgm::Points & aPoints) + : ContextHandler( rParent ) + , maPoints( aPoints ) + { + } + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case DGM_TOKEN( pt ): + { + // CT_Pt + dgm::PointPtr pPoint( new dgm::Point() ); + maPoints.push_back( pPoint ); + xRet.set( new PtContext( *this, xAttribs, pPoint ) ); + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } + +private: + dgm::Points & maPoints; +}; + +// CT_BackgroundFormatting +class BackgroundFormattingContext + : public ContextHandler +{ +public: + BackgroundFormattingContext( ContextHandler& rParent, DiagramDataPtr & pModel ) + : ContextHandler( rParent ) + , mpDataModel( pModel ) + { + OSL_ENSURE( pModel, "the data model MUST NOT be NULL" ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( sal_Int32 aElementToken, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( blipFill ): + case A_TOKEN( gradFill ): + case A_TOKEN( grpFill ): + case A_TOKEN( noFill ): + case A_TOKEN( pattFill ): + case A_TOKEN( solidFill ): + // EG_FillProperties + xRet.set( FillPropertiesContext::createFillContext( + *this, aElementToken, xAttribs, *mpDataModel->getFillProperties() ) ); + break; + case A_TOKEN( effectDag ): + case A_TOKEN( effectLst ): + // TODO + // EG_EffectProperties + break; + default: + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; + } +private: + DiagramDataPtr mpDataModel; +}; + + + +DataModelContext::DataModelContext( ContextHandler& rParent, + const DiagramDataPtr & pDataModel ) + : ContextHandler( rParent ) + , mpDataModel( pDataModel ) +{ + OSL_ENSURE( pDataModel, "Data Model must not be NULL" ); +} + + +DataModelContext::~DataModelContext() +{ + // some debug + mpDataModel->dump(); +} + + +Reference< XFastContextHandler > SAL_CALL +DataModelContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& /*xAttribs*/ ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( cxnLst ): + // CT_CxnList + xRet.set( new CxnListContext( *this, mpDataModel->getConnections() ) ); + break; + case DGM_TOKEN( ptLst ): + // CT_PtList + xRet.set( new PtListContext( *this, mpDataModel->getPoints() ) ); + break; + case DGM_TOKEN( bg ): + // CT_BackgroundFormatting + xRet.set( new BackgroundFormattingContext( *this, mpDataModel ) ); + break; + case DGM_TOKEN( whole ): + // CT_WholeE2oFormatting + // TODO + return xRet; + case DGM_TOKEN( extLst ): + return xRet; + default: + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx new file mode 100644 index 000000000000..cebb730af103 --- /dev/null +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -0,0 +1,297 @@ +/************************************************************************* + * + * 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 <functional> +#include <boost/bind.hpp> + +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include "oox/drawingml/diagram/diagram.hxx" +#include "oox/drawingml/fillproperties.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; + +namespace oox { namespace drawingml { + +namespace dgm { + + +void Connection::dump() +{ + OSL_TRACE("dgm: cnx modelId %s, srcId %s, dstId %s", + OUSTRING_TO_CSTR( msModelId ), + OUSTRING_TO_CSTR( msSourceId ), + OUSTRING_TO_CSTR( msDestId ) ); +} + +Point::Point() + : mpShape( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ) + , mnType( 0 ) +{ +} + +void Point::dump() +{ + OSL_TRACE( "dgm: pt cnxId %s, modelId %s", + OUSTRING_TO_CSTR( msCnxId ), + OUSTRING_TO_CSTR( msModelId ) ); +} + +void Point::setModelId( const ::rtl::OUString & sModelId ) +{ + msModelId = sModelId; + mpShape->setName( msModelId ); +} + + +bool PointsTree::addChild( const PointsTreePtr & pChild ) +{ + bool added = false; + + OSL_ENSURE( pChild->mpParent.expired(), "can't add, has already a parent" ); + OSL_ENSURE( mpNode, "has no node" ); + if( mpNode && pChild->mpParent.expired() ) + { + pChild->mpParent = shared_from_this(); + maChildrens.push_back( pChild ); + added = true; + } + + return added; +} + +PointsTreePtr PointsTree::getParent() const +{ + if( !mpParent.expired() ) + { + return mpParent.lock() ; + } + return PointsTreePtr(); +} + + +} // dgm namespace + +DiagramData::DiagramData() + : mpFillProperties( new FillProperties ) +{ +} + +void DiagramData::dump() +{ + OSL_TRACE("Dgm: DiagramData # of cnx: %d", maConnections.size() ); + std::for_each( maConnections.begin(), maConnections.end(), + boost::bind( &dgm::Connection::dump, _1 ) ); + OSL_TRACE("Dgm: DiagramData # of pt: %d", maPoints.size() ); + std::for_each( maPoints.begin(), maPoints.end(), + boost::bind( &dgm::Point::dump, _1 ) ); +} + +static void setPosition( const dgm::PointPtr & pPoint, const awt::Point & pt ) +{ + ShapePtr pShape = pPoint->getShape(); + awt::Size sz; + sz.Width = 50; + sz.Height = 50; + pShape->setPosition( pt ); + pShape->setSize( sz ); +} + +void DiagramLayout::layout( const dgm::PointsTreePtr & pTree, const awt::Point & pt ) +{ + setPosition( pTree->getPoint(), pt ); + awt::Point nextPt = pt; + nextPt.Y += 50; + dgm::PointsTree::Childrens::const_iterator iter; + for( iter = pTree->beginChild(); iter != pTree->endChild(); iter++ ) + { + layout( *iter, nextPt ); + nextPt.X += 50; + } +} + +void Diagram::setData( const DiagramDataPtr & pData) +{ + mpData = pData; +} + + +void Diagram::setLayout( const DiagramLayoutPtr & pLayout) +{ + mpLayout = pLayout; +} + +void Diagram::setQStyles( const DiagramQStylesPtr & pStyles) +{ + mpQStyles = pStyles; +} + + +void Diagram::setColors( const DiagramColorsPtr & pColors) +{ + mpColors = pColors; +} + +void Diagram::build( ) +{ + OSL_TRACE( "building diagram" ); + typedef std::map< OUString, dgm::PointPtr > PointsMap; + PointsMap aPointsMap; + dgm::Points::iterator aPointsIter( mpData->getPoints( ).begin() ); + for( ; aPointsIter != mpData->getPoints( ).end() ; aPointsIter++ ) + { + const OUString & sName((*aPointsIter)->getModelId()); + if( sName.getLength() > 0 ) + { + aPointsMap[ sName ] = *aPointsIter; + } + } + + typedef std::map< OUString, dgm::PointsTreePtr > PointsTreeMap; + PointsTreeMap aTreeMap; + PointsTreeMap aRoots; + + dgm::Connections & aConnections(mpData->getConnections( ) ); + dgm::Connections::iterator aCnxIter; + for( aCnxIter = aConnections.begin(); aCnxIter != aConnections.end(); ++aCnxIter ) + { + OSL_ENSURE( *aCnxIter, "NULL connection found" ); + if( (*aCnxIter)->mnType != XML_parOf ) + { +// OSL_TRACE( "ignoring relation %s", OUSTRING_TO_CSTR( (*aCnxIter)->msModelId ) ); + continue; + } + dgm::PointPtr pDest; + dgm::PointsTreePtr pSource; + PointsMap::iterator iterP; + OUString & srcId( (*aCnxIter)->msSourceId ); + OUString & dstId( (*aCnxIter)->msDestId ); + OSL_TRACE( "connexion %s -> %s", OUSTRING_TO_CSTR( srcId ), + OUSTRING_TO_CSTR( dstId ) ); + + PointsTreeMap::iterator iterT = aTreeMap.find( srcId ); + if( iterT != aTreeMap.end() ) + { + pSource = iterT->second; + } + else + { + // this tree node is not found. create it with the source + // and make it the root node. + iterP = aPointsMap.find( srcId ); + if( iterP != aPointsMap.end() ) + { + pSource.reset( new dgm::PointsTree( iterP->second ) ); + aRoots[ srcId ] = pSource; + aTreeMap[ srcId ] = pSource; + } + else + { + OSL_TRACE("parent node not found !"); + } + } + iterP = aPointsMap.find( dstId ); + if( iterP != aPointsMap.end() ) + { + pDest = iterP->second; + } + OSL_ENSURE( pDest, "destination not found" ); + OSL_ENSURE( pSource, "source not found" ); + if(pDest && pSource) + { + dgm::PointsTreePtr pNode( new dgm::PointsTree( pDest ) ); + bool added = pSource->addChild( pNode ); + (void)added; + aRoots.erase( dstId ); + OSL_ENSURE( added, "add child failed" ); + aTreeMap[ dstId ] = pNode; + } + } + // check bounds + OSL_ENSURE( aRoots.size() == 1, "more than one root" ); + // #i92239# roots may be empty + if( !aRoots.empty() ) + { + mpRoot = aRoots.begin()->second; + OSL_TRACE( "root is %s", OUSTRING_TO_CSTR( mpRoot->getPoint()->getModelId() ) ); + for( PointsTreeMap::iterator iter = aTreeMap.begin(); + iter != aTreeMap.end(); iter++ ) + { + if(! iter->second->getParent() ) + { + OSL_TRACE("node without parent %s", OUSTRING_TO_CSTR( iter->first ) ); + } + } + } +} + + +void Diagram::addTo( const ShapePtr & pParentShape ) +{ + dgm::Points & aPoints( mpData->getPoints( ) ); + dgm::Points::iterator aPointsIter; + build( ); + if( mpRoot.get() ) + mpLayout->layout( mpRoot, awt::Point( 0, 0 ) ); + + for( aPointsIter = aPoints.begin(); aPointsIter != aPoints.end(); ++aPointsIter ) + { + if( ( *aPointsIter )->getType() != XML_node ) + { + continue; + } + ShapePtr pShape = ( *aPointsIter )->getShape( ); + if( pShape->getName( ).getLength() > 0 ) + { + maShapeMap[ pShape->getName( ) ] = pShape; + OSL_TRACE( "Dgm: added shape %s to map", OUSTRING_TO_CSTR( pShape->getName() ) ); + } + pParentShape->addChild( pShape ); + } + + OSL_TRACE( "Dgm: addTo() # of childs %d", pParentShape->getChildren().size() ); + for( std::vector< ShapePtr >::iterator iter = pParentShape->getChildren().begin(); + iter != pParentShape->getChildren().end(); ++iter) + { + OSL_TRACE( "Dgm: shape name %s", OUSTRING_TO_CSTR( (*iter)->getName() ) ); + } +} + +OUString Diagram::getLayoutId() const +{ + OUString sLayoutId; + if( mpLayout ) + { + sLayoutId = mpLayout->getUniqueId(); + } + return sLayoutId; +} + + +} } diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx new file mode 100644 index 000000000000..ac98bfb18c38 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.cxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * 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 "diagramdefinitioncontext.hxx" +#include "oox/helper/helper.hxx" +#include "layoutnodecontext.hxx" +#include "oox/drawingml/diagram/datamodelcontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + + +// CT_DiagramDefinition +DiagramDefinitionContext::DiagramDefinitionContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttributes, + const DiagramLayoutPtr &pLayout ) + : ContextHandler( rParent ) + , mpLayout( pLayout ) +{ + OSL_TRACE( "OOX: DiagramDefinitionContext::DiagramDefinitionContext()" ); + mpLayout->setDefStyle( xAttributes->getOptionalValue( XML_defStyle ) ); + OUString sValue = xAttributes->getOptionalValue( XML_minVer ); + if( sValue.getLength() == 0 ) + { + sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ); + } + mpLayout->setMinVer( sValue ); + mpLayout->setUniqueId( xAttributes->getOptionalValue( XML_uniqueId ) ); +} + + +DiagramDefinitionContext::~DiagramDefinitionContext() +{ + mpLayout->getNode()->dump(0); +} + +void SAL_CALL DiagramDefinitionContext::endFastElement( ::sal_Int32 ) + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramDefinitionContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( title ): + mpLayout->setTitle( xAttribs->getOptionalValue( XML_val ) ); + break; + case DGM_TOKEN( desc ): + mpLayout->setDesc( xAttribs->getOptionalValue( XML_val ) ); + break; + case DGM_TOKEN( layoutNode ): + mpLayout->getNode().reset( new LayoutNode() ); + xRet.set( new LayoutNodeContext( *this, xAttribs, mpLayout->getNode() ) ); + break; + case DGM_TOKEN( clrData ): + // TODO, does not matter for the UI. skip. + return xRet; + case DGM_TOKEN( sampData ): + mpLayout->getSampData().reset( new DiagramData ); + xRet.set( new DataModelContext( *this, mpLayout->getSampData() ) ); + break; + case DGM_TOKEN( styleData ): + mpLayout->getStyleData().reset( new DiagramData ); + xRet.set( new DataModelContext( *this, mpLayout->getStyleData() ) ); + break; + case DGM_TOKEN( cat ): + case DGM_TOKEN( catLst ): + // TODO, does not matter for the UI + default: + break; + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx b/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx new file mode 100644 index 000000000000..99407aed80d3 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramdefinitioncontext.hxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_DIAGRAMDEFINITIONCONTEXT_HXX +#define OOX_DRAWINGML_DIAGRAMDEFINITIONCONTEXT_HXX + +#include "oox/core/contexthandler.hxx" +#include "oox/drawingml/diagram/diagram.hxx" + +namespace oox { namespace drawingml { + +class DiagramDefinitionContext : public ::oox::core::ContextHandler +{ +public: + DiagramDefinitionContext( ::oox::core::ContextHandler& rParent, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, const DiagramLayoutPtr &pLayout ); + virtual ~DiagramDefinitionContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +private: + DiagramLayoutPtr mpLayout; +}; + +} } + +#endif diff --git a/oox/source/drawingml/diagram/diagramfragmenthandler.cxx b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx new file mode 100644 index 000000000000..644e84771b3e --- /dev/null +++ b/oox/source/drawingml/diagram/diagramfragmenthandler.cxx @@ -0,0 +1,222 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/diagram/diagramfragmenthandler.hxx" +#include "oox/drawingml/diagram/datamodelcontext.hxx" +#include "diagramdefinitioncontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + +DiagramDataFragmentHandler::DiagramDataFragmentHandler( XmlFilterBase& rFilter, + const OUString& rFragmentPath, + const DiagramDataPtr pDataPtr ) + throw( ) + : FragmentHandler( rFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramDataFragmentHandler::~DiagramDataFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramDataFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramDataFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( dataModel ): + xRet.set( new DataModelContext( *this, mpDataPtr ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet = getFastContextHandler(); + + return xRet; +} + +/////////////////// + +DiagramLayoutFragmentHandler::DiagramLayoutFragmentHandler( XmlFilterBase& rFilter, + const OUString& rFragmentPath, + const DiagramLayoutPtr pDataPtr ) + throw( ) + : FragmentHandler( rFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramLayoutFragmentHandler::~DiagramLayoutFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramLayoutFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramLayoutFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( layoutDef ): + xRet.set( new DiagramDefinitionContext( *this, xAttribs, mpDataPtr ) ); + break; + default: + break; + } + + if( !xRet.is() ) + xRet = getFastContextHandler(); + + return xRet; +} + +/////////////////////// + +DiagramQStylesFragmentHandler::DiagramQStylesFragmentHandler( XmlFilterBase& rFilter, + const OUString& rFragmentPath, + const DiagramQStylesPtr pDataPtr ) + throw( ) + : FragmentHandler( rFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramQStylesFragmentHandler::~DiagramQStylesFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramQStylesFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramQStylesFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( styleDef ): + // TODO + break; + default: + break; + } + + if( !xRet.is() ) + xRet = getFastContextHandler(); + + return xRet; +} + +///////////////////// + +DiagramColorsFragmentHandler::DiagramColorsFragmentHandler( XmlFilterBase& rFilter, + const OUString& rFragmentPath, + const DiagramColorsPtr pDataPtr ) + throw( ) + : FragmentHandler( rFilter, rFragmentPath ) + , mpDataPtr( pDataPtr ) +{ +} + +DiagramColorsFragmentHandler::~DiagramColorsFragmentHandler( ) throw () +{ + +} + +void SAL_CALL DiagramColorsFragmentHandler::endDocument() + throw (SAXException, RuntimeException) +{ + +} + + +Reference< XFastContextHandler > SAL_CALL +DiagramColorsFragmentHandler::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& ) + throw ( SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( colorsDef ): + // TODO + break; + default: + break; + } + + if( !xRet.is() ) + xRet = getFastContextHandler(); + + return xRet; +} + + + + +} } diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx new file mode 100644 index 000000000000..a351189f3067 --- /dev/null +++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * 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/diagram/diagramlayoutatoms.hxx" + +#include <functional> +#include <boost/bind.hpp> + +#include "oox/helper/attributelist.hxx" +#include "layoutnodecontext.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +namespace oox { namespace drawingml { + + +IteratorAttr::IteratorAttr( ) + : mnAxis( 0 ) + , mnCnt( 0 ) + , mbHideLastTrans( false ) + , mnPtType( 0 ) + , mnSt( 0 ) + , mnStep( 1 ) +{ +} + +void IteratorAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr ) +{ + AttributeList attr( xAttr ); + mnAxis = xAttr->getOptionalValueToken( XML_axis, 0 ); + mnCnt = attr.getInteger( XML_cnt, 0 ); + mbHideLastTrans = attr.getBool( XML_hideLastTrans, false ); + mnPtType = xAttr->getOptionalValueToken( XML_ptType, 0 ); + mnSt = attr.getInteger( XML_st, 0 ); + mnStep = attr.getInteger( XML_step, 1 ); +} + + + +ConditionAttr::ConditionAttr() + : mnFunc( 0 ) + , mnArg( 0 ) + , mnOp( 0 ) +{ + +} + + +void ConditionAttr::loadFromXAttr( const Reference< XFastAttributeList >& xAttr ) +{ + mnFunc = xAttr->getOptionalValueToken( XML_func, 0 ); + // mnArg will be -1 for "none" or any other unknown value + mnArg = LayoutNodeContext::tagToVarIdx( xAttr->getOptionalValueToken( XML_arg, XML_none ) ); + mnOp = xAttr->getOptionalValueToken( XML_op, 0 ); + msVal = xAttr->getOptionalValue( XML_val ); +} + + +void LayoutAtom::dump(int level) +{ + OSL_TRACE( "level = %d - %s of type %s", level, + OUSTRING_TO_CSTR( msName ), + typeid(*this).name() ); + std::for_each( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &LayoutAtom::dump, _1, level + 1 ) ); +} + + +void ForEachAtom::processAtom() +{ + // TODO there is likely some conditions + std::for_each( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &LayoutAtom::processAtom, _1 ) ); +} + +/** call ConditionAtom::test() if pAtom is one + * if it is not a ConditionAtom, then return false. + */ +static bool _test_atom( const LayoutAtomPtr & pAtom) +{ + try { + bool bResult = false; + const ConditionAtomPtr pCond = boost::dynamic_pointer_cast< ConditionAtom >(pAtom); + if( pCond ) + { + bResult = pCond->test(); + } + return bResult; + } + catch(...) + { + } + return false; +} + +void ChooseAtom::processAtom() +{ + std::vector< LayoutAtomPtr >::iterator + iter = std::find_if( mpChildNodes.begin(), mpChildNodes.end(), + boost::bind( &_test_atom, _1 ) ); + if( iter != mpChildNodes.end() ) + { + // TODO do something + (*iter)->processAtom(); + } +} + +bool ConditionAtom::test() +{ + // TODO + return false; +} + + +} } diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx new file mode 100644 index 000000000000..0815843dd424 --- /dev/null +++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx @@ -0,0 +1,356 @@ +/************************************************************************* + * + * 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 "layoutnodecontext.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/diagram/diagram.hxx" +#include "oox/drawingml/shapecontext.hxx" +#include "diagramdefinitioncontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { + +class IfContext + : public LayoutNodeContext +{ +public: + IfContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, + const LayoutAtomPtr & pNode ) + : LayoutNodeContext( rParent, xAttribs, pNode ) + { + ConditionAtomPtr pAtom( boost::dynamic_pointer_cast< ConditionAtom >(pNode) ); + OSL_ENSURE( pAtom, "Must pass a ConditionAtom" ); + + pAtom->iterator().loadFromXAttr( xAttribs ); + pAtom->cond().loadFromXAttr( xAttribs ); + } +}; + + + +class AlgorithmContext + : public ContextHandler +{ +public: + AlgorithmContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : ContextHandler( rParent ) + , mnRevision( 0 ) + , mnType( 0 ) + , mpNode( pNode ) + { + AttributeList aAttribs( xAttribs ); + mnRevision = aAttribs.getInteger( XML_rev, 0 ); + mnType = xAttribs->getOptionalValueToken( XML_type, 0 ); + } + +private: + sal_Int32 mnRevision; + sal_Int32 mnType; + LayoutAtomPtr mpNode; +}; + + +class ChooseContext + : public ContextHandler +{ +public: + ChooseContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : ContextHandler( rParent ) + , mbHasElse( false ) + , mpNode( pNode ) + { + msName = xAttribs->getOptionalValue( XML_name ); + } + + virtual Reference< XFastContextHandler > SAL_CALL + createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case XML_if: + { + // CT_When + LayoutAtomPtr pAtom( new ConditionAtom( false ) ); + mpNode->addChild( pAtom ); + xRet.set( new IfContext( *this, xAttribs, pAtom ) ); + break; + } + case XML_else: + // CT_Otherwise + if( !mbHasElse ) + { + LayoutAtomPtr pAtom( new ConditionAtom( true ) ); + mpNode->addChild( pAtom ); + xRet.set( new IfContext( *this, xAttribs, pAtom ) ); + mbHasElse = true; + } + else + { + OSL_TRACE( "ignoring second else clause" ); + } + break; + default: + break; + } + + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } +private: + bool mbHasElse; + OUString msName; + LayoutAtomPtr mpNode; +}; + + + + +class ForEachContext + : public LayoutNodeContext +{ +public: + ForEachContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, const LayoutAtomPtr & pNode ) + : LayoutNodeContext( rParent, xAttribs, pNode ) + { + ForEachAtomPtr pAtom( boost::dynamic_pointer_cast< ForEachAtom >(pNode) ); + OSL_ENSURE( pAtom, "Must pass a ForEachAtom" ); + xAttribs->getOptionalValue( XML_ref ); + + pAtom->iterator().loadFromXAttr( xAttribs ); + } +}; + + +// CT_LayoutVariablePropertySet +class LayoutVariablePropertySetContext + : public ContextHandler +{ +public: + LayoutVariablePropertySetContext( ContextHandler& rParent, LayoutNode::VarMap & aVar ) + : ContextHandler( rParent ) + , mVariables( aVar ) + { + } + + virtual ~LayoutVariablePropertySetContext() + { + } + + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + + sal_Int32 nIdx = LayoutNodeContext::tagToVarIdx( getBaseToken( aElement ) ); + if( nIdx != -1 ) + { + mVariables[ nIdx ] = makeAny( xAttribs->getOptionalValue( XML_val ) ); + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; + } +private: + LayoutNode::VarMap & mVariables; +}; + + +// CT_LayoutNode +LayoutNodeContext::LayoutNodeContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, + const LayoutAtomPtr &pNode ) + : ContextHandler( rParent ) + , mpNode( pNode ) +{ + OSL_ENSURE( pNode, "Node must NOT be NULL" ); + mpNode->setName( xAttribs->getOptionalValue( XML_name ) ); + // TODO shall we even bother? + // b or t +// sal_Int32 nChOrder = xAttributes->getOptionalValueToken( XML_chOrder, XML_b ); +// OUString sMoveWith = xAttributes->getOptionalValue( XML_moveWith ); +// OUString sStyleLbl = xAttributes->getOptionalValue( XML_styleLbl ); +} + + +LayoutNodeContext::~LayoutNodeContext() +{ +} + +void SAL_CALL LayoutNodeContext::endFastElement( ::sal_Int32 ) + throw (SAXException, RuntimeException) +{ + +} + +/** convert the XML tag to a variable index in the array + * @param aTag the tag, wihout namespace + * @return the variable index. -1 is an error + */ +sal_Int32 LayoutNodeContext::tagToVarIdx( sal_Int32 aTag ) +{ + sal_Int32 nIdx = -1; + switch( aTag ) + { + case DGM_TOKEN( animLvl ): + nIdx = LayoutNode::VAR_animLvl; + break; + case DGM_TOKEN( animOne ): + nIdx = LayoutNode::VAR_animOne; + break; + case DGM_TOKEN( bulletEnabled ): + nIdx = LayoutNode::VAR_bulletEnabled; + break; + case DGM_TOKEN( chMax ): + nIdx = LayoutNode::VAR_chMax; + break; + case DGM_TOKEN( chPref ): + nIdx = LayoutNode::VAR_chPref; + break; + case DGM_TOKEN( dir ): + nIdx = LayoutNode::VAR_dir; + break; + case DGM_TOKEN( hierBranch ): + nIdx = LayoutNode::VAR_hierBranch; + break; + case DGM_TOKEN( orgChart ): + nIdx = LayoutNode::VAR_orgChart; + break; + case DGM_TOKEN( resizeHandles ): + nIdx = LayoutNode::VAR_resizeHandles; + break; + default: + break; + } + return nIdx; +} + + +Reference< XFastContextHandler > SAL_CALL +LayoutNodeContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElement ) + { + case DGM_TOKEN( layoutNode ): + { + LayoutNodePtr pNode( new LayoutNode() ); + mpNode->addChild( pNode ); + xRet.set( new LayoutNodeContext( *this, xAttribs, pNode ) ); + break; + } + case DGM_TOKEN( shape ): + { + ShapePtr pShape( new Shape() ); + xRet.set( new ShapeContext( *this, ShapePtr(), pShape ) ); + break; + } + case DGM_TOKEN( extLst ): + return xRet; + case DGM_TOKEN( alg ): + { + // CT_Algorithm + LayoutAtomPtr pAtom( new AlgAtom ); + mpNode->addChild( pAtom ); + xRet.set( new AlgorithmContext( *this, xAttribs, pAtom ) ); + break; + } + case DGM_TOKEN( choose ): + { + // CT_Choose + LayoutAtomPtr pAtom( new ChooseAtom ); + mpNode->addChild( pAtom ); + xRet.set( new ChooseContext( *this, xAttribs, pAtom ) ); + break; + } + case DGM_TOKEN( forEach ): + { + // CT_ForEach + LayoutAtomPtr pAtom( new ForEachAtom ); + mpNode->addChild( pAtom ); + xRet.set( new ForEachContext( *this, xAttribs, pAtom ) ); + break; + } + case DGM_TOKEN( constrLst ): + // CT_Constraints + // TODO + break; + case DGM_TOKEN( presOf ): + { + // CT_PresentationOf + // TODO + xAttribs->getOptionalValue( XML_axis ); + xAttribs->getOptionalValue( XML_cnt ); + xAttribs->getOptionalValue( XML_hideLastTrans ); + xAttribs->getOptionalValue( XML_ptType ); + xAttribs->getOptionalValue( XML_st ); + xAttribs->getOptionalValue( XML_step ); + break; + } + case DGM_TOKEN( ruleLst ): + // CT_Rules + // TODO + break; + case DGM_TOKEN( varLst ): + { + LayoutNodePtr pNode( boost::dynamic_pointer_cast< LayoutNode >( mpNode ) ); + if( pNode ) + { + xRet.set( new LayoutVariablePropertySetContext( *this, pNode->variables() ) ); + } + else + { + OSL_TRACE( "OOX: encountered a varLst in a non layoutNode context" ); + } + break; + } + default: + break; + } + if( !xRet.is() ) + xRet.set(this); + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/diagram/layoutnodecontext.hxx b/oox/source/drawingml/diagram/layoutnodecontext.hxx new file mode 100644 index 000000000000..19cb19aa602d --- /dev/null +++ b/oox/source/drawingml/diagram/layoutnodecontext.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_LAYOUTNODECONTEXT_HXX +#define OOX_DRAWINGML_LAYOUTNODECONTEXT_HXX + +#include "oox/core/contexthandler.hxx" +#include "oox/drawingml/diagram/diagram.hxx" + +namespace oox { namespace drawingml { + +class LayoutNodeContext : public ::oox::core::ContextHandler +{ +public: + LayoutNodeContext( ContextHandler& rParent, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttributes, const LayoutAtomPtr &pNode ); + virtual ~LayoutNodeContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + + static ::sal_Int32 tagToVarIdx( ::sal_Int32 aTag ); +private: + LayoutAtomPtr mpNode; +}; + +} } + +#endif diff --git a/oox/source/drawingml/diagram/makefile.mk b/oox/source/drawingml/diagram/makefile.mk new file mode 100644 index 000000000000..9d526ed3d3fb --- /dev/null +++ b/oox/source/drawingml/diagram/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=oox +TARGET=diagram +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/diagram.obj \ + $(SLO)$/diagramfragmenthandler.obj \ + $(SLO)$/diagramdefinitioncontext.obj \ + $(SLO)$/diagramlayoutatoms.obj \ + $(SLO)$/datamodelcontext.obj \ + $(SLO)$/layoutnodecontext.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/drawingmltypes.cxx b/oox/source/drawingml/drawingmltypes.cxx new file mode 100644 index 000000000000..f99fdc21ab55 --- /dev/null +++ b/oox/source/drawingml/drawingmltypes.cxx @@ -0,0 +1,295 @@ +/************************************************************************* + * + * 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/drawingmltypes.hxx" +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/style/CaseMap.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <sax/tools/converter.hxx> +#include "oox/token/tokens.hxx" + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::xml::sax::XFastAttributeList; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::geometry; +using namespace ::com::sun::star::style; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +/** converts an emu string into 1/100th mmm but constrain as per ST_TextMargin + * see 5.1.12.73 + */ +sal_Int32 GetTextMargin( const OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + else if( nRet < 0 ) + nRet = 0; + else if( nRet > 51206400 ) + nRet = 51206400; + + nRet /= 360; + return nRet; +} + +/** converts EMUs into 1/100th mmm */ +sal_Int32 GetCoordinate( sal_Int32 nValue ) +{ + return (nValue + 180) / 360; +} + +/** converts an emu string into 1/100th mmm */ +sal_Int32 GetCoordinate( const OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + return GetCoordinate( nRet ); +} + +/** converts a ST_Percentage % string into 1/1000th of % */ +sal_Int32 GetPercent( const OUString& sValue ) +{ + sal_Int32 nRet = 0; + if( !::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = 0; + + return nRet; +} + +double GetPositiveFixedPercentage( const OUString& sValue ) +{ + double fPercent = sValue.toFloat() / 100000.; + return fPercent; +} + +// -------------------------------------------------------------------- + +/** converts the attributes from an CT_Point2D into an awt Point with 1/100thmm */ +Point GetPoint2D( const Reference< XFastAttributeList >& xAttribs ) +{ + return Point( GetCoordinate( xAttribs->getOptionalValue( XML_x ) ), GetCoordinate( xAttribs->getOptionalValue( XML_y ) ) ); +} + +/** converts the attributes from an CT_TLPoint into an awt Point with 1/1000% */ +Point GetPointPercent( const Reference< XFastAttributeList >& xAttribs ) +{ + return Point( GetPercent( xAttribs->getOptionalValue( XML_x ) ), GetCoordinate( xAttribs->getOptionalValue( XML_y ) ) ); +} + +// -------------------------------------------------------------------- + +/** converts the ST_TextFontSize to point */ +float GetTextSize( const OUString& sValue ) +{ + float fRet = 0; + sal_Int32 nRet; + if( ::sax::Converter::convertNumber( nRet, sValue ) ) + fRet = static_cast< float >( static_cast< double >( nRet ) / 100.0 ); + return fRet; +} + + +/** converts the ST_TextSpacingPoint to 1/100mm */ +sal_Int32 GetTextSpacingPoint( const OUString& sValue ) +{ + sal_Int32 nRet; + if( ::sax::Converter::convertNumber( nRet, sValue ) ) + nRet = GetTextSpacingPoint( nRet ); + return nRet; +} + +sal_Int32 GetTextSpacingPoint( const sal_Int32 nValue ) +{ + return ( nValue * 254 + 360 ) / 720; +} + +TextVerticalAdjust GetTextVerticalAdjust( sal_Int32 nToken ) +{ + TextVerticalAdjust rVal = TextVerticalAdjust_TOP; + + switch( nToken ) { + case XML_b: + rVal = TextVerticalAdjust_BOTTOM; + break; + case XML_ctr: + rVal = TextVerticalAdjust_CENTER; + break; + } + + return rVal; +} + +float GetFontHeight( sal_Int32 nHeight ) +{ + // convert 1/100 points to points + return static_cast< float >( nHeight / 100.0 ); +} + +sal_Int16 GetFontUnderline( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_none: return FontUnderline::NONE; + case XML_dash: return FontUnderline::DASH; + case XML_dashHeavy: return FontUnderline::BOLDDASH; + case XML_dashLong: return FontUnderline::LONGDASH; + case XML_dashLongHeavy: return FontUnderline::BOLDLONGDASH; + case XML_dbl: return FontUnderline::DOUBLE; + case XML_dotDash: return FontUnderline::DASHDOT; + case XML_dotDashHeavy: return FontUnderline::BOLDDASHDOT; + case XML_dotDotDash: return FontUnderline::DASHDOTDOT; + case XML_dotDotDashHeavy: return FontUnderline::BOLDDASHDOTDOT; + case XML_dotted: return FontUnderline::DOTTED; + case XML_dottedHeavy: return FontUnderline::BOLDDOTTED; + case XML_heavy: return FontUnderline::BOLD; + case XML_sng: return FontUnderline::SINGLE; + case XML_wavy: return FontUnderline::WAVE; + case XML_wavyDbl: return FontUnderline::DOUBLEWAVE; + case XML_wavyHeavy: return FontUnderline::BOLDWAVE; +// case XML_words: // TODO + } + return FontUnderline::DONTKNOW; +} + +sal_Int16 GetFontStrikeout( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_dblStrike: return FontStrikeout::DOUBLE; + case XML_noStrike: return FontStrikeout::NONE; + case XML_sngStrike: return FontStrikeout::SINGLE; + } + return FontStrikeout::DONTKNOW; +} + +sal_Int16 GetCaseMap( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_all: return CaseMap::UPPERCASE; + case XML_small: return CaseMap::SMALLCAPS; + } + return CaseMap::NONE; +} + +/** converts a paragraph align to a ParaAdjust */ +sal_Int16 GetParaAdjust( sal_Int32 nAlign ) +{ + sal_Int16 nEnum; + switch( nAlign ) + { + case XML_ctr: + nEnum = ParagraphAdjust_CENTER; + break; + case XML_just: + case XML_justLow: + nEnum = ParagraphAdjust_BLOCK; + break; + case XML_r: + nEnum = ParagraphAdjust_RIGHT; + break; + case XML_thaiDist: + case XML_dist: + nEnum = ParagraphAdjust_STRETCH; + break; + case XML_l: + default: + nEnum = ParagraphAdjust_LEFT; + break; + } + return nEnum; +} + + +TabAlign GetTabAlign( sal_Int32 aToken ) +{ + TabAlign nEnum; + switch( aToken ) + { + case XML_ctr: + nEnum = TabAlign_CENTER; + break; + case XML_dec: + nEnum = TabAlign_DECIMAL; + break; + case XML_l: + nEnum = TabAlign_LEFT; + break; + case XML_r: + nEnum = TabAlign_RIGHT; + break; + default: + nEnum = TabAlign_DEFAULT; + break; + } + return nEnum; +} + +// -------------------------------------------------------------------- + +/** converts the attributes from a CT_RelativeRect to an IntegerRectangle2D */ +IntegerRectangle2D GetRelativeRect( const Reference< XFastAttributeList >& xAttribs ) +{ + IntegerRectangle2D r; + + r.X1 = xAttribs->getOptionalValue( XML_l ).toInt32(); + r.Y1 = xAttribs->getOptionalValue( XML_t ).toInt32(); + r.X2 = xAttribs->getOptionalValue( XML_r ).toInt32(); + r.Y2 = xAttribs->getOptionalValue( XML_b ).toInt32(); + + return r; +} + +// ============================================================================ + +/** converts the attributes from an CT_Size2D into an awt Size with 1/100thmm */ +Size GetSize2D( const Reference< XFastAttributeList >& xAttribs ) +{ + return Size( GetCoordinate( xAttribs->getOptionalValue( XML_cx ) ), GetCoordinate( xAttribs->getOptionalValue( XML_cy ) ) ); +} + +IndexRange GetIndexRange( const Reference< XFastAttributeList >& xAttributes ) +{ + IndexRange range; + range.start = xAttributes->getOptionalValue( XML_st ).toInt32(); + range.end = xAttributes->getOptionalValue( XML_end ).toInt32(); + return range; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/embeddedwavaudiofile.cxx b/oox/source/drawingml/embeddedwavaudiofile.cxx new file mode 100644 index 000000000000..5c9484894109 --- /dev/null +++ b/oox/source/drawingml/embeddedwavaudiofile.cxx @@ -0,0 +1,53 @@ +/************************************************************************* + * + * 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/embeddedwavaudiofile.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + + +namespace oox { namespace drawingml { + + + // CT_EmbeddedWAVAudioFile + void getEmbeddedWAVAudioFile( const Relations& rRelations, + const Reference< XFastAttributeList >& xAttribs, EmbeddedWAVAudioFile & aAudio ) + { + AttributeList attribs(xAttribs); + + OUString sId = xAttribs->getOptionalValue( R_TOKEN( embed ) ); + aAudio.msEmbed = rRelations.getFragmentPathFromRelId( sId ); + aAudio.mbBuiltIn = attribs.getBool( XML_builtIn, false ); + aAudio.msName = xAttribs->getOptionalValue( XML_name ); + } + + +} } diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx new file mode 100644 index 000000000000..19700cd8199c --- /dev/null +++ b/oox/source/drawingml/fillproperties.cxx @@ -0,0 +1,489 @@ +/************************************************************************* + * + * 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/fillproperties.hxx" +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/text/GraphicCrop.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/drawing/BitmapMode.hpp> +#include <com/sun/star/drawing/ColorMode.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/drawing/RectanglePoint.hpp> +#include <com/sun/star/graphic/XGraphicTransformer.hpp> +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/modelobjecthelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/token/tokens.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::graphic; + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::geometry::IntegerRectangle2D; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +namespace { + +static const sal_Int32 spnDefaultFillIds[ FillId_END ] = +{ + PROP_FillStyle, + PROP_FillColor, + PROP_FillTransparence, + PROP_FillGradient, + PROP_FillBitmapURL, + PROP_FillBitmapMode, + PROP_FillBitmapSizeX, + PROP_FillBitmapSizeY, + PROP_FillBitmapPositionOffsetX, + PROP_FillBitmapPositionOffsetY, + PROP_FillBitmapRectanglePoint +}; + +BitmapMode lclGetBitmapMode( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_tile: return BitmapMode_REPEAT; + case XML_stretch: return BitmapMode_STRETCH; + } + return BitmapMode_NO_REPEAT; +} + +RectanglePoint lclGetRectanglePoint( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_tl: return RectanglePoint_LEFT_TOP; + case XML_t: return RectanglePoint_MIDDLE_TOP; + case XML_tr: return RectanglePoint_RIGHT_TOP; + case XML_l: return RectanglePoint_LEFT_MIDDLE; + case XML_ctr: return RectanglePoint_MIDDLE_MIDDLE; + case XML_r: return RectanglePoint_RIGHT_MIDDLE; + case XML_bl: return RectanglePoint_LEFT_BOTTOM; + case XML_b: return RectanglePoint_MIDDLE_BOTTOM; + case XML_br: return RectanglePoint_RIGHT_BOTTOM; + } + return RectanglePoint_LEFT_TOP; +} + +const awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const Reference< XGraphic >& rxGraphic ) +{ + awt::Size aSizeHmm( 0, 0 ); + try + { + Reference< beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW ); + if( xGraphicPropertySet->getPropertyValue( CREATE_OUSTRING( "Size100thMM" ) ) >>= aSizeHmm ) + { + if( !aSizeHmm.Width && !aSizeHmm.Height ) + { // MAPMODE_PIXEL USED :-( + awt::Size aSourceSizePixel( 0, 0 ); + if( xGraphicPropertySet->getPropertyValue( CREATE_OUSTRING( "SizePixel" ) ) >>= aSourceSizePixel ) + aSizeHmm = rGraphicHelper.convertScreenPixelToHmm( aSourceSizePixel ); + } + } + } + catch( Exception& ) + { + } + return aSizeHmm; +} + +} // namespace + +// ============================================================================ + +FillPropertyIds::FillPropertyIds( const sal_Int32* pnPropertyIds, bool bNamedFillGradient, bool bNamedFillBitmap ) : + mpnPropertyIds( pnPropertyIds ), + mbNamedFillGradient( bNamedFillGradient ), + mbNamedFillBitmap( bNamedFillBitmap ) +{ + OSL_ENSURE( mpnPropertyIds != 0, "FillPropertyIds::FillPropertyIds - missing property identifiers" ); +} + +// ============================================================================ + +void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps ) +{ + if( !rSourceProps.maGradientStops.empty() ) + maGradientStops = rSourceProps.maGradientStops; + moFillToRect.assignIfUsed( rSourceProps.moFillToRect ); + moTileRect.assignIfUsed( rSourceProps.moTileRect ); + moGradientPath.assignIfUsed( rSourceProps.moGradientPath ); + moShadeAngle.assignIfUsed( rSourceProps.moShadeAngle ); + moShadeFlip.assignIfUsed( rSourceProps.moShadeFlip ); + moShadeScaled.assignIfUsed( rSourceProps.moShadeScaled ); + moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); +} + +// ============================================================================ + +void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps ) +{ + maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor ); + maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor ); + moPattPreset.assignIfUsed( rSourceProps.moPattPreset ); +} + +// ============================================================================ + +void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps ) +{ + if( rSourceProps.mxGraphic.is() ) + mxGraphic = rSourceProps.mxGraphic; + moBitmapMode.assignIfUsed( rSourceProps.moBitmapMode ); + moFillRect.assignIfUsed( rSourceProps.moFillRect ); + moTileOffsetX.assignIfUsed( rSourceProps.moTileOffsetX ); + moTileOffsetY.assignIfUsed( rSourceProps.moTileOffsetY ); + moTileScaleX.assignIfUsed( rSourceProps.moTileScaleX ); + moTileScaleY.assignIfUsed( rSourceProps.moTileScaleY ); + moTileAlign.assignIfUsed( rSourceProps.moTileAlign ); + moTileFlip.assignIfUsed( rSourceProps.moTileFlip ); + moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); + moColorEffect.assignIfUsed( rSourceProps.moColorEffect ); + moBrightness.assignIfUsed( rSourceProps.moBrightness ); + moContrast.assignIfUsed( rSourceProps.moContrast ); + maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom ); + maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo ); +} + +// ============================================================================ + +FillPropertyIds FillProperties::DEFAULT_IDS( spnDefaultFillIds, false, false ); + +void FillProperties::assignUsed( const FillProperties& rSourceProps ) +{ + moFillType.assignIfUsed( rSourceProps.moFillType ); + maFillColor.assignIfUsed( rSourceProps.maFillColor ); + maGradientProps.assignUsed( rSourceProps.maGradientProps ); + maPatternProps.assignUsed( rSourceProps.maPatternProps ); + maBlipProps.assignUsed( rSourceProps.maBlipProps ); +} + +Color FillProperties::getBestSolidColor() const +{ + Color aSolidColor; + if( moFillType.has() ) switch( moFillType.get() ) + { + case XML_solidFill: + aSolidColor = maFillColor; + break; + case XML_gradFill: + if( !maGradientProps.maGradientStops.empty() ) + aSolidColor = maGradientProps.maGradientStops.begin()->second; + break; + case XML_pattFill: + aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor; + break; + } + return aSolidColor; +} + +void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rModelObjHelper, + const GraphicHelper& rGraphicHelper, const FillPropertyIds& rPropIds, + sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const +{ + if( moFillType.has() ) + { + FillStyle eFillStyle = FillStyle_NONE; + switch( moFillType.get() ) + { + case XML_noFill: + eFillStyle = FillStyle_NONE; + break; + + case XML_solidFill: + if( maFillColor.isUsed() ) + { + rPropMap.setProperty( rPropIds[ FillColorId ], maFillColor.getColor( rGraphicHelper, nPhClr ) ); + if( maFillColor.hasTransparence() ) + rPropMap.setProperty( rPropIds[ FillTransparenceId ], maFillColor.getTransparence() ); + eFillStyle = FillStyle_SOLID; + } + break; + + case XML_gradFill: + // do not create gradient struct if property is not supported... + if( rPropIds.has( FillGradientId ) ) + { + awt::Gradient aGradient; + aGradient.Angle = 900; + aGradient.StartIntensity = 100; + aGradient.EndIntensity = 100; + + size_t nColorCount = maGradientProps.maGradientStops.size(); + if( nColorCount > 1 ) + { + aGradient.StartColor = maGradientProps.maGradientStops.begin()->second.getColor( rGraphicHelper, nPhClr ); + aGradient.EndColor = maGradientProps.maGradientStops.rbegin()->second.getColor( rGraphicHelper, nPhClr ); + } + + // "rotate with shape" not set, or set to false -> do not rotate + if ( !maGradientProps.moRotateWithShape.get( false ) ) + nShapeRotation = 0; + + sal_Int32 nDmlAngle = 0; + if( maGradientProps.moGradientPath.has() ) + { + aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT; + // position of gradient center (limited to [30%;70%], otherwise gradient is too hidden) + IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.get( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) ); + sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2; + aGradient.XOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterX / PER_PERCENT, 30, 70 ); + sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2; + aGradient.YOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterY / PER_PERCENT, 30, 70 ); + ::std::swap( aGradient.StartColor, aGradient.EndColor ); + nDmlAngle = nShapeRotation; + } + else + { + /* Try to detect a VML axial gradient. This type of + gradient is simulated by a 3-point linear gradient + with equal start and end color. */ + bool bAxial = (nColorCount == 3) && (aGradient.StartColor == aGradient.EndColor); + aGradient.Style = bAxial ? awt::GradientStyle_AXIAL : awt::GradientStyle_LINEAR; + if( bAxial ) + { + GradientFillProperties::GradientStopMap::const_iterator aIt = maGradientProps.maGradientStops.begin(); + // API StartColor is inner color in axial gradient + aGradient.StartColor = (++aIt)->second.getColor( rGraphicHelper, nPhClr ); + } + nDmlAngle = maGradientProps.moShadeAngle.get( 0 ) - nShapeRotation; + } + // convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees) + aGradient.Angle = static_cast< sal_Int16 >( (4500 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 ); + + // push gradient or named gradient to property map + if( rPropIds.mbNamedFillGradient ) + { + OUString aGradientName = rModelObjHelper.insertFillGradient( aGradient ); + if( aGradientName.getLength() > 0 ) + { + rPropMap.setProperty( rPropIds[ FillGradientId ], aGradientName ); + eFillStyle = FillStyle_GRADIENT; + } + } + else + { + rPropMap.setProperty( rPropIds[ FillGradientId ], aGradient ); + eFillStyle = FillStyle_GRADIENT; + } + } + break; + + case XML_blipFill: + // do not start complex graphic transformation if property is not supported... + if( maBlipProps.mxGraphic.is() && rPropIds.has( FillBitmapUrlId ) ) + { + // TODO: "rotate with shape" is not possible with our current core + + OUString aGraphicUrl = rGraphicHelper.createGraphicObject( maBlipProps.mxGraphic ); + if( aGraphicUrl.getLength() > 0 ) + { + // push bitmap or named bitmap to property map + if( rPropIds.mbNamedFillBitmap ) + { + OUString aBitmapName = rModelObjHelper.insertFillBitmap( aGraphicUrl ); + if( aBitmapName.getLength() > 0 ) + { + rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aBitmapName ); + eFillStyle = FillStyle_BITMAP; + } + } + else + { + rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aGraphicUrl ); + eFillStyle = FillStyle_BITMAP; + } + } + + // set other bitmap properties, if bitmap has been inserted into the map + if( eFillStyle == FillStyle_BITMAP ) + { + // bitmap mode (single, repeat, stretch) + BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) ); + rPropMap.setProperty( rPropIds[ FillBitmapModeId ], eBitmapMode ); + + // additional settings for repeated bitmap + if( eBitmapMode == BitmapMode_REPEAT ) + { + // anchor position inside bitmap + RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) ); + rPropMap.setProperty( rPropIds[ FillBitmapRectanglePointId ], eRectPoint ); + + awt::Size aOriginalSize = lclGetOriginalSize( rGraphicHelper, maBlipProps.mxGraphic ); + if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) ) + { + // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm + double fScaleX = maBlipProps.moTileScaleX.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); + sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 ); + rPropMap.setProperty( rPropIds[ FillBitmapSizeXId ], nFillBmpSizeX ); + double fScaleY = maBlipProps.moTileScaleY.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); + sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 ); + rPropMap.setProperty( rPropIds[ FillBitmapSizeYId ], nFillBmpSizeY ); + + // offset of the first bitmap tile (given as EMUs), convert to percent + sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 ); + rPropMap.setProperty( rPropIds[ FillBitmapOffsetXId ], nTileOffsetX ); + sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 ); + rPropMap.setProperty( rPropIds[ FillBitmapOffsetYId ], nTileOffsetY ); + } + } + } + } + break; + + case XML_pattFill: + { + // todo + Color aColor = getBestSolidColor(); + if( aColor.isUsed() ) + { + rPropMap.setProperty( rPropIds[ FillColorId ], aColor.getColor( rGraphicHelper, nPhClr ) ); + if( aColor.hasTransparence() ) + rPropMap.setProperty( rPropIds[ FillTransparenceId ], aColor.getTransparence() ); + eFillStyle = FillStyle_SOLID; + } + } + break; + + case XML_grpFill: + // todo + eFillStyle = FillStyle_NONE; + break; + } + + // set final fill style property + rPropMap.setProperty( rPropIds[ FillStyleId ], eFillStyle ); + } +} + +void FillProperties::pushToPropSet( PropertySet& rPropSet, ModelObjectHelper& rModelObjHelper, + const GraphicHelper& rGraphicHelper, const FillPropertyIds& rPropIds, + sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const +{ + PropertyMap aPropMap; + pushToPropMap( aPropMap, rModelObjHelper, rGraphicHelper, rPropIds, nShapeRotation, nPhClr ); + rPropSet.setProperties( aPropMap ); +} + +// ============================================================================ + +void GraphicProperties::assignUsed( const GraphicProperties& rSourceProps ) +{ + maBlipProps.assignUsed( rSourceProps.maBlipProps ); +} + +void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const +{ + if( maBlipProps.mxGraphic.is() ) + { + // created transformed graphic + Reference< XGraphic > xGraphic = maBlipProps.mxGraphic; + if( maBlipProps.maColorChangeFrom.isUsed() && maBlipProps.maColorChangeTo.isUsed() ) + { + sal_Int32 nFromColor = maBlipProps.maColorChangeFrom.getColor( rGraphicHelper, nPhClr ); + sal_Int32 nToColor = maBlipProps.maColorChangeTo.getColor( rGraphicHelper, nPhClr ); + if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparence() ) try + { + sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparence(); + sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!? + Reference< XGraphicTransformer > xTransformer( maBlipProps.mxGraphic, UNO_QUERY_THROW ); + xGraphic = xTransformer->colorChange( maBlipProps.mxGraphic, nFromColor, 9, nToColor, nToAlpha ); + } + catch( Exception& ) + { + } + } + + OUString aGraphicUrl = rGraphicHelper.createGraphicObject( xGraphic ); + if( aGraphicUrl.getLength() > 0 ) + rPropMap[ PROP_GraphicURL ] <<= aGraphicUrl; + + // cropping + if ( maBlipProps.moClipRect.has() ) + { + geometry::IntegerRectangle2D oClipRect( maBlipProps.moClipRect.get() ); + awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) ); + if ( aOriginalSize.Width && aOriginalSize.Height ) + { + text::GraphicCrop aGraphCrop( 0, 0, 0, 0 ); + if ( oClipRect.X1 ) + aGraphCrop.Left = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X1 ) / 100000 ); + if ( oClipRect.Y1 ) + aGraphCrop.Top = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y1 ) / 100000 ); + if ( oClipRect.X2 ) + aGraphCrop.Right = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X2 ) / 100000 ); + if ( oClipRect.Y2 ) + aGraphCrop.Bottom = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y2 ) / 100000 ); + rPropMap[ PROP_GraphicCrop ] <<= aGraphCrop; + } + } + } + + // color effect + ColorMode eColorMode = ColorMode_STANDARD; + switch( maBlipProps.moColorEffect.get( XML_TOKEN_INVALID ) ) + { + case XML_biLevel: eColorMode = ColorMode_MONO; break; + case XML_grayscl: eColorMode = ColorMode_GREYS; break; + } + rPropMap[ PROP_GraphicColorMode ] <<= eColorMode; + + // brightness and contrast + sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.get( 0 ) / PER_PERCENT, -100, 100 ); + if( nBrightness != 0 ) + rPropMap[ PROP_AdjustLuminance ] <<= nBrightness; + sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.get( 0 ) / PER_PERCENT, -100, 100 ); + if( nContrast != 0 ) + rPropMap[ PROP_AdjustContrast ] <<= nContrast; +} + +void GraphicProperties::pushToPropSet( PropertySet& rPropSet, const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const +{ + PropertyMap aPropMap; + pushToPropMap( aPropMap, rGraphicHelper, nPhClr ); + rPropSet.setProperties( aPropMap ); +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx new file mode 100644 index 000000000000..15b1ef0f2404 --- /dev/null +++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx @@ -0,0 +1,308 @@ +/************************************************************************* + * + * 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/fillpropertiesgroupcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/fillproperties.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::oox::core::ContextHandler; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +SolidFillContext::SolidFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >&, FillProperties& rFillProps ) : + ColorContext( rParent, rFillProps.maFillColor ) +{ +} + +// ============================================================================ + +GradientFillContext::GradientFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, GradientFillProperties& rGradientProps ) : + ContextHandler( rParent ), + mrGradientProps( rGradientProps ) +{ + AttributeList aAttribs( rxAttribs ); + mrGradientProps.moShadeFlip = aAttribs.getToken( XML_flip ); + mrGradientProps.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); +} + +Reference< XFastContextHandler > GradientFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( gsLst ): + return this; // for gs elements + + case A_TOKEN( gs ): + if( aAttribs.hasAttribute( XML_pos ) ) + { + double fPosition = getLimitedValue< double >( aAttribs.getDouble( XML_pos, 0.0 ) / 100000.0, 0.0, 1.0 ); + return new ColorContext( *this, mrGradientProps.maGradientStops[ fPosition ] ); + } + break; + + case A_TOKEN( lin ): + mrGradientProps.moShadeAngle = aAttribs.getInteger( XML_ang ); + mrGradientProps.moShadeScaled = aAttribs.getBool( XML_scaled ); + break; + + case A_TOKEN( path ): + // always set a path type, this disables linear gradient in conversion + mrGradientProps.moGradientPath = aAttribs.getToken( XML_path, XML_rect ); + return this; // for fillToRect element + + case A_TOKEN( fillToRect ): + mrGradientProps.moFillToRect = GetRelativeRect( rxAttribs ); + break; + + case A_TOKEN( tileRect ): + mrGradientProps.moTileRect = GetRelativeRect( rxAttribs ); + break; + } + return 0; +} + +// ============================================================================ + +PatternFillContext::PatternFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, PatternFillProperties& rPatternProps ) : + ContextHandler( rParent ), + mrPatternProps( rPatternProps ) +{ + AttributeList aAttribs( rxAttribs ); + mrPatternProps.moPattPreset = aAttribs.getToken( XML_prst ); +} + +Reference< XFastContextHandler > PatternFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( bgClr ): + return new ColorContext( *this, mrPatternProps.maPattBgColor ); + case A_TOKEN( fgClr ): + return new ColorContext( *this, mrPatternProps.maPattFgColor ); + } + return 0; +} + +// ============================================================================ +// ============================================================================ + +ColorChangeContext::ColorChangeContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) +{ + mrBlipProps.maColorChangeFrom.setUnused(); + mrBlipProps.maColorChangeTo.setUnused(); + AttributeList aAttribs( rxAttribs ); + mbUseAlpha = aAttribs.getBool( XML_useA, true ); +} + +ColorChangeContext::~ColorChangeContext() +{ + if( !mbUseAlpha ) + mrBlipProps.maColorChangeTo.clearTransparence(); +} + +Reference< XFastContextHandler > ColorChangeContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( clrFrom ): + return new ColorContext( *this, mrBlipProps.maColorChangeFrom ); + case A_TOKEN( clrTo ): + return new ColorContext( *this, mrBlipProps.maColorChangeTo ); + } + return 0; +} + +// ============================================================================ + +BlipContext::BlipContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) +{ + AttributeList aAttribs( rxAttribs ); + if( aAttribs.hasAttribute( R_TOKEN( embed ) ) ) + { + // internal picture URL + OUString aFragmentPath = getFragmentPathFromRelId( aAttribs.getString( R_TOKEN( embed ), OUString() ) ); + if( aFragmentPath.getLength() > 0 ) + mrBlipProps.mxGraphic = getFilter().getGraphicHelper().importEmbeddedGraphic( aFragmentPath ); + } + else if( aAttribs.hasAttribute( R_TOKEN( link ) ) ) + { + // external URL + OUString aRelId = aAttribs.getString( R_TOKEN( link ), OUString() ); + OUString aTargetLink = getFilter().getAbsoluteUrl( getRelations().getExternalTargetFromRelId( aRelId ) ); + // TODO: load external picture + } +} + +Reference< XFastContextHandler > BlipContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( biLevel ): + case A_TOKEN( grayscl ): + mrBlipProps.moColorEffect = getBaseToken( nElement ); + break; + + case A_TOKEN( clrChange ): + return new ColorChangeContext( *this, rxAttribs, mrBlipProps ); + + case A_TOKEN( lum ): + mrBlipProps.moBrightness = aAttribs.getInteger( XML_bright ); + mrBlipProps.moContrast = aAttribs.getInteger( XML_contrast ); + break; + } + return 0; +} + +// ============================================================================ + +BlipFillContext::BlipFillContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rxAttribs, BlipFillProperties& rBlipProps ) : + ContextHandler( rParent ), + mrBlipProps( rBlipProps ) +{ + AttributeList aAttribs( rxAttribs ); + mrBlipProps.moRotateWithShape = aAttribs.getBool( XML_rotWithShape ); +} + +Reference< XFastContextHandler > BlipFillContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( blip ): + return new BlipContext( *this, rxAttribs, mrBlipProps ); + + case A_TOKEN( srcRect ): + { + rtl::OUString aDefault( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) ); + ::com::sun::star::geometry::IntegerRectangle2D aClipRect; + aClipRect.X1 = GetPercent( aAttribs.getString( XML_l, aDefault ) ); + aClipRect.Y1 = GetPercent( aAttribs.getString( XML_t, aDefault ) ); + aClipRect.X2 = GetPercent( aAttribs.getString( XML_r, aDefault ) ); + aClipRect.Y2 = GetPercent( aAttribs.getString( XML_b, aDefault ) ); + mrBlipProps.moClipRect = aClipRect; + } + break; + + case A_TOKEN( tile ): + mrBlipProps.moBitmapMode = getBaseToken( nElement ); + mrBlipProps.moTileOffsetX = aAttribs.getInteger( XML_tx ); + mrBlipProps.moTileOffsetY = aAttribs.getInteger( XML_ty ); + mrBlipProps.moTileScaleX = aAttribs.getInteger( XML_sx ); + mrBlipProps.moTileScaleY = aAttribs.getInteger( XML_sy ); + mrBlipProps.moTileAlign = aAttribs.getToken( XML_algn ); + mrBlipProps.moTileFlip = aAttribs.getToken( XML_flip ); + break; + + case A_TOKEN( stretch ): + mrBlipProps.moBitmapMode = getBaseToken( nElement ); + return this; // for fillRect element + + case A_TOKEN( fillRect ): + mrBlipProps.moFillRect = GetRelativeRect( rxAttribs ); + break; + } + return 0; +} + +// ============================================================================ +// ============================================================================ + +FillPropertiesContext::FillPropertiesContext( ContextHandler& rParent, FillProperties& rFillProps ) : + ContextHandler( rParent ), + mrFillProps( rFillProps ) +{ +} + +Reference< XFastContextHandler > FillPropertiesContext::createFastChildContext( + sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) + throw ( SAXException, RuntimeException ) +{ + return createFillContext( *this, nElement, rxAttribs, mrFillProps ); +} + +/*static*/ Reference< XFastContextHandler > FillPropertiesContext::createFillContext( + ContextHandler& rParent, sal_Int32 nElement, + const Reference< XFastAttributeList >& rxAttribs, FillProperties& rFillProps ) +{ + switch( nElement ) + { + case A_TOKEN( noFill ): { rFillProps.moFillType = getBaseToken( nElement ); return 0; }; + case A_TOKEN( solidFill ): { rFillProps.moFillType = getBaseToken( nElement ); return new SolidFillContext( rParent, rxAttribs, rFillProps ); }; + case A_TOKEN( gradFill ): { rFillProps.moFillType = getBaseToken( nElement ); return new GradientFillContext( rParent, rxAttribs, rFillProps.maGradientProps ); }; + case A_TOKEN( pattFill ): { rFillProps.moFillType = getBaseToken( nElement ); return new PatternFillContext( rParent, rxAttribs, rFillProps.maPatternProps ); }; + case A_TOKEN( blipFill ): { rFillProps.moFillType = getBaseToken( nElement ); return new BlipFillContext( rParent, rxAttribs, rFillProps.maBlipProps ); }; + case A_TOKEN( grpFill ): { rFillProps.moFillType = getBaseToken( nElement ); return 0; }; // TODO + } + return 0; +} + +// ============================================================================ + +SimpleFillPropertiesContext::SimpleFillPropertiesContext( ContextHandler& rParent, Color& rColor ) : + FillPropertiesContext( rParent, *this ), + mrColor( rColor ) +{ +} + +SimpleFillPropertiesContext::~SimpleFillPropertiesContext() +{ + mrColor = getBestSolidColor(); +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx new file mode 100644 index 000000000000..646017aa22ea --- /dev/null +++ b/oox/source/drawingml/graphicshapecontext.cxx @@ -0,0 +1,317 @@ +/************************************************************************* + * + * 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/graphicshapecontext.hxx" +#include <osl/diagnose.h> + +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/customshapeproperties.hxx" +#include "oox/drawingml/diagram/diagramfragmenthandler.hxx" +#include "oox/drawingml/table/tablecontext.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/transform2dcontext.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +namespace oox { +namespace drawingml { + +// ============================================================================ +// CT_Picture + +GraphicShapeContext::GraphicShapeContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) +: ShapeContext( rParent, pMasterShapePtr, pShapePtr ) +{ +} + +Reference< XFastContextHandler > GraphicShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( getBaseToken( aElementToken ) ) + { + // CT_ShapeProperties + case XML_xfrm: + xRet.set( new Transform2DContext( *this, xAttribs, *mpShapePtr ) ); + break; + case XML_blipFill: + xRet.set( new BlipFillContext( *this, xAttribs, mpShapePtr->getGraphicProperties().maBlipProps ) ); + break; + } + + if ((getNamespace( aElementToken ) == NMSP_vml) && mpShapePtr) + { + mpShapePtr->setServiceName("com.sun.star.drawing.CustomShape"); + CustomShapePropertiesPtr pCstmShpProps + (mpShapePtr->getCustomShapeProperties()); + + sal_uInt32 nType = getBaseToken( aElementToken ); + OUString sType(GetShapeType(nType)); + + if (sType.getLength() > 0) + pCstmShpProps->setShapePresetType(sType); + } + + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +// ============================================================================ +// CT_GraphicalObjectFrameContext + +GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr, bool bEmbedShapesInChart ) : + ShapeContext( rParent, pMasterShapePtr, pShapePtr ), + mbEmbedShapesInChart( bEmbedShapesInChart ) +{ +} + +Reference< XFastContextHandler > GraphicalObjectFrameContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( getBaseToken( aElementToken ) ) + { + // CT_ShapeProperties + case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual + break; + case XML_xfrm: // CT_Transform2D + xRet.set( new Transform2DContext( *this, xAttribs, *mpShapePtr ) ); + break; + case XML_graphic: // CT_GraphicalObject + xRet.set( this ); + break; + + case XML_graphicData : // CT_GraphicalObjectData + { + OUString sUri( xAttribs->getOptionalValue( XML_uri ) ); + if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/presentationml/2006/ole" ) ) + xRet.set( new OleObjectGraphicDataContext( *this, mpShapePtr ) ); + else if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/drawingml/2006/diagram" ) ) + xRet.set( new DiagramGraphicDataContext( *this, mpShapePtr ) ); + else if ( sUri.equalsAscii( "http://schemas.openxmlformats.org/drawingml/2006/chart" ) ) + xRet.set( new ChartGraphicDataContext( *this, mpShapePtr, mbEmbedShapesInChart ) ); + else if ( sUri.compareToAscii( "http://schemas.openxmlformats.org/drawingml/2006/table" ) == 0 ) + xRet.set( new table::TableContext( *this, mpShapePtr ) ); + else + { + OSL_TRACE( "OOX: Ignore graphicsData of %s", OUSTRING_TO_CSTR( sUri ) ); + return xRet; + } + } + break; + } + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +// ============================================================================ + +OleObjectGraphicDataContext::OleObjectGraphicDataContext( ContextHandler& rParent, ShapePtr xShape ) : + ShapeContext( rParent, ShapePtr(), xShape ), + mrOleObjectInfo( xShape->setOleObjectType() ) +{ +} + +OleObjectGraphicDataContext::~OleObjectGraphicDataContext() +{ + /* Register the OLE shape at the VML drawing, this prevents that the + related VML shape converts the OLE object by itself. */ + if( mrOleObjectInfo.maShapeId.getLength() > 0 ) + if( ::oox::vml::Drawing* pVmlDrawing = getFilter().getVmlDrawing() ) + pVmlDrawing->registerOleObject( mrOleObjectInfo ); +} + +Reference< XFastContextHandler > OleObjectGraphicDataContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); + + switch( nElement ) + { + case PPT_TOKEN( oleObj ): + { + mrOleObjectInfo.maShapeId = aAttribs.getXString( XML_spid, OUString() ); + const Relation* pRelation = getRelations().getRelationFromRelId( aAttribs.getString( R_TOKEN( id ), OUString() ) ); + OSL_ENSURE( pRelation, "OleObjectGraphicDataContext::createFastChildContext - missing relation for OLE object" ); + if( pRelation ) + { + mrOleObjectInfo.mbLinked = pRelation->mbExternal; + if( pRelation->mbExternal ) + { + mrOleObjectInfo.maTargetLink = getFilter().getAbsoluteUrl( pRelation->maTarget ); + } + else + { + OUString aFragmentPath = getFragmentPathFromRelation( *pRelation ); + if( aFragmentPath.getLength() > 0 ) + getFilter().importBinaryData( mrOleObjectInfo.maEmbeddedData, aFragmentPath ); + } + } + mrOleObjectInfo.maName = aAttribs.getXString( XML_name, OUString() ); + mrOleObjectInfo.maProgId = aAttribs.getXString( XML_progId, OUString() ); + mrOleObjectInfo.mbShowAsIcon = aAttribs.getBool( XML_showAsIcon, false ); + xRet.set( this ); + } + break; + + case PPT_TOKEN( embed ): + OSL_ENSURE( !mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); + break; + + case PPT_TOKEN( link ): + OSL_ENSURE( mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); + mrOleObjectInfo.mbAutoUpdate = aAttribs.getBool( XML_updateAutomatic, false ); + break; + } + return xRet; +} + +// ============================================================================ + +DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler& rParent, ShapePtr pShapePtr ) +: ShapeContext( rParent, ShapePtr(), pShapePtr ) +{ + pShapePtr->setDiagramType(); +} + +DiagramGraphicDataContext::~DiagramGraphicDataContext() +{ +} + +DiagramPtr DiagramGraphicDataContext::loadDiagram() +{ + DiagramPtr pDiagram( new Diagram() ); + XmlFilterBase& rFilter = getFilter(); + + // data + OUString sDmPath = getFragmentPathFromRelId( msDm ); + if( sDmPath.getLength() > 0 ) + { + DiagramDataPtr pData( new DiagramData() ); + pDiagram->setData( pData ); + rFilter.importFragment( new DiagramDataFragmentHandler( rFilter, sDmPath, pData ) ); + } + // layout + OUString sLoPath = getFragmentPathFromRelId( msLo ); + if( sLoPath.getLength() > 0 ) + { + DiagramLayoutPtr pLayout( new DiagramLayout() ); + pDiagram->setLayout( pLayout ); + rFilter.importFragment( new DiagramLayoutFragmentHandler( rFilter, sLoPath, pLayout ) ); + } + // style + OUString sQsPath = getFragmentPathFromRelId( msQs ); + if( sQsPath.getLength() > 0 ) + { + DiagramQStylesPtr pStyles( new DiagramQStyles() ); + pDiagram->setQStyles( pStyles ); + rFilter.importFragment( new DiagramQStylesFragmentHandler( rFilter, sQsPath, pStyles ) ); + } + // colors + OUString sCsPath = getFragmentPathFromRelId( msCs ); + if( sCsPath.getLength() > 0 ) + { + DiagramColorsPtr pColors( new DiagramColors() ); + pDiagram->setColors( pColors ); + rFilter.importFragment( new DiagramColorsFragmentHandler( rFilter, sCsPath, pColors ) ) ; + } + + return pDiagram; +} + + +Reference< XFastContextHandler > DiagramGraphicDataContext::createFastChildContext( ::sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case DGM_TOKEN( relIds ): + { + msDm = xAttribs->getOptionalValue( R_TOKEN( dm ) ); + msLo = xAttribs->getOptionalValue( R_TOKEN( lo ) ); + msQs = xAttribs->getOptionalValue( R_TOKEN( qs ) ); + msCs = xAttribs->getOptionalValue( R_TOKEN( cs ) ); + DiagramPtr pDiagram = loadDiagram(); + pDiagram->addTo( mpShapePtr ); + OSL_TRACE("diagram added shape %s of type %s", OUSTRING_TO_CSTR( mpShapePtr->getName() ), + OUSTRING_TO_CSTR( mpShapePtr->getServiceName() ) ); + break; + } + default: + break; + } + + if( !xRet.is() ) + xRet.set( ShapeContext::createFastChildContext( aElementToken, xAttribs ) ); + + return xRet; +} + +// ============================================================================ + +ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler& rParent, const ShapePtr& rxShape, bool bEmbedShapes ) : + ShapeContext( rParent, ShapePtr(), rxShape ), + mrChartShapeInfo( rxShape->setChartType( bEmbedShapes ) ) +{ +} + +Reference< XFastContextHandler > ChartGraphicDataContext::createFastChildContext( ::sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) + throw (SAXException, RuntimeException) +{ + if( nElement == C_TOKEN( chart ) ) + { + AttributeList aAttribs( rxAttribs ); + mrChartShapeInfo.maFragmentPath = getFragmentPathFromRelId( aAttribs.getString( R_TOKEN( id ), OUString() ) ); + } + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/guidcontext.cxx b/oox/source/drawingml/guidcontext.cxx new file mode 100644 index 000000000000..d5fbc10783ac --- /dev/null +++ b/oox/source/drawingml/guidcontext.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * 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/guidcontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +GuidContext::GuidContext( ContextHandler& rParent, rtl::OUString& rGuidId ) +: ContextHandler( rParent ) +, mrGuidId( rGuidId ) +{ +} +void GuidContext::characters( const OUString& aChars ) throw ( SAXException, RuntimeException ) +{ + mrGuidId += aChars; +} + +} } diff --git a/oox/source/drawingml/hyperlinkcontext.cxx b/oox/source/drawingml/hyperlinkcontext.cxx new file mode 100644 index 000000000000..2b2b1ee1cef6 --- /dev/null +++ b/oox/source/drawingml/hyperlinkcontext.cxx @@ -0,0 +1,176 @@ +/************************************************************************* + * + * 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 "hyperlinkcontext.hxx" + +#include <com/sun/star/xml/sax/XFastContextHandler.hpp> + +#include "oox/helper/propertymap.hxx" +#include "oox/core/relations.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/embeddedwavaudiofile.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { +namespace drawingml { + +HyperLinkContext::HyperLinkContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttributes, PropertyMap& aProperties ) + : ContextHandler( rParent ) + , maProperties(aProperties) +{ + OUString sURL, sHref; + OUString aRelId = xAttributes->getOptionalValue( R_TOKEN( id ) ); + if ( aRelId.getLength() ) + { + OSL_TRACE("OOX: URI rId %s", ::rtl::OUStringToOString (aRelId, RTL_TEXTENCODING_UTF8).pData->buffer); + sHref = getRelations().getExternalTargetFromRelId( aRelId ); + if( sHref.getLength() > 0 ) + { + OSL_TRACE("OOX: URI href %s", ::rtl::OUStringToOString (sHref, RTL_TEXTENCODING_UTF8).pData->buffer); + sURL = getFilter().getAbsoluteUrl( sHref ); + } + } + OUString sTooltip = xAttributes->getOptionalValue( R_TOKEN( tooltip ) ); + if ( sTooltip.getLength() ) + maProperties[ PROP_Representation ] <<= sTooltip; + OUString sFrame = xAttributes->getOptionalValue( R_TOKEN( tgtFrame ) ); + if( sFrame.getLength() ) + maProperties[ PROP_TargetFrame ] <<= sFrame; + OUString aAction = xAttributes->getOptionalValue( XML_action ); + if ( aAction.getLength() ) + { + // reserved values of the unrestricted string aAction: + // ppaction://customshow?id=SHOW_ID // custom presentation + // ppaction://hlinkfile // external file via r:id + // ppaction://hlinkpres?slideindex=SLIDE_NUM // external presentation via r:id + // ppaction://hlinkshowjump?jump=endshow + // ppaction://hlinkshowjump?jump=firstslide + // ppaction://hlinkshowjump?jump=lastslide + // ppaction://hlinkshowjump?jump=lastslideviewed + // ppaction://hlinkshowjump?jump=nextslide + // ppaction://hlinkshowjump?jump=previousslide + // ppaction://hlinksldjump + // ppaction://macro?name=MACRO_NAME + // ppaction://program + + const OUString sPPAction( CREATE_OUSTRING( "ppaction://" ) ); + if ( aAction.matchIgnoreAsciiCase( sPPAction, 0 ) ) + { + OUString aPPAct( aAction.copy( sPPAction.getLength() ) ); + sal_Int32 nIndex = aPPAct.indexOf( '?', 0 ); + OUString aPPAction( nIndex > 0 ? aPPAct.copy( 0, nIndex ) : aPPAct ); + + const OUString sHlinkshowjump( CREATE_OUSTRING( "hlinkshowjump" ) ); + const OUString sHlinksldjump( CREATE_OUSTRING( "hlinksldjump" ) ); + if ( aPPAction.match( sHlinkshowjump ) ) + { + const OUString sJump( CREATE_OUSTRING( "jump=" ) ); + if ( aPPAct.match( sJump, nIndex + 1 ) ) + { + OUString aDestination( aPPAct.copy( nIndex + 1 + sJump.getLength() ) ); + sURL = sURL.concat( CREATE_OUSTRING( "#action?jump=" ) ); + sURL = sURL.concat( aDestination ); + } + } + else if ( aPPAction.match( sHlinksldjump ) ) + { + sURL = OUString(); + + sal_Int32 nIndex2 = 0; + while ( nIndex2 < sHref.getLength() ) + { + sal_Unicode nChar = sHref[ nIndex2 ]; + if ( ( nChar >= '0' ) && ( nChar <= '9' ) ) + break; + nIndex2++; + } + if ( nIndex2 && ( nIndex2 != sHref.getLength() ) ) + { + sal_Int32 nLength = 1; + while( ( nIndex2 + nLength ) < sHref.getLength() ) + { + sal_Unicode nChar = sHref[ nIndex2 + nLength ]; + if ( ( nChar < '0' ) || ( nChar > '9' ) ) + break; + nLength++; + } + sal_Int32 nPageNumber = sHref.copy( nIndex2, nLength ).toInt32(); + if ( nPageNumber ) + { + const OUString sSlide( CREATE_OUSTRING( "slide" ) ); + const OUString sNotesSlide( CREATE_OUSTRING( "notesSlide" ) ); + const OUString aSlideType( sHref.copy( 0, nIndex2 ) ); + if ( aSlideType.match( sSlide ) ) + sURL = CREATE_OUSTRING( "#Slide " ).concat( rtl::OUString::valueOf( nPageNumber ) ); + else if ( aSlideType.match( sNotesSlide ) ) + sURL = CREATE_OUSTRING( "#Notes " ).concat( rtl::OUString::valueOf( nPageNumber ) ); +// else: todo for other types such as notesMaster or slideMaster as they can't be referenced easily + } + } + } + } + } + if ( sURL.getLength() ) + maProperties[ PROP_URL ] <<= sURL; + + // TODO unhandled + // XML_invalidUrl + // XML_history + // XML_highlightClick + // XML_endSnd +} + +HyperLinkContext::~HyperLinkContext() +{ +} + +Reference< XFastContextHandler > HyperLinkContext::createFastChildContext( + ::sal_Int32 aElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case A_TOKEN( extLst ): + return xRet; + case A_TOKEN( snd ): + EmbeddedWAVAudioFile aAudio; + getEmbeddedWAVAudioFile( getRelations(), xAttribs, aAudio ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/hyperlinkcontext.hxx b/oox/source/drawingml/hyperlinkcontext.hxx new file mode 100644 index 000000000000..aa5b5f0a19ec --- /dev/null +++ b/oox/source/drawingml/hyperlinkcontext.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_HYPERLINKCONTEXT_HXX +#define OOX_DRAWINGML_HYPERLINKCONTEXT_HXX + +#include <com/sun/star/xml/sax/XFastAttributeList.hpp> +#include "oox/core/contexthandler.hxx" + +namespace oox { class PropertyMap; } + +namespace oox { +namespace drawingml { + +class HyperLinkContext : public ::oox::core::ContextHandler +{ +public: + HyperLinkContext( + ::oox::core::ContextHandler& rParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& xAttribs, + PropertyMap& aProperties ); + virtual ~HyperLinkContext(); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + PropertyMap& maProperties; +}; + +} // namespace drawingml +} // namespace oox + +#endif + diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx new file mode 100644 index 000000000000..2eb1ef8b4cdf --- /dev/null +++ b/oox/source/drawingml/lineproperties.cxx @@ -0,0 +1,477 @@ +/************************************************************************* + * + * 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/lineproperties.hxx" +#include <vector> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/drawing/FlagSequence.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineJoint.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/PointSequence.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/modelobjecthelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/token/tokens.hxx" + +using namespace ::com::sun::star::drawing; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::awt::Point; +using ::com::sun::star::container::XNameContainer; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +namespace { + +static const sal_Int32 spnDefaultLineIds[ LineId_END ] = +{ + PROP_LineStyle, + PROP_LineWidth, + PROP_LineColor, + PROP_LineTransparence, + PROP_LineDash, + PROP_LineJoint, + PROP_LineStartName, + PROP_LineStartWidth, + PROP_LineStartCenter, + PROP_LineEndName, + PROP_LineEndWidth, + PROP_LineEndCenter +}; + +// ---------------------------------------------------------------------------- + +void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen, + sal_Int16 nDashes, sal_Int32 nDashLen, sal_Int32 nDistance ) +{ + orLineDash.Dots = nDots; + orLineDash.DotLen = nDotLen; + orLineDash.Dashes = nDashes; + orLineDash.DashLen = nDashLen; + orLineDash.Distance = nDistance; +} + +/** Converts the specified preset dash to API dash. + + Line length and dot length are set relative to line width and have to be + multiplied by the actual line width after this function. + */ +void lclConvertPresetDash( LineDash& orLineDash, sal_Int32 nPresetDash ) +{ + switch( nPresetDash ) + { + case XML_dot: lclSetDashData( orLineDash, 1, 1, 0, 0, 3 ); break; + case XML_dash: lclSetDashData( orLineDash, 0, 0, 1, 4, 3 ); break; + case XML_dashDot: lclSetDashData( orLineDash, 1, 1, 1, 4, 3 ); break; + + case XML_lgDash: lclSetDashData( orLineDash, 0, 0, 1, 8, 3 ); break; + case XML_lgDashDot: lclSetDashData( orLineDash, 1, 1, 1, 8, 3 ); break; + case XML_lgDashDotDot: lclSetDashData( orLineDash, 2, 1, 1, 8, 3 ); break; + + case XML_sysDot: lclSetDashData( orLineDash, 1, 1, 0, 0, 1 ); break; + case XML_sysDash: lclSetDashData( orLineDash, 0, 0, 1, 3, 1 ); break; + case XML_sysDashDot: lclSetDashData( orLineDash, 1, 1, 1, 3, 1 ); break; + case XML_sysDashDotDot: lclSetDashData( orLineDash, 2, 1, 1, 3, 1 ); break; + + default: + OSL_ENSURE( false, "lclConvertPresetDash - unsupported preset dash" ); + lclSetDashData( orLineDash, 0, 0, 1, 4, 3 ); + } +} + +/** Converts the passed custom dash to API dash. + + Line length and dot length are set relative to line width and have to be + multiplied by the actual line width after this function. + */ +void lclConvertCustomDash( LineDash& orLineDash, const LineProperties::DashStopVector& rCustomDash ) +{ + if( rCustomDash.empty() ) + { + OSL_ENSURE( false, "lclConvertCustomDash - unexpected empty custom dash" ); + lclSetDashData( orLineDash, 0, 0, 1, 4, 3 ); + return; + } + + // count dashes and dots (stops equal or less than 2 are assumed to be dots) + sal_Int16 nDots = 0; + sal_Int32 nDotLen = 0; + sal_Int16 nDashes = 0; + sal_Int32 nDashLen = 0; + sal_Int32 nDistance = 0; + for( LineProperties::DashStopVector::const_iterator aIt = rCustomDash.begin(), aEnd = rCustomDash.end(); aIt != aEnd; ++aIt ) + { + if( aIt->first <= 2 ) + { + ++nDots; + nDotLen += aIt->first; + } + else + { + ++nDashes; + nDashLen += aIt->first; + } + nDistance += aIt->second; + } + orLineDash.DotLen = (nDots > 0) ? ::std::max< sal_Int32 >( nDotLen / nDots, 1 ) : 0; + orLineDash.Dots = nDots; + orLineDash.DashLen = (nDashes > 0) ? ::std::max< sal_Int32 >( nDashLen / nDashes, 1 ) : 0; + orLineDash.Dashes = nDashes; + orLineDash.Distance = ::std::max< sal_Int32 >( nDistance / rCustomDash.size(), 1 ); +} + +DashStyle lclGetDashStyle( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_rnd: return DashStyle_ROUNDRELATIVE; + case XML_sq: return DashStyle_RECTRELATIVE; + case XML_flat: return DashStyle_RECT; + } + return DashStyle_ROUNDRELATIVE; +} + +LineJoint lclGetLineJoint( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_round: return LineJoint_ROUND; + case XML_bevel: return LineJoint_BEVEL; + case XML_miter: return LineJoint_MITER; + } + return LineJoint_ROUND; +} + +const sal_Int32 OOX_ARROWSIZE_SMALL = 0; +const sal_Int32 OOX_ARROWSIZE_MEDIUM = 1; +const sal_Int32 OOX_ARROWSIZE_LARGE = 2; + +sal_Int32 lclGetArrowSize( sal_Int32 nToken ) +{ + switch( nToken ) + { + case XML_sm: return OOX_ARROWSIZE_SMALL; + case XML_med: return OOX_ARROWSIZE_MEDIUM; + case XML_lg: return OOX_ARROWSIZE_LARGE; + } + return OOX_ARROWSIZE_MEDIUM; +} + +// ---------------------------------------------------------------------------- + +void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& rArrowProps, + ModelObjectHelper& rModelObjHelper, const LinePropertyIds& rPropIds, sal_Int32 nLineWidth, bool bLineEnd ) +{ + PolyPolygonBezierCoords aMarker; + OUString aMarkerName; + sal_Int32 nMarkerWidth = 0; + bool bMarkerCenter = false; + + OUStringBuffer aBuffer; + sal_Int32 nArrowType = rArrowProps.moArrowType.get( XML_none ); + switch( nArrowType ) + { + case XML_triangle: + aBuffer.append( CREATE_OUSTRING( "msArrowEnd" ) ); + break; + case XML_arrow: + aBuffer.append( CREATE_OUSTRING( "msArrowOpenEnd" ) ); + break; + case XML_stealth: + aBuffer.append( CREATE_OUSTRING( "msArrowStealthEnd" ) ); + break; + case XML_diamond: + aBuffer.append( CREATE_OUSTRING( "msArrowDiamondEnd" ) ); + bMarkerCenter = true; + break; + case XML_oval: + aBuffer.append( CREATE_OUSTRING( "msArrowOvalEnd" ) ); + bMarkerCenter = true; + break; + } + + if( aBuffer.getLength() > 0 ) + { + sal_Int32 nLength = lclGetArrowSize( rArrowProps.moArrowLength.get( XML_med ) ); + sal_Int32 nWidth = lclGetArrowSize( rArrowProps.moArrowWidth.get( XML_med ) ); + + sal_Int32 nNameIndex = nWidth * 3 + nLength + 1; + aBuffer.append( sal_Unicode( ' ' ) ).append( nNameIndex ); + aMarkerName = aBuffer.makeStringAndClear(); + + bool bIsArrow = nArrowType == XML_arrow; + double fArrowLength = 1.0; + switch( nLength ) + { + case OOX_ARROWSIZE_SMALL: fArrowLength = (bIsArrow ? 3.5 : 2.0); break; + case OOX_ARROWSIZE_MEDIUM: fArrowLength = (bIsArrow ? 4.5 : 3.0); break; + case OOX_ARROWSIZE_LARGE: fArrowLength = (bIsArrow ? 6.0 : 5.0); break; + } + double fArrowWidth = 1.0; + switch( nWidth ) + { + case OOX_ARROWSIZE_SMALL: fArrowWidth = (bIsArrow ? 3.5 : 2.0); break; + case OOX_ARROWSIZE_MEDIUM: fArrowWidth = (bIsArrow ? 4.5 : 3.0); break; + case OOX_ARROWSIZE_LARGE: fArrowWidth = (bIsArrow ? 6.0 : 5.0); break; + } + // set arrow width relative to line width (convert line width from EMUs to 1/100 mm) + sal_Int32 nApiLineWidth = ::std::max< sal_Int32 >( GetCoordinate( nLineWidth ), 70 ); + nMarkerWidth = static_cast< sal_Int32 >( fArrowWidth * nApiLineWidth ); + + // test if the arrow already exists, do not create it again in this case + if( !rPropIds.mbNamedLineMarker || !rModelObjHelper.hasLineMarker( aMarkerName ) ) + { +// pass X and Y as percentage to OOX_ARROW_POINT +#define OOX_ARROW_POINT( x, y ) Point( static_cast< sal_Int32 >( fArrowWidth * x ), static_cast< sal_Int32 >( fArrowLength * y ) ) + + ::std::vector< Point > aPoints; + switch( rArrowProps.moArrowType.get() ) + { + case XML_triangle: + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + break; + case XML_arrow: + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + aPoints.push_back( OOX_ARROW_POINT( 100, 91 ) ); + aPoints.push_back( OOX_ARROW_POINT( 85, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 36 ) ); + aPoints.push_back( OOX_ARROW_POINT( 15, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 0, 91 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + break; + case XML_stealth: + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + aPoints.push_back( OOX_ARROW_POINT( 100, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 60 ) ); + aPoints.push_back( OOX_ARROW_POINT( 0, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + break; + case XML_diamond: + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + break; + case XML_oval: + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + aPoints.push_back( OOX_ARROW_POINT( 75, 7 ) ); + aPoints.push_back( OOX_ARROW_POINT( 93, 25 ) ); + aPoints.push_back( OOX_ARROW_POINT( 100, 50 ) ); + aPoints.push_back( OOX_ARROW_POINT( 93, 75 ) ); + aPoints.push_back( OOX_ARROW_POINT( 75, 93 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 100 ) ); + aPoints.push_back( OOX_ARROW_POINT( 25, 93 ) ); + aPoints.push_back( OOX_ARROW_POINT( 7, 75 ) ); + aPoints.push_back( OOX_ARROW_POINT( 0, 50 ) ); + aPoints.push_back( OOX_ARROW_POINT( 7, 25 ) ); + aPoints.push_back( OOX_ARROW_POINT( 25, 7 ) ); + aPoints.push_back( OOX_ARROW_POINT( 50, 0 ) ); + break; + } +#undef OOX_ARROW_POINT + + OSL_ENSURE( !aPoints.empty(), "ApiLineMarkerProperties::ApiLineMarkerProperties - missing arrow coordinates" ); + if( !aPoints.empty() ) + { + aMarker.Coordinates.realloc( 1 ); + aMarker.Coordinates[ 0 ] = ContainerHelper::vectorToSequence( aPoints ); + + ::std::vector< PolygonFlags > aFlags( aPoints.size(), PolygonFlags_NORMAL ); + aMarker.Flags.realloc( 1 ); + aMarker.Flags[ 0 ] = ContainerHelper::vectorToSequence( aFlags ); + + if( rPropIds.mbNamedLineMarker && !rModelObjHelper.insertLineMarker( aMarkerName, aMarker ) ) + aMarkerName = OUString(); + } + else + { + aMarkerName = OUString(); + } + } + } + + // push the properties (filled aMarkerName indicates valid marker) + if( aMarkerName.getLength() > 0 ) + { + if( bLineEnd ) + { + if( rPropIds.mbNamedLineMarker ) + rPropMap.setProperty( rPropIds[ LineEndId ], aMarkerName ); + else + rPropMap.setProperty( rPropIds[ LineEndId ], aMarker ); + rPropMap.setProperty( rPropIds[ LineEndWidthId ], nMarkerWidth ); + rPropMap.setProperty( rPropIds[ LineEndCenterId ], bMarkerCenter ); + } + else + { + if( rPropIds.mbNamedLineMarker ) + rPropMap.setProperty( rPropIds[ LineStartId ], aMarkerName ); + else + rPropMap.setProperty( rPropIds[ LineStartId ], aMarker ); + rPropMap.setProperty( rPropIds[ LineStartWidthId ], nMarkerWidth ); + rPropMap.setProperty( rPropIds[ LineStartCenterId ], bMarkerCenter ); + } + } +} + +} // namespace + +// ============================================================================ + +LinePropertyIds::LinePropertyIds( const sal_Int32* pnPropertyIds, bool bNamedLineDash, bool bNamedLineMarker ) : + mpnPropertyIds( pnPropertyIds ), + mbNamedLineDash( bNamedLineDash ), + mbNamedLineMarker( bNamedLineMarker ) +{ + OSL_ENSURE( mpnPropertyIds != 0, "LinePropertyIds::LinePropertyIds - missing property identifiers" ); +} + +// ============================================================================ + +void LineArrowProperties::assignUsed( const LineArrowProperties& rSourceProps ) +{ + moArrowType.assignIfUsed( rSourceProps.moArrowType ); + moArrowWidth.assignIfUsed( rSourceProps.moArrowWidth ); + moArrowLength.assignIfUsed( rSourceProps.moArrowLength ); +} + +// ============================================================================ + +LinePropertyIds LineProperties::DEFAULT_IDS( spnDefaultLineIds, false, true ); + +void LineProperties::assignUsed( const LineProperties& rSourceProps ) +{ + maStartArrow.assignUsed( rSourceProps.maStartArrow ); + maEndArrow.assignUsed( rSourceProps.maEndArrow ); + maLineFill.assignUsed( rSourceProps.maLineFill ); + if( !rSourceProps.maCustomDash.empty() ) + maCustomDash = rSourceProps.maCustomDash; + moLineWidth.assignIfUsed( rSourceProps.moLineWidth ); + moPresetDash.assignIfUsed( rSourceProps.moPresetDash ); + moLineCompound.assignIfUsed( rSourceProps.moLineCompound ); + moLineCap.assignIfUsed( rSourceProps.moLineCap ); + moLineJoint.assignIfUsed( rSourceProps.moLineJoint ); +} + +void LineProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rModelObjHelper, + const GraphicHelper& rGraphicHelper, const LinePropertyIds& rPropIds, sal_Int32 nPhClr ) const +{ + // line fill type must exist, otherwise ignore other properties + if( maLineFill.moFillType.has() ) + { + // line style (our core only supports none and solid) + LineStyle eLineStyle = (maLineFill.moFillType.get() == XML_noFill) ? LineStyle_NONE : LineStyle_SOLID; + + // create line dash from preset dash token (not for invisible line) + if( (eLineStyle != LineStyle_NONE) && (moPresetDash.differsFrom( XML_solid ) || (!moPresetDash && !maCustomDash.empty())) ) + { + LineDash aLineDash; + aLineDash.Style = lclGetDashStyle( moLineCap.get( XML_rnd ) ); + + // convert preset dash or custom dash + if( moPresetDash.has() ) + lclConvertPresetDash( aLineDash, moPresetDash.get() ); + else + lclConvertCustomDash( aLineDash, maCustomDash ); + + // convert relative dash/dot length to absolute length + sal_Int32 nLineWidth = GetCoordinate( moLineWidth.get( 103500 ) ); + aLineDash.DotLen *= nLineWidth; + aLineDash.DashLen *= nLineWidth; + aLineDash.Distance *= nLineWidth; + + if( rPropIds.mbNamedLineDash ) + { + OUString aDashName = rModelObjHelper.insertLineDash( aLineDash ); + if( aDashName.getLength() > 0 ) + { + rPropMap.setProperty( rPropIds[ LineDashId ], aDashName ); + eLineStyle = LineStyle_DASH; + } + } + else + { + rPropMap.setProperty( rPropIds[ LineDashId ], aLineDash ); + eLineStyle = LineStyle_DASH; + } + } + + // set final line style property + rPropMap.setProperty( rPropIds[ LineStyleId ], eLineStyle ); + + // line joint type + if( moLineJoint.has() ) + rPropMap.setProperty( rPropIds[ LineJointId ], lclGetLineJoint( moLineJoint.get() ) ); + + // convert line width from EMUs to 1/100 mm + if( moLineWidth.has() ) + rPropMap.setProperty( rPropIds[ LineWidthId ], GetCoordinate( moLineWidth.get() ) ); + + // line color and transparence + Color aLineColor = maLineFill.getBestSolidColor(); + if( aLineColor.isUsed() ) + { + rPropMap.setProperty( rPropIds[ LineColorId ], aLineColor.getColor( rGraphicHelper, nPhClr ) ); + if( aLineColor.hasTransparence() ) + rPropMap.setProperty( rPropIds[ LineTransparenceId ], aLineColor.getTransparence() ); + } + + // line markers + lclPushMarkerProperties( rPropMap, maStartArrow, rModelObjHelper, rPropIds, moLineWidth.get( 0 ), false ); + lclPushMarkerProperties( rPropMap, maEndArrow, rModelObjHelper, rPropIds, moLineWidth.get( 0 ), true ); + } +} + +void LineProperties::pushToPropSet( PropertySet& rPropSet, ModelObjectHelper& rModelObjHelper, + const GraphicHelper& rGraphicHelper, const LinePropertyIds& rPropIds, sal_Int32 nPhClr ) const +{ + PropertyMap aPropMap; + pushToPropMap( aPropMap, rModelObjHelper, rGraphicHelper, rPropIds, nPhClr ); + rPropSet.setProperties( aPropMap ); +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/linepropertiescontext.cxx b/oox/source/drawingml/linepropertiescontext.cxx new file mode 100644 index 000000000000..a200b60f9e4b --- /dev/null +++ b/oox/source/drawingml/linepropertiescontext.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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/linepropertiescontext.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +// CT_LineProperties + +namespace oox { namespace drawingml { +// --------------------------------------------------------------------- + +LinePropertiesContext::LinePropertiesContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, + LineProperties& rLineProperties ) throw() +: ContextHandler( rParent ) +, mrLineProperties( rLineProperties ) +{ + AttributeList aAttribs( xAttribs ); + mrLineProperties.moLineWidth = aAttribs.getInteger( XML_w ); + mrLineProperties.moLineCompound = aAttribs.getToken( XML_cmpd ); + mrLineProperties.moLineCap = aAttribs.getToken( XML_cap ); +} + +LinePropertiesContext::~LinePropertiesContext() +{ +} + +Reference< XFastContextHandler > LinePropertiesContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); + switch( nElement ) + { + // LineFillPropertiesGroup + case A_TOKEN( noFill ): + case A_TOKEN( solidFill ): + case A_TOKEN( gradFill ): + case A_TOKEN( pattFill ): + xRet = FillPropertiesContext::createFillContext( *this, nElement, xAttribs, mrLineProperties.maLineFill ); + break; + + // LineDashPropertiesGroup + case A_TOKEN( prstDash ): // CT_PresetLineDashProperties + mrLineProperties.moPresetDash = aAttribs.getToken( XML_val ); + break; + case A_TOKEN( custDash ): // CT_DashStopList + xRet = this; + break; + case A_TOKEN( ds ): + mrLineProperties.maCustomDash.push_back( LineProperties::DashStop( + aAttribs.getInteger( XML_d, 0 ), aAttribs.getInteger( XML_sp, 0 ) ) ); + break; + + // LineJoinPropertiesGroup + case A_TOKEN( round ): + case A_TOKEN( bevel ): + case A_TOKEN( miter ): + mrLineProperties.moLineJoint = getBaseToken( nElement ); + break; + + case A_TOKEN( headEnd ): // CT_LineEndProperties + case A_TOKEN( tailEnd ): // CT_LineEndProperties + { // ST_LineEndType + bool bTailEnd = nElement == A_TOKEN( tailEnd ); + LineArrowProperties& rArrowProps = bTailEnd ? mrLineProperties.maEndArrow : mrLineProperties.maStartArrow; + rArrowProps.moArrowType = aAttribs.getToken( XML_type ); + rArrowProps.moArrowWidth = aAttribs.getToken( XML_w ); + rArrowProps.moArrowLength = aAttribs.getToken( XML_len ); + } + break; + } + return xRet; +} + +} } diff --git a/oox/source/drawingml/makefile.mk b/oox/source/drawingml/makefile.mk new file mode 100644 index 000000000000..e2d4ea6b8f3d --- /dev/null +++ b/oox/source/drawingml/makefile.mk @@ -0,0 +1,91 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=oox +TARGET=drawingml +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/clrscheme.obj\ + $(SLO)$/clrschemecontext.obj\ + $(SLO)$/color.obj\ + $(SLO)$/colorchoicecontext.obj\ + $(SLO)$/connectorshapecontext.obj\ + $(SLO)$/customshapegeometry.obj\ + $(SLO)$/customshapeproperties.obj\ + $(SLO)$/drawingmltypes.obj\ + $(SLO)$/embeddedwavaudiofile.obj\ + $(SLO)$/fillproperties.obj\ + $(SLO)$/fillpropertiesgroupcontext.obj\ + $(SLO)$/graphicshapecontext.obj\ + $(SLO)$/guidcontext.obj\ + $(SLO)$/hyperlinkcontext.obj\ + $(SLO)$/lineproperties.obj\ + $(SLO)$/linepropertiescontext.obj\ + $(SLO)$/objectdefaultcontext.obj\ + $(SLO)$/shape.obj\ + $(SLO)$/shapecontext.obj\ + $(SLO)$/shapegroupcontext.obj\ + $(SLO)$/shapepropertiescontext.obj\ + $(SLO)$/shapestylecontext.obj\ + $(SLO)$/spdefcontext.obj\ + $(SLO)$/textbody.obj\ + $(SLO)$/textbodycontext.obj\ + $(SLO)$/textbodyproperties.obj\ + $(SLO)$/textbodypropertiescontext.obj\ + $(SLO)$/textcharacterproperties.obj\ + $(SLO)$/textcharacterpropertiescontext.obj\ + $(SLO)$/textfield.obj\ + $(SLO)$/textfieldcontext.obj\ + $(SLO)$/textfont.obj\ + $(SLO)$/textliststyle.obj \ + $(SLO)$/textliststylecontext.obj\ + $(SLO)$/textparagraph.obj\ + $(SLO)$/textparagraphproperties.obj\ + $(SLO)$/textparagraphpropertiescontext.obj\ + $(SLO)$/textrun.obj\ + $(SLO)$/textspacingcontext.obj\ + $(SLO)$/texttabstoplistcontext.obj\ + $(SLO)$/theme.obj\ + $(SLO)$/themeelementscontext.obj\ + $(SLO)$/themefragmenthandler.obj\ + $(SLO)$/transform2dcontext.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/objectdefaultcontext.cxx b/oox/source/drawingml/objectdefaultcontext.cxx new file mode 100644 index 000000000000..d233379f9b02 --- /dev/null +++ b/oox/source/drawingml/objectdefaultcontext.cxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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/objectdefaultcontext.hxx" +#include "oox/drawingml/spdefcontext.hxx" +#include "oox/drawingml/theme.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +objectDefaultContext::objectDefaultContext( ContextHandler& rParent, Theme& rTheme ) +: ContextHandler( rParent ) +, mrTheme( rTheme ) +{ +} + +Reference< XFastContextHandler > objectDefaultContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /* xAttribs */ ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case A_TOKEN( spDef ): + return new spDefContext( *this, mrTheme.getSpDef() ); + case A_TOKEN( lnDef ): + return new spDefContext( *this, mrTheme.getLnDef() ); + case A_TOKEN( txDef ): + return new spDefContext( *this, mrTheme.getTxDef() ); + } + return 0; +} + +} } diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx new file mode 100644 index 000000000000..61956c068deb --- /dev/null +++ b/oox/source/drawingml/shape.cxx @@ -0,0 +1,624 @@ +/************************************************************************* + * + * 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/shape.hxx" +#include "oox/drawingml/customshapeproperties.hxx" +#include "oox/drawingml/theme.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/textbody.hxx" +#include "oox/drawingml/table/tableproperties.hxx" +#include "oox/drawingml/chart/chartconverter.hxx" +#include "oox/drawingml/chart/chartspacefragment.hxx" +#include "oox/drawingml/chart/chartspacemodel.hxx" +#include "oox/vml/vmldrawing.hxx" +#include "oox/vml/vmlshape.hxx" +#include "oox/vml/vmlshapecontainer.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/graphichelper.hxx" +#include "oox/helper/propertyset.hxx" + +#include <tools/solar.h> // for the F_PI180 define +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/drawing/HomogenMatrix3.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <com/sun/star/document/XActionLockable.hpp> + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::drawing; + +namespace oox { namespace drawingml { + +// ============================================================================ + +Shape::Shape( const sal_Char* pServiceName ) +: mpLinePropertiesPtr( new LineProperties ) +, mpFillPropertiesPtr( new FillProperties ) +, mpGraphicPropertiesPtr( new GraphicProperties ) +, mpCustomShapePropertiesPtr( new CustomShapeProperties ) +, mpMasterTextListStyle( new TextListStyle ) +, mnSubType( 0 ) +, mnSubTypeIndex( -1 ) +, meFrameType( FRAMETYPE_GENERIC ) +, mnRotation( 0 ) +, mbFlipH( false ) +, mbFlipV( false ) +, mbHidden( false ) +{ + if ( pServiceName ) + msServiceName = OUString::createFromAscii( pServiceName ); + setDefaults(); +} + +Shape::~Shape() +{ +} + +table::TablePropertiesPtr Shape::getTableProperties() +{ + if ( !mpTablePropertiesPtr.get() ) + mpTablePropertiesPtr.reset( new table::TableProperties() ); + return mpTablePropertiesPtr; +} + +void Shape::setDefaults() +{ + maShapeProperties[ PROP_TextAutoGrowHeight ] <<= false; + maShapeProperties[ PROP_TextWordWrap ] <<= true; + maShapeProperties[ PROP_TextLeftDistance ] <<= static_cast< sal_Int32 >( 250 ); + maShapeProperties[ PROP_TextUpperDistance ] <<= static_cast< sal_Int32 >( 125 ); + maShapeProperties[ PROP_TextRightDistance ] <<= static_cast< sal_Int32 >( 250 ); + maShapeProperties[ PROP_TextLowerDistance ] <<= static_cast< sal_Int32 >( 125 ); + maShapeProperties[ PROP_CharHeight ] <<= static_cast< float >( 18.0 ); +} + +::oox::vml::OleObjectInfo& Shape::setOleObjectType() +{ + OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setOleObjectType - multiple frame types" ); + meFrameType = FRAMETYPE_OLEOBJECT; + mxOleObjectInfo.reset( new ::oox::vml::OleObjectInfo( true ) ); + return *mxOleObjectInfo; +} + +ChartShapeInfo& Shape::setChartType( bool bEmbedShapes ) +{ + OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setChartType - multiple frame types" ); + meFrameType = FRAMETYPE_CHART; + msServiceName = CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ); + mxChartShapeInfo.reset( new ChartShapeInfo( bEmbedShapes ) ); + return *mxChartShapeInfo; +} + +void Shape::setDiagramType() +{ + OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setDiagramType - multiple frame types" ); + meFrameType = FRAMETYPE_DIAGRAM; + msServiceName = CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ); + mnSubType = 0; +} + +void Shape::setTableType() +{ + OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setTableType - multiple frame types" ); + meFrameType = FRAMETYPE_TABLE; + msServiceName = CREATE_OUSTRING( "com.sun.star.drawing.TableShape" ); + mnSubType = 0; +} + +void Shape::setServiceName( const sal_Char* pServiceName ) +{ + if ( pServiceName ) + msServiceName = OUString::createFromAscii( pServiceName ); +} + + +const ShapeStyleRef* Shape::getShapeStyleRef( sal_Int32 nRefType ) const +{ + ShapeStyleRefMap::const_iterator aIt = maShapeStyleRefs.find( nRefType ); + return (aIt == maShapeStyleRefs.end()) ? 0 : &aIt->second; +} + +void Shape::addShape( + ::oox::core::XmlFilterBase& rFilterBase, + const Theme* pTheme, + const Reference< XShapes >& rxShapes, + const awt::Rectangle* pShapeRect, + ShapeIdMap* pShapeMap ) +{ + try + { + rtl::OUString sServiceName( msServiceName ); + if( sServiceName.getLength() ) + { + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, pShapeRect, sal_False ) ); + + if( pShapeMap && msId.getLength() ) + { + (*pShapeMap)[ msId ] = shared_from_this(); + } + + // if this is a group shape, we have to add also each child shape + Reference< XShapes > xShapes( xShape, UNO_QUERY ); + if ( xShapes.is() ) + addChildren( rFilterBase, *this, pTheme, xShapes, pShapeRect ? *pShapeRect : awt::Rectangle( maPosition.X, maPosition.Y, maSize.Width, maSize.Height ), pShapeMap ); + } + Reference< document::XActionLockable > xLockable( mxShape, UNO_QUERY ); + if( xLockable.is() ) + xLockable->removeActionLock(); + } + catch( const Exception& ) + { + } +} + +void Shape::applyShapeReference( const Shape& rReferencedShape ) +{ + mpTextBody = TextBodyPtr( new TextBody( *rReferencedShape.mpTextBody.get() ) ); + maShapeProperties = rReferencedShape.maShapeProperties; + mpLinePropertiesPtr = LinePropertiesPtr( new LineProperties( *rReferencedShape.mpLinePropertiesPtr.get() ) ); + mpFillPropertiesPtr = FillPropertiesPtr( new FillProperties( *rReferencedShape.mpFillPropertiesPtr.get() ) ); + mpCustomShapePropertiesPtr = CustomShapePropertiesPtr( new CustomShapeProperties( *rReferencedShape.mpCustomShapePropertiesPtr.get() ) ); + mpTablePropertiesPtr = table::TablePropertiesPtr( rReferencedShape.mpTablePropertiesPtr.get() ? new table::TableProperties( *rReferencedShape.mpTablePropertiesPtr.get() ) : NULL ); + mpMasterTextListStyle = TextListStylePtr( new TextListStyle( *rReferencedShape.mpMasterTextListStyle.get() ) ); + maShapeStyleRefs = rReferencedShape.maShapeStyleRefs; + maSize = rReferencedShape.maSize; + maPosition = rReferencedShape.maPosition; + mnRotation = rReferencedShape.mnRotation; + mbFlipH = rReferencedShape.mbFlipH; + mbFlipV = rReferencedShape.mbFlipV; + mbHidden = rReferencedShape.mbHidden; +} + +// for group shapes, the following method is also adding each child +void Shape::addChildren( + XmlFilterBase& rFilterBase, + Shape& rMaster, + const Theme* pTheme, + const Reference< XShapes >& rxShapes, + const awt::Rectangle& rClientRect, + ShapeIdMap* pShapeMap ) +{ + // first the global child union needs to be calculated + sal_Int32 nGlobalLeft = SAL_MAX_INT32; + sal_Int32 nGlobalRight = SAL_MIN_INT32; + sal_Int32 nGlobalTop = SAL_MAX_INT32; + sal_Int32 nGlobalBottom= SAL_MIN_INT32; + std::vector< ShapePtr >::iterator aIter( rMaster.maChildren.begin() ); + while( aIter != rMaster.maChildren.end() ) + { + sal_Int32 l = (*aIter)->maPosition.X; + sal_Int32 t = (*aIter)->maPosition.Y; + sal_Int32 r = l + (*aIter)->maSize.Width; + sal_Int32 b = t + (*aIter)->maSize.Height; + if ( nGlobalLeft > l ) + nGlobalLeft = l; + if ( nGlobalRight < r ) + nGlobalRight = r; + if ( nGlobalTop > t ) + nGlobalTop = t; + if ( nGlobalBottom < b ) + nGlobalBottom = b; + aIter++; + } + aIter = rMaster.maChildren.begin(); + while( aIter != rMaster.maChildren.end() ) + { + awt::Rectangle aShapeRect; + awt::Rectangle* pShapeRect = 0; + if ( ( nGlobalLeft != SAL_MAX_INT32 ) && ( nGlobalRight != SAL_MIN_INT32 ) && ( nGlobalTop != SAL_MAX_INT32 ) && ( nGlobalBottom != SAL_MIN_INT32 ) ) + { + sal_Int32 nGlobalWidth = nGlobalRight - nGlobalLeft; + sal_Int32 nGlobalHeight = nGlobalBottom - nGlobalTop; + if ( nGlobalWidth && nGlobalHeight ) + { + double fWidth = (*aIter)->maSize.Width; + double fHeight= (*aIter)->maSize.Height; + double fXScale = (double)rClientRect.Width / (double)nGlobalWidth; + double fYScale = (double)rClientRect.Height / (double)nGlobalHeight; + aShapeRect.X = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.X - nGlobalLeft ) * fXScale ) + rClientRect.X ); + aShapeRect.Y = static_cast< sal_Int32 >( ( ( (*aIter)->maPosition.Y - nGlobalTop ) * fYScale ) + rClientRect.Y ); + fWidth *= fXScale; + fHeight *= fYScale; + aShapeRect.Width = static_cast< sal_Int32 >( fWidth ); + aShapeRect.Height = static_cast< sal_Int32 >( fHeight ); + pShapeRect = &aShapeRect; + } + } + (*aIter++)->addShape( rFilterBase, pTheme, rxShapes, pShapeRect, pShapeMap ); + } +} + +Reference< XShape > Shape::createAndInsert( + ::oox::core::XmlFilterBase& rFilterBase, + const rtl::OUString& rServiceName, + const Theme* pTheme, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const awt::Rectangle* pShapeRect, + sal_Bool bClearText ) +{ + awt::Size aSize( pShapeRect ? awt::Size( pShapeRect->Width, pShapeRect->Height ) : maSize ); + awt::Point aPosition( pShapeRect ? awt::Point( pShapeRect->X, pShapeRect->Y ) : maPosition ); + awt::Rectangle aShapeRectHmm( aPosition.X / 360, aPosition.Y / 360, aSize.Width / 360, aSize.Height / 360 ); + + OUString aServiceName = finalizeServiceName( rFilterBase, rServiceName, aShapeRectHmm ); + sal_Bool bIsCustomShape = aServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.CustomShape" ) ); + + basegfx::B2DHomMatrix aTransformation; + if( aSize.Width != 1 || aSize.Height != 1) + { + // take care there are no zeros used by error + aTransformation.scale( + aSize.Width ? aSize.Width / 360.0 : 1.0, + aSize.Height ? aSize.Height / 360.0 : 1.0 ); + } + + if( mbFlipH || mbFlipV || mnRotation != 0) + { + // calculate object's center + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= aTransformation; + + // center object at origin + aTransformation.translate( -aCenter.getX(), -aCenter.getY() ); + + if( !bIsCustomShape && ( mbFlipH || mbFlipV ) ) + { + // mirror around object's center + aTransformation.scale( mbFlipH ? -1.0 : 1.0, mbFlipV ? -1.0 : 1.0 ); + } + + if( mnRotation != 0 ) + { + // rotate around object's center + aTransformation.rotate( F_PI180 * ( (double)mnRotation / 60000.0 ) ); + } + + // move object back from center + aTransformation.translate( aCenter.getX(), aCenter.getY() ); + } + + if( aPosition.X != 0 || aPosition.Y != 0) + { + // if global position is used, add it to transformation + aTransformation.translate( aPosition.X / 360.0, aPosition.Y / 360.0 ); + } + + // special for lineshape + if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.LineShape" ) ) + { + ::basegfx::B2DPolygon aPoly; + aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); + aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); + aPoly.transform( aTransformation ); + + // now creating the corresponding PolyPolygon + sal_Int32 i, nNumPoints = aPoly.count(); + uno::Sequence< awt::Point > aPointSequence( nNumPoints ); + awt::Point* pPoints = aPointSequence.getArray(); + for( i = 0; i < nNumPoints; ++i ) + { + const ::basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) ); + pPoints[ i ] = awt::Point( static_cast< sal_Int32 >( aPoint.getX() ), static_cast< sal_Int32 >( aPoint.getY() ) ); + } + uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 ); + aPolyPolySequence.getArray()[ 0 ] = aPointSequence; + + maShapeProperties[ PROP_PolyPolygon ] <<= aPolyPolySequence; + } + else if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.ConnectorShape" ) ) + { + ::basegfx::B2DPolygon aPoly; + aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); + aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); + aPoly.transform( aTransformation ); + + basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) ); + basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) ); + awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) ); + awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) ); + + maShapeProperties[ PROP_StartPosition ] <<= aAWTStartPosition; + maShapeProperties[ PROP_EndPosition ] <<= aAWTEndPosition; + } + else + { + // now set transformation for this object + HomogenMatrix3 aMatrix; + + aMatrix.Line1.Column1 = aTransformation.get(0,0); + aMatrix.Line1.Column2 = aTransformation.get(0,1); + aMatrix.Line1.Column3 = aTransformation.get(0,2); + + aMatrix.Line2.Column1 = aTransformation.get(1,0); + aMatrix.Line2.Column2 = aTransformation.get(1,1); + aMatrix.Line2.Column3 = aTransformation.get(1,2); + + aMatrix.Line3.Column1 = aTransformation.get(2,0); + aMatrix.Line3.Column2 = aTransformation.get(2,1); + aMatrix.Line3.Column3 = aTransformation.get(2,2); + + maShapeProperties[ PROP_Transformation ] <<= aMatrix; + } + Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); + if ( !mxShape.is() ) + mxShape = Reference< drawing::XShape >( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW ); + + Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); + if( mxShape.is() && xSet.is() ) + { + if( msName.getLength() ) + { + Reference< container::XNamed > xNamed( mxShape, UNO_QUERY ); + if( xNamed.is() ) + xNamed->setName( msName ); + } + rxShapes->add( mxShape ); + + if ( mbHidden ) + { + const OUString sHidden( CREATE_OUSTRING( "Visible" ) ); + xSet->setPropertyValue( sHidden, Any( !mbHidden ) ); + } + + Reference< document::XActionLockable > xLockable( mxShape, UNO_QUERY ); + if( xLockable.is() ) + xLockable->addActionLock(); + + // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape + if ( bClearText ) + { + uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY ); + if ( xText.is() ) + { + OUString aEmpty; + xText->setString( aEmpty ); + } + } + + ModelObjectHelper& rModelObjectHelper = rFilterBase.getModelObjectHelper(); + const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper(); + + LineProperties aLineProperties; + aLineProperties.maLineFill.moFillType = XML_noFill; + sal_Int32 nLinePhClr = -1; + FillProperties aFillProperties; + aFillProperties.moFillType = XML_noFill; + sal_Int32 nFillPhClr = -1; + + if( pTheme ) + { + if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) ) + { + if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) ) + aLineProperties.assignUsed( *pLineProps ); + nLinePhClr = pLineRef->maPhClr.getColor( rGraphicHelper ); + } + if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) ) + { + if( const FillProperties* pFillProps = pTheme->getFillStyle( pFillRef->mnThemedIdx ) ) + aFillProperties.assignUsed( *pFillProps ); + nFillPhClr = pFillRef->maPhClr.getColor( rGraphicHelper ); + } +// if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_fillRef ) ) +// { +// if( const EffectProperties* pEffectProps = pTheme->getEffectStyle( pEffectRef->mnThemedIdx ) ) +// aEffectProperties.assignUsed( *pEffectProps ); +// nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper ); +// } + } + + aLineProperties.assignUsed( getLineProperties() ); + aFillProperties.assignUsed( getFillProperties() ); + + PropertyMap aShapeProperties; + PropertyMap::const_iterator aShapePropIter; + + // add properties from textbody to shape properties + if( mpTextBody.get() ) + { + for ( aShapePropIter = mpTextBody->getTextProperties().maPropertyMap.begin(); + aShapePropIter != mpTextBody->getTextProperties().maPropertyMap.end(); aShapePropIter++ ) + aShapeProperties[ (*aShapePropIter).first ] = (*aShapePropIter).second; + } + + aShapeProperties.insert( getShapeProperties().begin(), getShapeProperties().end() ); + // applying properties + PropertySet aPropSet( xSet ); + if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) + mpGraphicPropertiesPtr->pushToPropSet( aPropSet, rGraphicHelper ); + if ( mpTablePropertiesPtr.get() && ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.TableShape" ) ) ) + mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle ); + aFillProperties.pushToPropSet( aPropSet, rModelObjectHelper, rGraphicHelper, FillProperties::DEFAULT_IDS, mnRotation, nFillPhClr ); + aLineProperties.pushToPropSet( aPropSet, rModelObjectHelper, rGraphicHelper, LineProperties::DEFAULT_IDS, nLinePhClr ); + + // applying autogrowheight property before setting shape size, because + // the shape size might be changed if currently autogrowheight is true + // we must also check that the PropertySet supports the property. + Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); + const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight ); + if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) ) + if( /*const Any* pAutoGrowHeight =*/ aShapeProperties.getProperty( PROP_TextAutoGrowHeight ) ) + xSet->setPropertyValue( rPropName, Any( false ) ); + + // do not set properties at a group shape (this causes assertions from svx) + if( aServiceName != OUString::createFromAscii( "com.sun.star.drawing.GroupShape" ) ) + aPropSet.setProperties( aShapeProperties ); + + if( bIsCustomShape ) + { + if ( mbFlipH ) + mpCustomShapePropertiesPtr->setMirroredX( sal_True ); + if ( mbFlipV ) + mpCustomShapePropertiesPtr->setMirroredY( sal_True ); + mpCustomShapePropertiesPtr->pushToPropSet( rFilterBase, xSet, mxShape ); + } + + // in some cases, we don't have any text body. + if( getTextBody() ) + { + Reference < XText > xText( mxShape, UNO_QUERY ); + if ( xText.is() ) // not every shape is supporting an XText interface (e.g. GroupShape) + { + TextCharacterProperties aCharStyleProperties; + if( const ShapeStyleRef* pFontRef = getShapeStyleRef( XML_fontRef ) ) + { + if( pTheme ) + if( const TextCharacterProperties* pCharProps = pTheme->getFontStyle( pFontRef->mnThemedIdx ) ) + aCharStyleProperties.assignUsed( *pCharProps ); + aCharStyleProperties.maCharColor.assignIfUsed( pFontRef->maPhClr ); + } + + Reference < XTextCursor > xAt = xText->createTextCursor(); + getTextBody()->insertAt( rFilterBase, xText, xAt, aCharStyleProperties, mpMasterTextListStyle ); + } + } + if( xLockable.is() ) + xLockable->removeActionLock(); + } + + if( mxShape.is() ) + finalizeXShape( rFilterBase, rxShapes ); + + return mxShape; +} + +// the properties of rSource which are not part of rDest are being put into rDest +void addMissingProperties( const PropertyMap& rSource, PropertyMap& rDest ) +{ + PropertyMap::const_iterator aSourceIter( rSource.begin() ); + while( aSourceIter != rSource.end() ) + { + if ( rDest.find( (*aSourceIter ).first ) == rDest.end() ) + rDest[ (*aSourceIter).first ] <<= (*aSourceIter).second; + aSourceIter++; + } +} + +void Shape::setTextBody(const TextBodyPtr & pTextBody) +{ + mpTextBody = pTextBody; +} + + +TextBodyPtr Shape::getTextBody() +{ + return mpTextBody; +} + +void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle ) +{ + mpMasterTextListStyle = pMasterTextListStyle; +} + +OUString Shape::finalizeServiceName( XmlFilterBase& rFilter, const OUString& rServiceName, const Rectangle& rShapeRect ) +{ + OUString aServiceName = rServiceName; + switch( meFrameType ) + { + case FRAMETYPE_OLEOBJECT: + { + Size aOleSize( rShapeRect.Width, rShapeRect.Height ); + if( rFilter.getOleObjectHelper().importOleObject( maShapeProperties, *mxOleObjectInfo, aOleSize ) ) + aServiceName = CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ); + + // get the path to the representation graphic + OUString aGraphicPath; + if( mxOleObjectInfo->maShapeId.getLength() > 0 ) + if( ::oox::vml::Drawing* pVmlDrawing = rFilter.getVmlDrawing() ) + if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId, true ) ) + aGraphicPath = pVmlShape->getGraphicPath(); + + // import and store the graphic + if( aGraphicPath.getLength() > 0 ) + { + Reference< graphic::XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath ); + if( xGraphic.is() ) + maShapeProperties[ PROP_Graphic ] <<= xGraphic; + } + } + break; + + default:; + } + return aServiceName; +} + +void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes ) +{ + switch( meFrameType ) + { + case FRAMETYPE_CHART: + { + OSL_ENSURE( mxChartShapeInfo->maFragmentPath.getLength() > 0, "Shape::finalizeXShape - missing chart fragment" ); + if( mxShape.is() && (mxChartShapeInfo->maFragmentPath.getLength() > 0) ) try + { + // set the chart2 OLE class ID at the OLE shape + PropertySet aShapeProp( mxShape ); + aShapeProp.setProperty( PROP_CLSID, CREATE_OUSTRING( "12dcae26-281f-416f-a234-c3086127382e" ) ); + + // get the XModel interface of the embedded object from the OLE shape + Reference< frame::XModel > xDocModel; + aShapeProp.getProperty( xDocModel, PROP_Model ); + Reference< chart2::XChartDocument > xChartDoc( xDocModel, UNO_QUERY_THROW ); + + // load the chart data from the XML fragment + chart::ChartSpaceModel aModel; + rFilter.importFragment( new chart::ChartSpaceFragment( rFilter, mxChartShapeInfo->maFragmentPath, aModel ) ); + + // convert imported chart model to chart document + Reference< drawing::XShapes > xExternalPage; + if( !mxChartShapeInfo->mbEmbedShapes ) + xExternalPage = rxShapes; + rFilter.getChartConverter().convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() ); + } + catch( Exception& ) + { + } + } + break; + + default:; + } +} + +// ============================================================================ + +} } diff --git a/oox/source/drawingml/shapecontext.cxx b/oox/source/drawingml/shapecontext.cxx new file mode 100644 index 000000000000..d4781fdaa436 --- /dev/null +++ b/oox/source/drawingml/shapecontext.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * 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 <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNamed.hpp> + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/shapecontext.hxx" +#include "oox/drawingml/shapestylecontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// CT_Shape +ShapeContext::ShapeContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pShapePtr ) +: ContextHandler( rParent ) +, mpMasterShapePtr( pMasterShapePtr ) +, mpShapePtr( pShapePtr ) +{ +} + +ShapeContext::~ShapeContext() +{ + if ( mpMasterShapePtr.get() && mpShapePtr.get() ) + mpMasterShapePtr->addChild( mpShapePtr ); +} + +ShapePtr ShapeContext::getShape() +{ + return mpShapePtr; +} + +void ShapeContext::endFastElement( sal_Int32 /* aElementToken */ ) throw( SAXException, RuntimeException ) +{ +} + +Reference< XFastContextHandler > ShapeContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( getBaseToken( aElementToken ) ) + { + // nvSpPr CT_ShapeNonVisual begin +// case XML_drElemPr: +// break; + case XML_cNvPr: + { + AttributeList aAttribs( xAttribs ); + mpShapePtr->setHidden( aAttribs.getBool( XML_hidden, false ) ); + mpShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + } + case XML_ph: + mpShapePtr->setSubType( xAttribs->getOptionalValueToken( XML_type, XML_obj ) ); + mpShapePtr->setSubTypeIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + break; + // nvSpPr CT_ShapeNonVisual end + + case XML_spPr: + xRet = new ShapePropertiesContext( *this, *mpShapePtr ); + break; + + case XML_style: + xRet = new ShapeStyleContext( *this, *mpShapePtr ); + break; + + case XML_txBody: + { + TextBodyPtr xTextBody( new TextBody ); + mpShapePtr->setTextBody( xTextBody ); + xRet = new TextBodyContext( *this, *xTextBody ); + break; + } + } + + if( !xRet.is() ) + { + uno::Reference<XFastContextHandler> xTmp(this); + xRet.set( xTmp ); + } + + return xRet; +} + + +} } diff --git a/oox/source/drawingml/shapegroupcontext.cxx b/oox/source/drawingml/shapegroupcontext.cxx new file mode 100644 index 000000000000..183302667066 --- /dev/null +++ b/oox/source/drawingml/shapegroupcontext.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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 <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/drawingml/connectorshapecontext.hxx" +#include "oox/drawingml/graphicshapecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/customshapegeometry.hxx" +#include "oox/drawingml/textbodycontext.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +ShapeGroupContext::ShapeGroupContext( ContextHandler& rParent, ShapePtr pMasterShapePtr, ShapePtr pGroupShapePtr ) +: ContextHandler( rParent ) +, mpGroupShapePtr( pGroupShapePtr ) +, mpMasterShapePtr( pMasterShapePtr ) +{ +} + +ShapeGroupContext::~ShapeGroupContext() +{ + if ( mpMasterShapePtr.get() && mpGroupShapePtr.get() ) + mpMasterShapePtr->addChild( mpGroupShapePtr ); +} + +Reference< XFastContextHandler > ShapeGroupContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( getBaseToken( aElementToken ) ) + { + case XML_cNvPr: + { + AttributeList aAttribs( xAttribs ); + mpGroupShapePtr->setHidden( aAttribs.getBool( XML_hidden, false ) ); + mpGroupShapePtr->setId( xAttribs->getOptionalValue( XML_id ) ); + mpGroupShapePtr->setName( xAttribs->getOptionalValue( XML_name ) ); + break; + } + case XML_ph: + mpGroupShapePtr->setSubType( xAttribs->getOptionalValueToken( XML_type, FastToken::DONTKNOW ) ); + mpGroupShapePtr->setSubTypeIndex( xAttribs->getOptionalValue( XML_idx ).toInt32() ); + break; + // nvSpPr CT_ShapeNonVisual end + + case XML_grpSpPr: + xRet = new ShapePropertiesContext( *this, *mpGroupShapePtr ); + break; + case XML_spPr: + xRet = new ShapePropertiesContext( *this, *mpGroupShapePtr ); + break; +/* + case XML_style: + xRet = new ShapeStyleContext( getParser() ); + break; +*/ + case XML_cxnSp: // connector shape + xRet.set( new ConnectorShapeContext( *this, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.ConnectorShape" ) ) ) ); + break; + case XML_grpSp: // group shape + xRet.set( new ShapeGroupContext( *this, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.GroupShape" ) ) ) ); + break; + case XML_sp: // shape + xRet.set( new ShapeContext( *this, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.CustomShape" ) ) ) ); + break; + case XML_pic: // CT_Picture + xRet.set( new GraphicShapeContext( *this, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ) ) ); + break; + case XML_graphicFrame: // CT_GraphicalObjectFrame + xRet.set( new GraphicalObjectFrameContext( *this, mpGroupShapePtr, ShapePtr( new Shape( "com.sun.star.drawing.GraphicObjectShape" ) ), true ) ); + break; + } + if( !xRet.is() ) + xRet.set( this ); + + + return xRet; +} + +} } diff --git a/oox/source/drawingml/shapepropertiescontext.cxx b/oox/source/drawingml/shapepropertiescontext.cxx new file mode 100644 index 000000000000..13fd8c421784 --- /dev/null +++ b/oox/source/drawingml/shapepropertiescontext.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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/shapepropertiescontext.hxx" + +#include <com/sun/star/xml/sax/FastToken.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNamed.hpp> + +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/transform2dcontext.hxx" +#include "oox/drawingml/customshapegeometry.hxx" + +using rtl::OUString; +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// ==================================================================== + +// CT_ShapeProperties +ShapePropertiesContext::ShapePropertiesContext( ContextHandler& rParent, Shape& rShape ) +: ContextHandler( rParent ) +, mrShape( rShape ) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > ShapePropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + // CT_Transform2D + case A_TOKEN( xfrm ): + xRet.set( new Transform2DContext( *this, xAttribs, mrShape ) ); + break; + + // GeometryGroup + case A_TOKEN( custGeom ): // custom geometry "CT_CustomGeometry2D" + xRet.set( new CustomShapeGeometryContext( *this, xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + break; + + + case A_TOKEN( prstGeom ): // preset geometry "CT_PresetGeometry2D" + { + sal_Int32 nToken = xAttribs->getOptionalValueToken( XML_prst, 0 ); + if ( nToken == XML_line ) + { + static const OUString sLineShape( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.LineShape" ) ); + mrShape.getServiceName() = sLineShape; + } + xRet.set( new PresetShapeGeometryContext( *this, xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + } + break; + + case A_TOKEN( prstTxWarp ): + xRet.set( new PresetTextShapeContext( *this, xAttribs, *(mrShape.getCustomShapeProperties()) ) ); + break; + + // CT_LineProperties + case A_TOKEN( ln ): + xRet.set( new LinePropertiesContext( *this, xAttribs, mrShape.getLineProperties() ) ); + break; + + // EffectPropertiesGroup + // todo not supported by core + case A_TOKEN( effectLst ): // CT_EffectList + case A_TOKEN( effectDag ): // CT_EffectContainer + break; + + // todo + case A_TOKEN( scene3d ): // CT_Scene3D + case A_TOKEN( sp3d ): // CT_Shape3D + break; + } + + // FillPropertiesGroupContext + if( !xRet.is() ) + xRet.set( FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, mrShape.getFillProperties() ) ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/shapestylecontext.cxx b/oox/source/drawingml/shapestylecontext.cxx new file mode 100644 index 000000000000..a1ae5df43cda --- /dev/null +++ b/oox/source/drawingml/shapestylecontext.cxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * 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/shapestylecontext.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// --------------- +// CT_ShapeStyle +// --------------- +ShapeStyleContext::ShapeStyleContext( ContextHandler& rParent, Shape& rShape ) +: ContextHandler( rParent ) +, mrShape( rShape ) +{ +} + +ShapeStyleContext::~ShapeStyleContext() +{ +} + +// -------------------------------------------------------------------- + +void ShapeStyleContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > ShapeStyleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttributes ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + AttributeList aAttribs( rxAttributes ); + switch( aElementToken ) + { + case A_TOKEN( lnRef ) : // CT_StyleMatrixReference + case A_TOKEN( fillRef ) : // CT_StyleMatrixReference + case A_TOKEN( effectRef ) : // CT_StyleMatrixReference + case A_TOKEN( fontRef ) : // CT_FontReference + { + sal_Int32 nToken = getBaseToken( aElementToken ); + ShapeStyleRef& rStyleRef = mrShape.getShapeStyleRefs()[ nToken ]; + rStyleRef.mnThemedIdx = (nToken == XML_fontRef) ? aAttribs.getToken( XML_idx, XML_none ) : aAttribs.getInteger( XML_idx, 0 ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); + } + break; + } + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/spdefcontext.cxx b/oox/source/drawingml/spdefcontext.cxx new file mode 100644 index 000000000000..da86e031ddec --- /dev/null +++ b/oox/source/drawingml/spdefcontext.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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/spdefcontext.hxx" +#include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/textbody.hxx" +#include "oox/drawingml/textbodypropertiescontext.hxx" +#include "oox/drawingml/textliststylecontext.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +spDefContext::spDefContext( ContextHandler& rParent, Shape& rDefaultObject ) +: ContextHandler( rParent ) +, mrDefaultObject( rDefaultObject ) +{ +} + +Reference< XFastContextHandler > spDefContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case A_TOKEN( spPr ): + { + xRet = new ShapePropertiesContext( *this, mrDefaultObject ); + break; + } + case A_TOKEN( bodyPr ): + { + TextBodyPtr xTextBody( new TextBody ); + mrDefaultObject.setTextBody( xTextBody ); + xRet = new TextBodyPropertiesContext( *this, xAttribs, xTextBody->getTextProperties() ); + break; + } + case A_TOKEN( lstStyle ): + xRet.set( new TextListStyleContext( *this, *mrDefaultObject.getMasterTextListStyle() ) ); + break; + case A_TOKEN( style ): + break; + } + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } diff --git a/oox/source/drawingml/table/makefile.mk b/oox/source/drawingml/table/makefile.mk new file mode 100644 index 000000000000..fa71971fc278 --- /dev/null +++ b/oox/source/drawingml/table/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=oox +TARGET=table +AUTOSEG=true + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE: $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/tablecontext.obj \ + $(SLO)$/tableproperties.obj \ + $(SLO)$/tablerow.obj \ + $(SLO)$/tablerowcontext.obj \ + $(SLO)$/tablecell.obj \ + $(SLO)$/tablecellcontext.obj \ + $(SLO)$/tablestylelist.obj \ + $(SLO)$/tablestylelistfragmenthandler.obj \ + $(SLO)$/tablestylecontext.obj \ + $(SLO)$/tablestyle.obj \ + $(SLO)$/tablebackgroundstylecontext.obj \ + $(SLO)$/tablepartstylecontext.obj \ + $(SLO)$/tablestyletextstylecontext.obj \ + $(SLO)$/tablestylecellstylecontext.obj \ + $(SLO)$/tablestylepart.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk diff --git a/oox/source/drawingml/table/tablebackgroundstylecontext.cxx b/oox/source/drawingml/table/tablebackgroundstylecontext.cxx new file mode 100644 index 000000000000..075e8ded9b31 --- /dev/null +++ b/oox/source/drawingml/table/tablebackgroundstylecontext.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablebackgroundstylecontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/helper/attributelist.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableBackgroundStyleContext::TableBackgroundStyleContext( ContextHandler& rParent, TableStyle& rTableStyle ) +: ContextHandler( rParent ) +, mrTableStyle( rTableStyle ) +{ +} + +TableBackgroundStyleContext::~TableBackgroundStyleContext() +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableBackgroundStyleContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + AttributeList aAttribs( xAttribs ); + switch( aElementToken ) + { + // EG_ThemeableFillStyle (choice) + case A_TOKEN( fill ): // CT_FillProperties + { + boost::shared_ptr< FillProperties >& rxFillProperties = mrTableStyle.getBackgroundFillProperties(); + rxFillProperties.reset( new FillProperties ); + xRet.set( new FillPropertiesContext( *this, *rxFillProperties ) ); + } + break; + case A_TOKEN( fillRef ): // CT_StyleMatrixReference + { + ShapeStyleRef& rStyleRef = mrTableStyle.getBackgroundFillStyleRef(); + rStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); + } + break; + + // EG_ThemeableEffectStyle (choice) + case A_TOKEN( effect ): // CT_EffectProperties + break; + case A_TOKEN( effectRef ): // CT_StyleMatrixReference + break; + } + if( !xRet.is() ) + { + uno::Reference<XFastContextHandler> xTmp(this); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx new file mode 100644 index 000000000000..f381b20d5383 --- /dev/null +++ b/oox/source/drawingml/table/tablecell.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * 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/table/tablecell.hxx" +#include "oox/drawingml/table/tableproperties.hxx" +#include "oox/drawingml/textbody.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/propertyset.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/table/BorderLine.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/text/XText.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 ::com::sun::star::table::BorderLine; +using ::com::sun::star::drawing::LineStyle; + +namespace oox { namespace drawingml { namespace table { + +TableCell::TableCell() +: mnRowSpan ( 1 ) +, mnGridSpan( 1 ) +, mbhMerge( sal_False ) +, mbvMerge( sal_False ) +, mnMarL( 91440 ) +, mnMarR( 91440 ) +, mnMarT( 45720 ) +, mnMarB( 45720 ) +, mnVertToken( XML_horz ) +, mnAnchorToken( XML_t ) +, mbAnchorCtr( sal_False ) +, mnHorzOverflowToken( XML_clip ) +{ +} +TableCell::~TableCell() +{ +} + +void applyLineAttributes( const ::oox::core::XmlFilterBase& rFilterBase, + Reference< XPropertySet >& rxPropSet, oox::drawingml::LineProperties& rLineProperties, + sal_Int32 nPropId ) +{ + BorderLine aBorderLine( 0, 0, 0, 0 ); + if( rLineProperties.maLineFill.moFillType.differsFrom( XML_noFill ) ) + { + Color aColor = rLineProperties.maLineFill.getBestSolidColor(); + aBorderLine.Color = aColor.getColor( rFilterBase.getGraphicHelper() ); + aBorderLine.OuterLineWidth = static_cast< sal_Int16 >( GetCoordinate( rLineProperties.moLineWidth.get( 0 ) ) / 4 ); + aBorderLine.InnerLineWidth = static_cast< sal_Int16 >( GetCoordinate( rLineProperties.moLineWidth.get( 0 ) ) / 4 ); + aBorderLine.LineDistance = 0; + } + + PropertySet aPropSet( rxPropSet ); + aPropSet.setProperty( nPropId, aBorderLine ); +} + +void applyBorder( TableStylePart& rTableStylePart, sal_Int32 nLineType, oox::drawingml::LineProperties& rLineProperties ) +{ + std::map < sal_Int32, ::oox::drawingml::LinePropertiesPtr >& rPartLineBorders( rTableStylePart.getLineBorders() ); + std::map < sal_Int32, ::oox::drawingml::LinePropertiesPtr >::const_iterator aIter( rPartLineBorders.find( nLineType ) ); + if ( ( aIter != rPartLineBorders.end() ) && aIter->second.get() ) + rLineProperties.assignUsed( *aIter->second ); +} + +void applyTableStylePart( const ::oox::core::XmlFilterBase& rFilterBase, const Reference < ::com::sun::star::table::XCell >& rxCell, oox::drawingml::FillProperties& rFillProperties, + oox::drawingml::LineProperties& rLeftBorder, + oox::drawingml::LineProperties& rRightBorder, + oox::drawingml::LineProperties& rTopBorder, + oox::drawingml::LineProperties& rBottomBorder, + oox::drawingml::LineProperties& rTopLeftToBottomRightBorder, + oox::drawingml::LineProperties& rBottomLeftToTopRightBorder, + TableStylePart& rTableStylePart ) +{ + boost::shared_ptr< ::oox::drawingml::FillProperties >& rPartFillPropertiesPtr( rTableStylePart.getFillProperties() ); + if ( rPartFillPropertiesPtr.get() ) + rFillProperties.assignUsed( *rPartFillPropertiesPtr ); + + applyBorder( rTableStylePart, XML_left, rLeftBorder ); + applyBorder( rTableStylePart, XML_right, rRightBorder ); + applyBorder( rTableStylePart, XML_top, rTopBorder ); + applyBorder( rTableStylePart, XML_bottom, rBottomBorder ); + applyBorder( rTableStylePart, XML_tl2br, rTopLeftToBottomRightBorder ); + applyBorder( rTableStylePart, XML_tr2bl, rBottomLeftToTopRightBorder ); + + TextCharacterProperties aTextCharProps; + aTextCharProps.maLatinFont = rTableStylePart.getLatinFont(); + aTextCharProps.maAsianFont = rTableStylePart.getAsianFont(); + aTextCharProps.maComplexFont = rTableStylePart.getComplexFont(); + aTextCharProps.maSymbolFont = rTableStylePart.getSymbolFont(); + aTextCharProps.maCharColor = rTableStylePart.getTextColor(); + + PropertySet aPropSet( rxCell ); + aTextCharProps.pushToPropSet( aPropSet, rFilterBase ); +} + +void applyTableCellProperties( const Reference < ::com::sun::star::table::XCell >& rxCell, const TableCell& rTableCell ) +{ + static const rtl::OUString sTopBorder( RTL_CONSTASCII_USTRINGPARAM( "TextUpperDistance" ) ); + static const rtl::OUString sBottomBorder( RTL_CONSTASCII_USTRINGPARAM( "TextLowerDistance" ) ); + static const rtl::OUString sLeftBorder( RTL_CONSTASCII_USTRINGPARAM( "TextLeftDistance" ) ); + static const rtl::OUString sRightBorder( RTL_CONSTASCII_USTRINGPARAM( "TextRightDistance" ) ); + static const rtl::OUString sVerticalAdjust( RTL_CONSTASCII_USTRINGPARAM( "TextVerticalAdjust" ) ); + + Reference< XPropertySet > xPropSet( rxCell, UNO_QUERY_THROW ); + xPropSet->setPropertyValue( sTopBorder, Any( static_cast< sal_Int32 >( rTableCell.getTopMargin() / 360 ) ) ); + xPropSet->setPropertyValue( sRightBorder, Any( static_cast< sal_Int32 >( rTableCell.getRightMargin() / 360 ) ) ); + xPropSet->setPropertyValue( sLeftBorder, Any( static_cast< sal_Int32 >( rTableCell.getLeftMargin() / 360 ) ) ); + xPropSet->setPropertyValue( sBottomBorder, Any( static_cast< sal_Int32 >( rTableCell.getBottomMargin() / 360 ) ) ); + + drawing::TextVerticalAdjust eVA; + switch( rTableCell.getAnchorToken() ) + { + case XML_ctr: eVA = drawing::TextVerticalAdjust_CENTER; break; + case XML_b: eVA = drawing::TextVerticalAdjust_BOTTOM; break; + case XML_just: + case XML_dist: + default: + case XML_t: eVA = drawing::TextVerticalAdjust_TOP; break; + } + xPropSet->setPropertyValue( sVerticalAdjust, Any( eVA ) ); +} + +void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, ::oox::drawingml::TextListStylePtr pMasterTextListStyle, + const ::com::sun::star::uno::Reference < ::com::sun::star::table::XCell >& rxCell, const TableProperties& rTableProperties, + const TableStyle& rTableStyle, sal_Int32 nColumn, sal_Int32 nMaxColumn, sal_Int32 nRow, sal_Int32 nMaxRow ) +{ + TableStyle& rTable( const_cast< TableStyle& >( rTableStyle ) ); + TableProperties& rProperties( const_cast< TableProperties& >( rTableProperties ) ); + + Reference< text::XText > xText( rxCell, UNO_QUERY_THROW ); + Reference< text::XTextCursor > xAt = xText->createTextCursor(); + + applyTableCellProperties( rxCell, *this ); + TextCharacterProperties aTextStyleProps; + getTextBody()->insertAt( rFilterBase, xText, xAt, aTextStyleProps, pMasterTextListStyle ); + + Reference< XPropertySet > xPropSet( rxCell, UNO_QUERY_THROW ); + oox::drawingml::FillProperties aFillProperties; + oox::drawingml::LineProperties aLinePropertiesLeft; + oox::drawingml::LineProperties aLinePropertiesRight; + oox::drawingml::LineProperties aLinePropertiesTop; + oox::drawingml::LineProperties aLinePropertiesBottom; + oox::drawingml::LineProperties aLinePropertiesTopLeftToBottomRight; + oox::drawingml::LineProperties aLinePropertiesBottomLeftToTopRight; + + boost::shared_ptr< ::oox::drawingml::FillProperties >& rBackgroundFillPropertiesPtr( rTable.getBackgroundFillProperties() ); + if ( rBackgroundFillPropertiesPtr.get() ) + aFillProperties.assignUsed( *rBackgroundFillPropertiesPtr ); + + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getWholeTbl() ); + + if ( rProperties.isFirstRow() && ( nRow == 0 ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getFirstRow() ); + } + if ( rProperties.isLastRow() && ( nRow == nMaxRow ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getLastRow() ); + } + if ( rProperties.isFirstCol() && ( nColumn == 0 ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getFirstCol() ); + } + if ( rProperties.isLastCol() && ( nColumn == nMaxColumn ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getLastCol() ); + } + if ( rProperties.isBandRow() ) + { + if ( ( !rProperties.isFirstRow() || ( nRow != 0 ) ) && + ( !rProperties.isLastRow() || ( nRow != nMaxRow ) ) ) + { + sal_Int32 nBand = nRow; + if ( rProperties.isFirstRow() ) + nBand++; + if ( nBand & 1 ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getBand2H() ); + } + else + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getBand1H() ); + } + } + } + if ( ( nRow == 0 ) && ( nColumn == 0 ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getNwCell() ); + } + if ( ( nRow == nMaxRow ) && ( nColumn == 0 ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getSwCell() ); + } + if ( ( nRow == 0 ) && ( nColumn == nMaxColumn ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getNeCell() ); + } + if ( ( nRow == nMaxColumn ) && ( nColumn == nMaxColumn ) ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getSeCell() ); + } + if ( rProperties.isBandCol() ) + { + if ( ( !rProperties.isFirstCol() || ( nColumn != 0 ) ) && + ( !rProperties.isLastCol() || ( nColumn != nMaxColumn ) ) ) + { + sal_Int32 nBand = nColumn; + if ( rProperties.isFirstCol() ) + nBand++; + if ( nBand & 1 ) + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getBand2V() ); + } + else + { + applyTableStylePart( rFilterBase, rxCell, aFillProperties, + aLinePropertiesLeft, + aLinePropertiesRight, + aLinePropertiesTop, + aLinePropertiesBottom, + aLinePropertiesTopLeftToBottomRight, + aLinePropertiesBottomLeftToTopRight, + rTable.getBand1V() ); + } + } + } + aLinePropertiesLeft.assignUsed( maLinePropertiesLeft ); + aLinePropertiesRight.assignUsed( maLinePropertiesRight ); + aLinePropertiesTop.assignUsed( maLinePropertiesTop ); + aLinePropertiesBottom.assignUsed( maLinePropertiesBottom ); + aLinePropertiesTopLeftToBottomRight.assignUsed( maLinePropertiesTopLeftToBottomRight ); + aLinePropertiesBottomLeftToTopRight.assignUsed( maLinePropertiesBottomLeftToTopRight ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesLeft, PROP_LeftBorder ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesRight, PROP_RightBorder ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesTop, PROP_TopBorder ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesBottom, PROP_BottomBorder ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesTopLeftToBottomRight, PROP_DiagonalTLBR ); + applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesBottomLeftToTopRight, PROP_DiagonalBLTR ); + + aFillProperties.assignUsed( maFillProperties ); + PropertySet aPropSet( xPropSet ); + // TODO: phClr? + aFillProperties.pushToPropSet( aPropSet, rFilterBase.getModelObjectHelper(), rFilterBase.getGraphicHelper() ); +} + +} } } diff --git a/oox/source/drawingml/table/tablecellcontext.cxx b/oox/source/drawingml/table/tablecellcontext.cxx new file mode 100644 index 000000000000..844f134c3e85 --- /dev/null +++ b/oox/source/drawingml/table/tablecellcontext.cxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablecellcontext.hxx" +#include "oox/drawingml/textbodycontext.hxx" +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/helper/attributelist.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableCellContext::TableCellContext( ContextHandler& rParent, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs, TableCell& rTableCell ) +: ContextHandler( rParent ) +, mrTableCell( rTableCell ) +{ + if ( xAttribs->hasAttribute( XML_rowSpan ) ) + mrTableCell.setRowSpan( xAttribs->getOptionalValue( XML_rowSpan ).toInt32() ); + if ( xAttribs->hasAttribute( XML_gridSpan ) ) + mrTableCell.setGridSpan( xAttribs->getOptionalValue( XML_gridSpan ).toInt32() ); + + AttributeList aAttribs( xAttribs ); + mrTableCell.sethMerge( aAttribs.getBool( XML_hMerge, sal_False ) ); + mrTableCell.setvMerge( aAttribs.getBool( XML_vMerge, sal_False ) ); +} + +TableCellContext::~TableCellContext() +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableCellContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( txBody ): // CT_TextBody + { + oox::drawingml::TextBodyPtr xTextBody( new oox::drawingml::TextBody ); + mrTableCell.setTextBody( xTextBody ); + xRet = new oox::drawingml::TextBodyContext( *this, *xTextBody ); + } + break; + + case A_TOKEN( tcPr ): // CT_TableCellProperties + { + AttributeList aAttribs( xAttribs ); + mrTableCell.setLeftMargin( aAttribs.getInteger( XML_marL, 91440 ) ); + mrTableCell.setRightMargin( aAttribs.getInteger( XML_marR, 91440 ) ); + mrTableCell.setTopMargin( aAttribs.getInteger( XML_marT, 45720 ) ); + mrTableCell.setBottomMargin( aAttribs.getInteger( XML_marB, 45720 ) ); + mrTableCell.setVertToken( xAttribs->getOptionalValueToken( XML_vert, XML_horz ) ); // ST_TextVerticalType + mrTableCell.setAnchorToken( xAttribs->getOptionalValueToken( XML_anchor, XML_t ) ); // ST_TextAnchoringType + mrTableCell.setAnchorCtr( aAttribs.getBool( XML_anchorCtr, sal_False ) ); + mrTableCell.setHorzOverflowToken( xAttribs->getOptionalValueToken( XML_horzOverflow, XML_clip ) ); // ST_TextHorzOverflowType + } + break; + case A_TOKEN( lnL ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesLeft ) ); + break; + case A_TOKEN( lnR ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesRight ) ); + break; + case A_TOKEN( lnT ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesTop ) ); + break; + case A_TOKEN( lnB ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesBottom ) ); + break; + case A_TOKEN( lnTlToBr ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesTopLeftToBottomRight ) ); + break; + case A_TOKEN( lnBlToTr ): + xRet.set( new oox::drawingml::LinePropertiesContext( *this, xAttribs, mrTableCell.maLinePropertiesBottomLeftToTopRight ) ); + break; + case A_TOKEN( cell3D ): // CT_Cell3D + break; + + case A_TOKEN( extLst ): // CT_OfficeArtExtensionList + break; + + default: + xRet.set( FillPropertiesContext::createFillContext( *this, aElementToken, xAttribs, mrTableCell.maFillProperties ) ); + break; + + } + if ( !xRet.is() ) + { + uno::Reference< XFastContextHandler > xTmp( this ); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablecontext.cxx b/oox/source/drawingml/table/tablecontext.cxx new file mode 100644 index 000000000000..f7e7af620428 --- /dev/null +++ b/oox/source/drawingml/table/tablecontext.cxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/guidcontext.hxx" +#include "oox/drawingml/table/tablecontext.hxx" +#include "oox/drawingml/table/tableproperties.hxx" +#include "oox/drawingml/table/tablestylecontext.hxx" +#include "oox/drawingml/table/tablerowcontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableContext::TableContext( ContextHandler& rParent, ShapePtr pShapePtr ) +: ShapeContext( rParent, ShapePtr(), pShapePtr ) +, mrTableProperties( *pShapePtr->getTableProperties().get() ) +{ + pShapePtr->setTableType(); +} + +TableContext::~TableContext() +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( tblPr ): // CT_TableProperties + { + AttributeList aAttribs( xAttribs ); + mrTableProperties.isRtl() = aAttribs.getBool( XML_rtl, sal_False ); + mrTableProperties.isFirstRow() = aAttribs.getBool( XML_firstRow, sal_False ); + mrTableProperties.isFirstCol() = aAttribs.getBool( XML_firstCol, sal_False ); + mrTableProperties.isLastRow() = aAttribs.getBool( XML_lastRow, sal_False ); + mrTableProperties.isLastCol() = aAttribs.getBool( XML_lastCol, sal_False ); + mrTableProperties.isBandRow() = aAttribs.getBool( XML_bandRow, sal_False ); + mrTableProperties.isBandCol() = aAttribs.getBool( XML_bandCol, sal_False ); + } + break; + case A_TOKEN( tableStyle ): // CT_TableStyle + { + boost::shared_ptr< TableStyle >& rTableStyle = mrTableProperties.getTableStyle(); + rTableStyle.reset( new TableStyle() ); + xRet = new TableStyleContext( *this, xAttribs, *rTableStyle ); + } + break; + case A_TOKEN( tableStyleId ): // ST_Guid + xRet.set( new oox::drawingml::GuidContext( *this, mrTableProperties.getStyleId() ) ); + break; + + case A_TOKEN( tblGrid ): // CT_TableGrid + break; + case A_TOKEN( gridCol ): // CT_TableCol + { + std::vector< sal_Int32 >& rvTableGrid( mrTableProperties.getTableGrid() ); + rvTableGrid.push_back( xAttribs->getOptionalValue( XML_w ).toInt32() ); + } + break; + case A_TOKEN( tr ): // CT_TableRow + { + std::vector< TableRow >& rvTableRows( mrTableProperties.getTableRows() ); + rvTableRows.resize( rvTableRows.size() + 1 ); + xRet.set( new TableRowContext( *this, xAttribs, rvTableRows.back() ) ); + } + break; + } + + if( !xRet.is() ) + xRet.set( this ); + + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablepartstylecontext.cxx b/oox/source/drawingml/table/tablepartstylecontext.cxx new file mode 100644 index 000000000000..1d48cbcf2a18 --- /dev/null +++ b/oox/source/drawingml/table/tablepartstylecontext.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablepartstylecontext.hxx" +#include "oox/drawingml/table/tablestyletextstylecontext.hxx" +#include "oox/drawingml/table/tablestylecellstylecontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TablePartStyleContext::TablePartStyleContext( ContextHandler& rParent, TableStylePart& rTableStylePart ) +: ContextHandler( rParent ) +, mrTableStylePart( rTableStylePart ) +{ +} + +TablePartStyleContext::~TablePartStyleContext() +{ +} + +// CT_TablePartStyle +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TablePartStyleContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( tcTxStyle ): // CT_TableStyleTextStyle + xRet.set( new TableStyleTextStyleContext( *this, xAttribs, mrTableStylePart ) ); + break; + case A_TOKEN( tcStyle ): // CT_TableStyleCellStyle + xRet.set( new TableStyleCellStyleContext( *this, mrTableStylePart ) ); + break; + } + if( !xRet.is() ) + { + uno::Reference<XFastContextHandler> xTmp(this); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tableproperties.cxx b/oox/source/drawingml/table/tableproperties.cxx new file mode 100644 index 000000000000..e0d0ac91c2ab --- /dev/null +++ b/oox/source/drawingml/table/tableproperties.cxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * 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/table/tableproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/table/BorderLine.hpp> +#include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/propertyset.hxx" + +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::table; + + +namespace oox { namespace drawingml { namespace table { + +TableProperties::TableProperties() +: mbRtl( sal_False ) +, mbFirstRow( sal_False ) +, mbFirstCol( sal_False ) +, mbLastRow( sal_False ) +, mbLastCol( sal_False ) +, mbBandRow( sal_False ) +, mbBandCol( sal_False ) +{ +} +TableProperties::~TableProperties() +{ +} + +void TableProperties::apply( const TablePropertiesPtr& /* rSourceTableProperties */ ) +{ +} + +void CreateTableRows( uno::Reference< XTableRows > xTableRows, const std::vector< TableRow >& rvTableRows ) +{ + if ( rvTableRows.size() > 1 ) + xTableRows->insertByIndex( 0, rvTableRows.size() - 1 ); + std::vector< TableRow >::const_iterator aTableRowIter( rvTableRows.begin() ); + uno::Reference< container::XIndexAccess > xIndexAccess( xTableRows, UNO_QUERY_THROW ); + for ( sal_Int32 n = 0; n < xIndexAccess->getCount(); n++ ) + { + static const rtl::OUString sHeight( RTL_CONSTASCII_USTRINGPARAM ( "Height" ) ); + Reference< XPropertySet > xPropSet( xIndexAccess->getByIndex( n ), UNO_QUERY_THROW ); + xPropSet->setPropertyValue( sHeight, Any( static_cast< sal_Int32 >( aTableRowIter->getHeight() / 360 ) ) ); + aTableRowIter++; + } +} + +void CreateTableColumns( Reference< XTableColumns > xTableColumns, const std::vector< sal_Int32 >& rvTableGrid ) +{ + if ( rvTableGrid.size() > 1 ) + xTableColumns->insertByIndex( 0, rvTableGrid.size() - 1 ); + std::vector< sal_Int32 >::const_iterator aTableGridIter( rvTableGrid.begin() ); + uno::Reference< container::XIndexAccess > xIndexAccess( xTableColumns, UNO_QUERY_THROW ); + for ( sal_Int32 n = 0; n < xIndexAccess->getCount(); n++ ) + { + static const rtl::OUString sWidth( RTL_CONSTASCII_USTRINGPARAM ( "Width" ) ); + Reference< XPropertySet > xPropSet( xIndexAccess->getByIndex( n ), UNO_QUERY_THROW ); + xPropSet->setPropertyValue( sWidth, Any( static_cast< sal_Int32 >( *aTableGridIter++ / 360 ) ) ); + } +} + +void MergeCells( const uno::Reference< XTable >& xTable, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan ) +{ + if( xTable.is() ) try + { + Reference< XMergeableCellRange > xRange( xTable->createCursorByRange( xTable->getCellRangeByPosition( nCol, nRow,nCol + nColSpan - 1, nRow + nRowSpan - 1 ) ), UNO_QUERY_THROW ); + if( xRange->isMergeable() ) + xRange->merge(); + } + catch( Exception& ) + { + } +} + +static TableStyle* pDefaultTableStyle = new TableStyle(); + +const TableStyle& TableProperties::getUsedTableStyle( const ::oox::core::XmlFilterBase& rFilterBase ) +{ + ::oox::core::XmlFilterBase& rBase( const_cast< ::oox::core::XmlFilterBase& >( rFilterBase ) ); + + TableStyle* pTableStyle = NULL; + if ( mpTableStyle ) + pTableStyle = &*mpTableStyle; + else if ( rBase.getTableStyles() ) + { + const std::vector< TableStyle >& rTableStyles( rBase.getTableStyles()->getTableStyles() ); + const rtl::OUString aStyleId( getStyleId().getLength() ? getStyleId() : rBase.getTableStyles()->getDefaultStyleId() ); + std::vector< TableStyle >::const_iterator aIter( rTableStyles.begin() ); + while( aIter != rTableStyles.end() ) + { + if ( const_cast< TableStyle& >( *aIter ).getStyleId() == aStyleId ) + { + pTableStyle = &const_cast< TableStyle& >( *aIter ); + break; // we get the correct style + } + aIter++; + } + } + if ( !pTableStyle ) + pTableStyle = pDefaultTableStyle; + + return *pTableStyle; +} + +void TableProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XPropertySet >& xPropSet, TextListStylePtr pMasterTextListStyle ) +{ + TableStyleListPtr( const_cast< ::oox::core::XmlFilterBase& >( rFilterBase ).getTableStyles() ); + + uno::Reference< XColumnRowRange > xColumnRowRange( + xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("Model") ) ), uno::UNO_QUERY_THROW ); + + CreateTableColumns( xColumnRowRange->getColumns(), mvTableGrid ); + CreateTableRows( xColumnRowRange->getRows(), mvTableRows ); + + const TableStyle& rTableStyle( getUsedTableStyle( rFilterBase ) ); + sal_Int32 nRow = 0; + std::vector< TableRow >::iterator aTableRowIter( mvTableRows.begin() ); + while( aTableRowIter != mvTableRows.end() ) + { + sal_Int32 nColumn = 0; + std::vector< TableCell >::iterator aTableCellIter( aTableRowIter->getTableCells().begin() ); + while( aTableCellIter != aTableRowIter->getTableCells().end() ) + { + TableCell& rTableCell( *aTableCellIter ); + if ( !rTableCell.getvMerge() && !rTableCell.gethMerge() ) + { + uno::Reference< XTable > xTable( xColumnRowRange, uno::UNO_QUERY_THROW ); + if ( ( rTableCell.getRowSpan() > 1 ) || ( rTableCell.getGridSpan() > 1 ) ) + MergeCells( xTable, nColumn, nRow, rTableCell.getGridSpan(), rTableCell.getRowSpan() ); + + Reference< XCellRange > xCellRange( xTable, UNO_QUERY_THROW ); + rTableCell.pushToXCell( rFilterBase, pMasterTextListStyle, xCellRange->getCellByPosition( nColumn, nRow ), *this, rTableStyle, + nColumn, aTableRowIter->getTableCells().size(), nRow, mvTableRows.size() ); + } + nColumn++; + aTableCellIter++; + } + nRow++; + aTableRowIter++; + } +} + +} } } diff --git a/oox/source/drawingml/table/tablerow.cxx b/oox/source/drawingml/table/tablerow.cxx new file mode 100644 index 000000000000..3c4af56a5d42 --- /dev/null +++ b/oox/source/drawingml/table/tablerow.cxx @@ -0,0 +1,53 @@ +/************************************************************************* + * + * 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/table/tablerow.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include "oox/helper/propertyset.hxx" +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/table/BorderLine.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; + +namespace oox { namespace drawingml { namespace table { + +TableRow::TableRow() +: mnHeight( 0 ) +{ +} +TableRow::~TableRow() +{ +} + +} } } diff --git a/oox/source/drawingml/table/tablerowcontext.cxx b/oox/source/drawingml/table/tablerowcontext.cxx new file mode 100644 index 000000000000..1a6c38167a8d --- /dev/null +++ b/oox/source/drawingml/table/tablerowcontext.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablerowcontext.hxx" +#include "oox/drawingml/table/tablecellcontext.hxx" +#include "oox/drawingml/table/tablerow.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableRowContext::TableRowContext( ContextHandler& rParent, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs, TableRow& rTableRow ) +: ContextHandler( rParent ) +, mrTableRow( rTableRow ) +{ + rTableRow.setHeight( xAttribs->getOptionalValue( XML_h ).toInt32() ); +} + +TableRowContext::~TableRowContext() +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableRowContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( tc ): // CT_TableCell + { + std::vector< TableCell >& rvTableCells = mrTableRow.getTableCells(); + rvTableCells.resize( rvTableCells.size() + 1 ); + xRet.set( new TableCellContext( *this, xAttribs, rvTableCells.back() ) ); + } + break; + case A_TOKEN( extLst ): // CT_OfficeArtExtensionList + default: + break; + } + if( !xRet.is() ) + { + uno::Reference< XFastContextHandler > xTmp( this ); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablestyle.cxx b/oox/source/drawingml/table/tablestyle.cxx new file mode 100644 index 000000000000..78a110ebb8cb --- /dev/null +++ b/oox/source/drawingml/table/tablestyle.cxx @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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/table/tablestyle.hxx" + +namespace oox { namespace drawingml { namespace table { + +TableStyle::TableStyle() +{ +} + +TableStyle::~TableStyle() +{ +} + +} } } diff --git a/oox/source/drawingml/table/tablestylecellstylecontext.cxx b/oox/source/drawingml/table/tablestylecellstylecontext.cxx new file mode 100644 index 000000000000..56127b0c049c --- /dev/null +++ b/oox/source/drawingml/table/tablestylecellstylecontext.cxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablestylecellstylecontext.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/helper/attributelist.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableStyleCellStyleContext::TableStyleCellStyleContext( ContextHandler& rParent, TableStylePart& rTableStylePart ) +: ContextHandler( rParent ) +, mrTableStylePart( rTableStylePart ) +, mnLineType( XML_none ) +{ +} + +TableStyleCellStyleContext::~TableStyleCellStyleContext() +{ +} + +// CT_TableStyleCellStyle +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableStyleCellStyleContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); + switch( aElementToken ) + { + case A_TOKEN( tcBdr ): // CT_TableCellBorderStyle + break; + case A_TOKEN( left ): // CT_ThemeableLineStyle + case A_TOKEN( right ): + case A_TOKEN( top ): + case A_TOKEN( bottom ): + case A_TOKEN( insideH ): + case A_TOKEN( insideV ): + case A_TOKEN( tl2br ): + case A_TOKEN( tr2bl ): + mnLineType = getBaseToken( aElementToken ); + break; + + case A_TOKEN( ln ): + { + if ( mnLineType != XML_none ) + { + std::map < sal_Int32, ::oox::drawingml::LinePropertiesPtr >& rLineBorders = mrTableStylePart.getLineBorders(); + ::oox::drawingml::LinePropertiesPtr mpLineProperties( new oox::drawingml::LineProperties ); + rLineBorders[ mnLineType ] = mpLineProperties; + xRet = new LinePropertiesContext( *this, xAttribs, *mpLineProperties ); + } + } + break; + case A_TOKEN( lnRef ): + { + if ( mnLineType != XML_none ) + { + ShapeStyleRef& rLineStyleRef = mrTableStylePart.getStyleRefs()[ mnLineType ]; + rLineStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); + xRet.set( new ColorContext( *this, rLineStyleRef.maPhClr ) ); + } + } + break; + + // EG_ThemeableFillStyle (choice) + case A_TOKEN( fill ): // CT_FillProperties + { + FillPropertiesPtr& rxFillProperties = mrTableStylePart.getFillProperties(); + rxFillProperties.reset( new FillProperties ); + xRet.set( new FillPropertiesContext( *this, *rxFillProperties ) ); + } + break; + case A_TOKEN( fillRef ): // CT_StyleMatrixReference + { + ShapeStyleRef& rStyleRef = mrTableStylePart.getStyleRefs()[ XML_fillRef ]; + rStyleRef.mnThemedIdx = aAttribs.getInteger( XML_idx, 0 ); + xRet.set( new ColorContext( *this, rStyleRef.maPhClr ) ); + } + break; + + case A_TOKEN( cell3D ): // CT_Cell3D + break; + } + if( !xRet.is() ) + { + uno::Reference<XFastContextHandler> xTmp(this); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablestylecontext.cxx b/oox/source/drawingml/table/tablestylecontext.cxx new file mode 100644 index 000000000000..aee23eaf9c7b --- /dev/null +++ b/oox/source/drawingml/table/tablestylecontext.cxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablestylecontext.hxx" +#include "oox/drawingml/table/tablebackgroundstylecontext.hxx" +#include "oox/drawingml/table/tablepartstylecontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableStyleContext::TableStyleContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, TableStyle& rTableStyle ) +: ContextHandler( rParent ) +, mrTableStyle( rTableStyle ) +{ + mrTableStyle.getStyleId() = xAttribs->getOptionalValue( XML_styleId ); + mrTableStyle.getStyleName() = xAttribs->getOptionalValue( XML_styleName ); +} + +TableStyleContext::~TableStyleContext() +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableStyleContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& /* xAttribs */ ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( tblBg ): // CT_TableBackgroundStyle + xRet = new TableBackgroundStyleContext( *this, mrTableStyle ); + break; + case A_TOKEN( wholeTbl ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getWholeTbl() ); + break; + case A_TOKEN( band1H ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getBand1H() ); + break; + case A_TOKEN( band2H ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getBand2H() ); + break; + case A_TOKEN( band1V ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getBand1V() ); + break; + case A_TOKEN( band2V ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getBand2V() ); + break; + case A_TOKEN( lastCol ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getLastCol() ); + break; + case A_TOKEN( firstCol ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getFirstCol() ); + break; + case A_TOKEN( lastRow ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getLastRow() ); + break; + case A_TOKEN( seCell ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getSeCell() ); + break; + case A_TOKEN( swCell ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getSwCell() ); + break; + case A_TOKEN( firstRow ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getFirstRow() ); + break; + case A_TOKEN( neCell ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getNeCell() ); + break; + case A_TOKEN( nwCell ): // CT_TablePartStyle + xRet = new TablePartStyleContext( *this, mrTableStyle.getNwCell() ); + break; + case A_TOKEN( extLst ): // CT_OfficeArtExtensionList + break; + } + if( !xRet.is() ) + { + uno::Reference<XFastContextHandler> xTmp(this); + xRet.set( xTmp ); + } + return xRet; +} + +} } } diff --git a/oox/source/drawingml/table/tablestylelist.cxx b/oox/source/drawingml/table/tablestylelist.cxx new file mode 100644 index 000000000000..36ebc56a84a3 --- /dev/null +++ b/oox/source/drawingml/table/tablestylelist.cxx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * 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/table/tablestylelist.hxx" +#include "oox/drawingml/table/tablestyle.hxx" + +namespace oox { namespace drawingml { namespace table { + +TableStyleList::TableStyleList() +{ +} + +TableStyleList::~TableStyleList() +{ +} + +} } } diff --git a/oox/source/drawingml/table/tablestylelistfragmenthandler.cxx b/oox/source/drawingml/table/tablestylelistfragmenthandler.cxx new file mode 100644 index 000000000000..7b837d27e826 --- /dev/null +++ b/oox/source/drawingml/table/tablestylelistfragmenthandler.cxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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/table/tablestylelistfragmenthandler.hxx" +#include "oox/drawingml/table/tablestylecontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { +namespace drawingml { +namespace table { + +// ============================================================================ + +TableStyleListFragmentHandler::TableStyleListFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, TableStyleList& rTableStyleList ): +FragmentHandler2( rFilter, rFragmentPath ), +mrTableStyleList( rTableStyleList ) +{ +} + +TableStyleListFragmentHandler::~TableStyleListFragmentHandler() +{ +} + +// CT_TableStyleList +Reference< XFastContextHandler > TableStyleListFragmentHandler::createFastChildContext( + sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case A_TOKEN( tblStyleLst ): // CT_TableStyleList + mrTableStyleList.getDefaultStyleId() = xAttribs->getOptionalValue( XML_def ); + break; + case A_TOKEN( tblStyle ): // CT_TableStyle + std::vector< TableStyle >& rTableStyles = mrTableStyleList.getTableStyles(); + rTableStyles.resize( rTableStyles.size() + 1 ); + xRet = new TableStyleContext( *this, xAttribs, rTableStyles.back() ); + break; + } + if ( !xRet.is() ) + xRet = getFastContextHandler(); + return xRet; +} + +// ============================================================================ + +} // namespace table +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/table/tablestylepart.cxx b/oox/source/drawingml/table/tablestylepart.cxx new file mode 100644 index 000000000000..b4a68fd488cd --- /dev/null +++ b/oox/source/drawingml/table/tablestylepart.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * 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/table/tablestylepart.hxx" +#include "oox/drawingml/drawingmltypes.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +namespace oox { namespace drawingml { namespace table { + +TableStylePart::TableStylePart() +{ +} + +TableStylePart::~TableStylePart() +{ +} + +} } } diff --git a/oox/source/drawingml/table/tablestyletextstylecontext.cxx b/oox/source/drawingml/table/tablestyletextstylecontext.cxx new file mode 100644 index 000000000000..7c04e3293eb1 --- /dev/null +++ b/oox/source/drawingml/table/tablestyletextstylecontext.cxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * 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 <osl/diagnose.h> + +#include "oox/drawingml/table/tablestyletextstylecontext.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/helper/attributelist.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using ::rtl::OUString; + +namespace oox { namespace drawingml { namespace table { + +TableStyleTextStyleContext::TableStyleTextStyleContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, TableStylePart& rTableStylePart ) +: ContextHandler( rParent ) +, mrTableStylePart( rTableStylePart ) +{ + sal_Int32 nB = xAttribs->getOptionalValueToken( XML_b, XML_def ); + if ( nB == XML_on ) + mrTableStylePart.getTextBoldStyle() = ::boost::optional< sal_Bool >( sal_True ); + else if ( nB == XML_off ) + mrTableStylePart.getTextBoldStyle() = ::boost::optional< sal_Bool >( sal_False ); + + sal_Int32 nI = xAttribs->getOptionalValueToken( XML_i, XML_def ); + if ( nI == XML_on ) + mrTableStylePart.getTextItalicStyle() = ::boost::optional< sal_Bool >( sal_True ); + else if ( nI == XML_off ) + mrTableStylePart.getTextItalicStyle() = ::boost::optional< sal_Bool >( sal_False ); +} + +TableStyleTextStyleContext::~TableStyleTextStyleContext() +{ +} + +// CT_TableStyleTextStyle +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL +TableStyleTextStyleContext::createFastChildContext( ::sal_Int32 aElementToken, const uno::Reference< xml::sax::XFastAttributeList >& xAttribs ) + throw ( xml::sax::SAXException, uno::RuntimeException) +{ + uno::Reference< xml::sax::XFastContextHandler > xRet; + AttributeList aAttribs( xAttribs ); + + switch( aElementToken ) + { + // EG_ThemeableFontStyles (choice) + case A_TOKEN( font ): // CT_FontCollection + xRet.set( this ); + break; + case A_TOKEN( ea ): // CT_TextFont + mrTableStylePart.getAsianFont().setAttributes( aAttribs ); + return 0; + case A_TOKEN( cs ): // CT_TextFont + mrTableStylePart.getComplexFont().setAttributes( aAttribs ); + return 0; + case A_TOKEN( sym ): // CT_TextFont + mrTableStylePart.getSymbolFont().setAttributes( aAttribs ); + return 0; + case A_TOKEN( latin ): // CT_TextFont + mrTableStylePart.getLatinFont().setAttributes( aAttribs ); + return 0; + + case A_TOKEN( fontRef ): // CT_FontReference + { + ShapeStyleRef& rFontStyle = mrTableStylePart.getStyleRefs()[ XML_fontRef ]; + rFontStyle.mnThemedIdx = aAttribs.getToken( XML_idx, XML_none ); + xRet.set( new ColorContext( *this, rFontStyle.maPhClr ) ); + } + break; + + case A_TOKEN( extLst ): // CT_OfficeArtExtensionList + break; + } + if( !xRet.is() ) + xRet.set( new ColorValueContext( *this, mrTableStylePart.getTextColor() ) ); + + return xRet; +} + +} } } diff --git a/oox/source/drawingml/textbody.cxx b/oox/source/drawingml/textbody.cxx new file mode 100644 index 000000000000..20c554ef3e64 --- /dev/null +++ b/oox/source/drawingml/textbody.cxx @@ -0,0 +1,72 @@ +/************************************************************************* + * + * 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/textbody.hxx" +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include "oox/drawingml/textparagraph.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::frame; + +namespace oox { namespace drawingml { + + +TextBody::TextBody() +{ +} + +TextBody::~TextBody() +{ +} + +TextParagraph& TextBody::addParagraph() +{ + TextParagraphPtr xPara( new TextParagraph ); + maParagraphs.push_back( xPara ); + return *xPara; +} + +void TextBody::insertAt( + const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XText > & xText, + const Reference < XTextCursor > & xAt, + const TextCharacterProperties& rTextStyleProperties, + const TextListStylePtr& pMasterTextListStylePtr ) const +{ + TextListStyle aCombinedTextStyle; + aCombinedTextStyle.apply( *pMasterTextListStylePtr ); + aCombinedTextStyle.apply( maTextListStyle ); + + for( TextParagraphVector::const_iterator aBeg = maParagraphs.begin(), aIt = aBeg, aEnd = maParagraphs.end(); aIt != aEnd; ++aIt ) + (*aIt)->insertAt( rFilterBase, xText, xAt, rTextStyleProperties, aCombinedTextStyle, aIt == aBeg ); +} + + +} } diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx new file mode 100644 index 000000000000..8d695e295fd4 --- /dev/null +++ b/oox/source/drawingml/textbodycontext.cxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * 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/textbodycontext.hxx" +#include "oox/drawingml/textbodypropertiescontext.hxx" +#include "oox/drawingml/textparagraph.hxx" +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/textliststylecontext.hxx" +#include "oox/drawingml/textfield.hxx" +#include "oox/drawingml/textfieldcontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextParagraph +class TextParagraphContext : public ContextHandler +{ +public: + TextParagraphContext( ContextHandler& rParent, TextParagraph& rPara ); + + virtual void SAL_CALL endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException); + +protected: + TextParagraph& mrParagraph; +}; + +// -------------------------------------------------------------------- +TextParagraphContext::TextParagraphContext( ContextHandler& rParent, TextParagraph& rPara ) +: ContextHandler( rParent ) +, mrParagraph( rPara ) +{ +} + +// -------------------------------------------------------------------- +void TextParagraphContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + if( aElementToken == (A_TOKEN( p )) ) + { + } +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextParagraphContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + // EG_TextRun + switch( aElementToken ) + { + case A_TOKEN( r ): // "CT_RegularTextRun" Regular Text Run. + { + TextRunPtr pRun( new TextRun ); + mrParagraph.addRun( pRun ); + xRet.set( new RegularTextRunContext( *this, pRun ) ); + break; + } + case A_TOKEN( br ): // "CT_TextLineBreak" Soft return line break (vertical tab). + { + TextRunPtr pRun( new TextRun ); + pRun->setLineBreak(); + mrParagraph.addRun( pRun ); + xRet.set( new RegularTextRunContext( *this, pRun ) ); + break; + } + case A_TOKEN( fld ): // "CT_TextField" Text Field. + { + TextFieldPtr pField( new TextField ); + mrParagraph.addRun( pField ); + xRet.set( new TextFieldContext( *this, xAttribs, *pField ) ); + break; + } + case A_TOKEN( pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, xAttribs, mrParagraph.getProperties() ) ); + break; + case A_TOKEN( endParaRPr ): + xRet.set( new TextCharacterPropertiesContext( *this, xAttribs, mrParagraph.getEndProperties() ) ); + break; + } + + return xRet; +} +// -------------------------------------------------------------------- + +RegularTextRunContext::RegularTextRunContext( ContextHandler& rParent, TextRunPtr pRunPtr ) +: ContextHandler( rParent ) +, mpRunPtr( pRunPtr ) +, mbIsInText( false ) +{ +} + +// -------------------------------------------------------------------- + +void RegularTextRunContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case A_TOKEN( t ): + { + mbIsInText = false; + break; + } + case A_TOKEN( r ): + { + break; + } + + } +} + +// -------------------------------------------------------------------- + +void RegularTextRunContext::characters( const OUString& aChars ) throw (SAXException, RuntimeException) +{ + if( mbIsInText ) + { + mpRunPtr->getText() += aChars; + } +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > RegularTextRunContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet( this ); + + switch( aElementToken ) + { + case A_TOKEN( rPr ): // "CT_TextCharPropertyBag" The text char properties of this text run. + xRet.set( new TextCharacterPropertiesContext( *this, xAttribs, mpRunPtr->getTextCharacterProperties() ) ); + break; + case A_TOKEN( t ): // "xsd:string" minOccurs="1" The actual text string. + mbIsInText = true; + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +TextBodyContext::TextBodyContext( ContextHandler& rParent, TextBody& rTextBody ) +: ContextHandler( rParent ) +, mrTextBody( rTextBody ) +{ +} + +// -------------------------------------------------------------------- + +void TextBodyContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextBodyContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + + switch( aElementToken ) + { + case A_TOKEN( bodyPr ): // CT_TextBodyPropertyBag + xRet.set( new TextBodyPropertiesContext( *this, xAttribs, mrTextBody.getTextProperties() ) ); + break; + case A_TOKEN( lstStyle ): // CT_TextListStyle + xRet.set( new TextListStyleContext( *this, mrTextBody.getTextListStyle() ) ); + break; + case A_TOKEN( p ): // CT_TextParagraph + xRet.set( new TextParagraphContext( *this, mrTextBody.addParagraph() ) ); + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textbodyproperties.cxx b/oox/source/drawingml/textbodyproperties.cxx new file mode 100644 index 000000000000..4339c93aa0ae --- /dev/null +++ b/oox/source/drawingml/textbodyproperties.cxx @@ -0,0 +1,54 @@ +/************************************************************************* + * + * 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/textbodyproperties.hxx" +#include <com/sun/star/text/WritingMode.hpp> +#include "oox/token/tokens.hxx" + +namespace oox { +namespace drawingml { + +// ============================================================================ + +TextBodyProperties::TextBodyProperties() +{ +} + +void TextBodyProperties::pushToPropMap( PropertyMap& rPropMap ) const +{ + rPropMap.insert( maPropertyMap.begin(), maPropertyMap.end() ); + + // #160799# fake different vertical text modes by top-bottom writing mode + if( moVert.get( XML_horz ) != XML_horz ) + rPropMap[ PROP_TextWritingMode ] <<= ::com::sun::star::text::WritingMode_TB_RL; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx b/oox/source/drawingml/textbodypropertiescontext.cxx new file mode 100644 index 000000000000..f22258075e16 --- /dev/null +++ b/oox/source/drawingml/textbodypropertiescontext.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * 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/textbodypropertiescontext.hxx" + +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/text/ControlCharacter.hpp> +#include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include "oox/drawingml/textbodyproperties.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertymap.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextBodyProperties +TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttributes, TextBodyProperties& rTextBodyProp ) +: ContextHandler( rParent ) +, mrTextBodyProp( rTextBodyProp ) +{ + AttributeList aAttribs( xAttributes ); + + // ST_TextWrappingType + sal_Int32 nWrappingType = aAttribs.getToken( XML_wrap, XML_square ); + mrTextBodyProp.maPropertyMap[ PROP_TextWordWrap ] <<= static_cast< sal_Bool >( nWrappingType == XML_square ); + + // ST_Coordinate + OUString sValue; + sValue = xAttributes->getOptionalValue( XML_lIns ); + if( sValue.getLength() ) { + sal_Int32 nLeftInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrTextBodyProp.maPropertyMap[ PROP_TextLeftDistance ] <<= static_cast< sal_Int32 >( nLeftInset ); + } + sValue = xAttributes->getOptionalValue( XML_tIns ); + if( sValue.getLength() ) { + sal_Int32 nTopInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrTextBodyProp.maPropertyMap[ PROP_TextUpperDistance ] <<= static_cast< sal_Int32 >( nTopInset ); + } + sValue = xAttributes->getOptionalValue( XML_rIns ); + if( sValue.getLength() ) { + sal_Int32 nRightInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 91440 / 360 ); + mrTextBodyProp.maPropertyMap[ PROP_TextRightDistance ] <<= static_cast< sal_Int32 >( nRightInset ); + } + sValue = xAttributes->getOptionalValue( XML_bIns ); + if( sValue.getLength() ) { + sal_Int32 nBottonInset = ( sValue.getLength() != 0 ? GetCoordinate( sValue ) : 45720 / 360 ); + mrTextBodyProp.maPropertyMap[ PROP_TextLowerDistance ] <<= static_cast< sal_Int32 >( nBottonInset ); + } + + // ST_TextAnchoringType + drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP ); + switch( xAttributes->getOptionalValueToken( XML_anchor, XML_t ) ) + { + case XML_b : eVA = drawing::TextVerticalAdjust_BOTTOM; break; + case XML_dist : + case XML_just : + case XML_ctr : eVA = drawing::TextVerticalAdjust_CENTER; break; + default: + case XML_t : eVA = drawing::TextVerticalAdjust_TOP; break; + } + mrTextBodyProp.maPropertyMap[ PROP_TextVerticalAdjust ] <<= eVA; + + bool bAnchorCenter = aAttribs.getBool( XML_anchorCtr, false ); + if( bAnchorCenter ) + mrTextBodyProp.maPropertyMap[ PROP_TextHorizontalAdjust ] <<= + TextHorizontalAdjust_CENTER; + +// bool bCompatLineSpacing = aAttribs.getBool( XML_compatLnSpc, false ); +// bool bForceAA = aAttribs.getBool( XML_forceAA, false ); +// bool bFromWordArt = aAttribs.getBool( XML_fromWordArt, false ); + + // ST_TextHorzOverflowType +// sal_Int32 nHorzOverflow = xAttributes->getOptionalValueToken( XML_horzOverflow, XML_overflow ); + // ST_TextVertOverflowType +// sal_Int32 nVertOverflow = xAttributes->getOptionalValueToken( XML_vertOverflow, XML_overflow ); + + // ST_TextColumnCount +// sal_Int32 nNumCol = aAttribs.getInteger( XML_numCol, 1 ); + + // ST_Angle + mrTextBodyProp.moRotation = aAttribs.getInteger( XML_rot ); + +// bool bRtlCol = aAttribs.getBool( XML_rtlCol, false ); + // ST_PositiveCoordinate +// sal_Int32 nSpcCol = aAttribs.getInteger( XML_spcCol, 0 ); +// bool bSpcFirstLastPara = aAttribs.getBool( XML_spcFirstLastPara, 0 ); +// bool bUpRight = aAttribs.getBool( XML_upright, 0 ); + + // ST_TextVerticalType + mrTextBodyProp.moVert = aAttribs.getToken( XML_vert ); + bool bRtl = aAttribs.getBool( XML_rtl, false ); + sal_Int32 tVert = mrTextBodyProp.moVert.get( XML_horz ); + if( tVert == XML_vert || tVert == XML_eaVert || tVert == XML_vert270 || tVert == XML_mongolianVert ) { + mrTextBodyProp.maPropertyMap[ PROP_TextWritingMode ] + <<= WritingMode_TB_RL; + // workaround for TB_LR as using WritingMode2 doesn't work + if( !bAnchorCenter ) + mrTextBodyProp.maPropertyMap[ PROP_TextHorizontalAdjust ] <<= + TextHorizontalAdjust_LEFT; + } else + mrTextBodyProp.maPropertyMap[ PROP_TextWritingMode ] + <<= ( bRtl ? WritingMode_RL_TB : WritingMode_LR_TB ); +} + +// -------------------------------------------------------------------- + +void TextBodyPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextBodyPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& /*xAttributes*/) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + // Sequence + case A_TOKEN( prstTxWarp ): // CT_PresetTextShape + case A_TOKEN( prot ): // CT_TextProtectionProperty + break; + + // EG_TextAutofit + case A_TOKEN( noAutofit ): + mrTextBodyProp.maPropertyMap[ PROP_TextAutoGrowHeight ] <<= false; // CT_TextNoAutofit + break; + case A_TOKEN( normAutofit ): // CT_TextNormalAutofit + mrTextBodyProp.maPropertyMap[ PROP_TextFitToSize ] <<= true; + mrTextBodyProp.maPropertyMap[ PROP_TextAutoGrowHeight ] <<= false; + break; + case A_TOKEN( spAutoFit ): + mrTextBodyProp.maPropertyMap[ PROP_TextAutoGrowHeight ] <<= true; + break; + + case A_TOKEN( scene3d ): // CT_Scene3D + + // EG_Text3D + case A_TOKEN( sp3d ): // CT_Shape3D + case A_TOKEN( flatTx ): // CT_FlatText + + break; + } + + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textcharacterproperties.cxx b/oox/source/drawingml/textcharacterproperties.cxx new file mode 100644 index 000000000000..61333535c38f --- /dev/null +++ b/oox/source/drawingml/textcharacterproperties.cxx @@ -0,0 +1,169 @@ +/************************************************************************* + * + * 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/textcharacterproperties.hxx" +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include "oox/helper/helper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/token/tokens.hxx" + +using ::rtl::OUString; +using ::oox::core::XmlFilterBase; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +void TextCharacterProperties::assignUsed( const TextCharacterProperties& rSourceProps ) +{ + // overwrite all properties exisiting in rSourceProps + maHyperlinkPropertyMap.insert( rSourceProps.maHyperlinkPropertyMap.begin(), rSourceProps.maHyperlinkPropertyMap.end() ); + maLatinFont.assignIfUsed( rSourceProps.maLatinFont ); + maAsianFont.assignIfUsed( rSourceProps.maAsianFont ); + maComplexFont.assignIfUsed( rSourceProps.maComplexFont ); + maSymbolFont.assignIfUsed( rSourceProps.maSymbolFont ); + maCharColor.assignIfUsed( rSourceProps.maCharColor ); + maHighlightColor.assignIfUsed( rSourceProps.maHighlightColor ); + maUnderlineColor.assignIfUsed( rSourceProps.maUnderlineColor ); + moHeight.assignIfUsed( rSourceProps.moHeight ); + moSpacing.assignIfUsed( rSourceProps.moSpacing ); + moUnderline.assignIfUsed( rSourceProps.moUnderline ); + moStrikeout.assignIfUsed( rSourceProps.moStrikeout ); + moCaseMap.assignIfUsed( rSourceProps.moCaseMap ); + moBold.assignIfUsed( rSourceProps.moBold ); + moItalic.assignIfUsed( rSourceProps.moItalic ); + moUnderlineLineFollowText.assignIfUsed( rSourceProps.moUnderlineLineFollowText ); + moUnderlineFillFollowText.assignIfUsed( rSourceProps.moUnderlineFillFollowText ); +} + +void TextCharacterProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFilterBase& rFilter ) const +{ + OUString aFontName; + sal_Int16 nFontPitch = 0; + sal_Int16 nFontFamily = 0; + + if( maLatinFont.getFontData( aFontName, nFontPitch, nFontFamily, rFilter ) ) + { + rPropMap[ PROP_CharFontName ] <<= aFontName; + rPropMap[ PROP_CharFontPitch ] <<= nFontPitch; + rPropMap[ PROP_CharFontFamily ] <<= nFontFamily; + } + + if( maAsianFont.getFontData( aFontName, nFontPitch, nFontFamily, rFilter ) ) + { + rPropMap[ PROP_CharFontNameAsian ] <<= aFontName; + rPropMap[ PROP_CharFontPitchAsian ] <<= nFontFamily; + rPropMap[ PROP_CharFontFamilyAsian ] <<= nFontPitch; + } + + if( maComplexFont.getFontData( aFontName, nFontPitch, nFontFamily, rFilter ) ) + { + rPropMap[ PROP_CharFontNameComplex ] <<= aFontName; + rPropMap[ PROP_CharFontPitchComplex ] <<= nFontPitch; + rPropMap[ PROP_CharFontFamilyComplex ] <<= nFontFamily; + } + + // symbolfont, will now be ... textrun.cxx ... ausgewertet !!!i#113673 + + if( maCharColor.isUsed() ) + rPropMap[ PROP_CharColor ] <<= maCharColor.getColor( rFilter.getGraphicHelper() ); + + if( moLang.has() && (moLang.get().getLength() > 0) ) + { + lang::Locale aLocale; + sal_Int32 nSepPos = moLang.get().indexOf( sal_Unicode( '-' ), 0 ); + if ( nSepPos >= 0 ) + { + aLocale.Language = moLang.get().copy( 0, nSepPos ); + aLocale.Country = moLang.get().copy( nSepPos + 1 ); + } + else + { + aLocale.Language = moLang.get(); + } + rPropMap[ PROP_CharLocale ] <<= aLocale; + rPropMap[ PROP_CharLocaleAsian ] <<= aLocale; + rPropMap[ PROP_CharLocaleComplex ] <<= aLocale; + } + + if( moHeight.has() ) + { + float fHeight = GetFontHeight( moHeight.get() ); + rPropMap[ PROP_CharHeight ] <<= fHeight; + rPropMap[ PROP_CharHeightAsian ] <<= fHeight; + rPropMap[ PROP_CharHeightComplex ] <<= fHeight; + } + + rPropMap[ PROP_CharKerning ] <<= (sal_Int16) GetTextSpacingPoint( moSpacing.get( 0 ) ); + + rPropMap[ PROP_CharUnderline ] <<= GetFontUnderline( moUnderline.get( XML_none ) ); + rPropMap[ PROP_CharStrikeout ] <<= GetFontStrikeout( moStrikeout.get( XML_noStrike ) ); + rPropMap[ PROP_CharCaseMap ] <<= GetCaseMap( moCaseMap.get( XML_none ) ); + + float fWeight = moBold.get( false ) ? awt::FontWeight::BOLD : awt::FontWeight::NORMAL; + rPropMap[ PROP_CharWeight ] <<= fWeight; + rPropMap[ PROP_CharWeightAsian ] <<= fWeight; + rPropMap[ PROP_CharWeightComplex ] <<= fWeight; + + awt::FontSlant eSlant = moItalic.get( false ) ? awt::FontSlant_ITALIC : awt::FontSlant_NONE; + rPropMap[ PROP_CharPosture ] <<= eSlant; + rPropMap[ PROP_CharPostureAsian ] <<= eSlant; + rPropMap[ PROP_CharPostureComplex ] <<= eSlant; + + bool bUnderlineFillFollowText = moUnderlineFillFollowText.get( false ); + if( moUnderline.has() && maUnderlineColor.isUsed() && !bUnderlineFillFollowText ) + { + rPropMap[ PROP_CharUnderlineHasColor ] <<= true; + rPropMap[ PROP_CharUnderlineColor ] <<= maUnderlineColor.getColor( rFilter.getGraphicHelper() ); + } +} + +void TextCharacterProperties::pushToPropSet( PropertySet& rPropSet, const XmlFilterBase& rFilter ) const +{ + PropertyMap aPropMap; + pushToPropMap( aPropMap, rFilter ); + rPropSet.setProperties( aPropMap ); +} + +float TextCharacterProperties::getCharHeightPoints( float fDefault ) const +{ + return moHeight.has() ? GetFontHeight( moHeight.get() ) : fDefault; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/textcharacterpropertiescontext.cxx b/oox/source/drawingml/textcharacterpropertiescontext.cxx new file mode 100644 index 000000000000..f3be44773a39 --- /dev/null +++ b/oox/source/drawingml/textcharacterpropertiescontext.cxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * 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/textcharacterpropertiescontext.hxx" + +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/textparagraphproperties.hxx" +#include "oox/core/relations.hxx" +#include "hyperlinkcontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::awt; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextCharacterProperties +TextCharacterPropertiesContext::TextCharacterPropertiesContext( + ContextHandler& rParent, + const Reference< XFastAttributeList >& rXAttributes, + TextCharacterProperties& rTextCharacterProperties ) +: ContextHandler( rParent ) +, mrTextCharacterProperties( rTextCharacterProperties ) +{ + AttributeList aAttribs( rXAttributes ); + if ( aAttribs.hasAttribute( XML_lang ) ) + mrTextCharacterProperties.moLang = aAttribs.getString( XML_lang ); + if ( aAttribs.hasAttribute( XML_sz ) ) + mrTextCharacterProperties.moHeight = aAttribs.getInteger( XML_sz ); + if ( aAttribs.hasAttribute( XML_u ) ) + mrTextCharacterProperties.moUnderline = aAttribs.getToken( XML_u ); + if ( aAttribs.hasAttribute( XML_strike ) ) + mrTextCharacterProperties.moStrikeout = aAttribs.getToken( XML_strike ); + +// mrTextCharacterProperties.moCaseMap = aAttribs.getToken( XML_cap ); + if ( aAttribs.hasAttribute( XML_b ) ) + mrTextCharacterProperties.moBold = aAttribs.getBool( XML_b ); + if ( aAttribs.hasAttribute( XML_i ) ) + mrTextCharacterProperties.moItalic = aAttribs.getBool( XML_i ); + +// TODO +/* todo: we need to be able to iterate over the XFastAttributes + + // ST_TextNonNegativePoint + const OUString sCharKerning( CREATE_OUSTRING( "CharKerning" ) ); + //case A_TOKEN( kern ): + + // ST_TextLanguageID + OUString sAltLang = rXAttributes->getOptionalValue( XML_altLang ); + + case A_TOKEN( kumimoji ): // xsd:boolean + break; + case A_TOKEN( spc ): // ST_TextPoint + case A_TOKEN( normalizeH ): // xsd:boolean + case A_TOKEN( baseline ): // ST_Percentage + case A_TOKEN( noProof ): // xsd:boolean + case A_TOKEN( dirty ): // xsd:boolean + case A_TOKEN( err ): // xsd:boolean + case A_TOKEN( smtClean ): // xsd:boolean + case A_TOKEN( smtId ): // xsd:unsignedInt + break; +*/ + +} + +TextCharacterPropertiesContext::~TextCharacterPropertiesContext() +{ +} + +// -------------------------------------------------------------------- + +void TextCharacterPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextCharacterPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttributes ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( xAttributes ); + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { +// TODO unsupported yet +// case A_TOKEN( ln ): // CT_LineProperties +// xRet.set( new LinePropertiesContext( getHandler(), xAttributes, maTextOutlineProperties ) ); +// break; + + case A_TOKEN( solidFill ): // EG_FillProperties + xRet.set( new ColorContext( *this, mrTextCharacterProperties.maCharColor ) ); + break; + + // EG_EffectProperties + case A_TOKEN( effectDag ): // CT_EffectContainer 5.1.10.25 + case A_TOKEN( effectLst ): // CT_EffectList 5.1.10.26 + break; + + case A_TOKEN( highlight ): // CT_Color + xRet.set( new ColorContext( *this, mrTextCharacterProperties.maHighlightColor ) ); + break; + + // EG_TextUnderlineLine + case A_TOKEN( uLnTx ): // CT_TextUnderlineLineFollowText + mrTextCharacterProperties.moUnderlineLineFollowText = true; + break; +// TODO unsupported yet +// case A_TOKEN( uLn ): // CT_LineProperties +// xRet.set( new LinePropertiesContext( getHandler(), xAttributes, maUnderlineProperties ) ); +// break; + + // EG_TextUnderlineFill + case A_TOKEN( uFillTx ): // CT_TextUnderlineFillFollowText + mrTextCharacterProperties.moUnderlineFillFollowText = true; + break; + case A_TOKEN( uFill ): // CT_TextUnderlineFillGroupWrapper->EG_FillProperties (not supported) + xRet.set( new SimpleFillPropertiesContext( *this, mrTextCharacterProperties.maUnderlineColor ) ); + break; + + // CT_FontCollection + case A_TOKEN( latin ): // CT_TextFont + mrTextCharacterProperties.maLatinFont.setAttributes( aAttribs ); + break; + case A_TOKEN( ea ): // CT_TextFont + mrTextCharacterProperties.maAsianFont.setAttributes( aAttribs ); + break; + case A_TOKEN( cs ): // CT_TextFont + mrTextCharacterProperties.maComplexFont.setAttributes( aAttribs ); + break; + case A_TOKEN( sym ): // CT_TextFont + mrTextCharacterProperties.maSymbolFont.setAttributes( aAttribs ); + break; + + case A_TOKEN( hlinkClick ): // CT_Hyperlink + case A_TOKEN( hlinkMouseOver ): // CT_Hyperlink + xRet.set( new HyperLinkContext( *this, xAttributes, mrTextCharacterProperties.maHyperlinkPropertyMap ) ); + break; + } + if( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textfield.cxx b/oox/source/drawingml/textfield.cxx new file mode 100644 index 000000000000..c3049415c89a --- /dev/null +++ b/oox/source/drawingml/textfield.cxx @@ -0,0 +1,195 @@ +/************************************************************************* + * + * 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/textfield.hxx" + +#include <list> + +#include <rtl/ustring.hxx> +#include <rtl/string.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/text/XTextField.hpp> + +#include "oox/helper/helper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/textparagraphproperties.hxx" +#include "oox/drawingml/textcharacterproperties.hxx" + +using ::rtl::OString; +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +namespace oox { namespace drawingml { + +TextField::TextField() +{ +} + +namespace { + +/** intsanciate the textfields. Because of semantics difference between + * OpenXML and OpenOffice, some OpenXML field might cause two fields to be created. + * @param aFields the created fields. The list is empty if no field has been created. + * @param xModel the model + * @param sType the OpenXML field type. + */ +void lclCreateTextFields( std::list< Reference< XTextField > > & aFields, + const Reference< XModel > & xModel, const OUString & sType ) +{ + Reference< XInterface > xIface; + Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW ); + + if( sType.compareToAscii( "datetime", 8 ) == 0) + { + OString s = ::rtl::OUStringToOString( sType, RTL_TEXTENCODING_UTF8); + OString p( s.pData->buffer + 8 ); + try + { + bool bIsDate = true; + int idx = p.toInt32(); +// OSL_TRACE( "OOX: p = %s, %d", p.pData->buffer, idx ); + xIface = xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.DateTime" ) ); + aFields.push_back( Reference< XTextField > ( xIface, UNO_QUERY ) ); + Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW ); + + // here we should format the field properly. waiting after #i81091. + switch( idx ) + { + case 1: // Date dd/mm/yyyy + // this is the default format... + break; + case 2: // Date Day, Month dd, yyyy + break; + case 3: // Date dd Month yyyy + break; + case 4: // Date Month dd, yyyy + break; + case 5: // Date dd-Mon-yy + break; + case 6: // Date Month yy + break; + case 7: // Date Mon-yy + break; + case 8: // DateTime dd/mm/yyyy H:MM PM + lclCreateTextFields( aFields, xModel, CREATE_OUSTRING( "datetime12" ) ); + break; + case 9: // DateTime dd/mm/yy H:MM:SS PM + lclCreateTextFields( aFields, xModel, CREATE_OUSTRING( "datetime13" ) ); + break; + case 10: // Time H:MM + bIsDate = false; + break; + case 11: // Time H:MM:SS + bIsDate = false; + // this is the default format + break; + case 12: // Time H:MM PM + bIsDate = false; + break; + case 13: // Time H:MM:SS PM + bIsDate = false; + break; + } + xProps->setPropertyValue( CREATE_OUSTRING( "IsDate" ), makeAny( bIsDate ) ); + xProps->setPropertyValue( CREATE_OUSTRING( "IsFixed" ), makeAny( false ) ); + } + catch(Exception & e) + { + OSL_TRACE( "Exception %s", OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + } + else if ( sType.compareToAscii( "slidenum" ) == 0 ) + { + xIface = xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.PageNumber" ) ); + aFields.push_back( Reference< XTextField > ( xIface, UNO_QUERY ) ); + } +} + +} // namespace + +void TextField::insertAt( + const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XText > & xText, + const Reference < XTextCursor > &xAt, + const TextCharacterProperties& rTextCharacterStyle ) const +{ + try + { + PropertyMap aioBulletList; + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + Reference< XPropertySet > xProps( xStart, UNO_QUERY); + PropertySet aPropSet( xProps ); + + maTextParagraphProperties.pushToPropSet( rFilterBase, xProps, aioBulletList, NULL, sal_True, 18 ); + + TextCharacterProperties aTextCharacterProps( rTextCharacterStyle ); + aTextCharacterProps.assignUsed( maTextParagraphProperties.getTextCharacterProperties() ); + aTextCharacterProps.assignUsed( getTextCharacterProperties() ); + aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase ); + + std::list< Reference< XTextField > > fields; + lclCreateTextFields( fields, rFilterBase.getModel(), msType ); + if( !fields.empty() ) + { + bool bFirst = true; + for( std::list< Reference< XTextField > >::iterator iter = fields.begin(); + iter != fields.end(); ++iter ) + { + if( iter->is() ) + { + Reference< XTextContent > xContent( *iter, UNO_QUERY); + if( bFirst) + { + bFirst = false; + } + else + { + xText->insertString( xStart, CREATE_OUSTRING( " " ), sal_False ); + } + xText->insertTextContent( xStart, xContent, sal_False ); + } + } + } + else + { + xText->insertString( xStart, getText(), sal_False ); + } + } + catch( const Exception& ) + { + OSL_TRACE("OOX: TextField::insertAt() exception"); + } +} + +} } diff --git a/oox/source/drawingml/textfieldcontext.cxx b/oox/source/drawingml/textfieldcontext.cxx new file mode 100644 index 000000000000..4e9f576a0ca9 --- /dev/null +++ b/oox/source/drawingml/textfieldcontext.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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/textfieldcontext.hxx" +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/textfield.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +TextFieldContext::TextFieldContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& rXAttributes, + TextField& rTextField) + : ContextHandler( rParent ) + , mrTextField( rTextField ) + , mbIsInText( false ) +{ + mrTextField.setUuid( rXAttributes->getOptionalValue( XML_id ) ); + mrTextField.setType( rXAttributes->getOptionalValue( XML_type ) ); +} + +void TextFieldContext::endFastElement( sal_Int32 aElementToken ) throw (SAXException, RuntimeException) +{ + if( aElementToken == (A_TOKEN( t )) ) + { + mbIsInText = false; + } +} + +void TextFieldContext::characters( const OUString& aChars ) throw (SAXException, RuntimeException) +{ + if( mbIsInText ) + { + mrTextField.getText() += aChars; + } +} + +Reference< XFastContextHandler > TextFieldContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case A_TOKEN( rPr ): + xRet.set( new TextCharacterPropertiesContext( *this, xAttribs, mrTextField.getTextCharacterProperties() ) ); + break; + case A_TOKEN( pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, xAttribs, mrTextField.getTextParagraphProperties() ) ); + break; + case A_TOKEN( t ): + mbIsInText = true; + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + + +} } diff --git a/oox/source/drawingml/textfont.cxx b/oox/source/drawingml/textfont.cxx new file mode 100644 index 000000000000..b4f9d359fb14 --- /dev/null +++ b/oox/source/drawingml/textfont.cxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * 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/textfont.hxx" +#include <com/sun/star/awt/FontFamily.hpp> +#include <com/sun/star/awt/FontPitch.hpp> +#include "oox/drawingml/theme.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; +using ::oox::core::XmlFilterBase; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +namespace { + +sal_Int16 lclGetFontPitch( sal_Int32 nOoxValue ) +{ + using namespace ::com::sun::star::awt::FontPitch; + static const sal_Int16 spnFontPitch[] = { DONTKNOW, FIXED, VARIABLE }; + return STATIC_ARRAY_SELECT( spnFontPitch, nOoxValue, DONTKNOW ); +} + +sal_Int16 lclGetFontFamily( sal_Int32 nOoxValue ) +{ + using namespace ::com::sun::star::awt::FontFamily; + static const sal_Int16 spnFontFamily[] = { DONTKNOW, ROMAN, SWISS, MODERN, SCRIPT, DECORATIVE }; + return STATIC_ARRAY_SELECT( spnFontFamily, nOoxValue, DONTKNOW ); +} + +} // namespace + +// ============================================================================ + +TextFont::TextFont() : + mnPitch( 0 ), + mnCharset( WINDOWS_CHARSET_ANSI ) +{ +} + +void TextFont::setAttributes( const AttributeList& rAttribs ) +{ + maTypeface = rAttribs.getString( XML_typeface, OUString() ); + maPanose = rAttribs.getString( XML_panose, OUString() ); + mnPitch = rAttribs.getInteger( XML_pitchFamily, 0 ); + mnCharset = rAttribs.getInteger( XML_charset, WINDOWS_CHARSET_DEFAULT ); +} + +void TextFont::assignIfUsed( const TextFont& rTextFont ) +{ + if( rTextFont.maTypeface.getLength() > 0 ) + *this = rTextFont; +} + +bool TextFont::getFontData( OUString& rFontName, sal_Int16 rnFontPitch, sal_Int16& rnFontFamily, const XmlFilterBase& rFilter ) const +{ + if( const Theme* pTheme = rFilter.getCurrentTheme() ) + if( const TextFont* pFont = pTheme->resolveFont( maTypeface ) ) + return pFont->implGetFontData( rFontName, rnFontPitch, rnFontFamily ); + return implGetFontData( rFontName, rnFontPitch, rnFontFamily ); +} + +bool TextFont::implGetFontData( OUString& rFontName, sal_Int16 rnFontPitch, sal_Int16& rnFontFamily ) const +{ + rFontName = maTypeface; + rnFontPitch = lclGetFontPitch( extractValue< sal_Int16 >( mnPitch, 0, 4 ) ); + rnFontFamily = lclGetFontFamily( extractValue< sal_Int16 >( mnPitch, 4, 4 ) ); + return rFontName.getLength() > 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/textliststyle.cxx b/oox/source/drawingml/textliststyle.cxx new file mode 100644 index 000000000000..8a491076909f --- /dev/null +++ b/oox/source/drawingml/textliststyle.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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/textliststyle.hxx" + +namespace oox { namespace drawingml { + +TextListStyle::TextListStyle() +{ + for ( int i = 0; i < 9; i++ ) + { + maListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) ); + maAggregationListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) ); + } +} + +TextListStyle::~TextListStyle() +{ +} + +void applyStyleList( const TextParagraphPropertiesVector& rSourceListStyle, TextParagraphPropertiesVector& rDestListStyle ) +{ + TextParagraphPropertiesVector::const_iterator aSourceListStyleIter( rSourceListStyle.begin() ); + TextParagraphPropertiesVector::iterator aDestListStyleIter( rDestListStyle.begin() ); + while( aSourceListStyleIter != rSourceListStyle.end() ) + { + if ( aDestListStyleIter != rDestListStyle.end() ) + { + (*aDestListStyleIter)->apply( **aSourceListStyleIter ); + aDestListStyleIter++; + } + else + rDestListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties( **aSourceListStyleIter ) ) ); + aSourceListStyleIter++; + } +} + +void TextListStyle::apply( const TextListStyle& rTextListStyle ) +{ + applyStyleList( rTextListStyle.getAggregationListStyle(), getAggregationListStyle() ); + applyStyleList( rTextListStyle.getListStyle(), getListStyle() ); +} + +} } diff --git a/oox/source/drawingml/textliststylecontext.cxx b/oox/source/drawingml/textliststylecontext.cxx new file mode 100644 index 000000000000..21afc698d730 --- /dev/null +++ b/oox/source/drawingml/textliststylecontext.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * 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/textliststylecontext.hxx" +#include "oox/drawingml/textparagraphpropertiescontext.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + +// -------------------------------------------------------------------- + +// CT_TextListStyle +TextListStyleContext::TextListStyleContext( ContextHandler& rParent, TextListStyle& rTextListStyle ) +: ContextHandler( rParent ) +, mrTextListStyle( rTextListStyle ) +{ +} + +TextListStyleContext::~TextListStyleContext() +{ +} + +// -------------------------------------------------------------------- + +void TextListStyleContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextListStyleContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rxAttributes ) throw (SAXException, RuntimeException) +{ + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case A_TOKEN( defPPr ): // CT_TextParagraphProperties + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 0 ] ) ); + break; + case A_TOKEN( outline1pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getAggregationListStyle()[ 0 ] ) ); + break; + case A_TOKEN( outline2pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getAggregationListStyle()[ 1 ] ) ); + break; + case A_TOKEN( lvl1pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 0 ] ) ); + break; + case A_TOKEN( lvl2pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 1 ] ) ); + break; + case A_TOKEN( lvl3pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 2 ] ) ); + break; + case A_TOKEN( lvl4pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 3 ] ) ); + break; + case A_TOKEN( lvl5pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 4 ] ) ); + break; + case A_TOKEN( lvl6pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 5 ] ) ); + break; + case A_TOKEN( lvl7pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 6 ] ) ); + break; + case A_TOKEN( lvl8pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 7 ] ) ); + break; + case A_TOKEN( lvl9pPr ): + xRet.set( new TextParagraphPropertiesContext( *this, rxAttributes, *mrTextListStyle.getListStyle()[ 8 ] ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textparagraph.cxx b/oox/source/drawingml/textparagraph.cxx new file mode 100644 index 000000000000..a4bef1a5013c --- /dev/null +++ b/oox/source/drawingml/textparagraph.cxx @@ -0,0 +1,130 @@ +/************************************************************************* + * + * 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/textparagraph.hxx" +#include "oox/drawingml/drawingmltypes.hxx" + +#include <rtl/ustring.hxx> +#include "oox/helper/propertyset.hxx" +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/text/ControlCharacter.hpp> + +using ::rtl::OUString; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +namespace oox { namespace drawingml { + +TextParagraph::TextParagraph() +{ +} + +TextParagraph::~TextParagraph() +{ +} + +void TextParagraph::insertAt( + const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XText > &xText, + const Reference < XTextCursor > &xAt, + const TextCharacterProperties& rTextStyleProperties, + const TextListStyle& rTextListStyle, bool bFirst) const +{ + try { + sal_Int32 nParagraphSize = 0; + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + + sal_Int16 nLevel = maProperties.getLevel(); + const TextParagraphPropertiesVector& rListStyle = rTextListStyle.getListStyle(); + if ( nLevel >= static_cast< sal_Int16 >( rListStyle.size() ) ) + nLevel = 0; + TextParagraphPropertiesPtr pTextParagraphStyle; + if ( rListStyle.size() ) + pTextParagraphStyle = rListStyle[ nLevel ]; + + TextCharacterProperties aTextCharacterStyle( rTextStyleProperties ); + if ( pTextParagraphStyle.get() ) + aTextCharacterStyle.assignUsed( pTextParagraphStyle->getTextCharacterProperties() ); + aTextCharacterStyle.assignUsed( maProperties.getTextCharacterProperties() ); + + if( !bFirst ) + { + xText->insertControlCharacter( xStart, ControlCharacter::APPEND_PARAGRAPH, sal_False ); + xAt->gotoEnd( sal_True ); + } + if ( maRuns.begin() == maRuns.end() ) + { + PropertySet aPropSet( xStart ); + + TextCharacterProperties aTextCharacterProps( aTextCharacterStyle ); + aTextCharacterProps.assignUsed( maEndProperties ); + aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase ); + } + else + { + for( TextRunVector::const_iterator aIt = maRuns.begin(), aEnd = maRuns.end(); aIt != aEnd; ++aIt ) + { + (*aIt)->insertAt( rFilterBase, xText, xAt, aTextCharacterStyle ); + nParagraphSize += (*aIt)->getText().getLength(); + } + } + xAt->gotoEnd( sal_True ); + + PropertyMap aioBulletList; + Reference< XPropertySet > xProps( xStart, UNO_QUERY); + float fCharacterSize = 18; + if ( pTextParagraphStyle.get() ) + { + pTextParagraphStyle->pushToPropSet( rFilterBase, xProps, aioBulletList, NULL, sal_False, fCharacterSize ); + fCharacterSize = pTextParagraphStyle->getCharHeightPoints( 18 ); + } + maProperties.pushToPropSet( rFilterBase, xProps, aioBulletList, &pTextParagraphStyle->getBulletList(), sal_True, fCharacterSize ); + + // empty paragraphs do not have bullets in ppt + if ( !nParagraphSize ) + { + const OUString sNumberingLevel( CREATE_OUSTRING( "NumberingLevel" ) ); + xProps->setPropertyValue( sNumberingLevel, Any( static_cast< sal_Int16 >( -1 ) ) ); + } + +// FIXME this is causing a lot of dispruption (ie does not work). I wonder what to do -- Hub +// Reference< XTextRange > xEnd( xAt, UNO_QUERY ); +// Reference< XPropertySet > xProps2( xEnd, UNO_QUERY ); +// mpEndProperties->pushToPropSet( xProps2 ); + } + catch( Exception & ) + { + OSL_TRACE("OOX: exception in TextParagraph::insertAt"); + } +} + + +} } + diff --git a/oox/source/drawingml/textparagraphproperties.cxx b/oox/source/drawingml/textparagraphproperties.cxx new file mode 100644 index 000000000000..cd969874513e --- /dev/null +++ b/oox/source/drawingml/textparagraphproperties.cxx @@ -0,0 +1,423 @@ +/************************************************************************* + * + * 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/textparagraphproperties.hxx" + +#include <com/sun/star/text/XNumberingRulesSupplier.hpp> +#include <com/sun/star/container/XIndexReplace.hpp> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include "oox/helper/helper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/drawingmltypes.hxx" + +using rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::container; +using ::com::sun::star::awt::FontDescriptor; + +namespace oox { namespace drawingml { + +BulletList::BulletList( ) +: maBulletColorPtr( new Color() ) +{ +} + +bool BulletList::is() const +{ + return mnNumberingType.hasValue(); +} + +void BulletList::setBulletChar( const ::rtl::OUString & sChar ) +{ + mnNumberingType <<= NumberingType::CHAR_SPECIAL; + msBulletChar <<= sChar; +} + +void BulletList::setGraphic( ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >& rXGraphic ) +{ + mnNumberingType <<= NumberingType::BITMAP; + maGraphic <<= rXGraphic; +} + +void BulletList::setNone( ) +{ + mnNumberingType <<= NumberingType::NUMBER_NONE; +} + +void BulletList::setSuffixParenBoth() +{ + msNumberingSuffix <<= CREATE_OUSTRING( ")" ); + msNumberingPrefix <<= CREATE_OUSTRING( "(" ); +} + +void BulletList::setSuffixParenRight() +{ + msNumberingSuffix <<= CREATE_OUSTRING( ")" ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixPeriod() +{ + msNumberingSuffix <<= CREATE_OUSTRING( "." ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixNone() +{ + msNumberingSuffix <<= OUString(); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setSuffixMinusRight() +{ + msNumberingSuffix <<= CREATE_OUSTRING( "-" ); + msNumberingPrefix <<= OUString(); +} + +void BulletList::setType( sal_Int32 nType ) +{ +// OSL_TRACE( "OOX: set list numbering type %d", nType); + switch( nType ) + { + case XML_alphaLcParenBoth: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixParenBoth(); + break; + case XML_alphaLcParenR: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixParenRight(); + break; + case XML_alphaLcPeriod: + mnNumberingType <<= NumberingType::CHARS_LOWER_LETTER; + setSuffixPeriod(); + break; + case XML_alphaUcParenBoth: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixParenBoth(); + break; + case XML_alphaUcParenR: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixParenRight(); + break; + case XML_alphaUcPeriod: + mnNumberingType <<= NumberingType::CHARS_UPPER_LETTER; + setSuffixPeriod(); + break; + case XML_arabic1Minus: + case XML_arabic2Minus: + case XML_arabicDbPeriod: + case XML_arabicDbPlain: + // TODO + break; + case XML_arabicParenBoth: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixParenBoth(); + break; + case XML_arabicParenR: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixParenRight(); + break; + case XML_arabicPeriod: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixPeriod(); + break; + case XML_arabicPlain: + mnNumberingType <<= NumberingType::ARABIC; + setSuffixNone(); + break; + case XML_circleNumDbPlain: + case XML_circleNumWdBlackPlain: + case XML_circleNumWdWhitePlain: + mnNumberingType <<= NumberingType::CIRCLE_NUMBER; + break; + case XML_ea1ChsPeriod: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; + setSuffixPeriod(); + break; + case XML_ea1ChsPlain: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH; + setSuffixNone(); + break; + case XML_ea1ChtPeriod: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; + setSuffixPeriod(); + break; + case XML_ea1ChtPlain: + mnNumberingType <<= NumberingType::NUMBER_UPPER_ZH_TW; + setSuffixNone(); + break; + case XML_ea1JpnChsDbPeriod: + case XML_ea1JpnKorPeriod: + case XML_ea1JpnKorPlain: + break; + case XML_hebrew2Minus: + mnNumberingType <<= NumberingType::CHARS_HEBREW; + setSuffixMinusRight(); + break; + case XML_hindiAlpha1Period: + case XML_hindiAlphaPeriod: + case XML_hindiNumParenR: + case XML_hindiNumPeriod: + // TODO + break; + case XML_romanLcParenBoth: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixParenBoth(); + break; + case XML_romanLcParenR: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixParenRight(); + break; + case XML_romanLcPeriod: + mnNumberingType <<= NumberingType::ROMAN_LOWER; + setSuffixPeriod(); + break; + case XML_romanUcParenBoth: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixParenBoth(); + break; + case XML_romanUcParenR: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixParenRight(); + break; + case XML_romanUcPeriod: + mnNumberingType <<= NumberingType::ROMAN_UPPER; + setSuffixPeriod(); + break; + case XML_thaiAlphaParenBoth: + case XML_thaiNumParenBoth: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixParenBoth(); + break; + case XML_thaiAlphaParenR: + case XML_thaiNumParenR: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixParenRight(); + break; + case XML_thaiAlphaPeriod: + case XML_thaiNumPeriod: + mnNumberingType <<= NumberingType::CHARS_THAI; + setSuffixPeriod(); + break; + } +} + +void BulletList::setBulletSize(sal_Int16 nSize) +{ + mnSize <<= nSize; +} + + +void BulletList::setFontSize(sal_Int16 nSize) +{ + mnFontSize <<= nSize; +} + +void BulletList::apply( const BulletList& rSource ) +{ + if ( rSource.maBulletColorPtr->isUsed() ) + maBulletColorPtr = rSource.maBulletColorPtr; + if ( rSource.mbBulletColorFollowText.hasValue() ) + mbBulletColorFollowText = rSource.mbBulletColorFollowText; + if ( rSource.mbBulletFontFollowText.hasValue() ) + mbBulletFontFollowText = rSource.mbBulletFontFollowText; + maBulletFont.assignIfUsed( rSource.maBulletFont ); + if ( rSource.msBulletChar.hasValue() ) + msBulletChar = rSource.msBulletChar; + if ( rSource.mnStartAt.hasValue() ) + mnStartAt = rSource.mnStartAt; + if ( rSource.mnNumberingType.hasValue() ) + mnNumberingType = rSource.mnNumberingType; + if ( rSource.msNumberingPrefix.hasValue() ) + msNumberingPrefix = rSource.msNumberingPrefix; + if ( rSource.msNumberingSuffix.hasValue() ) + msNumberingSuffix = rSource.msNumberingSuffix; + if ( rSource.mnSize.hasValue() ) + mnSize = rSource.mnSize; + if ( rSource.mnFontSize.hasValue() ) + mnFontSize = rSource.mnFontSize; + if ( rSource.maStyleName.hasValue() ) + maStyleName = rSource.maStyleName; + if ( rSource.maGraphic.hasValue() ) + maGraphic = rSource.maGraphic; +} + +void BulletList::pushToPropMap( const ::oox::core::XmlFilterBase& rFilterBase, PropertyMap& rPropMap ) const +{ + if( msNumberingPrefix.hasValue() ) + rPropMap[ PROP_Prefix ] = msNumberingPrefix; + if( msNumberingSuffix.hasValue() ) + rPropMap[ PROP_Suffix ] = msNumberingSuffix; + if( mnStartAt.hasValue() ) + rPropMap[ PROP_StartWith ] = mnStartAt; + rPropMap[ PROP_Adjust ] <<= HoriOrientation::LEFT; + + if( mnNumberingType.hasValue() ) + rPropMap[ PROP_NumberingType ] = mnNumberingType; + + OUString aBulletFontName; + sal_Int16 nBulletFontPitch = 0; + sal_Int16 nBulletFontFamily = 0; + if( maBulletFont.getFontData( aBulletFontName, nBulletFontPitch, nBulletFontFamily, rFilterBase ) ) + { + FontDescriptor aFontDesc; + sal_Int16 nFontSize = 0; + if( mnFontSize >>= nFontSize ) + aFontDesc.Height = nFontSize; + + // TODO move the to the TextFont struct. + aFontDesc.Name = aBulletFontName; + aFontDesc.Pitch = nBulletFontPitch; + aFontDesc.Family = nBulletFontFamily; + rPropMap[ PROP_BulletFont ] <<= aFontDesc; + rPropMap[ PROP_BulletFontName ] <<= aBulletFontName; + } + if ( msBulletChar.hasValue() ) + rPropMap[ PROP_BulletChar ] = msBulletChar; + if ( maGraphic.hasValue() ) + { + Reference< com::sun::star::awt::XBitmap > xBitmap( maGraphic, UNO_QUERY ); + if ( xBitmap.is() ) + rPropMap[ PROP_Graphic ] <<= xBitmap; + } + if( mnSize.hasValue() ) + rPropMap[ PROP_BulletRelSize ] = mnSize; + if ( maStyleName.hasValue() ) + rPropMap[ PROP_CharStyleName ] <<= maStyleName; + if ( maBulletColorPtr->isUsed() ) + rPropMap[ PROP_BulletColor ] <<= maBulletColorPtr->getColor( rFilterBase.getGraphicHelper() ); +} + +TextParagraphProperties::TextParagraphProperties() +: mnLevel( 0 ) +{ +} + +TextParagraphProperties::~TextParagraphProperties() +{ +} + +void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps ) +{ + maTextParagraphPropertyMap.insert( rSourceProps.maTextParagraphPropertyMap.begin(), rSourceProps.maTextParagraphPropertyMap.end() ); + maBulletList.apply( rSourceProps.maBulletList ); + maTextCharacterProperties.assignUsed( rSourceProps.maTextCharacterProperties ); + if ( rSourceProps.maParaTopMargin.bHasValue ) + maParaTopMargin = rSourceProps.maParaTopMargin; + if ( rSourceProps.maParaBottomMargin.bHasValue ) + maParaBottomMargin = rSourceProps.maParaBottomMargin; + if ( rSourceProps.moParaLeftMargin ) + moParaLeftMargin = rSourceProps.moParaLeftMargin; + if ( rSourceProps.moFirstLineIndentation ) + moFirstLineIndentation = rSourceProps.moFirstLineIndentation; +} + +void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, sal_Bool bApplyBulletMap, float fCharacterSize ) const +{ + PropertySet aPropSet( xPropSet ); + aPropSet.setProperties( maTextParagraphPropertyMap ); + + sal_Int32 nNumberingType = NumberingType::NUMBER_NONE; + if ( maBulletList.mnNumberingType.hasValue() ) + maBulletList.mnNumberingType >>= nNumberingType; + else if ( pMasterBuList && pMasterBuList->mnNumberingType.hasValue() ) + pMasterBuList->mnNumberingType >>= nNumberingType; + if ( nNumberingType == NumberingType::NUMBER_NONE ) + aPropSet.setProperty< sal_Int16 >( PROP_NumberingLevel, -1 ); + + maBulletList.pushToPropMap( rFilterBase, rioBulletMap ); + + if ( maParaTopMargin.bHasValue ) + aPropSet.setProperty( PROP_ParaTopMargin, maParaTopMargin.toMargin( getCharHeightPoints( 18.0 ) ) ); + if ( maParaBottomMargin.bHasValue ) + aPropSet.setProperty( PROP_ParaBottomMargin, maParaBottomMargin.toMargin( getCharHeightPoints( 18.0 ) ) ); + if ( nNumberingType == NumberingType::BITMAP ) + { + fCharacterSize = getCharHeightPoints( fCharacterSize ); + + com::sun::star::awt::Size aBulletSize; + aBulletSize.Width = aBulletSize.Height = static_cast< sal_Int32 >( ( fCharacterSize * ( 2540.0 / 72.0 ) * 0.8 ) ); + rioBulletMap[ PROP_GraphicSize ] <<= aBulletSize; + } + + boost::optional< sal_Int32 > noParaLeftMargin( moParaLeftMargin ); + boost::optional< sal_Int32 > noFirstLineIndentation( moFirstLineIndentation ); + + if ( nNumberingType != NumberingType::NUMBER_NONE ) + { + if ( noParaLeftMargin ) + { + rioBulletMap[ PROP_LeftMargin ] <<= static_cast< sal_Int32 >( *noParaLeftMargin ); + noParaLeftMargin = boost::optional< sal_Int32 >( 0 ); + } + if ( noFirstLineIndentation ) + { + rioBulletMap[ PROP_FirstLineOffset ] <<= static_cast< sal_Int32 >( *noFirstLineIndentation ); + noFirstLineIndentation = boost::optional< sal_Int32 >( 0 ); + } + } + + if ( bApplyBulletMap ) + { + Reference< XIndexReplace > xNumRule; + aPropSet.getProperty( xNumRule, PROP_NumberingRules ); + OSL_ENSURE( xNumRule.is(), "can't get Numbering rules"); + + if( xNumRule.is() ) + { + if( !rioBulletMap.empty() ) + { + Sequence< PropertyValue > aBulletPropSeq = rioBulletMap.makePropertyValueSequence(); + xNumRule->replaceByIndex( getLevel(), makeAny( aBulletPropSeq ) ); + } + + aPropSet.setProperty( PROP_NumberingRules, xNumRule ); + } + } + if ( noParaLeftMargin ) + aPropSet.setProperty( PROP_ParaLeftMargin, *noParaLeftMargin ); + if ( noFirstLineIndentation ) + aPropSet.setProperty( PROP_ParaFirstLineIndent, *noFirstLineIndentation ); +} + +float TextParagraphProperties::getCharHeightPoints( float fDefault ) const +{ + return maTextCharacterProperties.getCharHeightPoints( fDefault ); +} + +} } diff --git a/oox/source/drawingml/textparagraphpropertiescontext.cxx b/oox/source/drawingml/textparagraphpropertiescontext.cxx new file mode 100644 index 000000000000..eb888867556b --- /dev/null +++ b/oox/source/drawingml/textparagraphpropertiescontext.cxx @@ -0,0 +1,283 @@ +/************************************************************************* + * + * 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/textparagraphpropertiescontext.hxx" + +#include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> + +#include "oox/drawingml/colorchoicecontext.hxx" +#include "oox/drawingml/textcharacterpropertiescontext.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/helper/attributelist.hxx" +#include "textspacingcontext.hxx" +#include "texttabstoplistcontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using ::com::sun::star::awt::FontDescriptor; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; + +namespace oox { namespace drawingml { + +// CT_TextParagraphProperties +TextParagraphPropertiesContext::TextParagraphPropertiesContext( ContextHandler& rParent, + const Reference< XFastAttributeList >& xAttribs, + TextParagraphProperties& rTextParagraphProperties ) +: ContextHandler( rParent ) +, mrTextParagraphProperties( rTextParagraphProperties ) +, mrSpaceBefore( rTextParagraphProperties.getParaTopMargin() ) +, mrSpaceAfter( rTextParagraphProperties.getParaBottomMargin() ) +, mrBulletList( rTextParagraphProperties.getBulletList() ) +{ + OUString sValue; + AttributeList attribs( xAttribs ); + + PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() ); + + // ST_TextAlignType + if ( xAttribs->hasAttribute( XML_algn ) ) + { + sal_Int32 nAlign = xAttribs->getOptionalValueToken( XML_algn, XML_l ); + rPropertyMap[ PROP_ParaAdjust ] <<= GetParaAdjust( nAlign ); + } +// OSL_TRACE( "OOX: para adjust %d", GetParaAdjust( nAlign )); + // TODO see to do the same with RubyAdjust + + // ST_Coordinate32 +// sValue = xAttribs->getOptionalValue( XML_defTabSz ); SJ: we need to be able to set the default tab size for each text object, +// this is possible at the moment only for the whole document. +// sal_Int32 nDefTabSize = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + // TODO + +// bool bEaLineBrk = attribs.getBool( XML_eaLnBrk, true ); + if ( xAttribs->hasAttribute( XML_latinLnBrk ) ) + { + bool bLatinLineBrk = attribs.getBool( XML_latinLnBrk, true ); + rPropertyMap[ PROP_ParaIsHyphenation ] <<= bLatinLineBrk; + } + // TODO see what to do with Asian hyphenation + + // ST_TextFontAlignType + // TODO +// sal_Int32 nFontAlign = xAttribs->getOptionalValueToken( XML_fontAlgn, XML_base ); + + if ( xAttribs->hasAttribute( XML_hangingPunct ) ) + { + bool bHangingPunct = attribs.getBool( XML_hangingPunct, false ); + rPropertyMap[ PROP_ParaIsHangingPunctuation ] <<= bHangingPunct; + } + + // ST_Coordinate + if ( xAttribs->hasAttribute( XML_indent ) ) + { + sValue = xAttribs->getOptionalValue( XML_indent ); + mrTextParagraphProperties.getFirstLineIndentation() = boost::optional< sal_Int32 >( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + } + + // ST_TextIndentLevelType + // -1 is an invalid value and denote the lack of level + sal_Int32 nLevel = attribs.getInteger( XML_lvl, 0 ); + if( nLevel > 8 || nLevel < 0 ) + { + nLevel = 0; + } + + mrTextParagraphProperties.setLevel( static_cast< sal_Int16 >( nLevel ) ); + + char name[] = "Outline X"; + name[8] = static_cast<char>( '1' + nLevel ); + const OUString sStyleNameValue( rtl::OUString::createFromAscii( name ) ); + mrBulletList.setStyleName( sStyleNameValue ); + + // ST_TextMargin + // ParaLeftMargin + if ( xAttribs->hasAttribute( XML_marL ) ) + { + sValue = xAttribs->getOptionalValue( XML_marL ); + mrTextParagraphProperties.getParaLeftMargin() = boost::optional< sal_Int32 >( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + } + + // ParaRightMargin + if ( xAttribs->hasAttribute( XML_marR ) ) + { + sValue = xAttribs->getOptionalValue( XML_marR ); + sal_Int32 nMarR = ( sValue.getLength() == 0 ? 0 : GetCoordinate( sValue ) ); + rPropertyMap[ PROP_ParaRightMargin ] <<= nMarR; + } + + if ( xAttribs->hasAttribute( XML_rtl ) ) + { + bool bRtl = attribs.getBool( XML_rtl, false ); + rPropertyMap[ PROP_TextWritingMode ] <<= ( bRtl ? WritingMode_RL_TB : WritingMode_LR_TB ); + } +} + + + +TextParagraphPropertiesContext::~TextParagraphPropertiesContext() +{ + PropertyMap& rPropertyMap( mrTextParagraphProperties.getTextParagraphPropertyMap() ); + if ( maLineSpacing.bHasValue ) + rPropertyMap[ PROP_ParaLineSpacing ] <<= maLineSpacing.toLineSpacing(); + + ::std::list< TabStop >::size_type nTabCount = maTabList.size(); + if( nTabCount != 0 ) + { + Sequence< TabStop > aSeq( nTabCount ); + TabStop * aArray = aSeq.getArray(); + OSL_ENSURE( aArray != NULL, "sequence array is NULL" ); + ::std::copy( maTabList.begin(), maTabList.end(), aArray ); + rPropertyMap[ PROP_ParaTabStops ] <<= aSeq; + } + + if ( mxBlipProps.get() && mxBlipProps->mxGraphic.is() ) + mrBulletList.setGraphic( mxBlipProps->mxGraphic ); + + if( mrBulletList.is() ) + rPropertyMap[ PROP_IsNumbering ] <<= sal_True; + sal_Int16 nLevel = mrTextParagraphProperties.getLevel(); + rPropertyMap[ PROP_NumberingLevel ] <<= nLevel; + rPropertyMap[ PROP_NumberingIsNumber ] <<= sal_True; +} + +// -------------------------------------------------------------------- + +void TextParagraphPropertiesContext::endFastElement( sal_Int32 ) throw (SAXException, RuntimeException) +{ +} + + + +// -------------------------------------------------------------------- + +Reference< XFastContextHandler > TextParagraphPropertiesContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& rXAttributes ) throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rXAttributes ); + Reference< XFastContextHandler > xRet; + switch( aElementToken ) + { + case A_TOKEN( lnSpc ): // CT_TextSpacing + xRet.set( new TextSpacingContext( *this, maLineSpacing ) ); + break; + case A_TOKEN( spcBef ): // CT_TextSpacing + xRet.set( new TextSpacingContext( *this, mrSpaceBefore ) ); + break; + case A_TOKEN( spcAft ): // CT_TextSpacing + xRet.set( new TextSpacingContext( *this, mrSpaceAfter ) ); + break; + + // EG_TextBulletColor + case A_TOKEN( buClrTx ): // CT_TextBulletColorFollowText ??? + mrBulletList.mbBulletColorFollowText <<= sal_True; + break; + case A_TOKEN( buClr ): // CT_Color + xRet.set( new ColorContext( *this, *mrBulletList.maBulletColorPtr ) ); + break; + + // EG_TextBulletSize + case A_TOKEN( buSzTx ): // CT_TextBulletSizeFollowText + mrBulletList.setBulletSize(100); + break; + case A_TOKEN( buSzPct ): // CT_TextBulletSizePercent + mrBulletList.setBulletSize( static_cast<sal_Int16>( GetPercent( rXAttributes->getOptionalValue( XML_val ) ) / 1000 ) ); + break; + case A_TOKEN( buSzPts ): // CT_TextBulletSizePoint + mrBulletList.setBulletSize(0); + mrBulletList.setFontSize( static_cast<sal_Int16>(GetTextSize( rXAttributes->getOptionalValue( XML_val ) ) ) ); + break; + + // EG_TextBulletTypeface + case A_TOKEN( buFontTx ): // CT_TextBulletTypefaceFollowText + mrBulletList.mbBulletFontFollowText <<= sal_True; + break; + case A_TOKEN( buFont ): // CT_TextFont + mrBulletList.maBulletFont.setAttributes( aAttribs ); + break; + + // EG_TextBullet + case A_TOKEN( buNone ): // CT_TextNoBullet + mrBulletList.setNone(); + break; + case A_TOKEN( buAutoNum ): // CT_TextAutonumberBullet + { + AttributeList attribs( rXAttributes ); + try { + sal_Int32 nType = rXAttributes->getValueToken( XML_type ); + sal_Int32 nStartAt = attribs.getInteger( XML_startAt, 1 ); + if( nStartAt > 32767 ) + { + nStartAt = 32767; + } + else if( nStartAt < 1 ) + { + nStartAt = 1; + } + mrBulletList.setStartAt( nStartAt ); + mrBulletList.setType( nType ); + } + catch(SAXException& /* e */ ) + { + OSL_TRACE("OOX: SAXException in XML_buAutoNum"); + } + break; + } + case A_TOKEN( buChar ): // CT_TextCharBullet + try { + mrBulletList.setBulletChar( rXAttributes->getValue( XML_char ) ); + } + catch(SAXException& /* e */) + { + OSL_TRACE("OOX: SAXException in XML_buChar"); + } + break; + case A_TOKEN( buBlip ): // CT_TextBlipBullet + { + mxBlipProps.reset( new BlipFillProperties ); + xRet.set( new BlipFillContext( *this, rXAttributes, *mxBlipProps ) ); + } + break; + + case A_TOKEN( tabLst ): // CT_TextTabStopList + xRet.set( new TextTabStopListContext( *this, maTabList ) ); + break; + case A_TOKEN( defRPr ): // CT_TextCharacterProperties + xRet.set( new TextCharacterPropertiesContext( *this, rXAttributes, mrTextParagraphProperties.getTextCharacterProperties() ) ); + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; +} + +// -------------------------------------------------------------------- + +} } + diff --git a/oox/source/drawingml/textrun.cxx b/oox/source/drawingml/textrun.cxx new file mode 100644 index 000000000000..1e435defaa2d --- /dev/null +++ b/oox/source/drawingml/textrun.cxx @@ -0,0 +1,168 @@ +/************************************************************************* + * + * 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/textrun.hxx" + +#include <com/sun/star/text/ControlCharacter.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/text/XTextField.hpp> + +#include "oox/helper/helper.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/core/xmlfilterbase.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; + +namespace oox { namespace drawingml { + +TextRun::TextRun() : + mbIsLineBreak( false ) +{ +} + +TextRun::~TextRun() +{ +} + +void TextRun::insertAt( + const ::oox::core::XmlFilterBase& rFilterBase, + const Reference < XText > & xText, + const Reference < XTextCursor > &xAt, + const TextCharacterProperties& rTextCharacterStyle ) const +{ + try { + Reference< XTextRange > xStart( xAt, UNO_QUERY ); + PropertySet aPropSet( xStart ); + + TextCharacterProperties aTextCharacterProps( rTextCharacterStyle ); + aTextCharacterProps.assignUsed( maTextCharacterProperties ); + aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase ); + + if( maTextCharacterProperties.maHyperlinkPropertyMap.empty() ) + { + if( mbIsLineBreak ) + { + OSL_TRACE( "OOX: TextRun::insertAt() insert line break" ); + xText->insertControlCharacter( xStart, ControlCharacter::LINE_BREAK, sal_False ); + } + else + { + OUString aLatinFontName, aSymbolFontName; + sal_Int16 nLatinFontPitch = 0, nSymbolFontPitch = 0; + sal_Int16 nLatinFontFamily = 0, nSymbolFontFamily = 0; + + if ( !aTextCharacterProps.maSymbolFont.getFontData( aSymbolFontName, nSymbolFontPitch, nSymbolFontFamily, rFilterBase ) ) + xText->insertString( xStart, getText(), sal_False ); + else if ( getText().getLength() ) + { // !!#i113673<<< + aTextCharacterProps.maLatinFont.getFontData( aLatinFontName, nLatinFontPitch, nLatinFontFamily, rFilterBase ); + + sal_Int32 nIndex = 0; + while ( sal_True ) + { + sal_Int32 nCount = 0; + sal_Bool bSymbol = ( getText()[ nIndex ] & 0xff00 ) == 0xf000; + if ( bSymbol ) + { + do + { + nCount++; + } + while( ( ( nCount + nIndex ) < getText().getLength() ) && ( ( getText()[ nCount + nIndex ] & 0xff00 ) == 0xf000 ) ); + aPropSet.setAnyProperty( PROP_CharFontName, Any( aSymbolFontName ) ); + aPropSet.setAnyProperty( PROP_CharFontPitch, Any( nSymbolFontPitch ) ); + aPropSet.setAnyProperty( PROP_CharFontFamily, Any( nSymbolFontFamily ) ); + } + else + { + do + { + nCount++; + } + while( ( ( nCount + nIndex ) < getText().getLength() ) && ( ( getText()[ nCount + nIndex ] & 0xff00 ) != 0xf000 ) ); + aPropSet.setAnyProperty( PROP_CharFontName, Any( aLatinFontName ) ); + aPropSet.setAnyProperty( PROP_CharFontPitch, Any( nLatinFontPitch ) ); + aPropSet.setAnyProperty( PROP_CharFontFamily, Any( nLatinFontFamily ) ); + } + rtl::OUString aSubString( getText().copy( nIndex, nCount ) ); + xText->insertString( xStart, aSubString, sal_False ); + nIndex += nCount; + + if ( nIndex >= getText().getLength() ) + break; + + xStart = Reference< XTextRange >( xAt, UNO_QUERY ); + aPropSet = PropertySet( xStart ); + aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase ); + } + } + } + } + else + { + OSL_TRACE( "OOX: URL field" ); + Reference< XMultiServiceFactory > xFactory( rFilterBase.getModel(), UNO_QUERY ); + Reference< XTextField > xField( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), UNO_QUERY ); + if( xField.is() ) + { + Reference< XTextCursor > xTextFieldCursor = xText->createTextCursor(); + xTextFieldCursor->gotoEnd( sal_False ); + + PropertySet aFieldProps( xField ); + aFieldProps.setProperties( maTextCharacterProperties.maHyperlinkPropertyMap ); + aFieldProps.setProperty( PROP_Representation, getText() ); + Reference< XTextContent > xContent( xField, UNO_QUERY); + xText->insertTextContent( xStart, xContent, sal_False ); + + xTextFieldCursor->gotoEnd( sal_True ); + oox::core::TextField aTextField; + aTextField.xText = xText; + aTextField.xTextCursor = xTextFieldCursor; + aTextField.xTextField = xField; + rFilterBase.getTextFieldStack().push_back( aTextField ); + } + else + { + OSL_TRACE( "OOX: URL field couldn't be created" ); + xText->insertString( xStart, getText(), sal_False ); + } + } + } + catch( const Exception& ) + { + OSL_TRACE("OOX: TextRun::insertAt() exception"); + } +} + + +} } diff --git a/oox/source/drawingml/textspacingcontext.cxx b/oox/source/drawingml/textspacingcontext.cxx new file mode 100644 index 000000000000..5eb5f3d77f82 --- /dev/null +++ b/oox/source/drawingml/textspacingcontext.cxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * 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/drawingmltypes.hxx" +#include "oox/drawingml/textspacing.hxx" +#include "textspacingcontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + + +namespace oox { namespace drawingml { + + TextSpacingContext::TextSpacingContext( ContextHandler& rParent, TextSpacing & aSpacing ) + : ContextHandler( rParent ) + , maSpacing( aSpacing ) + { + maSpacing.bHasValue = sal_True; + } + + void TextSpacingContext::endFastElement( sal_Int32 /*nElement*/ ) + throw ( SAXException, RuntimeException ) + { + } + + Reference< XFastContextHandler > TextSpacingContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw ( SAXException, RuntimeException ) + { + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case A_TOKEN( spcPct ): + maSpacing.nUnit = TextSpacing::PERCENT; + maSpacing.nValue = GetPercent( xAttribs->getValue( XML_val ) ); + break; + case A_TOKEN( spcPts ): + maSpacing.nUnit = TextSpacing::POINTS; + maSpacing.nValue = GetTextSpacingPoint( xAttribs->getValue( XML_val ) ); + break; + default: + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + +} } diff --git a/oox/source/drawingml/textspacingcontext.hxx b/oox/source/drawingml/textspacingcontext.hxx new file mode 100644 index 000000000000..5b646c14d240 --- /dev/null +++ b/oox/source/drawingml/textspacingcontext.hxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_TEXTSPACINGCONTEXT_HXX +#define OOX_DRAWINGML_TEXTSPACINGCONTEXT_HXX + +#include "oox/core/contexthandler.hxx" + +namespace oox { namespace drawingml { + +class TextSpacing; + +class TextSpacingContext : public ::oox::core::ContextHandler +{ +public: + TextSpacingContext( ::oox::core::ContextHandler& rParent, TextSpacing & aSpacing ); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +private: + TextSpacing& maSpacing; +}; + + +} } + + + + +#endif + + diff --git a/oox/source/drawingml/texttabstoplistcontext.cxx b/oox/source/drawingml/texttabstoplistcontext.cxx new file mode 100644 index 000000000000..78248fd0b6f7 --- /dev/null +++ b/oox/source/drawingml/texttabstoplistcontext.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * 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 <list> +#include <algorithm> + +#include <rtl/ustring.hxx> + +#include "oox/drawingml/drawingmltypes.hxx" +#include "texttabstoplistcontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::xml::sax; + +namespace oox { namespace drawingml { + + TextTabStopListContext::TextTabStopListContext( ContextHandler& rParent, std::list< TabStop > & aTabList ) + : ContextHandler( rParent ) + , maTabList( aTabList ) + { + } + + TextTabStopListContext::~TextTabStopListContext() + { + } + + void SAL_CALL TextTabStopListContext::endFastElement( ::sal_Int32 /*Element*/ ) + throw ( SAXException, RuntimeException) + { + } + + + Reference< ::XFastContextHandler > TextTabStopListContext::createFastChildContext( ::sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) + { + Reference< XFastContextHandler > xRet; + switch( aElement ) + { + case A_TOKEN( tab ): + { + OUString sValue; + TabStop aTabStop; + sValue = xAttribs->getOptionalValue( XML_pos ); + if( sValue.getLength() ) + { + aTabStop.Position = GetCoordinate( sValue ); + } + sal_Int32 aToken = xAttribs->getOptionalValueToken( XML_algn, 0 ); + if( aToken != 0 ) + { + aTabStop.Alignment = GetTabAlign( aToken ); + } + maTabList.push_back(aTabStop); + break; + } + default: + break; + } + if ( !xRet.is() ) + xRet.set( this ); + return xRet; + } + + +} } + + diff --git a/oox/source/drawingml/texttabstoplistcontext.hxx b/oox/source/drawingml/texttabstoplistcontext.hxx new file mode 100644 index 000000000000..5545e1231e3d --- /dev/null +++ b/oox/source/drawingml/texttabstoplistcontext.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_TEXTTABSTOPLISTCONTEXT_HXX +#define OOX_DRAWINGML_TEXTTABSTOPLISTCONTEXT_HXX + +#include <list> + +#include <com/sun/star/style/TabStop.hpp> + +#include "oox/core/contexthandler.hxx" + +namespace oox { namespace drawingml { + + class TextTabStopListContext : public ::oox::core::ContextHandler + { + public: + TextTabStopListContext( ::oox::core::ContextHandler& rParent, + ::std::list< ::com::sun::star::style::TabStop > & aTabList ); + ~TextTabStopListContext(); + + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( ::sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException); + +protected: + ::std::list< ::com::sun::star::style::TabStop > & maTabList; + }; + + +} } + + +#endif + diff --git a/oox/source/drawingml/theme.cxx b/oox/source/drawingml/theme.cxx new file mode 100644 index 000000000000..b37ccdbaf13c --- /dev/null +++ b/oox/source/drawingml/theme.cxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * 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/theme.hxx" + +using ::rtl::OUString; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +Theme::Theme() +{ +} + +Theme::~Theme() +{ +} + +namespace { + +template< typename Type > +const Type* lclGetStyleElement( const RefVector< Type >& rVector, sal_Int32 nIndex ) +{ + return (rVector.empty() || (nIndex < 1)) ? 0 : + rVector.get( ::std::min( static_cast< sal_Int32 >( nIndex - 1 ), static_cast< sal_Int32 >( rVector.size() - 1 ) ) ).get(); +} + +} // namespace + +const FillProperties* Theme::getFillStyle( sal_Int32 nIndex ) const +{ + return (nIndex >= 1000) ? + lclGetStyleElement( maBgFillStyleList, nIndex - 1000 ) : + lclGetStyleElement( maFillStyleList, nIndex ); +} + +const LineProperties* Theme::getLineStyle( sal_Int32 nIndex ) const +{ + return lclGetStyleElement( maLineStyleList, nIndex ); +} + +const PropertyMap* Theme::getEffectStyle( sal_Int32 nIndex ) const +{ + return lclGetStyleElement( maEffectStyleList, nIndex ); +} + +const TextCharacterProperties* Theme::getFontStyle( sal_Int32 nSchemeType ) const +{ + return maFontScheme.get( nSchemeType ).get(); +} + +const TextFont* Theme::resolveFont( const OUString& rName ) const +{ + /* Resolves the following names: + +mj-lt, +mj-ea, +mj-cs -- major Latin, Asian, Complex font + +mn-lt, +mn-ea, +mn-cs -- minor Latin, Asian, Complex font + */ + if( (rName.getLength() == 6) && (rName[ 0 ] == '+') && (rName[ 3 ] == '-') ) + { + const TextCharacterProperties* pCharProps = 0; + if( (rName[ 1 ] == 'm') && (rName[ 2 ] == 'j') ) + pCharProps = maFontScheme.get( XML_major ).get(); + else if( (rName[ 1 ] == 'm') && (rName[ 2 ] == 'n') ) + pCharProps = maFontScheme.get( XML_minor ).get(); + if( pCharProps ) + { + if( (rName[ 4 ] == 'l') && (rName[ 5 ] == 't') ) + return &pCharProps->maLatinFont; + if( (rName[ 4 ] == 'e') && (rName[ 5 ] == 'a') ) + return &pCharProps->maAsianFont; + if( (rName[ 4 ] == 'c') && (rName[ 5 ] == 's') ) + return &pCharProps->maComplexFont; + } + } + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/themeelementscontext.cxx b/oox/source/drawingml/themeelementscontext.cxx new file mode 100644 index 000000000000..a27afdbc0ea3 --- /dev/null +++ b/oox/source/drawingml/themeelementscontext.cxx @@ -0,0 +1,241 @@ +/************************************************************************* + * + * 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/themeelementscontext.hxx" +#include "oox/drawingml/clrschemecontext.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/linepropertiescontext.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/fillpropertiesgroupcontext.hxx" +#include "oox/drawingml/theme.hxx" +#include "oox/helper/attributelist.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +class FillStyleListContext : public ContextHandler +{ +public: + FillStyleListContext( ContextHandler& rParent, FillStyleList& rFillStyleList ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + +private: + FillStyleList& mrFillStyleList; +}; + +FillStyleListContext::FillStyleListContext( ContextHandler& rParent, FillStyleList& rFillStyleList ) : + ContextHandler( rParent ), + mrFillStyleList( rFillStyleList ) +{ +} + +Reference< XFastContextHandler > FillStyleListContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( noFill ): + case A_TOKEN( solidFill ): + case A_TOKEN( gradFill ): + case A_TOKEN( blipFill ): + case A_TOKEN( pattFill ): + case A_TOKEN( grpFill ): + mrFillStyleList.push_back( FillPropertiesPtr( new FillProperties ) ); + return FillPropertiesContext::createFillContext( *this, nElement, xAttribs, *mrFillStyleList.back() ); + } + return 0; +} + +// ============================================================================ + +class LineStyleListContext : public ContextHandler +{ +public: + LineStyleListContext( ContextHandler& rParent, LineStyleList& rLineStyleList ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + +private: + LineStyleList& mrLineStyleList; +}; + +LineStyleListContext::LineStyleListContext( ContextHandler& rParent, LineStyleList& rLineStyleList ) : + ContextHandler( rParent ), + mrLineStyleList( rLineStyleList ) +{ +} + +Reference< XFastContextHandler > LineStyleListContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) + throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( ln ): + mrLineStyleList.push_back( LinePropertiesPtr( new LineProperties ) ); + return new LinePropertiesContext( *this, xAttribs, *mrLineStyleList.back() ); + } + return 0; +} + +// ============================================================================ + +class EffectStyleListContext : public ContextHandler +{ +public: + EffectStyleListContext( ContextHandler& rParent, EffectStyleList& rEffectStyleList ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + +private: + EffectStyleList& mrEffectStyleList; +}; + +EffectStyleListContext::EffectStyleListContext( ContextHandler& rParent, EffectStyleList& rEffectStyleList ) : + ContextHandler( rParent ), + mrEffectStyleList( rEffectStyleList ) +{ +} + +Reference< XFastContextHandler > EffectStyleListContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& /*xAttribs*/ ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( effectStyle ): + mrEffectStyleList.push_back( EffectStyleList::value_type( new PropertyMap ) ); + // TODO: import effect styles + return 0; + } + return 0; +} + +// ============================================================================ + +class FontSchemeContext : public ContextHandler +{ +public: + FontSchemeContext( ContextHandler& rParent, FontScheme& rFontScheme ); + virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException); + virtual void SAL_CALL endFastElement( sal_Int32 nElement ) throw (SAXException, RuntimeException); + +private: + FontScheme& mrFontScheme; + TextCharacterPropertiesPtr mxCharProps; +}; + +FontSchemeContext::FontSchemeContext( ContextHandler& rParent, FontScheme& rFontScheme ) : + ContextHandler( rParent ), + mrFontScheme( rFontScheme ) +{ +} + +Reference< XFastContextHandler > FontSchemeContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) + throw (SAXException, RuntimeException) +{ + AttributeList aAttribs( rxAttribs ); + switch( nElement ) + { + case A_TOKEN( majorFont ): + mxCharProps.reset( new TextCharacterProperties ); + mrFontScheme[ XML_major ] = mxCharProps; + return this; + case A_TOKEN( minorFont ): + mxCharProps.reset( new TextCharacterProperties ); + mrFontScheme[ XML_minor ] = mxCharProps; + return this; + + case A_TOKEN( latin ): + if( mxCharProps.get() ) + mxCharProps->maLatinFont.setAttributes( aAttribs ); + break; + case A_TOKEN( ea ): + if( mxCharProps.get() ) + mxCharProps->maAsianFont.setAttributes( aAttribs ); + break; + case A_TOKEN( cs ): + if( mxCharProps.get() ) + mxCharProps->maComplexFont.setAttributes( aAttribs ); + break; + } + return 0; +} + +void FontSchemeContext::endFastElement( sal_Int32 nElement ) throw (SAXException, RuntimeException) +{ + switch( nElement ) + { + case A_TOKEN( majorFont ): + case A_TOKEN( minorFont ): + mxCharProps.reset(); + break; + } +} + +// ============================================================================ + +ThemeElementsContext::ThemeElementsContext( ContextHandler& rParent, Theme& rTheme ) : + ContextHandler( rParent ), + mrTheme( rTheme ) +{ +} + +Reference< XFastContextHandler > ThemeElementsContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + // CT_BaseStyles + Reference< XFastContextHandler > xRet; + switch( nElement ) + { + case A_TOKEN( clrScheme ): // CT_ColorScheme + return new clrSchemeContext( *this, mrTheme.getClrScheme() ); + case A_TOKEN( fontScheme ): // CT_FontScheme + return new FontSchemeContext( *this, mrTheme.getFontScheme() ); + + case A_TOKEN( fmtScheme ): // CT_StyleMatrix + mrTheme.setStyleName( xAttribs->getOptionalValue( XML_name ) ); + return this; + + case A_TOKEN( fillStyleLst ): // CT_FillStyleList + return new FillStyleListContext( *this, mrTheme.getFillStyleList() ); + case A_TOKEN( lnStyleLst ): // CT_LineStyleList + return new LineStyleListContext( *this, mrTheme.getLineStyleList() ); + case A_TOKEN( effectStyleLst ): // CT_EffectStyleList + return new EffectStyleListContext( *this, mrTheme.getEffectStyleList() ); + case A_TOKEN( bgFillStyleLst ): // CT_BackgroundFillStyleList + return new FillStyleListContext( *this, mrTheme.getBgFillStyleList() ); + } + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/themefragmenthandler.cxx b/oox/source/drawingml/themefragmenthandler.cxx new file mode 100644 index 000000000000..3cae10e40b4f --- /dev/null +++ b/oox/source/drawingml/themefragmenthandler.cxx @@ -0,0 +1,87 @@ +/************************************************************************* + * + * 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/themefragmenthandler.hxx" +#include "oox/drawingml/objectdefaultcontext.hxx" +#include "oox/drawingml/theme.hxx" +#include "oox/drawingml/themeelementscontext.hxx" + +using ::rtl::OUString; +using namespace ::oox::core; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +ThemeFragmentHandler::ThemeFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, Theme& rTheme ) : + FragmentHandler2( rFilter, rFragmentPath ), + mrTheme( rTheme ) +{ +} + +ThemeFragmentHandler::~ThemeFragmentHandler() +{ +} + +ContextHandlerRef ThemeFragmentHandler::onCreateContext( sal_Int32 nElement, const AttributeList& ) +{ + // CT_OfficeStyleSheet + switch( getCurrentElement() ) + { + case XML_ROOT_CONTEXT: + switch( nElement ) + { + case A_TOKEN( theme ): + return this; + } + break; + + case A_TOKEN( theme ): + switch( nElement ) + { + case A_TOKEN( themeElements ): // CT_BaseStyles + return new ThemeElementsContext( *this, mrTheme ); + case A_TOKEN( objectDefaults ): // CT_ObjectStyleDefaults + return new objectDefaultContext( *this, mrTheme ); + case A_TOKEN( extraClrSchemeLst ): // CT_ColorSchemeList + return 0; + case A_TOKEN( custClrLst ): // CustomColorList + return 0; + case A_TOKEN( ext ): // CT_OfficeArtExtension + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + diff --git a/oox/source/drawingml/transform2dcontext.cxx b/oox/source/drawingml/transform2dcontext.cxx new file mode 100644 index 000000000000..c686feed165c --- /dev/null +++ b/oox/source/drawingml/transform2dcontext.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * 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/transform2dcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/drawingml/shape.hxx" + +using ::com::sun::star::awt::Point; +using ::com::sun::star::awt::Size; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::xml::sax::SAXException; +using ::com::sun::star::xml::sax::XFastAttributeList; +using ::com::sun::star::xml::sax::XFastContextHandler; +using ::oox::core::ContextHandler; + +namespace oox { +namespace drawingml { + +// ============================================================================ + +/** context to import a CT_Transform2D */ +Transform2DContext::Transform2DContext( ContextHandler& rParent, const Reference< XFastAttributeList >& xAttribs, Shape& rShape ) throw() +: ContextHandler( rParent ) +, mrShape( rShape ) +{ + AttributeList aAttributeList( xAttribs ); + mrShape.setRotation( aAttributeList.getInteger( XML_rot, 0 ) ); // 60000ths of a degree Positive angles are clockwise; negative angles are counter-clockwise + mrShape.setFlip( aAttributeList.getBool( XML_flipH, sal_False ), aAttributeList.getBool( XML_flipV, sal_False ) ); +} + +Reference< XFastContextHandler > Transform2DContext::createFastChildContext( sal_Int32 aElementToken, const Reference< XFastAttributeList >& xAttribs ) throw (SAXException, RuntimeException) +{ + switch( aElementToken ) + { + case A_TOKEN( off ): // horz/vert translation + mrShape.setPosition( Point( xAttribs->getOptionalValue( XML_x ).toInt32(), xAttribs->getOptionalValue( XML_y ).toInt32() ) ); + break; + case A_TOKEN( ext ): // horz/vert size + mrShape.setSize( Size( xAttribs->getOptionalValue( XML_cx ).toInt32(), xAttribs->getOptionalValue( XML_cy ).toInt32() ) ); + break; +/* todo: what to do? + case A_TOKEN( chOff ): // horz/vert translation of children + case A_TOKEN( chExt ): // horz/vert size of children + break; +*/ + } + + return 0; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + |