/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "unopool.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Support creation of GraphicStorageHandler and EmbeddedObjectResolver #include #include #include #include #include "UnoDocumentSettings.hxx" #include #include #include #include #include #include #include #include "unolayer.hxx" #include #include "unocpres.hxx" #include "unoobj.hxx" #include #include "unopback.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::cppu; using namespace ::com::sun::star; using namespace ::sd; const TranslateId aTypeResIds[SdLinkTargetType::Count] = { STR_SD_PAGE, // SdLinkTargetType::Page STR_NOTES_MODE, // SdLinkTargetType::Notes STR_HANDOUT, // SdLinkTargetType::Handout STR_MASTERPAGE_NAME, // SdLinkTargetType::MasterPage }; TranslateId SdTPAction::GetClickActionSdResId( presentation::ClickAction eCA ) { switch( eCA ) { case presentation::ClickAction_NONE: return STR_CLICK_ACTION_NONE; case presentation::ClickAction_PREVPAGE: return STR_CLICK_ACTION_PREVPAGE; case presentation::ClickAction_NEXTPAGE: return STR_CLICK_ACTION_NEXTPAGE; case presentation::ClickAction_FIRSTPAGE: return STR_CLICK_ACTION_FIRSTPAGE; case presentation::ClickAction_LASTPAGE: return STR_CLICK_ACTION_LASTPAGE; case presentation::ClickAction_BOOKMARK: return STR_CLICK_ACTION_BOOKMARK; case presentation::ClickAction_DOCUMENT: return STR_CLICK_ACTION_DOCUMENT; case presentation::ClickAction_PROGRAM: return STR_CLICK_ACTION_PROGRAM; case presentation::ClickAction_MACRO: return STR_CLICK_ACTION_MACRO; case presentation::ClickAction_SOUND: return STR_CLICK_ACTION_SOUND; case presentation::ClickAction_VERB: return STR_CLICK_ACTION_VERB; case presentation::ClickAction_STOPPRESENTATION: return STR_CLICK_ACTION_STOPPRESENTATION; default: OSL_FAIL( "No StringResource for ClickAction available!" ); } return {}; } class SdUnoForbiddenCharsTable : public SvxUnoForbiddenCharsTable, public SfxListener { public: explicit SdUnoForbiddenCharsTable(SdrModel* pModel); virtual ~SdUnoForbiddenCharsTable() override; // SfxListener virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override; protected: virtual void onChange() override; private: SdrModel* mpModel; }; namespace { class SlideBackgroundInfo { public: SlideBackgroundInfo(const uno::Reference& xDrawPage, const uno::Reference& xMasterPage); bool slideHasOwnBackground() const { return mbIsCustom; } bool hasBackground() const { return bHasBackground; } bool isSolidColor() const { return mbIsSolidColor; } ::Color getFillColor() const; sal_Int32 getFillTransparency() const; OString getFillColorAsRGBA() const; private: bool getFillStyleImpl(const uno::Reference& xDrawPage); private: uno::Reference mxBackground; bool mbIsCustom; bool bHasBackground; bool mbIsSolidColor; drawing::FillStyle maFillStyle; }; SlideBackgroundInfo::SlideBackgroundInfo( const uno::Reference& xDrawPage, const uno::Reference& xMasterPage) : mbIsCustom(false) , bHasBackground(false) , mbIsSolidColor(false) , maFillStyle(drawing::FillStyle_NONE) { mbIsCustom = getFillStyleImpl(xDrawPage); bHasBackground = mbIsCustom; if (!bHasBackground) { bHasBackground = getFillStyleImpl(xMasterPage); } if (bHasBackground) { if (maFillStyle == drawing::FillStyle_SOLID) { OUString sGradientName; mxBackground->getPropertyValue("FillTransparenceGradientName") >>= sGradientName; if (sGradientName.isEmpty()) { mbIsSolidColor = true; } } } } sal_Int32 SlideBackgroundInfo::getFillTransparency() const { if (!mxBackground.is()) return 0; sal_Int32 nFillTransparency = 0; mxBackground->getPropertyValue("FillTransparence") >>= nFillTransparency; return nFillTransparency; } ::Color SlideBackgroundInfo::getFillColor() const { if (!mxBackground.is()) return {}; if (sal_Int32 nFillColor; mxBackground->getPropertyValue("FillColor") >>= nFillColor) { return ::Color(ColorTransparency, nFillColor & 0xffffff); } return {}; } OString SlideBackgroundInfo::getFillColorAsRGBA() const { ::Color aColor = getFillColor(); OString sColor = aColor.AsRGBHEXString().toUtf8(); sal_uInt32 nAlpha = std::round((100 - getFillTransparency()) * 255 / 100.0); std::stringstream ss; ss << std::hex << std::uppercase << std::setfill ('0') << std::setw(2) << nAlpha; sColor += ss.str().c_str(); return sColor; } bool SlideBackgroundInfo::getFillStyleImpl(const uno::Reference& xDrawPage) { if( xDrawPage.is() ) { uno::Reference< beans::XPropertySet > xPropSet( xDrawPage, uno::UNO_QUERY ); if( xPropSet.is() ) { uno::Reference< beans::XPropertySet > xBackground; if (xPropSet->getPropertySetInfo()->hasPropertyByName("Background")) xPropSet->getPropertyValue( "Background" ) >>= xBackground; if( xBackground.is() ) { drawing::FillStyle aFillStyle; if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle ) { maFillStyle = aFillStyle; if (aFillStyle != drawing::FillStyle_NONE) { mxBackground = std::move(xBackground); return true; } } } } } return false; } using namespace ::css::animations; using namespace ::css::beans; using namespace ::css::container; using namespace ::css::uno; using namespace ::xmloff::token; using namespace ::css::presentation; template constexpr auto mapEnumToString(std::pair const (&items)[N]) { return frozen::make_unordered_map(items); } constexpr auto constTransitionTypeToString = mapEnumToString({ { animations::TransitionType::BARWIPE, "BarWipe" }, // Wipe { animations::TransitionType::PINWHEELWIPE, "PineWheelWipe" }, // Wheel { animations::TransitionType::SLIDEWIPE, "SlideWipe" }, // Cover, Uncover { animations::TransitionType::RANDOMBARWIPE, "RandomBarWipe" }, // Bars { animations::TransitionType::CHECKERBOARDWIPE, "CheckerBoardWipe" }, // Checkers { animations::TransitionType::FOURBOXWIPE, "FourBoxWipe" }, // Shape { animations::TransitionType::IRISWIPE, "IrisWipe" }, // Box { animations::TransitionType::FANWIPE, "FanWipe" }, // Wedge { animations::TransitionType::BLINDSWIPE, "BlindWipe"}, // Venetian { animations::TransitionType::FADE, "Fade"}, { animations::TransitionType::DISSOLVE, "Dissolve"}, { animations::TransitionType::PUSHWIPE, "PushWipe"}, // Comb { animations::TransitionType::ELLIPSEWIPE, "EllipseWipe"}, // Shape { animations::TransitionType::BARNDOORWIPE, "BarnDoorWipe"}, // Split { animations::TransitionType::WATERFALLWIPE, "WaterfallWipe"}, // Diagonal { animations::TransitionType::MISCSHAPEWIPE, "MiscShapeWipe"}, { animations::TransitionType::ZOOM, "Zoom"} }); constexpr auto constTransitionSubTypeToString = mapEnumToString({ { animations::TransitionSubType::LEFTTORIGHT, "LeftToRight" }, { animations::TransitionSubType::TOPTOBOTTOM, "TopToBottom" }, { animations::TransitionSubType::EIGHTBLADE, "8Blade" }, { animations::TransitionSubType::FOURBLADE, "4Blade" }, { animations::TransitionSubType::THREEBLADE, "3Blade" }, { animations::TransitionSubType::TWOBLADEVERTICAL, "2BladeVertical" }, { animations::TransitionSubType::ONEBLADE, "1Blade" }, { animations::TransitionSubType::FROMTOPLEFT, "FromTopLeft" }, { animations::TransitionSubType::FROMTOPRIGHT, "FromTopRight"}, { animations::TransitionSubType::FROMBOTTOMLEFT, "FromBottomLeft"}, { animations::TransitionSubType::FROMBOTTOMRIGHT, "FromBottomRight"}, { animations::TransitionSubType::VERTICAL, "Vertical"}, { animations::TransitionSubType::HORIZONTAL, "Horizontal"}, { animations::TransitionSubType::DOWN, "Down"}, { animations::TransitionSubType::ACROSS, "Across"}, { animations::TransitionSubType::CORNERSOUT, "CornersOut"}, { animations::TransitionSubType::DIAMOND, "Diamond"}, { animations::TransitionSubType::CIRCLE, "Circle"}, { animations::TransitionSubType::RECTANGLE, "Rectangle"}, { animations::TransitionSubType::CENTERTOP, "CenterTop"}, { animations::TransitionSubType::CROSSFADE, "CrossFade"}, { animations::TransitionSubType::FADEOVERCOLOR, "FadeOverColor"}, { animations::TransitionSubType::FROMLEFT, "FromLeft"}, { animations::TransitionSubType::FROMRIGHT, "FromRight"}, { animations::TransitionSubType::FROMTOP, "FromTop"}, { animations::TransitionSubType::HORIZONTALLEFT, "HorizontalLeft"}, { animations::TransitionSubType::HORIZONTALRIGHT, "HorizontalRight"}, { animations::TransitionSubType::COMBVERTICAL, "CombVertical"}, { animations::TransitionSubType::COMBHORIZONTAL, "CombHorizontal"}, { animations::TransitionSubType::TOPLEFT, "TopLeft"}, { animations::TransitionSubType::TOPRIGHT, "TopRight"}, { animations::TransitionSubType::BOTTOMRIGHT, "BottomRight"}, { animations::TransitionSubType::BOTTOMLEFT, "BottomLeft"}, { animations::TransitionSubType::TOPCENTER, "TopCenter"}, { animations::TransitionSubType::RIGHTCENTER, "RightCenter"}, { animations::TransitionSubType::BOTTOMCENTER, "BottomCenter"}, { animations::TransitionSubType::FANOUTHORIZONTAL, "FanOutHorizontal"}, { animations::TransitionSubType::CORNERSIN, "CornersIn"}, { animations::TransitionSubType::HEART, "Heart"}, { animations::TransitionSubType::ROTATEIN, "RotateIn"} }); constexpr auto constAnimationNodeTypeToString = mapEnumToString({ { AnimationNodeType::ANIMATE, "Animate" }, { AnimationNodeType::ANIMATECOLOR, "AnimateColor" }, { AnimationNodeType::ANIMATEMOTION, "Animate" }, { AnimationNodeType::ANIMATEPHYSICS, "Animate" }, { AnimationNodeType::ANIMATETRANSFORM, "AnimateTransform" }, { AnimationNodeType::AUDIO, "Audio" }, { AnimationNodeType::COMMAND, "Command" }, { AnimationNodeType::CUSTOM, "Custom" }, { AnimationNodeType::ITERATE, "Iterate" }, { AnimationNodeType::PAR, "Par" }, { AnimationNodeType::SEQ, "Seq" }, { AnimationNodeType::SET, "Set" }, { AnimationNodeType::TRANSITIONFILTER, "TransitionFilter" }, }); constexpr auto constFillToString = mapEnumToString({ { AnimationFill::DEFAULT, "Default" }, { AnimationFill::REMOVE, "Remove" }, { AnimationFill::FREEZE, "Freeze" }, { AnimationFill::HOLD, "Hold" }, { AnimationFill::TRANSITION, "Transition" }, { AnimationFill::AUTO, "Auto" }, }); constexpr auto constRestartToString = mapEnumToString({ { AnimationRestart::DEFAULT, "Default" }, { AnimationRestart::ALWAYS, "Always" }, { AnimationRestart::WHEN_NOT_ACTIVE, "WhenNotActive" }, { AnimationRestart::NEVER, "Never" }, }); constexpr auto constEndSyncToString = mapEnumToString({ { AnimationEndSync::FIRST, "First" }, { AnimationEndSync::LAST, "Last" }, { AnimationEndSync::ALL, "All" }, { AnimationEndSync::MEDIA, "Media" }, }); constexpr auto constCalcModeToString = mapEnumToString({ { AnimationCalcMode::DISCRETE, "Discrete" }, { AnimationCalcMode::LINEAR, "Linear" }, { AnimationCalcMode::PACED, "Paced" }, { AnimationCalcMode::SPLINE, "Spline" }, }); constexpr auto constAdditiveModeToString = mapEnumToString({ { AnimationAdditiveMode::BASE, "Base" }, { AnimationAdditiveMode::SUM, "Sum" }, { AnimationAdditiveMode::REPLACE, "Replace" }, { AnimationAdditiveMode::MULTIPLY, "Multiply" }, { AnimationAdditiveMode::NONE, "None" }, }); constexpr auto constEffectPresetClassToString = mapEnumToString({ { EffectPresetClass::CUSTOM, "Custom" }, { EffectPresetClass::ENTRANCE, "Entrance" }, { EffectPresetClass::EXIT, "Exit" }, { EffectPresetClass::EMPHASIS, "Emphasis" }, { EffectPresetClass::MOTIONPATH, "MotionPath" }, { EffectPresetClass::OLEACTION, "OleAction" }, { EffectPresetClass::MEDIACALL, "MediaCall" }, }); constexpr auto constEffectNodeTypeToString = mapEnumToString({ { EffectNodeType::DEFAULT, "Default" }, { EffectNodeType::ON_CLICK, "OnClick" }, { EffectNodeType::WITH_PREVIOUS, "WithPrevious" }, { EffectNodeType::AFTER_PREVIOUS, "AfterPrevious" }, { EffectNodeType::MAIN_SEQUENCE, "MainSequence" }, { EffectNodeType::TIMING_ROOT, "TimingRoot" }, { EffectNodeType::INTERACTIVE_SEQUENCE, "InteractiveSequence" }, }); constexpr auto constEventTriggerToString = mapEnumToString({ { EventTrigger::BEGIN_EVENT, "BeginEvent" }, { EventTrigger::END_EVENT, "EndEvent" }, { EventTrigger::NONE, "None" }, { EventTrigger::ON_BEGIN, "OnBegin" }, { EventTrigger::ON_CLICK, "OnClick" }, { EventTrigger::ON_DBL_CLICK, "OnDblClick" }, { EventTrigger::ON_END, "OnEnd" }, { EventTrigger::ON_MOUSE_ENTER, "OnMouseEnter" }, { EventTrigger::ON_MOUSE_LEAVE, "OnMouseLeave" }, { EventTrigger::ON_NEXT, "OnNext" }, { EventTrigger::ON_PREV, "OnPrev" }, { EventTrigger::ON_STOP_AUDIO, "OnStopAudio" }, { EventTrigger::REPEAT, "Repeat" }, }); constexpr auto constTimingToString = mapEnumToString({ { Timing_INDEFINITE, "indefinite" }, { Timing_MEDIA, "media" }, }); constexpr auto constTransformTypeToString = mapEnumToString({ { AnimationTransformType::TRANSLATE, "Translate" }, { AnimationTransformType::SCALE, "Scale" }, { AnimationTransformType::ROTATE, "Rotate" }, { AnimationTransformType::SKEWX, "SkewX" }, { AnimationTransformType::SKEWY, "SkewY" }, }); constexpr auto constSubItemToString = mapEnumToString({ { ShapeAnimationSubType::AS_WHOLE, "AsWhole" }, { ShapeAnimationSubType::ONLY_BACKGROUND, "OnlyBackground" }, { ShapeAnimationSubType::ONLY_TEXT, "OnlyText" }, }); constexpr auto constIterateTypeToString = mapEnumToString({ { TextAnimationType::BY_PARAGRAPH, "ByParagraph" }, { TextAnimationType::BY_WORD, "ByWord" }, { TextAnimationType::BY_LETTER, "ByLetter" }, }); constexpr auto constFillStyleToString = mapEnumToString({ { drawing::FillStyle_NONE, "None" }, { drawing::FillStyle_SOLID, "Solid" }, { drawing::FillStyle_BITMAP, "Bitmap" }, { drawing::FillStyle_GRADIENT, "Gradient" }, { drawing::FillStyle_HATCH, "Hatch" }, }); constexpr auto constLineStyleToString = mapEnumToString({ { drawing::LineStyle_NONE, "None" }, { drawing::LineStyle_SOLID, "Solid" }, { drawing::LineStyle_DASH, "Dash" }, }); constexpr auto constAttributeNameToXMLEnum = frozen::make_unordered_map({ { "X", XML_X }, { "Y", XML_Y }, { "Width", XML_WIDTH }, { "Height", XML_HEIGHT }, { "Rotate", XML_ROTATE }, { "SkewX", XML_SKEWX }, { "FillColor", XML_FILL_COLOR }, { "FillStyle", XML_FILL }, { "LineColor", XML_STROKE_COLOR }, { "LineStyle",XML_STROKE }, { "CharColor", XML_COLOR }, { "CharRotation", XML_TEXT_ROTATION_ANGLE }, { "CharWeight", XML_FONT_WEIGHT }, { "CharUnderline", XML_TEXT_UNDERLINE }, { "CharFontName", XML_FONT_FAMILY }, { "CharHeight", XML_FONT_SIZE }, { "CharPosture", XML_FONT_STYLE }, { "Visibility", XML_VISIBILITY }, { "Opacity", XML_OPACITY }, { "DimColor", XML_DIM }, }); class AnimationsExporter { public: AnimationsExporter(::tools::JsonWriter& rWriter, const Reference& xDrawPage); void exportAnimations(); [[nodiscard]] bool hasEffects() const { return mbHasEffects; } private: void exportNode(const Reference& xNode); void exportNodeImpl(const Reference& xNode); void exportContainer(const Reference& xContainer); void exportAnimate(const Reference& xAnimate); void convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, const Any& rValue) const; static void convertTarget(OStringBuffer& sTmp, const Any& rTarget); static Reference getParagraphTarget( const ParagraphTarget& pTarget ); void convertTiming(OStringBuffer& sTmp, const Any& rValue) const; private: ::tools::JsonWriter& mrWriter; Reference mxDrawPage; Reference mxPageProps; Reference mxRootNode; bool mbHasEffects; }; AnimationsExporter::AnimationsExporter(::tools::JsonWriter& rWriter, const Reference& xDrawPage) : mrWriter(rWriter) , mxDrawPage(xDrawPage) , mbHasEffects(false) { if (!mxDrawPage.is()) return; try { mxPageProps = Reference(xDrawPage, UNO_QUERY); if (!mxPageProps.is()) return; Reference xAnimNodeSupplier(mxDrawPage, UNO_QUERY); if (!xAnimNodeSupplier.is()) return; Reference xRootNode = xAnimNodeSupplier->getAnimationNode(); if (xRootNode.is()) { // first check if there are no animations Reference xEnumerationAccess(xRootNode, UNO_QUERY_THROW); Reference xEnumeration(xEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW); if (xEnumeration->hasMoreElements()) { // first child node may be an empty main sequence, check this Reference xMainNode(xEnumeration->nextElement(), UNO_QUERY_THROW); Reference xMainEnumerationAccess(xMainNode, UNO_QUERY_THROW); Reference xMainEnumeration( xMainEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW); // only export if the main sequence is not empty or if there are additional // trigger sequences mbHasEffects = xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements(); } } if (mbHasEffects) mxRootNode = std::move(xRootNode); } catch (const RuntimeException&) { TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); } } template constexpr bool convertEnum(OStringBuffer& rBuffer, EnumT nValue, const frozen::unordered_map& rMap) { auto iterator = rMap.find(nValue); if (iterator == rMap.end()) return false; rBuffer.append(iterator->second); return true; } void convertDouble(OStringBuffer& rBuffer, double fValue) { ::rtl::math::doubleToStringBuffer(rBuffer, fValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); } void convertBool(OStringBuffer& rBuffer, bool bValue) { rBuffer.append( bValue ); } void convertPath(OStringBuffer& sTmp, const Any& rPath) { OUString aStr; rPath >>= aStr; sTmp = aStr.toUtf8(); } void convertColor(OStringBuffer& rBuffer, sal_Int32 nColor) { OUStringBuffer aUBuffer; ::sax::Converter::convertColor(aUBuffer, nColor); rBuffer.append(aUBuffer.makeStringAndClear().toUtf8()); } void convertColor(OStringBuffer& rBuffer, const Any& rValue) { sal_Int32 nColor = 0; if (rValue >>= nColor) { convertColor(rBuffer, nColor); } else { Sequence aHSL; if ((rValue >>= aHSL) && (aHSL.getLength() == 3)) { rBuffer.append("hsl(" + OString::number(aHSL[0]) + "," + OString::number(aHSL[1] * 100.0) + "%," + OString::number(aHSL[2] * 100.0) + "%)"); } } } bool isValidNode(const Reference& xNode) { if (xNode.is()) { sal_Int16 nNodeType = xNode->getType(); auto iterator = constAnimationNodeTypeToString.find(nNodeType); return iterator != constAnimationNodeTypeToString.end(); } return false; } void AnimationsExporter::exportAnimations() { if (!mxDrawPage.is() || !mxPageProps.is() || !mxRootNode.is() || !hasEffects()) return; if (isValidNode(mxRootNode)) { auto aNode = mrWriter.startNode("root"); exportNodeImpl(mxRootNode); } } void AnimationsExporter::exportNode(const Reference& xNode) { if (!isValidNode(xNode)) return; auto aStruct = mrWriter.startStruct(); exportNodeImpl(xNode); } void AnimationsExporter::exportNodeImpl(const Reference& xNode) { try { std::string sId = GetInterfaceHash(xNode); mrWriter.put("id", sId); sal_Int16 nNodeType = xNode->getType(); auto iterator = constAnimationNodeTypeToString.find(nNodeType); assert(iterator != constAnimationNodeTypeToString.end() && "must be previously checked with isValidNode"); mrWriter.put("nodeName", iterator->second); // common properties OStringBuffer sTmp; Any aTemp; double fTemp = 0; sal_Int16 nTemp; aTemp = xNode->getBegin(); if (aTemp.hasValue()) { convertTiming(sTmp, aTemp); mrWriter.put("begin", sTmp.makeStringAndClear()); } aTemp = xNode->getDuration(); if (aTemp.hasValue()) { if (aTemp >>= fTemp) { convertDouble(sTmp, fTemp); sTmp.append('s'); mrWriter.put("dur", sTmp.makeStringAndClear()); } else { Timing eTiming; if (aTemp >>= eTiming) { mrWriter.put("dur", eTiming == Timing_INDEFINITE ? "indefinite" : "media"); } } } aTemp = xNode->getEnd(); if (aTemp.hasValue()) { convertTiming(sTmp, aTemp); mrWriter.put("end", sTmp.makeStringAndClear()); } nTemp = xNode->getFill(); if (nTemp != AnimationFill::DEFAULT) { convertEnum(sTmp, nTemp, constFillToString); mrWriter.put("fill", sTmp.makeStringAndClear()); } nTemp = xNode->getFillDefault(); if (nTemp != AnimationFill::INHERIT) { convertEnum(sTmp, nTemp, constFillToString); mrWriter.put("fillDefault", sTmp.makeStringAndClear()); } nTemp = xNode->getRestart(); if (nTemp != AnimationRestart::DEFAULT) { convertEnum(sTmp, nTemp, constRestartToString); mrWriter.put("restart", sTmp.makeStringAndClear()); } nTemp = xNode->getRestartDefault(); if (nTemp != AnimationRestart::INHERIT) { convertEnum(sTmp, nTemp, constRestartToString); mrWriter.put("restartDefault", sTmp.makeStringAndClear()); } fTemp = xNode->getAcceleration(); if (fTemp != 0.0) { convertDouble(sTmp, fTemp); mrWriter.put("accelerate", sTmp.makeStringAndClear()); } fTemp = xNode->getDecelerate(); if (fTemp != 0.0) { convertDouble(sTmp, fTemp); mrWriter.put("decelerate", sTmp.makeStringAndClear()); } bool bTemp = xNode->getAutoReverse(); if (bTemp) { convertBool(sTmp, bTemp); mrWriter.put("autoreverse", sTmp.makeStringAndClear()); } aTemp = xNode->getRepeatCount(); if (aTemp.hasValue()) { Timing eTiming; if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE)) { mrWriter.put("repeatCount", "indefinite"); } else if (aTemp >>= fTemp) { convertDouble(sTmp, fTemp); mrWriter.put("repeatCount", sTmp.makeStringAndClear()); } } aTemp = xNode->getRepeatDuration(); if (aTemp.hasValue()) { Timing eTiming; if ((aTemp >>= eTiming) && (eTiming == Timing_INDEFINITE)) { mrWriter.put("repeatDur", "indefinite"); } else if (aTemp >>= fTemp) { convertDouble(sTmp, fTemp); mrWriter.put("repeatDur", sTmp.makeStringAndClear()); } } aTemp = xNode->getEndSync(); if (aTemp.hasValue() && (aTemp >>= nTemp)) { convertEnum(sTmp, nTemp, constEndSyncToString); mrWriter.put("endSync", sTmp.makeStringAndClear()); } sal_Int16 nContainerNodeType = EffectNodeType::DEFAULT; const Sequence aUserData(xNode->getUserData()); for (const auto& rValue : aUserData) { if (IsXMLToken(rValue.Name, XML_NODE_TYPE)) { if ((rValue.Value >>= nContainerNodeType) && (nContainerNodeType != EffectNodeType::DEFAULT)) { convertEnum(sTmp, nContainerNodeType, constEffectNodeTypeToString); mrWriter.put("nodeType", sTmp.makeStringAndClear()); } } else if (IsXMLToken(rValue.Name, XML_PRESET_ID)) { OUString aPresetId; if (rValue.Value >>= aPresetId) { mrWriter.put("presetId", aPresetId); } } else if (IsXMLToken(rValue.Name, XML_PRESET_SUB_TYPE)) { OUString aPresetSubType; if (rValue.Value >>= aPresetSubType) { mrWriter.put("presetSubType", aPresetSubType); } } else if (IsXMLToken(rValue.Name, XML_PRESET_CLASS)) { sal_Int16 nEffectPresetClass = sal_uInt16(0); if (rValue.Value >>= nEffectPresetClass) { convertEnum(sTmp, nEffectPresetClass, constEffectPresetClassToString); mrWriter.put("presetClass", sTmp.makeStringAndClear()); } } else if (IsXMLToken(rValue.Name, XML_MASTER_ELEMENT)) { Reference xMaster; rValue.Value >>= xMaster; if (xMaster.is()) { const std::string& rIdentifier(GetInterfaceHash(xMaster)); if (!rIdentifier.empty()) mrWriter.put("masterElement", rIdentifier); } } else if (IsXMLToken(rValue.Name, XML_GROUP_ID)) { sal_Int32 nGroupId = 0; if (rValue.Value >>= nGroupId) mrWriter.put("groupId", nGroupId); } else { OUString aTmp; if (rValue.Value >>= aTmp) mrWriter.put(rValue.Name, aTmp); } } switch (nNodeType) { case AnimationNodeType::PAR: case AnimationNodeType::SEQ: case AnimationNodeType::ITERATE: { Reference xContainer(xNode, UNO_QUERY_THROW); exportContainer(xContainer); } break; case AnimationNodeType::ANIMATE: case AnimationNodeType::SET: case AnimationNodeType::ANIMATEMOTION: case AnimationNodeType::ANIMATEPHYSICS: case AnimationNodeType::ANIMATECOLOR: case AnimationNodeType::ANIMATETRANSFORM: case AnimationNodeType::TRANSITIONFILTER: { Reference xAnimate(xNode, UNO_QUERY_THROW); exportAnimate(xAnimate); } break; case AnimationNodeType::AUDIO: { SAL_WARN("sd", "AnimationsExporter::exportNode(): Audio Node not supported."); } break; case AnimationNodeType::COMMAND: { SAL_WARN("sd", "AnimationsExporter::exportNode(): Command Node not supported."); } break; default: { OSL_FAIL( "sd unomodel: AnimationsExporter::exportNode(), invalid AnimationNodeType!"); } } } catch (const RuntimeException&) { TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); } } Reference AnimationsExporter::getParagraphTarget(const ParagraphTarget& pTarget) { try { Reference xParaEnumAccess(pTarget.Shape, UNO_QUERY_THROW); Reference xEnumeration(xParaEnumAccess->createEnumeration(), css::uno::UNO_SET_THROW); sal_Int32 nParagraph = pTarget.Paragraph; while (xEnumeration->hasMoreElements()) { Reference xRef(xEnumeration->nextElement(), UNO_QUERY); if (nParagraph-- == 0) return xRef; } } catch (const RuntimeException&) { TOOLS_WARN_EXCEPTION("sd", "AnimationsExporter::getParagraphTarget"); } Reference xRef; return xRef; } void AnimationsExporter::convertTarget(OStringBuffer& sTmp, const Any& rTarget) { if (!rTarget.hasValue()) return; Reference xRef; if (!(rTarget >>= xRef)) { if (auto pt = o3tl::tryAccess(rTarget)) { xRef = getParagraphTarget(*pt); } } SAL_WARN_IF(!xRef.is(), "sd", "AnimationsExporter::convertTarget(), invalid target type!"); if (xRef.is()) { const std::string& rIdentifier(GetInterfaceHash(xRef)); if (!rIdentifier.empty()) sTmp.append(rIdentifier); } } void AnimationsExporter::convertTiming(OStringBuffer& sTmp, const Any& rValue) const { if (!rValue.hasValue()) return; if (auto pSequence = o3tl::tryAccess>(rValue)) { const sal_Int32 nLength = pSequence->getLength(); sal_Int32 nElement; const Any* pAny = pSequence->getConstArray(); OStringBuffer sTmp2; for (nElement = 0; nElement < nLength; nElement++, pAny++) { if (!sTmp.isEmpty()) sTmp.append(';'); convertTiming(sTmp2, *pAny); sTmp.append(sTmp2); sTmp2.setLength(0); } } else if (auto x = o3tl::tryAccess(rValue)) { sTmp.append(*x); sTmp.append('s'); } else if (auto pTiming = o3tl::tryAccess(rValue)) { const auto svTiming = (*pTiming == Timing_MEDIA) ? constTimingToString.at(Timing_MEDIA) : constTimingToString.at(Timing_INDEFINITE); sTmp.append(svTiming); } else if (auto pEvent = o3tl::tryAccess(rValue)) { OStringBuffer sTmp2; if (pEvent->Trigger != EventTrigger::NONE) { if (pEvent->Source.hasValue()) { convertTarget(sTmp, pEvent->Source); sTmp.append('.'); } convertEnum(sTmp2, pEvent->Trigger, constEventTriggerToString); sTmp.append(sTmp2); sTmp2.setLength(0); } if (pEvent->Offset.hasValue()) { convertTiming(sTmp2, pEvent->Offset); if (!sTmp.isEmpty()) sTmp.append('+'); sTmp.append(sTmp2); sTmp2.setLength(0); } } else { OSL_FAIL("sd.unomodel: AnimationsExporter::convertTiming, invalid value type!"); } } void AnimationsExporter::convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, const Any& rValue) const { if (!rValue.hasValue()) return; if (auto pValuePair = o3tl::tryAccess(rValue)) { OStringBuffer sTmp2; convertValue(eAttributeName, sTmp, pValuePair->First); sTmp.append(','); convertValue(eAttributeName, sTmp2, pValuePair->Second); sTmp.append(sTmp2); } else if (auto pSequence = o3tl::tryAccess>(rValue)) { const sal_Int32 nLength = pSequence->getLength(); sal_Int32 nElement; const Any* pAny = pSequence->getConstArray(); OStringBuffer sTmp2; for (nElement = 0; nElement < nLength; nElement++, pAny++) { if (!sTmp.isEmpty()) sTmp.append(';'); convertValue(eAttributeName, sTmp2, *pAny); sTmp.append(sTmp2); sTmp2.setLength(0); } } else { switch (eAttributeName) { case XML_X: case XML_Y: case XML_WIDTH: case XML_HEIGHT: case XML_ANIMATETRANSFORM: case XML_ANIMATEMOTION: case XML_ANIMATEPHYSICS: { if (auto sValue = o3tl::tryAccess(rValue)) { sTmp.append(sValue->toUtf8()); } else if (auto aValue = o3tl::tryAccess(rValue)) { sTmp.append(*aValue); } else { OSL_FAIL("sd::AnimationsExporter::convertValue(), invalid value type!"); } return; } case XML_SKEWX: case XML_ROTATE: case XML_OPACITY: case XML_TRANSITIONFILTER: if (auto aValue = o3tl::tryAccess(rValue)) { sTmp.append(*aValue); } break; case XML_TEXT_ROTATION_ANGLE: if (auto aValue = o3tl::tryAccess(rValue)) { // on win and armv7 platforms compiler complains // that append(sal_Int16) is ambiguous sTmp.append(static_cast(*aValue)); } break; case XML_FILL_COLOR: case XML_STROKE_COLOR: case XML_DIM: case XML_COLOR: { convertColor(sTmp, rValue); } break; case XML_FILL: if (auto aValue = o3tl::tryAccess(rValue)) { convertEnum(sTmp, *aValue, constFillStyleToString); } break; case XML_STROKE: if (auto aValue = o3tl::tryAccess(rValue)) { convertEnum(sTmp, *aValue, constLineStyleToString); } break; case XML_FONTSIZE: if (auto aValue = o3tl::tryAccess(rValue)) { double fValue = *aValue * 100; fValue += fValue > 0 ? 0.5 : -0.5; auto nValue = static_cast(fValue); sTmp.append(nValue); // percent } break; case XML_FONT_WEIGHT: case XML_FONT_STYLE: case XML_TEXT_UNDERLINE: SAL_WARN("sd", "AnimationsExporter::convertValue(): value type " << GetXMLToken(eAttributeName) << " not supported"); break; case XML_VISIBILITY: if (auto aValue = o3tl::tryAccess(rValue)) { OUString sValue = *aValue ? GetXMLToken(XML_VISIBLE) : GetXMLToken(XML_HIDDEN); sTmp.append(sValue.toUtf8()); } break; default: OSL_FAIL("unomodel: AnimationsExporter::convertValue(), invalid AttributeName!"); } } } void AnimationsExporter::exportContainer(const Reference& xContainer) { try { const sal_Int32 nNodeType = xContainer->getType(); if (nNodeType == AnimationNodeType::ITERATE) { OStringBuffer sTmp; Reference xIter(xContainer, UNO_QUERY_THROW); Any aTemp(xIter->getTarget()); if (aTemp.hasValue()) { convertTarget(sTmp, aTemp); mrWriter.put("targetElement", sTmp.makeStringAndClear()); } sal_Int16 nTemp = xIter->getSubItem(); if (nTemp) { convertEnum(sTmp, nTemp, constSubItemToString); mrWriter.put("subItem", sTmp.makeStringAndClear()); } nTemp = xIter->getIterateType(); if (nTemp) { convertEnum(sTmp, nTemp, constIterateTypeToString); mrWriter.put("iterateType", sTmp.makeStringAndClear()); } double fTemp = xIter->getIterateInterval(); if (fTemp != 0) { OUStringBuffer buf; ::sax::Converter::convertDuration(buf, fTemp / (24 * 60 * 60)); mrWriter.put("iterateInterval", sTmp.makeStringAndClear()); } } auto anArray = mrWriter.startArray("children"); Reference xEnumerationAccess(xContainer, UNO_QUERY_THROW); Reference xEnumeration(xEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW); while (xEnumeration->hasMoreElements()) { Reference xChildNode(xEnumeration->nextElement(), UNO_QUERY_THROW); exportNode(xChildNode); } } catch (const RuntimeException&) { TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); } } void AnimationsExporter::exportAnimate(const Reference& xAnimate) { try { const sal_Int16 nNodeType = xAnimate->getType(); OStringBuffer sTmp; sal_Int16 nTemp; bool bTemp; Any aTemp(xAnimate->getTarget()); if (aTemp.hasValue()) { convertTarget(sTmp, aTemp); mrWriter.put("targetElement", sTmp.makeStringAndClear()); } nTemp = xAnimate->getSubItem(); if (nTemp) { convertEnum(sTmp, nTemp, constSubItemToString); mrWriter.put("subItem", sTmp.makeStringAndClear()); } XMLTokenEnum eAttributeName = XML_TOKEN_INVALID; if (nNodeType == AnimationNodeType::TRANSITIONFILTER) { eAttributeName = XML_TRANSITIONFILTER; } else if (nNodeType == AnimationNodeType::ANIMATETRANSFORM) { eAttributeName = XML_ANIMATETRANSFORM; } else if (nNodeType == AnimationNodeType::ANIMATEMOTION) { eAttributeName = XML_ANIMATEMOTION; } else if (nNodeType == AnimationNodeType::ANIMATEPHYSICS) { eAttributeName = XML_ANIMATEPHYSICS; } else { OString sTemp(xAnimate->getAttributeName().toUtf8()); if (!sTemp.isEmpty()) { auto iterator = constAttributeNameToXMLEnum.find(sTemp); if (iterator != constAttributeNameToXMLEnum.end()) { eAttributeName = iterator->second; mrWriter.put("attributeName", sTemp); } else { mrWriter.put("attributeName", "invalid"); } } } Sequence aValues(xAnimate->getValues()); if (aValues.hasElements()) { aTemp <<= aValues; convertValue(eAttributeName, sTmp, aTemp); mrWriter.put("values", sTmp.makeStringAndClear()); } else { aTemp = xAnimate->getFrom(); if (aTemp.hasValue()) { convertValue(eAttributeName, sTmp, aTemp); mrWriter.put("from", sTmp.makeStringAndClear()); } aTemp = xAnimate->getBy(); if (aTemp.hasValue()) { convertValue(eAttributeName, sTmp, aTemp); mrWriter.put("by", sTmp.makeStringAndClear()); } aTemp = xAnimate->getTo(); if (aTemp.hasValue()) { convertValue(eAttributeName, sTmp, aTemp); mrWriter.put("to", sTmp.makeStringAndClear()); } } if (nNodeType != AnimationNodeType::SET) { const Sequence aKeyTimes(xAnimate->getKeyTimes()); if (aKeyTimes.hasElements()) { for (const auto& rKeyTime : aKeyTimes) { if (!sTmp.isEmpty()) sTmp.append(';'); sTmp.append(rKeyTime); } mrWriter.put("keyTimes", sTmp.makeStringAndClear()); } OUString sTemp(xAnimate->getFormula()); if (!sTemp.isEmpty()) { mrWriter.put("formula", sTemp); } if ((nNodeType != AnimationNodeType::TRANSITIONFILTER) && (nNodeType != AnimationNodeType::AUDIO)) { // calcMode = "discrete | linear | paced | spline" nTemp = xAnimate->getCalcMode(); if (((nNodeType == AnimationNodeType::ANIMATEMOTION) && (nTemp != AnimationCalcMode::PACED)) || ((nNodeType != AnimationNodeType::ANIMATEMOTION) && (nTemp != AnimationCalcMode::LINEAR))) { convertEnum(sTmp, nTemp, constCalcModeToString); mrWriter.put("calcMode", sTmp.makeStringAndClear()); } bTemp = xAnimate->getAccumulate(); if (bTemp) { mrWriter.put("accumulate", "sum"); } nTemp = xAnimate->getAdditive(); if (nTemp != AnimationAdditiveMode::REPLACE) { convertEnum(sTmp, nTemp, constAdditiveModeToString); mrWriter.put("additive", sTmp.makeStringAndClear()); } } const Sequence aTimeFilter(xAnimate->getTimeFilter()); if (aTimeFilter.hasElements()) { for (const auto& rPair : aTimeFilter) { if (!sTmp.isEmpty()) sTmp.append(';'); sTmp.append(OString::number(rPair.Time) + "," + OString::number(rPair.Progress)); } mrWriter.put("keySplines", sTmp.makeStringAndClear()); } } switch (nNodeType) { case AnimationNodeType::ANIMATEMOTION: { Reference xAnimateMotion(xAnimate, UNO_QUERY_THROW); aTemp = xAnimateMotion->getPath(); if (aTemp.hasValue()) { convertPath(sTmp, aTemp); mrWriter.put("path", sTmp.makeStringAndClear()); } } break; case AnimationNodeType::ANIMATEPHYSICS: { SAL_WARN( "sd", "unomodel: AnimationsExporter::exportAnimate(): AnimatePhysics not supported"); } break; case AnimationNodeType::ANIMATECOLOR: { Reference xAnimateColor(xAnimate, UNO_QUERY_THROW); nTemp = xAnimateColor->getColorInterpolation(); mrWriter.put("colorInterpolation", (nTemp == AnimationColorSpace::RGB) ? "rgb" : "hsl"); bTemp = xAnimateColor->getDirection(); mrWriter.put("colorInterpolationDirection", bTemp ? "clockwise" : "counterClockwise"); } break; case AnimationNodeType::ANIMATETRANSFORM: { mrWriter.put("attributeName", "transform"); Reference xTransform(xAnimate, UNO_QUERY_THROW); nTemp = xTransform->getTransformType(); convertEnum(sTmp, nTemp, constTransformTypeToString); mrWriter.put("transformType", sTmp.makeStringAndClear()); } break; case AnimationNodeType::TRANSITIONFILTER: { Reference xTransitionFilter(xAnimate, UNO_QUERY); sal_Int16 nTransition = xTransitionFilter->getTransition(); convertEnum(sTmp, nTransition, constTransitionTypeToString); mrWriter.put("transitionType", sTmp.makeStringAndClear()); sal_Int16 nSubtype = xTransitionFilter->getSubtype(); if (nSubtype != TransitionSubType::DEFAULT) { convertEnum(sTmp, nSubtype, constTransitionSubTypeToString); mrWriter.put("transitionSubType", sTmp.makeStringAndClear()); } bTemp = xTransitionFilter->getMode(); if (!bTemp) mrWriter.put("transitionMode", "out"); bTemp = xTransitionFilter->getDirection(); if (!bTemp) mrWriter.put("transitionDirection", "reverse"); if ((nTransition == TransitionType::FADE) && ((nSubtype == TransitionSubType::FADETOCOLOR) || (nSubtype == TransitionSubType::FADEFROMCOLOR))) { sal_Int32 nColor = xTransitionFilter->getFadeColor(); convertColor(sTmp, nColor); mrWriter.put("transitionFadeColor", sTmp.makeStringAndClear()); } } break; default: { SAL_WARN("sd", "unomodel: AnimationsExporter::exportAnimate(): not supported node type: " << nNodeType); } } } catch (const Exception&) { TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); } } } // end anonymous namespace SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel ) : SvxUnoForbiddenCharsTable( pModel->GetForbiddenCharsTable() ), mpModel( pModel ) { StartListening( *pModel ); } void SdUnoForbiddenCharsTable::onChange() { if( mpModel ) { mpModel->ReformatAllTextObjects(); } } SdUnoForbiddenCharsTable::~SdUnoForbiddenCharsTable() { SolarMutexGuard g; if( mpModel ) EndListening( *mpModel ); } void SdUnoForbiddenCharsTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept { if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) return; const SdrHint* pSdrHint = static_cast( &rHint ); if( SdrHintKind::ModelCleared == pSdrHint->GetKind() ) { mpModel = nullptr; } } const sal_uInt16 WID_MODEL_LANGUAGE = 1; const sal_uInt16 WID_MODEL_TABSTOP = 2; const sal_uInt16 WID_MODEL_VISAREA = 3; const sal_uInt16 WID_MODEL_MAPUNIT = 4; const sal_uInt16 WID_MODEL_FORBCHARS = 5; const sal_uInt16 WID_MODEL_CONTFOCUS = 6; const sal_uInt16 WID_MODEL_DSGNMODE = 7; const sal_uInt16 WID_MODEL_BASICLIBS = 8; const sal_uInt16 WID_MODEL_RUNTIMEUID = 9; const sal_uInt16 WID_MODEL_BUILDID = 10; const sal_uInt16 WID_MODEL_HASVALIDSIGNATURES = 11; const sal_uInt16 WID_MODEL_DIALOGLIBS = 12; const sal_uInt16 WID_MODEL_FONTS = 13; const sal_uInt16 WID_MODEL_INTEROPGRABBAG = 14; const sal_uInt16 WID_MODEL_THEME = 15; const sal_uInt16 WID_MODEL_ALLOWLINKUPDATE = 16; static const SvxItemPropertySet* ImplGetDrawModelPropertySet() { // Attention: the first parameter HAS TO BE sorted!!! const static SfxItemPropertyMapEntry aDrawModelPropertyMap_Impl[] = { { u"BuildId"_ustr, WID_MODEL_BUILDID, ::cppu::UnoType::get(), 0, 0}, { sUNO_Prop_CharLocale, WID_MODEL_LANGUAGE, ::cppu::UnoType::get(), 0, 0}, { sUNO_Prop_TabStop, WID_MODEL_TABSTOP, ::cppu::UnoType::get(), 0, 0}, { sUNO_Prop_VisibleArea, WID_MODEL_VISAREA, ::cppu::UnoType::get(), 0, 0}, { sUNO_Prop_MapUnit, WID_MODEL_MAPUNIT, ::cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_ForbiddenCharacters, WID_MODEL_FORBCHARS, cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_AutomContFocus, WID_MODEL_CONTFOCUS, cppu::UnoType::get(), 0, 0}, { sUNO_Prop_ApplyFrmDsgnMode, WID_MODEL_DSGNMODE, cppu::UnoType::get(), 0, 0}, { u"BasicLibraries"_ustr, WID_MODEL_BASICLIBS, cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { u"DialogLibraries"_ustr, WID_MODEL_DIALOGLIBS, cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_RuntimeUID, WID_MODEL_RUNTIMEUID, ::cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_HasValidSignatures, WID_MODEL_HASVALIDSIGNATURES, ::cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_AllowLinkUpdate, WID_MODEL_ALLOWLINKUPDATE, ::cppu::UnoType::get(), beans::PropertyAttribute::READONLY, 0}, { u"Fonts"_ustr, WID_MODEL_FONTS, cppu::UnoType>::get(), beans::PropertyAttribute::READONLY, 0}, { sUNO_Prop_InteropGrabBag, WID_MODEL_INTEROPGRABBAG, cppu::UnoType>::get(), 0, 0}, { sUNO_Prop_Theme, WID_MODEL_THEME, cppu::UnoType::get(), 0, 0}, }; static SvxItemPropertySet aDrawModelPropertySet_Impl( aDrawModelPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); return &aDrawModelPropertySet_Impl; } // this ctor is used from the DocShell SdXImpressDocument::SdXImpressDocument(::sd::DrawDocShell* pShell, bool bClipBoard) : SfxBaseModel( pShell ), mpDocShell( pShell ), mpDoc( pShell ? pShell->GetDoc() : nullptr ), mbDisposed(false), mbImpressDoc( pShell && pShell->GetDoc() && pShell->GetDoc()->GetDocumentType() == DocumentType::Impress ), mbClipBoard( bClipBoard ), mpPropSet( ImplGetDrawModelPropertySet() ), mbPaintTextEdit( true ) { if( mpDoc ) { StartListening( *mpDoc ); } else { OSL_FAIL("DocShell is invalid"); } } SdXImpressDocument::SdXImpressDocument(SdDrawDocument* pDoc, bool bClipBoard) : SfxBaseModel( nullptr ), mpDocShell( nullptr ), mpDoc( pDoc ), mbDisposed(false), mbImpressDoc( pDoc && pDoc->GetDocumentType() == DocumentType::Impress ), mbClipBoard( bClipBoard ), mpPropSet( ImplGetDrawModelPropertySet() ), mbPaintTextEdit( true ) { if( mpDoc ) { StartListening( *mpDoc ); } else { OSL_FAIL("SdDrawDocument is invalid"); } } /*********************************************************************** * * ***********************************************************************/ SdXImpressDocument::~SdXImpressDocument() noexcept { } // XInterface uno::Any SAL_CALL SdXImpressDocument::queryInterface( const uno::Type & rType ) { uno::Any aAny; if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (rType == cppu::UnoType::get()) aAny <<= uno::Reference(this); else if (mbImpressDoc && rType == cppu::UnoType::get()) aAny <<= uno::Reference< presentation::XPresentationSupplier >(this); else if (mbImpressDoc && rType == cppu::UnoType::get()) aAny <<= uno::Reference< presentation::XCustomPresentationSupplier >(this); else return SfxBaseModel::queryInterface(rType); return aAny; } void SAL_CALL SdXImpressDocument::acquire() noexcept { SfxBaseModel::acquire(); } void SAL_CALL SdXImpressDocument::release() noexcept { if (osl_atomic_decrement( &m_refCount ) != 0) return; // restore reference count: osl_atomic_increment( &m_refCount ); if(!mbDisposed) { try { dispose(); } catch (const uno::RuntimeException&) { // don't break throw () TOOLS_WARN_EXCEPTION( "sd", "" ); } } SfxBaseModel::release(); } // XUnoTunnel const css::uno::Sequence< sal_Int8 > & SdXImpressDocument::getUnoTunnelId() noexcept { static const comphelper::UnoIdInit theSdXImpressDocumentUnoTunnelId; return theSdXImpressDocumentUnoTunnelId.getSeq(); } sal_Int64 SAL_CALL SdXImpressDocument::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier ) { if (comphelper::isUnoTunnelId(rIdentifier)) return comphelper::getSomething_cast(mpDoc); return comphelper::getSomethingImpl(rIdentifier, this, comphelper::FallbackToGetSomethingOf{}); } // XTypeProvider uno::Sequence< uno::Type > SAL_CALL SdXImpressDocument::getTypes( ) { ::SolarMutexGuard aGuard; if( !maTypeSequence.hasElements() ) { uno::Sequence< uno::Type > aTypes( SfxBaseModel::getTypes() ); aTypes = comphelper::concatSequences(aTypes, uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() }); if( mbImpressDoc ) { aTypes = comphelper::concatSequences(aTypes, uno::Sequence { cppu::UnoType::get(), cppu::UnoType::get(), cppu::UnoType::get() }); } maTypeSequence = std::move(aTypes); } return maTypeSequence; } uno::Sequence< sal_Int8 > SAL_CALL SdXImpressDocument::getImplementationId( ) { return css::uno::Sequence(); } /*********************************************************************** * * ***********************************************************************/ void SdXImpressDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { if( mpDoc ) { if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint) { const SdrHint* pSdrHint = static_cast( &rHint ); if( hasEventListeners() ) { document::EventObject aEvent; if( SvxUnoDrawMSFactory::createEvent( mpDoc, pSdrHint, aEvent ) ) notifyEvent( aEvent ); } if( pSdrHint->GetKind() == SdrHintKind::ModelCleared ) { if( mpDoc ) EndListening( *mpDoc ); mpDoc = nullptr; mpDocShell = nullptr; } } else { // did our SdDrawDocument just died? if(rHint.GetId() == SfxHintId::Dying) { // yes, so we ask for a new one if( mpDocShell ) { SdDrawDocument *pNewDoc = mpDocShell->GetDoc(); // is there a new one? if( pNewDoc != mpDoc ) { mpDoc = pNewDoc; if(mpDoc) StartListening( *mpDoc ); } } } } } SfxBaseModel::Notify( rBC, rHint ); } /****************************************************************************** * * ******************************************************************************/ SdPage* SdXImpressDocument::InsertSdPage( sal_uInt16 nPage, bool bDuplicate ) { sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PageKind::Standard ); SdrLayerAdmin& rLayerAdmin = mpDoc->GetLayerAdmin(); SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background); SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects); rtl::Reference pStandardPage; if( 0 == nPageCount ) { // this is only used for clipboard where we only have one page pStandardPage = mpDoc->AllocSdPage(false); Size aDefSize(21000, 29700); // A4 portrait orientation pStandardPage->SetSize( aDefSize ); mpDoc->InsertPage(pStandardPage.get(), 0); } else { // here we determine the page after which we should insert SdPage* pPreviousStandardPage = mpDoc->GetSdPage( std::min( static_cast(nPageCount - 1), nPage ), PageKind::Standard ); SdrLayerIDSet aVisibleLayers = pPreviousStandardPage->TRG_GetMasterPageVisibleLayers(); bool bIsPageBack = aVisibleLayers.IsSet( aBckgrnd ); bool bIsPageObj = aVisibleLayers.IsSet( aBckgrndObj ); // AutoLayouts must be ready mpDoc->StopWorkStartupDelay(); /* First we create a standard page and then a notes page. It is guaranteed, that after a standard page the corresponding notes page follows. */ sal_uInt16 nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2; SdPage* pPreviousNotesPage = static_cast( mpDoc->GetPage( nStandardPageNum - 1 ) ); sal_uInt16 nNotesPageNum = nStandardPageNum + 1; /************************************************************** * standard page **************************************************************/ if( bDuplicate ) pStandardPage = static_cast( pPreviousStandardPage->CloneSdrPage(*mpDoc).get() ); else pStandardPage = mpDoc->AllocSdPage(false); pStandardPage->SetSize( pPreviousStandardPage->GetSize() ); pStandardPage->SetBorder( pPreviousStandardPage->GetLeftBorder(), pPreviousStandardPage->GetUpperBorder(), pPreviousStandardPage->GetRightBorder(), pPreviousStandardPage->GetLowerBorder() ); pStandardPage->SetOrientation( pPreviousStandardPage->GetOrientation() ); pStandardPage->SetName(OUString()); // insert page after current page mpDoc->InsertPage(pStandardPage.get(), nStandardPageNum); if( !bDuplicate ) { // use MasterPage of the current page pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage()); pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() ); pStandardPage->SetAutoLayout(AUTOLAYOUT_NONE, true ); } aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background); aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects); aVisibleLayers.Set(aBckgrnd, bIsPageBack); aVisibleLayers.Set(aBckgrndObj, bIsPageObj); pStandardPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); /************************************************************** * notes page **************************************************************/ rtl::Reference pNotesPage; if( bDuplicate ) pNotesPage = static_cast( pPreviousNotesPage->CloneSdrPage(*mpDoc).get() ); else pNotesPage = mpDoc->AllocSdPage(false); pNotesPage->SetSize( pPreviousNotesPage->GetSize() ); pNotesPage->SetBorder( pPreviousNotesPage->GetLeftBorder(), pPreviousNotesPage->GetUpperBorder(), pPreviousNotesPage->GetRightBorder(), pPreviousNotesPage->GetLowerBorder() ); pNotesPage->SetOrientation( pPreviousNotesPage->GetOrientation() ); pNotesPage->SetName(OUString()); pNotesPage->SetPageKind(PageKind::Notes); // insert page after current page mpDoc->InsertPage(pNotesPage.get(), nNotesPageNum); if( !bDuplicate ) { // use MasterPage of the current page pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage()); pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() ); pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true ); } } SetModified(); return pStandardPage.get(); } void SdXImpressDocument::SetModified() noexcept { if( mpDoc ) mpDoc->SetChanged(); } // XModel void SAL_CALL SdXImpressDocument::lockControllers( ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); mpDoc->setLock(true); } void SAL_CALL SdXImpressDocument::unlockControllers( ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); if( mpDoc->isLocked() ) { mpDoc->setLock(false); } } sal_Bool SAL_CALL SdXImpressDocument::hasControllersLocked( ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); return mpDoc->isLocked(); } uno::Reference < container::XIndexAccess > SAL_CALL SdXImpressDocument::getViewData() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() ); if( !xRet.is() ) { const std::vector> &rList = mpDoc->GetFrameViewList(); if( !rList.empty() ) { xRet = new comphelper::IndexedPropertyValuesContainer(); uno::Reference < container::XIndexContainer > xCont( xRet, uno::UNO_QUERY ); DBG_ASSERT( xCont.is(), "SdXImpressDocument::getViewData() failed for OLE object" ); if( xCont.is() ) { for( sal_uInt32 i = 0, n = rList.size(); i < n; i++ ) { ::sd::FrameView* pFrameView = rList[ i ].get(); uno::Sequence< beans::PropertyValue > aSeq; pFrameView->WriteUserDataSequence( aSeq ); xCont->insertByIndex( i, uno::Any( aSeq ) ); } } } } return xRet; } void SAL_CALL SdXImpressDocument::setViewData( const uno::Reference < container::XIndexAccess >& xData ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); SfxBaseModel::setViewData( xData ); if( !(mpDocShell && (mpDocShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED) && xData.is()) ) return; const sal_Int32 nCount = xData->getCount(); std::vector> &rViews = mpDoc->GetFrameViewList(); rViews.clear(); uno::Sequence< beans::PropertyValue > aSeq; for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) { if( xData->getByIndex( nIndex ) >>= aSeq ) { std::unique_ptr<::sd::FrameView> pFrameView(new ::sd::FrameView( mpDoc )); pFrameView->ReadUserDataSequence( aSeq ); rViews.push_back( std::move(pFrameView) ); } } } // XDrawPageDuplicator uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::duplicate( const uno::Reference< drawing::XDrawPage >& xPage ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); // get pPage from xPage and determine the Id (nPos ) afterwards SvxDrawPage* pSvxPage = comphelper::getFromUnoTunnel( xPage ); if( pSvxPage ) { SdPage* pPage = static_cast( pSvxPage->GetSdrPage() ); sal_uInt16 nPos = pPage->GetPageNum(); nPos = ( nPos - 1 ) / 2; pPage = InsertSdPage( nPos, true ); if( pPage ) { uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); return xDrawPage; } } uno::Reference< drawing::XDrawPage > xDrawPage; return xDrawPage; } // XDrawPagesSupplier uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getDrawPages() { ::SolarMutexGuard aGuard; return getSdDrawPages(); } rtl::Reference< SdDrawPagesAccess > SdXImpressDocument::getSdDrawPages() { if( nullptr == mpDoc ) throw lang::DisposedException(); rtl::Reference< SdDrawPagesAccess > xDrawPages( mxDrawPagesAccess ); if( !xDrawPages.is() ) { initializeDocument(); xDrawPages = new SdDrawPagesAccess(*this); mxDrawPagesAccess = xDrawPages.get(); } return xDrawPages; } // XMasterPagesSupplier uno::Reference< drawing::XDrawPages > SAL_CALL SdXImpressDocument::getMasterPages() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); rtl::Reference< SdMasterPagesAccess > xMasterPages( mxMasterPagesAccess ); if( !xMasterPages.is() ) { if ( !hasControllersLocked() ) initializeDocument(); xMasterPages = new SdMasterPagesAccess(*this); mxMasterPagesAccess = xMasterPages.get(); } return xMasterPages; } // XLayerManagerSupplier uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLayerManager( ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager ); if( !xLayerManager.is() ) { xLayerManager = new SdLayerManager(*this); mxLayerManager = xLayerManager.get(); } return xLayerManager; } // XCustomPresentationSupplier uno::Reference< container::XNameContainer > SAL_CALL SdXImpressDocument::getCustomPresentations() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); rtl::Reference< SdXCustomPresentationAccess > xCustomPres( mxCustomPresentationAccess ); if( !xCustomPres.is() ) { xCustomPres = new SdXCustomPresentationAccess(*this); mxCustomPresentationAccess = xCustomPres.get(); } return xCustomPres; } // XPresentationSupplier uno::Reference< presentation::XPresentation > SAL_CALL SdXImpressDocument::getPresentation() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); return mpDoc->getPresentation(); } // XHandoutMasterSupplier uno::Reference< drawing::XDrawPage > SAL_CALL SdXImpressDocument::getHandoutMasterPage() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); uno::Reference< drawing::XDrawPage > xPage; initializeDocument(); SdPage* pPage = mpDoc->GetMasterSdPage(0, PageKind::Handout); if (pPage) xPage.set(pPage->getUnoPage(), uno::UNO_QUERY); return xPage; } // XMultiServiceFactory ( SvxFmMSFactory ) css::uno::Reference SdXImpressDocument::create( OUString const & aServiceSpecifier, OUString const & referer) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); if( aServiceSpecifier == "com.sun.star.drawing.DashTable" ) { if( !mxDashTable.is() ) mxDashTable = SvxUnoDashTable_createInstance( mpDoc ); return mxDashTable; } if( aServiceSpecifier == "com.sun.star.drawing.GradientTable" ) { if( !mxGradientTable.is() ) mxGradientTable = SvxUnoGradientTable_createInstance( mpDoc ); return mxGradientTable; } if( aServiceSpecifier == "com.sun.star.drawing.HatchTable" ) { if( !mxHatchTable.is() ) mxHatchTable = SvxUnoHatchTable_createInstance( mpDoc ); return mxHatchTable; } if( aServiceSpecifier == "com.sun.star.drawing.BitmapTable" ) { if( !mxBitmapTable.is() ) mxBitmapTable = SvxUnoBitmapTable_createInstance( mpDoc ); return mxBitmapTable; } if( aServiceSpecifier == "com.sun.star.drawing.TransparencyGradientTable" ) { if( !mxTransGradientTable.is() ) mxTransGradientTable = SvxUnoTransGradientTable_createInstance( mpDoc ); return mxTransGradientTable; } if( aServiceSpecifier == "com.sun.star.drawing.MarkerTable" ) { if( !mxMarkerTable.is() ) mxMarkerTable = SvxUnoMarkerTable_createInstance( mpDoc ); return mxMarkerTable; } if( aServiceSpecifier == "com.sun.star.text.NumberingRules" ) { return uno::Reference< uno::XInterface >( SvxCreateNumRule( mpDoc ), uno::UNO_QUERY ); } if( aServiceSpecifier == "com.sun.star.drawing.Background" ) { return uno::Reference< uno::XInterface >( static_cast(new SdUnoPageBackground( mpDoc ))); } if( aServiceSpecifier == "com.sun.star.drawing.Defaults" ) { if( !mxDrawingPool.is() ) mxDrawingPool = SdUnoCreatePool( mpDoc ); return mxDrawingPool; } if ( aServiceSpecifier == sUNO_Service_ImageMapRectangleObject ) { return SvUnoImageMapRectangleObject_createInstance( ImplGetSupportedMacroItems() ); } if ( aServiceSpecifier == sUNO_Service_ImageMapCircleObject ) { return SvUnoImageMapCircleObject_createInstance( ImplGetSupportedMacroItems() ); } if ( aServiceSpecifier == sUNO_Service_ImageMapPolygonObject ) { return SvUnoImageMapPolygonObject_createInstance( ImplGetSupportedMacroItems() ); } if( aServiceSpecifier == "com.sun.star.document.Settings" || ( !mbImpressDoc && ( aServiceSpecifier == "com.sun.star.drawing.DocumentSettings" ) ) || ( mbImpressDoc && ( aServiceSpecifier == "com.sun.star.presentation.DocumentSettings" ) ) ) { return sd::DocumentSettings_createInstance( this ); } if( aServiceSpecifier == "com.sun.star.text.TextField.DateTime" || aServiceSpecifier == "com.sun.star.text.textfield.DateTime" ) { return static_cast(new SvxUnoTextField( text::textfield::Type::DATE )); } if( aServiceSpecifier == "com.sun.star.presentation.TextField.Header" || aServiceSpecifier == "com.sun.star.presentation.textfield.Header" ) { return static_cast(new SvxUnoTextField( text::textfield::Type::PRESENTATION_HEADER )); } if( aServiceSpecifier == "com.sun.star.presentation.TextField.Footer" || aServiceSpecifier == "com.sun.star.presentation.textfield.Footer" ) { return static_cast(new SvxUnoTextField( text::textfield::Type::PRESENTATION_FOOTER )); } if( aServiceSpecifier == "com.sun.star.presentation.TextField.DateTime" || aServiceSpecifier == "com.sun.star.presentation.textfield.DateTime" ) { return static_cast(new SvxUnoTextField( text::textfield::Type::PRESENTATION_DATE_TIME )); } if( aServiceSpecifier == "com.sun.star.text.TextField.PageName" || aServiceSpecifier == "com.sun.star.text.textfield.PageName" ) { return static_cast(new SvxUnoTextField( text::textfield::Type::PAGE_NAME )); } if (aServiceSpecifier == "com.sun.star.text.TextField.DocInfo.Custom" || aServiceSpecifier == "com.sun.star.text.textfield.DocInfo.Custom") { return static_cast(new SvxUnoTextField(text::textfield::Type::DOCINFO_CUSTOM)); } if( aServiceSpecifier == "com.sun.star.xml.NamespaceMap" ) { static sal_uInt16 aWhichIds[] = { SDRATTR_XMLATTRIBUTES, EE_CHAR_XMLATTRIBS, EE_PARA_XMLATTRIBS, 0 }; return svx::NamespaceMap_createInstance( aWhichIds, &mpDoc->GetItemPool() ); } // Support creation of GraphicStorageHandler and EmbeddedObjectResolver if (aServiceSpecifier == "com.sun.star.document.ExportGraphicStorageHandler") { return static_cast(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Write )); } if (aServiceSpecifier == "com.sun.star.document.ImportGraphicStorageHandler") { return static_cast(new SvXMLGraphicHelper( SvXMLGraphicHelperMode::Read )); } if( aServiceSpecifier == "com.sun.star.document.ExportEmbeddedObjectResolver" ) { comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist(); if( nullptr == pPersist ) throw lang::DisposedException(); return static_cast(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Write )); } if( aServiceSpecifier == "com.sun.star.document.ImportEmbeddedObjectResolver" ) { comphelper::IEmbeddedHelper* pPersist = mpDoc->GetPersist(); if( nullptr == pPersist ) throw lang::DisposedException(); return static_cast(new SvXMLEmbeddedObjectHelper( *pPersist, SvXMLEmbeddedObjectHelperMode::Read )); } uno::Reference< uno::XInterface > xRet; if( aServiceSpecifier.startsWith( "com.sun.star.presentation.") ) { const std::u16string_view aType( aServiceSpecifier.subView(26) ); rtl::Reference pShape; SdrObjKind nType = SdrObjKind::Text; // create a shape wrapper if( o3tl::starts_with(aType, u"TitleTextShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"OutlinerShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"SubtitleShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"GraphicObjectShape" ) ) { nType = SdrObjKind::Graphic; } else if( o3tl::starts_with(aType, u"PageShape" ) ) { nType = SdrObjKind::Page; } else if( o3tl::starts_with(aType, u"OLE2Shape" ) ) { nType = SdrObjKind::OLE2; } else if( o3tl::starts_with(aType, u"ChartShape" ) ) { nType = SdrObjKind::OLE2; } else if( o3tl::starts_with(aType, u"CalcShape" ) ) { nType = SdrObjKind::OLE2; } else if( o3tl::starts_with(aType, u"TableShape" ) ) { nType = SdrObjKind::Table; } else if( o3tl::starts_with(aType, u"OrgChartShape" ) ) { nType = SdrObjKind::OLE2; } else if( o3tl::starts_with(aType, u"NotesShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"HandoutShape" ) ) { nType = SdrObjKind::Page; } else if( o3tl::starts_with(aType, u"FooterShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"HeaderShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"SlideNumberShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"DateTimeShape" ) ) { nType = SdrObjKind::Text; } else if( o3tl::starts_with(aType, u"MediaShape" ) ) { nType = SdrObjKind::Media; } else { throw lang::ServiceNotRegisteredException(); } // create the API wrapper pShape = CreateSvxShapeByTypeAndInventor( nType, SdrInventor::Default, referer ); // set shape type if( pShape && !mbClipBoard ) pShape->SetShapeType(aServiceSpecifier); xRet = static_cast(pShape.get()); } else if ( aServiceSpecifier == "com.sun.star.drawing.TableShape" ) { rtl::Reference pShape = CreateSvxShapeByTypeAndInventor( SdrObjKind::Table, SdrInventor::Default, referer ); if( pShape && !mbClipBoard ) pShape->SetShapeType(aServiceSpecifier); xRet = static_cast(pShape.get()); } else { xRet = SvxFmMSFactory::createInstance( aServiceSpecifier ); } uno::Reference< drawing::XShape > xShape( xRet, uno::UNO_QUERY ); SvxShape* pShape = xShape.is() ? comphelper::getFromUnoTunnel(xShape) : nullptr; if (pShape) { xRet.clear(); new SdXShape( pShape, this ); xRet = xShape; xShape.clear(); } return xRet; } uno::Reference< uno::XInterface > SAL_CALL SdXImpressDocument::createInstance( const OUString& aServiceSpecifier ) { return create(aServiceSpecifier, u""_ustr); } css::uno::Reference SdXImpressDocument::createInstanceWithArguments( OUString const & ServiceSpecifier, css::uno::Sequence const & Arguments) { OUString arg; if ((ServiceSpecifier == "com.sun.star.drawing.GraphicObjectShape" || ServiceSpecifier == "com.sun.star.drawing.AppletShape" || ServiceSpecifier == "com.sun.star.drawing.FrameShape" || ServiceSpecifier == "com.sun.star.drawing.OLE2Shape" || ServiceSpecifier == "com.sun.star.drawing.MediaShape" || ServiceSpecifier == "com.sun.star.drawing.PluginShape" || ServiceSpecifier == "com.sun.star.presentation.MediaShape") && Arguments.getLength() == 1 && (Arguments[0] >>= arg)) { return create(ServiceSpecifier, arg); } return SvxFmMSFactory::createInstanceWithArguments( ServiceSpecifier, Arguments); } uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getAvailableServiceNames() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); const uno::Sequence< OUString > aSNS_ORG( SvxFmMSFactory::getAvailableServiceNames() ); uno::Sequence< OUString > aSNS_Common{ u"com.sun.star.drawing.DashTable"_ustr, u"com.sun.star.drawing.GradientTable"_ustr, u"com.sun.star.drawing.HatchTable"_ustr, u"com.sun.star.drawing.BitmapTable"_ustr, u"com.sun.star.drawing.TransparencyGradientTable"_ustr, u"com.sun.star.drawing.MarkerTable"_ustr, u"com.sun.star.text.NumberingRules"_ustr, u"com.sun.star.drawing.Background"_ustr, u"com.sun.star.document.Settings"_ustr, sUNO_Service_ImageMapRectangleObject, sUNO_Service_ImageMapCircleObject, sUNO_Service_ImageMapPolygonObject, u"com.sun.star.xml.NamespaceMap"_ustr, // Support creation of GraphicStorageHandler and EmbeddedObjectResolver u"com.sun.star.document.ExportGraphicStorageHandler"_ustr, u"com.sun.star.document.ImportGraphicStorageHandler"_ustr, u"com.sun.star.document.ExportEmbeddedObjectResolver"_ustr, u"com.sun.star.document.ImportEmbeddedObjectResolver"_ustr, u"com.sun.star.drawing.TableShape"_ustr }; uno::Sequence< OUString > aSNS_Specific; if(mbImpressDoc) aSNS_Specific = { u"com.sun.star.presentation.TitleTextShape"_ustr, u"com.sun.star.presentation.OutlinerShape"_ustr, u"com.sun.star.presentation.SubtitleShape"_ustr, u"com.sun.star.presentation.GraphicObjectShape"_ustr, u"com.sun.star.presentation.ChartShape"_ustr, u"com.sun.star.presentation.PageShape"_ustr, u"com.sun.star.presentation.OLE2Shape"_ustr, u"com.sun.star.presentation.TableShape"_ustr, u"com.sun.star.presentation.OrgChartShape"_ustr, u"com.sun.star.presentation.NotesShape"_ustr, u"com.sun.star.presentation.HandoutShape"_ustr, u"com.sun.star.presentation.DocumentSettings"_ustr, u"com.sun.star.presentation.FooterShape"_ustr, u"com.sun.star.presentation.HeaderShape"_ustr, u"com.sun.star.presentation.SlideNumberShape"_ustr, u"com.sun.star.presentation.DateTimeShape"_ustr, u"com.sun.star.presentation.CalcShape"_ustr, u"com.sun.star.presentation.MediaShape"_ustr }; else aSNS_Specific = { u"com.sun.star.drawing.DocumentSettings"_ustr }; return comphelper::concatSequences( aSNS_ORG, aSNS_Common, aSNS_Specific ); } // lang::XServiceInfo OUString SAL_CALL SdXImpressDocument::getImplementationName() { return u"SdXImpressDocument"_ustr; /* // Matching the .component information: return mbImpressDoc ? OUString("com.sun.star.comp.Draw.PresentationDocument") : OUString("com.sun.star.comp.Draw.DrawingDocument"); */ } sal_Bool SAL_CALL SdXImpressDocument::supportsService( const OUString& ServiceName ) { return cppu::supportsService(this, ServiceName); } uno::Sequence< OUString > SAL_CALL SdXImpressDocument::getSupportedServiceNames() { ::SolarMutexGuard aGuard; return { u"com.sun.star.document.OfficeDocument"_ustr, u"com.sun.star.drawing.GenericDrawingDocument"_ustr, u"com.sun.star.drawing.DrawingDocumentFactory"_ustr, mbImpressDoc?u"com.sun.star.presentation.PresentationDocument"_ustr:u"com.sun.star.drawing.DrawingDocument"_ustr }; } // XPropertySet uno::Reference< beans::XPropertySetInfo > SAL_CALL SdXImpressDocument::getPropertySetInfo( ) { ::SolarMutexGuard aGuard; return mpPropSet->getPropertySetInfo(); } void SAL_CALL SdXImpressDocument::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName); switch( pEntry ? pEntry->nWID : -1 ) { case WID_MODEL_LANGUAGE: { lang::Locale aLocale; if(!(aValue >>= aLocale)) throw lang::IllegalArgumentException(); mpDoc->SetLanguage( LanguageTag::convertToLanguageType(aLocale), EE_CHAR_LANGUAGE ); break; } case WID_MODEL_TABSTOP: { sal_Int32 nValue = 0; if(!(aValue >>= nValue) || nValue < 0 ) throw lang::IllegalArgumentException(); mpDoc->SetDefaultTabulator(static_cast(nValue)); break; } case WID_MODEL_VISAREA: { SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); if( !pEmbeddedObj ) break; awt::Rectangle aVisArea; if( !(aValue >>= aVisArea) || (aVisArea.Width < 0) || (aVisArea.Height < 0) ) throw lang::IllegalArgumentException(); sal_Int32 nRight, nTop; if (o3tl::checked_add(aVisArea.X, aVisArea.Width, nRight) || o3tl::checked_add(aVisArea.Y, aVisArea.Height, nTop)) throw lang::IllegalArgumentException(); pEmbeddedObj->SetVisArea(::tools::Rectangle(aVisArea.X, aVisArea.Y, nRight, nTop)); } break; case WID_MODEL_CONTFOCUS: { bool bFocus = false; if( !(aValue >>= bFocus ) ) throw lang::IllegalArgumentException(); mpDoc->SetAutoControlFocus( bFocus ); } break; case WID_MODEL_DSGNMODE: { bool bMode = false; if( !(aValue >>= bMode ) ) throw lang::IllegalArgumentException(); mpDoc->SetOpenInDesignMode( bMode ); } break; case WID_MODEL_BUILDID: aValue >>= maBuildId; return; case WID_MODEL_MAPUNIT: case WID_MODEL_BASICLIBS: case WID_MODEL_RUNTIMEUID: // is read-only case WID_MODEL_DIALOGLIBS: case WID_MODEL_FONTS: throw beans::PropertyVetoException(); case WID_MODEL_INTEROPGRABBAG: setGrabBagItem(aValue); break; case WID_MODEL_THEME: { SdrModel& rModel = getSdrModelFromUnoModel(); std::shared_ptr pTheme = model::Theme::FromAny(aValue); rModel.setTheme(pTheme); } break; default: throw beans::UnknownPropertyException( aPropertyName, static_cast(this)); } SetModified(); } uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& PropertyName ) { ::SolarMutexGuard aGuard; uno::Any aAny; if( nullptr == mpDoc ) throw lang::DisposedException(); const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName); switch( pEntry ? pEntry->nWID : -1 ) { case WID_MODEL_LANGUAGE: { LanguageType eLang = mpDoc->GetLanguage( EE_CHAR_LANGUAGE ); aAny <<= LanguageTag::convertToLocale( eLang); break; } case WID_MODEL_TABSTOP: aAny <<= static_cast(mpDoc->GetDefaultTabulator()); break; case WID_MODEL_VISAREA: { SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); if( !pEmbeddedObj ) break; const ::tools::Rectangle& aRect = pEmbeddedObj->GetVisArea(); awt::Rectangle aVisArea( aRect.Left(), aRect.Top(), aRect.getOpenWidth(), aRect.getOpenHeight() ); aAny <<= aVisArea; } break; case WID_MODEL_MAPUNIT: { SfxObjectShell* pEmbeddedObj = mpDoc->GetDocSh(); if( !pEmbeddedObj ) break; sal_Int16 nMeasureUnit = 0; SvxMapUnitToMeasureUnit( pEmbeddedObj->GetMapUnit(), nMeasureUnit ); aAny <<= nMeasureUnit; } break; case WID_MODEL_FORBCHARS: { aAny <<= getForbiddenCharsTable(); } break; case WID_MODEL_CONTFOCUS: aAny <<= mpDoc->GetAutoControlFocus(); break; case WID_MODEL_DSGNMODE: aAny <<= mpDoc->GetOpenInDesignMode(); break; case WID_MODEL_BASICLIBS: aAny <<= mpDocShell->GetBasicContainer(); break; case WID_MODEL_DIALOGLIBS: aAny <<= mpDocShell->GetDialogContainer(); break; case WID_MODEL_RUNTIMEUID: aAny <<= getRuntimeUID(); break; case WID_MODEL_BUILDID: return uno::Any( maBuildId ); case WID_MODEL_HASVALIDSIGNATURES: aAny <<= hasValidSignatures(); break; case WID_MODEL_ALLOWLINKUPDATE: { comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = mpDocShell->getEmbeddedObjectContainer(); aAny <<= rEmbeddedObjectContainer.getUserAllowsLinkUpdate(); break; } case WID_MODEL_FONTS: { uno::Sequence aSeq; int nSeqIndex = 0; sal_uInt16 const aWhichIds[] { EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK, EE_CHAR_FONTINFO_CTL }; const SfxItemPool& rPool = mpDoc->GetPool(); for(sal_uInt16 nWhichId : aWhichIds) { ItemSurrogates aSurrogates; rPool.GetItemSurrogates(aSurrogates, nWhichId); const sal_uInt32 nItems(aSurrogates.size()); aSeq.realloc( aSeq.getLength() + nItems*5 + 5 ); auto pSeq = aSeq.getArray(); for (const SfxPoolItem* pItem : aSurrogates) { const SvxFontItem *pFont = static_cast(pItem); pSeq[nSeqIndex++] <<= pFont->GetFamilyName(); pSeq[nSeqIndex++] <<= pFont->GetStyleName(); pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetFamily()); pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetPitch()); pSeq[nSeqIndex++] <<= sal_Int16(pFont->GetCharSet()); } const SvxFontItem& rFont = static_cast(rPool.GetUserOrPoolDefaultItem( nWhichId )); pSeq[nSeqIndex++] <<= rFont.GetFamilyName(); pSeq[nSeqIndex++] <<= rFont.GetStyleName(); pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetFamily()); pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetPitch()); pSeq[nSeqIndex++] <<= sal_Int16(rFont.GetCharSet()); } aSeq.realloc( nSeqIndex ); aAny <<= aSeq; break; } case WID_MODEL_INTEROPGRABBAG: getGrabBagItem(aAny); break; case WID_MODEL_THEME: { SdrModel& rModel = getSdrModelFromUnoModel(); auto const& pTheme = rModel.getTheme(); if (pTheme) { pTheme->ToAny(aAny); } else { beans::PropertyValues aValues; aAny <<= aValues; } break; } default: throw beans::UnknownPropertyException( PropertyName, static_cast(this)); } return aAny; } void SAL_CALL SdXImpressDocument::addPropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {} void SAL_CALL SdXImpressDocument::removePropertyChangeListener( const OUString& , const uno::Reference< beans::XPropertyChangeListener >& ) {} void SAL_CALL SdXImpressDocument::addVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {} void SAL_CALL SdXImpressDocument::removeVetoableChangeListener( const OUString& , const uno::Reference< beans::XVetoableChangeListener >& ) {} // XLinkTargetSupplier uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getLinks() { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); rtl::Reference< SdDocLinkTargets > xLinks( mxLinks ); if( !xLinks.is() ) { xLinks = new SdDocLinkTargets( *this ); mxLinks = xLinks.get(); } return xLinks; } // XStyleFamiliesSupplier uno::Reference< container::XNameAccess > SAL_CALL SdXImpressDocument::getStyleFamilies( ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); uno::Reference< container::XNameAccess > xStyles( static_cast< OWeakObject* >( mpDoc->GetStyleSheetPool() ), css::uno::UNO_QUERY ); return xStyles; } // XAnyCompareFactory uno::Reference< css::ucb::XAnyCompare > SAL_CALL SdXImpressDocument::createAnyCompareByName( const OUString& ) { return SvxCreateNumRuleCompare(); } // XRenderable sal_Int32 SAL_CALL SdXImpressDocument::getRendererCount( const uno::Any& rSelection, const uno::Sequence< beans::PropertyValue >& ) { ::SolarMutexGuard aGuard; sal_Int32 nRet = 0; if( nullptr == mpDoc ) throw lang::DisposedException(); if (mpDocShell) { uno::Reference< frame::XModel > xModel; rSelection >>= xModel; if( xModel == mpDocShell->GetModel() ) nRet = mpDoc->GetSdPageCount( PageKind::Standard ); else { uno::Reference< drawing::XShapes > xShapes; rSelection >>= xShapes; if( xShapes.is() && xShapes->getCount() ) nRet = 1; } } return nRet; } uno::Sequence< beans::PropertyValue > SAL_CALL SdXImpressDocument::getRenderer( sal_Int32 , const uno::Any& , const uno::Sequence< beans::PropertyValue >& rxOptions ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); bool bExportNotesPages = false; for( const auto& rOption : rxOptions ) { if ( rOption.Name == "ExportNotesPages" ) rOption.Value >>= bExportNotesPages; } uno::Sequence< beans::PropertyValue > aRenderer; if (mpDocShell) { awt::Size aPageSize; if ( bExportNotesPages ) { Size aNotesPageSize = mpDoc->GetSdPage( 0, PageKind::Notes )->GetSize(); aPageSize = awt::Size( aNotesPageSize.Width(), aNotesPageSize.Height() ); } else { const ::tools::Rectangle aVisArea( mpDocShell->GetVisArea( embed::Aspects::MSOLE_DOCPRINT ) ); aPageSize = awt::Size( aVisArea.GetWidth(), aVisArea.GetHeight() ); } aRenderer = { comphelper::makePropertyValue(u"PageSize"_ustr, aPageSize) }; } return aRenderer; } namespace { class ImplRenderPaintProc : public sdr::contact::ViewObjectContactRedirector { const SdrLayerAdmin& rLayerAdmin; SdrPageView* pSdrPageView; public: bool IsVisible ( const SdrObject* pObj ) const; bool IsPrintable( const SdrObject* pObj ) const; ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView* pView); // all default implementations just call the same methods at the original. To do something // different, override the method and at least do what the method does. virtual void createRedirectedPrimitive2DSequence( const sdr::contact::ViewObjectContact& rOriginal, const sdr::contact::DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) override; }; } ImplRenderPaintProc::ImplRenderPaintProc(const SdrLayerAdmin& rLA, SdrPageView *const pView) : rLayerAdmin(rLA) , pSdrPageView(pView) { } static sal_Int32 ImplPDFGetBookmarkPage( const OUString& rBookmark, SdDrawDocument const & rDoc ) { sal_Int32 nPage = -1; OUString aBookmark( rBookmark ); if( rBookmark.startsWith("#") ) aBookmark = rBookmark.copy( 1 ); // is the bookmark a page ? bool bIsMasterPage; sal_uInt16 nPgNum = rDoc.GetPageByName( aBookmark, bIsMasterPage ); if ( nPgNum == SDRPAGE_NOTFOUND ) { // is the bookmark an object ? SdrObject* pObj = rDoc.GetObj( aBookmark ); if (pObj) nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum(); } if ( nPgNum != SDRPAGE_NOTFOUND ) nPage = ( nPgNum - 1 ) / 2; return nPage; } static void ImplPDFExportComments( const uno::Reference< drawing::XDrawPage >& xPage, vcl::PDFExtOutDevData& rPDFExtOutDevData ) { try { uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW ); uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() ); while( xAnnotationEnumeration->hasMoreElements() ) { uno::Reference xAnnotation(xAnnotationEnumeration->nextElement()); geometry::RealPoint2D aRealPoint2D(xAnnotation->getPosition()); geometry::RealSize2D aRealSize2D(xAnnotation->getSize()); Point aPoint(aRealPoint2D.X * 100.0, aRealPoint2D.Y * 100.0); Size aSize(aRealSize2D.Width * 100.0, aRealSize2D.Height * 100.0); Point aPopupPoint(aPoint.X(), aPoint.Y()); Size aPopupSize(aSize.Width() * 10.0, aSize.Height() * 10.0); uno::Reference xText(xAnnotation->getTextRange()); vcl::pdf::PDFNote aNote; aNote.maTitle = xAnnotation->getAuthor(); aNote.maContents = xText->getString(); aNote.maModificationDate = xAnnotation->getDateTime(); auto* pAnnotation = dynamic_cast(xAnnotation.get()); if (pAnnotation && pAnnotation->getCreationInfo().meType != sdr::annotation::AnnotationType::None) { sdr::annotation::CreationInfo const& rCreation = pAnnotation->getCreationInfo(); aNote.maPolygons = rCreation.maPolygons; aNote.maAnnotationColor = rCreation.maColor; aNote.maInteriorColor = rCreation.maFillColor; aNote.mfWidth = rCreation.mnWidth; switch (rCreation.meType) { case sdr::annotation::AnnotationType::Square: aNote.meType = vcl::pdf::PDFAnnotationSubType::Square; break; case sdr::annotation::AnnotationType::Circle: aNote.meType = vcl::pdf::PDFAnnotationSubType::Circle; break; case sdr::annotation::AnnotationType::Polygon: aNote.meType = vcl::pdf::PDFAnnotationSubType::Polygon; break; case sdr::annotation::AnnotationType::Ink: aNote.meType = vcl::pdf::PDFAnnotationSubType::Ink; break; case sdr::annotation::AnnotationType::Highlight: aNote.meType = vcl::pdf::PDFAnnotationSubType::Highlight; break; case sdr::annotation::AnnotationType::Line: aNote.meType = vcl::pdf::PDFAnnotationSubType::Line; break; case sdr::annotation::AnnotationType::FreeText: aNote.meType = vcl::pdf::PDFAnnotationSubType::FreeText; break; default: aNote.meType = vcl::pdf::PDFAnnotationSubType::Text; break; } } rPDFExtOutDevData.CreateNote(::tools::Rectangle(aPoint, aSize), aNote, ::tools::Rectangle(aPopupPoint, aPopupSize)); } } catch (const uno::Exception&) { } } static void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape >& xShape, SdDrawDocument& rDoc, vcl::PDFExtOutDevData& rPDFExtOutDevData ) { if ( xShape->getShapeType() == "com.sun.star.drawing.GroupShape" ) { uno::Reference< container::XIndexAccess > xIndexAccess( xShape, uno::UNO_QUERY ); if ( xIndexAccess.is() ) { sal_Int32 i, nCount = xIndexAccess->getCount(); for ( i = 0; i < nCount; i++ ) { uno::Reference< drawing::XShape > xSubShape( xIndexAccess->getByIndex( i ), uno::UNO_QUERY ); if ( xSubShape.is() ) ImplPDFExportShapeInteraction( xSubShape, rDoc, rPDFExtOutDevData ); } } } else { uno::Reference< beans::XPropertySet > xShapePropSet( xShape, uno::UNO_QUERY ); if( xShapePropSet.is() ) { Size aPageSize( rDoc.GetSdPage( 0, PageKind::Standard )->GetSize() ); Point aPoint( 0, 0 ); ::tools::Rectangle aPageRect( aPoint, aPageSize ); awt::Point aShapePos( xShape->getPosition() ); awt::Size aShapeSize( xShape->getSize() ); ::tools::Rectangle aLinkRect( Point( aShapePos.X, aShapePos.Y ), Size( aShapeSize.Width, aShapeSize.Height ) ); // Handle linked videos. if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape") { OUString title; xShapePropSet->getPropertyValue(u"Title"_ustr) >>= title; OUString description; xShapePropSet->getPropertyValue(u"Description"_ustr) >>= description; OUString const altText(title.isEmpty() ? description : description.isEmpty() ? title : OUString::Concat(title) + OUString::Concat("\n") + OUString::Concat(description)); OUString aMediaURL; xShapePropSet->getPropertyValue(u"MediaURL"_ustr) >>= aMediaURL; if (!aMediaURL.isEmpty()) { SdrObject const*const pSdrObj(SdrObject::getSdrObjectFromXShape(xShape)); OUString const mimeType(xShapePropSet->getPropertyValue(u"MediaMimeType"_ustr).get()); sal_Int32 nScreenId = rPDFExtOutDevData.CreateScreen(aLinkRect, altText, mimeType, rPDFExtOutDevData.GetCurrentPageNumber(), pSdrObj); if (aMediaURL.startsWith("vnd.sun.star.Package:")) { OUString aTempFileURL; xShapePropSet->getPropertyValue(u"PrivateTempFileURL"_ustr) >>= aTempFileURL; rPDFExtOutDevData.SetScreenStream(nScreenId, aTempFileURL); } else rPDFExtOutDevData.SetScreenURL(nScreenId, aMediaURL); } } presentation::ClickAction eCa; uno::Any aAny( xShapePropSet->getPropertyValue( u"OnClick"_ustr ) ); if ( aAny >>= eCa ) { OUString const actionName(SdResId(SdTPAction::GetClickActionSdResId(eCa))); switch ( eCa ) { case presentation::ClickAction_LASTPAGE : { sal_Int32 nCount = rDoc.GetSdPageCount( PageKind::Standard ); sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nCount - 1, vcl::PDFWriter::DestAreaType::FitRectangle ); sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; case presentation::ClickAction_FIRSTPAGE : { sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, 0, vcl::PDFWriter::DestAreaType::FitRectangle ); sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; case presentation::ClickAction_PREVPAGE : { sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber(); if ( nDestPage ) nDestPage--; sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; case presentation::ClickAction_NEXTPAGE : { sal_Int32 nDestPage = rPDFExtOutDevData.GetCurrentPageNumber() + 1; sal_Int32 nLastPage = rDoc.GetSdPageCount( PageKind::Standard ) - 1; if ( nDestPage > nLastPage ) nDestPage = nLastPage; sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nDestPage, vcl::PDFWriter::DestAreaType::FitRectangle ); sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } break; case presentation::ClickAction_PROGRAM : case presentation::ClickAction_BOOKMARK : case presentation::ClickAction_DOCUMENT : { OUString aBookmark; xShapePropSet->getPropertyValue( u"Bookmark"_ustr ) >>= aBookmark; if( !aBookmark.isEmpty() ) { switch( eCa ) { case presentation::ClickAction_DOCUMENT : case presentation::ClickAction_PROGRAM : { sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkURL( nLinkId, aBookmark ); } break; case presentation::ClickAction_BOOKMARK : { sal_Int32 nPage = ImplPDFGetBookmarkPage( aBookmark, rDoc ); if ( nPage != -1 ) { sal_Int32 nDestId = rPDFExtOutDevData.CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ); sal_Int32 nLinkId = rPDFExtOutDevData.CreateLink(aLinkRect, actionName); rPDFExtOutDevData.SetLinkDest( nLinkId, nDestId ); } } break; default: break; } } } break; case presentation::ClickAction_STOPPRESENTATION : case presentation::ClickAction_SOUND : case presentation::ClickAction_INVISIBLE : case presentation::ClickAction_VERB : case presentation::ClickAction_VANISH : case presentation::ClickAction_MACRO : default : break; } } } } } void ImplRenderPaintProc::createRedirectedPrimitive2DSequence( const sdr::contact::ViewObjectContact& rOriginal, const sdr::contact::DisplayInfo& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) { SdrObject* pObject = rOriginal.GetViewContact().TryToGetSdrObject(); if(!pObject) { // not an object, maybe a page sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); return; } SdrPage* pSdrPage(pObject->getSdrPageFromSdrObject()); if(!pSdrPage) return; if(!pSdrPage->checkVisibility(rOriginal, rDisplayInfo, false)) return; if(!IsVisible(pObject) || !IsPrintable(pObject)) return; sdr::contact::ViewObjectContactRedirector::createRedirectedPrimitive2DSequence(rOriginal, rDisplayInfo, rVisitor); } bool ImplRenderPaintProc::IsVisible( const SdrObject* pObj ) const { bool bVisible = true; SdrLayerID nLayerId = pObj->GetLayer(); if( pSdrPageView ) { const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId ); if ( pSdrLayer ) { const OUString& aLayerName = pSdrLayer->GetName(); bVisible = pSdrPageView->IsLayerVisible( aLayerName ); } } return bVisible; } bool ImplRenderPaintProc::IsPrintable( const SdrObject* pObj ) const { bool bPrintable = true; SdrLayerID nLayerId = pObj->GetLayer(); if( pSdrPageView ) { const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId ); if ( pSdrLayer ) { const OUString& aLayerName = pSdrLayer->GetName(); bPrintable = pSdrPageView->IsLayerPrintable( aLayerName ); } } return bPrintable; } namespace { sal_Int16 CalcOutputPageNum(vcl::PDFExtOutDevData const * pPDFExtOutDevData, SdDrawDocument const *pDoc, sal_Int16 nPageNumber) { //export all pages, simple one to one case if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) return nPageNumber-1; //check all preceding pages, and only count non-hidden ones sal_Int16 nRet = 0; for (sal_Int16 i = 0; i < nPageNumber-1; ++i) { if (!pDoc->GetSdPage(i, PageKind::Standard)->IsExcluded()) ++nRet; } return nRet; } } void SAL_CALL SdXImpressDocument::render( sal_Int32 nRenderer, const uno::Any& rSelection, const uno::Sequence< beans::PropertyValue >& rxOptions ) { ::SolarMutexGuard aGuard; if( nullptr == mpDoc ) throw lang::DisposedException(); if (!mpDocShell) return; uno::Reference< awt::XDevice > xRenderDevice; const sal_Int32 nPageNumber = nRenderer + 1; PageKind ePageKind = PageKind::Standard; bool bExportNotesPages = false; for( const auto& rOption : rxOptions ) { if ( rOption.Name == "RenderDevice" ) rOption.Value >>= xRenderDevice; else if ( rOption.Name == "ExportNotesPages" ) { rOption.Value >>= bExportNotesPages; if ( bExportNotesPages ) ePageKind = PageKind::Notes; } } if( !(xRenderDevice.is() && nPageNumber && ( nPageNumber <= mpDoc->GetSdPageCount( ePageKind ) )) ) return; VCLXDevice* pDevice = dynamic_cast( xRenderDevice.get() ); VclPtr< OutputDevice> pOut = pDevice ? pDevice->GetOutputDevice() : VclPtr< OutputDevice >(); if( !pOut ) return; vcl::PDFExtOutDevData* pPDFExtOutDevData = dynamic_cast( pOut->GetExtOutDevData() ); if ( mpDoc->GetSdPage(static_cast(nPageNumber)-1, PageKind::Standard)->IsExcluded() && !(pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportHiddenSlides()) ) return; if (pPDFExtOutDevData) { css::lang::Locale const docLocale(Application::GetSettings().GetLanguageTag().getLocale()); pPDFExtOutDevData->SetDocumentLocale(docLocale); } ::sd::ClientView aView( mpDocShell, pOut ); ::tools::Rectangle aVisArea( Point(), mpDoc->GetSdPage( static_cast(nPageNumber) - 1, ePageKind )->GetSize() ); vcl::Region aRegion( aVisArea ); ::sd::ViewShell* pOldViewSh = mpDocShell->GetViewShell(); ::sd::View* pOldSdView = pOldViewSh ? pOldViewSh->GetView() : nullptr; if ( pOldSdView ) pOldSdView->SdrEndTextEdit(); aView.SetHlplVisible( false ); aView.SetGridVisible( false ); aView.SetBordVisible( false ); aView.SetPageVisible( false ); aView.SetGlueVisible( false ); pOut->SetMapMode(MapMode(MapUnit::Map100thMM)); pOut->IntersectClipRegion( aVisArea ); uno::Reference< frame::XModel > xModel; rSelection >>= xModel; if( xModel == mpDocShell->GetModel() ) { aView.ShowSdrPage( mpDoc->GetSdPage( static_cast(nPageNumber) - 1, ePageKind )); SdrPageView* pPV = aView.GetSdrPageView(); if( pOldSdView ) { SdrPageView* pOldPV = pOldSdView->GetSdrPageView(); if( pPV && pOldPV ) { pPV->SetVisibleLayers( pOldPV->GetVisibleLayers() ); pPV->SetPrintableLayers( pOldPV->GetPrintableLayers() ); } } ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(), pPV); // background color for outliner :o SdPage* pPage = pPV ? static_cast(pPV->GetPage()) : nullptr; if( pPage ) { SdrOutliner& rOutl = mpDoc->GetDrawOutliner(); bool bScreenDisplay(true); // #i75566# printing; suppress AutoColor BackgroundColor generation // for visibility reasons by giving GetPageBackgroundColor() // the needed hint // #i75566# PDF export; suppress AutoColor BackgroundColor generation (see printing) if (pOut && ((OUTDEV_PRINTER == pOut->GetOutDevType()) || (OUTDEV_PDF == pOut->GetOutDevType()))) bScreenDisplay = false; // #i75566# Name change GetBackgroundColor -> GetPageBackgroundColor and // hint value if screen display. Only then the AutoColor mechanisms shall be applied rOutl.SetBackgroundColor( pPage->GetPageBackgroundColor( pPV, bScreenDisplay ) ); } // produce link annots for media shapes before painting them if ( pPDFExtOutDevData && pPage ) { try { uno::Any aAny; uno::Reference< drawing::XDrawPage > xPage( uno::Reference< drawing::XDrawPage >::query( pPage->getUnoPage() ) ); if ( xPage.is() ) { if ( pPDFExtOutDevData->GetIsExportNotes() ) ImplPDFExportComments( xPage, *pPDFExtOutDevData ); uno::Reference< beans::XPropertySet > xPagePropSet( xPage, uno::UNO_QUERY ); if( xPagePropSet.is() ) { // exporting object interactions to pdf // if necessary, the master page interactions will be exported first bool bIsBackgroundObjectsVisible = false; // #i39428# IsBackgroundObjectsVisible not available for Draw if ( mbImpressDoc && xPagePropSet->getPropertySetInfo()->hasPropertyByName( u"IsBackgroundObjectsVisible"_ustr ) ) xPagePropSet->getPropertyValue( u"IsBackgroundObjectsVisible"_ustr ) >>= bIsBackgroundObjectsVisible; if ( bIsBackgroundObjectsVisible && !pPDFExtOutDevData->GetIsExportNotesPages() ) { uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( xPage, uno::UNO_QUERY ); if ( xMasterPageTarget.is() ) { uno::Reference< drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage(); if ( xMasterPage.is() ) { sal_Int32 i, nCount = xMasterPage->getCount(); for ( i = 0; i < nCount; i++ ) { aAny = xMasterPage->getByIndex( i ); uno::Reference< drawing::XShape > xShape; if ( aAny >>= xShape ) ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData ); } } } } // exporting slide page object interactions sal_Int32 i, nCount = xPage->getCount(); for ( i = 0; i < nCount; i++ ) { aAny = xPage->getByIndex( i ); uno::Reference< drawing::XShape > xShape; if ( aAny >>= xShape ) ImplPDFExportShapeInteraction( xShape, *mpDoc, *pPDFExtOutDevData ); } // exporting transition effects to pdf if ( mbImpressDoc && !pPDFExtOutDevData->GetIsExportNotesPages() && pPDFExtOutDevData->GetIsExportTransitionEffects() ) { static constexpr OUString sEffect( u"Effect"_ustr ); static constexpr OUString sSpeed ( u"Speed"_ustr ); sal_Int32 nTime = 800; presentation::AnimationSpeed aAs; if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) ) { aAny = xPagePropSet->getPropertyValue( sSpeed ); if ( aAny >>= aAs ) { switch( aAs ) { case presentation::AnimationSpeed_SLOW : nTime = 1500; break; case presentation::AnimationSpeed_FAST : nTime = 300; break; default: case presentation::AnimationSpeed_MEDIUM : nTime = 800; } } } presentation::FadeEffect eFe; vcl::PDFWriter::PageTransition eType = vcl::PDFWriter::PageTransition::Regular; if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) ) { aAny = xPagePropSet->getPropertyValue( sEffect ); if ( aAny >>= eFe ) { switch( eFe ) { case presentation::FadeEffect_HORIZONTAL_LINES : case presentation::FadeEffect_HORIZONTAL_CHECKERBOARD : case presentation::FadeEffect_HORIZONTAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsHorizontal; break; case presentation::FadeEffect_VERTICAL_LINES : case presentation::FadeEffect_VERTICAL_CHECKERBOARD : case presentation::FadeEffect_VERTICAL_STRIPES : eType = vcl::PDFWriter::PageTransition::BlindsVertical; break; case presentation::FadeEffect_UNCOVER_TO_RIGHT : case presentation::FadeEffect_UNCOVER_TO_UPPERRIGHT : case presentation::FadeEffect_ROLL_FROM_LEFT : case presentation::FadeEffect_FADE_FROM_UPPERLEFT : case presentation::FadeEffect_MOVE_FROM_UPPERLEFT : case presentation::FadeEffect_FADE_FROM_LEFT : case presentation::FadeEffect_MOVE_FROM_LEFT : eType = vcl::PDFWriter::PageTransition::WipeLeftToRight; break; case presentation::FadeEffect_UNCOVER_TO_BOTTOM : case presentation::FadeEffect_UNCOVER_TO_LOWERRIGHT : case presentation::FadeEffect_ROLL_FROM_TOP : case presentation::FadeEffect_FADE_FROM_UPPERRIGHT : case presentation::FadeEffect_MOVE_FROM_UPPERRIGHT : case presentation::FadeEffect_FADE_FROM_TOP : case presentation::FadeEffect_MOVE_FROM_TOP : eType = vcl::PDFWriter::PageTransition::WipeTopToBottom; break; case presentation::FadeEffect_UNCOVER_TO_LEFT : case presentation::FadeEffect_UNCOVER_TO_LOWERLEFT : case presentation::FadeEffect_ROLL_FROM_RIGHT : case presentation::FadeEffect_FADE_FROM_LOWERRIGHT : case presentation::FadeEffect_MOVE_FROM_LOWERRIGHT : case presentation::FadeEffect_FADE_FROM_RIGHT : case presentation::FadeEffect_MOVE_FROM_RIGHT : eType = vcl::PDFWriter::PageTransition::WipeRightToLeft; break; case presentation::FadeEffect_UNCOVER_TO_TOP : case presentation::FadeEffect_UNCOVER_TO_UPPERLEFT : case presentation::FadeEffect_ROLL_FROM_BOTTOM : case presentation::FadeEffect_FADE_FROM_LOWERLEFT : case presentation::FadeEffect_MOVE_FROM_LOWERLEFT : case presentation::FadeEffect_FADE_FROM_BOTTOM : case presentation::FadeEffect_MOVE_FROM_BOTTOM : eType = vcl::PDFWriter::PageTransition::WipeBottomToTop; break; case presentation::FadeEffect_OPEN_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalInward; break; case presentation::FadeEffect_CLOSE_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitHorizontalOutward; break; case presentation::FadeEffect_OPEN_HORIZONTAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalInward; break; case presentation::FadeEffect_CLOSE_VERTICAL : eType = vcl::PDFWriter::PageTransition::SplitVerticalOutward; break; case presentation::FadeEffect_FADE_TO_CENTER : eType = vcl::PDFWriter::PageTransition::BoxInward; break; case presentation::FadeEffect_FADE_FROM_CENTER : eType = vcl::PDFWriter::PageTransition::BoxOutward; break; case presentation::FadeEffect_NONE : eType = vcl::PDFWriter::PageTransition::Regular; break; case presentation::FadeEffect_RANDOM : case presentation::FadeEffect_DISSOLVE : default: eType = vcl::PDFWriter::PageTransition::Dissolve; break; } } } if ( xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sEffect ) || xPagePropSet->getPropertySetInfo( )->hasPropertyByName( sSpeed ) ) { pPDFExtOutDevData->SetPageTransition( eType, nTime ); } } } } } catch (const uno::Exception&) { } } aView.SdrPaintView::CompleteRedraw(pOut, aRegion, &aImplRenderPaintProc); if (pPDFExtOutDevData && pPage) { try { Size aPageSize( mpDoc->GetSdPage( 0, PageKind::Standard )->GetSize() ); Point aPoint( 0, 0 ); ::tools::Rectangle aPageRect( aPoint, aPageSize ); // resolving links found in this page by the method ImpEditEngine::Paint std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); for ( const auto& rBookmark : rBookmarks ) { sal_Int32 nPage = ImplPDFGetBookmarkPage( rBookmark.aBookmark, *mpDoc ); if ( nPage != -1 ) { if ( rBookmark.nLinkId != -1 ) pPDFExtOutDevData->SetLinkDest( rBookmark.nLinkId, pPDFExtOutDevData->CreateDest( aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ) ); else pPDFExtOutDevData->DescribeRegisteredDest( rBookmark.nDestId, aPageRect, nPage, vcl::PDFWriter::DestAreaType::FitRectangle ); } else pPDFExtOutDevData->SetLinkURL( rBookmark.nLinkId, rBookmark.aBookmark ); } rBookmarks.clear(); //---> #i56629, #i40318 //get the page name, will be used as outline element in PDF bookmark pane OUString aPageName = mpDoc->GetSdPage( static_cast(nPageNumber) - 1 , PageKind::Standard )->GetName(); if( !aPageName.isEmpty() ) { // Destination PageNum const sal_Int32 nDestPageNum = CalcOutputPageNum(pPDFExtOutDevData, mpDoc, nPageNumber); // insert the bookmark to this page into the NamedDestinations if( pPDFExtOutDevData->GetIsExportNamedDestinations() ) pPDFExtOutDevData->CreateNamedDest(aPageName, aPageRect, nDestPageNum); // add the name to the outline, (almost) same code as in sc/source/ui/unoobj/docuno.cxx // issue #i40318. if( pPDFExtOutDevData->GetIsExportBookmarks() ) { // Destination Export const sal_Int32 nDestId = pPDFExtOutDevData->CreateDest(aPageRect , nDestPageNum); // Create a new outline item: pPDFExtOutDevData->CreateOutlineItem( -1 , aPageName, nDestId ); } } //<--- #i56629, #i40318 } catch (const uno::Exception&) { } } } else { uno::Reference< drawing::XShapes > xShapes; rSelection >>= xShapes; if( xShapes.is() && xShapes->getCount() ) { SdrPageView* pPV = nullptr; ImplRenderPaintProc aImplRenderPaintProc( mpDoc->GetLayerAdmin(), pOldSdView ? pOldSdView->GetSdrPageView() : nullptr); for( sal_uInt32 i = 0, nCount = xShapes->getCount(); i < nCount; i++ ) { uno::Reference< drawing::XShape > xShape; xShapes->getByIndex( i ) >>= xShape; if( xShape.is() ) { SdrObject* pObj = SdrObject::getSdrObjectFromXShape( xShape ); if( pObj && pObj->getSdrPageFromSdrObject() && aImplRenderPaintProc.IsVisible( pObj ) && aImplRenderPaintProc.IsPrintable( pObj ) ) { if( !pPV ) pPV = aView.ShowSdrPage( pObj->getSdrPageFromSdrObject() ); if( pPV ) aView.MarkObj( pObj, pPV ); } } } aView.DrawMarkedObj(*pOut); } } } DrawViewShell* SdXImpressDocument::GetViewShell() { DrawViewShell* pViewSh = dynamic_cast(mpDocShell->GetViewShell()); if (!pViewSh) { SAL_WARN("sd", "DrawViewShell not available!"); return nullptr; } return pViewSh; } void SdXImpressDocument::paintTile( VirtualDevice& rDevice, int nOutputWidth, int nOutputHeight, int nTilePosX, int nTilePosY, ::tools::Long nTileWidth, ::tools::Long nTileHeight ) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; // we need to skip tile invalidation for controls on rendering comphelper::LibreOfficeKit::setTiledPainting(true); // Setup drawing layer to work properly. Since we use a custom VirtualDevice // for the drawing, SdrPaintView::BeginCompleteRedraw() will call FindPaintWindow() // unsuccessfully and use a temporary window that doesn't keep state. So patch // the existing SdrPageWindow to use a temporary, and this way the state will be kept. // Well, at least that's how I understand it based on Writer's RenderContextGuard, // as the drawing layer classes lack documentation. SdrPageWindow* patchedPageWindow = nullptr; SdrPaintWindow* previousPaintWindow = nullptr; std::unique_ptr temporaryPaintWindow; if(SdrView* pDrawView = pViewSh->GetDrawView()) { if(SdrPageView* pSdrPageView = pDrawView->GetSdrPageView()) { pSdrPageView->SetApplicationDocumentColor(pViewSh->GetViewOptions().mnDocBackgroundColor); patchedPageWindow = pSdrPageView->FindPageWindow(*getDocWindow()->GetOutDev()); temporaryPaintWindow.reset(new SdrPaintWindow(*pDrawView, rDevice)); if (patchedPageWindow) previousPaintWindow = patchedPageWindow->patchPaintWindow(*temporaryPaintWindow); } } // Scaling. Must convert from pixels to twips. We know // that VirtualDevices use a DPI of 96. // We specifically calculate these scales first as we're still // in TWIPs, and might as well minimize the number of conversions. const Fraction scale = conversionFract(o3tl::Length::px, o3tl::Length::twip); Fraction scaleX = Fraction(nOutputWidth, nTileWidth) * scale; Fraction scaleY = Fraction(nOutputHeight, nTileHeight) * scale; // svx seems to be the only component that works natively in // 100th mm rather than TWIP. It makes most sense just to // convert here and in getDocumentSize, and leave the tiled // rendering API working in TWIPs. ::tools::Long nTileWidthHMM = convertTwipToMm100( nTileWidth ); ::tools::Long nTileHeightHMM = convertTwipToMm100( nTileHeight ); int nTilePosXHMM = convertTwipToMm100( nTilePosX ); int nTilePosYHMM = convertTwipToMm100( nTilePosY ); MapMode aMapMode = rDevice.GetMapMode(); aMapMode.SetMapUnit( MapUnit::Map100thMM ); aMapMode.SetOrigin( Point( -nTilePosXHMM, -nTilePosYHMM) ); aMapMode.SetScaleX( scaleX ); aMapMode.SetScaleY( scaleY ); rDevice.SetMapMode( aMapMode ); rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) ); Point aPoint(nTilePosXHMM, nTilePosYHMM); Size aSize(nTileWidthHMM, nTileHeightHMM); ::tools::Rectangle aRect(aPoint, aSize); SdrView* pView = pViewSh->GetDrawView(); if (comphelper::LibreOfficeKit::isActive()) pView->SetPaintTextEdit(mbPaintTextEdit); pViewSh->GetView()->CompleteRedraw(&rDevice, vcl::Region(aRect)); if (comphelper::LibreOfficeKit::isActive()) pView->SetPaintTextEdit(true); LokChartHelper::PaintAllChartsOnTile(rDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight); LokStarMathHelper::PaintAllInPlaceOnTile(rDevice, nOutputWidth, nOutputHeight, nTilePosX, nTilePosY, nTileWidth, nTileHeight); if(patchedPageWindow != nullptr) patchedPageWindow->unpatchPaintWindow(previousPaintWindow); // Draw Form controls SdrView* pDrawView = pViewSh->GetDrawView(); SdrPageView* pPageView = pDrawView->GetSdrPageView(); if (pPageView != nullptr) { SdrPage* pPage = pPageView->GetPage(); ::sd::Window* pActiveWin = pViewSh->GetActiveWindow(); ::tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight)); Size aOutputSize(nOutputWidth, nOutputHeight); LokControlHandler::paintControlTile(pPage, pDrawView, *pActiveWin, rDevice, aOutputSize, aTileRect); } comphelper::LibreOfficeKit::setTiledPainting(false); } OString SdXImpressDocument::getViewRenderState(SfxViewShell* pViewShell) { OStringBuffer aState; DrawViewShell* pView = nullptr; if (ViewShellBase* pShellBase = dynamic_cast(pViewShell)) pView = dynamic_cast(pShellBase->GetMainViewShell().get()); else pView = GetViewShell(); if (pView) { const SdViewOptions& pVOpt = pView->GetViewOptions(); if (mpDoc->GetOnlineSpell()) aState.append('S'); if (pVOpt.mnDocBackgroundColor == svtools::ColorConfig::GetDefaultColor(svtools::DOCCOLOR, 1)) aState.append('D'); aState.append(';'); OString aThemeName = OUStringToOString(pVOpt.msColorSchemeName, RTL_TEXTENCODING_UTF8); aState.append(aThemeName); } return aState.makeStringAndClear(); } void SdXImpressDocument::selectPart(int nPart, int nSelect) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; pViewSh->SelectPage(nPart, nSelect); } void SdXImpressDocument::moveSelectedParts(int nPosition, bool bDuplicate) { // Duplicating is currently unsupported. if (!bDuplicate) mpDoc->MovePages(nPosition); } OUString SdXImpressDocument::getPartInfo(int nPart) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return OUString(); const SdPage* pSdPage = mpDoc->GetSdPage(nPart, pViewSh->GetPageKind()); const bool bIsVisible = pSdPage && !pSdPage->IsExcluded(); const bool bIsSelected = pViewSh->IsSelected(nPart); const sal_Int16 nMasterPageCount= pViewSh->GetDoc()->GetMasterSdPageCount(pViewSh->GetPageKind()); OUString aPartInfo = "{ \"visible\": \"" + OUString::number(static_cast(bIsVisible)) + "\", \"selected\": \"" + OUString::number(static_cast(bIsSelected)) + "\", \"masterPageCount\": \"" + OUString::number(nMasterPageCount) + "\", \"mode\": \"" + OUString::number(getEditMode()) + "\" }"; return aPartInfo; } void SdXImpressDocument::setPart( int nPart, bool bAllowChangeFocus ) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; pViewSh->SwitchPage( nPart, bAllowChangeFocus ); } int SdXImpressDocument::getParts() { if (!mpDoc) return 0; if (isMasterViewMode()) return mpDoc->GetMasterSdPageCount(PageKind::Standard); return mpDoc->GetSdPageCount(PageKind::Standard); } int SdXImpressDocument::getPart() { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return 0; return pViewSh->GetViewShellBase().getPart(); } OUString SdXImpressDocument::getPartName(int nPart) { SdPage* pPage; if (isMasterViewMode()) pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard); else pPage = mpDoc->GetSdPage(nPart, PageKind::Standard); if (!pPage) { SAL_WARN("sd", "DrawViewShell not available!"); return OUString(); } return pPage->GetName(); } OUString SdXImpressDocument::getPartHash(int nPart) { SdPage* pPage; if (isMasterViewMode()) pPage = mpDoc->GetMasterSdPage(nPart, PageKind::Standard); else pPage = mpDoc->GetSdPage(nPart, PageKind::Standard); if (!pPage) { SAL_WARN("sd", "DrawViewShell not available!"); return OUString(); } uno::Reference xDrawPage(pPage->getUnoPage(), uno::UNO_QUERY); return OUString::fromUtf8(GetInterfaceHash(xDrawPage)); } bool SdXImpressDocument::isMasterViewMode() { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return false; if (pViewSh->GetDispatcher()) { SfxPoolItemHolder aResult; pViewSh->GetDispatcher()->QueryState(SID_SLIDE_MASTER_MODE, aResult); const SfxBoolItem* isMasterViewMode(static_cast(aResult.getItem())); if (isMasterViewMode && isMasterViewMode->GetValue()) return true; } return false; } VclPtr SdXImpressDocument::getDocWindow() { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return {}; if (VclPtr pWindow = SfxLokHelper::getInPlaceDocWindow(pViewShell->GetViewShell())) return pWindow; return pViewShell->GetActiveWindow(); } void SdXImpressDocument::setPartMode( int nPartMode ) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; PageKind aPageKind( PageKind::Standard ); switch ( nPartMode ) { case LOK_PARTMODE_SLIDES: break; case LOK_PARTMODE_NOTES: aPageKind = PageKind::Notes; break; } pViewSh->SetPageKind( aPageKind ); } int SdXImpressDocument::getEditMode() { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return 0; return pViewSh->GetViewShellBase().getEditMode(); } void SdXImpressDocument::setEditMode(int nMode) { SolarMutexGuard aGuard; DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; pViewSh->GetViewShellBase().setEditMode(nMode); } Size SdXImpressDocument::getDocumentSize() { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return Size(); SdrView *pSdrView = pViewSh->GetView(); if (!pSdrView) return Size(); SdrPageView* pCurPageView = pSdrView->GetSdrPageView(); if (!pCurPageView) return Size(); Size aSize = pCurPageView->GetPageRect().GetSize(); // Convert the size in 100th mm to TWIP // See paintTile above for further info. return o3tl::convert(aSize, o3tl::Length::mm100, o3tl::Length::twip); } void SdXImpressDocument::getPostIts(::tools::JsonWriter& rJsonWriter) { auto commentsNode = rJsonWriter.startNode("comments"); if (!mpDoc) return; // Return annotations on master pages too ? const sal_uInt16 nMaxPages = mpDoc->GetPageCount(); for (sal_uInt16 nPage = 0; nPage < nMaxPages; ++nPage) { SdrPage* pPage = mpDoc->GetPage(nPage); for (auto const& xAnnotation : pPage->getAnnotations()) { sal_uInt32 nID = xAnnotation->GetId(); OString nodeName = "comment" + OString::number(nID); auto commentNode = rJsonWriter.startNode(nodeName); rJsonWriter.put("id", nID); rJsonWriter.put("author", xAnnotation->getAuthor()); rJsonWriter.put("dateTime", utl::toISO8601(xAnnotation->getDateTime())); uno::Reference xText(xAnnotation->getTextRange()); rJsonWriter.put("text", xText->getString()); rJsonWriter.put("parthash", pPage->GetUniqueID()); geometry::RealPoint2D const & rPoint = xAnnotation->getPosition(); geometry::RealSize2D const & rSize = xAnnotation->getSize(); ::tools::Rectangle aRectangle(Point(rPoint.X * 100.0, rPoint.Y * 100.0), Size(rSize.Width * 100.0, rSize.Height * 100.0)); aRectangle = o3tl::toTwips(aRectangle, o3tl::Length::mm100); OString sRectangle = aRectangle.toString(); rJsonWriter.put("rectangle", sRectangle.getStr()); } } } void SdXImpressDocument::initializeForTiledRendering(const css::uno::Sequence& rArguments) { SolarMutexGuard aGuard; OUString sThemeName; OUString sBackgroundThemeName; if (DrawViewShell* pViewShell = GetViewShell()) { DrawView* pDrawView = pViewShell->GetDrawView(); for (const beans::PropertyValue& rValue : rArguments) { if (rValue.Name == ".uno:ShowBorderShadow" && rValue.Value.has()) pDrawView->SetPageShadowVisible(rValue.Value.get()); else if (rValue.Name == ".uno:Author" && rValue.Value.has()) pDrawView->SetAuthor(rValue.Value.get()); else if (rValue.Name == ".uno:SpellOnline" && rValue.Value.has()) mpDoc->SetOnlineSpell(rValue.Value.get()); else if (rValue.Name == ".uno:ChangeTheme" && rValue.Value.has()) sThemeName = rValue.Value.get(); else if (rValue.Name == ".uno:InvertBackground" && rValue.Value.has()) sBackgroundThemeName = rValue.Value.get(); } // Disable comments if requested SdOptions* pOptions = SD_MOD()->GetSdOptions(mpDoc->GetDocumentType()); pOptions->SetShowComments(comphelper::LibreOfficeKit::isTiledAnnotations()); pViewShell->SetRuler(false); pViewShell->SetScrollBarsVisible(false); if (sd::Window* pWindow = pViewShell->GetActiveWindow()) { // get the full page size in pixels pWindow->EnableMapMode(); Size aSize(pWindow->LogicToPixel(pDrawView->GetSdrPageView()->GetPage()->GetSize())); // Disable map mode, so that it's possible to send mouse event // coordinates in logic units pWindow->EnableMapMode(false); // arrange UI elements again with new view size pViewShell->GetParentWindow()->SetSizePixel(aSize); pViewShell->Resize(); } // Forces all images to be swapped in synchronously, this // ensures that images are available when paintTile is called // (whereas with async loading images start being loaded after // we have painted the tile, resulting in an invalidate, followed // by the tile being rerendered - which is wasteful and ugly). pDrawView->SetSwapAsynchron(false); } // when the "This document may contain formatting or content that cannot // be saved..." dialog appears, it is auto-cancelled with tiled rendering, // causing 'Save' being disabled; so let's always save to the original // format auto xChanges = comphelper::ConfigurationChanges::create(); officecfg::Office::Common::Save::Document::WarnAlienFormat::set(false, xChanges); if (!o3tl::IsRunningUnitTest() || !comphelper::LibreOfficeKit::isActive()) officecfg::Office::Impress::MultiPaneGUI::SlideSorterBar::Visible::ImpressView::set(true,xChanges); xChanges->commit(); // if we know what theme the user wants, then we can dispatch that now early if (!sThemeName.isEmpty()) { css::uno::Sequence aPropertyValues(comphelper::InitPropertySequence( { { "NewTheme", uno::Any(sThemeName) } })); comphelper::dispatchCommand(u".uno:ChangeTheme"_ustr, aPropertyValues); } if (!sBackgroundThemeName.isEmpty()) { css::uno::Sequence aPropertyValues(comphelper::InitPropertySequence( { { "NewTheme", uno::Any(sBackgroundThemeName) } })); comphelper::dispatchCommand(".uno:InvertBackground", aPropertyValues); } } void SdXImpressDocument::postKeyEvent(int nType, int nCharCode, int nKeyCode) { SolarMutexGuard aGuard; SfxLokHelper::postKeyEventAsync(getDocWindow(), nType, nCharCode, nKeyCode); } void SdXImpressDocument::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier) { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px); if (SfxLokHelper::testInPlaceComponentMouseEventHit( pViewShell->GetViewShell(), nType, nX, nY, nCount, nButtons, nModifier, fScale, fScale)) return; // try to forward mouse event to control const Point aPointTwip(nX, nY); const Point aPointHMM = o3tl::convert(aPointTwip, o3tl::Length::twip, o3tl::Length::mm100); SdrView* pDrawView = pViewShell->GetDrawView(); SdrPageView* pPageView = pDrawView->GetSdrPageView(); SdrPage* pPage = pPageView->GetPage(); ::sd::Window* pActiveWin = pViewShell->GetActiveWindow(); if (!pActiveWin) { return; } if (LokControlHandler::postMouseEvent(pPage, pDrawView, *pActiveWin, nType, aPointHMM, nCount, nButtons, nModifier)) return; LokMouseEventData aMouseEventData(nType, aPointHMM, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier); SfxLokHelper::postMouseEventAsync(pViewShell->GetActiveWindow(), aMouseEventData); } void SdXImpressDocument::setTextSelection(int nType, int nX, int nY) { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; LokChartHelper aChartHelper(pViewShell->GetViewShell()); if (aChartHelper.setTextSelection(nType, nX, nY)) return; Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY)); switch (nType) { case LOK_SETTEXTSELECTION_START: pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/false, /*bClearMark=*/false); break; case LOK_SETTEXTSELECTION_END: pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/false); break; case LOK_SETTEXTSELECTION_RESET: pViewShell->SetCursorMm100Position(aPoint, /*bPoint=*/true, /*bClearMark=*/true); break; default: assert(false); break; } } uno::Reference SdXImpressDocument::getSelection() { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return uno::Reference(); return pViewShell->GetSelectionTransferable(); } void SdXImpressDocument::setGraphicSelection(int nType, int nX, int nY) { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; constexpr double fScale = o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::px); LokChartHelper aChartHelper(pViewShell->GetViewShell()); if (aChartHelper.setGraphicSelection(nType, nX, nY, fScale, fScale)) return; Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY)); switch (nType) { case LOK_SETGRAPHICSELECTION_START: pViewShell->SetGraphicMm100Position(/*bStart=*/true, aPoint); break; case LOK_SETGRAPHICSELECTION_END: pViewShell->SetGraphicMm100Position(/*bStart=*/false, aPoint); break; default: assert(false); break; } } void SdXImpressDocument::resetSelection() { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; SdrView* pSdrView = pViewShell->GetView(); if (!pSdrView) return; if (pSdrView->IsTextEdit()) { // Reset the editeng selection. pSdrView->UnmarkAll(); // Finish editing. pSdrView->SdrEndTextEdit(); } // Reset graphic selection. pSdrView->UnmarkAll(); } void SdXImpressDocument::setClientVisibleArea(const ::tools::Rectangle& rRectangle) { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; pViewShell->GetViewShellBase().setLOKVisibleArea(rRectangle); } void SdXImpressDocument::setClipboard(const uno::Reference& xClipboard) { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return; pViewShell->GetActiveWindow()->SetClipboard(xClipboard); } bool SdXImpressDocument::isMimeTypeSupported() { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return false; TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(pViewShell->GetActiveWindow())); return EditEngine::HasValidData(aDataHelper.GetTransferable()); } PointerStyle SdXImpressDocument::getPointer() { SolarMutexGuard aGuard; DrawViewShell* pViewShell = GetViewShell(); if (!pViewShell) return PointerStyle::Arrow; Window* pWindow = pViewShell->GetActiveWindow(); if (!pWindow) return PointerStyle::Arrow; return pWindow->GetPointer(); } uno::Reference< i18n::XForbiddenCharacters > SdXImpressDocument::getForbiddenCharsTable() { rtl::Reference xRef = mxForbiddenCharacters.get(); if( !xRef ) { xRef = new SdUnoForbiddenCharsTable( mpDoc ); mxForbiddenCharacters = xRef.get(); } return xRef; } void SdXImpressDocument::initializeDocument() { if( mbClipBoard ) return; switch( mpDoc->GetPageCount() ) { case 1: { // nasty hack to detect clipboard document mbClipBoard = true; break; } case 0: { mpDoc->CreateFirstPages(); mpDoc->StopWorkStartupDelay(); break; } } } OString SdXImpressDocument::getPresentationInfo() const { ::tools::JsonWriter aJsonWriter; try { rtl::Reference xDrawPages = const_cast(this)->getSdDrawPages(); // size in twips Size aDocSize = const_cast(this)->getDocumentSize(); aJsonWriter.put("docWidth", aDocSize.getWidth()); aJsonWriter.put("docHeight", aDocSize.getHeight()); auto aSlideList = aJsonWriter.startArray("slides"); sal_Int32 nSlideCount = xDrawPages->getCount(); for (sal_Int32 i = 0; i < nSlideCount; ++i) { SdGenericDrawPage* pSlide(xDrawPages->getDrawPageByIndex(i)); bool bIsVisible = true; // default visible pSlide->getPropertyValue("Visible") >>= bIsVisible; if (bIsVisible) { SdrPage* pPage = pSlide->GetSdrPage(); auto aSlideNode = aJsonWriter.startStruct(); std::string sSlideHash = GetInterfaceHash(cppu::getXWeak(pSlide)); aJsonWriter.put("hash", sSlideHash); aJsonWriter.put("index", i); bool bIsDrawPageEmpty = pSlide->getCount() == 0; aJsonWriter.put("empty", bIsDrawPageEmpty); // Notes SdPage* pNotesPage = mpDoc->GetSdPage((pPage->GetPageNum() - 1) >> 1, PageKind::Notes); if (pNotesPage) { SdrObject* pNotes = pNotesPage->GetPresObj(PresObjKind::Notes); if (pNotes) { OUStringBuffer strNotes; OutlinerParaObject* pPara = pNotes->GetOutlinerParaObject(); if (pPara) { const EditTextObject& rText = pPara->GetTextObject(); for (sal_Int32 nNote = 0; nNote < rText.GetParagraphCount(); nNote++) { strNotes.append(rText.GetText(nNote)); } aJsonWriter.put("notes", strNotes.makeStringAndClear()); } } } SdMasterPage* pMasterPage = nullptr; SdDrawPage* pMasterPageTarget(dynamic_cast(pSlide)); if (pMasterPageTarget) { pMasterPage = pMasterPageTarget->getSdMasterPage(); if (pMasterPage) { std::string sMPHash = GetInterfaceHash(cppu::getXWeak(pMasterPage)); aJsonWriter.put("masterPage", sMPHash); bool bBackgroundObjectsVisibility = true; // default visible pSlide->getPropertyValue("IsBackgroundObjectsVisible") >>= bBackgroundObjectsVisibility; aJsonWriter.put("masterPageObjectsVisibility", bBackgroundObjectsVisibility); } } bool bBackgroundVisibility = true; // default visible pSlide->getPropertyValue("IsBackgroundVisible") >>= bBackgroundVisibility; if (bBackgroundVisibility) { SlideBackgroundInfo aSlideBackgroundInfo(pSlide, static_cast(pMasterPage)); if (aSlideBackgroundInfo.hasBackground()) { auto aBackgroundNode = aJsonWriter.startNode("background"); aJsonWriter.put("isCustom", aSlideBackgroundInfo.slideHasOwnBackground()); if (aSlideBackgroundInfo.isSolidColor()) { aJsonWriter.put("fillColor", aSlideBackgroundInfo.getFillColorAsRGBA()); } } } { auto aVideoList = aJsonWriter.startArray("videos"); SdrObjListIter aIterator(pPage, SdrIterMode::DeepWithGroups); while (aIterator.IsMore()) { auto* pObject = aIterator.Next(); if (pObject->GetObjIdentifier() == SdrObjKind::Media) { auto aVideosNode = aJsonWriter.startStruct(); auto* pMediaObject = static_cast(pObject); auto const& rRectangle = pMediaObject->GetLogicRect(); auto aRectangle = o3tl::convert(rRectangle, o3tl::Length::mm100, o3tl::Length::twip); aJsonWriter.put("id", reinterpret_cast(pMediaObject)); aJsonWriter.put("url", pMediaObject->getTempURL()); aJsonWriter.put("x", aRectangle.Left()); aJsonWriter.put("y", aRectangle.Top()); aJsonWriter.put("width", aRectangle.GetWidth()); aJsonWriter.put("height", aRectangle.GetHeight()); } } } sal_Int32 nTransitionType = 0; pSlide->getPropertyValue("TransitionType") >>= nTransitionType; if (nTransitionType != 0) { auto iterator = constTransitionTypeToString.find(nTransitionType); if (iterator != constTransitionTypeToString.end()) { aJsonWriter.put("transitionType", iterator->second); sal_Int32 nTransitionSubtype = 0; pSlide->getPropertyValue("TransitionSubtype") >>= nTransitionSubtype; auto iteratorSubType = constTransitionSubTypeToString.find(nTransitionSubtype); if (iteratorSubType != constTransitionSubTypeToString.end()) { aJsonWriter.put("transitionSubtype", iteratorSubType->second); } else { SAL_WARN("sd", "Transition sub-type unknown: " << nTransitionSubtype); } bool nTransitionDirection = false; pSlide->getPropertyValue("TransitionDirection") >>= nTransitionDirection; aJsonWriter.put("transitionDirection", nTransitionDirection); // fade color if ((nTransitionType == TransitionType::FADE) && ((nTransitionSubtype == TransitionSubType::FADETOCOLOR) || (nTransitionSubtype == TransitionSubType::FADEFROMCOLOR) || (nTransitionSubtype == TransitionSubType::FADEOVERCOLOR))) { sal_Int32 nFadeColor = 0; pSlide->getPropertyValue("TransitionFadeColor") >>= nFadeColor; OUStringBuffer sTmpBuf; ::sax::Converter::convertColor(sTmpBuf, nFadeColor); aJsonWriter.put("transitionFadeColor", sTmpBuf.makeStringAndClear()); } } double nTransitionDuration(0.0); if( pSlide->getPropertySetInfo()->hasPropertyByName( "TransitionDuration" ) && (pSlide->getPropertyValue( "TransitionDuration" ) >>= nTransitionDuration ) && nTransitionDuration != 0.0 ) { // convert transitionDuration time to ms aJsonWriter.put("transitionDuration", nTransitionDuration * 1000); } sal_Int32 nChange(0); if( pSlide->getPropertySetInfo()->hasPropertyByName( "Change" ) && (pSlide->getPropertyValue( "Change" ) >>= nChange ) && nChange == 1 ) { double fSlideDuration(0); if( pSlide->getPropertySetInfo()->hasPropertyByName( "HighResDuration" ) && (pSlide->getPropertyValue( "HighResDuration" ) >>= fSlideDuration) ) { // convert slide duration time to ms aJsonWriter.put("nextSlideDuration", fSlideDuration * 1000); } } } sd::PresentationSettings const& rSettings = mpDoc->getPresentationSettings(); const bool bIsEndless = rSettings.mbEndless; aJsonWriter.put("isEndless", bIsEndless); if (bIsEndless) { const sal_Int32 nPauseTimeout = rSettings.mnPauseTimeout; aJsonWriter.put("loopAndRepeatDuration", nPauseTimeout); } AnimationsExporter aAnimationExporter(aJsonWriter, pSlide); if (aAnimationExporter.hasEffects()) { auto aAnimationsNode = aJsonWriter.startNode("animations"); aAnimationExporter.exportAnimations(); } } } } catch (uno::Exception& ) { TOOLS_WARN_EXCEPTION("sd", "SdXImpressDocument::getSlideShowInfo ... maybe some property can't be retrieved"); } return aJsonWriter.finishAndGetAsOString(); } bool SdXImpressDocument::createSlideRenderer( sal_Int32 nSlideNumber, sal_Int32& nViewWidth, sal_Int32& nViewHeight, bool bRenderBackground, bool bRenderMasterPage) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return false; uno::Reference xSlideShow = pViewSh->getXSlideShowInstance(); if (!xSlideShow.is()) return false; bool bSuccess = false; try { rtl::Reference xDrawPages(mpDoc->getUnoModel()); uno::Reference xSlides(xDrawPages->getDrawPages(), uno::UNO_QUERY_THROW); uno::Reference xSlide(xSlides->getByIndex(nSlideNumber), uno::UNO_QUERY_THROW); uno::Reference xAnimNodeSupplier(xSlide, uno::UNO_QUERY_THROW); uno::Reference xAnimNode = xAnimNodeSupplier->getAnimationNode(); bSuccess = xSlideShow->createLOKSlideRenderer(nViewWidth, nViewHeight, bRenderMasterPage, bRenderBackground, xSlide, xDrawPages, xAnimNode); } catch (uno::Exception&) { TOOLS_WARN_EXCEPTION( "sd", "SdXImpressDocument::createLOKSlideRenderer: failed" ); } return bSuccess; } void SdXImpressDocument::postSlideshowCleanup() { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return; pViewSh->destroyXSlideShowInstance(); } bool SdXImpressDocument::renderNextSlideLayer(unsigned char* pBuffer, bool& bIsBitmapLayer, OUString& rJsonMsg) { DrawViewShell* pViewSh = GetViewShell(); if (!pViewSh) return true; uno::Reference xSlideShow = pViewSh->getXSlideShowInstance(); if (!xSlideShow.is()) return true; auto nBufferPointer = sal::static_int_cast(reinterpret_cast(pBuffer)); sal_Bool bBitmapLayer = false; bool bDone = xSlideShow->renderNextLOKSlideLayer(nBufferPointer, bBitmapLayer, rJsonMsg); bIsBitmapLayer = bBitmapLayer; return bDone; } SdrModel& SdXImpressDocument::getSdrModelFromUnoModel() const { OSL_ENSURE(GetDoc(), "No SdrModel in draw/Impress, should not happen"); return *GetDoc(); // TTTT should be reference } void SAL_CALL SdXImpressDocument::dispose() { if( mbDisposed ) return; ::SolarMutexGuard aGuard; if( mpDoc ) { EndListening( *mpDoc ); mpDoc = nullptr; } // Call the base class dispose() before setting the mbDisposed flag // to true. The reason for this is that if close() has not yet been // called this is done in SfxBaseModel::dispose(). At the end of // that dispose() is called again. It is important to forward this // second dispose() to the base class, too. // As a consequence the following code has to be able to be run twice. SfxBaseModel::dispose(); mbDisposed = true; rtl::Reference< SdDocLinkTargets > xLinks( mxLinks ); if( xLinks.is() ) { xLinks->dispose(); xLinks = nullptr; } rtl::Reference< SdDrawPagesAccess > xDrawPagesAccess( mxDrawPagesAccess ); if( xDrawPagesAccess.is() ) { xDrawPagesAccess->dispose(); xDrawPagesAccess = nullptr; } rtl::Reference< SdMasterPagesAccess > xMasterPagesAccess( mxMasterPagesAccess ); if( xDrawPagesAccess.is() ) { xMasterPagesAccess->dispose(); xMasterPagesAccess = nullptr; } rtl::Reference< SdLayerManager > xLayerManager( mxLayerManager ); if( xLayerManager.is() ) { xLayerManager->dispose(); xLayerManager = nullptr; } mxDashTable = nullptr; mxGradientTable = nullptr; mxHatchTable = nullptr; mxBitmapTable = nullptr; mxTransGradientTable = nullptr; mxMarkerTable = nullptr; mxDrawingPool = nullptr; } SdDrawPagesAccess::SdDrawPagesAccess( SdXImpressDocument& rMyModel ) noexcept : mpModel( &rMyModel) { } SdDrawPagesAccess::~SdDrawPagesAccess() noexcept { } // XIndexAccess sal_Int32 SAL_CALL SdDrawPagesAccess::getCount() { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); return mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); } uno::Any SAL_CALL SdDrawPagesAccess::getByIndex( sal_Int32 Index ) { uno::Reference< drawing::XDrawPage > xDrawPage( getDrawPageByIndex(Index) ); return uno::Any(xDrawPage); } SdGenericDrawPage* SdDrawPagesAccess::getDrawPageByIndex( sal_Int32 Index ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); if( (Index < 0) || (Index >= mpModel->mpDoc->GetSdPageCount( PageKind::Standard ) ) ) throw lang::IndexOutOfBoundsException(); SdPage* pPage = mpModel->mpDoc->GetSdPage( static_cast(Index), PageKind::Standard ); if( pPage ) return dynamic_cast( pPage->getUnoPage().get() ); return nullptr; } // XNameAccess uno::Any SAL_CALL SdDrawPagesAccess::getByName( const OUString& aName ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); if( !aName.isEmpty() ) { const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); sal_uInt16 nPage; for( nPage = 0; nPage < nCount; nPage++ ) { SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); if(nullptr == pPage) continue; if( aName == SdDrawPage::getPageApiName( pPage ) ) { uno::Any aAny; uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); aAny <<= xDrawPage; return aAny; } } } throw container::NoSuchElementException(); } uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getElementNames() { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); uno::Sequence< OUString > aNames( nCount ); OUString* pNames = aNames.getArray(); sal_uInt16 nPage; for( nPage = 0; nPage < nCount; nPage++ ) { SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); *pNames++ = SdDrawPage::getPageApiName( pPage ); } return aNames; } sal_Bool SAL_CALL SdDrawPagesAccess::hasByName( const OUString& aName ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); const sal_uInt16 nCount = mpModel->mpDoc->GetSdPageCount( PageKind::Standard ); sal_uInt16 nPage; for( nPage = 0; nPage < nCount; nPage++ ) { SdPage* pPage = mpModel->mpDoc->GetSdPage( nPage, PageKind::Standard ); if(nullptr == pPage) continue; if( aName == SdDrawPage::getPageApiName( pPage ) ) return true; } return false; } // XElementAccess uno::Type SAL_CALL SdDrawPagesAccess::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL SdDrawPagesAccess::hasElements() { return getCount() > 0; } // XDrawPages /** * Creates a new page with model at the specified position. * @returns corresponding SdDrawPage */ uno::Reference< drawing::XDrawPage > SAL_CALL SdDrawPagesAccess::insertNewByIndex( sal_Int32 nIndex ) { ::SolarMutexGuard aGuard; comphelper::ProfileZone aZone("insertNewByIndex"); if( nullptr == mpModel ) throw lang::DisposedException(); if( mpModel->mpDoc ) { SdPage* pPage = mpModel->InsertSdPage( static_cast(nIndex), false ); if( pPage ) { uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); return xDrawPage; } } uno::Reference< drawing::XDrawPage > xDrawPage; return xDrawPage; } /** * Removes the specified SdDrawPage from the model and the internal list. It * only works, if there is at least one *normal* page in the model after * removing this page. */ void SAL_CALL SdDrawPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel || mpModel->mpDoc == nullptr ) throw lang::DisposedException(); SdDrawDocument& rDoc = *mpModel->mpDoc; sal_uInt16 nPageCount = rDoc.GetSdPageCount( PageKind::Standard ); if( nPageCount > 1 ) { // get pPage from xPage and determine the Id (nPos ) afterwards SdDrawPage* pSvxPage = comphelper::getFromUnoTunnel( xPage ); if( pSvxPage ) { SdPage* pPage = static_cast(pSvxPage->GetSdrPage()); if(pPage && ( pPage->GetPageKind() == PageKind::Standard ) ) { sal_uInt16 nPage = pPage->GetPageNum(); SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetPage( nPage+1 ) ); bool bUndo = rDoc.IsUndoEnabled(); if( bUndo ) { // Add undo actions and delete the pages. The order of adding // the undo actions is important. rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) ); rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage)); } rDoc.RemovePage( nPage ); // the page rDoc.RemovePage( nPage ); // the notes page if( bUndo ) { rDoc.EndUndo(); } } } } mpModel->SetModified(); } // XServiceInfo OUString SAL_CALL SdDrawPagesAccess::getImplementationName( ) { return u"SdDrawPagesAccess"_ustr; } sal_Bool SAL_CALL SdDrawPagesAccess::supportsService( const OUString& ServiceName ) { return cppu::supportsService(this, ServiceName); } uno::Sequence< OUString > SAL_CALL SdDrawPagesAccess::getSupportedServiceNames( ) { return { u"com.sun.star.drawing.DrawPages"_ustr }; } // XComponent void SAL_CALL SdDrawPagesAccess::dispose( ) { mpModel = nullptr; } void SAL_CALL SdDrawPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } void SAL_CALL SdDrawPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } SdMasterPagesAccess::SdMasterPagesAccess( SdXImpressDocument& rMyModel ) noexcept : mpModel(&rMyModel) { } SdMasterPagesAccess::~SdMasterPagesAccess() noexcept { } // XComponent void SAL_CALL SdMasterPagesAccess::dispose( ) { mpModel = nullptr; } void SAL_CALL SdMasterPagesAccess::addEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } void SAL_CALL SdMasterPagesAccess::removeEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } // XIndexAccess sal_Int32 SAL_CALL SdMasterPagesAccess::getCount() { ::SolarMutexGuard aGuard; if( nullptr == mpModel->mpDoc ) throw lang::DisposedException(); return mpModel->mpDoc->GetMasterSdPageCount(PageKind::Standard); } /** * Provides a drawing::XDrawPage interface for accessing the Masterpage at the * specified position in the model. */ uno::Any SAL_CALL SdMasterPagesAccess::getByIndex( sal_Int32 Index ) { ::SolarMutexGuard aGuard; comphelper::ProfileZone aZone("SdMasterPagesAccess::getByIndex"); if( nullptr == mpModel ) throw lang::DisposedException(); uno::Any aAny; if( (Index < 0) || (Index >= mpModel->mpDoc->GetMasterSdPageCount( PageKind::Standard ) ) ) throw lang::IndexOutOfBoundsException(); SdPage* pPage = mpModel->mpDoc->GetMasterSdPage( static_cast(Index), PageKind::Standard ); if( pPage ) { uno::Reference< drawing::XDrawPage > xDrawPage( pPage->getUnoPage(), uno::UNO_QUERY ); aAny <<= xDrawPage; } return aAny; } // XElementAccess uno::Type SAL_CALL SdMasterPagesAccess::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL SdMasterPagesAccess::hasElements() { return getCount() > 0; } // XDrawPages uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNewByIndex( sal_Int32 nInsertPos ) { return insertNewImpl(nInsertPos, std::nullopt); } // XDrawPages2 uno::Reference< drawing::XDrawPage > SAL_CALL SdMasterPagesAccess::insertNamedNewByIndex( sal_Int32 nInsertPos, const OUString& sName ) { return insertNewImpl(nInsertPos, sName); } uno::Reference< drawing::XDrawPage > SdMasterPagesAccess::insertNewImpl( sal_Int32 nInsertPos, std::optional oPageName ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); uno::Reference< drawing::XDrawPage > xDrawPage; SdDrawDocument* pDoc = mpModel->mpDoc; if( pDoc ) { // calculate internal index and check for range errors const sal_Int32 nMPageCount = pDoc->GetMasterPageCount(); nInsertPos = nInsertPos * 2 + 1; if( nInsertPos < 0 || nInsertPos > nMPageCount ) nInsertPos = nMPageCount; // now generate a unique name for the new masterpage OUString aPrefix; if (oPageName) aPrefix = *oPageName; else { const OUString aStdPrefix( SdResId(STR_LAYOUT_DEFAULT_NAME) ); aPrefix = aStdPrefix; bool bUnique = true; std::vector aPageNames; for (sal_Int32 nMaster = 1; nMaster < nMPageCount; ++nMaster) { const SdPage* pPage = static_cast(pDoc->GetMasterPage(static_cast(nMaster))); if (!pPage) continue; aPageNames.push_back(pPage->GetName()); if (aPageNames.back() == aPrefix) bUnique = false; } sal_Int32 i = 0; while (!bUnique) { aPrefix = aStdPrefix + " " + OUString::number(++i); bUnique = std::find(aPageNames.begin(), aPageNames.end(), aPrefix) == aPageNames.end(); } } OUString aLayoutName = aPrefix + SD_LT_SEPARATOR + STR_LAYOUT_OUTLINE; // create styles static_cast(pDoc->GetStyleSheetPool())->CreateLayoutStyleSheets( aPrefix ); // get the first page for initial size and border settings SdPage* pPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Standard ); SdPage* pRefNotesPage = mpModel->mpDoc->GetSdPage( sal_uInt16(0), PageKind::Notes); // create and insert new draw masterpage rtl::Reference pMPage = mpModel->mpDoc->AllocSdPage(true); pMPage->SetSize( pPage->GetSize() ); pMPage->SetBorder( pPage->GetLeftBorder(), pPage->GetUpperBorder(), pPage->GetRightBorder(), pPage->GetLowerBorder() ); if (oPageName) // no need to update the page URLs on a brand new page pMPage->SetName(*oPageName, /*bUpdatePageRelativeURLs*/false); pMPage->SetLayoutName( aLayoutName ); pDoc->InsertMasterPage(pMPage.get(), static_cast(nInsertPos)); { // ensure default MasterPage fill pMPage->EnsureMasterPageDefaultBackground(); } xDrawPage.set( pMPage->getUnoPage(), uno::UNO_QUERY ); // create and insert new notes masterpage rtl::Reference pMNotesPage = mpModel->mpDoc->AllocSdPage(true); pMNotesPage->SetSize( pRefNotesPage->GetSize() ); pMNotesPage->SetPageKind(PageKind::Notes); pMNotesPage->SetBorder( pRefNotesPage->GetLeftBorder(), pRefNotesPage->GetUpperBorder(), pRefNotesPage->GetRightBorder(), pRefNotesPage->GetLowerBorder() ); pMNotesPage->SetLayoutName( aLayoutName ); pDoc->InsertMasterPage(pMNotesPage.get(), static_cast(nInsertPos) + 1); pMNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, true, true); mpModel->SetModified(); } return xDrawPage; } /** * Removes the specified SdMasterPage from the model and the internal list. It * only works, if there is no *normal* page using this page as MasterPage in * the model. */ void SAL_CALL SdMasterPagesAccess::remove( const uno::Reference< drawing::XDrawPage >& xPage ) { ::SolarMutexGuard aGuard; if( nullptr == mpModel || mpModel->mpDoc == nullptr ) throw lang::DisposedException(); SdMasterPage* pSdPage = comphelper::getFromUnoTunnel( xPage ); if(pSdPage == nullptr) return; SdPage* pPage = dynamic_cast< SdPage* > (pSdPage->GetSdrPage()); DBG_ASSERT( pPage && pPage->IsMasterPage(), "SdMasterPage is not masterpage?"); if( !pPage || !pPage->IsMasterPage() || (mpModel->mpDoc->GetMasterPageUserCount(pPage) > 0)) return; //Todo: this should be excepted // only standard pages can be removed directly if( pPage->GetPageKind() != PageKind::Standard ) return; sal_uInt16 nPage = pPage->GetPageNum(); SdDrawDocument& rDoc = *mpModel->mpDoc; SdPage* pNotesPage = static_cast< SdPage* >( rDoc.GetMasterPage( nPage+1 ) ); bool bUndo = rDoc.IsUndoEnabled(); if( bUndo ) { // Add undo actions and delete the pages. The order of adding // the undo actions is important. rDoc.BegUndo( SdResId( STR_UNDO_DELETEPAGES ) ); rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); rDoc.AddUndo(rDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage)); } // remove both pages rDoc.RemoveMasterPage( nPage ); rDoc.RemoveMasterPage( nPage ); if( bUndo ) { rDoc.EndUndo(); } } // XServiceInfo OUString SAL_CALL SdMasterPagesAccess::getImplementationName( ) { return u"SdMasterPagesAccess"_ustr; } sal_Bool SAL_CALL SdMasterPagesAccess::supportsService( const OUString& ServiceName ) { return cppu::supportsService(this, ServiceName); } uno::Sequence< OUString > SAL_CALL SdMasterPagesAccess::getSupportedServiceNames( ) { return { u"com.sun.star.drawing.MasterPages"_ustr }; } SdDocLinkTargets::SdDocLinkTargets(SdXImpressDocument& rMyModel) : mpModel(&rMyModel) { for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++) aNames[i] = SdResId(aTypeResIds[i]); } SdDocLinkTargets::~SdDocLinkTargets() noexcept { } // XComponent void SAL_CALL SdDocLinkTargets::dispose( ) { mpModel = nullptr; } void SAL_CALL SdDocLinkTargets::addEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } void SAL_CALL SdDocLinkTargets::removeEventListener( const uno::Reference< lang::XEventListener >& ) { OSL_FAIL( "not implemented!" ); } // XNameAccess uno::Any SAL_CALL SdDocLinkTargets::getByName( const OUString& aName ) { if (mpModel) { for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++) if ( aNames[i] == aName ) return uno::Any(uno::Reference< beans::XPropertySet >(new SdDocLinkTargetType( mpModel, i ))); } throw container::NoSuchElementException(); } uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getElementNames() { uno::Sequence aRet(SdLinkTargetType::Count); OUString* pArray = aRet.getArray(); for (sal_uInt16 i=0; i < SdLinkTargetType::Count; i++) pArray[i] = aNames[i]; return aRet; } sal_Bool SAL_CALL SdDocLinkTargets::hasByName( const OUString& aName ) { for (const auto & i : aNames) if ( i == aName ) return true; return false; } // container::XElementAccess uno::Type SAL_CALL SdDocLinkTargets::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL SdDocLinkTargets::hasElements() { return true; } SdPage* SdDocLinkTarget::FindPage( std::u16string_view rName ) const { SdDrawDocument* pDoc = mpModel->GetDoc(); if( pDoc == nullptr ) return nullptr; const sal_uInt16 nMaxPages = pDoc->GetPageCount(); const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount(); sal_uInt16 nPage; SdPage* pPage; const bool bDraw = pDoc->GetDocumentType() == DocumentType::Draw; // standard pages for( nPage = 0; nPage < nMaxPages; nPage++ ) { pPage = static_cast(pDoc->GetPage( nPage )); if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) ) return pPage; } // master pages for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) { pPage = static_cast(pDoc->GetMasterPage( nPage )); if( (pPage->GetName() == rName) && (!bDraw || (pPage->GetPageKind() == PageKind::Standard)) ) return pPage; } return nullptr; } // XServiceInfo OUString SAL_CALL SdDocLinkTargets::getImplementationName() { return u"SdDocLinkTargets"_ustr; } sal_Bool SAL_CALL SdDocLinkTargets::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence< OUString > SAL_CALL SdDocLinkTargets::getSupportedServiceNames() { return { u"com.sun.star.document.LinkTargets"_ustr }; } SdDocLinkTargetType::SdDocLinkTargetType(SdXImpressDocument* pModel, sal_uInt16 nT) : mpModel(pModel) , mnType(nT) { maName = SdResId(aTypeResIds[nT]); } // beans::XPropertySet uno::Reference< beans::XPropertySetInfo > SAL_CALL SdDocLinkTargetType::getPropertySetInfo() { static uno::Reference< beans::XPropertySetInfo > aRef;//(new SfxItemPropertySetInfo( lcl_GetLinkTargetMap() )); return aRef; } void SAL_CALL SdDocLinkTargetType::setPropertyValue(const OUString& /* aPropertyName */, const uno::Any& /* aValue */) { // everything is read-only } uno::Any SAL_CALL SdDocLinkTargetType::getPropertyValue(const OUString& PropertyName) { uno::Any aRet; if ( PropertyName == "LinkDisplayName" ) aRet <<= maName; return aRet; } void SAL_CALL SdDocLinkTargetType::addPropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SdDocLinkTargetType::removePropertyChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SdDocLinkTargetType::addVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } void SAL_CALL SdDocLinkTargetType::removeVetoableChangeListener( const OUString&, const uno::Reference&) { OSL_FAIL("not implemented"); } // document::XLinkTargetSupplier uno::Reference< container::XNameAccess > SAL_CALL SdDocLinkTargetType::getLinks() { return new SdDocLinkTarget( mpModel, mnType ); } // XServiceInfo OUString SAL_CALL SdDocLinkTargetType::getImplementationName() { return u"SdDocLinkTargetType"_ustr; } sal_Bool SAL_CALL SdDocLinkTargetType::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence< OUString > SAL_CALL SdDocLinkTargetType::getSupportedServiceNames() { return { u"com.sun.star.document.LinkTargetSupplier"_ustr }; } SdDocLinkTarget::SdDocLinkTarget( SdXImpressDocument* pModel, sal_uInt16 nT ) : mpModel(pModel) , mnType(nT) { } // container::XNameAccess uno::Any SAL_CALL SdDocLinkTarget::getByName(const OUString& aName) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); SdPage* pPage = FindPage( aName ); if( pPage == nullptr ) throw container::NoSuchElementException(); uno::Any aAny; uno::Reference< beans::XPropertySet > xProps( pPage->getUnoPage(), uno::UNO_QUERY ); if( xProps.is() ) aAny <<= xProps; return aAny; } uno::Sequence SAL_CALL SdDocLinkTarget::getElementNames() { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); SdDrawDocument* pDoc = mpModel->GetDoc(); if( pDoc == nullptr ) { return { }; } if( pDoc->GetDocumentType() == DocumentType::Draw ) { const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( PageKind::Standard ); const sal_uInt16 nMaxMasterPages = pDoc->GetMasterSdPageCount( PageKind::Standard ); uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::Page ? nMaxPages : nMaxMasterPages ); OUString* pStr = aSeq.getArray(); sal_uInt16 nPage; if (mnType == SdLinkTargetType::Page) { // standard pages for( nPage = 0; nPage < nMaxPages; nPage++ ) *pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName(); } else { // master pages for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) *pStr++ = pDoc->GetMasterSdPage( nPage, PageKind::Standard )->GetName(); } return aSeq; } else { PageKind eKind; switch (mnType) { case SdLinkTargetType::Notes: eKind = PageKind::Notes; break; case SdLinkTargetType::Handout: eKind = PageKind::Handout; break; default: eKind = PageKind::Standard; break; } const sal_uInt16 nMaxPages = pDoc->GetSdPageCount( eKind ); const sal_uInt16 nMaxMasterPages = pDoc->GetMasterPageCount(); uno::Sequence< OUString > aSeq( mnType == SdLinkTargetType::MasterPage ? nMaxMasterPages : nMaxPages ); OUString* pStr = aSeq.getArray(); sal_uInt16 nPage; switch (mnType) { case SdLinkTargetType::Page: { for( nPage = 0; nPage < nMaxPages; nPage++ ) *pStr++ = pDoc->GetSdPage( nPage, PageKind::Standard )->GetName(); break; } case SdLinkTargetType::Notes: { for( nPage = 0; nPage < nMaxPages; nPage++ ) *pStr++ = pDoc->GetSdPage( nPage, PageKind::Notes )->GetName(); break; } case SdLinkTargetType::Handout: { for( nPage = 0; nPage < nMaxPages; nPage++ ) *pStr++ = pDoc->GetSdPage( nPage, PageKind::Handout )->GetName(); break; } case SdLinkTargetType::MasterPage: { for( nPage = 0; nPage < nMaxMasterPages; nPage++ ) *pStr++ = static_cast(pDoc->GetMasterPage( nPage ))->GetName(); break; } } return aSeq; } } sal_Bool SAL_CALL SdDocLinkTarget::hasByName(const OUString& aName) { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); return FindPage( aName ) != nullptr; } // container::XElementAccess uno::Type SAL_CALL SdDocLinkTarget::getElementType() { return cppu::UnoType::get(); } sal_Bool SAL_CALL SdDocLinkTarget::hasElements() { ::SolarMutexGuard aGuard; if( nullptr == mpModel ) throw lang::DisposedException(); return mpModel->GetDoc() != nullptr; } // XServiceInfo OUString SAL_CALL SdDocLinkTarget::getImplementationName() { return u"SdDocLinkTarget"_ustr; } sal_Bool SAL_CALL SdDocLinkTarget::supportsService( const OUString& ServiceName ) { return cppu::supportsService( this, ServiceName ); } uno::Sequence< OUString > SAL_CALL SdDocLinkTarget::getSupportedServiceNames() { return { u"com.sun.star.document.LinkTargets"_ustr }; } rtl::Reference< SdXImpressDocument > SdXImpressDocument::GetModel( SdDrawDocument const & rDocument ) { rtl::Reference< SdXImpressDocument > xRet; ::sd::DrawDocShell* pDocShell(rDocument.GetDocSh()); if( pDocShell ) { uno::Reference xModel(pDocShell->GetModel()); xRet.set( dynamic_cast< SdXImpressDocument* >( xModel.get() ) ); } return xRet; } void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName) { rtl::Reference xModel(SdXImpressDocument::GetModel(rDocument)); if (xModel.is()) { uno::Reference xSource(static_cast(xModel.get())); NotifyDocumentEvent(rDocument, rEventName, xSource); } } void NotifyDocumentEvent(SdDrawDocument const & rDocument, const OUString& rEventName, const uno::Reference& xSource) { rtl::Reference xModel(SdXImpressDocument::GetModel(rDocument)); if (xModel.is()) { css::document::EventObject aEvent(xSource, rEventName); xModel->notifyEvent(aEvent); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */