/* -*- 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 .
*/
// create table export helper and let him add his families in time
GetShapeTableExport();
}
XMLShapeExport::~XMLShapeExport()
{
}
// sj: replacing CustomShapes with standard objects that are also supported in OpenOffice.org format
uno::Reference< drawing::XShape > XMLShapeExport::checkForCustomShapeReplacement( const uno::Reference< drawing::XShape >& xShape )
{
uno::Reference< drawing::XShape > xCustomShapeReplacement;
// first compute the shapes type
ImpCalcShapeType(xShape, aShapeInfo.meShapeType);
// #i118485# enabled XmlShapeType::DrawChartShape and XmlShapeType::DrawOLE2Shape // to have text constbool bObjSupportsText =
supportsText(aShapeInfo.meShapeType);
if ( aShapeInfo.xCustomShapeReplacement.is() )
xPropSet.clear();
// prep text styles if( xPropSet.is() && bObjSupportsText )
{
uno::Reference< text::XText > xText(xShape, uno::UNO_QUERY); if (xText.is())
{ try
{ // tdf#153161: it seems that the call to xText->getText flushes the changes // for some objects, that otherwise fail to get exported correctly. Maybe at some // point it would make sense to find a better place for more targeted flush.
xText = xText->getText();
} catch (uno::RuntimeException const&)
{ // E.g., SwXTextFrame that contains only a table will throw; this is not an error
}
if(xStyle.is())
{ // get family ID
uno::Reference< beans::XPropertySet > xStylePropSet(xStyle, uno::UNO_QUERY);
SAL_WARN_IF( !xStylePropSet.is(), "xmloff", "style without a XPropertySet?" ); try
{ if(xStylePropSet.is())
{
OUString aFamilyName;
xStylePropSet->getPropertyValue(u"Family"_ustr) >>= aFamilyName; if( !aFamilyName.isEmpty() && aFamilyName != "graphics" )
aShapeInfo.mnFamily = XmlStyleFamily::SD_PRESENTATION_ID;
}
} catch(const beans::UnknownPropertyException&)
{ // Ignored.
SAL_WARN( "xmloff", "XMLShapeExport::collectShapeAutoStyles: style has no 'Family' property");
}
// get parent-style name if(XmlStyleFamily::SD_PRESENTATION_ID == aShapeInfo.mnFamily)
{
aParentName = msPresentationStylePrefix;
}
aParentName += xStyle->getName();
}
}
if (aParentName.isEmpty() && xPropertySetInfo->hasPropertyByName(u"TextBox"_ustr) && xPropSet->getPropertyValue(u"TextBox"_ustr).hasValue() && xPropSet->getPropertyValue(u"TextBox"_ustr).get<bool>())
{ // Shapes with a Writer TextBox always have a parent style. // If there would be none, then assign the default one.
aParentName = "Frame";
}
if (XmlShapeType::DrawControlShape == aShapeInfo.meShapeType)
{ // for control shapes, we additionally need the number format style (if any)
uno::Reference< drawing::XControlShape > xControl(xShape, uno::UNO_QUERY);
DBG_ASSERT(xControl.is(), "XMLShapeExport::collectShapeAutoStyles: ShapeType control, but no XControlShape!"); if (xControl.is())
{
uno::Reference< beans::XPropertySet > xControlModel(xControl->getControl(), uno::UNO_QUERY);
DBG_ASSERT(xControlModel.is(), "XMLShapeExport::collectShapeAutoStyles: no control model on the control shape!");
OUString sNumberStyle = mrExport.GetFormExport()->getControlNumberStyle(xControlModel); if (!sNumberStyle.isEmpty())
{
sal_Int32 nIndex = GetPropertySetMapper()->getPropertySetMapper()->FindEntryIndex(CTF_SD_CONTROL_SHAPE_DATA_STYLE); // TODO : this retrieval of the index could be moved into the ctor, holding the index // as member, thus saving time.
DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!");
if(nCount == 0)
{ // no hard attributes, use parent style name for export
aShapeInfo.msStyleName = aParentName;
} else
{ // there are filtered properties -> hard attributes // try to find this style in AutoStylePool
aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Find(aShapeInfo.mnFamily, aParentName, aPropStates);
if(aShapeInfo.msStyleName.isEmpty())
{ // Style did not exist, add it to AutoStalePool
aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Add(aShapeInfo.mnFamily, aParentName, std::move(aPropStates));
}
}
// optionally generate auto style for text attributes if( (!bIsEmptyPresObj || (aShapeInfo.meShapeType != XmlShapeType::PresPageShape)) && bObjSupportsText )
{
aPropStates = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(mrExport, xPropSet);
// yet more additionally, we need to care for the ParaAdjust property if ( XmlShapeType::DrawControlShape == aShapeInfo.meShapeType )
{
uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
uno::Reference< beans::XPropertyState > xPropState( xPropSet, uno::UNO_QUERY ); if ( xPropSetInfo.is() && xPropState.is() )
{ // this is because: // * if controls shapes have a ParaAdjust property, then this is the Align property of the control model // * control models are allowed to have an Align of "void" // * the Default for control model's Align is TextAlign_LEFT // * defaults for style properties are not written, but we need to write the "left", // because we need to distinguish this "left" from the case where not align attribute // is present which means "void" if ( xPropSetInfo->hasPropertyByName( u"ParaAdjust"_ustr )
&& ( beans::PropertyState_DEFAULT_VALUE == xPropState->getPropertyState( u"ParaAdjust"_ustr ) )
)
{
sal_Int32 nIndex = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->getPropertySetMapper()->FindEntryIndex( CTF_SD_SHAPE_PARA_ADJUST ); // TODO : this retrieval of the index should be moved into the ctor, holding the index // as member, thus saving time.
DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for the ParaAdjust context id!");
// Need to stash the attributes that are pre-loaded for the shape export // (otherwise they will become attributes of the draw:a element)
uno::Reference<xml::sax::XAttributeList> xSaveAttribs( new comphelper::AttributeList(GetExport().GetAttrList()));
GetExport().ClearAttrList(); if( xSet.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW) )
{ // export hyperlinks with <a><shape/></a>. Currently only in draw since draw // does not support document events try
{
presentation::ClickAction eAction = presentation::ClickAction_NONE;
xSet->getPropertyValue(gsOnClick) >>= eAction;
auto it = aShapeInfoMap.find(xShape); if (it == aShapeInfoMap.end())
{
SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no shape info collected for a given shape" ); return;
}
#ifdef DBG_UTIL // check if this is the correct ShapesInfo
uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY ); if( xChild.is() )
{
uno::Reference< drawing::XShapes > xParent( xChild->getParent(), uno::UNO_QUERY );
SAL_WARN_IF( !xParent.is() && xParent.get() == (*maCurrentShapesIter).first.get(), "xmloff", "XMLShapeExport::exportShape(): Wrong call to XMLShapeExport::seekShapes()" );
}
// first compute the shapes type
{
XmlShapeType eShapeType(XmlShapeType::NotYetSet);
ImpCalcShapeType(xShape, eShapeType);
SAL_WARN_IF( eShapeType != aShapeInfo.meShapeType, "xmloff", "exportShape callings do not correspond to collectShapeAutoStyles calls!: " << xShape->getShapeType() );
} #endif
// collect animation information if needed if( mxAnimationsExporter.is() )
mxAnimationsExporter->collect( xShape, mrExport );
/* Export shapes name if he has one (#i51726#) Export of the shape name for text documents only if the OpenDocument file format is written - exceptions are group shapes. Note: Writer documents in OpenOffice.org file format doesn't contain any names for shapes, except for group shapes.
*/
{ if ( ( GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER &&
GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERWEB &&
GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERGLOBAL ) ||
( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) ||
aShapeInfo.meShapeType == XmlShapeType::DrawGroupShape ||
( aShapeInfo.meShapeType == XmlShapeType::DrawCustomShape &&
aShapeInfo.xCustomShapeReplacement.is() ) )
{
uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY ); if( xNamed.is() )
{ const OUString aName( xNamed->getName() ); if( !aName.isEmpty() )
mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, aName );
}
}
}
// export layer information if( mbExportLayer )
{ // check for group or scene shape and not export layer if this is one
uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY ); if( !xShapes.is() )
{ try
{
uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
OUString aLayerName;
xProps->getPropertyValue(u"LayerName"_ustr) >>= aLayerName;
mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_LAYER, aLayerName );
} catch(const uno::Exception&)
{
DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting layer name for shape" );
}
}
}
// export draw:display (do not export in ODF 1.3 or older) if (xSet.is() && (mrExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
{ if( aShapeInfo.meShapeType != XmlShapeType::DrawPageShape && aShapeInfo.meShapeType != XmlShapeType::PresPageShape &&
aShapeInfo.meShapeType != XmlShapeType::HandoutShape && aShapeInfo.meShapeType != XmlShapeType::DrawChartShape ) try
{ bool bVisible = true; bool bPrintable = true;
// #82003# test export count // #91587# ALWAYS increment since now ALL to be exported shapes are counted. if(mrExport.GetShapeExport()->IsHandleProgressBarEnabled())
{
mrExport.GetProgressBarHelper()->Increment();
}
onExport( xShape );
// export shape element switch(aShapeInfo.meShapeType)
{ case XmlShapeType::DrawRectangleShape:
{
ImpExportRectangleShape(xShape, nFeatures, pRefPoint ); break;
} case XmlShapeType::DrawEllipseShape:
{
ImpExportEllipseShape(xShape, nFeatures, pRefPoint ); break;
} case XmlShapeType::DrawLineShape:
{
ImpExportLineShape(xShape, nFeatures, pRefPoint ); break;
} case XmlShapeType::DrawPolyPolygonShape: // closed PolyPolygon case XmlShapeType::DrawPolyLineShape: // open PolyPolygon case XmlShapeType::DrawClosedBezierShape: // closed tools::PolyPolygon containing curves case XmlShapeType::DrawOpenBezierShape: // open tools::PolyPolygon containing curves
{
ImpExportPolygonShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawTextShape: case XmlShapeType::PresTitleTextShape: case XmlShapeType::PresOutlinerShape: case XmlShapeType::PresSubtitleShape: case XmlShapeType::PresNotesShape: case XmlShapeType::PresHeaderShape: case XmlShapeType::PresFooterShape: case XmlShapeType::PresSlideNumberShape: case XmlShapeType::PresDateTimeShape:
{
ImpExportTextBoxShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawGraphicObjectShape: case XmlShapeType::PresGraphicObjectShape:
{
ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawChartShape: case XmlShapeType::PresChartShape:
{
ImpExportChartShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint, pAttrList ); break;
}
case XmlShapeType::DrawControlShape:
{
ImpExportControlShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawConnectorShape:
{
ImpExportConnectorShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawMeasureShape:
{
ImpExportMeasureShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawOLE2Shape: case XmlShapeType::PresOLE2Shape: case XmlShapeType::DrawSheetShape: case XmlShapeType::PresSheetShape:
{
ImpExportOLE2Shape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::PresTableShape: case XmlShapeType::DrawTableShape:
{
ImpExportTableShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawPageShape: case XmlShapeType::PresPageShape: case XmlShapeType::HandoutShape:
{
ImpExportPageShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawCaptionShape:
{
ImpExportCaptionShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::Draw3DCubeObject: case XmlShapeType::Draw3DSphereObject: case XmlShapeType::Draw3DLatheObject: case XmlShapeType::Draw3DExtrudeObject:
{
ImpExport3DShape(xShape, aShapeInfo.meShapeType); break;
}
case XmlShapeType::Draw3DSceneObject:
{
ImpExport3DSceneShape( xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawGroupShape:
{ // empty group
ImpExportGroupShape( xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawFrameShape:
{
ImpExportFrameShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawAppletShape:
{
ImpExportAppletShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawPluginShape:
{
ImpExportPluginShape(xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::DrawCustomShape:
{ if ( aShapeInfo.xCustomShapeReplacement.is() )
ImpExportGroupShape( aShapeInfo.xCustomShapeReplacement, nFeatures, pRefPoint ); else
ImpExportCustomShape( xShape, nFeatures, pRefPoint ); break;
}
case XmlShapeType::PresMediaShape: case XmlShapeType::DrawMediaShape:
{
ImpExportMediaShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint ); break;
}
case XmlShapeType::PresOrgChartShape: case XmlShapeType::Unknown: case XmlShapeType::NotYetSet: default:
{ // this should never happen and is an error
OSL_FAIL("XMLEXP: WriteShape: unknown or unexpected type of shape in export!"); break;
}
}
pHyperlinkElement.reset();
// #97489# #97111# // if there was an error and no element for the shape was exported // we need to clear the attribute list or the attributes will be // set on the next exported element, which can result in corrupt // xml files due to duplicate attributes
mrExport.CheckAttrList(); // asserts in non pro if we have attributes left
mrExport.ClearAttrList(); // clears the attributes
}
// This method collects all automatic styles for the shapes inside the given XShapes collection void XMLShapeExport::collectShapesAutoStyles( const uno::Reference < drawing::XShapes >& xShapes )
{
ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
seekShapes( xShapes );
/// returns the export property mapper for external chaining
SvXMLExportPropertyMapper* XMLShapeExport::CreateShapePropMapper(
SvXMLExport& rExport )
{
rtl::Reference< XMLPropertyHandlerFactory > xFactory = new XMLSdPropHdlFactory( rExport.GetModel(), rExport );
rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper( xFactory, true );
rExport.GetTextParagraphExport(); // get or create text paragraph export
SvXMLExportPropertyMapper* pResult = new XMLShapeExportPropertyMapper( xMapper, rExport ); // chain text attributes return pResult;
}
void XMLShapeExport::ImpCalcShapeType(const uno::Reference< drawing::XShape >& xShape,
XmlShapeType& eShapeType)
{ // set in every case, so init here
eShapeType = XmlShapeType::Unknown;
// #i72177# Note: Correcting CustomShape, CustomShape->Custom, len from 9 (was wrong anyways) to 6. // As can be seen at the other compares, the appendix "Shape" is left out of the comparison. elseif(aType.match("Custom", 21)) { eShapeType = XmlShapeType::DrawCustomShape; }
// #i72177# Note: This covers two types by purpose, PolyPolygonShape and PolyPolygonPathShape elseif(aType.match("PolyPolygon", 21)) { eShapeType = XmlShapeType::DrawPolyPolygonShape; }
// #i72177# Note: This covers two types by purpose, PolyLineShape and PolyLinePathShape elseif(aType.match("PolyLine", 21)) { eShapeType = XmlShapeType::DrawPolyLineShape; }
// decompose and correct about pRefPoint
::basegfx::B2DTuple aTRScale; double fTRShear(0.0); double fTRRotate(0.0);
::basegfx::B2DTuple aTRTranslate;
ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
// use features and write
ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
}
void XMLShapeExport::ImpExportNewTrans_GetB2DHomMatrix(::basegfx::B2DHomMatrix& rMatrix, const uno::Reference< beans::XPropertySet >& xPropSet)
{ /* Get <TransformationInHoriL2R>, if it exist and if the document is exported into the OpenOffice.org file format. This property only exists at service css::text::Shape - the Writer UNO service for shapes. This code is needed, because the positioning attributes in the OpenOffice.org file format are given in horizontal left-to-right layout regardless the layout direction the shape is in. In the OASIS Open Office file format the positioning attributes are correctly given in the layout direction the shape is in. Thus, this code provides the conversion from the OASIS Open Office file format to the OpenOffice.org file format. (#i28749#)
*/
uno::Any aAny; if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
xPropSet->getPropertySetInfo()->hasPropertyByName(u"TransformationInHoriL2R"_ustr) )
{
aAny = xPropSet->getPropertyValue(u"TransformationInHoriL2R"_ustr);
} else
{
aAny = xPropSet->getPropertyValue(u"Transformation"_ustr);
}
drawing::HomogenMatrix3 aMatrix;
aAny >>= aMatrix;
rMatrix.set(0, 0, aMatrix.Line1.Column1);
rMatrix.set(0, 1, aMatrix.Line1.Column2);
rMatrix.set(0, 2, aMatrix.Line1.Column3);
rMatrix.set(1, 0, aMatrix.Line2.Column1);
rMatrix.set(1, 1, aMatrix.Line2.Column2);
rMatrix.set(1, 2, aMatrix.Line2.Column3); // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
assert( aMatrix.Line3.Column1 == 0 );
assert( aMatrix.Line3.Column2 == 0 );
assert( aMatrix.Line3.Column3 == 1 );
}
// decide if transformation is necessary bool bTransformationIsNecessary(fTRShear != 0.0 || fTRRotate != 0.0);
if(bTransformationIsNecessary)
{ // write transformation, but WITHOUT scale which is exported as size above
SdXMLImExTransform2D aTransform;
aTransform.AddSkewX(atan(fTRShear));
// #i78696# // fTRRotate is mathematically correct, but due to the error // we export/import it mirrored. Since the API implementation is fixed and // uses the correctly oriented angle, it is necessary for compatibility to // mirror the angle here to stay at the old behaviour. There is a follow-up // task (#i78698#) to fix this in the next ODF FileFormat version
aTransform.AddRotate(-fTRRotate);
aTransform.AddTranslate(rTRTranslate);
// does transformation need to be exported? if(aTransform.NeedsAction())
mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
} else
{ // no shear, no rotate; just add object position to export and we are done if(nFeatures & XMLShapeExportFlags::X)
{ // svg: x
mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
basegfx::fround(rTRTranslate.getX()));
aStr = sStringBuffer.makeStringAndClear();
mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, aStr);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.