diff options
Diffstat (limited to 'oox/source/ppt')
43 files changed, 9228 insertions, 0 deletions
diff --git a/oox/source/ppt/animationspersist.cxx b/oox/source/ppt/animationspersist.cxx new file mode 100644 index 0000000000..450e3da006 --- /dev/null +++ b/oox/source/ppt/animationspersist.cxx @@ -0,0 +1,220 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/animationspersist.hxx> + +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> +#include <com/sun/star/animations/Event.hpp> +#include <com/sun/star/animations/XAnimationNode.hpp> + +#include <oox/drawingml/shape.hxx> +#include <oox/helper/addtosequence.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::text; + +namespace oox +{ + +Any addToSequence( const Any& rOldValue, const Any& rNewValue ) +{ + if( !rNewValue.hasValue() ) + { + return rOldValue; + } + else if( !rOldValue.hasValue() ) + { + return rNewValue; + } + else + { + Sequence< Any > aNewSeq; + if( rOldValue >>= aNewSeq ) + { + sal_Int32 nSize = aNewSeq.getLength(); + aNewSeq.realloc(nSize+1); + aNewSeq.getArray()[nSize] = rNewValue; + } + else + { + aNewSeq = { rOldValue, rNewValue }; + } + return Any( aNewSeq ); + } +} + +} // namespace oox + +namespace oox::ppt { + + void ShapeTargetElement::convert( css::uno::Any & rTarget, sal_Int16 & rSubType ) const + { + switch(mnType) + { + case XML_subSp: + rSubType = ShapeAnimationSubType::AS_WHOLE; + break; + case XML_bg: + rSubType = ShapeAnimationSubType::ONLY_BACKGROUND; + break; + case XML_txEl: + { + ParagraphTarget aParaTarget; + Reference< XShape > xShape; + rTarget >>= xShape; + aParaTarget.Shape = xShape; + rSubType = ShapeAnimationSubType::ONLY_TEXT; + + Reference< XText > xText( xShape, UNO_QUERY ); + if( xText.is() ) + { + switch(mnRangeType) + { + case XML_charRg: + // TODO calculate the corresponding paragraph for the text range... + SAL_INFO("oox.ppt", "OOX: TODO calculate the corresponding paragraph for the text range..." ); + break; + case XML_pRg: + aParaTarget.Paragraph = static_cast< sal_Int16 >( maRange.start ); + // TODO what to do with more than one. + SAL_INFO("oox.ppt", "OOX: TODO what to do with more than one" ); + break; + } + rTarget <<= aParaTarget; + } + break; + } + default: + break; + } + } + + Any AnimTargetElement::convert(const SlidePersistPtr & pSlide, sal_Int16 & nSubType) const + { + Any aTarget; + // see sd/source/files/ppt/pptinanimations.cxx:3191 (in importTargetElementContainer()) + switch(mnType) + { + case XML_inkTgt: + // TODO + SAL_INFO("oox.ppt", "OOX: TODO inkTgt" ); + break; + case XML_sldTgt: + // TODO + SAL_INFO("oox.ppt", "OOX: TODO sldTgt" ); + break; + case XML_sndTgt: + aTarget <<= msValue; + break; + case XML_spTgt: + { + OUString sShapeName = msValue; + + // bnc#705982 - catch referenced diagram fallback shapes + if( maShapeTarget.mnType == XML_dgm ) + sShapeName = maShapeTarget.msSubShapeId; + + Any rTarget; + ::oox::drawingml::ShapePtr pShape = pSlide->getShape( sShapeName ); + SAL_WARN_IF( !pShape, "oox.ppt", "failed to locate Shape" ); + + if( !pShape && maShapeTarget.mnType == XML_dgm ) + { + pShape = pSlide->getShape( msValue ); + } + + if( pShape ) + { + Reference< XShape > xShape( pShape->getXShape() ); + SAL_WARN_IF( !xShape.is(), "oox.ppt", "fail to get XShape from shape" ); + if( xShape.is() ) + { + rTarget <<= xShape; + maShapeTarget.convert(rTarget, nSubType); + aTarget = rTarget; + } + } + break; + } + default: + break; + } + return aTarget; + } + + // Convert a time node condition to XAnimation.Begin or XAnimation.End + Any AnimationCondition::convert(const SlidePersistPtr & pSlide) const + { + Any aAny; + Event aEvent; + if(mpTarget && (maValue >>= aEvent)) + { + sal_Int16 nSubType; + aAny = mpTarget->convert( pSlide, nSubType ); + aEvent.Source = aAny; + aAny <<= aEvent; + } + else if (mnType == PPT_TOKEN(tn) && (maValue >>= aEvent)) + { + OUString sId; + aEvent.Source >>= sId; + css::uno::Reference<XAnimationNode> xNode = pSlide->getAnimationNode(sId); + if (xNode.is()) + { + aEvent.Source <<= xNode; + } + else + aEvent.Source.clear(); + aAny <<= aEvent; + } + else + { + aAny = maValue; + } + return aAny; + } + + Any AnimationCondition::convertList(const SlidePersistPtr & pSlide, const AnimationConditionList & l) + { + Any aAny; + + if (l.size() == 1) + return l[0].convert(pSlide); + + for (auto const& elem : l) + { + aAny = addToSequence( aAny, elem.convert(pSlide) ); + } + return aAny; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/animationtypes.cxx b/oox/source/ppt/animationtypes.cxx new file mode 100644 index 0000000000..c6b49b3e87 --- /dev/null +++ b/oox/source/ppt/animationtypes.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "animationtypes.hxx" + +#include <com/sun/star/animations/Timing.hpp> + +#include <oox/helper/attributelist.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt +{ +// ST_TLTime +Any GetTime(const OUString& val) +{ + Any aDuration; + if (val == "indefinite") + { + aDuration <<= Timing_INDEFINITE; + } + else + { + aDuration <<= val.toFloat() / 1000.0; + } + return aDuration; +} + +// ST_TLTimeAnimateValueTime +Any GetTimeAnimateValueTime(const OUString& val) +{ + Any aPercent; + if (val == "indefinite") + { + aPercent <<= Timing_INDEFINITE; + } + else + { + aPercent <<= val.toFloat() / 100000.0; + } + return aPercent; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/animationtypes.hxx b/oox/source/ppt/animationtypes.hxx new file mode 100644 index 0000000000..92652978fd --- /dev/null +++ b/oox/source/ppt/animationtypes.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_ANIMATIONTYPES_HXX +#define INCLUDED_OOX_SOURCE_PPT_ANIMATIONTYPES_HXX + +#include <com/sun/star/uno/Any.hxx> + +namespace oox::ppt +{ +// ST_TLTime +css::uno::Any GetTime(const OUString& val); +// ST_TLTimeAnimateValueTime +css::uno::Any GetTimeAnimateValueTime(const OUString& val); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/animvariantcontext.cxx b/oox/source/ppt/animvariantcontext.cxx new file mode 100644 index 0000000000..1dc9380177 --- /dev/null +++ b/oox/source/ppt/animvariantcontext.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "animvariantcontext.hxx" + +#include <com/sun/star/uno/Any.hxx> +#include <rtl/ustring.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <drawingml/colorchoicecontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + AnimVariantContext::AnimVariantContext( FragmentHandler2 const & rParent, sal_Int32 aElement, Any & aValue ) + : FragmentHandler2( rParent ) + , mnElement( aElement ) + , maValue( aValue ) + { + } + + AnimVariantContext::~AnimVariantContext( ) noexcept + { + } + + void AnimVariantContext::onEndElement() + { + if( isCurrentElement( mnElement ) && maColor.isUsed() ) + { + maValue <<= maColor.getColor( getFilter().getGraphicHelper() ); + } + } + + ContextHandlerRef AnimVariantContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + switch( aElementToken ) + { + case PPT_TOKEN( boolVal ): + { + bool val = rAttribs.getBool( XML_val, false ); + maValue <<= val; + return this; + } + case PPT_TOKEN( clrVal ): + return new ::oox::drawingml::ColorContext( *this, maColor ); + // we'll defer setting the Any until the end. + case PPT_TOKEN( fltVal ): + { + double val = rAttribs.getDouble( XML_val, 0.0 ); + maValue <<= val; + return this; + } + case PPT_TOKEN( intVal ): + { + sal_Int32 val = rAttribs.getInteger( XML_val, 0 ); + maValue <<= val; + return this; + } + case PPT_TOKEN( strVal ): + { + OUString val = rAttribs.getStringDefaulted( XML_val); + maValue <<= val; + return this; + } + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/animvariantcontext.hxx b/oox/source/ppt/animvariantcontext.hxx new file mode 100644 index 0000000000..8830e0e6a7 --- /dev/null +++ b/oox/source/ppt/animvariantcontext.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_ANIMVARIANTCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_ANIMVARIANTCONTEXT_HXX + +#include <com/sun/star/uno/Any.hxx> + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/drawingml/color.hxx> + +namespace oox::ppt { + + /** context CT_TLAnimVariant */ + class AnimVariantContext + : public ::oox::core::FragmentHandler2 + { + public: + AnimVariantContext( ::oox::core::FragmentHandler2 const & rParent, ::sal_Int32 aElement, css::uno::Any & aValue ); + virtual ~AnimVariantContext( ) noexcept override; + virtual void onEndElement() override; + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + ::sal_Int32 mnElement; + css::uno::Any& maValue; + ::oox::drawingml::Color maColor; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/backgroundproperties.cxx b/oox/source/ppt/backgroundproperties.cxx new file mode 100644 index 0000000000..b3c71875e6 --- /dev/null +++ b/oox/source/ppt/backgroundproperties.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/backgroundproperties.hxx> +#include <drawingml/misccontexts.hxx> +#include <oox/core/contexthandler2.hxx> +#include <oox/token/namespaces.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +BackgroundPropertiesContext::BackgroundPropertiesContext( FragmentHandler2 const & rParent, ::oox::drawingml::FillProperties& rFillProperties ) +: FragmentHandler2( rParent ) +, mrFillProperties( rFillProperties ) +{ +} + +::oox::core::ContextHandlerRef BackgroundPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( fill ): // a:CT_FillEffect + return this; + } + + return ::oox::drawingml::FillPropertiesContext::createFillContext(*this, aElementToken, rAttribs, mrFillProperties, nullptr); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/buildlistcontext.cxx b/oox/source/ppt/buildlistcontext.cxx new file mode 100644 index 0000000000..1432166f07 --- /dev/null +++ b/oox/source/ppt/buildlistcontext.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "buildlistcontext.hxx" +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> + +namespace oox::ppt { + + BuildListContext::BuildListContext( FragmentHandler2 const & rParent ) + : FragmentHandler2( rParent ) + , mbInBldGraphic( false ) + , mbBuildAsOne( false ) + { + } + + BuildListContext::~BuildListContext( ) + { + } + + void BuildListContext::onEndElement() + { + switch( getCurrentElement() ) + { + case PPT_TOKEN( bldGraphic ): + mbInBldGraphic = false; + break; + default: + break; + } + } + + ::oox::core::ContextHandlerRef BuildListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) + { + switch( aElementToken ) + { + case PPT_TOKEN( bldAsOne ): + if( mbInBldGraphic ) + { + mbBuildAsOne = true; + } + return this; + case PPT_TOKEN( bldSub ): + return this; + case PPT_TOKEN( bldGraphic ): + { + mbInBldGraphic = true; +// OUString sShapeId = rAttribs.getStringDefaulted( XML_spid); +// TODO +// bool uiExpand = rAttribs.getBool( XML_uiExpand, true ); + /* this is unsigned */ +// sal_uInt32 nGroupId = rAttribs.getUnsignedInteger( XML_grpId, 0 ); + return this; + } + case A_TOKEN( bldDgm ): + case A_TOKEN( bldOleChart ): + case A_TOKEN( bldP ): + return this; + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/buildlistcontext.hxx b/oox/source/ppt/buildlistcontext.hxx new file mode 100644 index 0000000000..a95e464e99 --- /dev/null +++ b/oox/source/ppt/buildlistcontext.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_BUILDLISTCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_BUILDLISTCONTEXT_HXX + +#include <oox/core/fragmenthandler2.hxx> + +namespace oox::ppt { + + /** CT_BuildList */ + class BuildListContext + : public ::oox::core::FragmentHandler2 + { + public: + explicit BuildListContext( ::oox::core::FragmentHandler2 const & rParent ); + + virtual ~BuildListContext( ) override; + + virtual void onEndElement() override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + private: + bool mbInBldGraphic; + bool mbBuildAsOne; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/comments.cxx b/oox/source/ppt/comments.cxx new file mode 100644 index 0000000000..c38397fcad --- /dev/null +++ b/oox/source/ppt/comments.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <oox/ppt/comments.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <rtl/math.h> +#include <rtl/math.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> + +namespace oox::ppt +{ +void CommentAuthorList::setValues(const CommentAuthorList& list) +{ + for (auto const& author : list.cmAuthorLst) + { + CommentAuthor temp; + // TODO JNA : why not doing push_back at the end instead of using back()? + cmAuthorLst.push_back(temp); + cmAuthorLst.back().clrIdx = author.clrIdx; + cmAuthorLst.back().id = author.id; + cmAuthorLst.back().initials = author.initials; + cmAuthorLst.back().lastIdx = author.lastIdx; + cmAuthorLst.back().name = author.name; + } +} + +//DateTime is saved as : 2013-01-10T15:53:26.000 +void Comment::setDateTime(const OUString& sDateTime) +{ + sal_Int32 nIdx{ 0 }; + aDateTime.Year = o3tl::toInt32(o3tl::getToken(sDateTime, 0, '-', nIdx)); + aDateTime.Month = o3tl::toUInt32(o3tl::getToken(sDateTime, 0, '-', nIdx)); + aDateTime.Day = o3tl::toUInt32(o3tl::getToken(sDateTime, 0, 'T', nIdx)); + aDateTime.Hours = o3tl::toUInt32(o3tl::getToken(sDateTime, 0, ':', nIdx)); + aDateTime.Minutes = o3tl::toUInt32(o3tl::getToken(sDateTime, 0, ':', nIdx)); + double seconds = rtl_math_uStringToDouble(sDateTime.getStr() + nIdx, + sDateTime.getStr() + sDateTime.getLength(), '.', 0, + nullptr, nullptr); + aDateTime.Seconds = floor(seconds); + seconds -= aDateTime.Seconds; + aDateTime.NanoSeconds = ::rtl::math::round(seconds * 1000000000); + const int secondsOverflow = (aDateTime.Seconds == 60) ? 61 : 60; + // normalise time part of aDateTime + if (aDateTime.NanoSeconds == 1000000000) + { + aDateTime.NanoSeconds = 0; + ++aDateTime.Seconds; + } + if (aDateTime.Seconds == secondsOverflow) + { + aDateTime.Seconds = 0; + ++aDateTime.Minutes; + } + if (aDateTime.Minutes == 60) + { + aDateTime.Minutes = 0; + ++aDateTime.Hours; + } + // if overflow goes into date, I give up +} + +OUString Comment::getAuthor(const CommentAuthorList& list) +{ + const sal_Int32 nId = authorId.toInt32(); + for (auto const& author : list.cmAuthorLst) + { + if (author.id.toInt32() == nId) + return author.name; + } + return "Anonymous"; +} + +const Comment& CommentList::getCommentAtIndex(int index) +{ + if (index < 0 || o3tl::make_unsigned(index) >= cmLst.size()) + throw css::lang::IllegalArgumentException(); + + return cmLst.at(index); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/commonbehaviorcontext.cxx b/oox/source/ppt/commonbehaviorcontext.cxx new file mode 100644 index 0000000000..ca0a0c9ec7 --- /dev/null +++ b/oox/source/ppt/commonbehaviorcontext.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> + +#include "commonbehaviorcontext.hxx" +#include "commontimenodecontext.hxx" +#include "timetargetelementcontext.hxx" + +#include <string.h> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + + CommonBehaviorContext::CommonBehaviorContext( FragmentHandler2 const & rParent, + const TimeNodePtr & pNode) + : FragmentHandler2(rParent) + , mbInAttrList( false ) + , mbIsInAttrName( false ) + , mpNode(pNode) + { + } + + CommonBehaviorContext::~CommonBehaviorContext( ) noexcept + { + } + + void CommonBehaviorContext::onEndElement() + { + switch( getCurrentElement() ) + { + case PPT_TOKEN( cBhvr ): + { + if( !maAttributes.empty() ) + { + OUStringBuffer sAttributes; + for (auto const& attribute : maAttributes) + { + if( !sAttributes.isEmpty() ) + { + sAttributes.append( ";" ); + } + sAttributes.append( attribute.name ); + } + OUString sTmp( sAttributes.makeStringAndClear() ); + mpNode->getNodeProperties()[ NP_ATTRIBUTENAME ] <<= sTmp; + } + break; + } + case PPT_TOKEN( attrNameLst ): + mbInAttrList = false; + break; + case PPT_TOKEN( attrName ): + if( mbIsInAttrName ) + { + const ImplAttributeNameConversion *attrConv = getAttributeConversionList(); + while( attrConv->mpMSName != nullptr ) + { + if(msCurrentAttribute.equalsAscii( attrConv->mpMSName ) ) + { + Attribute attr; + attr.name = OUString( attrConv->mpAPIName, + strlen(attrConv->mpAPIName), + RTL_TEXTENCODING_ASCII_US ); + attr.type = attrConv->meAttribute; + maAttributes.push_back( attr ); + SAL_INFO("oox.ppt", "OOX: attrName is " << msCurrentAttribute << " -> " << attrConv->mpAPIName ); + break; + } + attrConv++; + } + mbIsInAttrName = false; + } + break; + default: + break; + } + } + + void CommonBehaviorContext::onCharacters( const OUString& aChars ) + { + if( mbIsInAttrName ) + { + msCurrentAttribute += aChars; + } + } + + ::oox::core::ContextHandlerRef CommonBehaviorContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + switch ( aElementToken ) + { + case PPT_TOKEN( cTn ): + return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode ); + case PPT_TOKEN( tgtEl ): + return new TimeTargetElementContext( *this, mpNode->getTarget() ); + case PPT_TOKEN( attrNameLst ): + mbInAttrList = true; + return this; + case PPT_TOKEN( attrName ): + { + if( mbInAttrList ) + { + mbIsInAttrName = true; + msCurrentAttribute.clear(); + } + else + { + SAL_INFO("oox.ppt", "OOX: Attribute Name outside an Attribute List" ); + } + return this; + } + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/commonbehaviorcontext.hxx b/oox/source/ppt/commonbehaviorcontext.hxx new file mode 100644 index 0000000000..eb6bc28fca --- /dev/null +++ b/oox/source/ppt/commonbehaviorcontext.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_COMMONBEHAVIORCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_COMMONBEHAVIORCONTEXT_HXX + +#include <rtl/ustring.hxx> +#include <oox/core/contexthandler.hxx> +#include <oox/core/fragmenthandler2.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> +#include <oox/ppt/timenode.hxx> + +namespace oox::ppt { + + struct Attribute + { + OUString name; + AnimationAttributeEnum type; + }; + + /** CT_TLCommonBehaviorData */ + class CommonBehaviorContext + : public ::oox::core::FragmentHandler2 + { + public: + CommonBehaviorContext( ::oox::core::FragmentHandler2 const & rParent, + const TimeNodePtr & pNode ); + virtual ~CommonBehaviorContext( ) + noexcept override; + + virtual void onEndElement() override; + + virtual void onCharacters( const OUString& aChars ) override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + bool mbInAttrList; + bool mbIsInAttrName; + std::vector< Attribute > maAttributes; + OUString msCurrentAttribute; + const TimeNodePtr& mpNode; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/commontimenodecontext.cxx b/oox/source/ppt/commontimenodecontext.cxx new file mode 100644 index 0000000000..e7d1cf1dce --- /dev/null +++ b/oox/source/ppt/commontimenodecontext.cxx @@ -0,0 +1,666 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "commontimenodecontext.hxx" +#include "conditioncontext.hxx" + +#include <com/sun/star/animations/AnimationFill.hpp> +#include <com/sun/star/animations/AnimationRestart.hpp> +#include <com/sun/star/presentation/TextAnimationType.hpp> +#include <com/sun/star/presentation/EffectPresetClass.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> + +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +#include "animationtypes.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; + + +namespace oox::ppt { + +const convert_subtype* convert_subtype::getList() +{ + static const convert_subtype aList[] = + { + // fly in + { 1, "from-top" }, + { 2, "from-right" }, + { 3, "from-top-right" }, + { 4, "from-bottom" }, + { 5, "horizontal" }, + { 6, "from-bottom-right" }, + { 8, "from-left" }, + { 9, "from-top-left" }, + { 10, "vertical" }, + { 12, "from-bottom-left" }, + { 16, "in" }, + { 21, "vertical-in" }, + { 26, "horizontal-in" }, + { 32, "out" }, + { 36, "out-from-screen-center" }, + { 37, "vertical-out" }, + { 42, "horizontal-out" }, + { 272, "in-slightly" }, + { 288, "out-slightly" }, + { 528, "in-from-screen-center" }, + { 0, nullptr } + }; + + return aList; +} + +const preset_mapping* preset_mapping::getList() +{ + + static const preset_mapping aList[] = + { + { css::presentation::EffectPresetClass::ENTRANCE, 1 ,"ooo-entrance-appear" }, + { css::presentation::EffectPresetClass::ENTRANCE, 2 ,"ooo-entrance-fly-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 3 ,"ooo-entrance-venetian-blinds" }, + { css::presentation::EffectPresetClass::ENTRANCE, 4 ,"ooo-entrance-box" }, + { css::presentation::EffectPresetClass::ENTRANCE, 5 ,"ooo-entrance-checkerboard" }, + { css::presentation::EffectPresetClass::ENTRANCE, 6 ,"ooo-entrance-circle" }, + { css::presentation::EffectPresetClass::ENTRANCE, 7 ,"ooo-entrance-fly-in-slow" }, + { css::presentation::EffectPresetClass::ENTRANCE, 8 ,"ooo-entrance-diamond" }, + { css::presentation::EffectPresetClass::ENTRANCE, 9 ,"ooo-entrance-dissolve-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 10 ,"ooo-entrance-fade-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 11 ,"ooo-entrance-flash-once" }, + { css::presentation::EffectPresetClass::ENTRANCE, 12 ,"ooo-entrance-peek-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 13 ,"ooo-entrance-plus" }, + { css::presentation::EffectPresetClass::ENTRANCE, 14 ,"ooo-entrance-random-bars" }, + { css::presentation::EffectPresetClass::ENTRANCE, 15 ,"ooo-entrance-spiral-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 16 ,"ooo-entrance-split" }, + { css::presentation::EffectPresetClass::ENTRANCE, 17 ,"ooo-entrance-stretchy" }, + { css::presentation::EffectPresetClass::ENTRANCE, 18 ,"ooo-entrance-diagonal-squares" }, + { css::presentation::EffectPresetClass::ENTRANCE, 19 ,"ooo-entrance-swivel" }, + { css::presentation::EffectPresetClass::ENTRANCE, 20 ,"ooo-entrance-wedge" }, + { css::presentation::EffectPresetClass::ENTRANCE, 21 ,"ooo-entrance-wheel" }, + { css::presentation::EffectPresetClass::ENTRANCE, 22 ,"ooo-entrance-wipe" }, + { css::presentation::EffectPresetClass::ENTRANCE, 23 ,"ooo-entrance-zoom" }, + { css::presentation::EffectPresetClass::ENTRANCE, 24 ,"ooo-entrance-random" }, + { css::presentation::EffectPresetClass::ENTRANCE, 25 ,"ooo-entrance-boomerang" }, + { css::presentation::EffectPresetClass::ENTRANCE, 26 ,"ooo-entrance-bounce" }, + { css::presentation::EffectPresetClass::ENTRANCE, 27 ,"ooo-entrance-colored-lettering" }, + { css::presentation::EffectPresetClass::ENTRANCE, 28 ,"ooo-entrance-movie-credits" }, + { css::presentation::EffectPresetClass::ENTRANCE, 29 ,"ooo-entrance-ease-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 30 ,"ooo-entrance-float" }, + { css::presentation::EffectPresetClass::ENTRANCE, 31 ,"ooo-entrance-turn-and-grow" }, + { css::presentation::EffectPresetClass::ENTRANCE, 34 ,"ooo-entrance-breaks" }, + { css::presentation::EffectPresetClass::ENTRANCE, 35 ,"ooo-entrance-pinwheel" }, + { css::presentation::EffectPresetClass::ENTRANCE, 37 ,"ooo-entrance-rise-up" }, + { css::presentation::EffectPresetClass::ENTRANCE, 38 ,"ooo-entrance-falling-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 39 ,"ooo-entrance-thread" }, + { css::presentation::EffectPresetClass::ENTRANCE, 40 ,"ooo-entrance-unfold" }, + { css::presentation::EffectPresetClass::ENTRANCE, 41 ,"ooo-entrance-whip" }, + { css::presentation::EffectPresetClass::ENTRANCE, 42 ,"ooo-entrance-ascend" }, + { css::presentation::EffectPresetClass::ENTRANCE, 43 ,"ooo-entrance-center-revolve" }, + { css::presentation::EffectPresetClass::ENTRANCE, 45 ,"ooo-entrance-fade-in-and-swivel" }, + { css::presentation::EffectPresetClass::ENTRANCE, 47 ,"ooo-entrance-descend" }, + { css::presentation::EffectPresetClass::ENTRANCE, 48 ,"ooo-entrance-sling" }, + { css::presentation::EffectPresetClass::ENTRANCE, 49 ,"ooo-entrance-spin-in" }, + { css::presentation::EffectPresetClass::ENTRANCE, 50 ,"ooo-entrance-compress" }, + { css::presentation::EffectPresetClass::ENTRANCE, 51 ,"ooo-entrance-magnify" }, + { css::presentation::EffectPresetClass::ENTRANCE, 52 ,"ooo-entrance-curve-up" }, + { css::presentation::EffectPresetClass::ENTRANCE, 53 ,"ooo-entrance-fade-in-and-zoom" }, + { css::presentation::EffectPresetClass::ENTRANCE, 54 ,"ooo-entrance-glide" }, + { css::presentation::EffectPresetClass::ENTRANCE, 55 ,"ooo-entrance-expand" }, + { css::presentation::EffectPresetClass::ENTRANCE, 56 ,"ooo-entrance-flip" }, + { css::presentation::EffectPresetClass::ENTRANCE, 58 ,"ooo-entrance-fold" }, + { css::presentation::EffectPresetClass::EMPHASIS, 1 ,"ooo-emphasis-fill-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 2 ,"ooo-emphasis-font" }, + { css::presentation::EffectPresetClass::EMPHASIS, 3 ,"ooo-emphasis-font-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 4 ,"ooo-emphasis-font-size" }, + { css::presentation::EffectPresetClass::EMPHASIS, 5 ,"ooo-emphasis-font-style" }, + { css::presentation::EffectPresetClass::EMPHASIS, 6 ,"ooo-emphasis-grow-and-shrink" }, + { css::presentation::EffectPresetClass::EMPHASIS, 7 ,"ooo-emphasis-line-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 8 ,"ooo-emphasis-spin" }, + { css::presentation::EffectPresetClass::EMPHASIS, 9 ,"ooo-emphasis-transparency" }, + { css::presentation::EffectPresetClass::EMPHASIS, 10 ,"ooo-emphasis-bold-flash" }, + { css::presentation::EffectPresetClass::EMPHASIS, 14 ,"ooo-emphasis-blast" }, + { css::presentation::EffectPresetClass::EMPHASIS, 15 ,"ooo-emphasis-bold-reveal" }, + { css::presentation::EffectPresetClass::EMPHASIS, 16 ,"ooo-emphasis-color-over-by-word" }, + { css::presentation::EffectPresetClass::EMPHASIS, 18 ,"ooo-emphasis-reveal-underline" }, + { css::presentation::EffectPresetClass::EMPHASIS, 19 ,"ooo-emphasis-color-blend" }, + { css::presentation::EffectPresetClass::EMPHASIS, 20 ,"ooo-emphasis-color-over-by-letter" }, + { css::presentation::EffectPresetClass::EMPHASIS, 21 ,"ooo-emphasis-complementary-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 22 ,"ooo-emphasis-complementary-color-2" }, + { css::presentation::EffectPresetClass::EMPHASIS, 23 ,"ooo-emphasis-contrasting-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 24 ,"ooo-emphasis-darken" }, + { css::presentation::EffectPresetClass::EMPHASIS, 25 ,"ooo-emphasis-desaturate" }, + { css::presentation::EffectPresetClass::EMPHASIS, 26 ,"ooo-emphasis-flash-bulb" }, + { css::presentation::EffectPresetClass::EMPHASIS, 27 ,"ooo-emphasis-flicker" }, + { css::presentation::EffectPresetClass::EMPHASIS, 28 ,"ooo-emphasis-grow-with-color" }, + { css::presentation::EffectPresetClass::EMPHASIS, 30 ,"ooo-emphasis-lighten" }, + { css::presentation::EffectPresetClass::EMPHASIS, 31 ,"ooo-emphasis-style-emphasis" }, + { css::presentation::EffectPresetClass::EMPHASIS, 32 ,"ooo-emphasis-teeter" }, + { css::presentation::EffectPresetClass::EMPHASIS, 33 ,"ooo-emphasis-vertical-highlight" }, + { css::presentation::EffectPresetClass::EMPHASIS, 34 ,"ooo-emphasis-wave" }, + { css::presentation::EffectPresetClass::EMPHASIS, 35 ,"ooo-emphasis-blink" }, + { css::presentation::EffectPresetClass::EMPHASIS, 36 ,"ooo-emphasis-shimmer" }, + { css::presentation::EffectPresetClass::EXIT, 1 ,"ooo-exit-disappear" }, + { css::presentation::EffectPresetClass::EXIT, 2 ,"ooo-exit-fly-out" }, + { css::presentation::EffectPresetClass::EXIT, 3 ,"ooo-exit-venetian-blinds" }, + { css::presentation::EffectPresetClass::EXIT, 4 ,"ooo-exit-box" }, + { css::presentation::EffectPresetClass::EXIT, 5 ,"ooo-exit-checkerboard" }, + { css::presentation::EffectPresetClass::EXIT, 6 ,"ooo-exit-circle" }, + { css::presentation::EffectPresetClass::EXIT, 7 ,"ooo-exit-crawl-out" }, + { css::presentation::EffectPresetClass::EXIT, 8 ,"ooo-exit-diamond" }, + { css::presentation::EffectPresetClass::EXIT, 9 ,"ooo-exit-dissolve" }, + { css::presentation::EffectPresetClass::EXIT, 10 ,"ooo-exit-fade-out" }, + { css::presentation::EffectPresetClass::EXIT, 11 ,"ooo-exit-flash-once" }, + { css::presentation::EffectPresetClass::EXIT, 12 ,"ooo-exit-peek-out" }, + { css::presentation::EffectPresetClass::EXIT, 13 ,"ooo-exit-plus" }, + { css::presentation::EffectPresetClass::EXIT, 14 ,"ooo-exit-random-bars" }, + { css::presentation::EffectPresetClass::EXIT, 15 ,"ooo-exit-spiral-out" }, + { css::presentation::EffectPresetClass::EXIT, 16 ,"ooo-exit-split" }, + { css::presentation::EffectPresetClass::EXIT, 17 ,"ooo-exit-collapse" }, + { css::presentation::EffectPresetClass::EXIT, 18 ,"ooo-exit-diagonal-squares" }, + { css::presentation::EffectPresetClass::EXIT, 19 ,"ooo-exit-swivel" }, + { css::presentation::EffectPresetClass::EXIT, 20 ,"ooo-exit-wedge" }, + { css::presentation::EffectPresetClass::EXIT, 21 ,"ooo-exit-wheel" }, + { css::presentation::EffectPresetClass::EXIT, 22 ,"ooo-exit-wipe" }, + { css::presentation::EffectPresetClass::EXIT, 23 ,"ooo-exit-zoom" }, + { css::presentation::EffectPresetClass::EXIT, 24 ,"ooo-exit-random" }, + { css::presentation::EffectPresetClass::EXIT, 25 ,"ooo-exit-boomerang" }, + { css::presentation::EffectPresetClass::EXIT, 26 ,"ooo-exit-bounce" }, + { css::presentation::EffectPresetClass::EXIT, 27 ,"ooo-exit-colored-lettering" }, + { css::presentation::EffectPresetClass::EXIT, 28 ,"ooo-exit-movie-credits" }, + { css::presentation::EffectPresetClass::EXIT, 29 ,"ooo-exit-ease-out" }, + { css::presentation::EffectPresetClass::EXIT, 30 ,"ooo-exit-float" }, + { css::presentation::EffectPresetClass::EXIT, 31 ,"ooo-exit-turn-and-grow" }, + { css::presentation::EffectPresetClass::EXIT, 34 ,"ooo-exit-breaks" }, + { css::presentation::EffectPresetClass::EXIT, 35 ,"ooo-exit-pinwheel" }, + { css::presentation::EffectPresetClass::EXIT, 37 ,"ooo-exit-sink-down" }, + { css::presentation::EffectPresetClass::EXIT, 38 ,"ooo-exit-swish" }, + { css::presentation::EffectPresetClass::EXIT, 39 ,"ooo-exit-thread" }, + { css::presentation::EffectPresetClass::EXIT, 40 ,"ooo-exit-unfold" }, + { css::presentation::EffectPresetClass::EXIT, 41 ,"ooo-exit-whip" }, + { css::presentation::EffectPresetClass::EXIT, 42 ,"ooo-exit-descend" }, + { css::presentation::EffectPresetClass::EXIT, 43 ,"ooo-exit-center-revolve" }, + { css::presentation::EffectPresetClass::EXIT, 45 ,"ooo-exit-fade-out-and-swivel" }, + { css::presentation::EffectPresetClass::EXIT, 47 ,"ooo-exit-ascend" }, + { css::presentation::EffectPresetClass::EXIT, 48 ,"ooo-exit-sling" }, + { css::presentation::EffectPresetClass::EXIT, 53 ,"ooo-exit-fade-out-and-zoom" }, + { css::presentation::EffectPresetClass::EXIT, 55 ,"ooo-exit-contract" }, + { css::presentation::EffectPresetClass::EXIT, 49 ,"ooo-exit-spin-out" }, + { css::presentation::EffectPresetClass::EXIT, 50 ,"ooo-exit-stretchy" }, + { css::presentation::EffectPresetClass::EXIT, 51 ,"ooo-exit-magnify" }, + { css::presentation::EffectPresetClass::EXIT, 52 ,"ooo-exit-curve-down" }, + { css::presentation::EffectPresetClass::EXIT, 54 ,"ooo-exit-glide" }, + { css::presentation::EffectPresetClass::EXIT, 56 ,"ooo-exit-flip" }, + { css::presentation::EffectPresetClass::EXIT, 58 ,"ooo-exit-fold" }, + + { css::presentation::EffectPresetClass::MOTIONPATH, 16 ,"ooo-motionpath-4-point-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 5 ,"ooo-motionpath-5-point-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 11 ,"ooo-motionpath-6-point-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 17 ,"ooo-motionpath-8-point-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 1 ,"ooo-motionpath-circle" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 6 ,"ooo-motionpath-crescent-moon" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 3 ,"ooo-motionpath-diamond" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 13 ,"ooo-motionpath-equal-triangle" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 12 ,"ooo-motionpath-oval" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 9 ,"ooo-motionpath-heart" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 4 ,"ooo-motionpath-hexagon" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 10 ,"ooo-motionpath-octagon" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 14 ,"ooo-motionpath-parallelogram" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 15 ,"ooo-motionpath-pentagon" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 2 ,"ooo-motionpath-right-triangle" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 7 ,"ooo-motionpath-square" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 18 ,"ooo-motionpath-teardrop" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 8 ,"ooo-motionpath-trapezoid" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 37 ,"ooo-motionpath-arc-down" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 51 ,"ooo-motionpath-arc-left" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 58 ,"ooo-motionpath-arc-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 44 ,"ooo-motionpath-arc-up" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 41 ,"ooo-motionpath-bounce-left" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 54 ,"ooo-motionpath-bounce-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 48 ,"ooo-motionpath-curvy-left" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 61 ,"ooo-motionpath-curvy-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 60 ,"ooo-motionpath-decaying-wave" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 49 ,"ooo-motionpath-diagonal-down-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 56 ,"ooo-motionpath-diagonal-up-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 42 ,"ooo-motionpath-down" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 52 ,"ooo-motionpath-funnel" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 53 ,"ooo-motionpath-spring" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 62 ,"ooo-motionpath-stairs-down" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 50 ,"ooo-motionpath-turn-down" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 36 ,"ooo-motionpath-turn-down-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 43 ,"ooo-motionpath-turn-up" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 57 ,"ooo-motionpath-turn-up-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 64 ,"ooo-motionpath-up" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 47 ,"ooo-motionpath-wave" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 38 ,"ooo-motionpath-zigzag" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 31 ,"ooo-motionpath-bean" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 25 ,"ooo-motionpath-buzz-saw" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 20 ,"ooo-motionpath-curved-square" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 21 ,"ooo-motionpath-curved-x" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 23 ,"ooo-motionpath-curvy-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 28 ,"ooo-motionpath-figure-8-four" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 26 ,"ooo-motionpath-horizontal-figure-8" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 34 ,"ooo-motionpath-inverted-square" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 33 ,"ooo-motionpath-inverted-triangle" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 24 ,"ooo-motionpath-loop-de-loop" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 29 ,"ooo-motionpath-neutron" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 27 ,"ooo-motionpath-peanut" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 32 ,"ooo-motionpath-clover" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 19 ,"ooo-motionpath-pointy-star" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 30 ,"ooo-motionpath-swoosh" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 22 ,"ooo-motionpath-vertical-figure-8" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 35 ,"ooo-motionpath-left" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 63 ,"ooo-motionpath-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 55 ,"ooo-motionpath-spiral-left" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 46 ,"ooo-motionpath-spiral-right" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 40 ,"ooo-motionpath-sine-wave" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 59 ,"ooo-motionpath-s-curve-1" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 39 ,"ooo-motionpath-s-curve-2" }, + { css::presentation::EffectPresetClass::MOTIONPATH, 45 ,"ooo-motionpath-heartbeat" }, + + { 0,0,nullptr } + }; + + return aList; +}; + +OUString getConvertedSubType( sal_Int16 nPresetClass, sal_Int32 nPresetId, sal_Int32 nPresetSubType ) +{ + const char* pStr = nullptr; + + if( (nPresetClass == EffectPresetClass::ENTRANCE) || (nPresetClass == EffectPresetClass::EXIT) ) + { + // skip wheel effect + if( nPresetId != 21 ) + { + if( nPresetId == 5 ) + { + // checkerboard + switch( nPresetSubType ) + { + case 5: pStr = "downward"; break; + case 10: pStr = "across"; break; + } + } + else if( nPresetId == 17 ) + { + // stretch + if( nPresetSubType == 10 ) + pStr = "across"; + } + else if( nPresetId == 18 ) + { + // strips + switch( nPresetSubType ) + { + case 3: pStr = "right-to-top"; break; + case 6: pStr = "right-to-bottom"; break; + case 9: pStr = "left-to-top"; break; + case 12: pStr = "left-to-bottom"; break; + } + } + + if( pStr == nullptr ) + { + const convert_subtype* p = convert_subtype::getList(); + + while( p->mpStrSubType ) + { + if( p->mnID == nPresetSubType ) + { + pStr = p->mpStrSubType; + break; + } + p++; + } + } + } + } + + if( pStr ) + return OUString::createFromAscii( pStr ); + else + return OUString::number( nPresetSubType ); +} + + CommonTimeNodeContext::CommonTimeNodeContext( + FragmentHandler2 const & rParent, + sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + , mbIterate( false ) + { + AttributeList attribs( xAttribs ); + sal_Int32 nInt; // some temporary int value for float conversions + + NodePropertyMap & aProps = pNode->getNodeProperties(); + TimeNode::UserDataMap & aUserData = pNode->getUserData(); + + if( attribs.hasAttribute( XML_accel ) ) + { + double dPercent = ::oox::drawingml::GetPositiveFixedPercentage( xAttribs->getOptionalValue( XML_accel ) ); + aProps[ NP_ACCELERATION ] <<= dPercent; + } + + if( attribs.hasAttribute( XML_afterEffect ) ) + { + aUserData[ "after-effect" ] + <<= attribs.getBool( XML_afterEffect, false ); + } + aProps[ NP_AUTOREVERSE ] <<= attribs.getBool( XML_autoRev, false ); + + // TODO + if( attribs.hasAttribute( XML_bldLvl ) ) + { + attribs.getInteger( XML_bldLvl, 0 ); + } + if( attribs.hasAttribute( XML_decel ) ) + { + double dPercent = ::oox::drawingml::GetPositiveFixedPercentage( xAttribs->getOptionalValue( XML_decel ) ); + aProps[ NP_DECELERATE ] <<= dPercent; + } + // TODO + if( attribs.hasAttribute( XML_display ) ) + { + aProps[ NP_DISPLAY ] <<= attribs.getBool( XML_display, true ); + } + if( attribs.hasAttribute( XML_dur ) ) + { + aProps[ NP_DURATION ] = GetTime( xAttribs->getOptionalValue( XML_dur) ); + } + // TODO + if( attribs.hasAttribute( XML_evtFilter ) ) + { + xAttribs->getOptionalValue( XML_evtFilter ); + } + // ST_TLTimeNodeFillType + if( attribs.hasAttribute( XML_fill ) ) + { + nInt = xAttribs->getOptionalValueToken( XML_fill, 0 ); + if( nInt != 0 ) + { + sal_Int16 nEnum; + switch( nInt ) + { + case XML_remove: + nEnum = AnimationFill::REMOVE; + break; + case XML_freeze: + nEnum = AnimationFill::FREEZE; + break; + case XML_hold: + nEnum = AnimationFill::HOLD; + break; + case XML_transition: + nEnum = AnimationFill::TRANSITION; + break; + default: + nEnum = AnimationFill::DEFAULT; + break; + } + aProps[ NP_FILL ] <<= nEnum; + } + } + if( attribs.hasAttribute( XML_grpId ) ) + { + attribs.getUnsigned( XML_grpId, 0 ); + } + // ST_TLTimeNodeID + if( attribs.hasAttribute( XML_id ) ) + { + sal_uInt32 nId = attribs.getUnsigned( XML_id, 0 ); + pNode->setId( nId ); + } + // ST_TLTimeNodeMasterRelation + nInt = xAttribs->getOptionalValueToken( XML_masterRel, 0 ); + if( nInt ) + { + // TODO + switch(nInt) + { + case XML_sameClick: + case XML_lastClick: + case XML_nextClick: + break; + } + } + + // TODO + if( attribs.hasAttribute( XML_nodePh ) ) + { + attribs.getBool( XML_nodePh, false ); + } + // ST_TLTimeNodeType + nInt = xAttribs->getOptionalValueToken( XML_nodeType, 0 ); + if( nInt != 0 ) + { + sal_Int16 nEnum; + switch( nInt ) + { + case XML_clickEffect: + case XML_clickPar: + nEnum = EffectNodeType::ON_CLICK; + break; + case XML_withEffect: + case XML_withGroup: + nEnum = EffectNodeType::WITH_PREVIOUS; + break; + case XML_mainSeq: + nEnum = EffectNodeType::MAIN_SEQUENCE; + break; + case XML_interactiveSeq: + nEnum = EffectNodeType::INTERACTIVE_SEQUENCE; + break; + case XML_afterGroup: + case XML_afterEffect: + nEnum = EffectNodeType::AFTER_PREVIOUS; + break; + case XML_tmRoot: + nEnum = EffectNodeType::TIMING_ROOT; + break; + default: + nEnum = EffectNodeType::DEFAULT; + break; + } + aUserData[ "node-type" ] <<= nEnum; + } + + // ST_TLTimeNodePresetClassType + nInt = xAttribs->getOptionalValueToken( XML_presetClass, 0 ); + if( nInt != 0 ) + { + sal_Int16 nEffectPresetClass = 0; + // TODO put that in a function + switch( nInt ) + { + case XML_entr: + nEffectPresetClass = EffectPresetClass::ENTRANCE; + break; + case XML_exit: + nEffectPresetClass = EffectPresetClass::EXIT; + break; + case XML_emph: + nEffectPresetClass = EffectPresetClass::EMPHASIS; + break; + case XML_path: + nEffectPresetClass = EffectPresetClass::MOTIONPATH; + break; + case XML_verb: + // TODO check that the value below is correct + nEffectPresetClass = EffectPresetClass::OLEACTION; + break; + case XML_mediacall: + nEffectPresetClass = EffectPresetClass::MEDIACALL; + break; + default: + nEffectPresetClass = 0; + break; + } + aUserData[ "preset-class" ] <<= nEffectPresetClass; + if( attribs.hasAttribute( XML_presetID ) ) + { + sal_Int32 nPresetId = attribs.getInteger( XML_presetID, 0 ); + const preset_mapping* p = preset_mapping::getList(); + while( p->mpStrPresetId && ((p->mnPresetClass != nEffectPresetClass) || (p->mnPresetId != nPresetId )) ) + p++; + + aUserData[ "preset-id" ] + <<= OUString::createFromAscii( p->mpStrPresetId ); + sal_Int32 nPresetSubType = attribs.getInteger( XML_presetSubtype, 0 ); + if( nPresetSubType ) + { + aUserData[ "preset-sub-type" ] <<= getConvertedSubType( nEffectPresetClass, nPresetId, nPresetSubType ); + } + } + } + if( attribs.hasAttribute( XML_repeatCount ) ) + { + aProps[ NP_REPEATCOUNT ] = GetTime( xAttribs->getOptionalValue( XML_repeatCount ) ); + } + /* see pptinanimation */ +// aProps[ NP_REPEATCOUNT ] <<= (fCount < ((float)3.40282346638528860e+38)) ? makeAny( (double)fCount ) : makeAny( Timing_INDEFINITE ); + if( attribs.hasAttribute( XML_repeatDur ) ) + { + aProps[ NP_REPEATDURATION ] = GetTime( xAttribs->getOptionalValue( XML_repeatDur ) ); + } + // TODO repeatDur is otherwise the same as dur. What shall we do? -- Hub + + // ST_TLTimeNodeRestartType + nInt = xAttribs->getOptionalValueToken( XML_restart, 0 ); + if( nInt != 0 ) + { + // TODO put that in a function + sal_Int16 nEnum; + switch( nInt ) + { + case XML_always: + nEnum = AnimationRestart::ALWAYS; + break; + case XML_whenNotActive: + nEnum = AnimationRestart::WHEN_NOT_ACTIVE; + break; + case XML_never: + nEnum = AnimationRestart::NEVER; + break; + default: + nEnum = AnimationRestart::DEFAULT; + break; + } + aProps[ NP_RESTART ] <<= nEnum; + } + // ST_Percentage TODO + xAttribs->getOptionalValue( XML_spd /*"10000" */ ); + // ST_TLTimeNodeSyncType TODO + xAttribs->getOptionalValue( XML_syncBehavior ); + // TODO (string) + xAttribs->getOptionalValue( XML_tmFilter ); + } + + CommonTimeNodeContext::~CommonTimeNodeContext( ) noexcept + { + } + + void CommonTimeNodeContext::onEndElement() + { + if( isCurrentElement( PPT_TOKEN( iterate ) ) ) + { + mbIterate = false; + } + } + + ::oox::core::ContextHandlerRef CommonTimeNodeContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + + switch ( aElementToken ) + { + case PPT_TOKEN( childTnLst ): + case PPT_TOKEN( subTnLst ): + return new TimeNodeListContext( *this, mpNode->getChildren() ); + + case PPT_TOKEN( stCondLst ): + return new CondListContext( *this, aElementToken, mpNode, mpNode->getStartCondition() ); + case PPT_TOKEN( endCondLst ): + return new CondListContext( *this, aElementToken, mpNode, mpNode->getEndCondition() ); + + case PPT_TOKEN( endSync ): + return new CondContext( *this, rAttribs.getFastAttributeList(), mpNode, mpNode->getEndSyncValue() ); + case PPT_TOKEN( iterate ): + { + sal_Int32 nVal = rAttribs.getToken( XML_type, XML_el ); + if( nVal != 0 ) + { + // TODO put that in a function + sal_Int16 nEnum; + switch( nVal ) + { + case XML_el: + nEnum = TextAnimationType::BY_PARAGRAPH; + break; + case XML_lt: + nEnum = TextAnimationType::BY_LETTER; + break; + case XML_wd: + nEnum = TextAnimationType::BY_WORD; + break; + default: + // default is BY_WORD. See Ppt97Animation::GetTextAnimationType() + // in sd/source/filter/ppt/ppt97animations.cxx:297 + nEnum = TextAnimationType::BY_WORD; + break; + } + mpNode->getNodeProperties()[ NP_ITERATETYPE ] <<= nEnum; + } + // in case of exception we ignore the whole tag. + // TODO what to do with this + /*bool bBackwards =*/ rAttribs.getBool( XML_backwards, false ); + mbIterate = true; + return this; + } + case PPT_TOKEN( tmAbs ): + if( mbIterate ) + { + double fTime = rAttribs.getUnsigned( XML_val, 0 ) / 1000.0; // convert ms. to second. + mpNode->getNodeProperties()[NP_ITERATEINTERVAL] <<= fTime; + } + return this; + case PPT_TOKEN( tmPct ): + if( mbIterate ) + { + // TODO: should use duration to get iterate interval in second. + double fPercent = static_cast<double>(rAttribs.getUnsigned( XML_val, 0 )) / 100000.0; + mpNode->getNodeProperties()[ NP_ITERATEINTERVAL ] <<= fPercent; + } + return this; + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/commontimenodecontext.hxx b/oox/source/ppt/commontimenodecontext.hxx new file mode 100644 index 0000000000..80ca749269 --- /dev/null +++ b/oox/source/ppt/commontimenodecontext.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_COMMONTIMENODECONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_COMMONTIMENODECONTEXT_HXX + +#include <oox/ppt/timenode.hxx> +#include <oox/ppt/timenodelistcontext.hxx> + +namespace oox::ppt { + + /** CT_TLCommonTimeNodeData */ + class CommonTimeNodeContext + : public TimeNodeContext + { + public: + CommonTimeNodeContext( ::oox::core::FragmentHandler2 const & rParent, sal_Int32 aElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttribs, const TimeNodePtr & pNode); + virtual ~CommonTimeNodeContext( ) noexcept override; + + virtual void onEndElement() override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + bool mbIterate; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/conditioncontext.cxx b/oox/source/ppt/conditioncontext.cxx new file mode 100644 index 0000000000..39fa33bc6b --- /dev/null +++ b/oox/source/ppt/conditioncontext.cxx @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "conditioncontext.hxx" + +#include <com/sun/star/animations/AnimationEndSync.hpp> +#include <com/sun/star/animations/EventTrigger.hpp> + +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/animationspersist.hxx> +#include "animationtypes.hxx" +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +#include "timetargetelementcontext.hxx" + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::animations; + +namespace oox::ppt { + + CondContext::CondContext( FragmentHandler2 const & rParent, const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, AnimationCondition & aValue ) + : TimeNodeContext( rParent, PPT_TOKEN( cond ), pNode ) + , maCond( aValue ) + { + maEvent.Trigger = EventTrigger::NONE; + maEvent.Repeat = 0; + + AttributeList attribs( xAttribs ); + if( attribs.hasAttribute( XML_evt ) ) + { + sal_Int32 nEvent = xAttribs->getOptionalValueToken( XML_evt, 0 ); + switch( nEvent ) + { + case XML_onBegin: + maEvent.Trigger = EventTrigger::ON_BEGIN; + break; + case XML_onEnd: + maEvent.Trigger = EventTrigger::ON_END; + break; + case XML_begin: + maEvent.Trigger = EventTrigger::BEGIN_EVENT; + break; + case XML_end: + maEvent.Trigger = EventTrigger::END_EVENT; + break; + case XML_onClick: + maEvent.Trigger = EventTrigger::ON_CLICK; + break; + case XML_onDblClick: + maEvent.Trigger = EventTrigger::ON_DBL_CLICK; + break; + case XML_onMouseOver: + maEvent.Trigger = EventTrigger::ON_MOUSE_ENTER; + break; + case XML_onMouseOut: + maEvent.Trigger = EventTrigger::ON_MOUSE_LEAVE; + break; + case XML_onNext: + maEvent.Trigger = EventTrigger::ON_NEXT; + break; + case XML_onPrev: + maEvent.Trigger = EventTrigger::ON_PREV; + break; + case XML_onStopAudio: + maEvent.Trigger = EventTrigger::ON_STOP_AUDIO; + break; + default: + break; + } + } + if( attribs.hasAttribute( XML_delay ) || ( maEvent.Trigger == EventTrigger::NONE ) ) + { + maEvent.Offset = GetTime( xAttribs->getOptionalValue( XML_delay ) ); + } + } + + CondContext::~CondContext( ) noexcept + { + if( maCond.mnType == 0 || maCond.mnType == PPT_TOKEN(tn)) + { + maCond.maValue = (maEvent.Trigger == EventTrigger::NONE) ? maEvent.Offset : Any( maEvent ); + } + } + + ::oox::core::ContextHandlerRef CondContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + switch( aElementToken ) + { + case PPT_TOKEN( rtn ): + { + // ST_TLTriggerRuntimeNode { first, last, all } + sal_Int32 aTok; + sal_Int16 nEnum; + aTok = rAttribs.getToken( XML_val, XML_first ); + switch( aTok ) + { + case XML_first: + nEnum = AnimationEndSync::FIRST; + break; + case XML_last: + nEnum = AnimationEndSync::LAST; + break; + case XML_all: + nEnum = AnimationEndSync::ALL; + break; + default: + break; + } + maCond.mnType = aElementToken; + maCond.maValue <<= nEnum; + return this; + } + case PPT_TOKEN( tn ): + { + maCond.mnType = aElementToken; + // Convert the node id string to XAnimationNode later + maEvent.Source <<= rAttribs.getStringDefaulted(XML_val); + return this; + } + case PPT_TOKEN( tgtEl ): + // CT_TLTimeTargetElement + return new TimeTargetElementContext( *this, maCond.getTarget() ); + default: + break; + } + + return this; + + } + + /** CT_TLTimeConditionList */ + CondListContext::CondListContext( + FragmentHandler2 const & rParent, sal_Int32 aElement, + const TimeNodePtr & pNode, + AnimationConditionList & aCond ) + : TimeNodeContext( rParent, aElement, pNode ) + , maConditions( aCond ) + { + } + + CondListContext::~CondListContext( ) + noexcept + { + } + + ::oox::core::ContextHandlerRef CondListContext::onCreateContext( sal_Int32 aElement, const AttributeList& rAttribs ) + { + switch( aElement ) + { + case PPT_TOKEN( cond ): + // add a condition to the list + maConditions.emplace_back( ); + return new CondContext( *this, rAttribs.getFastAttributeList(), mpNode, maConditions.back() ); + default: + break; + } + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/conditioncontext.hxx b/oox/source/ppt/conditioncontext.hxx new file mode 100644 index 0000000000..fd8d4dd109 --- /dev/null +++ b/oox/source/ppt/conditioncontext.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_CONDITIONCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_CONDITIONCONTEXT_HXX + +#include <com/sun/star/animations/Event.hpp> + +#include <oox/ppt/timenode.hxx> +#include <oox/ppt/timenodelistcontext.hxx> +#include <oox/ppt/animationspersist.hxx> + +namespace oox::ppt { + + /** CT_TLTimeCondition */ + class CondContext + : public TimeNodeContext + { + public: + CondContext( ::oox::core::FragmentHandler2 const & rParent, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode, AnimationCondition & aCond ); + virtual ~CondContext( ) noexcept override; + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + css::animations::Event maEvent; + AnimationCondition & maCond; + }; + + /** CT_TLTimeConditionList */ + class CondListContext + : public TimeNodeContext + { + public: + CondListContext( ::oox::core::FragmentHandler2 const & rParent, + sal_Int32 aElement, + const TimeNodePtr & pNode, AnimationConditionList & aCondList ); + virtual ~CondListContext( ) noexcept override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + AnimationConditionList & maConditions; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/customshowlistcontext.cxx b/oox/source/ppt/customshowlistcontext.cxx new file mode 100644 index 0000000000..fa76e55f37 --- /dev/null +++ b/oox/source/ppt/customshowlistcontext.cxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/customshowlistcontext.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +namespace { + +class CustomShowContext : public ::oox::core::FragmentHandler2 +{ + std::vector< CustomShow >& mrCustomShowList; + +public: + CustomShowContext( ::oox::core::FragmentHandler2 const & rParent, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttribs, + std::vector< CustomShow >& rCustomShowList ); + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; +}; + +} + +CustomShowContext::CustomShowContext( FragmentHandler2 const & rParent, + const Reference< XFastAttributeList >& rxAttribs, + std::vector< CustomShow >& rCustomShowList ) +: FragmentHandler2( rParent ) +, mrCustomShowList( rCustomShowList ) +{ + CustomShow aCustomShow; + aCustomShow.maCustomShowName = rxAttribs->getOptionalValue( XML_name ); + aCustomShow.mnId = rxAttribs->getOptionalValue( XML_id ); + mrCustomShowList.push_back(aCustomShow); +} + +::oox::core::ContextHandlerRef CustomShowContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( sld ) : + mrCustomShowList.back().maSldLst.push_back( + getRelations() + .getRelationFromRelId(rAttribs.getStringDefaulted(R_TOKEN(id))) + ->maTarget); + return this; + default: + break; + } + + return this; +} + +CustomShowListContext::CustomShowListContext( FragmentHandler2 const & rParent, + std::vector< CustomShow >& rCustomShowList ) +: FragmentHandler2( rParent ) +, mrCustomShowList( rCustomShowList ) +{ +} + +CustomShowListContext::~CustomShowListContext( ) +{ +} + +::oox::core::ContextHandlerRef CustomShowListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( custShow ) : + { + return new CustomShowContext( *this, rAttribs.getFastAttributeList(), mrCustomShowList ); + } + default: + break; + } + + return this; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/extdrawingfragmenthandler.cxx b/oox/source/ppt/extdrawingfragmenthandler.cxx new file mode 100644 index 0000000000..96cc02c1a3 --- /dev/null +++ b/oox/source/ppt/extdrawingfragmenthandler.cxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "extdrawingfragmenthandler.hxx" + +#include <oox/ppt/pptshapegroupcontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <utility> + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + +namespace oox::ppt { + +ExtDrawingFragmentHandler::ExtDrawingFragmentHandler( XmlFilterBase& rFilter, + const OUString& rFragmentPath, + oox::ppt::SlidePersistPtr pSlidePersistPtr, + const oox::ppt::ShapeLocation eShapeLocation, + oox::drawingml::ShapePtr pGroupShapePtr, + oox::drawingml::ShapePtr pShapePtr) + : FragmentHandler2( rFilter, rFragmentPath ), + mpSlidePersistPtr (std::move(pSlidePersistPtr )), + meShapeLocation( eShapeLocation ), + mpGroupShapePtr(std::move( pGroupShapePtr )), + mpShapePtr(std::move( pShapePtr )) +{ +} + +ExtDrawingFragmentHandler::~ExtDrawingFragmentHandler( ) noexcept +{ + // Empty DrawingML fallback, need to warn the user at the end. + if (mpShapePtr && mpShapePtr->getChildren().empty()) + getFilter().setMissingExtDrawing(); +} + +ContextHandlerRef +ExtDrawingFragmentHandler::onCreateContext( ::sal_Int32 aElement, + const AttributeList& ) +{ + switch( aElement ) + { + case DSP_TOKEN( drawing ): + break; + case DSP_TOKEN( spTree ): + return new PPTShapeGroupContext( + *this, mpSlidePersistPtr, meShapeLocation, mpGroupShapePtr, + mpShapePtr ); + default: + break; + } + + return this; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/extdrawingfragmenthandler.hxx b/oox/source/ppt/extdrawingfragmenthandler.hxx new file mode 100644 index 0000000000..ddc828af4c --- /dev/null +++ b/oox/source/ppt/extdrawingfragmenthandler.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_EXTDRAWINGFRAGMENTHANDLER_HXX +#define INCLUDED_OOX_SOURCE_PPT_EXTDRAWINGFRAGMENTHANDLER_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/ppt/slidepersist.hxx> + +namespace oox::ppt { + +class ExtDrawingFragmentHandler : public ::oox::core::FragmentHandler2 +{ +public: + ExtDrawingFragmentHandler( oox::core::XmlFilterBase& rFilter, const OUString& rFragmentPath, + oox::ppt::SlidePersistPtr pSlidePersistPtr, + const oox::ppt::ShapeLocation eShapeLocation, + oox::drawingml::ShapePtr pGroupShapePtr, + oox::drawingml::ShapePtr pShapePtr ); + virtual ~ExtDrawingFragmentHandler() noexcept override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const AttributeList& rAttribs ) override; + +private: + const oox::ppt::SlidePersistPtr mpSlidePersistPtr; + const oox::ppt::ShapeLocation meShapeLocation; + oox::drawingml::ShapePtr mpGroupShapePtr; + oox::drawingml::ShapePtr mpShapePtr; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/headerfootercontext.cxx b/oox/source/ppt/headerfootercontext.cxx new file mode 100644 index 0000000000..2a51fdafd4 --- /dev/null +++ b/oox/source/ppt/headerfootercontext.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "headerfootercontext.hxx" +#include <oox/helper/attributelist.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + + HeaderFooterContext::HeaderFooterContext( FragmentHandler2 const & rParent, + const AttributeList& rAttribs, HeaderFooter& rHeaderFooter ) + : FragmentHandler2( rParent ) + { + if ( rAttribs.hasAttribute( XML_sldNum ) ) + { + rHeaderFooter.mbSlideNumber = rAttribs.getBool( XML_sldNum, true ); + } + if ( rAttribs.hasAttribute( XML_hdr ) ) + { + rHeaderFooter.mbHeader = rAttribs.getBool( XML_hdr, true ); + } + if ( rAttribs.hasAttribute( XML_ftr ) ) + { + rHeaderFooter.mbFooter = rAttribs.getBool( XML_ftr, true ); + } + if ( rAttribs.hasAttribute( XML_dt ) ) + { + rHeaderFooter.mbDateTime = rAttribs.getBool( XML_dt, true ); + } + } + + HeaderFooterContext::~HeaderFooterContext( ) + { + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/headerfootercontext.hxx b/oox/source/ppt/headerfootercontext.hxx new file mode 100644 index 0000000000..9b93fb5f1b --- /dev/null +++ b/oox/source/ppt/headerfootercontext.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_HEADERFOOTERCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_HEADERFOOTERCONTEXT_HXX + +#include <oox/ppt/headerfooter.hxx> +#include <oox/core/fragmenthandler2.hxx> + +namespace oox::ppt { + + /** CT_HeaderFooter */ + class HeaderFooterContext : public ::oox::core::FragmentHandler2 + { + public: + HeaderFooterContext( ::oox::core::FragmentHandler2 const & rParent, + const AttributeList& rAttribs, HeaderFooter& rHeaderFooter ); + + virtual ~HeaderFooterContext( ) override; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/layoutfragmenthandler.cxx b/oox/source/ppt/layoutfragmenthandler.cxx new file mode 100644 index 0000000000..352eded1fa --- /dev/null +++ b/oox/source/ppt/layoutfragmenthandler.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "headerfootercontext.hxx" +#include <oox/ppt/layoutfragmenthandler.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <utility> + +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::ppt { + +// CT_SlideLayout + +LayoutFragmentHandler::LayoutFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath, + const SlidePersistPtr& pMasterPersistPtr) + : SlideFragmentHandler(rFilter, rFragmentPath, pMasterPersistPtr, Layout) +{ +} + +LayoutFragmentHandler::~LayoutFragmentHandler() +{ + +} + +ContextHandlerRef LayoutFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( sldLayout ): // CT_SlideLayout + { + mpSlidePersistPtr->setLayoutValueToken( rAttribs.getToken( XML_type, 0 ) ); // CT_SlideLayoutType + + std::optional< bool > aShowMasterShapes = rAttribs.getBool( XML_showMasterSp ); + if( aShowMasterShapes.has_value() && !aShowMasterShapes.value() ) { + mpSlidePersistPtr->hideShapesAsMasterShapes(); + } + break; + } + case PPT_TOKEN( hf ): // CT_HeaderFooter + return new HeaderFooterContext( *this, rAttribs, mpSlidePersistPtr->getHeaderFooter() ); + default: + return SlideFragmentHandler::onCreateContext( aElementToken, rAttribs ); + } + return this; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptfilterhelpers.cxx b/oox/source/ppt/pptfilterhelpers.cxx new file mode 100644 index 0000000000..054bf6260c --- /dev/null +++ b/oox/source/ppt/pptfilterhelpers.cxx @@ -0,0 +1,422 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/animations/TransitionType.hpp> +#include <com/sun/star/animations/TransitionSubType.hpp> +#include <com/sun/star/animations/ValuePair.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> +#include <tools/color.hxx> +#include <o3tl/string_view.hxx> + +namespace { + int lcl_gethex(int nChar) + { + if (nChar >= '0' && nChar <= '9') + return nChar - '0'; + else if (nChar >= 'a' && nChar <= 'f') + return nChar - 'a' + 10; + else if (nChar >= 'A' && nChar <= 'F') + return nChar - 'A' + 10; + else + return 0; + } +} + +namespace oox::ppt { + + const ImplAttributeNameConversion *getAttributeConversionList() + { + static const ImplAttributeNameConversion aList[] = + { + { AnimationAttributeEnum::PPT_X, "ppt_x", "X" }, + { AnimationAttributeEnum::PPT_Y, "ppt_y", "Y" }, + { AnimationAttributeEnum::PPT_W, "ppt_w", "Width" }, + { AnimationAttributeEnum::PPT_H, "ppt_h", "Height" }, + { AnimationAttributeEnum::PPT_C, "ppt_c", "DimColor" }, + { AnimationAttributeEnum::R, "r", "Rotate" }, + { AnimationAttributeEnum::XSHEAR, "xshear", "SkewX" }, + { AnimationAttributeEnum::FILLCOLOR, "fillcolor", "FillColor" }, + { AnimationAttributeEnum::FILLCOLOR, "fillColor", "FillColor" }, + { AnimationAttributeEnum::FILLTYPE, "fill.type", "FillStyle" }, + { AnimationAttributeEnum::FILLON, "fill.on", "FillOn" }, + { AnimationAttributeEnum::STROKECOLOR, "stroke.color", "LineColor" }, + { AnimationAttributeEnum::STROKEON, "stroke.on", "LineStyle" }, + { AnimationAttributeEnum::STYLECOLOR, "style.color", "CharColor" }, + { AnimationAttributeEnum::STYLEROTATION, "style.rotation", "Rotate" }, + { AnimationAttributeEnum::FONTWEIGHT, "style.fontWeight", "CharWeight" }, + { AnimationAttributeEnum::STYLEUNDERLINE, "style.textDecorationUnderline","CharUnderline" }, + { AnimationAttributeEnum::STYLEFONTFAMILY, "style.fontFamily", "CharFontName" }, + { AnimationAttributeEnum::STYLEFONTSIZE, "style.fontSize", "CharHeight" }, + { AnimationAttributeEnum::STYLEFONTSTYLE, "style.fontStyle", "CharPosture" }, + { AnimationAttributeEnum::STYLEVISIBILITY, "style.visibility", "Visibility" }, + { AnimationAttributeEnum::STYLEOPACITY, "style.opacity", "Opacity" }, + { AnimationAttributeEnum::UNKNOWN, nullptr, nullptr } + }; + + return aList; + } + + const transition* transition::getList() + { + static const transition aList[] = + { + { "wipe(up)", css::animations::TransitionType::BARWIPE, css::animations::TransitionSubType::TOPTOBOTTOM, true }, + { "wipe(right)", css::animations::TransitionType::BARWIPE, css::animations::TransitionSubType::LEFTTORIGHT, false }, + { "wipe(left)", css::animations::TransitionType::BARWIPE, css::animations::TransitionSubType::LEFTTORIGHT, true }, + { "wipe(down)", css::animations::TransitionType::BARWIPE, css::animations::TransitionSubType::TOPTOBOTTOM, false }, + { "wheel(1)", css::animations::TransitionType::PINWHEELWIPE, css::animations::TransitionSubType::ONEBLADE, true }, + { "wheel(2)", css::animations::TransitionType::PINWHEELWIPE, css::animations::TransitionSubType::TWOBLADEVERTICAL, true }, + { "wheel(3)", css::animations::TransitionType::PINWHEELWIPE, css::animations::TransitionSubType::THREEBLADE, true }, + { "wheel(4)", css::animations::TransitionType::PINWHEELWIPE, css::animations::TransitionSubType::FOURBLADE, true }, + { "wheel(8)", css::animations::TransitionType::PINWHEELWIPE, css::animations::TransitionSubType::EIGHTBLADE, true }, + { "strips(downLeft)", css::animations::TransitionType::WATERFALLWIPE, css::animations::TransitionSubType::HORIZONTALRIGHT, true }, + { "strips(upLeft)", css::animations::TransitionType::WATERFALLWIPE, css::animations::TransitionSubType::HORIZONTALLEFT, false }, + { "strips(downRight)", css::animations::TransitionType::WATERFALLWIPE, css::animations::TransitionSubType::HORIZONTALLEFT, true }, + { "strips(upRight)", css::animations::TransitionType::WATERFALLWIPE, css::animations::TransitionSubType::HORIZONTALRIGHT, false }, + { "barn(inVertical)", css::animations::TransitionType::BARNDOORWIPE, css::animations::TransitionSubType::VERTICAL, false }, + { "barn(outVertical)", css::animations::TransitionType::BARNDOORWIPE, css::animations::TransitionSubType::VERTICAL, true }, + { "barn(inHorizontal)", css::animations::TransitionType::BARNDOORWIPE, css::animations::TransitionSubType::HORIZONTAL, false }, + { "barn(outHorizontal)", css::animations::TransitionType::BARNDOORWIPE, css::animations::TransitionSubType::HORIZONTAL, true }, + { "randombar(vertical)", css::animations::TransitionType::RANDOMBARWIPE, css::animations::TransitionSubType::VERTICAL, true}, + { "randombar(horizontal)", css::animations::TransitionType::RANDOMBARWIPE, css::animations::TransitionSubType::HORIZONTAL, true }, + { "checkerboard(down)", css::animations::TransitionType::CHECKERBOARDWIPE, css::animations::TransitionSubType::DOWN, true}, + { "checkerboard(across)", css::animations::TransitionType::CHECKERBOARDWIPE, css::animations::TransitionSubType::ACROSS, true }, + { "plus(out)", css::animations::TransitionType::FOURBOXWIPE, css::animations::TransitionSubType::CORNERSIN, false }, + { "plus(in)", css::animations::TransitionType::FOURBOXWIPE, css::animations::TransitionSubType::CORNERSIN, true }, + { "diamond(out)", css::animations::TransitionType::IRISWIPE, css::animations::TransitionSubType::DIAMOND, true }, + { "diamond(in)", css::animations::TransitionType::IRISWIPE, css::animations::TransitionSubType::DIAMOND, false }, + { "circle(out)", css::animations::TransitionType::ELLIPSEWIPE, css::animations::TransitionSubType::HORIZONTAL, true }, + { "circle(in)", css::animations::TransitionType::ELLIPSEWIPE, css::animations::TransitionSubType::HORIZONTAL, false }, + { "box(out)", css::animations::TransitionType::IRISWIPE, css::animations::TransitionSubType::RECTANGLE, true }, + { "box(in)", css::animations::TransitionType::IRISWIPE, css::animations::TransitionSubType::RECTANGLE, false }, + { "wedge", css::animations::TransitionType::FANWIPE, css::animations::TransitionSubType::CENTERTOP, true }, + { "blinds(vertical)", css::animations::TransitionType::BLINDSWIPE, css::animations::TransitionSubType::VERTICAL, true }, + { "blinds(horizontal)", css::animations::TransitionType::BLINDSWIPE, css::animations::TransitionSubType::HORIZONTAL, true }, + { "fade", css::animations::TransitionType::FADE, css::animations::TransitionSubType::CROSSFADE, true }, + { "slide(fromTop)", css::animations::TransitionType::SLIDEWIPE, css::animations::TransitionSubType::FROMTOP, true }, + { "slide(fromRight)", css::animations::TransitionType::SLIDEWIPE, css::animations::TransitionSubType::FROMRIGHT, true }, + { "slide(fromLeft)", css::animations::TransitionType::SLIDEWIPE, css::animations::TransitionSubType::FROMLEFT, true }, + { "slide(fromBottom)", css::animations::TransitionType::SLIDEWIPE, css::animations::TransitionSubType::FROMBOTTOM, true }, + { "dissolve", css::animations::TransitionType::DISSOLVE, css::animations::TransitionSubType::DEFAULT, true }, + { "image", css::animations::TransitionType::DISSOLVE, css::animations::TransitionSubType::DEFAULT, true }, // TODO + { nullptr, 0, 0, false } + }; + + return aList; + } + + const transition* transition::find( std::u16string_view rName ) + { + const transition* p = transition::getList(); + + while( p->mpName ) + { + if( o3tl::equalsAscii( rName, p->mpName ) ) + return p; + + p++; + } + + return nullptr; + } + + bool convertMeasure(OUString& rString) + { + bool bRet = false; + + const char* pSource[] = { "ppt_x", "ppt_y", "ppt_w", "ppt_h", nullptr }; + const char* pDest[] = { "x", "y", "width", "height", nullptr }; + + /* here we want to substitute all occurrences of + * [#]ppt_[xyhw] with + * x,y,height and width respectively + */ + sal_Int32 nIndex = 0; + + const char** ps = pSource; + const char** pd = pDest; + + while (*ps) + { + const OUString aSearch(OUString::createFromAscii(*ps)); + while ((nIndex = rString.indexOf(aSearch, nIndex)) != -1) + { + sal_Int32 nLength = aSearch.getLength(); + if (nIndex && (rString[nIndex - 1] == '#')) + { + nIndex--; + nLength++; + } + + const OUString aNew(OUString::createFromAscii(*pd)); + rString = rString.replaceAt(nIndex, nLength, aNew); + nIndex += aNew.getLength(); + bRet = true; + } + ps++; + pd++; + } + + return bRet; + } + + bool convertAnimationValue(AnimationAttributeEnum eAttribute, css::uno::Any& rValue) + { + using css::animations::ValuePair; + bool bRet = false; + switch (eAttribute) + { + case AnimationAttributeEnum::PPT_X: + case AnimationAttributeEnum::PPT_Y: + case AnimationAttributeEnum::PPT_W: + case AnimationAttributeEnum::PPT_H: + { + OUString aString; + + if (rValue.getValueType() == cppu::UnoType<ValuePair>::get()) + { + ValuePair aValuePair; + if (rValue >>= aValuePair) + { + if (aValuePair.First >>= aString) + { + if (convertMeasure(aString)) + { + aValuePair.First <<= aString; + bRet = true; + } + } + + if (aValuePair.Second >>= aString) + { + if (convertMeasure(aString)) + { + aValuePair.Second <<= aString; + bRet = true; + } + } + } + } + else if (rValue.getValueType() == cppu::UnoType<OUString>::get()) + { + if (rValue >>= aString) + { + bRet = convertMeasure(aString); + + if (bRet) + rValue <<= aString; + } + } + } + break; + + case AnimationAttributeEnum::XSHEAR: + case AnimationAttributeEnum::R: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString.toDouble(); + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STYLEROTATION: + { + if (rValue.getValueType() == cppu::UnoType<OUString>::get()) + { + OUString aString; + rValue >>= aString; + rValue <<= static_cast<sal_Int16>(aString.toDouble()); + bRet = true; + } + else if (rValue.getValueType() == cppu::UnoType<double>::get()) + { + double fValue = 0.0; + rValue >>= fValue; + rValue <<= static_cast<sal_Int16>(fValue); + bRet = true; + } + } + break; + + case AnimationAttributeEnum::FILLCOLOR: + case AnimationAttributeEnum::STROKECOLOR: + case AnimationAttributeEnum::STYLECOLOR: + case AnimationAttributeEnum::PPT_C: + { + OUString aString; + if (rValue >>= aString) + { + if (aString.getLength() >= 7 && aString[0] == '#') + { + Color aColor; + aColor.SetRed(static_cast<sal_uInt8>(lcl_gethex(aString[1]) * 16 + + lcl_gethex(aString[2]))); + aColor.SetGreen(static_cast<sal_uInt8>(lcl_gethex(aString[3]) * 16 + + lcl_gethex(aString[4]))); + aColor.SetBlue(static_cast<sal_uInt8>(lcl_gethex(aString[5]) * 16 + + lcl_gethex(aString[6]))); + rValue <<= aColor; + bRet = true; + } + else if (aString.startsWith("rgb(")) + { + aString = aString.copy(4, aString.getLength() - 5); + Color aColor; + sal_Int32 index = 0; + aColor.SetRed( + static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)))); + aColor.SetGreen( + static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)))); + aColor.SetRed( + static_cast<sal_uInt8>(o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)))); + rValue <<= aColor; + bRet = true; + } + else if (aString.startsWith("hsl(")) + { + sal_Int32 index = 0; + sal_Int32 nA = o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)); + sal_Int32 nB = o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)); + sal_Int32 nC = o3tl::toInt32(o3tl::getToken(aString, 0, ',', index)); + css::uno::Sequence<double> aHSL + { + nA * 360.0 / 255.0, + nB / 255.0, + nC / 255.0 + }; + rValue <<= aHSL; + bRet = true; + } + } + } + break; + case AnimationAttributeEnum::FILLON: + { + // Slideshow doesn't support FillOn, but we need to convert the value type + // so it can be written out again. + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "true"; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::FILLTYPE: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "solid" ? css::drawing::FillStyle_SOLID + : css::drawing::FillStyle_NONE; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STROKEON: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "true" ? css::drawing::LineStyle_SOLID + : css::drawing::LineStyle_NONE; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::FONTWEIGHT: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "bold" ? css::awt::FontWeight::BOLD + : css::awt::FontWeight::NORMAL; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STYLEFONTSTYLE: + { + OUString aString; + if (rValue >>= aString) + { + rValue + <<= aString == "italic" ? css::awt::FontSlant_ITALIC : css::awt::FontSlant_NONE; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STYLEUNDERLINE: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "true" ? css::awt::FontUnderline::SINGLE + : css::awt::FontUnderline::NONE; + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STYLEOPACITY: + case AnimationAttributeEnum::STYLEFONTSIZE: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= static_cast<float>(aString.toDouble()); + bRet = true; + } + } + break; + + case AnimationAttributeEnum::STYLEVISIBILITY: + { + OUString aString; + if (rValue >>= aString) + { + rValue <<= aString == "visible"; + bRet = true; + } + } + break; + default: + break; + } + + return bRet; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptgraphicshapecontext.cxx b/oox/source/ppt/pptgraphicshapecontext.cxx new file mode 100644 index 0000000000..ff6b56a601 --- /dev/null +++ b/oox/source/ppt/pptgraphicshapecontext.cxx @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/pptgraphicshapecontext.hxx> +#include <oox/ppt/pptshapepropertiescontext.hxx> +#include <oox/ppt/slidepersist.hxx> +#include <drawingml/shapestylecontext.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <drawingml/textbodycontext.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <oox/token/properties.hxx> +#include <utility> + +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; + +namespace oox::ppt { + +// CT_Shape +PPTGraphicShapeContext::PPTGraphicShapeContext( ContextHandler2Helper const & rParent, SlidePersistPtr pSlidePersistPtr, const oox::drawingml::ShapePtr& pMasterShapePtr, const oox::drawingml::ShapePtr& pShapePtr ) +: oox::drawingml::GraphicShapeContext( rParent, pMasterShapePtr, pShapePtr ) +, mpSlidePersistPtr(std::move( pSlidePersistPtr )) +{ +} + +ContextHandlerRef PPTGraphicShapeContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + // nvSpPr CT_ShapeNonVisual begin +// case NMSP_PPT|XML_drElemPr: +// break; + case PPT_TOKEN(cNvPr): + mpShapePtr->setId( rAttribs.getStringDefaulted( XML_id ) ); + mpShapePtr->setName( rAttribs.getStringDefaulted( XML_name ) ); + break; + case PPT_TOKEN(ph): + { + sal_Int32 nSubType( rAttribs.getToken( XML_type, XML_obj ) ); + mpShapePtr->setSubType( nSubType ); + OUString sIdx( rAttribs.getStringDefaulted( XML_idx ) ); + bool bHasIdx = !sIdx.isEmpty(); + sal_Int32 nIdx = sIdx.toInt32(); + if( rAttribs.hasAttribute( XML_idx ) ) + mpShapePtr->setSubTypeIndex( nIdx ); + + if ( nSubType || bHasIdx ) + { + PPTShape* pPPTShapePtr = dynamic_cast< PPTShape* >( mpShapePtr.get() ); + if ( pPPTShapePtr ) + { + oox::ppt::ShapeLocation eShapeLocation = pPPTShapePtr->getShapeLocation(); + oox::drawingml::ShapePtr pPlaceholder; + + if ( bHasIdx && eShapeLocation == Slide ) + { + // TODO: use id to shape map + SlidePersistPtr pMasterPersist( mpSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersist && rAttribs.hasAttribute( XML_idx ) ) + pPlaceholder = PPTShape::findPlaceholderByIndex( nIdx, pMasterPersist->getShapes()->getChildren() ); + } + if ( !pPlaceholder && ( ( eShapeLocation == Slide ) || ( eShapeLocation == Layout ) ) ) + { + // inheriting properties from placeholder objects by cloning shape + + sal_Int32 nFirstPlaceholder = 0; + sal_Int32 nSecondPlaceholder = 0; + switch( nSubType ) + { + case XML_ctrTitle : // slide/layout + nFirstPlaceholder = XML_ctrTitle; + nSecondPlaceholder = XML_title; + break; + case XML_subTitle : // slide/layout + nFirstPlaceholder = XML_subTitle; + nSecondPlaceholder = XML_title; + break; + case XML_obj : // slide/layout + nFirstPlaceholder = XML_body; + break; + case XML_dt : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_sldNum : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_ftr : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_hdr : // notes/notesmaster/handoutmaster + case XML_body : // slide/layout/master/notes/notesmaster + case XML_title : // slide/layout/master/ + case XML_chart : // slide/layout + case XML_tbl : // slide/layout + case XML_clipArt : // slide/layout + case XML_dgm : // slide/layout + case XML_media : // slide/layout + case XML_sldImg : // notes/notesmaster + case XML_pic : // slide/layout + nFirstPlaceholder = nSubType; + break; + default: + break; + } + if ( nFirstPlaceholder ) + { + if ( eShapeLocation == Layout ) // for layout objects the referenced object can be found within the same shape tree + pPlaceholder = PPTShape::findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, + pPPTShapePtr->getSubTypeIndex(), mpSlidePersistPtr->getShapes()->getChildren(), true ); + else if ( eShapeLocation == Slide ) // normal slide shapes have to search within the corresponding master tree for referenced objects + { + SlidePersistPtr pMasterPersist( mpSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersist ) + pPlaceholder = PPTShape::findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, + pPPTShapePtr->getSubTypeIndex(), pMasterPersist->getShapes()->getChildren() ); + } + } + } + if ( pPlaceholder ) + { + bool bUseText = true; + switch( pPlaceholder->getSubType() ) + { + case XML_title : + case XML_body : + case XML_ctrTitle : + case XML_subTitle : + case XML_dt : + case XML_sldNum : + case XML_ftr : + case XML_hdr : + case XML_obj : + case XML_chart : + case XML_tbl : + case XML_clipArt : + case XML_dgm : + case XML_media : + case XML_sldImg : + case XML_pic : + bUseText = false; + } + pPlaceholder->getShapeProperties().setAnyProperty( + PROP_URL, mpShapePtr->getShapeProperties().getProperty(PROP_URL)); + mpShapePtr->applyShapeReference( *pPlaceholder, bUseText ); + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( pPlaceholder.get() ); + if ( pPPTShape ) + pPPTShape->setReferenced( true ); + pPPTShapePtr->setPlaceholder( pPlaceholder ); + } + } + } + break; + } + // nvSpPr CT_ShapeNonVisual end + + case PPT_TOKEN(spPr): + return new PPTShapePropertiesContext( *this, *mpShapePtr ); + + case PPT_TOKEN(style): + return new oox::drawingml::ShapeStyleContext( *this, *mpShapePtr ); + + case PPT_TOKEN(txBody): + { + oox::drawingml::TextBodyPtr xTextBody = std::make_shared<oox::drawingml::TextBody>(); + mpShapePtr->setTextBody( xTextBody ); + return new oox::drawingml::TextBodyContext( *this, *xTextBody ); + } + } + + return GraphicShapeContext::onCreateContext( aElementToken, rAttribs ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptimport.cxx b/oox/source/ppt/pptimport.cxx new file mode 100644 index 0000000000..55e094db65 --- /dev/null +++ b/oox/source/ppt/pptimport.cxx @@ -0,0 +1,309 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_wasm_strip.h> + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/document/XUndoManager.hpp> +#include <com/sun/star/document/XUndoManagerSupplier.hpp> +#include <comphelper/propertysequence.hxx> +#include <comphelper/scopeguard.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <tools/urlobj.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <oox/ppt/pptimport.hxx> +#include <oox/drawingml/chart/chartconverter.hxx> +#include <oox/dump/pptxdumper.hxx> +#include <drawingml/table/tablestylelistfragmenthandler.hxx> +#include <oox/helper/graphichelper.hxx> +#include <oox/ole/vbaproject.hxx> +#include <oox/ppt/presentationfragmenthandler.hxx> +#include <oox/ppt/presPropsfragmenthandler.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace oox::core; + +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::lang::XComponent; + +namespace oox::ppt { + +#if OSL_DEBUG_LEVEL > 0 +XmlFilterBase* PowerPointImport::mpDebugFilterBase = nullptr; +#endif + +PowerPointImport::PowerPointImport( const Reference< XComponentContext >& rxContext ) : + XmlFilterBase( rxContext ), +#if ENABLE_WASM_STRIP_CHART + // WASM_CHART change + mxChartConv( ) +#else + mxChartConv( std::make_shared<::oox::drawingml::chart::ChartConverter>() ) +#endif +{ +#if OSL_DEBUG_LEVEL > 0 + mpDebugFilterBase = this; +#endif +} + +PowerPointImport::~PowerPointImport() +{ +} + +bool PowerPointImport::importDocument() +{ + /* to activate the PPTX dumper, define the environment variable + OOO_PPTXDUMPER and insert the full path to the file + file:///<path-to-oox-module>/source/dump/pptxdumper.ini. */ + OOX_DUMP_FILE( ::oox::dump::pptx::Dumper ); + + uno::Reference< document::XUndoManagerSupplier > xUndoManagerSupplier (getModel(), UNO_QUERY ); + uno::Reference< util::XLockable > xUndoManager; + bool bWasUnLocked = true; + if(xUndoManagerSupplier.is()) + { + xUndoManager = xUndoManagerSupplier->getUndoManager(); + if(xUndoManager.is()) + { + bWasUnLocked = !xUndoManager->isLocked(); + xUndoManager->lock(); + } + } + + importDocumentProperties(); + + OUString aFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"officeDocument" ); + FragmentHandlerRef xPresentationFragmentHandler( new PresentationFragmentHandler( *this, aFragmentPath ) ); + maTableStyleListPath = xPresentationFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"tableStyles" ); + const OUString sPresPropsPath + = xPresentationFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc(u"presProps"); + + bool bRet = importFragment(xPresentationFragmentHandler); + if (bRet && !sPresPropsPath.isEmpty()) + { + FragmentHandlerRef xPresPropsFragmentHandler( + new PresPropsFragmentHandler(*this, sPresPropsPath)); + importFragment(xPresPropsFragmentHandler); + } + + static bool bNoSmartartWarning = getenv("OOX_NO_SMARTART_WARNING"); + if (!bNoSmartartWarning && mbMissingExtDrawing) + { + // Construct a warning message. + INetURLObject aURL(getFileUrl()); + SfxErrorContext aContext(ERRCTX_SFX_OPENDOC, aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset), nullptr, RID_ERRCTX); + OUString aWarning; + aContext.GetString(ERRCODE_NONE.MakeWarning(), aWarning); + aWarning += ":\n" + SvxResId(RID_SVXSTR_WARN_MISSING_SMARTART); + + // Show it. + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr, + VclMessageType::Warning, VclButtonsType::Ok, + aWarning)); + xWarn->run(); + } + + if(xUndoManager.is() && bWasUnLocked) + xUndoManager->unlock(); + + return bRet; + +} + +bool PowerPointImport::exportDocument() noexcept +{ + return false; +} + +::Color PowerPointImport::getSchemeColor( sal_Int32 nToken ) const +{ + ::Color nColor; + if ( mpActualSlidePersist ) + { + bool bColorMapped = false; + oox::drawingml::ClrMapPtr pClrMapPtr( mpActualSlidePersist->getClrMap() ); + if ( pClrMapPtr ) + bColorMapped = pClrMapPtr->getColorMap( nToken ); + + if ( !bColorMapped ) // try masterpage mapping + { + SlidePersistPtr pMasterPersist = mpActualSlidePersist->getMasterPersist(); + if ( pMasterPersist ) + { + pClrMapPtr = pMasterPersist->getClrMap(); + if ( pClrMapPtr ) + pClrMapPtr->getColorMap( nToken ); + } + } + + ::oox::drawingml::ThemePtr pTheme = mpActualSlidePersist->getTheme(); + if( pTheme ) + { + pTheme->getClrScheme().getColor( nToken, nColor ); + } + else + { + SAL_WARN("oox", "OOX: PowerPointImport::mpThemePtr is NULL"); + } + } + return nColor; +} + +const ::oox::drawingml::Theme* PowerPointImport::getCurrentTheme() const +{ + return mpActualSlidePersist ? mpActualSlidePersist->getTheme().get() : nullptr; +} + +std::shared_ptr<::oox::drawingml::Theme> PowerPointImport::getCurrentThemePtr() const +{ + return mpActualSlidePersist ? mpActualSlidePersist->getTheme() : std::shared_ptr<::oox::drawingml::Theme>(); +} + +sal_Bool SAL_CALL PowerPointImport::filter( const Sequence< PropertyValue >& rDescriptor ) +{ + if( XmlFilterBase::filter( rDescriptor ) ) + return true; + + if (isExportFilter()) + { + uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence( + { + {"IsPPTM", uno::Any(exportVBA())}, + {"IsTemplate", uno::Any(isExportTemplate())}, + })); + + Reference<css::lang::XMultiServiceFactory> aFactory(getComponentContext()->getServiceManager(), UNO_QUERY_THROW); + Reference< XExporter > xExporter(aFactory->createInstanceWithArguments("com.sun.star.comp.Impress.oox.PowerPointExport", aArguments), UNO_QUERY); + + if (Reference<XFilter> xFilter{ xExporter, UNO_QUERY }) + { + Reference<util::XLockable> xUndoManager; + bool bWasUnLocked = true; + if (Reference<document::XUndoManagerSupplier> xUMS{ getModel(), UNO_QUERY }) + { + xUndoManager = xUMS->getUndoManager(); + if (xUndoManager.is()) + { + bWasUnLocked = !xUndoManager->isLocked(); + xUndoManager->lock(); + } + } + comphelper::ScopeGuard aGuard([xUndoManager, bWasUnLocked] { + if (xUndoManager && bWasUnLocked) + xUndoManager->unlock(); + }); + + Reference< XComponent > xDocument = getModel(); + xExporter->setSourceDocument(xDocument); + if (xFilter->filter(rDescriptor)) + return true; + } + } + + return false; +} + +::oox::vml::Drawing* PowerPointImport::getVmlDrawing() +{ + return mpActualSlidePersist ? mpActualSlidePersist->getDrawing() : nullptr; +} + +oox::drawingml::table::TableStyleListPtr PowerPointImport::getTableStyles() +{ + if ( !mpTableStyleList && !maTableStyleListPath.isEmpty() ) + { + mpTableStyleList = std::make_shared<oox::drawingml::table::TableStyleList>( ); + importFragment( new oox::drawingml::table::TableStyleListFragmentHandler( + *this, maTableStyleListPath, *mpTableStyleList ) ); + } + return mpTableStyleList; +} + +::oox::drawingml::chart::ChartConverter* PowerPointImport::getChartConverter() +{ + return mxChartConv.get(); +} + +namespace { + +class PptGraphicHelper : public GraphicHelper +{ +public: + explicit PptGraphicHelper( const PowerPointImport& rFilter ); + virtual ::Color getSchemeColor( sal_Int32 nToken ) const override; + virtual sal_Int32 getDefaultChartAreaFillStyle() const override; +private: + const PowerPointImport& mrFilter; +}; + +PptGraphicHelper::PptGraphicHelper( const PowerPointImport& rFilter ) : + GraphicHelper( rFilter.getComponentContext(), rFilter.getTargetFrame(), rFilter.getStorage() ), + mrFilter( rFilter ) +{ +} + +::Color PptGraphicHelper::getSchemeColor( sal_Int32 nToken ) const +{ + return mrFilter.getSchemeColor( nToken ); +} + +sal_Int32 PptGraphicHelper::getDefaultChartAreaFillStyle() const +{ + return XML_noFill; +} + +} // namespace + +GraphicHelper* PowerPointImport::implCreateGraphicHelper() const +{ + return new PptGraphicHelper( *this ); +} + +::oox::ole::VbaProject* PowerPointImport::implCreateVbaProject() const +{ + return new ::oox::ole::VbaProject( getComponentContext(), getModel(), u"Impress" ); +} + +OUString PowerPointImport::getImplementationName() +{ + return "com.sun.star.comp.oox.ppt.PowerPointImport"; +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_oox_ppt_PowerPointImport_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new oox::ppt::PowerPointImport(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx new file mode 100644 index 0000000000..733aa2a73a --- /dev/null +++ b/oox/source/ppt/pptshape.cxx @@ -0,0 +1,769 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/pptshape.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <drawingml/customshapeproperties.hxx> +#include <drawingml/textbody.hxx> +#include <drawingml/textparagraph.hxx> +#include <drawingml/textfield.hxx> +#include <editeng/flditem.hxx> + +#include <com/sun/star/text/XTextField.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/document/XEventsSupplier.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/presentation/ClickAction.hpp> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <sal/log.hxx> +#include <oox/ppt/slidepersist.hxx> +#include <oox/token/tokens.hxx> +#include <oox/token/properties.hxx> +#include <o3tl/string_view.hxx> + +using namespace ::oox::core; +using namespace ::oox::drawingml; +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::text; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::presentation; + +namespace oox::ppt { + +PPTShape::PPTShape( const oox::ppt::ShapeLocation eShapeLocation, const char* pServiceName ) +: Shape( pServiceName ) +, meShapeLocation( eShapeLocation ) +, mbReferenced( false ) +, mbHasNoninheritedShapeProperties( false ) +{ +} + +PPTShape::~PPTShape() +{ +} + +static const char* lclDebugSubType( sal_Int32 nType ) +{ + switch (nType) { + case XML_ctrTitle : + return "ctrTitle"; + case XML_title : + return "title"; + case XML_subTitle : + return "subTitle"; + case XML_obj : + return "obj"; + case XML_body : + return "body"; + case XML_dt : + return "dt"; + case XML_hdr : + return "hdr"; + case XML_ftr : + return "frt"; + case XML_sldNum : + return "sldNum"; + case XML_sldImg : + return "sldImg"; + } + + return "unknown - please extend lclDebugSubType"; +} + +namespace +{ +bool ShapeHasNoVisualPropertiesOnImport(const oox::ppt::PPTShape& rPPTShape) +{ + return !rPPTShape.hasNonInheritedShapeProperties() + && !rPPTShape.hasShapeStyleRefs() + && !rPPTShape.getTextBody()->hasVisualRunProperties() + && !rPPTShape.getTextBody()->hasNoninheritedBodyProperties() + && !rPPTShape.getTextBody()->hasListStyleOnImport() + && !rPPTShape.getTextBody()->hasParagraphProperties(); +} +} + +oox::drawingml::TextListStylePtr PPTShape::getSubTypeTextListStyle( const SlidePersist& rSlidePersist, sal_Int32 nSubType ) +{ + oox::drawingml::TextListStylePtr pTextListStyle; + + SAL_INFO("oox.ppt", "subtype style: " << lclDebugSubType( nSubType ) ); + + switch( nSubType ) + { + case XML_ctrTitle : + case XML_title : + pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle(); + break; + case XML_subTitle : + case XML_obj : + case XML_body : + if ( rSlidePersist.isNotesPage() ) + pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle(); + else + pTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + break; + } + + return pTextListStyle; +} + +bool PPTShape::IsPlaceHolderCandidate(const SlidePersist& rSlidePersist) const +{ + if (meShapeLocation != Slide) + return false; + if (rSlidePersist.isNotesPage()) + return false; + auto pTextBody = getTextBody(); + if (!pTextBody) + return false; + auto rParagraphs = pTextBody->getParagraphs(); + if (rParagraphs.size() != 1) + return false; + if (rParagraphs.front()->getRuns().size() != 1) + return false; + // If the placeholder has a shape other than rectangle, + // we have to place it in the slide as a CustomShape. + if (!mpCustomShapePropertiesPtr->representsDefaultShape()) + return false; + return ShapeHasNoVisualPropertiesOnImport(*this); +} + +void PPTShape::addShape( + oox::core::XmlFilterBase& rFilterBase, + const SlidePersist& rSlidePersist, + const oox::drawingml::Theme* pTheme, + const Reference< XShapes >& rxShapes, + basegfx::B2DHomMatrix& aTransformation, + ::oox::drawingml::ShapeIdMap* pShapeMap ) +{ + SAL_INFO("oox.ppt","add shape id: " << msId << " location: " << ((meShapeLocation == Master) ? "master" : ((meShapeLocation == Slide) ? "slide" : ((meShapeLocation == Layout) ? "layout" : "other"))) << " subtype: " << mnSubType << " service: " << msServiceName); + // only placeholder from layout are being inserted + if ( mnSubType && ( meShapeLocation == Master ) ) + return; + + OUString sServiceName( msServiceName ); + if (sServiceName.isEmpty()) + return; + try + { + oox::drawingml::TextListStylePtr aMasterTextListStyle; + Reference<lang::XMultiServiceFactory> xServiceFact(rFilterBase.getModel(), UNO_QUERY_THROW); + bool bClearText = false; + + if (sServiceName != "com.sun.star.drawing.GraphicObjectShape" && + sServiceName != "com.sun.star.drawing.OLE2Shape") + { + static constexpr OUString sOutlinerShapeService(u"com.sun.star.presentation.OutlinerShape"_ustr); + SAL_INFO("oox.ppt","has master: " << std::hex << rSlidePersist.getMasterPersist().get()); + switch (mnSubType) + { + case XML_ctrTitle : + case XML_title : + { + sServiceName = "com.sun.star.presentation.TitleTextShape"; + aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getTitleTextStyle() : rSlidePersist.getTitleTextStyle(); + } + break; + case XML_subTitle : + { + if ((meShapeLocation == Master) || (meShapeLocation == Layout)) + sServiceName = OUString(); + else { + sServiceName = "com.sun.star.presentation.SubtitleShape"; + aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + } + } + break; + case XML_obj : + { + sServiceName = sOutlinerShapeService; + if (getSubTypeIndex().has_value()) + aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + } + break; + case XML_body : + { + if (rSlidePersist.isNotesPage()) + { + sServiceName = "com.sun.star.presentation.NotesShape"; + aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getNotesTextStyle() : rSlidePersist.getNotesTextStyle(); + } + else + { + sServiceName = sOutlinerShapeService; + aMasterTextListStyle = rSlidePersist.getMasterPersist() ? rSlidePersist.getMasterPersist()->getBodyTextStyle() : rSlidePersist.getBodyTextStyle(); + } + } + break; + case XML_dt : + if (IsPlaceHolderCandidate(rSlidePersist)) + { + TextRunPtr& pTextRun = getTextBody()->getParagraphs().front()->getRuns().front(); + oox::drawingml::TextField* pTextField = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get()); + if (pTextField) + { + OUString aType = pTextField->getType(); + if ( aType.startsWith("datetime") ) + { + SvxDateFormat eDateFormat = drawingml::TextField::getLODateFormat(aType); + SvxTimeFormat eTimeFormat = drawingml::TextField::getLOTimeFormat(aType); + Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY ); + + if( eDateFormat != SvxDateFormat::AppDefault + || eTimeFormat != SvxTimeFormat::AppDefault ) + { + // DateTimeFormat property looks for the date in 4 LSBs + // and looks for time format in the 4 bits after that + sal_Int32 nDateTimeFormat = static_cast<sal_Int32>(eDateFormat) | + static_cast<sal_Int32>(eTimeFormat) << 4; + xPropertySet->setPropertyValue( "IsDateTimeVisible", Any(true) ); + xPropertySet->setPropertyValue( "IsDateTimeFixed", Any(false) ); + xPropertySet->setPropertyValue( "DateTimeFormat", Any(nDateTimeFormat) ); + return; + } + } + } + } + sServiceName = "com.sun.star.presentation.DateTimeShape"; + bClearText = true; + break; + case XML_hdr : + sServiceName = "com.sun.star.presentation.HeaderShape"; + bClearText = true; + break; + case XML_ftr : + if (IsPlaceHolderCandidate(rSlidePersist)) + { + const OUString& rFooterText = getTextBody()->toString(); + + if( !rFooterText.isEmpty() ) + { + // if it is possible to get the footer as a property the LO way, + // get it and discard the shape + Reference< XPropertySet > xPropertySet( rSlidePersist.getPage(), UNO_QUERY ); + xPropertySet->setPropertyValue( "IsFooterVisible", Any( true ) ); + xPropertySet->setPropertyValue( "FooterText", Any(rFooterText) ); + return; + } + } + sServiceName = "com.sun.star.presentation.FooterShape"; + bClearText = true; + break; + case XML_sldNum : + if (IsPlaceHolderCandidate(rSlidePersist)) + { + TextRunPtr& pTextRun + = getTextBody()->getParagraphs().front()->getRuns().front(); + oox::drawingml::TextField* pTextField + = dynamic_cast<oox::drawingml::TextField*>(pTextRun.get()); + if (pTextField && pTextField->getType() == "slidenum") + { + // if it is possible to get the slidenum placeholder as a property + // do that and discard the shape + Reference<XPropertySet> xPropertySet(rSlidePersist.getPage(), + UNO_QUERY); + xPropertySet->setPropertyValue("IsPageNumberVisible", Any(true)); + return; + } + } + sServiceName = "com.sun.star.presentation.SlideNumberShape"; + bClearText = true; + break; + case XML_sldImg : + sServiceName = "com.sun.star.presentation.PageShape"; + break; + case XML_chart : + if (meShapeLocation == Layout) + sServiceName = sOutlinerShapeService; + else + sServiceName = "com.sun.star.presentation.ChartShape"; + break; + case XML_tbl : + if (meShapeLocation == Layout) + sServiceName = sOutlinerShapeService; + else + sServiceName = "com.sun.star.presentation.TableShape"; + break; + case XML_pic : + if (meShapeLocation == Layout) + sServiceName = sOutlinerShapeService; + else + sServiceName = "com.sun.star.presentation.GraphicObjectShape"; + break; + case XML_media : + if (meShapeLocation == Layout) + sServiceName = sOutlinerShapeService; + else + sServiceName = "com.sun.star.presentation.MediaShape"; + break; + default: + if (mnSubType && meShapeLocation == Layout) + sServiceName = sOutlinerShapeService; + break; + } + } + + // Since it is not possible to represent custom shaped placeholders in Impress + // Need to use service name css.drawing.CustomShape if they have a non default shape. + // This workaround has the drawback of them not really being processed as placeholders + // so it is only done for slide footers... + bool convertInSlideMode = meShapeLocation == Slide && + (mnSubType == XML_sldNum || mnSubType == XML_dt || mnSubType == XML_ftr || mnSubType == XML_body); + bool convertInLayoutMode = meShapeLocation == Layout && (mnSubType == XML_body); + if ((convertInSlideMode || convertInLayoutMode) && !mpCustomShapePropertiesPtr->representsDefaultShape()) + { + sServiceName = "com.sun.star.drawing.CustomShape"; + } + + SAL_INFO("oox.ppt","shape service: " << sServiceName); + + if (mnSubType && getSubTypeIndex().has_value() && meShapeLocation == Layout) + { + oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex( getSubTypeIndex().value(), rSlidePersist.getShapes()->getChildren(), true ); + if (!pPlaceholder) + pPlaceholder = PPTShape::findPlaceholder( mnSubType, 0, getSubTypeIndex(), rSlidePersist.getShapes()->getChildren(), true ); + + if (pPlaceholder) { + if (maSize.Width == 0 || maSize.Height == 0) { + awt::Size aSize = maSize; + if (maSize.Width == 0) + aSize.Width = pPlaceholder->getSize().Width; + if (maSize.Height == 0) + aSize.Height = pPlaceholder->getSize().Height; + setSize( aSize ); + if (maPosition.X == 0 || maPosition.Y == 0) { + awt::Point aPosition = maPosition; + if (maPosition.X == 0) + aPosition.X = pPlaceholder->getPosition().X; + if (maPosition.Y == 0) + aPosition.Y = pPlaceholder->getPosition().Y; + setPosition( aPosition ); + } + } + } + } + + // use placeholder index if possible + if (mnSubType && getSubTypeIndex().has_value() && rSlidePersist.getMasterPersist()) + { + oox::drawingml::ShapePtr pPlaceholder = PPTShape::findPlaceholderByIndex(getSubTypeIndex().value(), rSlidePersist.getMasterPersist()->getShapes()->getChildren()); + // TODO: Check if this is required for non-notes slides as well... + if (rSlidePersist.isNotesPage() && pPlaceholder && pPlaceholder->getSubType() != getSubType()) + pPlaceholder.reset(); + + if (pPlaceholder) { + SAL_INFO("oox.ppt","found placeholder with index: " << getSubTypeIndex().value() << " and type: " << lclDebugSubType( mnSubType )); + PPTShape* pPPTPlaceholder = dynamic_cast< PPTShape* >( pPlaceholder.get() ); + TextListStylePtr pNewTextListStyle = std::make_shared<TextListStyle>(); + + if (pPlaceholder->getTextBody()) { + + pNewTextListStyle->apply( pPlaceholder->getTextBody()->getTextListStyle() ); + if (pPlaceholder->getMasterTextListStyle()) + pNewTextListStyle->apply( *pPlaceholder->getMasterTextListStyle() ); + + // SAL_INFO("oox.ppt","placeholder body style"); + // pPlaceholder->getTextBody()->getTextListStyle().dump(); + // SAL_INFO("oox.ppt","master text list style"); + // pPlaceholder->getMasterTextListStyle()->dump(); + + aMasterTextListStyle = pNewTextListStyle; + // SAL_INFO("oox.ppt","combined master text list style"); + // aMasterTextListStyle->dump(); + } + if (pPPTPlaceholder && pPPTPlaceholder->mpPlaceholder) { + SAL_INFO("oox.ppt","placeholder has parent placeholder: " << pPPTPlaceholder->mpPlaceholder->getId() << " type: " << lclDebugSubType( pPPTPlaceholder->mpPlaceholder->getSubType() ) << " index: " << pPPTPlaceholder->mpPlaceholder->getSubTypeIndex().value() ); + SAL_INFO("oox.ppt","has textbody " << (pPPTPlaceholder->mpPlaceholder->getTextBody() != nullptr) ); + TextListStylePtr pPlaceholderStyle = getSubTypeTextListStyle( rSlidePersist, pPPTPlaceholder->mpPlaceholder->getSubType() ); + if (pPPTPlaceholder->mpPlaceholder->getTextBody()) + pNewTextListStyle->apply( pPPTPlaceholder->mpPlaceholder->getTextBody()->getTextListStyle() ); + if (pPlaceholderStyle) { + pNewTextListStyle->apply( *pPlaceholderStyle ); + //pPlaceholderStyle->dump(); + } + } + } else if (!mpPlaceholder) { + aMasterTextListStyle.reset(); + } + SAL_INFO("oox.ppt","placeholder id: " << (pPlaceholder ? pPlaceholder->getId() : "not found")); + } + + if (!sServiceName.isEmpty()) + { + if (!aMasterTextListStyle) + { + bool isOther = !getTextBody() && sServiceName != "com.sun.star.drawing.GroupShape"; + TextListStylePtr aSlideStyle = isOther ? rSlidePersist.getOtherTextStyle() : rSlidePersist.getDefaultTextStyle(); + // Combine from MasterSlide details as well. + if (rSlidePersist.getMasterPersist()) + { + aMasterTextListStyle = isOther ? rSlidePersist.getMasterPersist()->getOtherTextStyle() : rSlidePersist.getMasterPersist()->getDefaultTextStyle(); + if (aSlideStyle) + aMasterTextListStyle->apply( *aSlideStyle ); + } + else + { + aMasterTextListStyle = aSlideStyle; + } + } + + if( aMasterTextListStyle && getTextBody() ) { + TextListStylePtr aCombinedTextListStyle = std::make_shared<TextListStyle>(); + + aCombinedTextListStyle->apply( *aMasterTextListStyle ); + + if( mpPlaceholder && mpPlaceholder->getTextBody() ) + aCombinedTextListStyle->apply( mpPlaceholder->getTextBody()->getTextListStyle() ); + aCombinedTextListStyle->apply( getTextBody()->getTextListStyle() ); + + setMasterTextListStyle( aCombinedTextListStyle ); + } else + setMasterTextListStyle( aMasterTextListStyle ); + + Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, bClearText, bool(mpPlaceholder), aTransformation, getFillProperties() ) ); + + // Apply text properties on placeholder text inside this placeholder shape + if (meShapeLocation == Slide && mpPlaceholder && getTextBody() && getTextBody()->isEmpty()) + { + Reference < XText > xText(mxShape, UNO_QUERY); + if (xText.is()) + { + TextCharacterProperties aCharStyleProperties; + getTextBody()->ApplyStyleEmpty(rFilterBase, xText, aCharStyleProperties, mpMasterTextListStyle); + } + } + if (pShapeMap) + { + // bnc#705982 - if optional model id reference is + // there, use that to obtain target shape + if (!msModelId.isEmpty()) + { + (*pShapeMap)[ msModelId ] = shared_from_this(); + } + else if (!msId.isEmpty()) + { + (*pShapeMap)[ msId ] = shared_from_this(); + } + } + + // we will be losing whatever information there is in the footer placeholder on master/layout slides + // since they should have the "<footer>" textfield in them in order to make LibreOffice process them as expected + // likewise DateTime placeholder data on master/layout slides will be lost and replaced + if( (mnSubType == XML_ftr || mnSubType == XML_dt) && meShapeLocation != Slide ) + { + OUString aFieldType; + if( mnSubType == XML_ftr ) + aFieldType = "com.sun.star.presentation.TextField.Footer"; + else + aFieldType = "com.sun.star.presentation.TextField.DateTime"; + Reference < XTextField > xField( xServiceFact->createInstance( aFieldType ), UNO_QUERY ); + Reference < XText > xText(mxShape, UNO_QUERY); + if(xText.is()) + { + xText->setString(""); + Reference < XTextCursor > xTextCursor = xText->createTextCursor(); + xText->insertTextContent( xTextCursor, xField, false); + } + } + + OUString sURL; + std::vector<std::pair<OUString, Reference<XShape>>> aURLShapes; + // if this is a group shape, we have to add also each child shape + Reference<XShapes> xShapes(xShape, UNO_QUERY); + if (xShapes.is()) + { + // temporarily remember setting + NamedShapePairs* pDiagramFontHeights(rFilterBase.getDiagramFontHeights()); + + // for shapes unequal to FRAMETYPE_DIAGRAM do + // disable DiagramFontHeights recording + if (meFrameType != FRAMETYPE_DIAGRAM) + rFilterBase.setDiagramFontHeights(nullptr); + + addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aTransformation ); + + // restore remembered setting + rFilterBase.setDiagramFontHeights(pDiagramFontHeights); + + for (size_t i = 0; i < this->getChildren().size(); i++) + { + this->getChildren()[i]->getShapeProperties().getProperty(PROP_URL) >>= sURL; + if (!sURL.isEmpty()) + { + Reference<XShape> xChild = this->getChildren()[i]->getXShape(); + aURLShapes.push_back({ sURL, xChild }); + } + } + } + + if (meFrameType == FRAMETYPE_DIAGRAM) + { + keepDiagramCompatibilityInfo(); + } + + // Support advanced DiagramHelper + if (FRAMETYPE_DIAGRAM == meFrameType) + { + propagateDiagramHelper(); + } + + getShapeProperties().getProperty(PROP_URL) >>= sURL; + if (!sURL.isEmpty() && !xShapes.is()) + aURLShapes.push_back({ sURL, xShape }); + + if (!aURLShapes.empty()) + { + for (auto const& URLShape : aURLShapes) + { + Reference<XEventsSupplier> xEventsSupplier(URLShape.second, UNO_QUERY); + if (!xEventsSupplier.is()) + return; + + Reference<XNameReplace> xEvents(xEventsSupplier->getEvents()); + if (!xEvents.is()) + return; + + OUString sAPIEventName; + sal_Int32 nPropertyCount = 2; + css::presentation::ClickAction meClickAction; + uno::Sequence<beans::PropertyValue> aProperties; + + std::map<OUString, css::presentation::ClickAction> ActionMap = { + { "#action?jump=nextslide", ClickAction_NEXTPAGE }, + { "#action?jump=previousslide", ClickAction_PREVPAGE }, + { "#action?jump=firstslide", ClickAction_FIRSTPAGE }, + { "#action?jump=lastslide", ClickAction_LASTPAGE }, + { "#action?jump=endshow", ClickAction_STOPPRESENTATION }, + }; + + sURL = URLShape.first; + std::map<OUString, css::presentation::ClickAction>::const_iterator aIt + = ActionMap.find(sURL); + aIt != ActionMap.end() ? meClickAction = aIt->second + : meClickAction = ClickAction_BOOKMARK; + + // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same event + // so check here if it's a bookmark or a document + if (meClickAction == ClickAction_BOOKMARK) + { + if (!sURL.startsWith("#")) + meClickAction = ClickAction_DOCUMENT; + else + { + sURL = OUString::Concat("page") + + sURL.subView(sURL.lastIndexOf(' ') + 1); + } + nPropertyCount += 1; + } + + aProperties.realloc(nPropertyCount); + beans::PropertyValue* pProperties = aProperties.getArray(); + + pProperties->Name = "EventType"; + pProperties->Handle = -1; + pProperties->Value <<= OUString("Presentation"); + pProperties->State = beans::PropertyState_DIRECT_VALUE; + pProperties++; + + pProperties->Name = "ClickAction"; + pProperties->Handle = -1; + pProperties->Value <<= meClickAction; + pProperties->State = beans::PropertyState_DIRECT_VALUE; + pProperties++; + + switch (meClickAction) + { + case ClickAction_BOOKMARK: + case ClickAction_DOCUMENT: + pProperties->Name = "Bookmark"; + pProperties->Handle = -1; + pProperties->Value <<= sURL; + pProperties->State = beans::PropertyState_DIRECT_VALUE; + break; + default: + break; + } + + sAPIEventName = "OnClick"; + xEvents->replaceByName(sAPIEventName, uno::Any(aProperties)); + } + } + } + } + catch (const Exception&) + { + } +} + +namespace +{ + bool ShapeLocationIsMaster(oox::drawingml::Shape *pInShape) + { + PPTShape* pShape = dynamic_cast<PPTShape*>(pInShape); + return pShape && pShape->getShapeLocation() == Master; + } +} + +// Function to find placeholder (ph) for a shape. No idea how MSO implements this, but +// this order seems to work quite well +// (probably it's unnecessary complicated / wrong. i.e. tdf#104202): +// 1. ph with nFirstSubType and the same oSubTypeIndex +// 2. ph with nFirstSubType +// 3. ph with nSecondSubType and the same oSubTypeIndex +// 4. ph with nSecondSubType +// 5. ph with the same oSubTypeIndex + +oox::drawingml::ShapePtr PPTShape::findPlaceholder( sal_Int32 nFirstSubType, sal_Int32 nSecondSubType, + const std::optional< sal_Int32 >& oSubTypeIndex, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly ) +{ + class Placeholders + { + public: + Placeholders() + : aChoice(5) // resize to 5 + { + } + + void add(const oox::drawingml::ShapePtr& aShape, sal_Int32 nFirstSubType, sal_Int32 nSecondSubType, const std::optional< sal_Int32 >& oSubTypeIndex) + { + if (!aShape) + return; + + // get flags + const bool bSameFirstSubType = aShape->getSubType() == nFirstSubType; + const bool bSameSecondSubType = aShape->getSubType() == nSecondSubType; + const bool bSameIndex = aShape->getSubTypeIndex() == oSubTypeIndex; + + // get prio + int aPrioIndex = -1; + if (bSameIndex && bSameFirstSubType) + aPrioIndex = 0; + else if (!bSameIndex && bSameFirstSubType) + aPrioIndex = 1; + else if (bSameIndex && bSameSecondSubType) + aPrioIndex = 2; + else if (!bSameIndex && bSameSecondSubType) + aPrioIndex = 3; + else if (bSameIndex) + aPrioIndex = 4; + + // add + if (aPrioIndex != -1) + { + if (!aChoice.at(aPrioIndex)) + { + aChoice.at(aPrioIndex) = aShape; + } + } + } + + // return according to prio + oox::drawingml::ShapePtr getByPrio() const + { + for (const oox::drawingml::ShapePtr& aShape : aChoice) + { + if (aShape) + { + return aShape; + } + } + + return oox::drawingml::ShapePtr(); + } + + bool hasByPrio(size_t aIndex) const + { + return bool(aChoice.at(aIndex)); + } + + private: + std::vector< oox::drawingml::ShapePtr > aChoice; + + } aPlaceholders; + + // check all shapes + std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() ); + for (; aRevIter != rShapes.rend(); ++aRevIter) + { + // check shape + if (!bMasterOnly || ShapeLocationIsMaster((*aRevIter).get())) + { + const oox::drawingml::ShapePtr& aShape = *aRevIter; + aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex); + } + + // check children + std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren(); + if (!rChildren.empty()) + { + const oox::drawingml::ShapePtr aShape = findPlaceholder( nFirstSubType, nSecondSubType, oSubTypeIndex, rChildren, bMasterOnly ); + if (aShape) + { + aPlaceholders.add(aShape, nFirstSubType, nSecondSubType, oSubTypeIndex); + } + } + + if (aPlaceholders.hasByPrio(0)) + { + break; + } + } + + // return something according to prio + return aPlaceholders.getByPrio(); +} + +oox::drawingml::ShapePtr PPTShape::findPlaceholderByIndex( const sal_Int32 nIdx, std::vector< oox::drawingml::ShapePtr >& rShapes, bool bMasterOnly ) +{ + oox::drawingml::ShapePtr aShapePtr; + + std::vector< oox::drawingml::ShapePtr >::reverse_iterator aRevIter( rShapes.rbegin() ); + while( aRevIter != rShapes.rend() ) + { + if ( (*aRevIter)->getSubTypeIndex().has_value() && (*aRevIter)->getSubTypeIndex().value() == nIdx && + ( !bMasterOnly || ShapeLocationIsMaster((*aRevIter).get()) ) ) + { + aShapePtr = *aRevIter; + break; + } + std::vector< oox::drawingml::ShapePtr >& rChildren = (*aRevIter)->getChildren(); + aShapePtr = findPlaceholderByIndex( nIdx, rChildren, bMasterOnly ); + if ( aShapePtr ) + break; + ++aRevIter; + } + return aShapePtr; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptshapecontext.cxx b/oox/source/ppt/pptshapecontext.cxx new file mode 100644 index 0000000000..f127c3a2a2 --- /dev/null +++ b/oox/source/ppt/pptshapecontext.cxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/log.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/pptshapecontext.hxx> +#include <oox/ppt/pptshapepropertiescontext.hxx> +#include <oox/ppt/slidepersist.hxx> +#include <drawingml/shapestylecontext.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <drawingml/textbodycontext.hxx> +#include <drawingml/transform2dcontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> +#include <utility> + +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; + +namespace oox::ppt { + +// CT_Shape +PPTShapeContext::PPTShapeContext( ContextHandler2Helper const & rParent, SlidePersistPtr pSlidePersistPtr, const oox::drawingml::ShapePtr& pMasterShapePtr, const oox::drawingml::ShapePtr& pShapePtr ) +: oox::drawingml::ShapeContext( rParent, pMasterShapePtr, pShapePtr ) +, mpSlidePersistPtr(std::move( pSlidePersistPtr )) +{ +} + +ContextHandlerRef PPTShapeContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + if( getNamespace( aElementToken ) == NMSP_dsp ) + aElementToken = NMSP_ppt | getBaseToken( aElementToken ); + + switch( aElementToken ) + { + // nvSpPr CT_ShapeNonVisual begin + // case PPT_TOKEN( drElemPr ): + // break; + case PPT_TOKEN( cNvPr ): + { + mpShapePtr->setHidden( rAttribs.getBool( XML_hidden, false ) ); + mpShapePtr->setId( rAttribs.getStringDefaulted( XML_id ) ); + mpShapePtr->setName( rAttribs.getStringDefaulted( XML_name ) ); + break; + } + case PPT_TOKEN( ph ): + { + SlidePersistPtr pMasterPersist( mpSlidePersistPtr->getMasterPersist() ); + std::optional< sal_Int32 > oSubType( rAttribs.getToken( XML_type) ); + sal_Int32 nSubType( rAttribs.getToken( XML_type, XML_obj ) ); + oox::drawingml::ShapePtr pTmpPlaceholder; + + mpShapePtr->setSubType( nSubType ); + + if( rAttribs.hasAttribute( XML_idx ) ) + { + sal_Int32 nSubTypeIndex = rAttribs.getInteger( XML_idx, 0 ); + mpShapePtr->setSubTypeIndex( nSubTypeIndex ); + + if(!oSubType.has_value() && pMasterPersist) + { + pTmpPlaceholder = PPTShape::findPlaceholderByIndex( nSubTypeIndex, pMasterPersist->getShapes()->getChildren() ); + + if(pTmpPlaceholder) + nSubType = pTmpPlaceholder->getSubType(); // When we don't have type attribute on slide but have on slidelayout we have to use it instead of default type + } + } + + if ( nSubType ) + { + PPTShape* pPPTShapePtr = dynamic_cast< PPTShape* >( mpShapePtr.get() ); + if ( pPPTShapePtr ) + { + oox::ppt::ShapeLocation eShapeLocation = pPPTShapePtr->getShapeLocation(); + if ( ( eShapeLocation == Slide ) || ( eShapeLocation == Layout ) ) + { + // inheriting properties from placeholder objects by cloning shape + sal_Int32 nFirstPlaceholder = 0; + sal_Int32 nSecondPlaceholder = 0; + switch( nSubType ) + { + case XML_ctrTitle : // slide/layout + nFirstPlaceholder = XML_ctrTitle; + nSecondPlaceholder = XML_title; + break; + + case XML_subTitle : // slide/layout + nFirstPlaceholder = XML_subTitle; + nSecondPlaceholder = XML_body; + break; + + case XML_obj : // slide/layout + nFirstPlaceholder = XML_obj; + nSecondPlaceholder = XML_body; + break; + + case XML_dt : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_sldNum : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_ftr : // slide/layout/master/notes/notesmaster/handoutmaster + case XML_hdr : // notes/notesmaster/handoutmaster + case XML_body : // slide/layout/master/notes/notesmaster + case XML_title : // slide/layout/master/ + case XML_chart : // slide/layout + case XML_tbl : // slide/layout + case XML_clipArt : // slide/layout + case XML_dgm : // slide/layout + case XML_media : // slide/layout + case XML_sldImg : // notes/notesmaster + case XML_pic : // slide/layout + nFirstPlaceholder = nSubType; + break; + default: + break; + } + if ( nFirstPlaceholder ) + { + oox::drawingml::ShapePtr pPlaceholder; + if ( eShapeLocation == Layout ) // for layout objects the referenced object can be found within the same shape tree + { + pPlaceholder = PPTShape::findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, + pPPTShapePtr->getSubTypeIndex(), mpSlidePersistPtr->getShapes()->getChildren(), true ); + } + else if ( eShapeLocation == Slide ) // normal slide shapes have to search within the corresponding master tree for referenced objects + { + if ( pMasterPersist ) + { + pPlaceholder = PPTShape::findPlaceholder( nFirstPlaceholder, nSecondPlaceholder, + pPPTShapePtr->getSubTypeIndex(), pMasterPersist->getShapes()->getChildren() ); + } + } + if ( pPlaceholder ) + { + SAL_INFO("oox.ppt","shape " << mpShapePtr->getId() << + " will get shape reference " << pPlaceholder->getId() << " applied"); + mpShapePtr->applyShapeReference( *pPlaceholder ); + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( pPlaceholder.get() ); + if ( pPPTShape ) + pPPTShape->setReferenced( true ); + pPPTShapePtr->setPlaceholder( pPlaceholder ); + } + } + } + } + + } + break; + } + + // nvSpPr CT_ShapeNonVisual end + + case PPT_TOKEN( spPr ): + return new PPTShapePropertiesContext( *this, *mpShapePtr ); + + case PPT_TOKEN( style ): + return new oox::drawingml::ShapeStyleContext( *this, *mpShapePtr ); + + case PPT_TOKEN( txBody ): + { + oox::drawingml::TextBodyPtr xTextBody = std::make_shared<oox::drawingml::TextBody>( mpShapePtr->getTextBody() ); + xTextBody->getTextProperties().maPropertyMap.setProperty( PROP_FontIndependentLineSpacing, true ); + mpShapePtr->setTextBody( xTextBody ); + return new oox::drawingml::TextBodyContext( *this, mpShapePtr ); + } + case PPT_TOKEN( txXfrm ): + { + return new oox::drawingml::Transform2DContext( *this, rAttribs, *mpShapePtr, true ); + } + } + + return ShapeContext::onCreateContext(aElementToken, rAttribs); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptshapegroupcontext.cxx b/oox/source/ppt/pptshapegroupcontext.cxx new file mode 100644 index 0000000000..49a5f5ce4b --- /dev/null +++ b/oox/source/ppt/pptshapegroupcontext.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <com/sun/star/xml/sax/FastToken.hpp> + +#include <oox/core/xmlfilterbase.hxx> +#include <oox/core/fragmenthandler2.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/pptgraphicshapecontext.hxx> +#include <oox/ppt/pptshapecontext.hxx> +#include <oox/ppt/pptshapegroupcontext.hxx> +#include <oox/drawingml/graphicshapecontext.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <drawingml/shapepropertiescontext.hxx> +#include <oox/drawingml/connectorshapecontext.hxx> +#include <drawingml/fillproperties.hxx> +#include "extdrawingfragmenthandler.hxx" +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <utility> + +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::text; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +PPTShapeGroupContext::PPTShapeGroupContext( + FragmentHandler2 const & rParent, + oox::ppt::SlidePersistPtr pSlidePersistPtr, + const ShapeLocation eShapeLocation, + const oox::drawingml::ShapePtr& pMasterShapePtr, + const oox::drawingml::ShapePtr& pGroupShapePtr ) +: ShapeGroupContext( rParent, pMasterShapePtr, pGroupShapePtr ) +, mpSlidePersistPtr(std::move( pSlidePersistPtr )) +, meShapeLocation( eShapeLocation ) +{ +} + +ContextHandlerRef PPTShapeGroupContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + if( getNamespace( aElementToken ) == NMSP_dsp ) + aElementToken = NMSP_ppt | getBaseToken( aElementToken ); + + switch( aElementToken ) + { + case OOX_TOKEN(dml, extLst): + case OOX_TOKEN(dml, ext): + break; + case OOX_TOKEN(adec, decorative): + { + mpGroupShapePtr->setDecorative(rAttribs.getBool(XML_val, false)); + } + break; + case PPT_TOKEN( cNvPr ): + { + // don't override SmartArt properties for embedded drawing's spTree + mpGroupShapePtr->setHidden( rAttribs.getBool( XML_hidden, false ) ); + if (mpGroupShapePtr->getId().isEmpty()) + mpGroupShapePtr->setId(rAttribs.getStringDefaulted(XML_id)); + if (mpGroupShapePtr->getName().isEmpty()) + mpGroupShapePtr->setName( rAttribs.getStringDefaulted( XML_name ) ); + break; + } + case PPT_TOKEN( ph ): + mpGroupShapePtr->setSubType( rAttribs.getToken( XML_type, FastToken::DONTKNOW ) ); + if( rAttribs.hasAttribute( XML_idx ) ) + mpGroupShapePtr->setSubTypeIndex( rAttribs.getInteger( XML_idx, 0 ) ); + break; + // nvSpPr CT_ShapeNonVisual end + + case PPT_TOKEN( grpSpPr ): + return new oox::drawingml::ShapePropertiesContext( *this, *mpGroupShapePtr ); + case PPT_TOKEN( spPr ): + return new oox::drawingml::ShapePropertiesContext( *this, *mpGroupShapePtr ); +/* + case PPT_TOKEN( style ): + return new ShapeStyleContext( getParser() ); +*/ + case PPT_TOKEN( cxnSp ): // connector shape + { + auto pShape = std::make_shared<PPTShape>(meShapeLocation, "com.sun.star.drawing.ConnectorShape"); + return new oox::drawingml::ConnectorShapeContext(*this, mpGroupShapePtr, pShape, + pShape->getConnectorShapeProperties()); + } + case PPT_TOKEN( grpSp ): // group shape + return new PPTShapeGroupContext( *this, mpSlidePersistPtr, meShapeLocation, mpGroupShapePtr, std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.GroupShape" ) ); + case PPT_TOKEN( sp ): // Shape + { + auto pShape = std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.CustomShape" ); + bool bUseBgFill = rAttribs.getBool(XML_useBgFill, false); + if (bUseBgFill) + { + pShape->getFillProperties().moFillType = XML_noFill; + pShape->getFillProperties().moUseBgFill = true; + } + pShape->setModelId(rAttribs.getStringDefaulted( XML_modelId )); + return new PPTShapeContext( *this, mpSlidePersistPtr, mpGroupShapePtr, pShape ); + } + case PPT_TOKEN( pic ): // CT_Picture + return new PPTGraphicShapeContext( *this, mpSlidePersistPtr, mpGroupShapePtr, std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.GraphicObjectShape" ) ); + case PPT_TOKEN( graphicFrame ): // CT_GraphicalObjectFrame + { + pGraphicShape = std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.OLE2Shape" ); + return new oox::drawingml::GraphicalObjectFrameContext( *this, mpGroupShapePtr, pGraphicShape, true ); + } + } + + return this; +} + +void PPTShapeGroupContext::importExtDrawings( ) +{ + if( !pGraphicShape ) + return; + + for (auto const& extDrawing : pGraphicShape->getExtDrawings()) + { + OUString aFragmentPath = getFragmentPathFromRelId(extDrawing); + getFilter().importFragment( new ExtDrawingFragmentHandler( getFilter(), aFragmentPath, + mpSlidePersistPtr, + meShapeLocation, + mpGroupShapePtr, + pGraphicShape ) ); + pGraphicShape->keepDiagramDrawing(getFilter(), aFragmentPath); + + // Apply font color imported from color fragment + if( pGraphicShape->getFontRefColorForNodes().isUsed() ) + applyFontRefColor(mpGroupShapePtr, pGraphicShape->getFontRefColorForNodes()); + } + pGraphicShape = oox::drawingml::ShapePtr( nullptr ); +} + +void PPTShapeGroupContext::applyFontRefColor(const oox::drawingml::ShapePtr& pShape, const oox::drawingml::Color& rFontRefColor) +{ + pShape->getShapeStyleRefs()[XML_fontRef].maPhClr = rFontRefColor; + std::vector< oox::drawingml::ShapePtr >& vChildren = pShape->getChildren(); + for (auto const& child : vChildren) + { + applyFontRefColor(child, rFontRefColor); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/pptshapepropertiescontext.cxx b/oox/source/ppt/pptshapepropertiescontext.cxx new file mode 100644 index 0000000000..70ef2fcef8 --- /dev/null +++ b/oox/source/ppt/pptshapepropertiescontext.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/pptshapepropertiescontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#include <oox/ppt/pptshape.hxx> + +using namespace oox::core; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace oox::ppt { + +// CT_Shape +PPTShapePropertiesContext::PPTShapePropertiesContext( ContextHandler2Helper const & rParent, ::oox::drawingml::Shape& rShape ) +: ShapePropertiesContext( rParent, rShape ) +{ +} + +ContextHandlerRef PPTShapePropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + PPTShape* pPPTShape = dynamic_cast<PPTShape*>(&mrShape); + if (pPPTShape) + pPPTShape->setHasNoninheritedShapeProperties(); + + switch( aElementToken ) + { + case A_TOKEN( xfrm ): + mrShape.getShapeProperties().setProperty( PROP_IsPlaceholderDependent, false); + return ShapePropertiesContext::onCreateContext( aElementToken, rAttribs ); + + default: + return ShapePropertiesContext::onCreateContext( aElementToken, rAttribs ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/presPropsfragmenthandler.cxx b/oox/source/ppt/presPropsfragmenthandler.cxx new file mode 100644 index 0000000000..2cd9d82950 --- /dev/null +++ b/oox/source/ppt/presPropsfragmenthandler.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <com/sun/star/presentation/XCustomPresentationSupplier.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> + +#include <oox/core/xmlfilterbase.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/presPropsfragmenthandler.hxx> +#include <oox/token/namespaces.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace oox::ppt +{ +PresPropsFragmentHandler::PresPropsFragmentHandler(core::XmlFilterBase& rFilter, + const OUString& rFragmentPath) + : FragmentHandler2(rFilter, rFragmentPath) +{ +} + +PresPropsFragmentHandler::~PresPropsFragmentHandler() = default; + +void PresPropsFragmentHandler::finalizeImport() +{ + css::uno::Reference<css::presentation::XPresentationSupplier> xPresentationSupplier( + getFilter().getModel(), css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::beans::XPropertySet> xPresentationProps( + xPresentationSupplier->getPresentation(), css::uno::UNO_QUERY_THROW); + xPresentationProps->setPropertyValue("IsEndless", css::uno::Any(m_bLoop)); + xPresentationProps->setPropertyValue("IsAutomatic", css::uno::Any(!m_bTiming)); + + if (!m_sId.isEmpty()) + { + css::uno::Reference<css::presentation::XCustomPresentationSupplier> + XCustPresentationSupplier(getFilter().getModel(), css::uno::UNO_QUERY_THROW); + css::uno::Reference<css::container::XNameContainer> mxCustShows; + mxCustShows = XCustPresentationSupplier->getCustomPresentations(); + const css::uno::Sequence<OUString> aNameSeq(mxCustShows->getElementNames()); + xPresentationProps->setPropertyValue("CustomShow", + css::uno::Any(aNameSeq[m_sId.toInt32()])); + } + + if (!m_sSt.isEmpty()) + { + Reference<drawing::XDrawPagesSupplier> xDPS(getFilter().getModel(), uno::UNO_QUERY_THROW); + Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), uno::UNO_SET_THROW); + Reference<drawing::XDrawPage> xDrawPage; + xDrawPages->getByIndex(m_sSt.toInt32() - 1) >>= xDrawPage; + Reference<container::XNamed> xNamed(xDrawPage, uno::UNO_QUERY_THROW); + xPresentationProps->setPropertyValue("FirstPage", uno::Any(xNamed->getName())); + } +} + +core::ContextHandlerRef PresPropsFragmentHandler::onCreateContext(sal_Int32 aElementToken, + const AttributeList& rAttribs) +{ + switch (aElementToken) + { + case PPT_TOKEN(presentationPr): + return this; + case PPT_TOKEN(showPr): + m_bLoop = rAttribs.getBool(XML_loop, false); + m_bTiming = rAttribs.getBool(XML_useTimings, true); + return this; + case PPT_TOKEN(custShow): + m_sId = rAttribs.getStringDefaulted(XML_id); + return this; + case PPT_TOKEN(sldRg): + m_sSt = rAttribs.getStringDefaulted(XML_st); + return this; + } + return this; +} +} // namespace oox::ppt + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/oox/source/ppt/presentationfragmenthandler.cxx b/oox/source/ppt/presentationfragmenthandler.cxx new file mode 100644 index 0000000000..2e0f48bbae --- /dev/null +++ b/oox/source/ppt/presentationfragmenthandler.cxx @@ -0,0 +1,781 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/anytostring.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <o3tl/string_view.hxx> +#include <sal/log.hxx> +#include <tools/multisel.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <frozen/bits/defines.h> +#include <frozen/bits/elsa_std.h> +#include <frozen/unordered_map.h> + +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XMasterPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XMasterPageTarget.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/text/XTextField.hpp> +#include <com/sun/star/xml/dom/XDocument.hpp> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> +#include <com/sun/star/presentation/XPresentationPage.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/presentation/XCustomPresentationSupplier.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/container/XNameContainer.hpp> + +#include <oox/drawingml/theme.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <oox/drawingml/themefragmenthandler.hxx> +#include <drawingml/textliststylecontext.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/ole/olestorage.hxx> +#include <oox/ole/vbaproject.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/presentationfragmenthandler.hxx> +#include <oox/ppt/slidefragmenthandler.hxx> +#include <oox/ppt/layoutfragmenthandler.hxx> +#include <oox/ppt/pptimport.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +#include <com/sun/star/office/XAnnotation.hpp> +#include <com/sun/star/office/XAnnotationAccess.hpp> +#include <ooxresid.hxx> +#include <strings.hrc> + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt +{ + +namespace +{ +constexpr frozen::unordered_map<PredefinedClrSchemeId, sal_Int32, 12> constPredefinedClrTokens +{ + { dk1, XML_dk1 }, + { lt1, XML_lt1 }, + { dk2, XML_dk2 }, + { lt2, XML_lt2 }, + { accent1, XML_accent1 }, + { accent2, XML_accent2 }, + { accent3, XML_accent3 }, + { accent4, XML_accent4 }, + { accent5, XML_accent5 }, + { accent6, XML_accent6 }, + { hlink, XML_hlink }, + { folHlink, XML_folHlink } +}; + +sal_Int32 getPredefinedClrTokens(PredefinedClrSchemeId eID) +{ + auto iterator = constPredefinedClrTokens.find(eID); + if (iterator == constPredefinedClrTokens.end()) + return XML_TOKEN_INVALID; + return iterator->second; +} +} // end anonymous ns + +PresentationFragmentHandler::PresentationFragmentHandler(XmlFilterBase& rFilter, const OUString& rFragmentPath) + : FragmentHandler2( rFilter, rFragmentPath ) + , mpTextListStyle( std::make_shared<TextListStyle>() ) + , mbCommentAuthorsRead(false) +{ + TextParagraphPropertiesArray& rParagraphDefaultsVector( mpTextListStyle->getListStyle() ); + for (auto & elem : rParagraphDefaultsVector) + { + // ppt is having zero bottom margin per default, whereas OOo is 0,5cm, + // so this attribute needs to be set always + elem.getParaBottomMargin() = TextSpacing( 0 ); + } +} + +PresentationFragmentHandler::~PresentationFragmentHandler() noexcept +{ +} + +void PresentationFragmentHandler::importSlideNames(XmlFilterBase& rFilter, const std::vector<SlidePersistPtr>& rSlidePersist) +{ + sal_Int32 nMaxPages = rSlidePersist.size(); + for (sal_Int32 nPage = 0; nPage < nMaxPages; nPage++) + { + auto aShapeMap = rSlidePersist[nPage]->getShapeMap(); + auto aIter = std::find_if(aShapeMap.begin(), aShapeMap.end(), + [](const std::pair<OUString, ShapePtr>& element) { + auto pShapePtr = element.second; + return (pShapePtr + && (pShapePtr->getSubType() == XML_title + || pShapePtr->getSubType() == XML_ctrTitle)); + }); + if (aIter != aShapeMap.end()) + { + OUString aTitleText; + Reference<text::XTextRange> xText(aIter->second->getXShape(), UNO_QUERY_THROW); + aTitleText = xText->getString(); + // just a magic value but we don't want to drop out slide names which are too long + if (aTitleText.getLength() > 63) + aTitleText = aTitleText.copy(0, 63); + bool bUseTitleAsSlideName = !aTitleText.isEmpty(); + // check duplicated title name + if (bUseTitleAsSlideName) + { + sal_Int32 nCount = 1; + Reference<XDrawPagesSupplier> xDPS(rFilter.getModel(), UNO_QUERY_THROW); + Reference<XDrawPages> xDrawPages(xDPS->getDrawPages(), UNO_SET_THROW); + for (sal_Int32 i = 0; i < nPage; ++i) + { + Reference<XDrawPage> xDrawPage(xDrawPages->getByIndex(i), UNO_QUERY); + Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW); + std::u16string_view sRest; + if (o3tl::starts_with(xNamed->getName(), aTitleText, &sRest) + && (sRest.empty() + || (o3tl::starts_with(sRest, u" (") && o3tl::ends_with(sRest, u")") + && o3tl::toInt32(sRest.substr(2, sRest.size() - 3)) > 0))) + nCount++; + } + Reference<container::XNamed> xName(rSlidePersist[nPage]->getPage(), UNO_QUERY_THROW); + xName->setName( + aTitleText + + (nCount == 1 ? OUString("") : " (" + OUString::number(nCount) + ")")); + } + } + } +} + +void PresentationFragmentHandler::importCustomSlideShow(std::vector<CustomShow>& rCustomShowList) +{ + PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter()); + Reference<frame::XModel> xModel(rFilter.getModel()); + Reference<XDrawPagesSupplier> xDrawPagesSupplier(xModel, UNO_QUERY_THROW); + Reference<XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages(), UNO_SET_THROW); + + Reference<css::lang::XSingleServiceFactory> mxShowFactory; + Reference<css::container::XNameContainer> mxShows; + Reference<XCustomPresentationSupplier> xShowsSupplier(xModel, UNO_QUERY); + if (xShowsSupplier.is()) + { + mxShows = xShowsSupplier->getCustomPresentations(); + mxShowFactory.set(mxShows, UNO_QUERY); + } + + for (size_t i = 0; i < rCustomShowList.size(); ++i) + { + Reference<com::sun::star::container::XIndexContainer> xShow(mxShowFactory->createInstance(), + UNO_QUERY); + if (xShow.is()) + { + static constexpr OUString sSlide = u"slides/slide"_ustr; + for (size_t j = 0; j < rCustomShowList[i].maSldLst.size(); ++j) + { + OUString sCustomSlide = rCustomShowList[i].maSldLst[j]; + sal_Int32 nPageNumber = 0; + if (sCustomSlide.match(sSlide)) + nPageNumber = o3tl::toInt32(sCustomSlide.subView(sSlide.getLength())); + + Reference<XDrawPage> xPage; + xDrawPages->getByIndex(nPageNumber - 1) >>= xPage; + if (xPage.is()) + xShow->insertByIndex(xShow->getCount(), Any(xPage)); + } + + Any aAny; + aAny <<= xShow; + mxShows->insertByName(rCustomShowList[i].maCustomShowName, aAny); + } + } +} + +void PresentationFragmentHandler::importMasterSlide(const Reference<frame::XModel>& xModel, + PowerPointImport& rFilter, + const OUString& rMasterFragmentPath) +{ + OUString aLayoutFragmentPath; + SlidePersistPtr pMasterPersistPtr; + Reference< drawing::XDrawPage > xMasterPage; + Reference< drawing::XMasterPagesSupplier > xMPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xMasterPages( xMPS->getMasterPages(), uno::UNO_SET_THROW ); + RelationsRef xMasterRelations = rFilter.importRelations( rMasterFragmentPath ); + + for (const auto& rEntry : *xMasterRelations) + { + if (!rEntry.second.maType.endsWith("relationships/slideLayout")) + continue; + + aLayoutFragmentPath = xMasterRelations->getFragmentPathFromRelation(rEntry.second); + + sal_Int32 nIndex; + if( rFilter.getMasterPages().empty() ) + { + nIndex = 0; + xMasterPages->getByIndex( nIndex ) >>= xMasterPage; + } + else + { + nIndex = xMasterPages->getCount(); + xMasterPage = xMasterPages->insertNewByIndex( nIndex ); + } + + pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, false, xMasterPage, + std::make_shared<PPTShape>( Master, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + pMasterPersistPtr->setLayoutPath( aLayoutFragmentPath ); + rFilter.getMasterPages().push_back( pMasterPersistPtr ); + rFilter.setActualSlidePersist( pMasterPersistPtr ); + FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, rMasterFragmentPath, pMasterPersistPtr, Master ) ); + + // set the correct theme + OUString aThemeFragmentPath = xMasterFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" ); + if( !aThemeFragmentPath.isEmpty() ) + { + std::map< OUString, oox::drawingml::ThemePtr >& rThemes( rFilter.getThemes() ); + std::map< OUString, oox::drawingml::ThemePtr >::iterator aIter2( rThemes.find( aThemeFragmentPath ) ); + if( aIter2 == rThemes.end() ) + { + oox::drawingml::ThemePtr pThemePtr = std::make_shared<oox::drawingml::Theme>(); + pMasterPersistPtr->setTheme( pThemePtr ); + Reference<xml::dom::XDocument> xDoc= + rFilter.importFragment(aThemeFragmentPath); + + auto pTheme = std::make_shared<model::Theme>(); + pThemePtr->setTheme(pTheme); + + rFilter.importFragment( + new ThemeFragmentHandler(rFilter, aThemeFragmentPath, *pThemePtr, *pTheme), + Reference<xml::sax::XFastSAXSerializable>( + xDoc, + UNO_QUERY_THROW)); + rThemes[ aThemeFragmentPath ] = pThemePtr; + pThemePtr->setFragment(xDoc); + saveThemeToGrabBag(pThemePtr, nIndex + 1); + } + else + { + pMasterPersistPtr->setTheme( (*aIter2).second ); + } + } + importSlide( xMasterFragmentHandler, pMasterPersistPtr ); + rFilter.importFragment( new LayoutFragmentHandler( rFilter, aLayoutFragmentPath, pMasterPersistPtr ) ); + pMasterPersistPtr->createBackground( rFilter ); + pMasterPersistPtr->createXShapes( rFilter ); + + uno::Reference< beans::XPropertySet > xSet(pMasterPersistPtr->getPage(), uno::UNO_QUERY_THROW); + xSet->setPropertyValue("SlideLayout", Any(pMasterPersistPtr->getLayoutFromValueToken())); + + oox::drawingml::ThemePtr pTheme = pMasterPersistPtr->getTheme(); + if (pTheme) + { + pTheme->addTheme(pMasterPersistPtr->getPage()); + } + } +} + +void PresentationFragmentHandler::saveThemeToGrabBag(const oox::drawingml::ThemePtr& pThemePtr, + sal_Int32 nThemeIdx) +{ + if (!pThemePtr) + return; + + try + { + uno::Reference<beans::XPropertySet> xDocProps(getFilter().getModel(), uno::UNO_QUERY); + if (xDocProps.is()) + { + uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo(); + + static constexpr OUString aGrabBagPropName = u"InteropGrabBag"_ustr; + if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName)) + { + // get existing grab bag + comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName)); + + comphelper::SequenceAsHashMap aThemesHashMap; + + // create current theme + uno::Sequence<beans::PropertyValue> aCurrentTheme(PredefinedClrSchemeId::Count); + auto pCurrentTheme = aCurrentTheme.getArray(); + + ClrScheme rClrScheme = pThemePtr->getClrScheme(); + for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++) + { + auto eID = static_cast<PredefinedClrSchemeId>(nId); + sal_uInt32 nToken = getPredefinedClrTokens(eID); + OUString sName(getPredefinedClrNames(eID)); + ::Color nColor; + + rClrScheme.getColor(nToken, nColor); + const uno::Any& rColor = uno::Any(nColor); + + pCurrentTheme[nId].Name = sName; + pCurrentTheme[nId].Value = rColor; + } + + + uno::Sequence<beans::PropertyValue> aTheme{ + // add new theme to the sequence + // Export code uses the master slide's index to find the right theme + // so use the same index in the grabbag. + comphelper::makePropertyValue( + "ppt/theme/theme" + OUString::number(nThemeIdx) + ".xml", aCurrentTheme), + // store DOM fragment for SmartArt re-generation + comphelper::makePropertyValue("OOXTheme", pThemePtr->getFragment()) + }; + + aThemesHashMap << aTheme; + + // put the new items + aGrabBag.update(aThemesHashMap); + + // put it back to the document + xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList())); + } + } + } + catch (const uno::Exception&) + { + SAL_WARN("oox", "oox::ppt::PresentationFragmentHandler::saveThemeToGrabBag, Failed to save grab bag"); + } +} + +void PresentationFragmentHandler::importMasterSlides() +{ + OUString aMasterFragmentPath; + PowerPointImport& rFilter = dynamic_cast<PowerPointImport&>(getFilter()); + Reference<frame::XModel> xModel(rFilter.getModel()); + + for (size_t nMaster = 0; nMaster < maSlideMasterVector.size(); ++nMaster) + { + aMasterFragmentPath = getFragmentPathFromRelId(maSlideMasterVector[nMaster]); + importMasterSlide(xModel, rFilter, aMasterFragmentPath); + } +} + +void PresentationFragmentHandler::importSlide(sal_uInt32 nSlide, bool bFirstPage, bool bImportNotesPage) +{ + PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); + + Reference< frame::XModel > xModel( rFilter.getModel() ); + Reference< drawing::XDrawPage > xSlide; + + // importing slide pages and its corresponding notes page + Reference< drawing::XDrawPagesSupplier > xDPS( xModel, uno::UNO_QUERY_THROW ); + Reference< drawing::XDrawPages > xDrawPages( xDPS->getDrawPages(), uno::UNO_SET_THROW ); + + try { + + if( bFirstPage ) + { + xDrawPages->getByIndex( 0 ) >>= xSlide; + importMasterSlides(); + } + else + xSlide = xDrawPages->insertNewByIndex( xDrawPages->getCount() ); + + OUString aSlideFragmentPath = getFragmentPathFromRelId( maSlidesVector[ nSlide ] ); + if( !aSlideFragmentPath.isEmpty() ) + { + SlidePersistPtr pMasterPersistPtr; + SlidePersistPtr pSlidePersistPtr = std::make_shared<SlidePersist>( rFilter, false, false, xSlide, + std::make_shared<PPTShape>( Slide, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + + FragmentHandlerRef xSlideFragmentHandler( new SlideFragmentHandler( rFilter, aSlideFragmentPath, pSlidePersistPtr, Slide ) ); + + // importing the corresponding masterpage/layout + OUString aLayoutFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideLayout" ); + OUString aCommentFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"comments" ); + if ( !aLayoutFragmentPath.isEmpty() ) + { + // importing layout + RelationsRef xLayoutRelations = rFilter.importRelations( aLayoutFragmentPath ); + OUString aMasterFragmentPath = xLayoutRelations->getFragmentPathFromFirstTypeFromOfficeDoc( u"slideMaster" ); + if( !aMasterFragmentPath.isEmpty() ) + { + // check if the corresponding masterpage+layout has already been imported + std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() ); + for (auto const& masterPage : rMasterPages) + { + if ( ( masterPage->getPath() == aMasterFragmentPath ) && ( masterPage->getLayoutPath() == aLayoutFragmentPath ) ) + { + pMasterPersistPtr = masterPage; + break; + } + } + } + } + + // importing slide page + if (pMasterPersistPtr) { + pSlidePersistPtr->setMasterPersist( pMasterPersistPtr ); + pSlidePersistPtr->setTheme( pMasterPersistPtr->getTheme() ); + Reference< drawing::XMasterPageTarget > xMasterPageTarget( pSlidePersistPtr->getPage(), UNO_QUERY ); + if( xMasterPageTarget.is() ) + xMasterPageTarget->setMasterPage( pMasterPersistPtr->getPage() ); + } + rFilter.getDrawPages().push_back( pSlidePersistPtr ); + rFilter.setActualSlidePersist( pSlidePersistPtr ); + importSlide( xSlideFragmentHandler, pSlidePersistPtr ); + pSlidePersistPtr->createBackground( rFilter ); + pSlidePersistPtr->createXShapes( rFilter ); + + if(bImportNotesPage) { + + // now importing the notes page + OUString aNotesFragmentPath = xSlideFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"notesSlide" ); + if( !aNotesFragmentPath.isEmpty() ) + { + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + if ( xPresentationPage.is() ) + { + Reference< XDrawPage > xNotesPage( xPresentationPage->getNotesPage() ); + if ( xNotesPage.is() ) + { + SlidePersistPtr pNotesPersistPtr = std::make_shared<SlidePersist>( rFilter, false, true, xNotesPage, + std::make_shared<PPTShape>( Slide, "com.sun.star.drawing.GroupShape" ), mpTextListStyle ); + FragmentHandlerRef xNotesFragmentHandler( new SlideFragmentHandler( getFilter(), aNotesFragmentPath, pNotesPersistPtr, Slide ) ); + rFilter.getNotesPages().push_back( pNotesPersistPtr ); + rFilter.setActualSlidePersist( pNotesPersistPtr ); + importSlide( xNotesFragmentHandler, pNotesPersistPtr ); + pNotesPersistPtr->createBackground( rFilter ); + pNotesPersistPtr->createXShapes( rFilter ); + } + } + } + } + + if( !mbCommentAuthorsRead && !aCommentFragmentPath.isEmpty() ) + { + // Comments are present and commentAuthors.xml has still not been read + mbCommentAuthorsRead = true; + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + Reference< XDrawPage > xCommentAuthorsPage( xPresentationPage->getNotesPage() ); + SlidePersistPtr pCommentAuthorsPersistPtr = + std::make_shared<SlidePersist>( rFilter, false, true, xCommentAuthorsPage, + std::make_shared<PPTShape>( + Slide, "com.sun.star.drawing.GroupShape" ), + mpTextListStyle ); + FragmentHandlerRef xCommentAuthorsFragmentHandler( + new SlideFragmentHandler( getFilter(), + "ppt/commentAuthors.xml", + pCommentAuthorsPersistPtr, + Slide ) ); + + getFilter().importFragment( xCommentAuthorsFragmentHandler ); + maAuthorList.setValues( pCommentAuthorsPersistPtr->getCommentAuthors() ); + } + if( !aCommentFragmentPath.isEmpty() ) + { + Reference< XPresentationPage > xPresentationPage( xSlide, UNO_QUERY ); + Reference< XDrawPage > xCommentsPage( xPresentationPage->getNotesPage() ); + SlidePersistPtr pCommentsPersistPtr = + std::make_shared<SlidePersist>( + rFilter, false, true, xCommentsPage, + std::make_shared<PPTShape>( + Slide, "com.sun.star.drawing.GroupShape" ), + mpTextListStyle ); + + FragmentHandlerRef xCommentsFragmentHandler( + new SlideFragmentHandler( + getFilter(), + aCommentFragmentPath, + pCommentsPersistPtr, + Slide ) ); + pCommentsPersistPtr->getCommentsList().cmLst.clear(); + getFilter().importFragment( xCommentsFragmentHandler ); + + if (!pCommentsPersistPtr->getCommentsList().cmLst.empty()) + { + //set comment chars for last comment on slide + SlideFragmentHandler* comment_handler = + dynamic_cast<SlideFragmentHandler*>(xCommentsFragmentHandler.get()); + assert(comment_handler); + // some comments have no text -> set empty string as text to avoid + // crash (back() on empty vector is undefined) and losing other + // comment data that might be there (author, position, timestamp etc.) + pCommentsPersistPtr->getCommentsList().cmLst.back().setText( + comment_handler->getCharVector().empty() ? "" : + comment_handler->getCharVector().back() ); + } + pCommentsPersistPtr->getCommentAuthors().setValues(maAuthorList); + + //insert all comments from commentsList + for(int i=0; i<pCommentsPersistPtr->getCommentsList().getSize(); i++) + { + try { + Comment aComment = pCommentsPersistPtr->getCommentsList().getCommentAtIndex(i); + uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xSlide, UNO_QUERY_THROW ); + uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() ); + int nPosX = aComment.getIntX(); + int nPosY = aComment.getIntY(); + xAnnotation->setPosition( + geometry::RealPoint2D( + ::oox::drawingml::convertEmuToHmm( nPosX ) * 15.87, + ::oox::drawingml::convertEmuToHmm( nPosY ) * 15.87 ) ); + xAnnotation->setAuthor( aComment.getAuthor(maAuthorList) ); + xAnnotation->setDateTime( aComment.getDateTime() ); + uno::Reference< text::XText > xText( xAnnotation->getTextRange() ); + xText->setString( aComment.get_text()); + } catch( css::lang::IllegalArgumentException& ) {} + } + } + } + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::EndDocument()" ); + } +} + +void PresentationFragmentHandler::finalizeImport() +{ + PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); + + sal_Int32 nPageCount = maSlidesVector.size(); + + // we will take the FilterData property "PageRange" if available, otherwise full range is used + comphelper::SequenceAsHashMap& rFilterData = rFilter.getFilterData(); + + // writing back the original PageCount of this document, it can be accessed from the XModel + // via getArgs after the import. + rFilterData["OriginalPageCount"] <<= nPageCount; + bool bImportNotesPages = rFilterData.getUnpackedValueOrDefault("ImportNotesPages", true); + OUString aPageRange = rFilterData.getUnpackedValueOrDefault("PageRange", OUString()); + + if( !aPageRange.getLength() ) + { + aPageRange = "1-" + OUString::number( nPageCount ); + } + + StringRangeEnumerator aRangeEnumerator( aPageRange, 0, nPageCount - 1 ); + if (aRangeEnumerator.size()) + { + // todo: localized progress bar text + const Reference< task::XStatusIndicator >& rxStatusIndicator( getFilter().getStatusIndicator() ); + if ( rxStatusIndicator.is() ) + rxStatusIndicator->start( OUString(), 10000 ); + + try + { + int nPagesImported = 0; + for (sal_Int32 elem : aRangeEnumerator) + { + if ( rxStatusIndicator.is() ) + rxStatusIndicator->setValue((nPagesImported * 10000) / aRangeEnumerator.size()); + + importSlide(elem, !nPagesImported, bImportNotesPages); + nPagesImported++; + } + importSlideNames( rFilter, rFilter.getDrawPages()); + if (!maCustomShowList.empty()) + importCustomSlideShow(maCustomShowList); + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::PresentationFragmentHandler::finalizeImport()" ); + } + // todo error handling; + if ( rxStatusIndicator.is() ) + rxStatusIndicator->end(); + } + + // open the VBA project storage + OUString aVbaFragmentPath = getFragmentPathFromFirstType(CREATE_MSOFFICE_RELATION_TYPE("vbaProject")); + if (!aVbaFragmentPath.isEmpty()) + { + uno::Reference<io::XInputStream> xInStrm = getFilter().openInputStream(aVbaFragmentPath); + if (xInStrm.is()) + { + StorageRef xPrjStrg = std::make_shared<oox::ole::OleStorage>(getFilter().getComponentContext(), xInStrm, false); + getFilter().getVbaProject().importVbaProject(*xPrjStrg); + } + } +} + +// CT_Presentation +::oox::core::ContextHandlerRef PresentationFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( presentation ): + case PPT_TOKEN( sldMasterIdLst ): + case PPT_TOKEN( notesMasterIdLst ): + case PPT_TOKEN( sldIdLst ): + return this; + case PPT_TOKEN( sldMasterId ): + maSlideMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); + return this; + case PPT_TOKEN( sldId ): + maSlidesVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); + return this; + case PPT_TOKEN( notesMasterId ): + maNotesMasterVector.push_back( rAttribs.getStringDefaulted( R_TOKEN( id )) ); + return this; + case PPT_TOKEN( sldSz ): + maSlideSize = GetSize2D( rAttribs.getFastAttributeList() ); + return this; + case PPT_TOKEN( notesSz ): + maNotesSize = GetSize2D( rAttribs.getFastAttributeList() ); + return this; + case PPT_TOKEN( custShowLst ): + return new CustomShowListContext( *this, maCustomShowList ); + case PPT_TOKEN( defaultTextStyle ): + return new TextListStyleContext( *this, *mpTextListStyle ); + case PPT_TOKEN( modifyVerifier ): + OUString sAlgorithmClass = rAttribs.getStringDefaulted(XML_cryptAlgorithmClass); + OUString sAlgorithmType = rAttribs.getStringDefaulted(XML_cryptAlgorithmType); + sal_Int32 nAlgorithmSid = rAttribs.getInteger(XML_cryptAlgorithmSid, 0); + sal_Int32 nSpinCount = rAttribs.getInteger(XML_spinCount, 0); + OUString sSalt = rAttribs.getStringDefaulted(XML_saltData); + OUString sHash = rAttribs.getStringDefaulted(XML_hashData); + if (sAlgorithmClass == "hash" && sAlgorithmType == "typeAny" && nAlgorithmSid != 0 + && !sSalt.isEmpty() && !sHash.isEmpty()) + { + OUString sAlgorithmName; + switch (nAlgorithmSid) + { + case 1: + sAlgorithmName = "MD2"; + break; + case 2: + sAlgorithmName = "MD4"; + break; + case 3: + sAlgorithmName = "MD5"; + break; + case 4: + sAlgorithmName = "SHA-1"; + break; + case 5: + sAlgorithmName = "MAC"; + break; + case 6: + sAlgorithmName = "RIPEMD"; + break; + case 7: + sAlgorithmName = "RIPEMD-160"; + break; + case 9: + sAlgorithmName = "HMAC"; + break; + case 12: + sAlgorithmName = "SHA-256"; + break; + case 13: + sAlgorithmName = "SHA-384"; + break; + case 14: + sAlgorithmName = "SHA-512"; + break; + default:; // 8, 10, 11, any other value: Undefined. + } + + if (!sAlgorithmName.isEmpty()) + { + uno::Sequence<beans::PropertyValue> aResult{ + comphelper::makePropertyValue("algorithm-name", sAlgorithmName), + comphelper::makePropertyValue("salt", sSalt), + comphelper::makePropertyValue("iteration-count", nSpinCount), + comphelper::makePropertyValue("hash", sHash) + }; + try + { + uno::Reference<beans::XPropertySet> xDocSettings( + getFilter().getModelFactory()->createInstance( + "com.sun.star.document.Settings"), + uno::UNO_QUERY); + xDocSettings->setPropertyValue("ModifyPasswordInfo", uno::Any(aResult)); + } + catch (const uno::Exception&) + { + } + } + } + return this; + } + return this; +} + +void PresentationFragmentHandler::importSlide( const FragmentHandlerRef& rxSlideFragmentHandler, + const SlidePersistPtr& rSlidePersistPtr ) +{ + Reference< drawing::XDrawPage > xSlide( rSlidePersistPtr->getPage() ); + SlidePersistPtr pMasterPersistPtr( rSlidePersistPtr->getMasterPersist() ); + if ( pMasterPersistPtr ) + { + // Setting "Layout" property adds extra title and outliner preset shapes to the master slide + Reference< drawing::XDrawPage > xMasterSlide(pMasterPersistPtr->getPage()); + const int nCount = xMasterSlide->getCount(); + + uno::Reference< beans::XPropertySet > xSet( xSlide, uno::UNO_QUERY_THROW ); + xSet->setPropertyValue( "Layout", Any( pMasterPersistPtr->getLayoutFromValueToken() ) ); + + while( nCount < xMasterSlide->getCount()) + { + Reference< drawing::XShape > xShape; + xMasterSlide->getByIndex(xMasterSlide->getCount()-1) >>= xShape; + xMasterSlide->remove(xShape); + } + } + while( xSlide->getCount() ) + { + Reference< drawing::XShape > xShape; + xSlide->getByIndex(0) >>= xShape; + xSlide->remove( xShape ); + } + + Reference< XPropertySet > xPropertySet( xSlide, UNO_QUERY ); + if ( xPropertySet.is() ) + { + awt::Size& rPageSize( rSlidePersistPtr->isNotesPage() ? maNotesSize : maSlideSize ); + xPropertySet->setPropertyValue( "Width", Any( rPageSize.Width ) ); + xPropertySet->setPropertyValue( "Height", Any( rPageSize.Height ) ); + + oox::ppt::HeaderFooter aHeaderFooter( rSlidePersistPtr->getHeaderFooter() ); + if ( !rSlidePersistPtr->isMasterPage() ) + aHeaderFooter.mbSlideNumber = aHeaderFooter.mbHeader = aHeaderFooter.mbFooter = aHeaderFooter.mbDateTime = false; + try + { + if ( rSlidePersistPtr->isNotesPage() ) + xPropertySet->setPropertyValue( "IsHeaderVisible", Any( aHeaderFooter.mbHeader ) ); + xPropertySet->setPropertyValue( "IsFooterVisible", Any( aHeaderFooter.mbFooter ) ); + xPropertySet->setPropertyValue( "IsDateTimeVisible", Any( aHeaderFooter.mbDateTime ) ); + xPropertySet->setPropertyValue( "IsPageNumberVisible", Any( aHeaderFooter.mbSlideNumber ) ); + } + catch( uno::Exception& ) + { + } + } + rSlidePersistPtr->setPath( rxSlideFragmentHandler->getFragmentPath() ); + getFilter().importFragment( rxSlideFragmentHandler ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidefragmenthandler.cxx b/oox/source/ppt/slidefragmenthandler.cxx new file mode 100644 index 0000000000..87fc980b07 --- /dev/null +++ b/oox/source/ppt/slidefragmenthandler.cxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <comphelper/diagnose_ex.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/helper/propertyset.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include "headerfootercontext.hxx" +#include <oox/ppt/backgroundproperties.hxx> +#include <oox/ppt/slidefragmenthandler.hxx> +#include <oox/ppt/slidetimingcontext.hxx> +#include <oox/ppt/slidetransitioncontext.hxx> +#include <oox/ppt/slidemastertextstylescontext.hxx> +#include <oox/ppt/pptshapegroupcontext.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/vml/vmldrawing.hxx> +#include <oox/vml/vmldrawingfragment.hxx> +#include <drawingml/clrschemecontext.hxx> +#include <drawingml/fillproperties.hxx> +#include <oox/ppt/pptimport.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::container; + +namespace oox::ppt { + +SlideFragmentHandler::SlideFragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, const SlidePersistPtr& pPersistPtr, const ShapeLocation eShapeLocation ) +: FragmentHandler2( rFilter, rFragmentPath ) +, mpSlidePersistPtr( pPersistPtr ) +, meShapeLocation( eShapeLocation ) +{ + OUString aVMLDrawingFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"vmlDrawing" ); + if( !aVMLDrawingFragmentPath.isEmpty() ) + getFilter().importFragment( new oox::vml::DrawingFragment( + getFilter(), aVMLDrawingFragmentPath, *pPersistPtr->getDrawing() ) ); +} + +SlideFragmentHandler::~SlideFragmentHandler() +{ + // convert and insert all VML shapes (mostly form controls) + mpSlidePersistPtr->getDrawing()->convertAndInsert(); +} + +::oox::core::ContextHandlerRef SlideFragmentHandler::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( sldMaster ): // CT_SlideMaster + case PPT_TOKEN( handoutMaster ): // CT_HandoutMaster + case PPT_TOKEN( sld ): // CT_CommonSlideData + { + Reference< XDrawPage > xSlide( mpSlidePersistPtr->getPage() ); + Reference< css::beans::XPropertySet > xSet(xSlide, UNO_QUERY); + PropertyMap aPropMap; + PropertySet aSlideProp( xSlide ); + + std::optional<bool> aShowMasterShapes = rAttribs.getBool(XML_showMasterSp); + if (aShowMasterShapes.has_value() && !aShowMasterShapes.value()) + xSet->setPropertyValue("IsBackgroundObjectsVisible", Any(false)); + + aPropMap.setProperty( PROP_Visible, rAttribs.getBool( XML_show, true )); + aSlideProp.setProperties( aPropMap ); + + return this; + } + case PPT_TOKEN( notes ): // CT_NotesSlide + { + // Import notesMaster + PowerPointImport& rFilter = dynamic_cast< PowerPointImport& >( getFilter() ); + OUString aNotesFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( u"notesMaster" ); + + std::vector< SlidePersistPtr >& rMasterPages( rFilter.getMasterPages() ); + bool bNotesFragmentPathFound = false; + for (auto const& masterPage : rMasterPages) + { + if( masterPage->getPath() == aNotesFragmentPath ) + { + if( !mpSlidePersistPtr->getMasterPersist() ) + mpSlidePersistPtr->setMasterPersist(masterPage); + bNotesFragmentPathFound=true; + break; + } + } + if( !bNotesFragmentPathFound && !mpSlidePersistPtr->getMasterPersist() ) + { + SlidePersistPtr pMasterPersistPtr = std::make_shared<SlidePersist>( rFilter, true, true, mpSlidePersistPtr->getPage(), + std::make_shared<PPTShape>( Master, "com.sun.star.drawing.GroupShape" ), mpSlidePersistPtr->getNotesTextStyle() ); + pMasterPersistPtr->setPath( aNotesFragmentPath ); + rFilter.getMasterPages().push_back( pMasterPersistPtr ); + FragmentHandlerRef xMasterFragmentHandler( new SlideFragmentHandler( rFilter, aNotesFragmentPath, pMasterPersistPtr, Master ) ); + rFilter.importFragment( xMasterFragmentHandler ); + mpSlidePersistPtr->setMasterPersist( pMasterPersistPtr ); + } + return this; + } + case PPT_TOKEN( notesMaster ): // CT_NotesMaster + return this; + case PPT_TOKEN( cSld ): // CT_CommonSlideData + maSlideName = rAttribs.getStringDefaulted(XML_name); + return this; + + case PPT_TOKEN( spTree ): // CT_GroupShape + { + return new PPTShapeGroupContext( + *this, mpSlidePersistPtr, meShapeLocation, mpSlidePersistPtr->getShapes(), + std::make_shared<PPTShape>( meShapeLocation, "com.sun.star.drawing.GroupShape" ) ); + } + break; + + case PPT_TOKEN( controls ): + return this; + case PPT_TOKEN( control ): + { + ::oox::vml::ControlInfo aInfo; + aInfo.setShapeId( rAttribs.getInteger( XML_spid, 0 ) ); + aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getStringDefaulted( R_TOKEN( id )) ); + aInfo.maName = rAttribs.getXString( XML_name, OUString() ); + mpSlidePersistPtr->getDrawing()->registerControl( aInfo ); + } + return this; + + case PPT_TOKEN( timing ): // CT_SlideTiming + return new SlideTimingContext( *this, mpSlidePersistPtr->getTimeNodeList() ); + case PPT_TOKEN( transition ): // CT_SlideTransition + return new SlideTransitionContext( *this, rAttribs, maSlideProperties ); + case PPT_TOKEN( hf ): + return new HeaderFooterContext( *this, rAttribs, mpSlidePersistPtr->getHeaderFooter() ); + + // BackgroundGroup + case PPT_TOKEN( bg ): + return this; + case PPT_TOKEN( bgPr ): // CT_BackgroundProperties + { + FillPropertiesPtr pFillPropertiesPtr =std::make_shared<FillProperties>(); + mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr ); + return new BackgroundPropertiesContext( *this, *pFillPropertiesPtr ); + } + break; + + case PPT_TOKEN( bgRef ): // a:CT_StyleMatrixReference + { + const FillProperties *pFillProperties = nullptr; + if( mpSlidePersistPtr->getTheme() ) + pFillProperties = mpSlidePersistPtr->getTheme()->getFillStyle( rAttribs.getInteger( XML_idx, -1 ) ); + FillPropertiesPtr pFillPropertiesPtr = + pFillProperties + ? std::make_shared<FillProperties>( *pFillProperties ) + : std::make_shared<FillProperties>(); + mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr ); + ContextHandlerRef ret = new ColorContext( *this, mpSlidePersistPtr->getBackgroundColor() ); + return ret; + } + break; + + case A_TOKEN( overrideClrMapping ): + case PPT_TOKEN( clrMap ): // CT_ColorMapping + { + oox::drawingml::ClrMapPtr pClrMapPtr = + ( aElementToken == PPT_TOKEN( clrMap ) || !mpSlidePersistPtr || !mpSlidePersistPtr->getClrMap() ) + ? std::make_shared<oox::drawingml::ClrMap>() + : std::make_shared<oox::drawingml::ClrMap>( *mpSlidePersistPtr->getClrMap() ); + ContextHandlerRef ret = new oox::drawingml::clrMapContext( *this, rAttribs, *pClrMapPtr ); + mpSlidePersistPtr->setClrMap( pClrMapPtr ); + return ret; + } + break; + case PPT_TOKEN( clrMapOvr ): // CT_ColorMappingOverride + case PPT_TOKEN( sldLayoutIdLst ): // CT_SlideLayoutIdList + return this; + case PPT_TOKEN( txStyles ): // CT_SlideMasterTextStyles + return new SlideMasterTextStylesContext( *this, mpSlidePersistPtr ); + case PPT_TOKEN( custDataLst ): // CT_CustomerDataList + case PPT_TOKEN( tagLst ): // CT_TagList + return this; + + //for Comments + case PPT_TOKEN( cmLst ): + break; + case PPT_TOKEN( cm ): + if (!mpSlidePersistPtr->getCommentsList().cmLst.empty() && !getCharVector().empty()) + { + // set comment text for earlier comment + mpSlidePersistPtr->getCommentsList().cmLst.back().setText( getCharVector().back() ); + } + // insert a new comment in vector commentsList + mpSlidePersistPtr->getCommentsList().cmLst.emplace_back(); + mpSlidePersistPtr->getCommentsList().cmLst.back().setAuthorId(rAttribs.getStringDefaulted(XML_authorId)); + mpSlidePersistPtr->getCommentsList().cmLst.back().setdt(rAttribs.getStringDefaulted(XML_dt)); + mpSlidePersistPtr->getCommentsList().cmLst.back().setidx(rAttribs.getStringDefaulted(XML_idx)); + break; + + case PPT_TOKEN( pos ): + mpSlidePersistPtr->getCommentsList().cmLst.back().setPoint( + rAttribs.getStringDefaulted(XML_x), + rAttribs.getStringDefaulted(XML_y)); + break; + + case PPT_TOKEN( cmAuthor ): + CommentAuthor _author; + _author.clrIdx = rAttribs.getStringDefaulted(XML_clrIdx); + _author.id = rAttribs.getStringDefaulted(XML_id); + _author.initials = rAttribs.getStringDefaulted(XML_initials); + _author.lastIdx = rAttribs.getStringDefaulted(XML_lastIdx); + _author.name = rAttribs.getStringDefaulted(XML_name); + mpSlidePersistPtr->getCommentAuthors().addAuthor(_author); + break; + } + + return this; +} +void SlideFragmentHandler::onCharacters( const OUString& rChars) +{ + maCharVector.push_back(rChars); +} +void SlideFragmentHandler::finalizeImport() +{ + try + { + Reference< XDrawPage > xSlide( mpSlidePersistPtr->getPage() ); + PropertySet aSlideProp( xSlide ); + aSlideProp.setProperties( maSlideProperties ); + if ( !maSlideName.isEmpty() ) + { + Reference< XNamed > xNamed( xSlide, UNO_QUERY ); + if( xNamed.is() ) + xNamed->setName( maSlideName ); + } + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "oox", "oox::ppt::SlideFragmentHandler::EndElement()" ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidemastertextstylescontext.cxx b/oox/source/ppt/slidemastertextstylescontext.cxx new file mode 100644 index 0000000000..a069bbe28c --- /dev/null +++ b/oox/source/ppt/slidemastertextstylescontext.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <drawingml/textliststyle.hxx> +#include <drawingml/textliststylecontext.hxx> +#include <oox/ppt/slidemastertextstylescontext.hxx> +#include <oox/token/namespaces.hxx> +#include <utility> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +SlideMasterTextStylesContext::SlideMasterTextStylesContext( FragmentHandler2 const & rParent, SlidePersistPtr pSlidePersistPtr ) +: FragmentHandler2( rParent ) +, mpSlidePersistPtr(std::move( pSlidePersistPtr )) +{ +} + +SlideMasterTextStylesContext::~SlideMasterTextStylesContext() +{ +} + +::oox::core::ContextHandlerRef SlideMasterTextStylesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) +{ + oox::drawingml::TextListStylePtr aTextListStylePtr; + switch( aElementToken ) + { + case PPT_TOKEN( titleStyle ): + { + aTextListStylePtr = mpSlidePersistPtr->getTitleTextStyle(); + break; + } + case PPT_TOKEN( bodyStyle ): + { + aTextListStylePtr = mpSlidePersistPtr->getBodyTextStyle(); + break; + } + case PPT_TOKEN( notesStyle ): + { + aTextListStylePtr = mpSlidePersistPtr->getNotesTextStyle(); + break; + } + case PPT_TOKEN( otherStyle ): + { + aTextListStylePtr = mpSlidePersistPtr->getOtherTextStyle(); + break; + } + } + if ( aTextListStylePtr ) // sj: the master list style is the last instance of from where properties + { // are obtained. i got some documents without having the textsize set at + for ( int i = 0; i < 9; i++ ) // any point, the master reference application is using 18pt then + aTextListStylePtr->getListStyle()[ i ].getTextCharacterProperties().moHeight = 1800; + return new oox::drawingml::TextListStyleContext( *this, *aTextListStylePtr ); + } + + return this; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx new file mode 100644 index 0000000000..a4225f95cd --- /dev/null +++ b/oox/source/ppt/slidepersist.cxx @@ -0,0 +1,702 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <oox/ppt/timenode.hxx> +#include <oox/ppt/pptshape.hxx> +#include <oox/ppt/slidepersist.hxx> +#include <drawingml/fillproperties.hxx> +#include <oox/drawingml/shapepropertymap.hxx> +#include <oox/helper/propertymap.hxx> +#include <oox/helper/propertyset.hxx> +#include <oox/vml/vmldrawing.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <drawingml/textliststyle.hxx> +#include <drawingml/textparagraphproperties.hxx> + +#include <osl/diagnose.h> + +#include <com/sun/star/style/XStyle.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/animations/XAnimationNodeSupplier.hpp> +#include <com/sun/star/drawing/XGluePointsSupplier.hpp> +#include <com/sun/star/container/XIdentifierContainer.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp> +#include <com/sun/star/drawing/ConnectorType.hpp> +#include <utility> +#include <svx/svdobj.hxx> + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::animations; + + +namespace oox::ppt { + +SlidePersist::SlidePersist( XmlFilterBase& rFilter, bool bMaster, bool bNotes, + const css::uno::Reference< css::drawing::XDrawPage >& rxPage, + oox::drawingml::ShapePtr pShapesPtr, drawingml::TextListStylePtr pDefaultTextStyle ) +: mpDrawingPtr( std::make_shared<oox::vml::Drawing>( rFilter, rxPage, oox::vml::VMLDRAWING_POWERPOINT ) ) +, mxPage( rxPage ) +, maShapesPtr(std::move( pShapesPtr )) +, mnLayoutValueToken( 0 ) +, mbMaster( bMaster ) +, mbNotes ( bNotes ) +, maDefaultTextStylePtr(std::move( pDefaultTextStyle )) +, maTitleTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() ) +, maBodyTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() ) +, maNotesTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() ) +, maOtherTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() ) +{ +#if OSL_DEBUG_LEVEL > 0 + mxDebugPage = mxPage; +#endif +} + +#if OSL_DEBUG_LEVEL > 0 +css::uno::WeakReference< css::drawing::XDrawPage > SlidePersist::mxDebugPage; +#endif + +SlidePersist::~SlidePersist() +{ +} + +sal_Int16 SlidePersist::getLayoutFromValueToken() const +{ + sal_Int16 nLayout = 20; // 20 == blank (so many magic numbers :-( the description at com.sun.star.presentation.DrawPage.Layout does not help) + switch( mnLayoutValueToken ) + { + case XML_blank: nLayout = 20; break; + case XML_chart: nLayout = 2; break; + case XML_chartAndTx: nLayout = 7; break; + case XML_clipArtAndTx: nLayout = 9; break; + case XML_clipArtAndVertTx: nLayout = 24; break; + case XML_fourObj: nLayout = 18; break; + case XML_obj: nLayout = 11; break; + case XML_objAndTx: nLayout = 13; break; + case XML_objOverTx: nLayout = 14; break; + case XML_tbl: nLayout = 8; break; + case XML_title: nLayout = 0; break; + case XML_titleOnly: nLayout = 19; break; + case XML_twoObj: + case XML_twoColTx: nLayout = 3; break; + case XML_twoObjAndObj: + case XML_twoObjAndTx: nLayout = 15; break; + case XML_twoObjOverTx: nLayout = 16; break; + case XML_tx: nLayout = 1; break; + case XML_txAndChart: nLayout = 4; break; + case XML_txAndClipArt: nLayout = 6; break; + case XML_txAndMedia: nLayout = 6; break; + case XML_txAndObj: nLayout = 10; break; + case XML_objAndTwoObj: + case XML_txAndTwoObj: nLayout = 12; break; + case XML_txOverObj: nLayout = 17; break; + case XML_vertTitleAndTx: nLayout = 22; break; + case XML_vertTitleAndTxOverChart: nLayout = 21; break; + case XML_vertTx: nLayout = 23; break; + case XML_objOnly: nLayout = 32; break; + + case XML_twoTxTwoObj: + case XML_objTx: + case XML_picTx: + case XML_secHead: + case XML_mediaAndTx: + case XML_dgm: + case XML_cust: + default: + nLayout = 20; + } + return nLayout; +} + +void SlidePersist::createXShapes( XmlFilterBase& rFilterBase ) +{ + applyTextStyles( rFilterBase ); + + Reference< XShapes > xShapes( getPage() ); + std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChildren() ); + + for (auto const& shape : rShapes) + { + std::vector< oox::drawingml::ShapePtr >& rChildren( shape->getChildren() ); + for (auto const& child : rChildren) + { + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( child.get() ); + basegfx::B2DHomMatrix aTransformation; + if ( pPPTShape ) + { + pPPTShape->addShape( rFilterBase, *this, getTheme().get(), xShapes, aTransformation, &getShapeMap() ); + if (pPPTShape->isConnectorShape()) + maConnectorShapeId.push_back(pPPTShape->getId()); + if (!pPPTShape->getChildren().empty()) + { + for (size_t i = 0; i < pPPTShape->getChildren().size(); i++) + { + if (pPPTShape->getChildren()[i]->isConnectorShape()) + maConnectorShapeId.push_back(pPPTShape->getChildren()[i]->getId()); + } + } + } + else + child->addShape( rFilterBase, getTheme().get(), xShapes, aTransformation, maShapesPtr->getFillProperties(), &getShapeMap() ); + } + } + + if (!maConnectorShapeId.empty()) + createConnectorShapeConnection(); + + Reference< XAnimationNodeSupplier > xNodeSupplier( getPage(), UNO_QUERY); + if( !xNodeSupplier.is() ) + return; + + Reference< XAnimationNode > xNode( xNodeSupplier->getAnimationNode() ); + if( xNode.is() && !maTimeNodeList.empty() ) + { + SlidePersistPtr pSlidePtr( shared_from_this() ); + TimeNodePtr pNode(maTimeNodeList.front()); + OSL_ENSURE( pNode, "pNode" ); + + Reference<XAnimationNode> xDummy; + pNode->setNode(rFilterBase, xNode, pSlidePtr, xDummy); + } +} + +void SlidePersist::createBackground( const XmlFilterBase& rFilterBase ) +{ + if ( mpBackgroundPropertiesPtr ) + { + ::Color nPhClr = maBackgroundColor.isUsed() ? + maBackgroundColor.getColor( rFilterBase.getGraphicHelper() ) : API_RGB_TRANSPARENT; + + css::awt::Size aSize; + Reference< css::beans::XPropertySet > xSet(mxPage, UNO_QUERY); + xSet->getPropertyValue("Width") >>= aSize.Width; + xSet->getPropertyValue("Height") >>= aSize.Height; + + oox::drawingml::ShapePropertyIds aPropertyIds = oox::drawingml::ShapePropertyInfo::DEFAULT.mrPropertyIds; + aPropertyIds[oox::drawingml::ShapeProperty::FillGradient] = PROP_FillGradientName; + oox::drawingml::ShapePropertyInfo aPropInfo( aPropertyIds, true, false, true, false, false ); + oox::drawingml::ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper(), aPropInfo ); + mpBackgroundPropertiesPtr->pushToPropMap( aPropMap, rFilterBase.getGraphicHelper(), 0, nPhClr, aSize); + PropertySet( mxPage ).setProperty( PROP_Background, aPropMap.makePropertySet() ); + } +} + +static void setTextStyle( Reference< beans::XPropertySet > const & rxPropSet, const XmlFilterBase& rFilter, + oox::drawingml::TextListStylePtr const & pTextListStylePtr, int nLevel ) +{ + ::oox::drawingml::TextParagraphProperties* pTextParagraphPropertiesPtr( &pTextListStylePtr->getListStyle()[ nLevel ] ); + if( pTextParagraphPropertiesPtr == nullptr ) + { + // no properties. return + return; + } + + PropertyMap& rTextParagraphPropertyMap( pTextParagraphPropertiesPtr->getTextParagraphPropertyMap() ); + + PropertySet aPropSet( rxPropSet ); + aPropSet.setProperties( rTextParagraphPropertyMap ); + pTextParagraphPropertiesPtr->getTextCharacterProperties().pushToPropSet( aPropSet, rFilter ); +} + +void SlidePersist::applyTextStyles( const XmlFilterBase& rFilterBase ) +{ + if ( !mbMaster ) + return; + + try + { + Reference< style::XStyleFamiliesSupplier > aXStyleFamiliesSupplier( rFilterBase.getModel(), UNO_QUERY_THROW ); + Reference< container::XNameAccess > aXNameAccess( aXStyleFamiliesSupplier->getStyleFamilies() ); + Reference< container::XNamed > aXNamed( mxPage, UNO_QUERY_THROW ); + + if ( aXNameAccess.is() ) + { + oox::drawingml::TextListStylePtr pTextListStylePtr; + OUString aStyle; + OUString aFamily; + + static constexpr OUStringLiteral sOutline( u"outline1" ); + static constexpr OUString sTitle( u"title"_ustr ); + static constexpr OUStringLiteral sStandard( u"standard" ); + static constexpr OUStringLiteral sSubtitle( u"subtitle" ); + + for( int i = 0; i < 4; i++ ) // todo: aggregation of bodystyle (subtitle) + { + switch( i ) + { + case 0 : // title style + { + pTextListStylePtr = maTitleTextStylePtr; + aStyle = sTitle; + aFamily= aXNamed->getName(); + break; + } + case 1 : // body style + { + pTextListStylePtr = maBodyTextStylePtr; + aStyle = sOutline; + aFamily= aXNamed->getName(); + break; + } + case 3 : // notes style + { + pTextListStylePtr = maNotesTextStylePtr; + aStyle = sTitle; + aFamily= aXNamed->getName(); + break; + } + case 4 : // standard style + { + pTextListStylePtr = maOtherTextStylePtr; + aStyle = sStandard; + aFamily = "graphics"; + break; + } + case 5 : // subtitle + { + pTextListStylePtr = maBodyTextStylePtr; + aStyle = sSubtitle; + aFamily = aXNamed->getName(); + break; + } + } + Reference< container::XNameAccess > xFamilies; + if ( aXNameAccess->hasByName( aFamily ) ) + { + if( aXNameAccess->getByName( aFamily ) >>= xFamilies ) + { + if ( xFamilies->hasByName( aStyle ) ) + { + Reference< style::XStyle > aXStyle; + if ( xFamilies->getByName( aStyle ) >>= aXStyle ) + { + Reference< beans::XPropertySet > xPropSet( aXStyle, UNO_QUERY_THROW ); + setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, 0 ); + setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, 0 ); + if ( i == 1 /* BodyStyle */ ) + { + for ( int nLevel = 1; nLevel < 5; nLevel++ ) + { + { + char pOutline[ 9 ] = "outline1"; + pOutline[ 7 ] = static_cast< char >( '0' + nLevel ); + OUString sOutlineStyle( OUString::createFromAscii( pOutline ) ); + if ( xFamilies->hasByName( sOutlineStyle ) ) + { + xFamilies->getByName( sOutlineStyle ) >>= aXStyle; + if( aXStyle.is() ) + xPropSet.set( aXStyle, UNO_QUERY_THROW ); + } + } + setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, nLevel ); + setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, nLevel ); + } + } + } + } + } + } + } + } + } + catch( const Exception& ) + { + } +} + +void SlidePersist::hideShapesAsMasterShapes() +{ + std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChildren() ); + for (auto const& shape : rShapes) + { + std::vector< oox::drawingml::ShapePtr >& rChildren( shape->getChildren() ); + for (auto const& child : rChildren) + { + PPTShape* pPPTShape = dynamic_cast< PPTShape* >( child.get() ); + if (!pPPTShape) + continue; + pPPTShape->setHiddenMasterShape( true ); + } + } +} + +// This angle determines in the direction of the line +static sal_Int32 lcl_GetAngle(uno::Reference<drawing::XShape>& rXShape, awt::Point& rPt) +{ + SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape); + tools::Rectangle aR(pObj->GetSnapRect()); + sal_Int32 nLeftX = rPt.X - aR.Left(); + sal_Int32 nTopY = rPt.Y - aR.Top(); + sal_Int32 nRightX = aR.Right() - rPt.X; + sal_Int32 nBottomY = aR.Bottom() - rPt.Y; + sal_Int32 nX = std::min(nLeftX, nRightX); + sal_Int32 nY = std::min(nTopY, nBottomY); + + sal_Int32 nAngle; + if (nX < nY) + { + if (nLeftX < nRightX) + nAngle = 180; // Left + else + nAngle = 0; // Right + } + else + { + if (nTopY < nBottomY) + nAngle = 270; // Top + else + nAngle = 90; // Bottom + } + return nAngle; +} + +Reference<XAnimationNode> SlidePersist::getAnimationNode(const OUString& sId) const +{ + const auto& pIter = maAnimNodesMap.find(sId); + if (pIter != maAnimNodesMap.end()) + return pIter->second; + + Reference<XAnimationNode> aResult; + return aResult; +} + +static void lcl_SetEdgeLineValue(uno::Reference<drawing::XShape>& rXConnector, + oox::drawingml::ShapePtr& rShapePtr) +{ + sal_Int32 nEdge = 0; + awt::Point aStartPt, aEndPt; + tools::Rectangle aS, aE; // Start, End rectangle + uno::Reference<drawing::XShape> xStartSp, xEndSp; + uno::Reference<beans::XPropertySet> xPropSet(rXConnector, uno::UNO_QUERY); + xPropSet->getPropertyValue("EdgeStartPoint") >>= aStartPt; + xPropSet->getPropertyValue("EdgeEndPoint") >>= aEndPt; + xPropSet->getPropertyValue("StartShape") >>= xStartSp; + xPropSet->getPropertyValue("EndShape") >>= xEndSp; + xPropSet->setPropertyValue("EdgeNode1HorzDist", Any(sal_Int32(0))); + xPropSet->setPropertyValue("EdgeNode1VertDist", Any(sal_Int32(0))); + xPropSet->setPropertyValue("EdgeNode2HorzDist", Any(sal_Int32(0))); + xPropSet->setPropertyValue("EdgeNode2VertDist", Any(sal_Int32(0))); + + SdrObject* pStartObj = xStartSp.is() ? SdrObject::getSdrObjectFromXShape(xStartSp) : nullptr; + SdrObject* pEndObj = xEndSp.is() ? SdrObject::getSdrObjectFromXShape(xEndSp) : nullptr; + + sal_Int32 nStartA = -1; + sal_Int32 nEndA = -1; + if (pStartObj) + { + aS = pStartObj->GetSnapRect(); + nStartA = lcl_GetAngle(xStartSp, aStartPt); + } + if (pEndObj) + { + aE = pEndObj->GetSnapRect(); + nEndA = lcl_GetAngle(xEndSp, aEndPt); + } + + // bentConnector3, bentConnector4, bentConnector5 + if (!rShapePtr->getConnectorAdjustments().empty()) + { + sal_Int32 nAdjustValue = 0; + for (size_t i = 0; i < rShapePtr->getConnectorAdjustments().size(); i++) + { + bool bVertical = false; + if (xStartSp.is() || xEndSp.is()) + bVertical = xStartSp.is() ? ((nStartA == 90 || nStartA == 270) ? true : false) + : ((nEndA == 90 || nEndA == 270) ? true : false); + else + { + sal_Int32 nAng = rShapePtr->getRotation() / 60000; + bVertical = (nAng == 90 || nAng == 270) ? true : false; + } + + if (i % 2 == 1) + bVertical = !bVertical; + + nAdjustValue = rShapePtr->getConnectorAdjustments()[i].toInt32(); + if (bVertical) + { + sal_Int32 nY = aStartPt.Y + ((nAdjustValue * (aEndPt.Y - aStartPt.Y)) / 100000); + if (xStartSp.is() && xEndSp.is()) + { + if (aS.Top() <= aE.Top()) + { + if (nStartA == 270 && i != 2) + nEdge = nY - aS.Top(); + else + { + if (aS.Bottom() < aE.Top() && nEndA != 90) + { + nEdge = nY - (aS.Bottom() + ((aE.Top() - aS.Bottom()) / 2)); + } + else + nEdge = nY - aE.Bottom(); + } + } + else + { + if (nStartA == 90 && i != 2) + nEdge = nY - aS.Bottom(); + else + { + if (aE.Bottom() < aS.Top() && nEndA != 270) + nEdge = nY - (aS.Top() + ((aE.Bottom() - aS.Top()) / 2)); + else + nEdge = nY - aE.Top(); + } + } + } + else if ((xStartSp.is() && !xEndSp.is()) || (!xStartSp.is() && xEndSp.is())) + { + if (aStartPt.Y < aEndPt.Y) + { + if (xStartSp.is()) + nEdge = (nStartA == 90) + ? nY - (aEndPt.Y - ((aEndPt.Y - aS.Bottom()) / 2)) + : nY - aS.Top(); + else + nEdge = (nEndA == 90) + ? nY - aE.Bottom() + : nY - (aStartPt.Y + ((aE.Top() - aStartPt.Y) / 2)); + } + else + { + if (xStartSp.is()) + nEdge = (nStartA == 90) ? nY - aS.Bottom() + : nY - (aEndPt.Y + ((aS.Top() - aEndPt.Y) / 2)); + else + nEdge = (nEndA == 90) + ? nY - (aStartPt.Y - ((aStartPt.Y - aE.Bottom()) / 2)) + : nY - aE.Top(); + } + } + else + { + nEdge = (aStartPt.Y < aEndPt.Y) + ? nY - (aStartPt.Y + (rXConnector->getSize().Height / 2)) + : nY - (aStartPt.Y - (rXConnector->getSize().Height / 2)); + } + } + else // Horizontal + { + sal_Int32 nX = aStartPt.X + ((nAdjustValue * (aEndPt.X - aStartPt.X)) / 100000); + if (xStartSp.is() && xEndSp.is()) + { + if (aS.Left() <= aE.Left()) + { + if (nStartA == 180 && i != 2) + nEdge = nX - aS.Left(); + else + { + if (aS.Right() < aE.Left() && nEndA != 0) + nEdge = nX - (aS.Right() + ((aE.Left() - aS.Right()) / 2)); + else + nEdge = nX - aE.Right(); + } + } + else + { + if (nStartA == 0 && i != 2) + nEdge = nX - aS.Right(); + else + { + if (aE.Right() < aS.Left() && nEndA != 180) + nEdge = nX - (aS.Left() + ((aE.Right() - aS.Left()) / 2)); + else + nEdge = nX - aE.Left(); + } + } + } + else if ((xStartSp.is() && !xEndSp.is()) || (!xStartSp.is() && xEndSp.is())) + { + if (aStartPt.X < aEndPt.X) + { + if (xStartSp.is()) + nEdge = (nStartA == 0) + ? nX - (aS.Right() + ((aEndPt.X - aS.Right()) / 2)) + : nX - aS.Left(); + else + nEdge = (nEndA == 0) + ? nX - aE.Right() + : nX - (aStartPt.X + ((aE.Left() - aStartPt.X) / 2)); + } + else + { + if (xStartSp.is()) + nEdge = (nStartA == 0) ? nX - aS.Right() + : nX - (aEndPt.X + ((aS.Left() - aEndPt.X) / 2)); + else + nEdge = (nEndA == 0) + ? nX - (aE.Right() + ((aStartPt.X - aE.Right()) / 2)) + : nX - aE.Left(); + } + } + else + { + nEdge = (aStartPt.X < aEndPt.X) + ? nX - (aStartPt.X + (rXConnector->getSize().Width / 2)) + : nX - (aStartPt.X - (rXConnector->getSize().Width / 2)); + } + } + xPropSet->setPropertyValue("EdgeLine" + OUString::number(i + 1) + "Delta", Any(nEdge)); + } + } + else + { + const OUString sConnectorName = rShapePtr->getConnectorName(); + if (sConnectorName == "bentConnector2") + { + awt::Size aConnSize = rXConnector->getSize(); + if (xStartSp.is() || xEndSp.is()) + { + if (nStartA >= 0) + { + switch (nStartA) + { + case 0: nEdge = aEndPt.X - aS.Right(); break; + case 180: nEdge = aEndPt.X - aS.Left(); break; + case 90: nEdge = aEndPt.Y - aS.Bottom(); break; + case 270: nEdge = aEndPt.Y - aS.Top(); break; + } + } else { + switch (nEndA) + { + case 0: nEdge = aStartPt.X - aE.Right(); break; + case 180: nEdge = aStartPt.X - aE.Left(); break; + case 90: nEdge = aStartPt.Y - aE.Bottom(); break; + case 270: nEdge = aStartPt.Y - aE.Top(); break; + } + } + } + else + { + bool bFlipH = rShapePtr->getFlipH(); + bool bFlipV = rShapePtr->getFlipV(); + sal_Int32 nConnectorAngle = rShapePtr->getRotation() / 60000; + if (aConnSize.Height < aConnSize.Width) + { + if ((nConnectorAngle == 90 && bFlipH && bFlipV) || (nConnectorAngle == 180) + || (nConnectorAngle == 270 && bFlipH)) + nEdge -= aConnSize.Width; + else + nEdge += aConnSize.Width; + } + else + { + if ((nConnectorAngle == 180 && bFlipV) || (nConnectorAngle == 270 && bFlipV) + || (nConnectorAngle == 90 && bFlipH && bFlipV) + || (nConnectorAngle == 0 && !bFlipV)) + nEdge -= aConnSize.Height; + else + nEdge += aConnSize.Height; + } + } + xPropSet->setPropertyValue("EdgeLine1Delta", Any(nEdge / 2)); + } + } +} + +// create connection between two shape with a connector shape. +void SlidePersist::createConnectorShapeConnection() +{ + sal_Int32 nConnectorShapeCount = maConnectorShapeId.size(); + for (sal_Int32 i = 0; i < nConnectorShapeCount; i++) + { + const auto& pIt = maShapeMap.find(maConnectorShapeId[i]); + if (pIt == maShapeMap.end()) + continue; + oox::drawingml::ConnectorShapePropertiesList aConnectorShapeProperties + = pIt->second->getConnectorShapeProperties(); + uno::Reference<drawing::XShape> xConnector(pIt->second->getXShape(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPropertySet(xConnector, uno::UNO_QUERY); + + if (xConnector.is()) + { + sal_Int32 nCount = aConnectorShapeProperties.size(); + for (sal_Int32 j = 0; j < nCount; j++) + { + OUString aDestShapeId = aConnectorShapeProperties[j].maDestShapeId; + const auto& pShape = maShapeMap.find(aDestShapeId); + if (pShape == maShapeMap.end()) + continue; + uno::Reference<drawing::XShape> xShape(pShape->second->getXShape(), uno::UNO_QUERY); + if (xShape.is()) + { + uno::Reference<drawing::XGluePointsSupplier> xSupplier(xShape, uno::UNO_QUERY); + css::uno::Reference<css::container::XIdentifierContainer> xGluePoints( + xSupplier->getGluePoints(), uno::UNO_QUERY); + + sal_Int32 nCountGluePoints = xGluePoints->getIdentifiers().getLength(); + sal_Int32 nGlueId = aConnectorShapeProperties[j].mnDestGlueId; + + // The first 4 glue points belong to the bounding box. + if (nCountGluePoints > 4) + nGlueId += 4; + else + { + bool bFlipH = pShape->second->getFlipH(); + bool bFlipV = pShape->second->getFlipV(); + if ((!bFlipH && !bFlipV) || (bFlipH && bFlipV)) + { + // change id of the left and right glue points of the bounding box (1 <-> 3) + if (nGlueId == 1) + nGlueId = 3; // Right + else if (nGlueId == 3) + nGlueId = 1; // Left + } + } + + bool bStart = aConnectorShapeProperties[j].mbStartShape; + if (bStart) + { + xPropertySet->setPropertyValue("StartShape", uno::Any(xShape)); + xPropertySet->setPropertyValue("StartGluePointIndex", uno::Any(nGlueId)); + } + else + { + xPropertySet->setPropertyValue("EndShape", uno::Any(xShape)); + xPropertySet->setPropertyValue("EndGluePointIndex", uno::Any(nGlueId)); + } + } + } + uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropertySet->getPropertySetInfo(); + if (xPropInfo->hasPropertyByName("EdgeKind")) + { + ConnectorType aConnectorType; + xPropertySet->getPropertyValue("EdgeKind") >>= aConnectorType; + if (aConnectorType == ConnectorType_STANDARD) + lcl_SetEdgeLineValue(xConnector, pIt->second); + } + } + } + maConnectorShapeId.clear(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidetimingcontext.cxx b/oox/source/ppt/slidetimingcontext.cxx new file mode 100644 index 0000000000..3002494462 --- /dev/null +++ b/oox/source/ppt/slidetimingcontext.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/slidetimingcontext.hxx> + +#include <oox/helper/attributelist.hxx> +#include <oox/ppt/timenodelistcontext.hxx> +#include "buildlistcontext.hxx" +#include <oox/token/namespaces.hxx> + + +using namespace ::com::sun::star; +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + +SlideTimingContext::SlideTimingContext( FragmentHandler2 const & rParent, TimeNodePtrList & aTimeNodeList ) noexcept + : FragmentHandler2( rParent ) + , maTimeNodeList( aTimeNodeList ) +{ +} + +SlideTimingContext::~SlideTimingContext() noexcept +{ + +} + +::oox::core::ContextHandlerRef SlideTimingContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( bldLst ): + return new BuildListContext( *this ); + case PPT_TOKEN( extLst ): + return this; + case PPT_TOKEN( tnLst ): + // timing nodes + { + return new TimeNodeListContext( *this, maTimeNodeList ); + } + break; + + default: + return this; + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidetransition.cxx b/oox/source/ppt/slidetransition.cxx new file mode 100644 index 0000000000..8379f9e4b6 --- /dev/null +++ b/oox/source/ppt/slidetransition.cxx @@ -0,0 +1,467 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/slidetransition.hxx> + +#include <com/sun/star/animations/TransitionType.hpp> +#include <com/sun/star/animations/TransitionSubType.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> + +#include <sal/log.hxx> +#include <tools/color.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <oox/helper/propertymap.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +namespace oox::ppt { + + SlideTransition::SlideTransition() + : mnTransitionType( 0 ) + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) + , mfTransitionDurationInSeconds( -1.0 ) + , mbMode( true ) + , mnAdvanceTime( -1 ) + , mnTransitionFadeColor( 0 ) + { + + } + + SlideTransition::SlideTransition(std::u16string_view sFilterName) + : mnTransitionType( 0 ) + , mnTransitionSubType( 0 ) + , mbTransitionDirectionNormal( true ) + , mnAnimationSpeed( AnimationSpeed_FAST ) + , mfTransitionDurationInSeconds( -1.0 ) + , mbMode( true ) + , mnAdvanceTime( -1 ) + , mnTransitionFadeColor( 0 ) + { + const transition *p = transition::find( sFilterName ); + if( p ) + { + mnTransitionType = p->mnType; + mnTransitionSubType = p->mnSubType; + mbTransitionDirectionNormal = p->mbDirection; + } + } + + void SlideTransition::setSlideProperties( PropertyMap & aProps ) + { + try + { + aProps.setProperty( PROP_TransitionType, mnTransitionType); + aProps.setProperty( PROP_TransitionSubtype, mnTransitionSubType); + aProps.setProperty( PROP_TransitionDirection, mbTransitionDirectionNormal); + aProps.setProperty( PROP_Speed, mnAnimationSpeed); + if( mfTransitionDurationInSeconds >= 0.0 ) + aProps.setProperty( PROP_TransitionDuration, mfTransitionDurationInSeconds); + aProps.setProperty( PROP_TransitionFadeColor, mnTransitionFadeColor); + if( mnAdvanceTime != -1 ) { + aProps.setProperty( PROP_Duration, mnAdvanceTime/1000); + aProps.setProperty( PROP_Change, static_cast<sal_Int32>(1)); + } + } + catch( Exception& ) + { + // should not happen + TOOLS_WARN_EXCEPTION( "oox", "" ); + } + } + + void SlideTransition::setTransitionFilterProperties( const Reference< XTransitionFilter > & xFilter ) + { + try + { + xFilter->setTransition( mnTransitionType ); + xFilter->setSubtype( mnTransitionSubType ); + xFilter->setDirection( mbTransitionDirectionNormal ); + xFilter->setFadeColor( 0 ); + xFilter->setMode( mbMode ); + } + catch( Exception& ) + { + // should not happen + TOOLS_WARN_EXCEPTION( "oox", "" ); + } + } + + void SlideTransition::setOoxTransitionSpeed( sal_Int32 nToken) + { + switch( nToken ) + { + /* the speed values are located in the PPT97 importer + * sd/source/filter/ppt/pptin.cxx:1783 + * (void ImplSdPPTImport::ImportPageEffect) + */ + case XML_fast: + mnAnimationSpeed = AnimationSpeed_FAST; + mfTransitionDurationInSeconds = 0.5; + break; + case XML_med: + mnAnimationSpeed = AnimationSpeed_MEDIUM; + mfTransitionDurationInSeconds = 0.75; + break; + case XML_slow: + mnAnimationSpeed = AnimationSpeed_SLOW; + mfTransitionDurationInSeconds = 1.0; + break; + default: + // should not happen. just ignore + break; + } + } + + void SlideTransition::setOoxTransitionSpeed( double fDurationInSeconds ) + { + // for compatibility + mnAnimationSpeed = ( fDurationInSeconds <= 0.5 ) ? AnimationSpeed_FAST + : ( fDurationInSeconds >= 1.0 ) ? AnimationSpeed_SLOW : AnimationSpeed_MEDIUM; + mfTransitionDurationInSeconds = fDurationInSeconds; + } + + sal_Int16 SlideTransition::ooxToOdpEightDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + nOdpDirection = ooxToOdpBorderDirections( nOoxType ); + if( nOdpDirection == 0 ) + { + nOdpDirection = ooxToOdpCornerDirections( nOoxType ); + } + return nOdpDirection; + } + + sal_Int16 SlideTransition::ooxToOdpBorderDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + switch( nOoxType ) + { + case XML_d: + nOdpDirection = TransitionSubType::FROMTOP; + break; + case XML_l: + nOdpDirection = TransitionSubType::FROMLEFT; + break; + case XML_r: + nOdpDirection = TransitionSubType::FROMRIGHT; + break; + case XML_u: + nOdpDirection = TransitionSubType::FROMBOTTOM; + break; + default: + nOdpDirection= 0; + break; + } + return nOdpDirection; + } + + sal_Int16 SlideTransition::ooxToOdpSideDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + switch( nOoxType ) + { + case XML_d: + case XML_u: + nOdpDirection = TransitionSubType::TOPTOBOTTOM; + break; + case XML_l: + case XML_r: + nOdpDirection = TransitionSubType::LEFTTORIGHT; + break; + default: + nOdpDirection= 0; + break; + } + return nOdpDirection; + } + + bool SlideTransition::ooxToOdpSideDirectionsDirectionNormal( ::sal_Int32 nOoxType ) + { + bool bOdpDirection = true; + switch( nOoxType ) + { + case XML_u: + case XML_l: + bOdpDirection = false; + break; + } + return bOdpDirection; + } + + sal_Int16 SlideTransition::ooxToOdpCornerDirections( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDirection; + switch( nOoxType ) + { + case XML_lu: + nOdpDirection = TransitionSubType::FROMBOTTOMRIGHT; + break; + case XML_ru: + nOdpDirection = TransitionSubType::FROMBOTTOMLEFT; + break; + case XML_ld: + nOdpDirection = TransitionSubType::FROMTOPRIGHT; + break; + case XML_rd: + nOdpDirection = TransitionSubType::FROMTOPLEFT; + break; + default: + nOdpDirection = 0; + break; + } + return nOdpDirection; + } + + sal_Int16 SlideTransition::ooxToOdpDirection( ::sal_Int32 nOoxType ) + { + sal_Int16 nOdpDir; + switch( nOoxType ) + { + case XML_vert: + nOdpDir = TransitionSubType::VERTICAL; + break; + case XML_horz: + nOdpDir = TransitionSubType::HORIZONTAL; + break; + default: + nOdpDir = 0; + break; + } + return nOdpDir; + } + + void SlideTransition::setOoxTransitionType( ::sal_Int32 OoxType, ::sal_Int32 param1, ::sal_Int32 param2 ) + { + switch( OoxType ) + { + case PPT_TOKEN( blinds ): + mnTransitionType = TransitionType::BLINDSWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + break; + case PPT_TOKEN( checker ): + mnTransitionType = TransitionType::CHECKERBOARDWIPE; + switch ( param1 ) + { + case XML_vert: + mnTransitionSubType = TransitionSubType::DOWN; + break; + case XML_horz: + mnTransitionSubType = TransitionSubType::ACROSS; + break; + default: + break; + } + break; + case PPT_TOKEN( comb ): + mnTransitionType = TransitionType::PUSHWIPE; + switch( param1 ) + { + case XML_vert: + mnTransitionSubType = TransitionSubType::COMBVERTICAL; + break; + case XML_horz: + mnTransitionSubType = TransitionSubType::COMBHORIZONTAL; + break; + default: + break; + } + break; + case PPT_TOKEN( cover ): + mnTransitionType = TransitionType::SLIDEWIPE; + mnTransitionSubType = ooxToOdpEightDirections( param1 ); + break; + case PPT_TOKEN( pull ): // uncover + mnTransitionType = TransitionType::SLIDEWIPE; + mnTransitionSubType = ooxToOdpEightDirections( param1 ); + mbTransitionDirectionNormal = false; + break; + case PPT_TOKEN( cut ): + if( param1 ) + { + mnTransitionType = TransitionType::BARWIPE; + mnTransitionSubType = TransitionSubType::FADEOVERCOLOR; + } + SAL_WARN("oox.ppt", "OOX: cut transition fallback." ); + break; + case PPT_TOKEN( fade ): + mnTransitionType = TransitionType::FADE; + if( param1 ) + { + mnTransitionSubType = TransitionSubType::FADEOVERCOLOR; + } + else + { + mnTransitionSubType = TransitionSubType::CROSSFADE; + } + break; + case PPT_TOKEN( push ): + mnTransitionType = TransitionType::PUSHWIPE; + mnTransitionSubType = ooxToOdpBorderDirections( param1 ); + break; + case PPT_TOKEN( wipe ): + mnTransitionType = TransitionType::BARWIPE; + mnTransitionSubType = ooxToOdpSideDirections( param1 ); + mbTransitionDirectionNormal = ooxToOdpSideDirectionsDirectionNormal( param1 ); + break; + case PPT_TOKEN( split ): + mnTransitionType = TransitionType::BARNDOORWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + if( param2 == XML_in ) + { + // reverse + mbTransitionDirectionNormal = false; + } + break; + case PPT_TOKEN( wheel ): + mnTransitionType = TransitionType::PINWHEELWIPE; + switch( param1 ) + { + case 1: + mnTransitionSubType = TransitionSubType::ONEBLADE; + break; + case 2: + mnTransitionSubType = TransitionSubType::TWOBLADEVERTICAL; + break; + case 3: + mnTransitionSubType = TransitionSubType::THREEBLADE; + break; + case 4: + mnTransitionSubType = TransitionSubType::FOURBLADE; + break; + case 8: + mnTransitionSubType = TransitionSubType::EIGHTBLADE; + break; + default: + SAL_INFO( + "oox.ppt", + "strange number of blades for the wheel-wipe " << param1); + if( param1 > 8 ) + { + mnTransitionSubType = TransitionSubType::EIGHTBLADE; + } + else if( param1 > 4 ) + { + mnTransitionSubType = TransitionSubType::FOURBLADE; + } + else if( param1 == 0) + { + mnTransitionSubType = TransitionSubType::ONEBLADE; + } + break; + } + break; + case PPT_TOKEN( randomBar ): + mnTransitionType = TransitionType::RANDOMBARWIPE; + mnTransitionSubType = ooxToOdpDirection( param1 ); + break; + case PPT_TOKEN( circle ): + mnTransitionType = TransitionType::ELLIPSEWIPE; + mnTransitionSubType = TransitionSubType::CIRCLE; + break; + case PPT_TOKEN( diamond ): + mnTransitionType = TransitionType::IRISWIPE; + mnTransitionSubType = TransitionSubType::DIAMOND; + break; + case PPT_TOKEN( dissolve ): + mnTransitionType = TransitionType::DISSOLVE; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + case PPT_TOKEN( newsflash ): + mnTransitionType = TransitionType::ZOOM; + mnTransitionSubType = TransitionSubType::ROTATEIN; + break; + case PPT_TOKEN( plus ): + mnTransitionType = TransitionType::FOURBOXWIPE; + mnTransitionSubType = TransitionSubType::CORNERSOUT; + break; + case PPT_TOKEN( random ): + mnTransitionType = TransitionType::RANDOM; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + case PPT_TOKEN( wedge ): + mnTransitionType = TransitionType::FANWIPE; + mnTransitionSubType = TransitionSubType::CENTERTOP; + break; + case PPT_TOKEN( zoom ): + mnTransitionType = TransitionType::ZOOM; + mnTransitionSubType = TransitionSubType::DEFAULT; + break; + case P14_TOKEN(prism): + mnTransitionType = TransitionType::MISCSHAPEWIPE; + if (param1) + mnTransitionSubType = TransitionSubType::CORNERSIN; + else + mnTransitionSubType = TransitionSubType::CORNERSOUT; + break; + case P14_TOKEN(vortex): + mnTransitionType = TransitionType::MISCSHAPEWIPE; + mnTransitionSubType = TransitionSubType::VERTICAL; + break; + case P14_TOKEN(ripple): + mnTransitionType = TransitionType::MISCSHAPEWIPE; + mnTransitionSubType = TransitionSubType::HORIZONTAL; + break; + case P14_TOKEN(glitter): + mnTransitionType = TransitionType::MISCSHAPEWIPE; + mnTransitionSubType = TransitionSubType::DIAMOND; + break; + case P14_TOKEN(honeycomb): + mnTransitionType = TransitionType::MISCSHAPEWIPE; + mnTransitionSubType = TransitionSubType::HEART; + break; + case P14_TOKEN(flash): + mnTransitionType = TransitionType::FADE; + mnTransitionSubType = TransitionSubType::FADEOVERCOLOR; + mnTransitionFadeColor = static_cast<sal_Int32>(COL_WHITE); + break; + case PPT_TOKEN(strips): + mnTransitionType = TransitionType::SLIDEWIPE; + mnTransitionSubType = ooxToOdpCornerDirections( param1 ); + break; + default: + mnTransitionType = 0; + break; + } + } + + void SlideTransition::setPresetTransition(std::u16string_view sPresetTransition) + { + if (sPresetTransition == u"fallOver") + { + mnTransitionType = TransitionType::MISCSHAPEWIPE; + mnTransitionSubType = TransitionSubType::LEFTTORIGHT; + } + else + { + mnTransitionType = 0; + } + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx new file mode 100644 index 0000000000..b7a5d9c19f --- /dev/null +++ b/oox/source/ppt/slidetransitioncontext.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/slidetransitioncontext.hxx> + +#include <oox/ppt/backgroundproperties.hxx> +#include <oox/ppt/soundactioncontext.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +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::ppt { + +SlideTransitionContext::SlideTransitionContext( FragmentHandler2 const & rParent, const AttributeList& rAttribs, PropertyMap & aProperties ) +: FragmentHandler2( rParent ) +, maSlideProperties( aProperties ) +, mbHasTransition( false ) +, mbHasTransitionDuration( false ) +{ + // ST_TransitionSpeed + maTransition.setOoxTransitionSpeed( rAttribs.getToken( XML_spd, XML_fast ) ); + + // p14:dur + sal_Int32 nDurationInMs = rAttribs.getInteger( P14_TOKEN( dur ), -1 ); + if( nDurationInMs > -1 ) + { + // In MSO 0 is visible as 0.01s + if( nDurationInMs == 0.0 ) + nDurationInMs = 10; + maTransition.setOoxTransitionSpeed( nDurationInMs / 1000.0 ); + mbHasTransitionDuration = true; + } + + // TODO + rAttribs.getBool( XML_advClick, true ); + + // careful. if missing, no auto advance... 0 looks like a valid value + // for auto advance + if(rAttribs.hasAttribute( XML_advTm )) + maTransition.setOoxAdvanceTime( rAttribs.getInteger( XML_advTm, -1 ) ); +} + +SlideTransitionContext::~SlideTransitionContext() noexcept +{ + +} + +::oox::core::ContextHandlerRef SlideTransitionContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case PPT_TOKEN( blinds ): + case PPT_TOKEN( checker ): + case PPT_TOKEN( comb ): + case PPT_TOKEN( randomBar ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_dir, XML_horz ), 0); + } + return this; + case PPT_TOKEN( cover ): + case PPT_TOKEN( pull ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_dir, XML_l ), 0 ); + } + return this; + case PPT_TOKEN( cut ): + case PPT_TOKEN( fade ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, sal_Int32(rAttribs.getBool( XML_thruBlk, false )), 0); + } + return this; + case PPT_TOKEN( push ): + case PPT_TOKEN( wipe ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_dir, XML_l ), 0 ); + } + return this; + case PPT_TOKEN( split ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_orient, XML_horz ), rAttribs.getToken( XML_dir, XML_out ) ); + } + return this; + case PPT_TOKEN( zoom ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_dir, XML_out ), 0 ); + } + return this; + case PPT_TOKEN( wheel ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getUnsigned( XML_spokes, 4 ), 0 ); + // unsignedInt + } + return this; + case PPT_TOKEN( circle ): + case PPT_TOKEN( diamond ): + case PPT_TOKEN( dissolve ): + case PPT_TOKEN( newsflash ): + case PPT_TOKEN( plus ): + case PPT_TOKEN( random ): + case PPT_TOKEN( wedge ): + case P14_TOKEN( vortex ): + case P14_TOKEN( ripple ): + case P14_TOKEN( glitter ): + case P14_TOKEN( honeycomb ): + case P14_TOKEN( flash ): + // CT_Empty + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, 0, 0 ); + } + return this; + + case PPT_TOKEN( sndAc ): // CT_TransitionSoundAction + //"Sound" + return new SoundActionContext ( *this, maSlideProperties ); + case PPT_TOKEN( extLst ): // CT_OfficeArtExtensionList + return this; + + case P14_TOKEN(prism): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType(aElementToken, sal_Int32(rAttribs.getBool(XML_isInverted, false)), 0); + } + return this; + case P15_TOKEN(prstTrans): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setPresetTransition(rAttribs.getStringDefaulted(XML_prst)); + } + return this; + case PPT_TOKEN( strips ): + if (!mbHasTransition) + { + mbHasTransition = true; + maTransition.setOoxTransitionType( aElementToken, rAttribs.getToken( XML_dir, XML_ld ), 0 ); + } + return this; + + + default: + break; + } + + return this; +} + +void SlideTransitionContext::onEndElement() +{ + if( isCurrentElement(PPT_TOKEN( transition )) ) + { + if( mbHasTransition || mbHasTransitionDuration ) + { + maTransition.setSlideProperties( maSlideProperties ); + mbHasTransition = false; + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/soundactioncontext.cxx b/oox/source/ppt/soundactioncontext.cxx new file mode 100644 index 0000000000..bac5c6641e --- /dev/null +++ b/oox/source/ppt/soundactioncontext.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <oox/ppt/soundactioncontext.hxx> + +#include <com/sun/star/io/XInputStream.hpp> + +#include <oox/helper/attributelist.hxx> +#include <oox/helper/propertymap.hxx> +#include <drawingml/embeddedwavaudiofile.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <avmedia/mediaitem.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + +namespace oox::ppt { + + SoundActionContext::SoundActionContext( FragmentHandler2 const & rParent, PropertyMap & aProperties ) noexcept + : FragmentHandler2( rParent ) + , maSlideProperties( aProperties ) + , mbHasStartSound( false ) + , mbLoopSound( false ) + , mbStopSound( false ) + { + } + + SoundActionContext::~SoundActionContext() noexcept + { + } + + void SoundActionContext::onEndElement() + { + if ( !isCurrentElement( PPT_TOKEN( sndAc ) ) ) + return; + + if( !mbHasStartSound ) + return; + + OUString url; +#if HAVE_FEATURE_AVMEDIA + if ( !msSndName.isEmpty() ) + { + Reference<css::io::XInputStream> + xInputStream = getFilter().openInputStream(msSndName); + if (xInputStream.is()) + { + ::avmedia::EmbedMedia(getFilter().getModel(), msSndName, url, xInputStream); + xInputStream->closeInput(); + } + } +#endif + if ( !url.isEmpty() ) + { + maSlideProperties.setProperty( PROP_Sound, url); + maSlideProperties.setProperty( PROP_SoundOn, true); + } + } + + ::oox::core::ContextHandlerRef SoundActionContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + switch( aElementToken ) + { + case PPT_TOKEN( snd ): + if( mbHasStartSound ) + { + msSndName = drawingml::getEmbeddedWAVAudioFile( getRelations(), rAttribs ); + } + return this; + case PPT_TOKEN( endSnd ): + // CT_Empty + mbStopSound = true; + return this; + case PPT_TOKEN( stSnd ): + mbHasStartSound = true; + mbLoopSound = rAttribs.getBool( XML_loop, false ); + return this; + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timeanimvaluecontext.cxx b/oox/source/ppt/timeanimvaluecontext.cxx new file mode 100644 index 0000000000..443b0b0393 --- /dev/null +++ b/oox/source/ppt/timeanimvaluecontext.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "timeanimvaluecontext.hxx" + +#include "animvariantcontext.hxx" + +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +namespace oox::ppt { + + TimeAnimValueListContext::TimeAnimValueListContext( FragmentHandler2 const & rParent, + TimeAnimationValueList & aTavList ) + : FragmentHandler2( rParent ) + , maTavList( aTavList ) + , mbInValue( false ) + { + } + + TimeAnimValueListContext::~TimeAnimValueListContext( ) + { + } + + void TimeAnimValueListContext::onEndElement() + { + if( isCurrentElement( PPT_TOKEN( tav ) ) ) + { + mbInValue = false; + } + } + + ::oox::core::ContextHandlerRef TimeAnimValueListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + + switch ( aElementToken ) + { + case PPT_TOKEN( tav ): + { + mbInValue = true; + TimeAnimationValue val; + val.msFormula = rAttribs.getStringDefaulted( XML_fmla); + val.msTime = rAttribs.getStringDefaulted( XML_tm); + maTavList.push_back( val ); + return this; + } + case PPT_TOKEN( val ): + if( mbInValue ) + { + // CT_TLAnimVariant + return new AnimVariantContext( *this, aElementToken, maTavList.back().maValue ); + } + break; + default: + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timeanimvaluecontext.hxx b/oox/source/ppt/timeanimvaluecontext.hxx new file mode 100644 index 0000000000..34b1c54326 --- /dev/null +++ b/oox/source/ppt/timeanimvaluecontext.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_TIMEANIMVALUECONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_TIMEANIMVALUECONTEXT_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/ppt/animationspersist.hxx> + +namespace oox::ppt { + + /** CT_TLTimeAnimateValueList */ + class TimeAnimValueListContext + : public ::oox::core::FragmentHandler2 + { + public: + TimeAnimValueListContext( ::oox::core::FragmentHandler2 const & rParent, + TimeAnimationValueList & aTavList ); + + virtual ~TimeAnimValueListContext( ) override; + + virtual void onEndElement() override; + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + TimeAnimationValueList & maTavList; + bool mbInValue; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timenode.cxx b/oox/source/ppt/timenode.cxx new file mode 100644 index 0000000000..e8732e8858 --- /dev/null +++ b/oox/source/ppt/timenode.cxx @@ -0,0 +1,668 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/timenode.hxx> + +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/animations/XAnimateColor.hpp> +#include <com/sun/star/animations/XAnimateMotion.hpp> +#include <com/sun/star/animations/XAnimateTransform.hpp> +#include <com/sun/star/animations/XCommand.hpp> +#include <com/sun/star/animations/XAudio.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/animations/XTimeContainer.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/Event.hpp> +#include <com/sun/star/animations/EventTrigger.hpp> +#include <com/sun/star/io/WrongFormatException.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +#include <oox/core/xmlfilterbase.hxx> +#include <oox/ppt/pptfilterhelpers.hxx> +#include <oox/token/tokens.hxx> +#include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> + +using namespace ::oox::core; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +namespace { + +void lcl_setAncestorSubItem( const Reference<XAnimationNode>& xParent, sal_Int16 nSubItem ) +{ + + Reference<XAnimationNode> xNode = xParent; + + while ( xNode.is() ) + { + if ( xNode->getType() == AnimationNodeType::ANIMATE ) + { + Reference<XAnimate> xAnimate( xNode, UNO_QUERY ); + if ( xAnimate.is() ) + xAnimate->setSubItem( nSubItem ); + break; + } + else if ( xNode->getType() == AnimationNodeType::ITERATE ) + { + Reference<XIterateContainer> xIterateContainer( xNode, UNO_QUERY ); + if ( xIterateContainer.is() ) + xIterateContainer->setSubItem( nSubItem ); + break; + } + + xNode.set( xNode->getParent(), UNO_QUERY ); + } +} + +} + +namespace oox::ppt { + OUString TimeNode::getServiceName( sal_Int16 nNodeType ) + { + OUString sServiceName; + switch( nNodeType ) + { + case AnimationNodeType::PAR: + sServiceName = "com.sun.star.animations.ParallelTimeContainer"; + break; + case AnimationNodeType::SEQ: + sServiceName = "com.sun.star.animations.SequenceTimeContainer"; + break; + case AnimationNodeType::ANIMATE: + sServiceName = "com.sun.star.animations.Animate"; + break; + case AnimationNodeType::ITERATE: + sServiceName = "com.sun.star.animations.IterateContainer"; + break; + case AnimationNodeType::ANIMATECOLOR: + sServiceName = "com.sun.star.animations.AnimateColor"; + break; + case AnimationNodeType::TRANSITIONFILTER: + sServiceName = "com.sun.star.animations.TransitionFilter"; + break; + case AnimationNodeType::ANIMATEMOTION: + sServiceName = "com.sun.star.animations.AnimateMotion"; + break; + case AnimationNodeType::ANIMATETRANSFORM: + sServiceName = "com.sun.star.animations.AnimateTransform"; + break; + case AnimationNodeType::COMMAND: + sServiceName = "com.sun.star.animations.Command"; + break; + case AnimationNodeType::SET: + sServiceName = "com.sun.star.animations.AnimateSet"; + break; + case AnimationNodeType::AUDIO: + sServiceName = "com.sun.star.animations.Audio"; + break; + default: + SAL_INFO("oox.ppt","OOX: unhandled type " << nNodeType ); + break; + } + return sServiceName; + } + + TimeNode::TimeNode( sal_Int16 nNodeType ) + : mnNodeType( nNodeType ) + , mbHasEndSyncValue( false ) + { + } + + TimeNode::~TimeNode() + { + } + + void fixMainSequenceTiming( const css::uno::Reference< css::animations::XAnimationNode >& xNode ) + { + try + { + bool bFirst = true; + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_SET_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + + Event aEvent; + aEvent.Trigger = EventTrigger::ON_NEXT; + aEvent.Repeat = 0; + xClickNode->setBegin( Any( aEvent ) ); + + if( bFirst ) + { + bFirst = false; + Reference< XEnumerationAccess > xEA2( xClickNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE2( xEA2->createEnumeration(), UNO_SET_THROW ); + if( xE2->hasMoreElements() ) + { + // with node + xE2->nextElement() >>= xEA2; + if( xEA2.is() ) + xE2 = xEA2->createEnumeration(); + else + xE2.clear(); + + if( xE2.is() && xE2->hasMoreElements() ) + { + Reference< XAnimationNode > xEffectNode( xE2->nextElement(), UNO_QUERY_THROW ); + const Sequence< NamedValue > aUserData( xEffectNode->getUserData() ); + for( const NamedValue& rProp : aUserData ) + { + if ( rProp.Name == "node-type" ) + { + sal_Int16 nNodeType = 0; + rProp.Value >>= nNodeType; + if( nNodeType != css::presentation::EffectNodeType::ON_CLICK ) + { + // first effect does not start on click, so correct + // first click nodes begin to 0s + xClickNode->setBegin( Any( 0.0 ) ); + break; + } + } + } + } + } + } + } + } + catch( Exception& ) + { + SAL_INFO("oox.ppt","fixMainSequenceTiming(), exception caught!" ); + } + } + + void fixInteractiveSequenceTiming( const css::uno::Reference< css::animations::XAnimationNode >& xNode ) + { + try + { + Any aBegin( xNode->getBegin() ); + Any aEmpty; + xNode->setBegin( aEmpty ); + + Reference< XEnumerationAccess > xEA( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_SET_THROW ); + while( xE->hasMoreElements() ) + { + // click node + Reference< XAnimationNode > xClickNode( xE->nextElement(), UNO_QUERY ); + xClickNode->setBegin( aBegin ); + } + } + catch( Exception& ) + { + SAL_INFO("oox.ppt","fixInteractiveSequenceTiming(), exception caught!" ); + } + } + + void TimeNode::addNode( const XmlFilterBase& rFilter, const Reference< XAnimationNode >& rxNode, const SlidePersistPtr & pSlide ) + { + try { + sal_Int16 nNodeType = mnNodeType; + + if (mnNodeType == AnimationNodeType::PAR && maNodeProperties[NP_ITERATETYPE].hasValue()) + nNodeType = AnimationNodeType::ITERATE; + + OUString sServiceName = getServiceName(nNodeType); + + Reference< XAnimationNode > xNode = createAndInsert( rFilter, sServiceName, rxNode ); + if (!xNode) + return; + setNode(rFilter, xNode, pSlide, rxNode); + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::addNode()" ); + } + } + + void TimeNode::setNode(const XmlFilterBase& rFilter, const Reference< XAnimationNode >& xNode, const SlidePersistPtr & pSlide, const Reference<XAnimationNode>& xParent) + { + SAL_WARN_IF( !xNode.is(), "oox.ppt", "null node passed" ); + + try { + if( !msId.isEmpty() ) + { + pSlide->getAnimNodesMap()[ msId ] = xNode; + } + + if( mpTarget ) + { + sal_Int16 nSubItem(0); + maNodeProperties[ NP_TARGET ] = mpTarget->convert( pSlide, nSubItem ); + if( mpTarget->mnType == XML_spTgt ) + { + if ( xNode->getType() == AnimationNodeType::ANIMATE || + xNode->getType() == AnimationNodeType::ITERATE ) + { + maNodeProperties[ NP_SUBITEM ] <<= nSubItem; + } + else + lcl_setAncestorSubItem( xParent, nSubItem ); + } + } + + if( !maStCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maStCondList ); + if( aAny.hasValue() ) + { + xNode->setBegin( aAny ); + } + + } + if( !maEndCondList.empty() ) + { + Any aAny = AnimationCondition::convertList( pSlide, maEndCondList ); + if( aAny.hasValue() ) + { + xNode->setEnd( aAny ); + } + } + if( mbHasEndSyncValue ) + { + Any aValue = maEndSyncValue.convert( pSlide ); + xNode->setEndSync(aValue); + } + + if( !maUserData.empty() ) + { + Sequence< NamedValue > aUserDataSeq( static_cast< sal_Int32 >( maUserData.size() ) ); + NamedValue* pValues = aUserDataSeq.getArray(); + for (auto const& elem : maUserData) + { + pValues->Name = elem.first; + pValues->Value = elem.second; + ++pValues; + } + maNodeProperties[ NP_USERDATA ] <<= aUserDataSeq; + } + + Reference< XAnimate > xAnimate( xNode, UNO_QUERY ); + Reference< XAnimateColor > xAnimateColor( xNode, UNO_QUERY ); + Reference< XAnimateMotion > xAnimateMotion( xNode, UNO_QUERY ); + Reference< XAnimateTransform > xAnimateTransform( xNode, UNO_QUERY ); + Reference< XCommand > xCommand( xNode, UNO_QUERY ); + Reference< XAudio > xAudio( xNode, UNO_QUERY ); + Reference< XIterateContainer > xIterateContainer( xNode, UNO_QUERY ); + sal_Int16 nInt16 = 0; + bool bBool = false; + double fDouble = 0; + OUString sString; + Sequence< NamedValue > aSeq; + + for( int i = 0; i < NP_SIZE_; i++) + { + Any & aValue( maNodeProperties[ i ] ); + if( aValue.hasValue() ) + { + switch( i ) + { + case NP_TO: + if( xAnimate.is() ) + xAnimate->setTo( aValue ); + break; + case NP_FROM: + if( xAnimate.is() ) + xAnimate->setFrom( aValue ); + break; + case NP_BY: + if( xAnimate.is() ) + xAnimate->setBy( aValue ); + break; + case NP_HIDEDURINGSHOW: + if (xAudio.is() && (aValue >>= bBool)) + { + xAudio->setHideDuringShow(bBool); + } + break; + case NP_ISNARRATION: + if (xAudio.is() && (aValue >>= bBool)) + { + xAudio->setNarration(bBool); + } + break; + case NP_TARGET: + + if (xParent.is() && xParent->getType() == AnimationNodeType::ITERATE) + { + Reference<XIterateContainer> xParentContainer(xParent, UNO_QUERY); + if (xParentContainer.is()) + xParentContainer->setTarget(aValue); + } + else + { + if (xAnimate.is()) + xAnimate->setTarget(aValue); + if (xCommand.is()) + xCommand->setTarget(aValue); + if (xAudio.is()) + xAudio->setSource(aValue); + } + break; + case NP_SUBITEM: + if( aValue >>= nInt16 ) + { + if( xAnimate.is() ) + { + xAnimate->setSubItem( nInt16 ); + } + else if ( xIterateContainer.is() ) + { + xIterateContainer->setSubItem( nInt16 ); + } + } + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_ATTRIBUTENAME: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setAttributeName( sString ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_CALCMODE: + if( xAnimate.is() ) + { + if( aValue >>= nInt16 ) + xAnimate->setCalcMode( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_KEYTIMES: + if( xAnimate.is() ) + { + Sequence<double> aKeyTimes; + if( aValue >>= aKeyTimes ) + xAnimate->setKeyTimes(aKeyTimes); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_VALUES: + if( xAnimate.is() ) + { + Sequence<Any> aValues; + if( aValue >>= aValues ) + xAnimate->setValues(aValues); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_FORMULA: + if( xAnimate.is() ) + { + if( aValue >>= sString ) + xAnimate->setFormula(sString); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_COLORINTERPOLATION: + if( xAnimateColor.is() ) + { + if( aValue >>= nInt16 ) + xAnimateColor->setColorInterpolation( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_DIRECTION: + if( xAnimateColor.is() ) + { + if( aValue >>= bBool ) + xAnimateColor->setDirection( bBool ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_PATH: + if( xAnimateMotion.is() ) + xAnimateMotion->setPath( aValue ); + break; + case NP_TRANSFORMTYPE: + if( xAnimateTransform.is() ) + { + if( aValue >>= nInt16 ) + xAnimateTransform->setTransformType( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_USERDATA: + if( aValue >>= aSeq ) + xNode->setUserData( aSeq ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_ACCELERATION: + if( aValue >>= fDouble ) + xNode->setAcceleration( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_DECELERATE: + if( aValue >>= fDouble ) + xNode->setDecelerate( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_AUTOREVERSE: + if( aValue >>= bBool ) + xNode->setAutoReverse( bBool ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_DURATION: + xNode->setDuration( aValue ); + break; + case NP_FILL: + if( aValue >>= nInt16 ) + xNode->setFill( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_REPEATCOUNT: + xNode->setRepeatCount( aValue ); + break; + case NP_REPEATDURATION: + xNode->setRepeatDuration( aValue ); + break; + case NP_RESTART: + if( aValue >>= nInt16 ) + xNode->setRestart( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + break; + case NP_COMMAND: + if( xCommand.is() ) + { + if( aValue >>= nInt16 ) + xCommand->setCommand( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_PARAMETER: + if( xCommand.is() ) + xCommand->setParameter( aValue ); + break; + case NP_ITERATETYPE: + if( xIterateContainer.is() ) + { + if( aValue >>= nInt16 ) + xIterateContainer->setIterateType( nInt16 ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + case NP_ITERATEINTERVAL: + if( xIterateContainer.is() ) + { + if( aValue >>= fDouble ) + xIterateContainer->setIterateInterval( fDouble ); + else + { + SAL_INFO("oox.ppt","any >>= failed " << __LINE__ ); + } + } + break; + default: + SAL_INFO("oox.ppt","ERR-OOX: unknown prop index " << i ); + break; + } + } + } + + if (xAnimate.is() && xAnimate->getValues().getLength() != xAnimate->getKeyTimes().getLength()) + throw css::io::WrongFormatException(); + + if( mnNodeType == AnimationNodeType::TRANSITIONFILTER ) + { + + Reference< XTransitionFilter > xFilter( xNode, UNO_QUERY ); + maTransitionFilter.setTransitionFilterProperties( xFilter ); + } + + std::for_each( + maChildren.begin(), maChildren.end(), + [&rFilter, &xNode, &pSlide] (TimeNodePtr const & child) { + child->addNode(rFilter, xNode, pSlide); + } ); + + switch( mnNodeType ) + { + case AnimationNodeType::SEQ: + { + sal_Int16 nEnum = 0; + if( maUserData[ "node-type" ] >>= nEnum ) + { + if( nEnum == EffectNodeType::MAIN_SEQUENCE ) + { + fixMainSequenceTiming( xNode ); + } + else if( nEnum == EffectNodeType::INTERACTIVE_SEQUENCE ) + { + fixInteractiveSequenceTiming( xNode ); + } + } + break; + } + case AnimationNodeType::PAR: + // some other cut&paste... from AnimationImporter::importAnimationContainer() + break; + } + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt","OOX: exception raised in TimeNode::setNode()"); + } + } + + Reference< XAnimationNode > TimeNode::createAndInsert( + const XmlFilterBase& rFilter, + const OUString& rServiceName, + const Reference< XAnimationNode >& rxNode ) + { + try { + Reference< XAnimationNode > xNode( Reference<css::lang::XMultiServiceFactory>(rFilter.getComponentContext()->getServiceManager(), UNO_QUERY_THROW)->createInstance( rServiceName ), UNO_QUERY_THROW ); + Reference< XTimeContainer > xParentContainer( rxNode, UNO_QUERY_THROW ); + + xParentContainer->appendChild( xNode ); + return xNode; + } + catch( const Exception& ) + { + TOOLS_INFO_EXCEPTION("oox.ppt", "OOX: exception raised in TimeNode::createAndInsert() trying to create a service " << rServiceName); + } + + return Reference< XAnimationNode >(); + } + + void TimeNode::setId( sal_Int32 nId ) + { + msId = OUString::number(nId); + } + + void TimeNode::setTo( const Any & aTo ) + { + maNodeProperties[ NP_TO ] = aTo; + } + + void TimeNode::setFrom( const Any & aFrom ) + { + maNodeProperties[ NP_FROM ] = aFrom; + } + + void TimeNode::setBy( const Any & aBy ) + { + maNodeProperties[ NP_BY ] = aBy; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timenodelistcontext.cxx b/oox/source/ppt/timenodelistcontext.cxx new file mode 100644 index 0000000000..50d5c032f6 --- /dev/null +++ b/oox/source/ppt/timenodelistcontext.cxx @@ -0,0 +1,1049 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <oox/ppt/timenodelistcontext.hxx> + +#include <rtl/math.hxx> +#include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> + +#include <com/sun/star/animations/AnimationTransformType.hpp> +#include <com/sun/star/animations/AnimationCalcMode.hpp> +#include <com/sun/star/animations/AnimationColorSpace.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/ValuePair.hpp> +#include <com/sun/star/presentation/EffectCommands.hpp> +#include <com/sun/star/beans/NamedValue.hpp> + +#include <oox/helper/attributelist.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <drawingml/colorchoicecontext.hxx> +#include <oox/ppt/slidetransition.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <o3tl/string_view.hxx> +#include <utility> + +#include "animvariantcontext.hxx" +#include "commonbehaviorcontext.hxx" +#include "conditioncontext.hxx" +#include "commontimenodecontext.hxx" +#include "timeanimvaluecontext.hxx" +#include "animationtypes.hxx" +#include "timetargetelementcontext.hxx" + +using namespace ::oox::core; +using namespace ::oox::drawingml; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::xml::sax; +using ::com::sun::star::beans::NamedValue; + +namespace { + + oox::ppt::AnimationAttributeEnum getAttributeEnumByAPIName(std::u16string_view rAPIName) + { + oox::ppt::AnimationAttributeEnum eResult = oox::ppt::AnimationAttributeEnum::UNKNOWN; + const oox::ppt::ImplAttributeNameConversion *attrConv = oox::ppt::getAttributeConversionList(); + while(attrConv->mpAPIName != nullptr) + { + if(o3tl::equalsAscii(rAPIName, attrConv->mpAPIName)) + { + eResult = attrConv->meAttribute; + break; + } + attrConv++; + } + return eResult; + } + + bool convertAnimationValueWithTimeNode(const oox::ppt::TimeNodePtr& pNode, css::uno::Any &rAny) + { + css::uno::Any aAny = pNode->getNodeProperties()[oox::ppt::NP_ATTRIBUTENAME]; + OUString aNameList; + aAny >>= aNameList; + + // only get first token. + return oox::ppt::convertAnimationValue(getAttributeEnumByAPIName(o3tl::getToken(aNameList, 0, ';')), rAny); + } + + css::uno::Any convertPointPercent(const css::awt::Point& rPoint) + { + css::animations::ValuePair aPair; + // rPoint.X and rPoint.Y are in 1000th of a percent, but we only need ratio. + aPair.First <<= static_cast<double>(rPoint.X) / 100000.0; + aPair.Second <<= static_cast<double>(rPoint.Y) / 100000.0; + return Any(aPair); + } +} + +namespace oox::ppt { + + namespace { + + struct AnimColor + { + AnimColor(sal_Int16 cs, sal_Int32 o, sal_Int32 t, sal_Int32 th ) + : colorSpace( cs ), one( o ), two( t ), three( th ) + { + } + + Any get() const + { + sal_Int32 nColor; + Any aColor; + + switch( colorSpace ) + { + case AnimationColorSpace::HSL: + aColor <<= Sequence< double >{ one / 100000.0, two / 100000.0, three / 100000.0 }; + break; + case AnimationColorSpace::RGB: + nColor = ( ( ( one * 128 ) / 1000 ) & 0xff ) << 16 + | ( ( ( two * 128 ) / 1000 ) & 0xff ) << 8 + | ( ( ( three * 128 ) / 1000 ) & 0xff ); + aColor <<= nColor; + break; + default: + nColor = 0; + aColor <<= nColor; + break; + } + return aColor; + } + + sal_Int16 colorSpace; + sal_Int32 one; + sal_Int32 two; + sal_Int32 three; + }; + + /** CT_TLMediaNodeAudio + CT_TLMediaNodeVideo */ + class MediaNodeContext + : public TimeNodeContext + { + public: + MediaNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + , mbIsNarration( false ) + , mbFullScrn( false ) + , mbHideDuringShow(false) + { + AttributeList attribs( xAttribs ); + + switch( aElement ) + { + case PPT_TOKEN( audio ): + mbIsNarration = attribs.getBool( XML_isNarration, false ); + break; + case PPT_TOKEN( video ): + mbFullScrn = attribs.getBool( XML_fullScrn, false ); + break; + default: + break; + } + } + + virtual void onEndElement() override + { + sal_Int32 aElement = getCurrentElement(); + if( aElement == PPT_TOKEN( audio ) ) + { + mpNode->getNodeProperties()[NP_ISNARRATION] <<= mbIsNarration; + } + else if( aElement == PPT_TOKEN( video ) ) + { + // TODO deal with mbFullScrn + } + else if (aElement == PPT_TOKEN(cMediaNode)) + { + mpNode->getNodeProperties()[NP_HIDEDURINGSHOW] <<= mbHideDuringShow; + } + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cTn ): + return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode ); + case PPT_TOKEN( tgtEl ): + return new TimeTargetElementContext( *this, mpNode->getTarget() ); + case PPT_TOKEN(cMediaNode): + mbHideDuringShow = !rAttribs.getBool(XML_showWhenStopped, true); + break; + default: + break; + } + + return this; + } + + private: + bool mbIsNarration; + bool mbFullScrn; + bool mbHideDuringShow; + }; + + /** CT_TLSetBehavior + */ + class SetTimeNodeContext + : public TimeNodeContext + { + public: + SetTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + { + + } + + virtual ~SetTimeNodeContext() noexcept override + { + if(maTo.hasValue()) + { + convertAnimationValueWithTimeNode(mpNode, maTo); + mpNode->setTo(maTo); + } + + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( to ): + // CT_TLAnimVariant + return new AnimVariantContext( *this, aElementToken, maTo ); + default: + break; + } + + return this; + } + private: + Any maTo; + }; + + /** CT_TLCommandBehavior + */ + class CmdTimeNodeContext + : public TimeNodeContext + { + public: + CmdTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + , maType(0) + { + switch ( aElement ) + { + case PPT_TOKEN( cmd ): + msCommand = xAttribs->getOptionalValue( XML_cmd ); + maType = xAttribs->getOptionalValueToken( XML_type, 0 ); + break; + default: + break; + } + } + + virtual void onEndElement() override + { + if( !isCurrentElement( PPT_TOKEN( cmd ) ) ) + return; + + try { + // see sd/source/filter/ppt/pptinanimations.cxx + // in AnimationImporter::importCommandContainer() + // REFACTOR? + // a good chunk of this code has been copied verbatim *sigh* + sal_Int16 nCommand = EffectCommands::CUSTOM; + NamedValue aParamValue; + + switch( maType ) + { + case XML_verb: + aParamValue.Name = "Verb"; + // TODO make sure msCommand has what we want + aParamValue.Value <<= msCommand.toInt32(); + nCommand = EffectCommands::VERB; + break; + case XML_evt: + case XML_call: + if ( msCommand == "onstopaudio" ) + { + nCommand = EffectCommands::STOPAUDIO; + } + else if ( msCommand == "play" ) + { + nCommand = EffectCommands::PLAY; + } + else if (msCommand.startsWith("playFrom")) + { + std::u16string_view aMediaTime( msCommand.subView( 9, msCommand.getLength() - 10 ) ); + rtl_math_ConversionStatus eStatus; + double fMediaTime = ::rtl::math::stringToDouble( aMediaTime, u'.', u',', &eStatus ); + if( eStatus == rtl_math_ConversionStatus_Ok ) + { + aParamValue.Name = "MediaTime"; + aParamValue.Value <<= fMediaTime; + } + nCommand = EffectCommands::PLAY; + } + else if ( msCommand == "togglePause" ) + { + nCommand = EffectCommands::TOGGLEPAUSE; + } + else if ( msCommand == "stop" ) + { + nCommand = EffectCommands::STOP; + } + break; + } + mpNode->getNodeProperties()[ NP_COMMAND ] <<= nCommand; + if( nCommand == EffectCommands::CUSTOM ) + { + SAL_WARN("oox.ppt", "OOX: CmdTimeNodeContext::endFastElement(), unknown command!"); + aParamValue.Name = "UserDefined"; + aParamValue.Value <<= msCommand; + } + if( aParamValue.Value.hasValue() ) + { + Sequence< NamedValue > aParamSeq( &aParamValue, 1 ); + mpNode->getNodeProperties()[ NP_PARAMETER ] <<= aParamSeq; + } + } + catch( RuntimeException& ) + { + TOOLS_WARN_EXCEPTION("oox.ppt", "OOX: Exception in CmdTimeNodeContext::endFastElement()" ); + } + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + default: + break; + } + + return this; + } + + private: + OUString msCommand; + sal_Int32 maType; + }; + + /** CT_TLTimeNodeSequence + */ + class SequenceTimeNodeContext + : public TimeNodeContext + { + public: + SequenceTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + , mnNextAc(0) + , mnPrevAc(0) + { + AttributeList attribs(xAttribs); + mbConcurrent = attribs.getBool( XML_concurrent, false ); + mnNextAc = xAttribs->getOptionalValueToken( XML_nextAc, 0 ); + mnPrevAc = xAttribs->getOptionalValueToken( XML_prevAc, 0 ); + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cTn ): + return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode ); + case PPT_TOKEN( nextCondLst ): + return new CondListContext( *this, aElementToken, mpNode, mpNode->getNextCondition() ); + case PPT_TOKEN( prevCondLst ): + return new CondListContext( *this, aElementToken, mpNode, mpNode->getPrevCondition() ); + default: + break; + } + + return this; + } + private: + bool mbConcurrent; + sal_Int32 mnNextAc, mnPrevAc; + }; + + /** CT_TLTimeNodeParallel + * CT_TLTimeNodeExclusive + */ + class ParallelExclTimeNodeContext + : public TimeNodeContext + { + public: + ParallelExclTimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + { + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cTn ): + return new CommonTimeNodeContext( *this, aElementToken, rAttribs.getFastAttributeList(), mpNode ); + default: + break; + } + + return this; + } + + protected: + + }; + + /** CT_TLAnimateColorBehavior */ + class AnimColorContext + : public TimeNodeContext + { + public: + AnimColorContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) noexcept + : TimeNodeContext( rParent, aElement, pNode ) + , mnColorSpace( xAttribs->getOptionalValueToken( XML_clrSpc, 0 ) ) + , mnDir( xAttribs->getOptionalValueToken( XML_dir, 0 ) ) + , mbHasByColor( false ) + , m_byColor( AnimationColorSpace::RGB, 0, 0, 0) + { + } + + virtual void onEndElement() override + { + //xParentNode + if( !isCurrentElement( mnElement ) ) + return; + + NodePropertyMap & rProps(mpNode->getNodeProperties()); + rProps[ NP_DIRECTION ] <<= mnDir == XML_cw; + rProps[ NP_COLORINTERPOLATION ] <<= mnColorSpace == XML_hsl ? AnimationColorSpace::HSL : AnimationColorSpace::RGB; + const GraphicHelper& rGraphicHelper = getFilter().getGraphicHelper(); + if( maToClr.isUsed() ) + mpNode->setTo( Any( maToClr.getColor( rGraphicHelper ) ) ); + if( maFromClr.isUsed() ) + mpNode->setFrom( Any( maFromClr.getColor( rGraphicHelper ) ) ); + if( mbHasByColor ) + mpNode->setBy( m_byColor.get() ); + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( hsl ): + // CT_TLByHslColorTransform + { + if( mbHasByColor ) + { + m_byColor.colorSpace = AnimationColorSpace::HSL; + m_byColor.one = rAttribs.getInteger( XML_h, 0 ); + m_byColor.two = rAttribs.getInteger( XML_s, 0 ); + m_byColor.three = rAttribs.getInteger( XML_l, 0 ); + } + return this; + } + case PPT_TOKEN( rgb ): + { + if( mbHasByColor ) + { + // CT_TLByRgbColorTransform + m_byColor.colorSpace = AnimationColorSpace::RGB; + m_byColor.one = rAttribs.getInteger( XML_r, 0 ); + m_byColor.two = rAttribs.getInteger( XML_g, 0 ); + m_byColor.three = rAttribs.getInteger( XML_b, 0 ); + } + return this; + } + case PPT_TOKEN( by ): + // CT_TLByAnimateColorTransform + mbHasByColor = true; + return this; + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( to ): + // CT_Color + return new ColorContext( *this, maToClr ); + case PPT_TOKEN( from ): + // CT_Color + return new ColorContext( *this, maFromClr ); + + default: + break; + } + + return this; + } + + private: + sal_Int32 mnColorSpace; + sal_Int32 mnDir; + bool mbHasByColor; + AnimColor m_byColor; + oox::drawingml::Color maToClr; + oox::drawingml::Color maFromClr; + }; + + /** CT_TLAnimateBehavior */ + class AnimContext + : public TimeNodeContext + { + public: + AnimContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) noexcept + : TimeNodeContext( rParent, aElement, pNode ) + { + NodePropertyMap & aProps( pNode->getNodeProperties() ); + sal_Int32 nCalcMode = xAttribs->getOptionalValueToken( XML_calcmode, 0 ); + if(nCalcMode) + { + sal_Int16 nEnum = 0; + switch(nCalcMode) + { + case XML_discrete: + nEnum = AnimationCalcMode::DISCRETE; + break; + case XML_lin: + nEnum = AnimationCalcMode::LINEAR; + break; + case XML_fmla: + default: + // TODO what value is good ? + nEnum = AnimationCalcMode::DISCRETE; + break; + } + aProps[ NP_CALCMODE ] <<= nEnum; + } + + msFrom = xAttribs->getOptionalValue(XML_from); + msTo = xAttribs->getOptionalValue(XML_to); + msBy = xAttribs->getOptionalValue(XML_by); + + mnValueType = xAttribs->getOptionalValueToken( XML_valueType, 0 ); + } + + virtual ~AnimContext() noexcept override + { + if (!msFrom.isEmpty()) + { + css::uno::Any aAny; + aAny <<= msFrom; + convertAnimationValueWithTimeNode(mpNode, aAny); + mpNode->setFrom(aAny); + } + + if (!msTo.isEmpty()) + { + css::uno::Any aAny; + aAny <<= msTo; + convertAnimationValueWithTimeNode(mpNode, aAny); + mpNode->setTo(aAny); + } + + if (!msBy.isEmpty()) + { + css::uno::Any aAny; + aAny <<= msBy; + convertAnimationValueWithTimeNode(mpNode, aAny); + mpNode->setBy(aAny); + } + + int nKeyTimes = maTavList.size(); + if( nKeyTimes <= 0) + return; + + int i=0; + Sequence< double > aKeyTimes( nKeyTimes ); + auto pKeyTimes = aKeyTimes.getArray(); + Sequence< Any > aValues( nKeyTimes ); + auto pValues = aValues.getArray(); + + NodePropertyMap & aProps( mpNode->getNodeProperties() ); + for (auto const& tav : maTavList) + { + // TODO what to do if it is Timing_INFINITE ? + Any aTime = GetTimeAnimateValueTime( tav.msTime ); + aTime >>= pKeyTimes[i]; + pValues[i] = tav.maValue; + convertAnimationValueWithTimeNode(mpNode, pValues[i]); + + // Examine pptx documents and find that only the first tav + // has the formula set. The formula can be used for the whole. + if (!tav.msFormula.isEmpty()) + { + OUString sFormula = tav.msFormula; + (void)convertMeasure(sFormula); + aProps[NP_FORMULA] <<= sFormula; + } + + ++i; + } + aProps[ NP_VALUES ] <<= aValues; + aProps[ NP_KEYTIMES ] <<= aKeyTimes; + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( tavLst ): + return new TimeAnimValueListContext ( *this, maTavList ); + default: + break; + } + + return this; + } + private: + sal_Int32 mnValueType; + TimeAnimationValueList maTavList; + OUString msFrom; + OUString msTo; + OUString msBy; + }; + + /** CT_TLAnimateScaleBehavior */ + class AnimScaleContext + : public TimeNodeContext + { + public: + AnimScaleContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + : TimeNodeContext( rParent, aElement, pNode ) + , mbZoomContents( false ) + { + AttributeList attribs( xAttribs ); + // TODO what to do with mbZoomContents + mbZoomContents = attribs.getBool( XML_zoomContents, false ); + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + <<= sal_Int16(AnimationTransformType::SCALE); + } + + virtual void onEndElement() override + { + if( !isCurrentElement( mnElement ) ) + return; + + if( maTo.hasValue() ) + { + mpNode->setTo( maTo ); + } + if( maBy.hasValue() ) + { + mpNode->setBy( maBy ); + } + if( maFrom.hasValue() ) + { + mpNode->setFrom( maFrom ); + } + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( to ): + { + // CT_TLPoint + maTo = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList())); + return this; + } + case PPT_TOKEN( from ): + { + // CT_TLPoint + maFrom = convertPointPercent(GetPointPercent(rAttribs.getFastAttributeList())); + return this; + } + case PPT_TOKEN( by ): + { + // CT_TLPoint + css::awt::Point aPoint = GetPointPercent(rAttribs.getFastAttributeList()); + // We got ending values instead of offset values, so subtract 100% from them. + aPoint.X -= 100000; + aPoint.Y -= 100000; + maBy = convertPointPercent(aPoint); + return this; + } + default: + break; + } + + return this; + } + private: + Any maBy; + Any maFrom; + Any maTo; + bool mbZoomContents; + }; + + /** CT_TLAnimateRotationBehavior */ + class AnimRotContext + : public TimeNodeContext + { + public: + AnimRotContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) noexcept + : TimeNodeContext( rParent, aElement, pNode ) + { + AttributeList attribs( xAttribs ); + + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + <<= sal_Int16(AnimationTransformType::ROTATE); + // see also DFF_msofbtAnimateRotationData in + // sd/source/filter/ppt/pptinanimations.cxx + if(attribs.hasAttribute( XML_by ) ) + { + double fBy = attribs.getDouble( XML_by, 0.0 ) / PER_DEGREE; //1 PowerPoint-angle-unit = 1/60000 degree + pNode->setBy( Any( fBy ) ); + } + if(attribs.hasAttribute( XML_from ) ) + { + double fFrom = attribs.getDouble( XML_from, 0.0 ) / PER_DEGREE; + pNode->setFrom( Any( fFrom ) ); + } + if(attribs.hasAttribute( XML_to ) ) + { + double fTo = attribs.getDouble( XML_to, 0.0 ) / PER_DEGREE; + pNode->setTo( Any( fTo ) ); + } + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + default: + break; + } + + return this; + } + }; + + /** CT_TLAnimateMotionBehavior */ + class AnimMotionContext + : public TimeNodeContext + { + public: + AnimMotionContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) noexcept + : TimeNodeContext( rParent, aElement, pNode ) + { + pNode->getNodeProperties()[ NP_TRANSFORMTYPE ] + <<= sal_Int16(AnimationTransformType::TRANSLATE); + + AttributeList attribs( xAttribs ); + sal_Int32 nOrigin = xAttribs->getOptionalValueToken( XML_origin, 0 ); + if( nOrigin != 0 ) + { + switch(nOrigin) + { + case XML_layout: + case XML_parent: + break; + } + // TODO + } + + OUString aStr = xAttribs->getOptionalValue( XML_path ); + // E can appear inside a number, so we only check for its presence at the end + aStr = aStr.trim(); + if (aStr.endsWith("E")) + aStr = aStr.copy(0, aStr.getLength() - 1); + aStr = aStr.trim(); + pNode->getNodeProperties()[ NP_PATH ] <<= aStr; + mnPathEditMode = xAttribs->getOptionalValueToken( XML_pathEditMode, 0 ); + msPtsTypes = xAttribs->getOptionalValue( XML_ptsTypes ); + mnAngle = attribs.getInteger( XML_rAng, 0 ); + // TODO make sure the units are right. Likely not. + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( to ): + { + // CT_TLPoint + awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setTo( rAny ); + return this; + } + case PPT_TOKEN( from ): + { + // CT_TLPoint + awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setFrom( rAny ); + return this; + } + case PPT_TOKEN( by ): + { + // CT_TLPoint + awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() ); + Any rAny; + rAny <<= p.X; + rAny <<= p.Y; + mpNode->setBy( rAny ); + return this; + } + case PPT_TOKEN( rCtr ): + { + // CT_TLPoint + awt::Point p = GetPointPercent( rAttribs.getFastAttributeList() ); + // TODO push + (void)p; + return this; + } + default: + break; + } + + return this; + } + private: + OUString msPtsTypes; + sal_Int32 mnPathEditMode; + sal_Int32 mnAngle; + }; + + /** CT_TLAnimateEffectBehavior */ + class AnimEffectContext + : public TimeNodeContext + { + public: + AnimEffectContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) noexcept + : TimeNodeContext( rParent, aElement, pNode ) + { + sal_Int32 nDir = xAttribs->getOptionalValueToken( XML_transition, 0 ); + OUString sFilter = xAttribs->getOptionalValue( XML_filter ); + // TODO +// OUString sPrList = xAttribs->getOptionalValue( XML_prLst ); + + if( !sFilter.isEmpty() ) + { + SlideTransition aFilter( sFilter ); + aFilter.setMode( nDir != XML_out ); + pNode->setTransitionFilter( aFilter ); + } + } + + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/ ) override + { + switch ( aElementToken ) + { + case PPT_TOKEN( cBhvr ): + return new CommonBehaviorContext ( *this, mpNode ); + case PPT_TOKEN( progress ): + return new AnimVariantContext( *this, aElementToken, maProgress ); + // TODO handle it. + default: + break; + } + + return this; + } + private: + Any maProgress; + }; + + } + + rtl::Reference<TimeNodeContext> TimeNodeContext::makeContext( + FragmentHandler2 const & rParent, sal_Int32 aElement, + const Reference< XFastAttributeList >& xAttribs, + const TimeNodePtr & pNode ) + { + rtl::Reference<TimeNodeContext> pCtx; + switch( aElement ) + { + case PPT_TOKEN( animClr ): + pCtx = new AnimColorContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( par ): + pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode ); + break; + case PPT_TOKEN( seq ): + pCtx = new SequenceTimeNodeContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( excl ): + pCtx = new ParallelExclTimeNodeContext( rParent, aElement, pNode ); + break; + case PPT_TOKEN( anim ): + pCtx = new AnimContext ( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( animEffect ): + pCtx = new AnimEffectContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( animMotion ): + pCtx = new AnimMotionContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( animRot ): + pCtx = new AnimRotContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( animScale ): + pCtx = new AnimScaleContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( cmd ): + pCtx = new CmdTimeNodeContext( rParent, aElement, xAttribs, pNode ); + break; + case PPT_TOKEN( set ): + pCtx = new SetTimeNodeContext( rParent, aElement, pNode ); + break; + case PPT_TOKEN( audio ): + case PPT_TOKEN( video ): + pCtx = new MediaNodeContext( rParent, aElement, xAttribs, pNode ); + break; + default: + break; + } + return pCtx; + } + + TimeNodeContext::TimeNodeContext( FragmentHandler2 const & rParent, sal_Int32 aElement, + TimeNodePtr pNode ) noexcept + : FragmentHandler2( rParent ) + , mnElement( aElement ) + , mpNode(std::move( pNode )) + { + } + + TimeNodeContext::~TimeNodeContext( ) noexcept + { + + } + + TimeNodeListContext::TimeNodeListContext( FragmentHandler2 const & rParent, TimeNodePtrList & aList ) + noexcept + : FragmentHandler2( rParent ) + , maList( aList ) + { + } + + TimeNodeListContext::~TimeNodeListContext( ) noexcept + { + } + + ::oox::core::ContextHandlerRef TimeNodeListContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + sal_Int16 nNodeType; + + switch( aElementToken ) + { + case PPT_TOKEN( par ): + nNodeType = AnimationNodeType::PAR; + break; + case PPT_TOKEN( seq ): + nNodeType = AnimationNodeType::SEQ; + break; + case PPT_TOKEN( excl ): + // TODO pick the right type. We choose parallel for now as + // there does not seem to be an "Exclusive" + nNodeType = AnimationNodeType::PAR; + break; + case PPT_TOKEN( anim ): + nNodeType = AnimationNodeType::ANIMATE; + break; + case PPT_TOKEN( animClr ): + nNodeType = AnimationNodeType::ANIMATECOLOR; + break; + case PPT_TOKEN( animEffect ): + nNodeType = AnimationNodeType::TRANSITIONFILTER; + break; + case PPT_TOKEN( animMotion ): + nNodeType = AnimationNodeType::ANIMATEMOTION; + break; + case PPT_TOKEN( animRot ): + case PPT_TOKEN( animScale ): + nNodeType = AnimationNodeType::ANIMATETRANSFORM; + break; + case PPT_TOKEN( cmd ): + nNodeType = AnimationNodeType::COMMAND; + break; + case PPT_TOKEN( set ): + nNodeType = AnimationNodeType::SET; + break; + case PPT_TOKEN( audio ): + nNodeType = AnimationNodeType::AUDIO; + break; + case PPT_TOKEN( video ): + nNodeType = AnimationNodeType::AUDIO; + SAL_WARN("oox.ppt", "OOX: video requested, gave Audio instead" ); + break; + + default: + nNodeType = AnimationNodeType::CUSTOM; + SAL_INFO("oox.ppt", "unhandled token " << aElementToken); + break; + } + + TimeNodePtr pNode = std::make_shared<TimeNode>(nNodeType); + maList.push_back( pNode ); + rtl::Reference<FragmentHandler2> pContext = TimeNodeContext::makeContext( *this, aElementToken, rAttribs.getFastAttributeList(), pNode ); + + return pContext ? pContext : this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timetargetelementcontext.cxx b/oox/source/ppt/timetargetelementcontext.cxx new file mode 100644 index 0000000000..a4003ee1ad --- /dev/null +++ b/oox/source/ppt/timetargetelementcontext.cxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include "timetargetelementcontext.hxx" + +#include <osl/diagnose.h> +#include <sal/log.hxx> + +#include <oox/helper/attributelist.hxx> +#include <drawingml/embeddedwavaudiofile.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <avmedia/mediaitem.hxx> +#include <utility> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +namespace oox::ppt { + + namespace { + + // CT_TLShapeTargetElement + class ShapeTargetElementContext + : public FragmentHandler2 + { + public: + ShapeTargetElementContext( FragmentHandler2 const & rParent, ShapeTargetElement & aValue ) + : FragmentHandler2( rParent ) + , bTargetSet(false) + , maShapeTarget(aValue) + { + } + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override + { + switch( aElementToken ) + { + case PPT_TOKEN( bg ): + bTargetSet = true; + maShapeTarget.mnType = XML_bg; + return this; + case PPT_TOKEN( txEl ): + bTargetSet = true; + maShapeTarget.mnType = XML_txEl; + return this; + case PPT_TOKEN( subSp ): + bTargetSet = true; + maShapeTarget.mnType = XML_subSp; + maShapeTarget.msSubShapeId = rAttribs.getStringDefaulted( XML_spid); + return this; + case PPT_TOKEN( graphicEl ): + return this; // needs a:dgm for the target + case A_TOKEN( dgm ): + bTargetSet = true; + maShapeTarget.mnType = XML_dgm; + maShapeTarget.msSubShapeId = rAttribs.getStringDefaulted( XML_id); + return this; + case PPT_TOKEN( oleChartEl ): + bTargetSet = true; + // TODO + return this; + case PPT_TOKEN( charRg ): + case PPT_TOKEN( pRg ): + if( bTargetSet && maShapeTarget.mnType == XML_txEl ) + { + maShapeTarget.mnRangeType = getBaseToken( aElementToken ); + maShapeTarget.maRange = drawingml::GetIndexRange( rAttribs.getFastAttributeList() ); + } + return this; + default: + break; + } + return this; + } + + private: + bool bTargetSet; + ShapeTargetElement & maShapeTarget; + }; + + } + + TimeTargetElementContext::TimeTargetElementContext( FragmentHandler2 const & rParent, AnimTargetElementPtr pValue ) + : FragmentHandler2( rParent ), + mpTarget(std::move( pValue )) + { + OSL_ENSURE( mpTarget, "no valid target passed" ); + } + + TimeTargetElementContext::~TimeTargetElementContext( ) noexcept + { + } + + ::oox::core::ContextHandlerRef TimeTargetElementContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) + { + switch( aElementToken ) + { + case PPT_TOKEN( inkTgt ): + { + mpTarget->mnType = XML_inkTgt; + OUString aId = rAttribs.getStringDefaulted( XML_spid); + if( !aId.isEmpty() ) + { + mpTarget->msValue = aId; + } + return this; + } + case PPT_TOKEN( sldTgt ): + mpTarget->mnType = XML_sldTgt; + return this; + case PPT_TOKEN( sndTgt ): + { + mpTarget->mnType = XML_sndTgt; + +#if HAVE_FEATURE_AVMEDIA + OUString srcFile = drawingml::getEmbeddedWAVAudioFile(getRelations(), rAttribs); + Reference<css::io::XInputStream> + xInputStream = getFilter().openInputStream(srcFile); + + if (xInputStream.is()) + { + ::avmedia::EmbedMedia(getFilter().getModel(), srcFile, mpTarget->msValue, xInputStream); + xInputStream->closeInput(); + } +#endif + break; + } + case PPT_TOKEN( spTgt ): + { + mpTarget->mnType = XML_spTgt; + OUString aId = rAttribs.getStringDefaulted( XML_spid); + mpTarget->msValue = aId; + return new ShapeTargetElementContext( *this, mpTarget->maShapeTarget ); + } + default: + SAL_INFO( + "oox.ppt", + "unhandled tag " << getBaseToken(aElementToken) + << " in TL_TimeTargetElement"); + break; + } + + return this; + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/ppt/timetargetelementcontext.hxx b/oox/source/ppt/timetargetelementcontext.hxx new file mode 100644 index 0000000000..d420c9e735 --- /dev/null +++ b/oox/source/ppt/timetargetelementcontext.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_OOX_SOURCE_PPT_TIMETARGETELEMENTCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_PPT_TIMETARGETELEMENTCONTEXT_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/ppt/animationspersist.hxx> + +namespace oox::ppt { + + /** context CT_TLTimeTargetElement */ + class TimeTargetElementContext + : public ::oox::core::FragmentHandler2 + { + public: + TimeTargetElementContext( ::oox::core::FragmentHandler2 const & rParent, AnimTargetElementPtr aValue ); + virtual ~TimeTargetElementContext( ) noexcept override; + virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override; + + private: + AnimTargetElementPtr mpTarget; + }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |