558b5a1183
V1037 Two or more case-branches perform the same actions. Check lines: 836, 890 Change-Id: If6036da666ea46a4e5c2bc0f4547c78aa43a26a9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175270 Tested-by: Jenkins Reviewed-by: David Gilbert <freedesktop@treblig.org>
4017 lines
140 KiB
C++
4017 lines
140 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <config_wasm_strip.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include <sal/log.hxx>
|
|
#include <com/sun/star/document/XEventsSupplier.hpp>
|
|
#include <com/sun/star/container/XNameReplace.hpp>
|
|
#include <com/sun/star/presentation/ClickAction.hpp>
|
|
#include <com/sun/star/drawing/FillStyle.hpp>
|
|
#include <com/sun/star/drawing/LineStyle.hpp>
|
|
#include <utility>
|
|
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
|
|
#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
|
|
#include <com/sun/star/drawing/GluePoint2.hpp>
|
|
#include <com/sun/star/media/ZoomLevel.hpp>
|
|
#include <com/sun/star/awt/Rectangle.hpp>
|
|
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
|
|
#include <com/sun/star/container/XNameAccess.hpp>
|
|
#include "ximpshap.hxx"
|
|
#include <xmloff/XMLBase64ImportContext.hxx>
|
|
#include <xmloff/XMLShapeStyleContext.hxx>
|
|
#include <xmloff/xmluconv.hxx>
|
|
#include <com/sun/star/container/XNamed.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/awt/XControlModel.hpp>
|
|
#include <com/sun/star/drawing/XControlShape.hpp>
|
|
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
|
|
#include <com/sun/star/drawing/PointSequence.hpp>
|
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/util/XCloneable.hpp>
|
|
#include <com/sun/star/beans/XMultiPropertyStates.hpp>
|
|
#include <xexptran.hxx>
|
|
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
|
|
#include <com/sun/star/beans/XPropertySetInfo.hpp>
|
|
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
|
|
#include <com/sun/star/graphic/XGraphic.hpp>
|
|
#include <com/sun/star/style/XStyle.hpp>
|
|
|
|
#include <sax/tools/converter.hxx>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <comphelper/mediamimetype.hxx>
|
|
|
|
#include <xmloff/families.hxx>
|
|
#include<xmloff/xmlnamespace.hxx>
|
|
#include <xmloff/xmltoken.hxx>
|
|
#include <EnhancedCustomShapeToken.hxx>
|
|
#include <XMLReplacementImageContext.hxx>
|
|
#include <XMLImageMapContext.hxx>
|
|
#include "sdpropls.hxx"
|
|
#include "eventimp.hxx"
|
|
#include "descriptionimp.hxx"
|
|
#include "SignatureLineContext.hxx"
|
|
#include "QRCodeContext.hxx"
|
|
#include "ximpcustomshape.hxx"
|
|
#include <XMLEmbeddedObjectImportContext.hxx>
|
|
#include <xmloff/xmlerror.hxx>
|
|
#include <xmloff/table/XMLTableImport.hxx>
|
|
#include <xmloff/ProgressBarHelper.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
|
|
#include <com/sun/star/container/XChild.hpp>
|
|
#include <com/sun/star/text/XTextDocument.hpp>
|
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
|
#include <basegfx/point/b2dpoint.hxx>
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
#include <basegfx/vector/b2dvector.hxx>
|
|
#include <tools/urlobj.hxx>
|
|
#include <o3tl/any.hxx>
|
|
#include <o3tl/safeint.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::drawing;
|
|
using namespace ::com::sun::star::style;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::document;
|
|
using namespace ::xmloff::token;
|
|
using namespace ::xmloff::EnhancedCustomShapeToken;
|
|
|
|
SvXMLEnumMapEntry<drawing::Alignment> const aXML_GlueAlignment_EnumMap[] =
|
|
{
|
|
{ XML_TOP_LEFT, drawing::Alignment_TOP_LEFT },
|
|
{ XML_TOP, drawing::Alignment_TOP },
|
|
{ XML_TOP_RIGHT, drawing::Alignment_TOP_RIGHT },
|
|
{ XML_LEFT, drawing::Alignment_LEFT },
|
|
{ XML_CENTER, drawing::Alignment_CENTER },
|
|
{ XML_RIGHT, drawing::Alignment_RIGHT },
|
|
{ XML_BOTTOM_LEFT, drawing::Alignment_BOTTOM_LEFT },
|
|
{ XML_BOTTOM, drawing::Alignment_BOTTOM },
|
|
{ XML_BOTTOM_RIGHT, drawing::Alignment_BOTTOM_RIGHT },
|
|
{ XML_TOKEN_INVALID, drawing::Alignment(0) }
|
|
};
|
|
|
|
SvXMLEnumMapEntry<drawing::EscapeDirection> const aXML_GlueEscapeDirection_EnumMap[] =
|
|
{
|
|
{ XML_AUTO, drawing::EscapeDirection_SMART },
|
|
{ XML_LEFT, drawing::EscapeDirection_LEFT },
|
|
{ XML_RIGHT, drawing::EscapeDirection_RIGHT },
|
|
{ XML_UP, drawing::EscapeDirection_UP },
|
|
{ XML_DOWN, drawing::EscapeDirection_DOWN },
|
|
{ XML_HORIZONTAL, drawing::EscapeDirection_HORIZONTAL },
|
|
{ XML_VERTICAL, drawing::EscapeDirection_VERTICAL },
|
|
{ XML_TOKEN_INVALID, drawing::EscapeDirection(0) }
|
|
};
|
|
|
|
static bool ImpIsEmptyURL( std::u16string_view rURL )
|
|
{
|
|
if( rURL.empty() )
|
|
return true;
|
|
|
|
// #i13140# Also compare against 'toplevel' URLs. which also
|
|
// result in empty filename strings.
|
|
if( rURL == u"#./" )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
SdXMLShapeContext::SdXMLShapeContext(
|
|
SvXMLImport& rImport,
|
|
css::uno::Reference< css::xml::sax::XFastAttributeList> xAttrList,
|
|
uno::Reference< drawing::XShapes > xShapes,
|
|
bool bTemporaryShape)
|
|
: SvXMLShapeContext( rImport, bTemporaryShape )
|
|
, mxShapes(std::move( xShapes ))
|
|
, mxAttrList(std::move(xAttrList))
|
|
, mbListContextPushed( false )
|
|
, mnStyleFamily(XmlStyleFamily::SD_GRAPHICS_ID)
|
|
, mbIsPlaceholder(false)
|
|
, mbClearDefaultAttributes( true )
|
|
, mbIsUserTransformed(false)
|
|
, mnZOrder(-1)
|
|
, maSize(1, 1)
|
|
, mnRelWidth(0)
|
|
, mnRelHeight(0)
|
|
, maPosition(0, 0)
|
|
, mbVisible(true)
|
|
, mbPrintable(true)
|
|
, mbHaveXmlId(false)
|
|
, mbTextBox(false)
|
|
{
|
|
}
|
|
|
|
SdXMLShapeContext::~SdXMLShapeContext()
|
|
{
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
SvXMLImportContextRef xContext;
|
|
// #i68101#
|
|
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) )
|
|
{
|
|
xContext = new SdXMLDescriptionContext( GetImport(), nElement, mxShape );
|
|
}
|
|
else if( nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE) )
|
|
{
|
|
xContext = new SignatureLineContext( GetImport(), nElement, xAttrList, mxShape );
|
|
}
|
|
else if( nElement == XML_ELEMENT(LO_EXT, XML_QRCODE) )
|
|
{
|
|
xContext = new QRCodeContext( GetImport(), nElement, xAttrList, mxShape );
|
|
}
|
|
else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
|
|
{
|
|
xContext = new SdXMLEventsContext( GetImport(), mxShape );
|
|
}
|
|
else if( nElement == XML_ELEMENT(DRAW, XML_GLUE_POINT) )
|
|
{
|
|
addGluePoint( xAttrList );
|
|
}
|
|
else if( nElement == XML_ELEMENT(DRAW, XML_THUMBNAIL) )
|
|
{
|
|
// search attributes for xlink:href
|
|
maThumbnailURL = xAttrList->getOptionalValue(XML_ELEMENT(XLINK, XML_HREF));
|
|
}
|
|
else
|
|
{
|
|
// create text cursor on demand
|
|
if( !mxCursor.is() )
|
|
{
|
|
uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
|
|
if( xText.is() )
|
|
{
|
|
rtl::Reference < XMLTextImportHelper > xTxtImport =
|
|
GetImport().GetTextImport();
|
|
mxOldCursor = xTxtImport->GetCursor();
|
|
mxCursor = xText->createTextCursor();
|
|
if( mxCursor.is() )
|
|
{
|
|
xTxtImport->SetCursor( mxCursor );
|
|
}
|
|
|
|
// remember old list item and block (#91964#) and reset them
|
|
// for the text frame
|
|
xTxtImport->PushListContext();
|
|
mbListContextPushed = true;
|
|
}
|
|
}
|
|
|
|
// if we have a text cursor, let's try to import some text
|
|
if( mxCursor.is() )
|
|
{
|
|
xContext = GetImport().GetTextImport()->CreateTextChildContext(
|
|
GetImport(), nElement, xAttrList,
|
|
( mbTextBox ? XMLTextType::TextBox : XMLTextType::Shape ) );
|
|
}
|
|
}
|
|
|
|
if (!xContext)
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
|
|
return xContext;
|
|
}
|
|
|
|
void SdXMLShapeContext::addGluePoint( const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
|
|
{
|
|
// get the gluepoints container for this shape if it's not already there
|
|
if( !mxGluePoints.is() )
|
|
{
|
|
uno::Reference< drawing::XGluePointsSupplier > xSupplier( mxShape, uno::UNO_QUERY );
|
|
if( !xSupplier.is() )
|
|
return;
|
|
|
|
mxGluePoints.set( xSupplier->getGluePoints(), UNO_QUERY );
|
|
|
|
if( !mxGluePoints.is() )
|
|
return;
|
|
}
|
|
|
|
drawing::GluePoint2 aGluePoint;
|
|
aGluePoint.IsUserDefined = true;
|
|
aGluePoint.Position.X = 0;
|
|
aGluePoint.Position.Y = 0;
|
|
aGluePoint.Escape = drawing::EscapeDirection_SMART;
|
|
aGluePoint.PositionAlignment = drawing::Alignment_CENTER;
|
|
aGluePoint.IsRelative = true;
|
|
|
|
sal_Int32 nId = -1;
|
|
|
|
// read attributes for the 3DScene
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
switch(aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_X):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
aGluePoint.Position.X, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
aGluePoint.Position.Y, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_ID):
|
|
nId = aIter.toInt32();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_ALIGN):
|
|
{
|
|
drawing::Alignment eKind;
|
|
if( SvXMLUnitConverter::convertEnum( eKind, aIter.toView(), aXML_GlueAlignment_EnumMap ) )
|
|
{
|
|
aGluePoint.PositionAlignment = eKind;
|
|
aGluePoint.IsRelative = false;
|
|
}
|
|
break;
|
|
}
|
|
case XML_ELEMENT(DRAW, XML_ESCAPE_DIRECTION):
|
|
{
|
|
SvXMLUnitConverter::convertEnum( aGluePoint.Escape, aIter.toView(), aXML_GlueEscapeDirection_EnumMap );
|
|
break;
|
|
}
|
|
default:
|
|
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
|
|
}
|
|
}
|
|
|
|
if( nId != -1 )
|
|
{
|
|
try
|
|
{
|
|
sal_Int32 nInternalId = mxGluePoints->insert( uno::Any( aGluePoint ) );
|
|
GetImport().GetShapeImport()->addGluePointMapping( mxShape, nId, nInternalId );
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "during setting of gluepoints");
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdXMLShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
|
|
{
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
}
|
|
|
|
void SdXMLShapeContext::endFastElement(sal_Int32 )
|
|
{
|
|
if(mxCursor.is())
|
|
{
|
|
// tdf#72776 force UpdateData in the EditSource so we will not override text in SdrOutliner
|
|
if( mxLockable.is() )
|
|
{
|
|
mxLockable->removeActionLock();
|
|
mxLockable->addActionLock();
|
|
}
|
|
|
|
// delete addition newline
|
|
mxCursor->gotoEnd( false );
|
|
mxCursor->goLeft( 1, true );
|
|
mxCursor->setString( u""_ustr );
|
|
|
|
// reset cursor
|
|
GetImport().GetTextImport()->ResetCursor();
|
|
}
|
|
|
|
if(mxOldCursor.is())
|
|
GetImport().GetTextImport()->SetCursor( mxOldCursor );
|
|
|
|
// reinstall old list item (if necessary) #91964#
|
|
if (mbListContextPushed) {
|
|
GetImport().GetTextImport()->PopListContext();
|
|
}
|
|
|
|
if( !msHyperlink.isEmpty() ) try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProp( mxShape, uno::UNO_QUERY );
|
|
|
|
if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName( u"Hyperlink"_ustr ) )
|
|
xProp->setPropertyValue( u"Hyperlink"_ustr, uno::Any( msHyperlink ) );
|
|
Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
|
|
|
|
if( xEventsSupplier.is() )
|
|
{
|
|
Reference< XNameReplace > xEvents( xEventsSupplier->getEvents(), UNO_SET_THROW );
|
|
|
|
uno::Sequence< beans::PropertyValue > aProperties{
|
|
{ /* Name */ u"EventType"_ustr,
|
|
/* Handle */ -1,
|
|
/* Value */ uno::Any(u"Presentation"_ustr),
|
|
/* State */ beans::PropertyState_DIRECT_VALUE },
|
|
|
|
{ /* Name */ u"ClickAction"_ustr,
|
|
/* Handle */ -1,
|
|
/* Value */ uno::Any(css::presentation::ClickAction_DOCUMENT),
|
|
/* State */ beans::PropertyState_DIRECT_VALUE },
|
|
|
|
{ /* Name */ u"Bookmark"_ustr,
|
|
/* Handle */ -1,
|
|
/* Value */ uno::Any(msHyperlink),
|
|
/* State */ beans::PropertyState_DIRECT_VALUE }
|
|
};
|
|
|
|
xEvents->replaceByName( u"OnClick"_ustr, Any( aProperties ) );
|
|
}
|
|
else
|
|
{
|
|
// in draw use the Bookmark property
|
|
Reference< beans::XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
|
|
xSet->setPropertyValue( u"Bookmark"_ustr, Any( msHyperlink ) );
|
|
xSet->setPropertyValue(u"OnClick"_ustr, Any( css::presentation::ClickAction_DOCUMENT ) );
|
|
}
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("xmloff", "while setting hyperlink");
|
|
}
|
|
|
|
if( mxLockable.is() )
|
|
mxLockable->removeActionLock();
|
|
}
|
|
|
|
void SdXMLShapeContext::AddShape(uno::Reference< drawing::XShape >& xShape)
|
|
{
|
|
if(xShape.is())
|
|
{
|
|
// set shape local
|
|
mxShape = xShape;
|
|
|
|
if(!maShapeName.isEmpty())
|
|
{
|
|
uno::Reference< container::XNamed > xNamed( mxShape, uno::UNO_QUERY );
|
|
if( xNamed.is() )
|
|
xNamed->setName( maShapeName );
|
|
}
|
|
|
|
rtl::Reference< XMLShapeImportHelper > xImp( GetImport().GetShapeImport() );
|
|
xImp->addShape( xShape, mxAttrList, mxShapes );
|
|
|
|
if( mbClearDefaultAttributes )
|
|
{
|
|
uno::Reference<beans::XMultiPropertyStates> xMultiPropertyStates(xShape, uno::UNO_QUERY );
|
|
if (xMultiPropertyStates.is())
|
|
xMultiPropertyStates->setAllPropertiesToDefault();
|
|
}
|
|
|
|
if( !mbVisible || !mbPrintable ) try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY_THROW );
|
|
if( !mbVisible )
|
|
xSet->setPropertyValue(u"Visible"_ustr, uno::Any( false ) );
|
|
|
|
if( !mbPrintable )
|
|
xSet->setPropertyValue(u"Printable"_ustr, uno::Any( false ) );
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "while setting visible or printable" );
|
|
}
|
|
|
|
if(!mbTemporaryShape && (!GetImport().HasTextImport()
|
|
|| !GetImport().GetTextImport()->IsInsideDeleteContext()))
|
|
{
|
|
xImp->shapeWithZIndexAdded( xShape, mnZOrder );
|
|
}
|
|
|
|
if (mnRelWidth || mnRelHeight)
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
|
|
uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
|
|
if (mnRelWidth && xPropertySetInfo->hasPropertyByName(u"RelativeWidth"_ustr))
|
|
xPropertySet->setPropertyValue(u"RelativeWidth"_ustr, uno::Any(mnRelWidth));
|
|
if (mnRelHeight && xPropertySetInfo->hasPropertyByName(u"RelativeHeight"_ustr))
|
|
xPropertySet->setPropertyValue(u"RelativeHeight"_ustr, uno::Any(mnRelHeight));
|
|
}
|
|
|
|
if( !maShapeId.isEmpty() )
|
|
{
|
|
uno::Reference< uno::XInterface > xRef( static_cast<uno::XInterface *>(xShape.get()) );
|
|
GetImport().getInterfaceToIdentifierMapper().registerReference( maShapeId, xRef );
|
|
}
|
|
|
|
// #91065# count only if counting for shape import is enabled
|
|
if(GetImport().GetShapeImport()->IsHandleProgressBarEnabled())
|
|
{
|
|
// #80365# increment progress bar at load once for each draw object
|
|
GetImport().GetProgressBarHelper()->Increment();
|
|
}
|
|
}
|
|
|
|
mxLockable.set( xShape, UNO_QUERY );
|
|
|
|
if( mxLockable.is() )
|
|
mxLockable->addActionLock();
|
|
|
|
}
|
|
|
|
void SdXMLShapeContext::AddShape(OUString const & serviceName)
|
|
{
|
|
uno::Reference< lang::XMultiServiceFactory > xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
|
|
if(!xServiceFact.is())
|
|
return;
|
|
|
|
try
|
|
{
|
|
/* Since fix for issue i33294 the Writer model doesn't support
|
|
com.sun.star.drawing.OLE2Shape anymore.
|
|
To handle Draw OLE objects it's decided to import these
|
|
objects as com.sun.star.drawing.OLE2Shape and convert these
|
|
objects after the import into com.sun.star.drawing.GraphicObjectShape.
|
|
*/
|
|
uno::Reference< drawing::XShape > xShape;
|
|
if ( serviceName == "com.sun.star.drawing.OLE2Shape" &&
|
|
uno::Reference< text::XTextDocument >(GetImport().GetModel(), uno::UNO_QUERY).is() )
|
|
{
|
|
xShape.set(xServiceFact->createInstance(u"com.sun.star.drawing.temporaryForXMLImportOLE2Shape"_ustr), uno::UNO_QUERY);
|
|
}
|
|
else if (serviceName == "com.sun.star.drawing.GraphicObjectShape"
|
|
|| serviceName == "com.sun.star.drawing.AppletShape"
|
|
|| serviceName == "com.sun.star.drawing.FrameShape"
|
|
|| serviceName == "com.sun.star.drawing.MediaShape"
|
|
|| serviceName == "com.sun.star.drawing.OLE2Shape"
|
|
|| serviceName == "com.sun.star.drawing.PluginShape"
|
|
|| serviceName == "com.sun.star.presentation.MediaShape")
|
|
{
|
|
// On adding another entry to this list of service names to pass an argument via the WithArguments variant
|
|
// you may need to adjust the more obscure OReportDefinition::createInstanceWithArguments as well as the
|
|
// more obvious SvxUnoDrawMSFactory::createInstanceWithArguments
|
|
xShape.set( xServiceFact->createInstanceWithArguments(serviceName, { css::uno::Any(GetImport().GetDocumentBase()) }),
|
|
css::uno::UNO_QUERY);
|
|
}
|
|
else
|
|
{
|
|
xShape.set(xServiceFact->createInstance(serviceName), uno::UNO_QUERY);
|
|
}
|
|
if( xShape.is() )
|
|
AddShape( xShape );
|
|
}
|
|
catch(const uno::Exception& e)
|
|
{
|
|
TOOLS_WARN_EXCEPTION("xmloff", "AddShape " << serviceName);
|
|
uno::Sequence<OUString> aSeq { serviceName };
|
|
GetImport().SetError( XMLERROR_FLAG_ERROR | XMLERROR_API,
|
|
aSeq, e.Message, nullptr );
|
|
}
|
|
}
|
|
|
|
void SdXMLShapeContext::SetTransformation()
|
|
{
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(!xPropSet.is())
|
|
return;
|
|
|
|
maUsedTransformation.identity();
|
|
|
|
if(maSize.Width != 1 || maSize.Height != 1)
|
|
{
|
|
// take care there are no zeros used by error
|
|
if(0 == maSize.Width)
|
|
maSize.Width = 1;
|
|
if(0 == maSize.Height)
|
|
maSize.Height = 1;
|
|
|
|
// set global size. This should always be used.
|
|
maUsedTransformation.scale(maSize.Width, maSize.Height);
|
|
}
|
|
|
|
if(maPosition.X != 0 || maPosition.Y != 0)
|
|
{
|
|
// if global position is used, add it to transformation
|
|
maUsedTransformation.translate(maPosition.X, maPosition.Y);
|
|
}
|
|
|
|
if(mnTransform.NeedsAction())
|
|
{
|
|
// transformation is used, apply to object.
|
|
// NOTICE: The transformation is applied AFTER evtl. used
|
|
// global positioning and scaling is used, so any shear or
|
|
// rotate used herein is applied around the (0,0) position
|
|
// of the PAGE object !!!
|
|
::basegfx::B2DHomMatrix aMat;
|
|
mnTransform.GetFullTransform(aMat);
|
|
|
|
// now add to transformation
|
|
maUsedTransformation *= aMat;
|
|
}
|
|
|
|
// now set transformation for this object
|
|
|
|
// maUsedTransformtion contains the mathematical correct matrix, which if
|
|
// applied to a unit square would generate the transformed shape. But the property
|
|
// "Transformation" contains a matrix, which can be used in TRSetBaseGeometry
|
|
// and would be created by TRGetBaseGeometry. And those use a mathematically wrong
|
|
// sign for the shearing angle. So we need to adapt the matrix here.
|
|
basegfx::B2DTuple aScale;
|
|
basegfx::B2DTuple aTranslate;
|
|
double fRotate;
|
|
double fShearX;
|
|
maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
basegfx::B2DHomMatrix aB2DHomMatrix;
|
|
aB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
|
|
aScale,
|
|
basegfx::fTools::equalZero(fShearX) ? 0.0 : -fShearX,
|
|
basegfx::fTools::equalZero(fRotate) ? 0.0 : fRotate,
|
|
aTranslate);
|
|
drawing::HomogenMatrix3 aUnoMatrix;
|
|
|
|
aUnoMatrix.Line1.Column1 = aB2DHomMatrix.get(0, 0);
|
|
aUnoMatrix.Line1.Column2 = aB2DHomMatrix.get(0, 1);
|
|
aUnoMatrix.Line1.Column3 = aB2DHomMatrix.get(0, 2);
|
|
|
|
aUnoMatrix.Line2.Column1 = aB2DHomMatrix.get(1, 0);
|
|
aUnoMatrix.Line2.Column2 = aB2DHomMatrix.get(1, 1);
|
|
aUnoMatrix.Line2.Column3 = aB2DHomMatrix.get(1, 2);
|
|
|
|
aUnoMatrix.Line3.Column1 = 0;
|
|
aUnoMatrix.Line3.Column2 = 0;
|
|
aUnoMatrix.Line3.Column3 = 1;
|
|
|
|
xPropSet->setPropertyValue(u"Transformation"_ustr, Any(aUnoMatrix));
|
|
}
|
|
|
|
void SdXMLShapeContext::SetStyle( bool bSupportsStyle /* = true */)
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if( !xPropSet.is() )
|
|
return;
|
|
|
|
do
|
|
{
|
|
// set style on shape
|
|
if(maDrawStyleName.isEmpty())
|
|
break;
|
|
|
|
const SvXMLStyleContext* pStyle = nullptr;
|
|
bool bAutoStyle(false);
|
|
|
|
if(GetImport().GetShapeImport()->GetAutoStylesContext())
|
|
pStyle = GetImport().GetShapeImport()->GetAutoStylesContext()->FindStyleChildContext(mnStyleFamily, maDrawStyleName);
|
|
|
|
if(pStyle)
|
|
bAutoStyle = true;
|
|
|
|
if(!pStyle && GetImport().GetShapeImport()->GetStylesContext())
|
|
pStyle = GetImport().GetShapeImport()->GetStylesContext()->FindStyleChildContext(mnStyleFamily, maDrawStyleName);
|
|
|
|
OUString aStyleName = maDrawStyleName;
|
|
uno::Reference< style::XStyle > xStyle;
|
|
|
|
XMLPropStyleContext* pDocStyle
|
|
= dynamic_cast<XMLShapeStyleContext*>(const_cast<SvXMLStyleContext*>(pStyle));
|
|
if (pDocStyle)
|
|
{
|
|
if( pDocStyle->GetStyle().is() )
|
|
{
|
|
xStyle = pDocStyle->GetStyle();
|
|
}
|
|
else
|
|
{
|
|
aStyleName = pDocStyle->GetParentName();
|
|
}
|
|
}
|
|
|
|
if( !xStyle.is() && !aStyleName.isEmpty() )
|
|
{
|
|
try
|
|
{
|
|
|
|
uno::Reference< style::XStyleFamiliesSupplier > xFamiliesSupplier( GetImport().GetModel(), uno::UNO_QUERY );
|
|
|
|
if( xFamiliesSupplier.is() )
|
|
{
|
|
uno::Reference< container::XNameAccess > xFamilies( xFamiliesSupplier->getStyleFamilies() );
|
|
if( xFamilies.is() )
|
|
{
|
|
|
|
uno::Reference< container::XNameAccess > xFamily;
|
|
|
|
if( XmlStyleFamily::SD_PRESENTATION_ID == mnStyleFamily )
|
|
{
|
|
aStyleName = GetImport().GetStyleDisplayName(
|
|
XmlStyleFamily::SD_PRESENTATION_ID,
|
|
aStyleName );
|
|
sal_Int32 nPos = aStyleName.lastIndexOf( '-' );
|
|
if( -1 != nPos )
|
|
{
|
|
OUString aFamily( aStyleName.copy( 0, nPos ) );
|
|
|
|
xFamilies->getByName( aFamily ) >>= xFamily;
|
|
aStyleName = aStyleName.copy( nPos + 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// get graphics family
|
|
if (xFamilies->hasByName(u"graphics"_ustr))
|
|
xFamilies->getByName(u"graphics"_ustr) >>= xFamily;
|
|
else
|
|
xFamilies->getByName(u"GraphicStyles"_ustr) >>= xFamily;
|
|
|
|
aStyleName = GetImport().GetStyleDisplayName(
|
|
XmlStyleFamily::SD_GRAPHICS_ID,
|
|
aStyleName );
|
|
}
|
|
|
|
if( xFamily.is() )
|
|
xFamily->getByName( aStyleName ) >>= xStyle;
|
|
}
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "finding style for shape" );
|
|
}
|
|
}
|
|
|
|
if( bSupportsStyle && xStyle.is() )
|
|
{
|
|
try
|
|
{
|
|
// set style on object
|
|
xPropSet->setPropertyValue(u"Style"_ustr, Any(xStyle));
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting style for shape" );
|
|
}
|
|
}
|
|
|
|
// Writer shapes: if this one has a TextBox, set it here. We need to do it before
|
|
// pDocStyle->FillPropertySet, because setting some properties depend on the format
|
|
// having RES_CNTNT attribute (e.g., UNO_NAME_TEXT_(LEFT|RIGHT|UPPER|LOWER)DIST; see
|
|
// SwTextBoxHelper::syncProperty, which indirectly calls SwTextBoxHelper::isTextBox)
|
|
uno::Reference<beans::XPropertySetInfo> xPropertySetInfo
|
|
= xPropSet->getPropertySetInfo();
|
|
static constexpr OUString sTextBox = u"TextBox"_ustr;
|
|
if (xPropertySetInfo->hasPropertyByName(sTextBox))
|
|
xPropSet->setPropertyValue(sTextBox, uno::Any(mbTextBox));
|
|
|
|
// if this is an auto style, set its properties
|
|
if(bAutoStyle && pDocStyle)
|
|
{
|
|
// set PropertySet on object
|
|
pDocStyle->FillPropertySet(xPropSet);
|
|
}
|
|
|
|
} while(false);
|
|
|
|
// try to set text auto style
|
|
do
|
|
{
|
|
// set style on shape
|
|
if( maTextStyleName.isEmpty() )
|
|
break;
|
|
|
|
if( nullptr == GetImport().GetShapeImport()->GetAutoStylesContext())
|
|
break;
|
|
|
|
const SvXMLStyleContext* pTempStyle = GetImport().GetShapeImport()->GetAutoStylesContext()->FindStyleChildContext(XmlStyleFamily::TEXT_PARAGRAPH, maTextStyleName);
|
|
XMLPropStyleContext* pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast<const XMLPropStyleContext*>( pTempStyle ) ); // use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
|
|
if( pStyle == nullptr )
|
|
break;
|
|
|
|
// set PropertySet on object
|
|
pStyle->FillPropertySet(xPropSet);
|
|
|
|
} while(false);
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
void SdXMLShapeContext::SetLayer()
|
|
{
|
|
if( maLayerName.isEmpty() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is() )
|
|
{
|
|
xPropSet->setPropertyValue(u"LayerName"_ustr, Any(maLayerName));
|
|
return;
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
void SdXMLShapeContext::SetThumbnail()
|
|
{
|
|
if( maThumbnailURL.isEmpty() )
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if( !xPropSet.is() )
|
|
return;
|
|
|
|
uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
|
|
if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( u"ThumbnailGraphic"_ustr ) )
|
|
{
|
|
// load the thumbnail graphic and export it to a wmf stream so we can set
|
|
// it at the api
|
|
|
|
uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicByURL(maThumbnailURL);
|
|
xPropSet->setPropertyValue(u"ThumbnailGraphic"_ustr, uno::Any(xGraphic));
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
sal_Int32 nTmp;
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_ZINDEX):
|
|
case XML_ELEMENT(DRAW_EXT, XML_ZINDEX):
|
|
mnZOrder = aIter.toInt32();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_ID):
|
|
case XML_ELEMENT(DRAW_EXT, XML_ID):
|
|
if (!mbHaveXmlId) { maShapeId = aIter.toString(); }
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_NAME):
|
|
case XML_ELEMENT(DRAW_EXT, XML_NAME):
|
|
maShapeName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_STYLE_NAME):
|
|
case XML_ELEMENT(DRAW_EXT, XML_STYLE_NAME):
|
|
maDrawStyleName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_TEXT_STYLE_NAME):
|
|
case XML_ELEMENT(DRAW_EXT, XML_TEXT_STYLE_NAME):
|
|
maTextStyleName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_LAYER):
|
|
case XML_ELEMENT(DRAW_EXT, XML_LAYER):
|
|
maLayerName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_DISPLAY):
|
|
case XML_ELEMENT(DRAW_EXT, XML_DISPLAY):
|
|
mbVisible = IsXMLToken( aIter, XML_ALWAYS ) || IsXMLToken( aIter, XML_SCREEN );
|
|
mbPrintable = IsXMLToken( aIter, XML_ALWAYS ) || IsXMLToken( aIter, XML_PRINTER );
|
|
break;
|
|
case XML_ELEMENT(PRESENTATION, XML_USER_TRANSFORMED):
|
|
mbIsUserTransformed = IsXMLToken( aIter, XML_TRUE );
|
|
break;
|
|
case XML_ELEMENT(PRESENTATION, XML_PLACEHOLDER):
|
|
mbIsPlaceholder = IsXMLToken( aIter, XML_TRUE );
|
|
if( mbIsPlaceholder )
|
|
mbClearDefaultAttributes = false;
|
|
break;
|
|
case XML_ELEMENT(PRESENTATION, XML_CLASS):
|
|
maPresentationClass = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(PRESENTATION, XML_STYLE_NAME):
|
|
maDrawStyleName = aIter.toString();
|
|
mnStyleFamily = XmlStyleFamily::SD_PRESENTATION_ID;
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_X):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maPosition.X, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maPosition.Y, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_WIDTH):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maSize.Width, aIter.toView());
|
|
if (maSize.Width > 0)
|
|
maSize.Width = o3tl::saturating_add<sal_Int32>(maSize.Width, 1);
|
|
else if (maSize.Width < 0)
|
|
maSize.Width = o3tl::saturating_add<sal_Int32>(maSize.Width, -1);
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_HEIGHT):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maSize.Height, aIter.toView());
|
|
if (maSize.Height > 0)
|
|
maSize.Height = o3tl::saturating_add<sal_Int32>(maSize.Height, 1);
|
|
else if (maSize.Height < 0)
|
|
maSize.Height = o3tl::saturating_add<sal_Int32>(maSize.Height, -1);
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_TRANSFORM):
|
|
case XML_ELEMENT(DRAW_EXT, XML_TRANSFORM):
|
|
case XML_ELEMENT(SVG, XML_TRANSFORM):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_TRANSFORM):
|
|
// because of #85127# take svg:transform into account and handle like
|
|
// draw:transform for compatibility
|
|
mnTransform.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
|
|
break;
|
|
case XML_ELEMENT(STYLE, XML_REL_WIDTH):
|
|
if (sax::Converter::convertPercent(nTmp, aIter.toView()))
|
|
mnRelWidth = static_cast<sal_Int16>(nTmp);
|
|
break;
|
|
case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
|
|
if (sax::Converter::convertPercent(nTmp, aIter.toView()))
|
|
mnRelHeight = static_cast<sal_Int16>(nTmp);
|
|
break;
|
|
case XML_ELEMENT(NONE, XML_ID):
|
|
case XML_ELEMENT(XML, XML_ID):
|
|
maShapeId = aIter.toString();
|
|
mbHaveXmlId = true;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool SdXMLShapeContext::isPresentationShape() const
|
|
{
|
|
if( !maPresentationClass.isEmpty() && const_cast<SdXMLShapeContext*>(this)->GetImport().GetShapeImport()->IsPresentationShapesSupported() )
|
|
{
|
|
if(XmlStyleFamily::SD_PRESENTATION_ID == mnStyleFamily)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if( IsXMLToken( maPresentationClass, XML_HEADER ) || IsXMLToken( maPresentationClass, XML_FOOTER ) ||
|
|
IsXMLToken( maPresentationClass, XML_PAGE_NUMBER ) || IsXMLToken( maPresentationClass, XML_DATE_TIME ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
SdXMLRectShapeContext::SdXMLRectShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
mnRadius( 0 )
|
|
{
|
|
}
|
|
|
|
SdXMLRectShapeContext::~SdXMLRectShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLRectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRadius, aIter.toView());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLRectShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create rectangle shape
|
|
AddShape(u"com.sun.star.drawing.RectangleShape"_ustr);
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
// Add, set Style and properties from base shape
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
if(mnRadius)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
try
|
|
{
|
|
xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
|
|
}
|
|
}
|
|
}
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLLineShapeContext::SdXMLLineShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
mnX1( 0 ),
|
|
mnY1( 0 ),
|
|
mnX2( 1 ),
|
|
mnY2( 1 )
|
|
{
|
|
}
|
|
|
|
SdXMLLineShapeContext::~SdXMLLineShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLLineShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_X1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X1):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnX1, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y1):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnY1, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_X2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X2):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnX2, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y2):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnY2, aIter.toView());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLLineShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// #85920# use SetTransformation() to handle import of simple lines.
|
|
// This is necessary to take into account all anchor positions and
|
|
// other things. All shape imports use the same import schemata now.
|
|
// create necessary shape (Line Shape)
|
|
AddShape(u"com.sun.star.drawing.PolyLineShape"_ustr);
|
|
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
// Add, set Style and properties from base shape
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// get sizes and offsets
|
|
awt::Point aTopLeft(mnX1, mnY1);
|
|
awt::Point aBottomRight(mnX2, mnY2);
|
|
|
|
if(mnX1 > mnX2)
|
|
{
|
|
aTopLeft.X = mnX2;
|
|
aBottomRight.X = mnX1;
|
|
}
|
|
|
|
if(mnY1 > mnY2)
|
|
{
|
|
aTopLeft.Y = mnY2;
|
|
aBottomRight.Y = mnY1;
|
|
}
|
|
|
|
// set local parameters on shape
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
drawing::PointSequenceSequence aPolyPoly(1);
|
|
drawing::PointSequence* pOuterSequence = aPolyPoly.getArray();
|
|
pOuterSequence->realloc(2);
|
|
awt::Point* pInnerSequence = pOuterSequence->getArray();
|
|
|
|
*pInnerSequence = awt::Point(o3tl::saturating_sub(mnX1, aTopLeft.X), o3tl::saturating_sub(mnY1, aTopLeft.Y));
|
|
pInnerSequence++;
|
|
*pInnerSequence = awt::Point(o3tl::saturating_sub(mnX2, aTopLeft.X), o3tl::saturating_sub(mnY2, aTopLeft.Y));
|
|
|
|
xPropSet->setPropertyValue(u"Geometry"_ustr, Any(aPolyPoly));
|
|
}
|
|
|
|
// Size is included in point coordinates
|
|
maSize.Width = 1;
|
|
maSize.Height = 1;
|
|
maPosition.X = aTopLeft.X;
|
|
maPosition.Y = aTopLeft.Y;
|
|
|
|
// set pos, size, shear and rotate and get copy of matrix
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLEllipseShapeContext::SdXMLEllipseShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
mnCX( 0 ),
|
|
mnCY( 0 ),
|
|
mnRX( 1 ),
|
|
mnRY( 1 ),
|
|
meKind( drawing::CircleKind_FULL ),
|
|
mnStartAngle( 0 ),
|
|
mnEndAngle( 0 )
|
|
{
|
|
}
|
|
|
|
SdXMLEllipseShapeContext::~SdXMLEllipseShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLEllipseShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_RX):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_RX):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRX, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_RY):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_RY):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRY, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_CX):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_CX):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnCX, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_CY):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_CY):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnCY, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_R):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_R):
|
|
// single radius, it's a circle and both radii are the same
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRX, aIter.toView());
|
|
mnRY = mnRX;
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_KIND):
|
|
SvXMLUnitConverter::convertEnum( meKind, aIter.toView(), aXML_CircleKind_EnumMap );
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_START_ANGLE):
|
|
{
|
|
double dStartAngle;
|
|
if (::sax::Converter::convertAngle( dStartAngle, aIter.toView()))
|
|
mnStartAngle = static_cast<sal_Int32>(basegfx::fround(dStartAngle * 100));
|
|
break;
|
|
}
|
|
case XML_ELEMENT(DRAW, XML_END_ANGLE):
|
|
{
|
|
double dEndAngle;
|
|
if (::sax::Converter::convertAngle( dEndAngle, aIter.toView()))
|
|
mnEndAngle = static_cast<sal_Int32>(basegfx::fround(dEndAngle * 100));
|
|
break;
|
|
}
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLEllipseShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create rectangle shape
|
|
AddShape(u"com.sun.star.drawing.EllipseShape"_ustr);
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
// Add, set Style and properties from base shape
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
if(mnCX != 0 || mnCY != 0 || mnRX != 1 || mnRY != 1)
|
|
{
|
|
// #i121972# center/radius is used, put to pos and size
|
|
maSize.Width = 2 * mnRX;
|
|
maSize.Height = 2 * mnRY;
|
|
maPosition.X = mnCX - mnRX;
|
|
maPosition.Y = mnCY - mnRY;
|
|
}
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
if( meKind != drawing::CircleKind_FULL )
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
|
|
if( xPropSet.is() )
|
|
{
|
|
// calculate the correct start and end angle
|
|
sal_Int32 mnOldStartAngle = mnStartAngle;
|
|
sal_Int32 mnOldEndAngle = mnEndAngle;
|
|
basegfx::B2DTuple aScale;
|
|
basegfx::B2DTuple aTranslate;
|
|
double fRotate;
|
|
double fShearX;
|
|
maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
if (aScale.getX() < 0 || aScale.getY() < 0)
|
|
{
|
|
// The angle for a horizontal flip is the same as the angle for a
|
|
// vertical flip because a vertical flip is treated as a horizontal
|
|
// flip plus a rotation.
|
|
|
|
// To perform the flip, the start and end angle are switched and we
|
|
// use the fact performing a horizontal flip on a shape will change
|
|
// the angle that a radius makes with the origin to 180 degrees
|
|
// minus that angle (we use 54000 hundredths of a degree to get the
|
|
// modulus operation to give a value between 0 and 36000).
|
|
|
|
mnStartAngle = (54000 - mnOldEndAngle) % 36000;
|
|
mnEndAngle = (54000 - mnOldStartAngle) % 36000;
|
|
}
|
|
|
|
xPropSet->setPropertyValue(u"CircleKind"_ustr, Any( meKind) );
|
|
xPropSet->setPropertyValue(u"CircleStartAngle"_ustr, Any(mnStartAngle) );
|
|
xPropSet->setPropertyValue(u"CircleEndAngle"_ustr, Any(mnEndAngle) );
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLPolygonShapeContext::SdXMLPolygonShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes, bool bClosed, bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
mbClosed( bClosed )
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLPolygonShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_VIEWBOX):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
|
|
maViewBox = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_POINTS):
|
|
maPoints = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SdXMLPolygonShapeContext::~SdXMLPolygonShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLPolygonShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// Add, set Style and properties from base shape
|
|
if(mbClosed)
|
|
AddShape(u"com.sun.star.drawing.PolyPolygonShape"_ustr);
|
|
else
|
|
AddShape(u"com.sun.star.drawing.PolyLineShape"_ustr);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set local parameters on shape
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
// set polygon
|
|
if(!maPoints.isEmpty() && !maViewBox.isEmpty())
|
|
{
|
|
const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
|
|
basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
|
|
|
|
// Is this correct? It overrides ViewBox stuff; OTOH it makes no
|
|
// sense to have the geometry content size different from object size
|
|
if(maSize.Width != 0 && maSize.Height != 0)
|
|
{
|
|
aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
|
|
}
|
|
|
|
basegfx::B2DPolygon aPolygon;
|
|
|
|
if(basegfx::utils::importFromSvgPoints(aPolygon, maPoints))
|
|
{
|
|
if(aPolygon.count())
|
|
{
|
|
const basegfx::B2DRange aSourceRange(
|
|
aViewBox.GetX(), aViewBox.GetY(),
|
|
aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
|
|
const basegfx::B2DRange aTargetRange(
|
|
aViewBox.GetX(), aViewBox.GetY(),
|
|
aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
|
|
|
|
if(!aSourceRange.equal(aTargetRange))
|
|
{
|
|
aPolygon.transform(
|
|
basegfx::utils::createSourceRangeTargetRangeTransform(
|
|
aSourceRange,
|
|
aTargetRange));
|
|
}
|
|
|
|
css::drawing::PointSequenceSequence aPointSequenceSequence;
|
|
basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(basegfx::B2DPolyPolygon(aPolygon), aPointSequenceSequence);
|
|
xPropSet->setPropertyValue(u"Geometry"_ustr, Any(aPointSequenceSequence));
|
|
// Size is now contained in the point coordinates, adapt maSize for
|
|
// to use the correct transformation matrix in SetTransformation()
|
|
maSize.Width = 1;
|
|
maSize.Height = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// set pos, size, shear and rotate and get copy of matrix
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLPathShapeContext::SdXMLPathShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
|
|
{
|
|
}
|
|
|
|
SdXMLPathShapeContext::~SdXMLPathShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLPathShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(SVG, XML_VIEWBOX):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
|
|
maViewBox = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_D):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_D):
|
|
maD = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLPathShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create polygon shape
|
|
if(maD.isEmpty())
|
|
return;
|
|
|
|
const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
|
|
basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
|
|
|
|
// Is this correct? It overrides ViewBox stuff; OTOH it makes no
|
|
// sense to have the geometry content size different from object size
|
|
if(maSize.Width != 0 && maSize.Height != 0)
|
|
{
|
|
aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon aPolyPolygon;
|
|
|
|
if(!basegfx::utils::importFromSvgD(aPolyPolygon, maD, GetImport().needFixPositionAfterZ(), nullptr))
|
|
return;
|
|
|
|
if(!aPolyPolygon.count())
|
|
return;
|
|
|
|
const basegfx::B2DRange aSourceRange(
|
|
aViewBox.GetX(), aViewBox.GetY(),
|
|
aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
|
|
const basegfx::B2DRange aTargetRange(
|
|
aViewBox.GetX(), aViewBox.GetY(),
|
|
aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
|
|
|
|
if(!aSourceRange.equal(aTargetRange))
|
|
{
|
|
aPolyPolygon.transform(
|
|
basegfx::utils::createSourceRangeTargetRangeTransform(
|
|
aSourceRange,
|
|
aTargetRange));
|
|
}
|
|
|
|
// create shape
|
|
OUString service;
|
|
|
|
if(aPolyPolygon.areControlPointsUsed())
|
|
{
|
|
if(aPolyPolygon.isClosed())
|
|
{
|
|
service = "com.sun.star.drawing.ClosedBezierShape";
|
|
}
|
|
else
|
|
{
|
|
service = "com.sun.star.drawing.OpenBezierShape";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(aPolyPolygon.isClosed())
|
|
{
|
|
service = "com.sun.star.drawing.PolyPolygonShape";
|
|
}
|
|
else
|
|
{
|
|
service = "com.sun.star.drawing.PolyLineShape";
|
|
}
|
|
}
|
|
|
|
// Add, set Style and properties from base shape
|
|
AddShape(service);
|
|
|
|
// #89344# test for mxShape.is() and not for mxShapes.is() to support
|
|
// shape import helper classes WITHOUT XShapes (member mxShapes). This
|
|
// is used by the writer.
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set local parameters on shape
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
|
|
if(xPropSet.is())
|
|
{
|
|
uno::Any aAny;
|
|
|
|
// set polygon data
|
|
if(aPolyPolygon.areControlPointsUsed())
|
|
{
|
|
drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
|
|
|
|
basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
|
|
aPolyPolygon,
|
|
aSourcePolyPolygon);
|
|
aAny <<= aSourcePolyPolygon;
|
|
}
|
|
else
|
|
{
|
|
drawing::PointSequenceSequence aSourcePolyPolygon;
|
|
|
|
basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(
|
|
aPolyPolygon,
|
|
aSourcePolyPolygon);
|
|
aAny <<= aSourcePolyPolygon;
|
|
}
|
|
|
|
xPropSet->setPropertyValue(u"Geometry"_ustr, aAny);
|
|
// Size is now contained in the point coordinates, adapt maSize for
|
|
// to use the correct transformation matrix in SetTransformation()
|
|
maSize.Width = 1;
|
|
maSize.Height = 1;
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLTextBoxShapeContext::SdXMLTextBoxShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
|
|
mnRadius(0),
|
|
maChainNextName(u""_ustr)
|
|
{
|
|
}
|
|
|
|
SdXMLTextBoxShapeContext::~SdXMLTextBoxShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLTextBoxShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRadius, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
|
|
maChainNextName = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLTextBoxShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create textbox shape
|
|
bool bIsPresShape = false;
|
|
bool bClearText = false;
|
|
|
|
OUString service;
|
|
|
|
if( isPresentationShape() )
|
|
{
|
|
// check if the current document supports presentation shapes
|
|
if( GetImport().GetShapeImport()->IsPresentationShapesSupported() )
|
|
{
|
|
if( IsXMLToken( maPresentationClass, XML_SUBTITLE ))
|
|
{
|
|
// XmlShapeType::PresSubtitleShape
|
|
service = "com.sun.star.presentation.SubtitleShape";
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_PRESENTATION_OUTLINE ) )
|
|
{
|
|
// XmlShapeType::PresOutlinerShape
|
|
service = "com.sun.star.presentation.OutlinerShape";
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_NOTES ) )
|
|
{
|
|
// XmlShapeType::PresNotesShape
|
|
service = "com.sun.star.presentation.NotesShape";
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_HEADER ) )
|
|
{
|
|
// XmlShapeType::PresHeaderShape
|
|
service = "com.sun.star.presentation.HeaderShape";
|
|
bClearText = true;
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_FOOTER ) )
|
|
{
|
|
// XmlShapeType::PresFooterShape
|
|
service = "com.sun.star.presentation.FooterShape";
|
|
bClearText = true;
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_PAGE_NUMBER ) )
|
|
{
|
|
// XmlShapeType::PresSlideNumberShape
|
|
service = "com.sun.star.presentation.SlideNumberShape";
|
|
bClearText = true;
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_DATE_TIME ) )
|
|
{
|
|
// XmlShapeType::PresDateTimeShape
|
|
service = "com.sun.star.presentation.DateTimeShape";
|
|
bClearText = true;
|
|
}
|
|
else // IsXMLToken( maPresentationClass, XML_TITLE ) )
|
|
{
|
|
// XmlShapeType::PresTitleTextShape
|
|
service = "com.sun.star.presentation.TitleTextShape";
|
|
}
|
|
bIsPresShape = true;
|
|
}
|
|
}
|
|
|
|
if( service.isEmpty() )
|
|
{
|
|
// normal text shape
|
|
service = "com.sun.star.drawing.TextShape";
|
|
}
|
|
|
|
// Add, set Style and properties from base shape
|
|
AddShape(service);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
if(bIsPresShape)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
|
|
|
|
if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bClearText )
|
|
{
|
|
uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
|
|
xText->setString( u""_ustr );
|
|
}
|
|
|
|
// set parameters on shape
|
|
//A AW->CL: Eventually You need to strip scale and translate from the transformation
|
|
//A to reach the same goal again.
|
|
//A if(!bIsPresShape || mbIsUserTransformed)
|
|
//A {
|
|
//A // set pos and size on shape, this should remove binding
|
|
//A // to presentation object on masterpage
|
|
//A SetSizeAndPosition();
|
|
//A }
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
if(mnRadius)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
try
|
|
{
|
|
xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!maChainNextName.isEmpty())
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
try
|
|
{
|
|
xPropSet->setPropertyValue(u"TextChainNextName"_ustr,
|
|
uno::Any( maChainNextName ) );
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting name of next chain link");
|
|
}
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLControlShapeContext::SdXMLControlShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
|
|
{
|
|
}
|
|
|
|
SdXMLControlShapeContext::~SdXMLControlShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLControlShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_CONTROL):
|
|
maFormId = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLControlShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create Control shape
|
|
// add, set style and properties from base shape
|
|
AddShape(u"com.sun.star.drawing.ControlShape"_ustr);
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SAL_WARN_IF( !!maFormId.isEmpty(), "xmloff", "draw:control without a form:id attribute!" );
|
|
if( !maFormId.isEmpty() )
|
|
{
|
|
if( GetImport().IsFormsSupported() )
|
|
{
|
|
uno::Reference< awt::XControlModel > xControlModel( GetImport().GetFormImport()->lookupControl( maFormId ), uno::UNO_QUERY );
|
|
if( xControlModel.is() )
|
|
{
|
|
uno::Reference< drawing::XControlShape > xControl( mxShape, uno::UNO_QUERY );
|
|
if( xControl.is() )
|
|
xControl->setControl( xControlModel );
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLConnectorShapeContext::SdXMLConnectorShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
maStart(0,0),
|
|
maEnd(1,1),
|
|
mnType( drawing::ConnectorType_STANDARD ),
|
|
mnStartGlueId(-1),
|
|
mnEndGlueId(-1),
|
|
mnDelta1(0),
|
|
mnDelta2(0),
|
|
mnDelta3(0),
|
|
mbLikelyOOXMLCurve(true)
|
|
{
|
|
}
|
|
|
|
SdXMLConnectorShapeContext::~SdXMLConnectorShapeContext()
|
|
{
|
|
}
|
|
|
|
bool SvXMLImport::needFixPositionAfterZ() const
|
|
{
|
|
bool bWrongPositionAfterZ( false );
|
|
sal_Int32 nUPD( 0 );
|
|
sal_Int32 nBuildId( 0 );
|
|
if ( getBuildIds( nUPD, nBuildId ) && // test OOo and old versions of LibO and AOO
|
|
( ( ( nUPD == 641 ) || ( nUPD == 645 ) || ( nUPD == 680 ) || ( nUPD == 300 ) ||
|
|
( nUPD == 310 ) || ( nUPD == 320 ) || ( nUPD == 330 ) || ( nUPD == 340 ) ||
|
|
( nUPD == 350 && nBuildId < 202 ) )
|
|
|| (getGeneratorVersion() == SvXMLImport::AOO_40x))) // test if AOO 4.0.x
|
|
// apparently bug was fixed in AOO by i#123433 f15874d8f976f3874bdbcb53429eeefa65c28841
|
|
{
|
|
bWrongPositionAfterZ = true;
|
|
}
|
|
return bWrongPositionAfterZ;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
bool lcl_IsLikelyOOXMLCurve(const basegfx::B2DPolygon& rPolygon)
|
|
{
|
|
sal_uInt32 nCount = rPolygon.count();
|
|
if (!rPolygon.areControlPointsUsed() or nCount < 2)
|
|
return false; // no curve at all
|
|
|
|
basegfx::B2DVector aStartVec(rPolygon.getNextControlPoint(0) - rPolygon.getB2DPoint(0));
|
|
basegfx::B2DVector aEndVec(rPolygon.getPrevControlPoint(nCount-1) - rPolygon.getB2DPoint(nCount - 1));
|
|
// LibreOffice uses one point less than OOXML for the same underlying bentConnector or
|
|
// STANDARD connector, respectively. A deeper inspection is only needed in case of 2 resulting
|
|
// points. Those connector paths look like a quarter ellipse.
|
|
switch (nCount)
|
|
{
|
|
case 2:
|
|
{
|
|
// In case start and end direction are parallel, it cannot be OOXML because that case
|
|
// introduces a handle on the path and the curve has three points then.
|
|
if (basegfx::areParallel(aStartVec, aEndVec))
|
|
return false;
|
|
// OOXML sets the control point at 1/2, LibreOffice at 2/3 of width or height.
|
|
// A tolerance is used because +-1 deviations due to integer arithmetic in many places.
|
|
basegfx::B2DRange aRect(rPolygon.getB2DPoint(0), rPolygon.getB2DPoint(1));
|
|
if ((basegfx::fTools::equalZero(aStartVec.getX())
|
|
&& basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getHeight(), 2.0))
|
|
|| (basegfx::fTools::equalZero(aStartVec.getY())
|
|
&& basegfx::fTools::equal(aStartVec.getLength() * 2.0, aRect.getWidth(), 2.0)))
|
|
return true;
|
|
}
|
|
break;
|
|
case 3:
|
|
case 5:
|
|
return basegfx::areParallel(aStartVec, aEndVec);
|
|
break;
|
|
case 4: // start and end direction are orthogonal
|
|
return basegfx::fTools::equalZero(aStartVec.scalar( aEndVec));
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
} // end namespace
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLConnectorShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_START_SHAPE):
|
|
maStartShapeId = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_START_GLUE_POINT):
|
|
mnStartGlueId = aIter.toInt32();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_END_SHAPE):
|
|
maEndShapeId = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_END_GLUE_POINT):
|
|
mnEndGlueId = aIter.toInt32();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_LINE_SKEW):
|
|
{
|
|
OUString sValue = aIter.toString();
|
|
SvXMLTokenEnumerator aTokenEnum( sValue );
|
|
std::u16string_view aToken;
|
|
if( aTokenEnum.getNextToken( aToken ) )
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnDelta1, aToken);
|
|
if( aTokenEnum.getNextToken( aToken ) )
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnDelta2, aToken);
|
|
if( aTokenEnum.getNextToken( aToken ) )
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnDelta3, aToken);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case XML_ELEMENT(DRAW, XML_TYPE):
|
|
{
|
|
(void)SvXMLUnitConverter::convertEnum( mnType, aIter.toView(), aXML_ConnectionKind_EnumMap );
|
|
break;
|
|
}
|
|
// #121965# draw:transform may be used in ODF1.2, e.g. exports from MS seem to use these
|
|
case XML_ELEMENT(DRAW, XML_TRANSFORM):
|
|
mnTransform.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
|
|
break;
|
|
|
|
case XML_ELEMENT(SVG, XML_X1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X1):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maStart.X, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y1):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maStart.Y, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_X2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X2):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maEnd.X, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_Y2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y2):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maEnd.Y, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(SVG, XML_D):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_D):
|
|
{
|
|
basegfx::B2DPolyPolygon aPolyPolygon;
|
|
|
|
if(basegfx::utils::importFromSvgD(aPolyPolygon, aIter.toString(), GetImport().needFixPositionAfterZ(), nullptr))
|
|
{
|
|
if(aPolyPolygon.count())
|
|
{
|
|
drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
|
|
|
|
basegfx::utils::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
|
|
aPolyPolygon,
|
|
aSourcePolyPolygon);
|
|
maPath <<= aSourcePolyPolygon;
|
|
|
|
mbLikelyOOXMLCurve = lcl_IsLikelyOOXMLCurve(aPolyPolygon.getB2DPolygon(0));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLConnectorShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// For security reasons, do not add empty connectors. There may have been an error in EA2
|
|
// that created empty, far set off connectors (e.g. 63 meters below top of document). This
|
|
// is not guaranteed, but it's definitely safe to not add empty connectors.
|
|
bool bDoAdd(true);
|
|
|
|
if( maStartShapeId.isEmpty()
|
|
&& maEndShapeId.isEmpty()
|
|
&& maStart.X == maEnd.X
|
|
&& maStart.Y == maEnd.Y
|
|
&& 0 == mnDelta1
|
|
&& 0 == mnDelta2
|
|
&& 0 == mnDelta3
|
|
)
|
|
{
|
|
bDoAdd = false;
|
|
}
|
|
|
|
if(!bDoAdd)
|
|
return;
|
|
|
|
// create Connector shape
|
|
// add, set style and properties from base shape
|
|
AddShape(u"com.sun.star.drawing.ConnectorShape"_ustr);
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
// #121965# if draw:transform is used, apply directly to the start
|
|
// and end positions before using these
|
|
if(mnTransform.NeedsAction())
|
|
{
|
|
// transformation is used, apply to object.
|
|
::basegfx::B2DHomMatrix aMat;
|
|
mnTransform.GetFullTransform(aMat);
|
|
|
|
if(!aMat.isIdentity())
|
|
{
|
|
basegfx::B2DPoint aStart(maStart.X, maStart.Y);
|
|
basegfx::B2DPoint aEnd(maEnd.X, maEnd.Y);
|
|
|
|
aStart = aMat * aStart;
|
|
aEnd = aMat * aEnd;
|
|
|
|
maStart.X = basegfx::fround(aStart.getX());
|
|
maStart.Y = basegfx::fround(aStart.getY());
|
|
maEnd.X = basegfx::fround(aEnd.getX());
|
|
maEnd.Y = basegfx::fround(aEnd.getY());
|
|
}
|
|
}
|
|
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
if (xProps.is())
|
|
xProps->setPropertyValue(u"EdgeOOXMLCurve"_ustr, Any(mbLikelyOOXMLCurve));
|
|
|
|
// add connection ids
|
|
if( !maStartShapeId.isEmpty() )
|
|
GetImport().GetShapeImport()->addShapeConnection( mxShape, true, maStartShapeId, mnStartGlueId );
|
|
if( !maEndShapeId.isEmpty() )
|
|
GetImport().GetShapeImport()->addShapeConnection( mxShape, false, maEndShapeId, mnEndGlueId );
|
|
|
|
if( xProps.is() )
|
|
{
|
|
xProps->setPropertyValue(u"StartPosition"_ustr, Any(maStart));
|
|
xProps->setPropertyValue(u"EndPosition"_ustr, Any(maEnd) );
|
|
xProps->setPropertyValue(u"EdgeKind"_ustr, Any(mnType) );
|
|
xProps->setPropertyValue(u"EdgeLine1Delta"_ustr, Any(mnDelta1) );
|
|
xProps->setPropertyValue(u"EdgeLine2Delta"_ustr, Any(mnDelta2) );
|
|
xProps->setPropertyValue(u"EdgeLine3Delta"_ustr, Any(mnDelta3) );
|
|
}
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
if ( maPath.hasValue() )
|
|
{
|
|
// #i115492#
|
|
// Ignore svg:d attribute for text documents created by OpenOffice.org
|
|
// versions before OOo 3.3, because these OOo versions are storing
|
|
// svg:d values not using the correct unit.
|
|
bool bApplySVGD( true );
|
|
if ( uno::Reference< text::XTextDocument >(GetImport().GetModel(), uno::UNO_QUERY).is() )
|
|
{
|
|
sal_Int32 nUPD( 0 );
|
|
sal_Int32 nBuild( 0 );
|
|
const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
|
|
if ( GetImport().IsTextDocInOOoFileFormat() ||
|
|
( bBuildIdFound &&
|
|
( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
|
|
( nUPD == 680 ) || // OOo 2.x
|
|
( nUPD == 300 ) || // OOo 3.0 - OOo 3.0.1
|
|
( nUPD == 310 ) || // OOo 3.1 - OOo 3.1.1
|
|
( nUPD == 320 ) ) ) ) // OOo 3.2 - OOo 3.2.1
|
|
{
|
|
bApplySVGD = false;
|
|
}
|
|
}
|
|
|
|
if ( bApplySVGD )
|
|
{
|
|
// tdf#83360 use path data only when redundant data of start and end point coordinates of
|
|
// path start/end and connector start/end is equal. This is to avoid using erroneous
|
|
// or inconsistent path data at import of foreign formats. Office itself always
|
|
// writes out a consistent data set. Not using it when there is inconsistency
|
|
// is okay since the path data is redundant, buffered data just to avoid recalculation
|
|
// of the connector's layout at load time, no real information would be lost.
|
|
// A 'connected' end has prio to direct coordinate data in Start/EndPosition
|
|
// to the path data (which should have the start/end redundant in the path)
|
|
const drawing::PolyPolygonBezierCoords* pSource = static_cast< const drawing::PolyPolygonBezierCoords* >(maPath.getValue());
|
|
const sal_uInt32 nSequenceCount(pSource->Coordinates.getLength());
|
|
bool bStartEqual(false);
|
|
bool bEndEqual(false);
|
|
|
|
if(nSequenceCount)
|
|
{
|
|
const drawing::PointSequence& rStartSeq = pSource->Coordinates[0];
|
|
const sal_uInt32 nStartCount = rStartSeq.getLength();
|
|
|
|
if(nStartCount)
|
|
{
|
|
const awt::Point& rStartPoint = rStartSeq.getConstArray()[0];
|
|
|
|
if(rStartPoint.X == maStart.X && rStartPoint.Y == maStart.Y)
|
|
{
|
|
bStartEqual = true;
|
|
}
|
|
}
|
|
|
|
const drawing::PointSequence& rEndSeq = pSource->Coordinates[nSequenceCount - 1];
|
|
const sal_uInt32 nEndCount = rEndSeq.getLength();
|
|
|
|
if(nEndCount)
|
|
{
|
|
const awt::Point& rEndPoint = rEndSeq.getConstArray()[nEndCount - 1];
|
|
|
|
if(rEndPoint.X == maEnd.X && rEndPoint.Y == maEnd.Y)
|
|
{
|
|
bEndEqual = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bStartEqual || !bEndEqual)
|
|
{
|
|
bApplySVGD = false;
|
|
}
|
|
}
|
|
|
|
if ( bApplySVGD )
|
|
{
|
|
assert(maPath.getValueType() == cppu::UnoType<drawing::PolyPolygonBezierCoords>::get());
|
|
xProps->setPropertyValue(u"PolyPolygonBezier"_ustr, maPath);
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLMeasureShapeContext::SdXMLMeasureShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
maStart(0,0),
|
|
maEnd(1,1)
|
|
{
|
|
}
|
|
|
|
SdXMLMeasureShapeContext::~SdXMLMeasureShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLMeasureShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(SVG, XML_X1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X1):
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maStart.X, aIter.toView());
|
|
break;
|
|
}
|
|
case XML_ELEMENT(SVG, XML_Y1):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y1):
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maStart.Y, aIter.toView());
|
|
break;
|
|
}
|
|
case XML_ELEMENT(SVG, XML_X2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_X2):
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maEnd.X, aIter.toView());
|
|
break;
|
|
}
|
|
case XML_ELEMENT(SVG, XML_Y2):
|
|
case XML_ELEMENT(SVG_COMPAT, XML_Y2):
|
|
{
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maEnd.Y, aIter.toView());
|
|
break;
|
|
}
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLMeasureShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create Measure shape
|
|
// add, set style and properties from base shape
|
|
AddShape(u"com.sun.star.drawing.MeasureShape"_ustr);
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
if( xProps.is() )
|
|
{
|
|
xProps->setPropertyValue(u"StartPosition"_ustr, Any(maStart));
|
|
xProps->setPropertyValue(u"EndPosition"_ustr, Any(maEnd) );
|
|
}
|
|
|
|
// delete pre created fields
|
|
uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
|
|
if( xText.is() )
|
|
{
|
|
xText->setString( u" "_ustr );
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
void SdXMLMeasureShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
do
|
|
{
|
|
// delete pre created fields
|
|
uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
|
|
if( !xText.is() )
|
|
break;
|
|
|
|
uno::Reference< text::XTextCursor > xCursor( xText->createTextCursor() );
|
|
if( !xCursor.is() )
|
|
break;
|
|
|
|
xCursor->collapseToStart();
|
|
xCursor->goRight( 1, true );
|
|
xCursor->setString( u""_ustr );
|
|
}
|
|
while(false);
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
|
|
SdXMLPageShapeContext::SdXMLPageShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ), mnPageNumber(0)
|
|
{
|
|
mbClearDefaultAttributes = false;
|
|
}
|
|
|
|
SdXMLPageShapeContext::~SdXMLPageShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLPageShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(DRAW, XML_PAGE_NUMBER) )
|
|
mnPageNumber = aIter.toInt32();
|
|
else
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
return true;
|
|
}
|
|
|
|
void SdXMLPageShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create Page shape
|
|
// add, set style and properties from base shape
|
|
|
|
// #86163# take into account which type of PageShape needs to
|
|
// be constructed. It's a presentation shape if presentation:XML_CLASS == XML_PAGE.
|
|
bool bIsPresentation = !maPresentationClass.isEmpty() &&
|
|
GetImport().GetShapeImport()->IsPresentationShapesSupported();
|
|
|
|
uno::Reference< lang::XServiceInfo > xInfo( mxShapes, uno::UNO_QUERY );
|
|
const bool bIsOnHandoutPage = xInfo.is() && xInfo->supportsService(u"com.sun.star.presentation.HandoutMasterPage"_ustr);
|
|
|
|
if( bIsOnHandoutPage )
|
|
{
|
|
AddShape(u"com.sun.star.presentation.HandoutShape"_ustr);
|
|
}
|
|
else
|
|
{
|
|
if(bIsPresentation && !IsXMLToken( maPresentationClass, XML_PAGE ) )
|
|
{
|
|
bIsPresentation = false;
|
|
}
|
|
|
|
if(bIsPresentation)
|
|
{
|
|
AddShape(u"com.sun.star.presentation.PageShape"_ustr);
|
|
}
|
|
else
|
|
{
|
|
AddShape(u"com.sun.star.drawing.PageShape"_ustr);
|
|
}
|
|
}
|
|
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
|
|
static constexpr OUString aPageNumberStr(u"PageNumber"_ustr);
|
|
if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(aPageNumberStr))
|
|
xPropSet->setPropertyValue(aPageNumberStr, uno::Any( mnPageNumber ));
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
|
|
SdXMLCaptionShapeContext::SdXMLCaptionShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
// #86616# for correct edge rounding import mnRadius needs to be initialized
|
|
mnRadius( 0 )
|
|
{
|
|
}
|
|
|
|
SdXMLCaptionShapeContext::~SdXMLCaptionShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLCaptionShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create Caption shape
|
|
// add, set style and properties from base shape
|
|
AddShape(u"com.sun.star.drawing.CaptionShape"_ustr);
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
|
|
// SJ: If AutoGrowWidthItem is set, SetTransformation will lead to the wrong SnapRect
|
|
// because NbcAdjustTextFrameWidthAndHeight() is called (text is set later and center alignment
|
|
// is the default setting, so the top left reference point that is used by the caption point is
|
|
// no longer correct) There are two ways to solve this problem, temporarily disabling the
|
|
// autogrowwidth as we are doing here or to apply the CaptionPoint after setting text
|
|
bool bIsAutoGrowWidth = false;
|
|
if ( xProps.is() )
|
|
{
|
|
uno::Any aAny( xProps->getPropertyValue(u"TextAutoGrowWidth"_ustr) );
|
|
aAny >>= bIsAutoGrowWidth;
|
|
|
|
if ( bIsAutoGrowWidth )
|
|
xProps->setPropertyValue(u"TextAutoGrowWidth"_ustr, uno::Any( false ) );
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
if( xProps.is() )
|
|
xProps->setPropertyValue(u"CaptionPoint"_ustr, uno::Any( maCaptionPoint ) );
|
|
|
|
if ( bIsAutoGrowWidth )
|
|
xProps->setPropertyValue(u"TextAutoGrowWidth"_ustr, uno::Any( true ) );
|
|
|
|
if(mnRadius)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if(xPropSet.is())
|
|
{
|
|
try
|
|
{
|
|
xPropSet->setPropertyValue(u"CornerRadius"_ustr, uno::Any( mnRadius ) );
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting corner radius");
|
|
}
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLCaptionShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_CAPTION_POINT_X):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maCaptionPoint.X, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_CAPTION_POINT_Y):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
maCaptionPoint.Y, aIter.toView());
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_CORNER_RADIUS):
|
|
GetImport().GetMM100UnitConverter().convertMeasureToCore(
|
|
mnRadius, aIter.toView());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
SdXMLGraphicObjectShapeContext::SdXMLGraphicObjectShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLGraphicObjectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(XLINK, XML_HREF):
|
|
maURL = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_MIME_TYPE):
|
|
case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
|
|
msMimeType = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute(aIter);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLGraphicObjectShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create graphic object shape
|
|
OUString service;
|
|
|
|
if( IsXMLToken( maPresentationClass, XML_GRAPHIC ) && GetImport().GetShapeImport()->IsPresentationShapesSupported() )
|
|
{
|
|
service = "com.sun.star.presentation.GraphicObjectShape";
|
|
}
|
|
else
|
|
{
|
|
service = "com.sun.star.drawing.GraphicObjectShape";
|
|
}
|
|
|
|
AddShape(service);
|
|
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
uno::Reference< beans::XPropertySet > xPropset(mxShape, uno::UNO_QUERY);
|
|
if(xPropset.is())
|
|
{
|
|
// since OOo 1.x had no line or fill style for graphics, but may create
|
|
// documents with them, we have to override them here
|
|
sal_Int32 nUPD, nBuildId;
|
|
if( GetImport().getBuildIds( nUPD, nBuildId ) && (nUPD == 645) ) try
|
|
{
|
|
xPropset->setPropertyValue(u"FillStyle"_ustr, Any( FillStyle_NONE ) );
|
|
xPropset->setPropertyValue(u"LineStyle"_ustr, Any( LineStyle_NONE ) );
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
}
|
|
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xPropset->getPropertySetInfo() );
|
|
if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xPropset->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any( mbIsPlaceholder ) );
|
|
|
|
if( !mbIsPlaceholder )
|
|
{
|
|
if( !maURL.isEmpty() )
|
|
{
|
|
uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicByURL(maURL);
|
|
if (xGraphic.is())
|
|
{
|
|
xPropset->setPropertyValue(u"Graphic"_ustr, uno::Any(xGraphic));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(mbIsUserTransformed)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
void SdXMLGraphicObjectShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
if (mxBase64Stream.is())
|
|
{
|
|
uno::Reference<graphic::XGraphic> xGraphic(GetImport().loadGraphicFromBase64(mxBase64Stream));
|
|
if (xGraphic.is())
|
|
{
|
|
uno::Reference<beans::XPropertySet> xProperties(mxShape, uno::UNO_QUERY);
|
|
if (xProperties.is())
|
|
{
|
|
xProperties->setPropertyValue(u"Graphic"_ustr, uno::Any(xGraphic));
|
|
}
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLGraphicObjectShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
|
|
|
|
if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
|
|
{
|
|
if( maURL.isEmpty() && !mxBase64Stream.is() )
|
|
{
|
|
mxBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
|
|
if( mxBase64Stream.is() )
|
|
xContext = new XMLBase64ImportContext( GetImport(),
|
|
mxBase64Stream );
|
|
}
|
|
}
|
|
|
|
// delegate to parent class if no context could be created
|
|
if (!xContext)
|
|
xContext = SdXMLShapeContext::createFastChildContext(nElement,
|
|
xAttrList);
|
|
|
|
if (!xContext)
|
|
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
|
|
|
|
return xContext;
|
|
}
|
|
|
|
SdXMLGraphicObjectShapeContext::~SdXMLGraphicObjectShapeContext()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
SdXMLChartShapeContext::SdXMLChartShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape )
|
|
{
|
|
}
|
|
|
|
void SdXMLChartShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
const bool bIsPresentation = isPresentationShape();
|
|
|
|
AddShape(
|
|
bIsPresentation
|
|
? u"com.sun.star.presentation.ChartShape"_ustr
|
|
: u"com.sun.star.drawing.OLE2Shape"_ustr);
|
|
|
|
if(!mxShape.is())
|
|
return;
|
|
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
if( !mbIsPlaceholder )
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
|
|
|
|
uno::Any aAny;
|
|
|
|
xProps->setPropertyValue(u"CLSID"_ustr, Any(u"12DCAE26-281F-416F-a234-c3086127382e"_ustr) );
|
|
|
|
aAny = xProps->getPropertyValue(u"Model"_ustr);
|
|
uno::Reference< frame::XModel > xChartModel;
|
|
if( aAny >>= xChartModel )
|
|
{
|
|
#if !ENABLE_WASM_STRIP_CHART
|
|
// WASM_CHART change
|
|
// TODO: Maybe use SdXMLGraphicObjectShapeContext completely instead
|
|
// or try to create as mbIsPlaceholder object adding a Chart visualization
|
|
// that should be available somehow
|
|
mxChartContext.set( GetImport().GetChartImport()->CreateChartContext( GetImport(), xChartModel ) );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
if(mbIsUserTransformed)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
|
|
if( mxChartContext.is() )
|
|
mxChartContext->startFastElement( nElement, xAttrList );
|
|
}
|
|
|
|
void SdXMLChartShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
if( mxChartContext.is() )
|
|
mxChartContext->endFastElement(nElement);
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
void SdXMLChartShapeContext::characters( const OUString& rChars )
|
|
{
|
|
if( mxChartContext.is() )
|
|
mxChartContext->characters( rChars );
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLChartShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if( mxChartContext.is() )
|
|
return mxChartContext->createFastChildContext( nElement, xAttrList );
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
SdXMLObjectShapeContext::SdXMLObjectShapeContext( SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
css::uno::Reference< css::drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
|
|
{
|
|
}
|
|
|
|
SdXMLObjectShapeContext::~SdXMLObjectShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLObjectShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
|
|
{
|
|
// #96717# in theorie, if we don't have a URL we shouldn't even
|
|
// export this OLE shape. But practically it's too risky right now
|
|
// to change this so we better dispose this on load
|
|
//if( !mbIsPlaceholder && ImpIsEmptyURL(maHref) )
|
|
// return;
|
|
|
|
// #100592# this BugFix prevents that a shape is created. CL
|
|
// is thinking about an alternative.
|
|
// #i13140# Check for more than empty string in maHref, there are
|
|
// other possibilities that maHref results in empty container
|
|
// storage names
|
|
if( !(GetImport().getImportFlags() & SvXMLImportFlags::EMBEDDED) && !mbIsPlaceholder && ImpIsEmptyURL(maHref) )
|
|
return;
|
|
|
|
OUString service(u"com.sun.star.drawing.OLE2Shape"_ustr);
|
|
|
|
bool bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
|
|
|
|
if( bIsPresShape )
|
|
{
|
|
if( IsXMLToken( maPresentationClass, XML_CHART ) )
|
|
{
|
|
service = "com.sun.star.presentation.ChartShape";
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_TABLE ) )
|
|
{
|
|
service = "com.sun.star.presentation.CalcShape";
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_OBJECT ) )
|
|
{
|
|
service = "com.sun.star.presentation.OLE2Shape";
|
|
}
|
|
}
|
|
|
|
AddShape(service);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetLayer();
|
|
|
|
if(bIsPresShape)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
|
|
|
|
if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !mbIsPlaceholder && !maHref.isEmpty() )
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
|
|
if( xProps.is() )
|
|
{
|
|
OUString aPersistName = GetImport().ResolveEmbeddedObjectURL( maHref, maCLSID );
|
|
|
|
if ( GetImport().IsPackageURL( maHref ) )
|
|
{
|
|
static constexpr OUString sURL( u"vnd.sun.star.EmbeddedObject:"_ustr );
|
|
|
|
if ( aPersistName.startsWith( sURL ) )
|
|
aPersistName = aPersistName.copy( sURL.getLength() );
|
|
|
|
xProps->setPropertyValue(u"PersistName"_ustr,
|
|
uno::Any( aPersistName ) );
|
|
}
|
|
else
|
|
{
|
|
// this is OOo link object
|
|
xProps->setPropertyValue(u"LinkURL"_ustr,
|
|
uno::Any( aPersistName ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
SetStyle();
|
|
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
}
|
|
|
|
void SdXMLObjectShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
if (GetImport().isGeneratorVersionOlderThan(
|
|
SvXMLImport::OOo_34x, SvXMLImport::LO_41x)) // < LO 4.0
|
|
{
|
|
// #i118485#
|
|
// If it's an old file from us written before OOo3.4, we need to correct
|
|
// FillStyle and LineStyle for OLE2 objects. The error was that the old paint
|
|
// implementations just ignored added fill/linestyles completely, thus
|
|
// those objects need to be corrected to not show blue and hairline which
|
|
// always was the default, but would be shown now
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
|
|
if( xProps.is() )
|
|
{
|
|
xProps->setPropertyValue(u"FillStyle"_ustr, uno::Any(drawing::FillStyle_NONE));
|
|
xProps->setPropertyValue(u"LineStyle"_ustr, uno::Any(drawing::LineStyle_NONE));
|
|
}
|
|
}
|
|
|
|
if( mxBase64Stream.is() )
|
|
{
|
|
OUString aPersistName( GetImport().ResolveEmbeddedObjectURLFromBase64() );
|
|
static constexpr OUStringLiteral sURL( u"vnd.sun.star.EmbeddedObject:" );
|
|
|
|
aPersistName = aPersistName.copy( sURL.getLength() );
|
|
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
if( xProps.is() )
|
|
xProps->setPropertyValue(u"PersistName"_ustr, uno::Any( aPersistName ) );
|
|
}
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLObjectShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_CLASS_ID):
|
|
maCLSID = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(XLINK, XML_HREF):
|
|
maHref = aIter.toString();
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLObjectShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if(nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA))
|
|
{
|
|
mxBase64Stream = GetImport().GetStreamForEmbeddedObjectURLFromBase64();
|
|
if( mxBase64Stream.is() )
|
|
return new XMLBase64ImportContext( GetImport(), mxBase64Stream );
|
|
}
|
|
else if( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
|
|
nElement == XML_ELEMENT(MATH, XML_MATH) )
|
|
{
|
|
rtl::Reference<XMLEmbeddedObjectImportContext> xEContext(
|
|
new XMLEmbeddedObjectImportContext(GetImport(), nElement, xAttrList));
|
|
maCLSID = xEContext->GetFilterCLSID();
|
|
if( !maCLSID.isEmpty() )
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
if( xPropSet.is() )
|
|
{
|
|
xPropSet->setPropertyValue(u"CLSID"_ustr, uno::Any( maCLSID ) );
|
|
|
|
uno::Reference< lang::XComponent > xComp;
|
|
xPropSet->getPropertyValue(u"Model"_ustr) >>= xComp;
|
|
SAL_WARN_IF( !xComp.is(), "xmloff", "no xModel for own OLE format" );
|
|
xEContext->SetComponent(xComp);
|
|
}
|
|
}
|
|
return xEContext;
|
|
}
|
|
|
|
// delegate to parent class if no context could be created
|
|
return SdXMLShapeContext::createFastChildContext(nElement, xAttrList);
|
|
}
|
|
|
|
SdXMLAppletShapeContext::SdXMLAppletShapeContext( SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
css::uno::Reference< css::drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
|
|
mbIsScript( false )
|
|
{
|
|
}
|
|
|
|
SdXMLAppletShapeContext::~SdXMLAppletShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLAppletShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
|
|
{
|
|
AddShape(u"com.sun.star.drawing.AppletShape"_ustr);
|
|
|
|
if( mxShape.is() )
|
|
{
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
}
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLAppletShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_APPLET_NAME):
|
|
maAppletName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_CODE):
|
|
maAppletCode = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
|
|
mbIsScript = IsXMLToken( aIter, XML_TRUE );
|
|
break;
|
|
case XML_ELEMENT(XLINK, XML_HREF):
|
|
maHref = GetImport().GetAbsoluteReference(aIter.toString());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLAppletShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
if( xProps.is() )
|
|
{
|
|
if ( maSize.Width && maSize.Height )
|
|
{
|
|
// the visual area for applet must be set on loading
|
|
awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
|
|
xProps->setPropertyValue(u"VisibleArea"_ustr, Any(aRect) );
|
|
}
|
|
|
|
if( maParams.hasElements() )
|
|
{
|
|
xProps->setPropertyValue(u"AppletCommands"_ustr, Any(maParams) );
|
|
}
|
|
|
|
if( !maHref.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"AppletCodeBase"_ustr, Any(maHref) );
|
|
}
|
|
|
|
if( !maAppletName.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"AppletName"_ustr, Any(maAppletName) );
|
|
}
|
|
|
|
if( mbIsScript )
|
|
{
|
|
xProps->setPropertyValue(u"AppletIsScript"_ustr, Any(mbIsScript) );
|
|
|
|
}
|
|
|
|
if( !maAppletCode.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"AppletCode"_ustr, Any(maAppletCode) );
|
|
}
|
|
|
|
xProps->setPropertyValue(u"AppletDocBase"_ustr, Any(GetImport().GetDocumentBase()) );
|
|
|
|
SetThumbnail();
|
|
}
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLAppletShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
|
|
{
|
|
OUString aParamName, aParamValue;
|
|
// now parse the attribute list and look for draw:name and draw:value
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(DRAW, XML_NAME) )
|
|
aParamName = aIter.toString();
|
|
if( aIter.getToken() == XML_ELEMENT(DRAW, XML_VALUE) )
|
|
aParamValue = aIter.toString();
|
|
}
|
|
|
|
if( !aParamName.isEmpty() )
|
|
{
|
|
sal_Int32 nIndex = maParams.getLength();
|
|
maParams.realloc( nIndex + 1 );
|
|
auto pParams = maParams.getArray();
|
|
pParams[nIndex].Name = aParamName;
|
|
pParams[nIndex].Handle = -1;
|
|
pParams[nIndex].Value <<= aParamValue;
|
|
pParams[nIndex].State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
|
|
return new SvXMLImportContext( GetImport() );
|
|
}
|
|
|
|
return SdXMLShapeContext::createFastChildContext( nElement, xAttrList );
|
|
}
|
|
|
|
|
|
SdXMLPluginShapeContext::SdXMLPluginShapeContext( SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
css::uno::Reference< css::drawing::XShapes > const & rShapes) :
|
|
SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ),
|
|
mbMedia( false )
|
|
{
|
|
}
|
|
|
|
SdXMLPluginShapeContext::~SdXMLPluginShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLPluginShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
|
|
// watch for MimeType attribute to see 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()))
|
|
mbMedia = true;
|
|
// leave this loop
|
|
break;
|
|
}
|
|
}
|
|
|
|
OUString service;
|
|
|
|
bool bIsPresShape = false;
|
|
|
|
if( mbMedia )
|
|
{
|
|
service = "com.sun.star.drawing.MediaShape";
|
|
|
|
bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
|
|
if( bIsPresShape )
|
|
{
|
|
if( IsXMLToken( maPresentationClass, XML_OBJECT ) )
|
|
{
|
|
service = "com.sun.star.presentation.MediaShape";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
service = "com.sun.star.drawing.PluginShape";
|
|
|
|
AddShape(service);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
if (mbMedia)
|
|
{
|
|
// The media may have a crop, apply it.
|
|
SetStyle(/*bSupportsStyle=*/false);
|
|
}
|
|
|
|
SetLayer();
|
|
|
|
if(bIsPresShape)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
if(xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
|
|
|
|
if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
}
|
|
|
|
static OUString
|
|
lcl_GetMediaReference(SvXMLImport const& rImport, OUString const& rURL)
|
|
{
|
|
if (rImport.IsPackageURL(rURL))
|
|
{
|
|
return "vnd.sun.star.Package:" + rURL;
|
|
}
|
|
else
|
|
{
|
|
return rImport.GetAbsoluteReference(rURL);
|
|
}
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLPluginShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_MIME_TYPE):
|
|
maMimeType = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(XLINK, XML_HREF):
|
|
maHref = lcl_GetMediaReference(GetImport(), aIter.toString());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLPluginShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
|
|
if( xProps.is() )
|
|
{
|
|
if ( maSize.Width && maSize.Height )
|
|
{
|
|
static constexpr OUString sVisibleArea( u"VisibleArea"_ustr );
|
|
uno::Reference< beans::XPropertySetInfo > aXPropSetInfo( xProps->getPropertySetInfo() );
|
|
if ( !aXPropSetInfo.is() || aXPropSetInfo->hasPropertyByName( sVisibleArea ) )
|
|
{
|
|
// the visual area for a plugin must be set on loading
|
|
awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
|
|
xProps->setPropertyValue( sVisibleArea, Any(aRect) );
|
|
}
|
|
}
|
|
|
|
if( !mbMedia )
|
|
{
|
|
// in case we have a plugin object
|
|
if( maParams.hasElements() )
|
|
{
|
|
xProps->setPropertyValue(u"PluginCommands"_ustr, Any(maParams) );
|
|
}
|
|
|
|
if( !maMimeType.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"PluginMimeType"_ustr, Any(maMimeType) );
|
|
}
|
|
|
|
if( !maHref.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"PluginURL"_ustr, Any(maHref) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// in case we have a media object
|
|
xProps->setPropertyValue( u"MediaURL"_ustr, uno::Any(maHref));
|
|
|
|
xProps->setPropertyValue(u"MediaMimeType"_ustr, uno::Any(maMimeType) );
|
|
|
|
for (const auto& rParam : maParams)
|
|
{
|
|
const OUString& rName = rParam.Name;
|
|
|
|
if( rName == "Loop" )
|
|
{
|
|
OUString aValueStr;
|
|
rParam.Value >>= aValueStr;
|
|
xProps->setPropertyValue(u"Loop"_ustr,
|
|
uno::Any( aValueStr == "true" ) );
|
|
}
|
|
else if( rName == "Mute" )
|
|
{
|
|
OUString aValueStr;
|
|
rParam.Value >>= aValueStr;
|
|
xProps->setPropertyValue(u"Mute"_ustr,
|
|
uno::Any( aValueStr == "true" ) );
|
|
}
|
|
else if( rName == "VolumeDB" )
|
|
{
|
|
OUString aValueStr;
|
|
rParam.Value >>= aValueStr;
|
|
xProps->setPropertyValue(u"VolumeDB"_ustr,
|
|
uno::Any( static_cast< sal_Int16 >( aValueStr.toInt32() ) ) );
|
|
}
|
|
else if( rName == "Zoom" )
|
|
{
|
|
OUString aZoomStr;
|
|
media::ZoomLevel eZoomLevel;
|
|
|
|
rParam.Value >>= aZoomStr;
|
|
|
|
if( aZoomStr == "25%" )
|
|
eZoomLevel = media::ZoomLevel_ZOOM_1_TO_4;
|
|
else if( aZoomStr == "50%" )
|
|
eZoomLevel = media::ZoomLevel_ZOOM_1_TO_2;
|
|
else if( aZoomStr == "100%" )
|
|
eZoomLevel = media::ZoomLevel_ORIGINAL;
|
|
else if( aZoomStr == "200%" )
|
|
eZoomLevel = media::ZoomLevel_ZOOM_2_TO_1;
|
|
else if( aZoomStr == "400%" )
|
|
eZoomLevel = media::ZoomLevel_ZOOM_4_TO_1;
|
|
else if( aZoomStr == "fit" )
|
|
eZoomLevel = media::ZoomLevel_FIT_TO_WINDOW;
|
|
else if( aZoomStr == "fixedfit" )
|
|
eZoomLevel = media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT;
|
|
else if( aZoomStr == "fullscreen" )
|
|
eZoomLevel = media::ZoomLevel_FULLSCREEN;
|
|
else
|
|
eZoomLevel = media::ZoomLevel_NOT_AVAILABLE;
|
|
|
|
xProps->setPropertyValue(u"Zoom"_ustr, uno::Any( eZoomLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
SetThumbnail();
|
|
}
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLPluginShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
|
|
{
|
|
OUString aParamName, aParamValue;
|
|
// now parse the attribute list and look for draw:name and draw:value
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(DRAW, XML_NAME) )
|
|
aParamName = aIter.toString();
|
|
else if( aIter.getToken() == XML_ELEMENT(DRAW, XML_VALUE) )
|
|
aParamValue = aIter.toString();
|
|
}
|
|
|
|
if( !aParamName.isEmpty() )
|
|
{
|
|
sal_Int32 nIndex = maParams.getLength();
|
|
maParams.realloc( nIndex + 1 );
|
|
auto pParams = maParams.getArray();
|
|
pParams[nIndex].Name = aParamName;
|
|
pParams[nIndex].Handle = -1;
|
|
pParams[nIndex].Value <<= aParamValue;
|
|
pParams[nIndex].State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
|
|
return new SvXMLImportContext( GetImport() );
|
|
}
|
|
|
|
return SdXMLShapeContext::createFastChildContext( nElement, xAttrList );
|
|
}
|
|
|
|
|
|
SdXMLFloatingFrameShapeContext::SdXMLFloatingFrameShapeContext( SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
css::uno::Reference< css::drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
|
|
{
|
|
}
|
|
|
|
SdXMLFloatingFrameShapeContext::~SdXMLFloatingFrameShapeContext()
|
|
{
|
|
}
|
|
|
|
uno::Reference<drawing::XShape> SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const
|
|
{
|
|
uno::Reference<lang::XMultiServiceFactory> xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
|
|
if (!xServiceFact.is())
|
|
return nullptr;
|
|
uno::Reference<drawing::XShape> xShape(
|
|
xServiceFact->createInstance(u"com.sun.star.drawing.FrameShape"_ustr), uno::UNO_QUERY);
|
|
return xShape;
|
|
}
|
|
|
|
void SdXMLFloatingFrameShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
|
|
{
|
|
uno::Reference<drawing::XShape> xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape());
|
|
|
|
uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY);
|
|
// set FrameURL before AddShape, we have to do it again later because it
|
|
// gets cleared when the SdrOle2Obj is attached to the XShape. But we want
|
|
// FrameURL to exist when AddShape triggers SetPersistName which itself
|
|
// triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
|
|
// know what URL will end up being used. So bodge this by setting FrameURL
|
|
// to the temp pre-SdrOle2Obj attached properties and we can smuggle it
|
|
// eventually into SdrOle2Obj::SetPersistName at the right point after
|
|
// PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
|
|
// in order to inform the link manager that this is an IFrame that links to
|
|
// a URL
|
|
if (xProps && !maHref.isEmpty())
|
|
xProps->setPropertyValue(u"FrameURL"_ustr, Any(maHref));
|
|
|
|
AddShape(xShape);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
if( xProps.is() )
|
|
{
|
|
if( !maFrameName.isEmpty() )
|
|
{
|
|
xProps->setPropertyValue(u"FrameName"_ustr, Any(maFrameName) );
|
|
}
|
|
|
|
if( !maHref.isEmpty() )
|
|
{
|
|
if (INetURLObject(maHref).IsExoticProtocol())
|
|
GetImport().NotifyMacroEventRead();
|
|
|
|
xProps->setPropertyValue(u"FrameURL"_ustr, Any(maHref) );
|
|
}
|
|
}
|
|
|
|
SetStyle();
|
|
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLFloatingFrameShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
switch( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_FRAME_NAME):
|
|
maFrameName = aIter.toString();
|
|
break;
|
|
case XML_ELEMENT(XLINK, XML_HREF):
|
|
maHref = GetImport().GetAbsoluteReference(aIter.toString());
|
|
break;
|
|
default:
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void SdXMLFloatingFrameShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY );
|
|
|
|
if( xProps.is() )
|
|
{
|
|
if ( maSize.Width && maSize.Height )
|
|
{
|
|
// the visual area for a floating frame must be set on loading
|
|
awt::Rectangle aRect( 0, 0, maSize.Width, maSize.Height );
|
|
xProps->setPropertyValue(u"VisibleArea"_ustr, Any(aRect) );
|
|
}
|
|
}
|
|
|
|
SetThumbnail();
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
|
|
SdXMLFrameShapeContext::SdXMLFrameShapeContext( SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
css::uno::Reference< css::drawing::XShapes > const & rShapes,
|
|
bool bTemporaryShape)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ),
|
|
mbSupportsReplacement( false )
|
|
{
|
|
uno::Reference < util::XCloneable > xClone( xAttrList, uno::UNO_QUERY );
|
|
if( xClone.is() )
|
|
mxAttrList.set( xClone->createClone(), uno::UNO_QUERY );
|
|
else
|
|
mxAttrList = new sax_fastparser::FastAttributeList(xAttrList);
|
|
}
|
|
|
|
SdXMLFrameShapeContext::~SdXMLFrameShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLFrameShapeContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext)
|
|
{
|
|
const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext);
|
|
|
|
if(!pSdXMLGraphicObjectShapeContext)
|
|
return;
|
|
|
|
try
|
|
{
|
|
uno::Reference< container::XChild > xChild(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW);
|
|
|
|
uno::Reference< drawing::XShapes > xParent(xChild->getParent(), uno::UNO_QUERY_THROW);
|
|
|
|
// remove from parent
|
|
xParent->remove(pSdXMLGraphicObjectShapeContext->getShape());
|
|
|
|
// dispose
|
|
uno::Reference< lang::XComponent > xComp(pSdXMLGraphicObjectShapeContext->getShape(), UNO_QUERY);
|
|
|
|
if(xComp.is())
|
|
{
|
|
xComp->dispose();
|
|
}
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "Error in cleanup of multiple graphic object import." );
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
uno::Reference<beans::XPropertySet> getGraphicPropertySetFromImportContext(const SvXMLImportContext& rContext)
|
|
{
|
|
uno::Reference<beans::XPropertySet> aPropertySet;
|
|
const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast<const SdXMLGraphicObjectShapeContext*>(&rContext);
|
|
|
|
if (pSdXMLGraphicObjectShapeContext)
|
|
aPropertySet.set(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY);
|
|
|
|
return aPropertySet;
|
|
}
|
|
|
|
} // end anonymous namespace
|
|
|
|
uno::Reference<graphic::XGraphic> SdXMLFrameShapeContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
|
|
{
|
|
uno::Reference<graphic::XGraphic> xGraphic;
|
|
try
|
|
{
|
|
const uno::Reference<beans::XPropertySet> xPropertySet = getGraphicPropertySetFromImportContext(rContext);
|
|
|
|
if (xPropertySet.is())
|
|
{
|
|
xPropertySet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
|
|
}
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("xmloff", "Error in cleanup of multiple graphic object import.");
|
|
}
|
|
|
|
return xGraphic;
|
|
}
|
|
|
|
OUString SdXMLFrameShapeContext::getMimeTypeFromImportContext(const SvXMLImportContext& rContext) const
|
|
{
|
|
OUString aMimeType;
|
|
const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast<const SdXMLGraphicObjectShapeContext*>(&rContext);
|
|
|
|
if (pSdXMLGraphicObjectShapeContext)
|
|
aMimeType = pSdXMLGraphicObjectShapeContext->getMimeType();
|
|
return aMimeType;
|
|
}
|
|
|
|
OUString SdXMLFrameShapeContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
|
|
{
|
|
OUString aRetval;
|
|
const SdXMLGraphicObjectShapeContext* pSdXMLGraphicObjectShapeContext = dynamic_cast< const SdXMLGraphicObjectShapeContext* >(&rContext);
|
|
|
|
if(pSdXMLGraphicObjectShapeContext)
|
|
{
|
|
try
|
|
{
|
|
const uno::Reference< beans::XPropertySet > xPropSet(pSdXMLGraphicObjectShapeContext->getShape(), uno::UNO_QUERY_THROW);
|
|
|
|
xPropSet->getPropertyValue(u"GraphicStreamURL"_ustr) >>= aRetval;
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "Error in cleanup of multiple graphic object import." );
|
|
}
|
|
}
|
|
|
|
return aRetval;
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
|
|
{
|
|
SvXMLImportContextRef xContext;
|
|
if( !mxImplContext.is() )
|
|
{
|
|
SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateFrameChildContext(
|
|
GetImport(), nElement, xAttrList, mxShapes, mxAttrList );
|
|
|
|
xContext = pShapeContext;
|
|
|
|
// propagate the hyperlink to child context
|
|
if ( !msHyperlink.isEmpty() )
|
|
pShapeContext->setHyperlink( msHyperlink );
|
|
|
|
auto nToken = nElement & TOKEN_MASK;
|
|
bool bMedia = false;
|
|
// Ignore gltf model if necessary and so the fallback image will be imported
|
|
if( nToken == XML_PLUGIN )
|
|
{
|
|
SdXMLPluginShapeContext* pPluginContext = dynamic_cast<SdXMLPluginShapeContext*>(pShapeContext);
|
|
if( pPluginContext && pPluginContext->getMimeType() == "model/vnd.gltf+json" )
|
|
{
|
|
mxImplContext = nullptr;
|
|
return new SvXMLImportContext(GetImport());
|
|
}
|
|
else if (pPluginContext && ::comphelper::IsMediaMimeType(pPluginContext->getMimeType()))
|
|
{
|
|
// The media may have a preview, import it.
|
|
bMedia = true;
|
|
}
|
|
}
|
|
|
|
mxImplContext = xContext;
|
|
mbSupportsReplacement = (nToken == XML_OBJECT ) || (nToken == XML_OBJECT_OLE) || bMedia;
|
|
setSupportsMultipleContents(nToken == XML_IMAGE);
|
|
|
|
if(getSupportsMultipleContents() && dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get()))
|
|
{
|
|
if ( !maShapeId.isEmpty() )
|
|
GetImport().getInterfaceToIdentifierMapper().reserveIdentifier( maShapeId );
|
|
|
|
addContent(*mxImplContext);
|
|
}
|
|
}
|
|
else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
|
|
{
|
|
// read another image
|
|
xContext = XMLShapeImportHelper::CreateFrameChildContext(
|
|
GetImport(), nElement, xAttrList, mxShapes, mxAttrList);
|
|
mxImplContext = xContext;
|
|
|
|
if(dynamic_cast< SdXMLGraphicObjectShapeContext* >(xContext.get()))
|
|
{
|
|
addContent(*mxImplContext);
|
|
}
|
|
}
|
|
else if( mbSupportsReplacement && !mxReplImplContext.is() &&
|
|
nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
|
|
{
|
|
// read replacement image
|
|
SvXMLImportContext *pImplContext = mxImplContext.get();
|
|
SdXMLShapeContext *pSContext =
|
|
dynamic_cast<SdXMLShapeContext*>( pImplContext );
|
|
if( pSContext )
|
|
{
|
|
uno::Reference < beans::XPropertySet > xPropSet(
|
|
pSContext->getShape(), uno::UNO_QUERY );
|
|
if( xPropSet.is() )
|
|
{
|
|
xContext = new XMLReplacementImageContext( GetImport(),
|
|
nElement, xAttrList, xPropSet );
|
|
mxReplImplContext = xContext;
|
|
}
|
|
}
|
|
}
|
|
else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || // #i68101#
|
|
nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) ||
|
|
nElement == XML_ELEMENT(SVG, XML_DESC) ||
|
|
nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC) ||
|
|
nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) ||
|
|
nElement == XML_ELEMENT(DRAW, XML_GLUE_POINT) ||
|
|
nElement == XML_ELEMENT(DRAW, XML_THUMBNAIL) )
|
|
{
|
|
if (getSupportsMultipleContents())
|
|
{ // tdf#103567 ensure props are set on surviving shape
|
|
// note: no more draw:image can be added once we get here
|
|
mxImplContext = solveMultipleImages();
|
|
}
|
|
SvXMLImportContext *pImplContext = mxImplContext.get();
|
|
xContext = static_cast<SvXMLImportContext*>(dynamic_cast<SdXMLShapeContext&>(*pImplContext).createFastChildContext( nElement,
|
|
xAttrList ).get());
|
|
}
|
|
else if ( nElement == XML_ELEMENT(DRAW, XML_IMAGE_MAP) )
|
|
{
|
|
if (getSupportsMultipleContents())
|
|
{ // tdf#103567 ensure props are set on surviving shape
|
|
// note: no more draw:image can be added once we get here
|
|
mxImplContext = solveMultipleImages();
|
|
}
|
|
SdXMLShapeContext *pSContext = dynamic_cast< SdXMLShapeContext* >( mxImplContext.get() );
|
|
if( pSContext )
|
|
{
|
|
uno::Reference < beans::XPropertySet > xPropSet( pSContext->getShape(), uno::UNO_QUERY );
|
|
if (xPropSet.is())
|
|
{
|
|
xContext = new XMLImageMapContext(GetImport(), xPropSet);
|
|
}
|
|
}
|
|
}
|
|
else if ( nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE) )
|
|
{
|
|
SdXMLShapeContext* pSContext = dynamic_cast<SdXMLShapeContext*>(mxImplContext.get());
|
|
if (pSContext)
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropSet(pSContext->getShape(), uno::UNO_QUERY);
|
|
if (xPropSet.is())
|
|
{
|
|
xContext = new SignatureLineContext(GetImport(), nElement, xAttrList,
|
|
pSContext->getShape());
|
|
}
|
|
}
|
|
}
|
|
else if ( nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
|
|
{
|
|
SdXMLShapeContext* pSContext = dynamic_cast<SdXMLShapeContext*>(mxImplContext.get());
|
|
if (pSContext)
|
|
{
|
|
uno::Reference<beans::XPropertySet> xPropSet(pSContext->getShape(), uno::UNO_QUERY);
|
|
if (xPropSet.is())
|
|
{
|
|
xContext = new QRCodeContext(GetImport(), nElement, xAttrList,
|
|
pSContext->getShape());
|
|
}
|
|
}
|
|
}
|
|
|
|
return xContext;
|
|
}
|
|
|
|
void SdXMLFrameShapeContext::startFastElement (sal_Int32 /*nElement*/,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/)
|
|
{
|
|
// ignore
|
|
}
|
|
|
|
void SdXMLFrameShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
// solve if multiple image child contexts were imported
|
|
SvXMLImportContextRef const pSelectedContext(solveMultipleImages());
|
|
const SdXMLGraphicObjectShapeContext* pShapeContext(
|
|
dynamic_cast<const SdXMLGraphicObjectShapeContext*>(pSelectedContext.get()));
|
|
if ( pShapeContext )
|
|
{
|
|
assert( mxImplContext.is() );
|
|
const uno::Reference< uno::XInterface > xShape( pShapeContext->getShape() );
|
|
GetImport().getInterfaceToIdentifierMapper().registerReservedReference( maShapeId, xShape );
|
|
}
|
|
|
|
if( !mxImplContext.is() )
|
|
{
|
|
// now check if this is an empty presentation object
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(mxAttrList) )
|
|
{
|
|
switch (aIter.getToken())
|
|
{
|
|
case XML_ELEMENT(PRESENTATION, XML_PLACEHOLDER):
|
|
mbIsPlaceholder = IsXMLToken( aIter, XML_TRUE );
|
|
break;
|
|
case XML_ELEMENT(PRESENTATION, XML_CLASS):
|
|
maPresentationClass = aIter.toString();
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
|
|
if( (!maPresentationClass.isEmpty()) && mbIsPlaceholder )
|
|
{
|
|
uno::Reference< xml::sax::XFastAttributeList> xEmpty;
|
|
|
|
enum XMLTokenEnum eToken = XML_TEXT_BOX;
|
|
|
|
if( IsXMLToken( maPresentationClass, XML_GRAPHIC ) )
|
|
{
|
|
eToken = XML_IMAGE;
|
|
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_PAGE ) )
|
|
{
|
|
eToken = XML_PAGE_THUMBNAIL;
|
|
}
|
|
else if( IsXMLToken( maPresentationClass, XML_CHART ) ||
|
|
IsXMLToken( maPresentationClass, XML_TABLE ) ||
|
|
IsXMLToken( maPresentationClass, XML_OBJECT ) )
|
|
{
|
|
eToken = XML_OBJECT;
|
|
}
|
|
|
|
auto x = XML_ELEMENT(DRAW, eToken);
|
|
mxImplContext = XMLShapeImportHelper::CreateFrameChildContext(
|
|
GetImport(), x, mxAttrList, mxShapes, xEmpty );
|
|
|
|
if( mxImplContext.is() )
|
|
{
|
|
mxImplContext->startFastElement( x, mxAttrList );
|
|
mxImplContext->endFastElement(x);
|
|
}
|
|
}
|
|
}
|
|
|
|
mxImplContext = nullptr;
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
}
|
|
|
|
bool SdXMLFrameShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
bool bId( false );
|
|
|
|
switch ( aIter.getToken() )
|
|
{
|
|
case XML_ELEMENT(DRAW, XML_ID):
|
|
case XML_ELEMENT(DRAW_EXT, XML_ID):
|
|
case XML_ELEMENT(NONE, XML_ID):
|
|
case XML_ELEMENT(XML, XML_ID) :
|
|
bId = true;
|
|
break;
|
|
default:;
|
|
}
|
|
|
|
if ( bId )
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
return true; // deliberately ignoring other attributes
|
|
}
|
|
|
|
|
|
SdXMLCustomShapeContext::SdXMLCustomShapeContext(
|
|
SvXMLImport& rImport,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
|
|
uno::Reference< drawing::XShapes > const & rShapes)
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ )
|
|
{
|
|
// See the XMLTextFrameContext ctor, a frame has Writer content (and not
|
|
// editeng) if its autostyle has a parent style. Do the same for shapes as well.
|
|
for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
|
|
{
|
|
if (aIter.getToken() == XML_ELEMENT(DRAW, XML_STYLE_NAME))
|
|
{
|
|
OUString aStyleName = aIter.toString();
|
|
if(!aStyleName.isEmpty())
|
|
{
|
|
rtl::Reference<XMLTextImportHelper> xTxtImport = GetImport().GetTextImport();
|
|
XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle(aStyleName);
|
|
// Note that this an API name, so intentionally not localized.
|
|
// Also allow other Frame styles with the same prefix, we just want to reject
|
|
// Graphics after all.
|
|
if (pStyle && pStyle->GetParentName().startsWith("Frame"))
|
|
{
|
|
mbTextBox = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SdXMLCustomShapeContext::~SdXMLCustomShapeContext()
|
|
{
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLCustomShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
if( aIter.getToken() == XML_ELEMENT(DRAW, XML_ENGINE) )
|
|
{
|
|
maCustomShapeEngine = aIter.toString();
|
|
}
|
|
else if (aIter.getToken() == XML_ELEMENT(DRAW, XML_DATA) )
|
|
{
|
|
maCustomShapeData = aIter.toString();
|
|
}
|
|
else
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
return true;
|
|
}
|
|
|
|
void SdXMLCustomShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
// create rectangle shape
|
|
AddShape(u"com.sun.star.drawing.CustomShape"_ustr);
|
|
if ( !mxShape.is() )
|
|
return;
|
|
|
|
// Add, set Style and properties from base shape
|
|
SetStyle();
|
|
SetLayer();
|
|
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
|
|
if( xPropSet.is() )
|
|
{
|
|
if ( !maCustomShapeEngine.isEmpty() )
|
|
{
|
|
xPropSet->setPropertyValue( EASGet( EAS_CustomShapeEngine ), Any(maCustomShapeEngine) );
|
|
}
|
|
if ( !maCustomShapeData.isEmpty() )
|
|
{
|
|
xPropSet->setPropertyValue( EASGet( EAS_CustomShapeData ), Any(maCustomShapeData) );
|
|
}
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting enhanced customshape geometry" );
|
|
}
|
|
SdXMLShapeContext::startFastElement(nElement, xAttrList);
|
|
}
|
|
|
|
void SdXMLCustomShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
// Customshapes remember mirror state in its enhanced geometry.
|
|
// SetTransformation() in StartElement() may have applied mirroring, but that is not yet
|
|
// contained. Merge that information here before writing the property.
|
|
if(!maUsedTransformation.isIdentity())
|
|
{
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
|
|
maUsedTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
if (aScale.getX() < 0.0)
|
|
{
|
|
static constexpr OUString sName(u"MirroredX"_ustr);
|
|
//fdo#84043 Merge, if property exists, otherwise append it
|
|
auto aI = std::find_if(maCustomShapeGeometry.begin(), maCustomShapeGeometry.end(),
|
|
[](beans::PropertyValue& rValue) { return rValue.Name == sName; });
|
|
if (aI != maCustomShapeGeometry.end())
|
|
{
|
|
beans::PropertyValue& rItem = *aI;
|
|
bool bMirroredX = *o3tl::doAccess<bool>(rItem.Value);
|
|
rItem.Value <<= !bMirroredX;
|
|
rItem.Handle = -1;
|
|
rItem.State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
else
|
|
{
|
|
beans::PropertyValue* pItem;
|
|
maCustomShapeGeometry.emplace_back();
|
|
pItem = &maCustomShapeGeometry.back();
|
|
pItem->Name = sName;
|
|
pItem->Handle = -1;
|
|
pItem->Value <<= true;
|
|
pItem->State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
}
|
|
|
|
if (aScale.getY() < 0.0)
|
|
{
|
|
static constexpr OUString sName(u"MirroredY"_ustr);
|
|
//fdo#84043 Merge, if property exists, otherwise append it
|
|
auto aI = std::find_if(maCustomShapeGeometry.begin(), maCustomShapeGeometry.end(),
|
|
[](beans::PropertyValue& rValue) { return rValue.Name == sName; });
|
|
if (aI != maCustomShapeGeometry.end())
|
|
{
|
|
beans::PropertyValue& rItem = *aI;
|
|
bool bMirroredY = *o3tl::doAccess<bool>(rItem.Value);
|
|
rItem.Value <<= !bMirroredY;
|
|
rItem.Handle = -1;
|
|
rItem.State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
else
|
|
{
|
|
beans::PropertyValue* pItem;
|
|
maCustomShapeGeometry.emplace_back();
|
|
pItem = &maCustomShapeGeometry.back();
|
|
pItem->Name = sName;
|
|
pItem->Handle = -1;
|
|
pItem->Value <<= true;
|
|
pItem->State = beans::PropertyState_DIRECT_VALUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !maCustomShapeGeometry.empty() )
|
|
{
|
|
// converting the vector to a sequence
|
|
uno::Sequence< beans::PropertyValue > aSeq( comphelper::containerToSequence(maCustomShapeGeometry) );
|
|
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet( mxShape, uno::UNO_QUERY );
|
|
if( xPropSet.is() )
|
|
{
|
|
xPropSet->setPropertyValue( u"CustomShapeGeometry"_ustr, Any(aSeq) );
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION( "xmloff", "setting enhanced customshape geometry" );
|
|
}
|
|
|
|
sal_Int32 nUPD;
|
|
sal_Int32 nBuild;
|
|
if (GetImport().getBuildIds(nUPD, nBuild))
|
|
{
|
|
if( ((nUPD >= 640 && nUPD <= 645) || (nUPD == 680)) && (nBuild <= 9221) )
|
|
{
|
|
Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( mxShape, UNO_QUERY );
|
|
if( xDefaulter.is() )
|
|
{
|
|
xDefaulter->createCustomShapeDefaults( u""_ustr );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
|
|
// tdf#98163 call a custom slot to be able to reset the UNO API
|
|
// implementations held on the SdrObjects of type
|
|
// SdrObjCustomShape - those tend to linger until the entire file
|
|
// is loaded. For large files with a lot of these, 32bit systems
|
|
// may crash due to being out of resources after ca. 4200
|
|
// Outliners and VirtualDevices used there as RefDevice
|
|
try
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
|
|
|
|
if(xPropSet.is())
|
|
{
|
|
xPropSet->setPropertyValue(
|
|
u"FlushCustomShapeUnoApiObjects"_ustr, css::uno::Any(true));
|
|
}
|
|
}
|
|
catch(const uno::Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("xmloff", "flushing after load");
|
|
}
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLCustomShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
|
|
{
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
|
|
if ( nElement == XML_ELEMENT(DRAW, XML_ENHANCED_GEOMETRY) )
|
|
{
|
|
uno::Reference< beans::XPropertySet > xPropSet( mxShape,uno::UNO_QUERY );
|
|
if ( xPropSet.is() )
|
|
xContext = new XMLEnhancedCustomShapeContext( GetImport(), mxShape, maCustomShapeGeometry );
|
|
}
|
|
// delegate to parent class if no context could be created
|
|
if (!xContext)
|
|
xContext = SdXMLShapeContext::createFastChildContext( nElement,
|
|
xAttrList);
|
|
return xContext;
|
|
}
|
|
|
|
SdXMLTableShapeContext::SdXMLTableShapeContext( SvXMLImport& rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList, css::uno::Reference< css::drawing::XShapes > const & rShapes )
|
|
: SdXMLShapeContext( rImport, xAttrList, rShapes, false )
|
|
{
|
|
}
|
|
|
|
SdXMLTableShapeContext::~SdXMLTableShapeContext()
|
|
{
|
|
}
|
|
|
|
void SdXMLTableShapeContext::startFastElement (sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
|
|
{
|
|
OUString service(u"com.sun.star.drawing.TableShape"_ustr);
|
|
|
|
bool bIsPresShape = !maPresentationClass.isEmpty() && GetImport().GetShapeImport()->IsPresentationShapesSupported();
|
|
if( bIsPresShape )
|
|
{
|
|
if( IsXMLToken( maPresentationClass, XML_TABLE ) )
|
|
{
|
|
service = "com.sun.star.presentation.TableShape";
|
|
}
|
|
}
|
|
|
|
AddShape(service);
|
|
|
|
if( !mxShape.is() )
|
|
return;
|
|
|
|
SetLayer();
|
|
|
|
uno::Reference< beans::XPropertySet > xProps(mxShape, uno::UNO_QUERY);
|
|
|
|
if(bIsPresShape && xProps.is())
|
|
{
|
|
uno::Reference< beans::XPropertySetInfo > xPropsInfo( xProps->getPropertySetInfo() );
|
|
if( xPropsInfo.is() )
|
|
{
|
|
if( !mbIsPlaceholder && xPropsInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr))
|
|
xProps->setPropertyValue(u"IsEmptyPresentationObject"_ustr, css::uno::Any(false) );
|
|
|
|
if( mbIsUserTransformed && xPropsInfo->hasPropertyByName(u"IsPlaceholderDependent"_ustr))
|
|
xProps->setPropertyValue(u"IsPlaceholderDependent"_ustr, css::uno::Any(false) );
|
|
}
|
|
}
|
|
|
|
SetStyle();
|
|
|
|
if( xProps.is() )
|
|
{
|
|
if( !msTemplateStyleName.isEmpty() ) try
|
|
{
|
|
Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetImport().GetModel(), UNO_QUERY_THROW );
|
|
Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
|
|
Reference< XNameAccess > xTableFamily( xFamilies->getByName( u"table"_ustr ), UNO_QUERY_THROW );
|
|
Reference< XStyle > xTableStyle( xTableFamily->getByName( msTemplateStyleName ), UNO_QUERY_THROW );
|
|
xProps->setPropertyValue(u"TableTemplate"_ustr, Any( xTableStyle ) );
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("xmloff.draw");
|
|
}
|
|
|
|
const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0];
|
|
for( int i = 0; !pEntry->IsEnd() && (i < 6); i++, pEntry++ )
|
|
{
|
|
try
|
|
{
|
|
xProps->setPropertyValue( pEntry->getApiName(), Any( maTemplateStylesUsed[i] ) );
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("xmloff.draw");
|
|
}
|
|
}
|
|
}
|
|
|
|
GetImport().GetShapeImport()->finishShape( mxShape, mxAttrList, mxShapes );
|
|
|
|
const rtl::Reference< XMLTableImport >& xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() );
|
|
if( xTableImport.is() && xProps.is() )
|
|
{
|
|
uno::Reference< table::XColumnRowRange > xColumnRowRange(
|
|
xProps->getPropertyValue(u"Model"_ustr), uno::UNO_QUERY );
|
|
|
|
if( xColumnRowRange.is() )
|
|
mxTableImportContext = xTableImport->CreateTableContext( xColumnRowRange );
|
|
|
|
if( mxTableImportContext.is() )
|
|
mxTableImportContext->startFastElement( nElement, xAttrList );
|
|
}
|
|
}
|
|
|
|
void SdXMLTableShapeContext::endFastElement(sal_Int32 nElement)
|
|
{
|
|
if( mxTableImportContext.is() )
|
|
mxTableImportContext->endFastElement(nElement);
|
|
|
|
SdXMLShapeContext::endFastElement(nElement);
|
|
|
|
if( mxShape.is() )
|
|
{
|
|
// set pos, size, shear and rotate
|
|
SetTransformation();
|
|
}
|
|
}
|
|
|
|
// this is called from the parent group for each unparsed attribute in the attribute list
|
|
bool SdXMLTableShapeContext::processAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter & aIter )
|
|
{
|
|
auto nElement = aIter.getToken();
|
|
if( IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
|
|
{
|
|
if( (nElement & TOKEN_MASK) == XML_TEMPLATE_NAME )
|
|
{
|
|
msTemplateStyleName = aIter.toString();
|
|
}
|
|
else
|
|
{
|
|
int i = 0;
|
|
const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0];
|
|
while( !pEntry->IsEnd() && (i < 6) )
|
|
{
|
|
if( (nElement & TOKEN_MASK) == pEntry->meXMLName )
|
|
{
|
|
if( IsXMLToken( aIter, XML_TRUE ) )
|
|
maTemplateStylesUsed[i] = true;
|
|
break;
|
|
}
|
|
pEntry++;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
return SdXMLShapeContext::processAttribute( aIter );
|
|
}
|
|
|
|
css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLTableShapeContext::createFastChildContext(
|
|
sal_Int32 nElement,
|
|
const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
|
|
{
|
|
if( mxTableImportContext.is() && IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) )
|
|
return mxTableImportContext->createFastChildContext(nElement, xAttrList);
|
|
return SdXMLShapeContext::createFastChildContext(nElement, xAttrList);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|