/* -*- 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 "XMLAnchorTypePropHdl.hxx" #include #include #include #include #include #include #include #include #include #include "XMLTextFrameContext.hxx" #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::text; using namespace ::com::sun::star::xml::sax; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::container; using namespace ::com::sun::star::drawing; using namespace ::com::sun::star::document; using namespace ::xmloff::token; using ::com::sun::star::document::XEventsSupplier; #define XML_TEXT_FRAME_TEXTBOX 1 #define XML_TEXT_FRAME_GRAPHIC 2 #define XML_TEXT_FRAME_OBJECT 3 #define XML_TEXT_FRAME_OBJECT_OLE 4 #define XML_TEXT_FRAME_APPLET 5 #define XML_TEXT_FRAME_PLUGIN 6 #define XML_TEXT_FRAME_FLOATING_FRAME 7 typedef ::std::map < const OUString, OUString > ParamMap; class XMLTextFrameContextHyperlink_Impl { OUString sHRef; OUString sName; OUString sTargetFrameName; bool bMap; public: inline XMLTextFrameContextHyperlink_Impl( OUString aHRef, OUString aName, OUString aTargetFrameName, bool bMap ); const OUString& GetHRef() const { return sHRef; } const OUString& GetName() const { return sName; } const OUString& GetTargetFrameName() const { return sTargetFrameName; } bool GetMap() const { return bMap; } }; inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl( OUString aHRef, OUString aName, OUString aTargetFrameName, bool bM ) : sHRef(std::move( aHRef )), sName(std::move( aName )), sTargetFrameName(std::move( aTargetFrameName )), bMap( bM ) { } namespace { // Implement Title/Description Elements UI (#i73249#) class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext { OUString& mrTitleOrDesc; public: XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport, OUString& rTitleOrDesc ); virtual void SAL_CALL characters( const OUString& rText ) override; }; } XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport, OUString& rTitleOrDesc ) : SvXMLImportContext( rImport ) , mrTitleOrDesc( rTitleOrDesc ) { } void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString& rText ) { mrTitleOrDesc += rText; } namespace { class XMLTextFrameParam_Impl : public SvXMLImportContext { public: XMLTextFrameParam_Impl( SvXMLImport& rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList, ParamMap &rParamMap); }; } XMLTextFrameParam_Impl::XMLTextFrameParam_Impl( SvXMLImport& rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList, ParamMap &rParamMap): SvXMLImportContext( rImport ) { OUString sName, sValue; bool bFoundValue = false; // to allow empty values for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) { switch (aIter.getToken()) { case XML_ELEMENT(DRAW, XML_VALUE): { sValue = aIter.toString(); bFoundValue = true; break; } case XML_ELEMENT(DRAW, XML_NAME): sName = aIter.toString(); break; default: XMLOFF_WARN_UNKNOWN("xmloff", aIter); } } if (!sName.isEmpty() && bFoundValue ) rParamMap[sName] = sValue; } namespace { class XMLTextFrameContourContext_Impl : public SvXMLImportContext { Reference < XPropertySet > xPropSet; public: XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList, const Reference < XPropertySet >& rPropSet, bool bPath ); }; } XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 /*nElement*/, const Reference< XFastAttributeList > & xAttrList, const Reference < XPropertySet >& rPropSet, bool bPath ) : SvXMLImportContext( rImport ), xPropSet( rPropSet ) { OUString sD, sPoints, sViewBox; bool bPixelWidth = false, bPixelHeight = false; bool bAuto = false; sal_Int32 nWidth = 0; sal_Int32 nHeight = 0; for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) { switch( aIter.getToken() ) { case XML_ELEMENT(SVG, XML_VIEWBOX): case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX): sViewBox = aIter.toString(); break; case XML_ELEMENT(SVG, XML_D): case XML_ELEMENT(SVG_COMPAT, XML_D): if( bPath ) sD = aIter.toString(); break; case XML_ELEMENT(DRAW,XML_POINTS): if( !bPath ) sPoints = aIter.toString(); break; case XML_ELEMENT(SVG, XML_WIDTH): case XML_ELEMENT(SVG_COMPAT, XML_WIDTH): if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView())) bPixelWidth = true; else GetImport().GetMM100UnitConverter().convertMeasureToCore( nWidth, aIter.toView()); break; case XML_ELEMENT(SVG, XML_HEIGHT): case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT): if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView())) bPixelHeight = true; else GetImport().GetMM100UnitConverter().convertMeasureToCore( nHeight, aIter.toView()); break; case XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT): bAuto = IsXMLToken(aIter, XML_TRUE); break; } } OUString sContourPolyPolygon("ContourPolyPolygon"); Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo(); if(!xPropSetInfo->hasPropertyByName(sContourPolyPolygon) || nWidth <= 0 || nHeight <= 0 || bPixelWidth != bPixelHeight || !(bPath ? sD : sPoints).getLength()) return; const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter()); basegfx::B2DPolyPolygon aPolyPolygon; if( bPath ) { basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr); } else { basegfx::B2DPolygon aPolygon; if(basegfx::utils::importFromSvgPoints(aPolygon, sPoints)) { aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon); } } if(aPolyPolygon.count()) { const basegfx::B2DRange aSourceRange( aViewBox.GetX(), aViewBox.GetY(), aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight()); const basegfx::B2DRange aTargetRange( 0.0, 0.0, nWidth, nHeight); if(!aSourceRange.equal(aTargetRange)) { aPolyPolygon.transform( basegfx::utils::createSourceRangeTargetRangeTransform( aSourceRange, aTargetRange)); } css::drawing::PointSequenceSequence aPointSequenceSequence; basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence); xPropSet->setPropertyValue( sContourPolyPolygon, Any(aPointSequenceSequence) ); } static const OUStringLiteral sIsPixelContour(u"IsPixelContour"); if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) ) { xPropSet->setPropertyValue( sIsPixelContour, Any(bPixelWidth) ); } static const OUStringLiteral sIsAutomaticContour(u"IsAutomaticContour"); if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) ) { xPropSet->setPropertyValue( sIsAutomaticContour, Any(bAuto) ); } } namespace { class XMLTextFrameContext_Impl : public SvXMLImportContext { css::uno::Reference < css::text::XTextCursor > xOldTextCursor; css::uno::Reference < css::beans::XPropertySet > xPropSet; css::uno::Reference < css::io::XOutputStream > xBase64Stream; /// old list item and block (#89891#) bool mbListContextPushed; OUString m_sOrigName; OUString sName; OUString sStyleName; OUString sNextName; OUString sHRef; OUString sCode; OUString sMimeType; OUString sFrameName; OUString sAppletName; OUString sFilterService; OUString sBase64CharsLeft; OUString sTblName; OUStringBuffer maUrlBuffer; ParamMap aParamMap; sal_Int32 nX; sal_Int32 nY; sal_Int32 nWidth; sal_Int32 nHeight; sal_Int32 nZIndex; sal_Int16 nPage; sal_Int16 nRotation; sal_Int16 nRelWidth; sal_Int16 nRelHeight; sal_uInt16 nType; css::text::TextContentAnchorType eAnchorType; bool bMayScript : 1; bool bMinWidth : 1; bool bMinHeight : 1; bool bSyncWidth : 1; bool bSyncHeight : 1; bool bCreateFailed : 1; bool bOwnBase64Stream : 1; bool mbMultipleContent : 1; // This context is created based on a multiple content (image) bool m_isDecorative = false; bool m_isSplitAllowed = false; void Create(); public: bool CreateIfNotThere(); const OUString& GetHRef() const { return sHRef; } XMLTextFrameContext_Impl( SvXMLImport& rImport, sal_Int32 nElement, const css::uno::Reference & rAttrList, css::text::TextContentAnchorType eAnchorType, sal_uInt16 nType, const css::uno::Reference & rFrameAttrList, bool bMultipleContent = false ); virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; virtual void SAL_CALL characters( const OUString& rChars ) override; virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override; void SetHyperlink( const OUString& rHRef, const OUString& rName, const OUString& rTargetFrameName, bool bMap ); // Implement Title/Description Elements UI (#i73249#) void SetTitle( const OUString& rTitle ); void SetDesc( const OUString& rDesc ); void SetName(); const OUString& GetOrigName() const { return m_sOrigName; } css::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; } const css::uno::Reference < css::beans::XPropertySet >& GetPropSet() const { return xPropSet; } }; } void XMLTextFrameContext_Impl::Create() { rtl::Reference < XMLTextImportHelper > xTextImportHelper = GetImport().GetTextImport(); switch ( nType) { case XML_TEXT_FRAME_OBJECT: case XML_TEXT_FRAME_OBJECT_OLE: if( xBase64Stream.is() ) { OUString sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() ); if( !sURL.isEmpty() ) xPropSet = GetImport().GetTextImport() ->createAndInsertOLEObject( GetImport(), sURL, sStyleName, sTblName, nWidth, nHeight ); } else if( !sHRef.isEmpty() ) { OUString sURL( GetImport().ResolveEmbeddedObjectURL( sHRef, std::u16string_view() ) ); if( GetImport().IsPackageURL( sHRef ) ) { xPropSet = GetImport().GetTextImport() ->createAndInsertOLEObject( GetImport(), sURL, sStyleName, sTblName, nWidth, nHeight ); } else { // it should be an own OOo link that has no storage persistence xPropSet = GetImport().GetTextImport() ->createAndInsertOOoLink( GetImport(), sURL, sStyleName, sTblName, nWidth, nHeight ); } } else { OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService; xPropSet = GetImport().GetTextImport() ->createAndInsertOLEObject( GetImport(), sURL, sStyleName, sTblName, nWidth, nHeight ); } break; case XML_TEXT_FRAME_APPLET: { xPropSet = GetImport().GetTextImport() ->createAndInsertApplet( sAppletName, sCode, bMayScript, sHRef, nWidth, nHeight); break; } case XML_TEXT_FRAME_PLUGIN: { if(!sHRef.isEmpty()) GetImport().GetAbsoluteReference(sHRef); xPropSet = GetImport().GetTextImport() ->createAndInsertPlugin( sMimeType, sHRef, nWidth, nHeight); break; } case XML_TEXT_FRAME_FLOATING_FRAME: { xPropSet = GetImport().GetTextImport() ->createAndInsertFloatingFrame( sFrameName, sHRef, sStyleName, nWidth, nHeight); break; } default: { Reference xFactory( GetImport().GetModel(), UNO_QUERY ); if( xFactory.is() ) { OUString sServiceName; switch( nType ) { case XML_TEXT_FRAME_TEXTBOX: sServiceName = "com.sun.star.text.TextFrame"; break; case XML_TEXT_FRAME_GRAPHIC: sServiceName = "com.sun.star.text.GraphicObject"; break; } Reference xIfc = xFactory->createInstance( sServiceName ); SAL_WARN_IF( !xIfc.is(), "xmloff.text", "couldn't create frame" ); if( xIfc.is() ) xPropSet.set( xIfc, UNO_QUERY ); } } } if( !xPropSet.is() ) { bCreateFailed = true; return; } Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); // Skip duplicated frames if(!mbMultipleContent && // It's allowed to have multiple image for the same frame !sName.isEmpty() && xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight)) { bCreateFailed = true; return; } // set name Reference < XNamed > xNamed( xPropSet, UNO_QUERY ); if( xNamed.is() ) { OUString sOrigName( xNamed->getName() ); if( sOrigName.isEmpty() || (!sName.isEmpty() && sOrigName != sName) ) { OUString sOldName( sName ); sal_Int32 i = 0; while( xTextImportHelper->HasFrameByName( sName ) ) { sName = sOldName + OUString::number( ++i ); } xNamed->setName( sName ); if( sName != sOldName ) { xTextImportHelper->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME, sOldName, sName ); } } } // frame style XMLPropStyleContext *pStyle = nullptr; if( !sStyleName.isEmpty() ) { pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName ); if( pStyle ) sStyleName = pStyle->GetParentName(); } Any aAny; if( !sStyleName.isEmpty() ) { OUString sDisplayStyleName( GetImport().GetStyleDisplayName( XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) ); const Reference < XNameContainer > & rStyles = xTextImportHelper->GetFrameStyles(); if( rStyles.is() && rStyles->hasByName( sDisplayStyleName ) ) { xPropSet->setPropertyValue( "FrameStyleName", Any(sDisplayStyleName) ); } } // anchor type (must be set before any other properties, because // otherwise some orientations cannot be set or will be changed // afterwards) xPropSet->setPropertyValue( "AnchorType", Any(eAnchorType) ); // hard properties if( pStyle ) pStyle->FillPropertySet( xPropSet ); // x and y sal_Int16 nHoriOrient = HoriOrientation::NONE; aAny = xPropSet->getPropertyValue( "HoriOrient" ); aAny >>= nHoriOrient; if( HoriOrientation::NONE == nHoriOrient ) { xPropSet->setPropertyValue( "HoriOrientPosition", Any(nX) ); } sal_Int16 nVertOrient = VertOrientation::NONE; aAny = xPropSet->getPropertyValue( "VertOrient" ); aAny >>= nVertOrient; if( VertOrientation::NONE == nVertOrient ) { xPropSet->setPropertyValue( "VertOrientPosition", Any(nY) ); } // width if( nWidth > 0 ) { xPropSet->setPropertyValue( "Width", Any(nWidth) ); } if( nRelWidth > 0 || nWidth > 0 ) { xPropSet->setPropertyValue( "RelativeWidth", Any(nRelWidth) ); } if( bSyncWidth || nWidth > 0 ) { xPropSet->setPropertyValue( "IsSyncWidthToHeight", Any(bSyncWidth) ); } if( xPropSetInfo->hasPropertyByName( "WidthType" ) && (bMinWidth || nWidth > 0 || nRelWidth > 0 ) ) { sal_Int16 nSizeType = (bMinWidth && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN : SizeType::FIX; xPropSet->setPropertyValue( "WidthType", Any(nSizeType) ); } if( nHeight > 0 ) { xPropSet->setPropertyValue( "Height", Any(nHeight) ); } if( nRelHeight > 0 || nHeight > 0 ) { xPropSet->setPropertyValue( "RelativeHeight", Any(nRelHeight) ); } if( bSyncHeight || nHeight > 0 ) { xPropSet->setPropertyValue( "IsSyncHeightToWidth", Any(bSyncHeight) ); } if( xPropSetInfo->hasPropertyByName( "SizeType" ) && (bMinHeight || nHeight > 0 || nRelHeight > 0 ) ) { sal_Int16 nSizeType = (bMinHeight && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN : SizeType::FIX; xPropSet->setPropertyValue( "SizeType", Any(nSizeType) ); } if( XML_TEXT_FRAME_GRAPHIC == nType ) { // URL OSL_ENSURE( !sHRef.isEmpty() || xBase64Stream.is(), "neither URL nor base64 image data given" ); uno::Reference xGraphic; if (!sHRef.isEmpty()) { xGraphic = GetImport().loadGraphicByURL(sHRef); } else if (xBase64Stream.is()) { xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream); xBase64Stream = nullptr; } if (xGraphic.is()) xPropSet->setPropertyValue("Graphic", Any(xGraphic)); // filter name xPropSet->setPropertyValue( "GraphicFilter", Any(OUString()) ); // rotation xPropSet->setPropertyValue( "GraphicRotation", Any(nRotation) ); } // page number (must be set after the frame is inserted, because it // will be overwritten then inserting the frame. if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 ) { xPropSet->setPropertyValue( "AnchorPageNo", Any(nPage) ); } if (m_isDecorative && xPropSetInfo->hasPropertyByName("Decorative")) { xPropSet->setPropertyValue("Decorative", uno::Any(true)); } if (m_isSplitAllowed && xPropSetInfo->hasPropertyByName("IsSplitAllowed")) { xPropSet->setPropertyValue("IsSplitAllowed", uno::Any(true)); } if( XML_TEXT_FRAME_OBJECT != nType && XML_TEXT_FRAME_OBJECT_OLE != nType && XML_TEXT_FRAME_APPLET != nType && XML_TEXT_FRAME_PLUGIN!= nType && XML_TEXT_FRAME_FLOATING_FRAME != nType) { Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY ); try { xTextImportHelper->InsertTextContent(xTxtCntnt); } catch (lang::IllegalArgumentException const&) { TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?"); return; } } // Make adding the shape to Z-Ordering dependent from if we are // inside an inside_deleted_section (redlining). That is necessary // since the shape will be removed again later. It would lead to // errors if it would stay inside the Z-Ordering. Thus, the // easiest way to solve that conflict is to not add it here. if(!GetImport().HasTextImport() || !GetImport().GetTextImport()->IsInsideDeleteContext()) { Reference < XShape > xShape( xPropSet, UNO_QUERY ); GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex ); } if( XML_TEXT_FRAME_TEXTBOX != nType ) return; xTextImportHelper->ConnectFrameChains( sName, sNextName, xPropSet ); Reference < XTextFrame > xTxtFrame( xPropSet, UNO_QUERY ); Reference < XText > xTxt = xTxtFrame->getText(); xOldTextCursor = xTextImportHelper->GetCursor(); xTextImportHelper->SetCursor( xTxt->createTextCursor() ); // remember old list item and block (#89892#) and reset them // for the text frame xTextImportHelper->PushListContext(); mbListContextPushed = true; } void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext) { const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext); if(!pXMLTextFrameContext_Impl) return; try { // just dispose to delete uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY); // Inform shape importer about the removal so it can adjust // z-indexes. uno::Reference xShape(xComp, uno::UNO_QUERY); GetImport().GetShapeImport()->shapeRemoved(xShape); if(xComp.is()) { xComp->dispose(); } } catch( uno::Exception& ) { OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" ); } } OUString XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const { const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext); if(pXMLTextFrameContext_Impl) { return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl->GetHRef(); } return OUString(); } css::uno::Reference XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const { uno::Reference xGraphic; const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast(&rContext); if (pXMLTextFrameContext_Impl) { try { const uno::Reference& xPropertySet = pXMLTextFrameContext_Impl->GetPropSet(); if (xPropertySet.is()) { xPropertySet->getPropertyValue("Graphic") >>= xGraphic; } } catch (uno::Exception&) {} } return xGraphic; } bool XMLTextFrameContext_Impl::CreateIfNotThere() { if( !xPropSet.is() && ( XML_TEXT_FRAME_OBJECT_OLE == nType || XML_TEXT_FRAME_GRAPHIC == nType ) && xBase64Stream.is() && !bCreateFailed ) { if( bOwnBase64Stream ) xBase64Stream->closeOutput(); Create(); } return xPropSet.is(); } XMLTextFrameContext_Impl::XMLTextFrameContext_Impl( SvXMLImport& rImport, sal_Int32 /*nElement*/, const Reference< XFastAttributeList > & rAttrList, TextContentAnchorType eATyp, sal_uInt16 nNewType, const Reference< XFastAttributeList > & rFrameAttrList, bool bMultipleContent ) : SvXMLImportContext( rImport ) , mbListContextPushed( false ) , nType( nNewType ) , eAnchorType( eATyp ) { nX = 0; nY = 0; nWidth = 0; nHeight = 0; nZIndex = -1; nPage = 0; nRotation = 0; nRelWidth = 0; nRelHeight = 0; bMayScript = false; bMinHeight = false; bMinWidth = false; bSyncWidth = false; bSyncHeight = false; bCreateFailed = false; bOwnBase64Stream = false; mbMultipleContent = bMultipleContent; auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void { switch( nElement ) { case XML_ELEMENT(DRAW, XML_STYLE_NAME): sStyleName = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_NAME): m_sOrigName = aIter.toString(); sName = m_sOrigName; break; case XML_ELEMENT(DRAW, XML_FRAME_NAME): sFrameName = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_APPLET_NAME): sAppletName = aIter.toString(); break; case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE): if( TextContentAnchorType_AT_PARAGRAPH == eAnchorType || TextContentAnchorType_AT_CHARACTER == eAnchorType || TextContentAnchorType_AS_CHARACTER == eAnchorType ) { TextContentAnchorType eNew; if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) && ( TextContentAnchorType_AT_PARAGRAPH == eNew || TextContentAnchorType_AT_CHARACTER == eNew || TextContentAnchorType_AS_CHARACTER == eNew || TextContentAnchorType_AT_PAGE == eNew) ) eAnchorType = eNew; } break; case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER): { sal_Int32 nTmp; if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, SHRT_MAX)) nPage = static_cast(nTmp); } break; case XML_ELEMENT(SVG, XML_X): case XML_ELEMENT(SVG_COMPAT, XML_X): GetImport().GetMM100UnitConverter().convertMeasureToCore( nX, aIter.toView()); break; case XML_ELEMENT(SVG, XML_Y): case XML_ELEMENT(SVG_COMPAT, XML_Y): GetImport().GetMM100UnitConverter().convertMeasureToCore( nY, aIter.toView() ); break; case XML_ELEMENT(SVG, XML_WIDTH): case XML_ELEMENT(SVG_COMPAT, XML_WIDTH): // relative widths are obsolete since SRC617. Remove them some day! if( aIter.toView().find( '%' ) != std::string_view::npos ) { sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView())) nRelWidth = static_cast(nTmp); } else { GetImport().GetMM100UnitConverter().convertMeasureToCore( nWidth, aIter.toView(), 0 ); } break; case XML_ELEMENT(STYLE, XML_REL_WIDTH): if( IsXMLToken(aIter, XML_SCALE) ) { bSyncWidth = true; } else { sal_Int32 nTmp; if (::sax::Converter::convertPercent( nTmp, aIter.toView() )) nRelWidth = static_cast(nTmp); } break; case XML_ELEMENT(FO, XML_MIN_WIDTH): case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH): if( aIter.toView().find( '%' ) != std::string_view::npos ) { sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView())) nRelWidth = static_cast(nTmp); } else { GetImport().GetMM100UnitConverter().convertMeasureToCore( nWidth, aIter.toView(), 0 ); } bMinWidth = true; break; case XML_ELEMENT(SVG, XML_HEIGHT): case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT): // relative heights are obsolete since SRC617. Remove them some day! if( aIter.toView().find( '%' ) != std::string_view::npos ) { sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView())) nRelHeight = static_cast(nTmp); } else { GetImport().GetMM100UnitConverter().convertMeasureToCore( nHeight, aIter.toView(), 0 ); } break; case XML_ELEMENT(STYLE, XML_REL_HEIGHT): if( IsXMLToken( aIter, XML_SCALE ) ) { bSyncHeight = true; } else if( IsXMLToken( aIter, XML_SCALE_MIN ) ) { bSyncHeight = true; bMinHeight = true; } else { sal_Int32 nTmp; if (::sax::Converter::convertPercent( nTmp, aIter.toView() )) nRelHeight = static_cast(nTmp); } break; case XML_ELEMENT(FO, XML_MIN_HEIGHT): case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT): if( aIter.toView().find( '%' ) != std::string_view::npos ) { sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView())) nRelHeight = static_cast(nTmp); } else { GetImport().GetMM100UnitConverter().convertMeasureToCore( nHeight, aIter.toView(), 0 ); } bMinHeight = true; break; case XML_ELEMENT(DRAW, XML_ZINDEX): ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 ); break; case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME): sNextName = aIter.toString(); break; case XML_ELEMENT(XLINK, XML_HREF): sHRef = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_TRANSFORM): { // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling // Currently only rotation is used, but combinations with 'draw:transform' // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height // may be extended/replaced with 'draw:transform' (see draw objects) SdXMLImExTransform2D aSdXMLImExTransform2D; basegfx::B2DHomMatrix aFullTransform; // Use SdXMLImExTransform2D to convert to transformation // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed, // but is not generally available (as it should be, a 'current' UnitConverter should // be available at GetExport() - and maybe was once). May have to be addressed as soon // as translate transformations are used here. aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter()); aSdXMLImExTransform2D.GetFullTransform(aFullTransform); if(!aFullTransform.isIdentity()) { const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform); // currently we *only* use rotation (and translation indirectly), so warn if *any* // of the other transform parts is used SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" ); SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" ); SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" ); // Translation comes from the translate to RotCenter, rot and BackTranslate. // This means that it represents the translation between unrotated TopLeft // and rotated TopLeft. This may be checked here now, but currently we only // use rotation around center and assume that this *was* a rotation around // center. The check would compare the object's center with the RotCenter // that can be extracted from the transformation in aFullTransform. // The definition contains implicitly the RotationCenter absolute // to the scaled and translated object, so this may be used if needed (see // _exportTextGraphic how the -trans/rot/trans is composed) if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate())) { // rotation is used, set it. Convert from deg to 10th degree integer // CAUTION: due to #i78696# (rotation mirrored using API) the rotate // value is already mirrored, so do not do it again here (to be in sync // with XMLTextParagraphExport::_exportTextGraphic normally it would need // to me mirrored using * -1.0, see conversion there) // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it // with the wrong orientation as in all other cases - ARGH! We will need to // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN const double fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate())); nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600); // tdf#115529 may be negative, with the above modulo maximal -3599, so // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation") // and *has* to be in the range [0 .. 3600[ if(nRotation < 0) { nRotation += 3600; } } } } break; case XML_ELEMENT(DRAW, XML_CODE): sCode = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_OBJECT): break; case XML_ELEMENT(DRAW, XML_ARCHIVE): break; case XML_ELEMENT(DRAW, XML_MAY_SCRIPT): bMayScript = IsXMLToken( aIter, XML_TRUE ); break; case XML_ELEMENT(DRAW, XML_MIME_TYPE): case XML_ELEMENT(LO_EXT, XML_MIME_TYPE): sMimeType = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES): case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE): sTblName = aIter.toString(); break; case XML_ELEMENT(LO_EXT, XML_DECORATIVE): case XML_ELEMENT(DRAW, XML_DECORATIVE): ::sax::Converter::convertBool(m_isDecorative, aIter.toString()); break; case XML_ELEMENT(LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES): case XML_ELEMENT(DRAW, XML_MAY_BREAK_BETWEEN_PAGES): sax::Converter::convertBool(m_isSplitAllowed, aIter.toString()); break; default: SAL_INFO("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " value=" << aIter.toString()); } }; for( auto& aIter : sax_fastparser::castToFastAttributeList(rAttrList) ) processAttr(aIter.getToken(), aIter); for( auto& aIter : sax_fastparser::castToFastAttributeList(rFrameAttrList) ) processAttr(aIter.getToken(), aIter); if( ( (XML_TEXT_FRAME_GRAPHIC == nType || XML_TEXT_FRAME_OBJECT == nType || XML_TEXT_FRAME_OBJECT_OLE == nType) && sHRef.isEmpty() ) || ( XML_TEXT_FRAME_APPLET == nType && sCode.isEmpty() ) || ( XML_TEXT_FRAME_PLUGIN == nType && sHRef.isEmpty() && sMimeType.isEmpty() ) ) return; // no URL: no image or OLE object Create(); } void XMLTextFrameContext_Impl::endFastElement(sal_Int32 ) { if( ( XML_TEXT_FRAME_OBJECT_OLE == nType || XML_TEXT_FRAME_GRAPHIC == nType) && !xPropSet.is() && !bCreateFailed ) { std::u16string_view sTrimmedChars = o3tl::trim(maUrlBuffer); if( !sTrimmedChars.empty() ) { if( !xBase64Stream.is() ) { if( XML_TEXT_FRAME_GRAPHIC == nType ) { xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64(); } else { xBase64Stream = GetImport().GetStreamForEmbeddedObjectURLFromBase64(); } if( xBase64Stream.is() ) bOwnBase64Stream = true; } if( bOwnBase64Stream && xBase64Stream.is() ) { OUString sChars; if( !sBase64CharsLeft.isEmpty() ) { sChars = sBase64CharsLeft + sTrimmedChars; sBase64CharsLeft.clear(); } else { sChars = sTrimmedChars; } Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 ); sal_Int32 nCharsDecoded = ::comphelper::Base64::decodeSomeChars( aBuffer, sChars ); xBase64Stream->writeBytes( aBuffer ); if( nCharsDecoded != sChars.getLength() ) sBase64CharsLeft = sChars.copy( nCharsDecoded ); } } maUrlBuffer.setLength(0); } CreateIfNotThere(); if( xOldTextCursor.is() ) { GetImport().GetTextImport()->DeleteParagraph(); GetImport().GetTextImport()->SetCursor( xOldTextCursor ); } // reinstall old list item (if necessary) #89892# if (mbListContextPushed) { GetImport().GetTextImport()->PopListContext(); } if (( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) && xPropSet.is()) GetImport().GetTextImport()->endAppletOrPlugin( xPropSet, aParamMap); } css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext_Impl::createFastChildContext( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) { if( nElement == XML_ELEMENT(DRAW, XML_PARAM) ) { if ( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) return new XMLTextFrameParam_Impl( GetImport(), xAttrList, aParamMap ); } else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) ) { if( !xPropSet.is() && !xBase64Stream.is() && !bCreateFailed ) { switch( nType ) { case XML_TEXT_FRAME_GRAPHIC: xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64(); break; case XML_TEXT_FRAME_OBJECT_OLE: xBase64Stream = GetImport().GetStreamForEmbeddedObjectURLFromBase64(); break; } if( xBase64Stream.is() ) return new XMLBase64ImportContext( GetImport(), xBase64Stream ); } } // Correction of condition which also avoids warnings. (#i100480#) if( XML_TEXT_FRAME_OBJECT == nType && ( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) || nElement == XML_ELEMENT(MATH, XML_MATH) ) ) { if( !xPropSet.is() && !bCreateFailed ) { XMLEmbeddedObjectImportContext *pEContext = new XMLEmbeddedObjectImportContext( GetImport(), nElement, xAttrList ); sFilterService = pEContext->GetFilterServiceName(); if( !sFilterService.isEmpty() ) { Create(); if( xPropSet.is() ) { Reference < XEmbeddedObjectSupplier > xEOS( xPropSet, UNO_QUERY ); OSL_ENSURE( xEOS.is(), "no embedded object supplier for own object" ); Reference aXComponent(xEOS->getEmbeddedObject()); pEContext->SetComponent( aXComponent ); } } return pEContext; } } if( xOldTextCursor.is() ) // text-box { auto p = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nElement, xAttrList, XMLTextType::TextBox ); if (p) return p; } XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); return nullptr; } void XMLTextFrameContext_Impl::characters( const OUString& rChars ) { maUrlBuffer.append(rChars); } void XMLTextFrameContext_Impl::SetHyperlink( const OUString& rHRef, const OUString& rName, const OUString& rTargetFrameName, bool bMap ) { static constexpr OUStringLiteral s_HyperLinkURL = u"HyperLinkURL"; static constexpr OUStringLiteral s_HyperLinkName = u"HyperLinkName"; static constexpr OUStringLiteral s_HyperLinkTarget = u"HyperLinkTarget"; static constexpr OUStringLiteral s_ServerMap = u"ServerMap"; if( !xPropSet.is() ) return; Reference < XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); if( !xPropSetInfo.is() || !xPropSetInfo->hasPropertyByName(s_HyperLinkURL)) return; xPropSet->setPropertyValue( s_HyperLinkURL, Any(rHRef) ); if (xPropSetInfo->hasPropertyByName(s_HyperLinkName)) { xPropSet->setPropertyValue(s_HyperLinkName, Any(rName)); } if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget)) { xPropSet->setPropertyValue( s_HyperLinkTarget, Any(rTargetFrameName) ); } if (xPropSetInfo->hasPropertyByName(s_ServerMap)) { xPropSet->setPropertyValue(s_ServerMap, Any(bMap)); } } void XMLTextFrameContext_Impl::SetName() { Reference xNamed(xPropSet, UNO_QUERY); if (m_sOrigName.isEmpty() || !xNamed.is()) return; OUString const name(xNamed->getName()); if (name != m_sOrigName) { try { xNamed->setName(m_sOrigName); } catch (uno::Exception const&) { // fdo#71698 document contains 2 frames with same draw:name TOOLS_INFO_EXCEPTION("xmloff.text", "SetName(): exception setting \"" << m_sOrigName << "\""); } } } // Implement Title/Description Elements UI (#i73249#) void XMLTextFrameContext_Impl::SetTitle( const OUString& rTitle ) { if ( xPropSet.is() ) { Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); if( xPropSetInfo->hasPropertyByName( "Title" ) ) { xPropSet->setPropertyValue( "Title", Any( rTitle ) ); } } } void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc ) { if ( xPropSet.is() ) { Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); if( xPropSetInfo->hasPropertyByName( "Description" ) ) { xPropSet->setPropertyValue( "Description", Any( rDesc ) ); } } } bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet ) { SvXMLImportContext *pContext = m_xImplContext.get(); XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext ); if( pImpl && pImpl->CreateIfNotThere() ) rPropSet = pImpl->GetPropSet(); return rPropSet.is(); } XMLTextFrameContext::XMLTextFrameContext( SvXMLImport& rImport, const Reference< XFastAttributeList > & xAttrList, TextContentAnchorType eATyp ) : SvXMLImportContext( rImport ) , m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList ) ) // Implement Title/Description Elements UI (#i73249#) , m_eDefaultAnchorType( eATyp ) // Shapes in Writer cannot be named via context menu (#i51726#) , m_HasAutomaticStyleWithoutParentStyle( false ) , m_bSupportsReplacement( false ) { for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) { // New distinguish attribute between Writer objects and Draw objects is: // Draw objects have an automatic style without a parent style (#i51726#) switch (aIter.getToken()) { case XML_ELEMENT(DRAW, XML_STYLE_NAME): { OUString aStyleName = aIter.toString(); if( !aStyleName.isEmpty() ) { rtl::Reference < XMLTextImportHelper > xTxtImport = GetImport().GetTextImport(); XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle( aStyleName ); if ( pStyle && pStyle->GetParentName().isEmpty() ) { m_HasAutomaticStyleWithoutParentStyle = true; } } break; } case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE): { TextContentAnchorType eNew; if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) && ( TextContentAnchorType_AT_PARAGRAPH == eNew || TextContentAnchorType_AT_CHARACTER == eNew || TextContentAnchorType_AS_CHARACTER == eNew || TextContentAnchorType_AT_PAGE == eNew) ) m_eDefaultAnchorType = eNew; break; } } } } void XMLTextFrameContext::endFastElement(sal_Int32 ) { /// solve if multiple image child contexts were imported SvXMLImportContextRef const pMultiContext(solveMultipleImages()); SvXMLImportContext const*const pContext = (pMultiContext.is()) ? pMultiContext.get() : m_xImplContext.get(); XMLTextFrameContext_Impl *pImpl = const_cast(dynamic_cast< const XMLTextFrameContext_Impl*>( pContext )); assert(!pMultiContext.is() || pImpl); // When we are dealing with a textbox, pImpl will be null; // we need to set the hyperlink to the shape instead Reference xShape = GetShape(); if (xShape.is() && m_pHyperlink) { Reference xProps(xShape, UNO_QUERY); if (xProps.is()) xProps->setPropertyValue("Hyperlink", Any(m_pHyperlink->GetHRef())); } if( !pImpl ) return; pImpl->CreateIfNotThere(); // fdo#68839: in case the surviving image was not the first one, // it will have a counter added to its name - set the original name if (pMultiContext.is()) // do this only when necessary; esp. not for text { // frames that may have entries in GetRenameMap()! pImpl->SetName(); } if( !m_sTitle.isEmpty() ) { pImpl->SetTitle( m_sTitle ); } if( !m_sDesc.isEmpty() ) { pImpl->SetDesc( m_sDesc ); } if( m_pHyperlink ) { pImpl->SetHyperlink( m_pHyperlink->GetHRef(), m_pHyperlink->GetName(), m_pHyperlink->GetTargetFrameName(), m_pHyperlink->GetMap() ); m_pHyperlink.reset(); } GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl->GetOrigName()); } css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::createFastChildContext( sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList>& xAttrList ) { SvXMLImportContextRef xContext; if( !m_xImplContext.is() ) { // no child exists if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) ) { sal_uInt16 nFrameType = USHRT_MAX; switch (nElement & TOKEN_MASK) { case XML_TEXT_BOX: nFrameType = XML_TEXT_FRAME_TEXTBOX; break; case XML_IMAGE: nFrameType = XML_TEXT_FRAME_GRAPHIC; break; case XML_OBJECT: nFrameType = XML_TEXT_FRAME_OBJECT; break; case XML_OBJECT_OLE: nFrameType = XML_TEXT_FRAME_OBJECT_OLE; break; case XML_APPLET: nFrameType = XML_TEXT_FRAME_APPLET; break; case XML_PLUGIN: nFrameType = XML_TEXT_FRAME_PLUGIN; break; case XML_FLOATING_FRAME: nFrameType = XML_TEXT_FRAME_FLOATING_FRAME; break; } if( USHRT_MAX != nFrameType ) { // Shapes in Writer cannot be named via context menu (#i51726#) if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType || XML_TEXT_FRAME_GRAPHIC == nFrameType ) && m_HasAutomaticStyleWithoutParentStyle ) { Reference < XShapes > xShapes; xContext = XMLShapeImportHelper::CreateFrameChildContext( GetImport(), nElement, xAttrList, xShapes, m_xAttrList ); } else if( XML_TEXT_FRAME_PLUGIN == nFrameType ) { bool bMedia = false; // check, if we have a media object for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) { if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) ) { if (::comphelper::IsMediaMimeType(aIter.toView())) bMedia = true; // leave this loop break; } } if( bMedia ) { Reference < XShapes > xShapes; xContext = XMLShapeImportHelper::CreateFrameChildContext( GetImport(), nElement, xAttrList, xShapes, m_xAttrList ); } } else if( XML_TEXT_FRAME_OBJECT == nFrameType || XML_TEXT_FRAME_OBJECT_OLE == nFrameType ) { m_bSupportsReplacement = true; } else if(XML_TEXT_FRAME_GRAPHIC == nFrameType) { setSupportsMultipleContents( (nElement & TOKEN_MASK) == XML_IMAGE ); } if (!xContext) { xContext = new XMLTextFrameContext_Impl( GetImport(), nElement, xAttrList, m_eDefaultAnchorType, nFrameType, m_xAttrList ); } m_xImplContext = xContext; if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType) { addContent(*m_xImplContext); } } } } else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE)) { // read another image xContext = new XMLTextFrameContext_Impl( GetImport(), nElement, xAttrList, m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList, true); m_xImplContext = xContext; addContent(*m_xImplContext); } else if( m_bSupportsReplacement && !m_xReplImplContext.is() && nElement == XML_ELEMENT(DRAW, XML_IMAGE) ) { // read replacement image Reference < XPropertySet > xPropSet; if( CreateIfNotThere( xPropSet ) ) { xContext = new XMLReplacementImageContext( GetImport(), nElement, xAttrList, xPropSet ); m_xReplImplContext = xContext; } } else if( nullptr != dynamic_cast< const XMLTextFrameContext_Impl*>( m_xImplContext.get() )) { // the child is a writer frame if( IsTokenInNamespace(nElement, XML_NAMESPACE_SVG) || IsTokenInNamespace(nElement, XML_NAMESPACE_SVG_COMPAT) ) { // Implement Title/Description Elements UI (#i73249#) const bool bOld = SvXMLImport::OOo_2x >= GetImport().getGeneratorVersion(); if ( bOld ) { if ( (nElement & TOKEN_MASK) == XML_DESC ) { xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(), m_sTitle ); } } else { if( (nElement & TOKEN_MASK) == XML_TITLE ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(), m_sTitle ); } else if ( (nElement & TOKEN_MASK) == XML_DESC ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(), m_sDesc ); } } } else if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) ) { Reference < XPropertySet > xPropSet; if( (nElement & TOKEN_MASK) == XML_CONTOUR_POLYGON ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } if( CreateIfNotThere( xPropSet ) ) xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement, xAttrList, xPropSet, false ); } else if( (nElement & TOKEN_MASK) == XML_CONTOUR_PATH ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } if( CreateIfNotThere( xPropSet ) ) xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement, xAttrList, xPropSet, true ); } else if( (nElement & TOKEN_MASK) == XML_IMAGE_MAP ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } if( CreateIfNotThere( xPropSet ) ) xContext = new XMLImageMapContext( GetImport(), xPropSet ); } } else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape m_xImplContext = solveMultipleImages(); } // do we still have the frame object? Reference < XPropertySet > xPropSet; if( CreateIfNotThere( xPropSet ) ) { // is it an event supplier? Reference xEventsSupplier(xPropSet, UNO_QUERY); if (xEventsSupplier.is()) { // OK, we have the events, so create the context xContext = new XMLEventsImportContext(GetImport(), xEventsSupplier); } } } } // #i68101# else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC ) || nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC ) ) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape // note: no more draw:image can be added once we get here m_xImplContext = solveMultipleImages(); } xContext = static_cast(m_xImplContext->createFastChildContext( nElement, xAttrList ).get()); } else if (nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE)) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape // note: no more draw:image can be added once we get here m_xImplContext = solveMultipleImages(); } xContext = static_cast(m_xImplContext->createFastChildContext(nElement, xAttrList).get()); } else if (nElement == XML_ELEMENT(LO_EXT, XML_QRCODE)) { if (getSupportsMultipleContents()) { // tdf#103567 ensure props are set on surviving shape // note: no more draw:image can be added once we get here m_xImplContext = solveMultipleImages(); } xContext = static_cast(m_xImplContext->createFastChildContext(nElement, xAttrList).get()); } else if (nElement == XML_ELEMENT(DRAW, XML_A)) { xContext = static_cast(m_xImplContext->createFastChildContext(nElement, xAttrList).get()); } else { // the child is a drawing shape return XMLShapeImportHelper::CreateFrameChildContext( m_xImplContext.get(), nElement, xAttrList ); } return xContext; } void XMLTextFrameContext::SetHyperlink( const OUString& rHRef, const OUString& rName, const OUString& rTargetFrameName, bool bMap ) { OSL_ENSURE( !m_pHyperlink, "recursive SetHyperlink call" ); m_pHyperlink = std::make_unique( rHRef, rName, rTargetFrameName, bMap ); } TextContentAnchorType XMLTextFrameContext::GetAnchorType() const { SvXMLImportContext *pContext = m_xImplContext.get(); XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext ); if( pImpl ) return pImpl->GetAnchorType(); else return m_eDefaultAnchorType; } Reference < XTextContent > XMLTextFrameContext::GetTextContent() const { Reference < XTextContent > xTxtCntnt; SvXMLImportContext *pContext = m_xImplContext.get(); XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl* >( pContext ); if( pImpl ) xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY ); return xTxtCntnt; } Reference < XShape > XMLTextFrameContext::GetShape() const { Reference < XShape > xShape; SvXMLImportContext* pContext = m_xImplContext.get(); SvXMLShapeContext* pImpl = dynamic_cast( pContext ); if ( pImpl ) { xShape = pImpl->getShape(); } return xShape; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */