/** this map store all gluepoint id mappings for shapes that had user defined gluepoints. This
is needed because on insertion the gluepoints will get a new and unique id */ typedef std::map<sal_Int32,sal_Int32> GluePointIdMap; typedef std::unordered_map< css::uno::Reference < css::drawing::XShape >, GluePointIdMap > ShapeGluePointsMap;
/** this struct is created for each startPage() call and stores information that is needed during importofshapesforonepage.Sincepagescouldbenested(notespagesinsideimpress)there
is a pointer so one can build up a stack of this structs */ struct XMLShapeImportPageContextImpl
{
ShapeGluePointsMap maShapeGluePointsMap;
/** this class is to enable adding members to the XMLShapeImportHelper without getting incompatible */ struct XMLShapeImportHelperImpl
{ // context for sorting shapes
std::shared_ptr<ShapeGroupContext> mpGroupContext;
std::vector<ConnectionHint> maConnections;
// #88546# possibility to switch progress bar handling on/off bool mbHandleProgressBar;
// stores the capability of the current model to create presentation shapes bool mbIsPresentationShapesSupported;
};
XMLShapeImportHelper::~XMLShapeImportHelper()
{
SAL_WARN_IF( !mpImpl->maConnections.empty(), "xmloff", "XMLShapeImportHelper::restoreConnections() was not called!" );
// cleanup factory, decrease refcount. Should lead to destruction.
mpSdPropHdlFactory.clear();
if(rShapes.is())
{ switch(nElement)
{ case XML_ELEMENT(DR3D, XML_SCENE):
{ // dr3d:3dscene inside dr3d:3dscene context
pContext = new SdXML3DSceneShapeContext( rImport, xAttrList, rShapes, false); break;
} case XML_ELEMENT(DR3D, XML_CUBE):
{ // dr3d:3dcube inside dr3d:3dscene context
pContext = new SdXML3DCubeObjectShapeContext( rImport, xAttrList, rShapes); break;
} case XML_ELEMENT(DR3D, XML_SPHERE):
{ // dr3d:3dsphere inside dr3d:3dscene context
pContext = new SdXML3DSphereObjectShapeContext( rImport, xAttrList, rShapes); break;
} case XML_ELEMENT(DR3D, XML_ROTATE):
{ // dr3d:3dlathe inside dr3d:3dscene context
pContext = new SdXML3DLatheObjectShapeContext( rImport, xAttrList, rShapes); break;
} case XML_ELEMENT(DR3D, XML_EXTRUDE):
{ // dr3d:3dextrude inside dr3d:3dscene context
pContext = new SdXML3DExtrudeObjectShapeContext( rImport, xAttrList, rShapes); break;
} default:
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
}
}
if (!pContext) return nullptr;
// now parse the attribute list and call the child context for each unknown attribute for(auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
{ if (!pContext->processAttribute( aIter ))
XMLOFF_WARN_UNKNOWN("xmloff", aIter);
SvXMLShapeContext* XMLShapeImportHelper::CreateGroupChildContext(
SvXMLImport& rImport,
sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList>& xAttrList,
uno::Reference< drawing::XShapes > const & rShapes, bool bTemporaryShape)
{
SdXMLShapeContext *pContext = nullptr; switch (nElement)
{ case XML_ELEMENT(DRAW, XML_G): // draw:g inside group context (RECURSIVE)
pContext = new SdXMLGroupShapeContext( rImport, xAttrList, rShapes, bTemporaryShape); break; case XML_ELEMENT(DR3D, XML_SCENE):
{ // dr3d:3dscene inside group context
pContext = new SdXML3DSceneShapeContext( rImport, xAttrList, rShapes, bTemporaryShape); break;
} case XML_ELEMENT(DRAW, XML_RECT):
{ // draw:rect inside group context
pContext = new SdXMLRectShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_LINE):
{ // draw:line inside group context
pContext = new SdXMLLineShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_CIRCLE): case XML_ELEMENT(DRAW, XML_ELLIPSE):
{ // draw:circle or draw:ellipse inside group context
pContext = new SdXMLEllipseShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_POLYGON): case XML_ELEMENT(DRAW, XML_POLYLINE):
{ // draw:polygon or draw:polyline inside group context
pContext = new SdXMLPolygonShapeContext( rImport, xAttrList, rShapes,
nElement == XML_ELEMENT(DRAW, XML_POLYGON), bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_PATH):
{ // draw:path inside group context
pContext = new SdXMLPathShapeContext( rImport, xAttrList, rShapes, bTemporaryShape); break;
} case XML_ELEMENT(DRAW, XML_FRAME):
{ // text:text-box inside group context
pContext = new SdXMLFrameShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_CONTROL):
{ // draw:control inside group context
pContext = new SdXMLControlShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_CONNECTOR):
{ // draw:connector inside group context
pContext = new SdXMLConnectorShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_MEASURE):
{ // draw:measure inside group context
pContext = new SdXMLMeasureShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_PAGE_THUMBNAIL):
{ // draw:page inside group context
pContext = new SdXMLPageShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_CAPTION): case XML_ELEMENT(OFFICE, XML_ANNOTATION):
{ // draw:caption inside group context
pContext = new SdXMLCaptionShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(CHART, XML_CHART):
{ // chart:chart inside group context
pContext = new SdXMLChartShapeContext( rImport, xAttrList, rShapes, bTemporaryShape ); break;
} case XML_ELEMENT(DRAW, XML_CUSTOM_SHAPE):
{ // draw:customshape
pContext = new SdXMLCustomShapeContext( rImport, xAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_A): returnnew SdXMLShapeLinkContext( rImport, xAttrList, rShapes ); // add other shapes here... default:
XMLOFF_INFO_UNKNOWN_ELEMENT("xmloff", nElement); returnnew SvXMLShapeContext( rImport, bTemporaryShape );
}
// now parse the attribute list and call the child context for each unknown attribute for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
{ if (!pContext->processAttribute( aIter ))
XMLOFF_INFO_UNKNOWN("xmloff", aIter);
} return pContext;
}
// This method is called from SdXMLFrameShapeContext to create children of draw:frame
SvXMLShapeContext* XMLShapeImportHelper::CreateFrameChildContext(
SvXMLImport& rImport,
sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList>& rAttrList,
uno::Reference< drawing::XShapes > const & rShapes, const uno::Reference< xml::sax::XFastAttributeList>& rFrameAttrList)
{
SdXMLShapeContext *pContext = nullptr;
rtl::Reference<sax_fastparser::FastAttributeList> xCombinedAttrList = new sax_fastparser::FastAttributeList(rAttrList); if( rFrameAttrList.is() )
xCombinedAttrList->add(rFrameAttrList);
switch(nElement)
{ case XML_ELEMENT(DRAW, XML_TEXT_BOX):
{ // text:text-box inside group context
pContext = new SdXMLTextBoxShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_IMAGE):
{ // office:image inside group context
pContext = new SdXMLGraphicObjectShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_OBJECT): case XML_ELEMENT(DRAW, XML_OBJECT_OLE):
{ // draw:object or draw:object_ole
pContext = new SdXMLObjectShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(TABLE, XML_TABLE):
{ // draw:object or draw:object_ole if( rImport.IsTableShapeSupported() )
pContext = new SdXMLTableShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_PLUGIN):
{ // draw:plugin
pContext = new SdXMLPluginShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_FLOATING_FRAME):
{ // draw:floating-frame
pContext = new SdXMLFloatingFrameShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} case XML_ELEMENT(DRAW, XML_APPLET):
{ // draw:applet
pContext = new SdXMLAppletShapeContext( rImport, xCombinedAttrList, rShapes ); break;
} // add other shapes here... default:
SAL_INFO("xmloff", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement)); break;
}
if( pContext )
{ // now parse the attribute list and call the child context for each unknown attribute for(auto& aIter : *xCombinedAttrList)
{ if (!pContext->processAttribute( aIter ))
SAL_INFO("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " value=" << aIter.toString());
}
}
if (!xContext)
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); return xContext;
}
/** this function is called whenever the implementation classes like to add this new shapetothegivenXShapes.
*/ void XMLShapeImportHelper::addShape( uno::Reference< drawing::XShape >& rShape, const uno::Reference< xml::sax::XFastAttributeList >&,
uno::Reference< drawing::XShapes >& rShapes)
{ if( rShape.is() && rShapes.is() )
{ // add new shape to parent
rShapes->add( rShape );
/** this function is called whenever the implementation classes have finished importing ashapetothegivenXShapes.TheshapeisalreadyinsertedintoitsXShapesand allpropertiesandstylesareset.
*/ void XMLShapeImportHelper::finishShape(
css::uno::Reference< css::drawing::XShape >& rShape, const css::uno::Reference< css::xml::sax::XFastAttributeList >&,
css::uno::Reference< css::drawing::XShapes >&)
{ /* Set property <PositionLayoutDir> to<PositionInHoriL2R>,ifitexistsandtheimportstatesthat theshapepositioningattributesareinhorizontalleft-to-right layout.ThisisthecasefortheOpenOffice.orgfileformat. ThissettingisdoneforWriterdocuments,becausetheproperty onlyexistsatservicecss::text::Shape-theWriter UNOserviceforshapes. Thevalueindicatesthatthepositioningattributesaregiven inhorizontalleft-to-rightlayout.Thepropertyisevaluated duringthefirstpositioningoftheshapeinordertoconvert theshapepositiongivenintheOpenOffice.orgfileformatto theonefortheOASISOpenOfficefileformat.(#i28749#,#i36248#)
*/
uno::Reference< beans::XPropertySet > xPropSet(rShape, uno::UNO_QUERY); if ( xPropSet.is() )
{ if ( mrImporter.IsShapePositionInHoriL2R() &&
xPropSet->getPropertySetInfo()->hasPropertyByName(
u"PositionLayoutDir"_ustr) )
{
uno::Any aPosLayoutDir;
aPosLayoutDir <<= text::PositionLayoutDir::PositionInHoriL2R;
xPropSet->setPropertyValue( u"PositionLayoutDir"_ustr, aPosLayoutDir );
}
}
}
namespace {
// helper functions for z-order sorting struct ZOrderHint
{
sal_Int32 nIs;
sal_Int32 nShould; /// The hint is for this shape. We don't use uno::Reference here to speed up /// some operations, and because this shape is always held by mxShapes
drawing::XShape* pShape;
// a) handle z-order of group contents after it has been imported // b) apply group events over group contents after it has been imported class ShapeGroupContext
{ public:
uno::Reference< drawing::XShapes > mxShapes;
std::vector<SdXMLEventContextData> maEventData;
std::vector<ZOrderHint> maZOrderList;
std::vector<ZOrderHint> maUnsortedList;
// sort shapes void ShapeGroupContext::popGroupAndPostProcess()
{ if (!maEventData.empty())
{ // tdf#127791 wait until a group is popped to set its event data for (auto& event : maEventData)
event.ApplyProperties();
maEventData.clear();
}
// only do something if we have shapes to sort if( maZOrderList.empty() ) return;
// check if there are more shapes than inserted with ::shapeWithZIndexAdded() // This can happen if there where already shapes on the page before import // Since the writer may delete some of this shapes during import, we need // to do this here and not in our c'tor anymore
// check if we have more shapes than we know of
sal_Int32 nCount = mxShapes->getCount();
for (const ZOrderHint& rHint : maZOrderList)
{ // fill in the gaps from unordered list for (std::vector<ZOrderHint>::iterator aIt = maUnsortedList.begin(); aIt != maUnsortedList.end() && nIndex < rHint.nShould; )
{
pNewOrder[nIndex++] = (*aIt).nIs;
aIt = maUnsortedList.erase(aIt);
}
// this is the current index, all shapes before that // index are finished
sal_Int32 nIndex = 0; for (const ZOrderHint& rHint : maZOrderList)
{ for (std::vector<ZOrderHint>::iterator aIt = maUnsortedList.begin(); aIt != maUnsortedList.end() && nIndex < rHint.nShould; )
{
moveShape( (*aIt).nIs, nIndex++ );
aIt = maUnsortedList.erase(aIt);
void XMLShapeImportHelper::addShapeEvents(SdXMLEventContextData& rData)
{ if (mpImpl->mpGroupContext && mpImpl->mpGroupContext->mxShapes == rData.mxShape)
{ // tdf#127791 wait until a group is popped to set its event data so // that the events are applied to all its children, which are not available // at the start of the group tag
mpImpl->mpGroupContext->maEventData.push_back(rData);
} else
rData.ApplyProperties();
}
void XMLShapeImportHelper::popGroupAndPostProcess()
{
SAL_WARN_IF( !mpImpl->mpGroupContext, "xmloff", "No context to sort!" ); if( !mpImpl->mpGroupContext ) return;
if( nZIndex == -1 )
{ // don't care, so add to unsorted list
mpImpl->mpGroupContext->maUnsortedList.push_back(aNewHint);
} else
{ // insert into sort list
mpImpl->mpGroupContext->maZOrderList.push_back(aNewHint);
}
}
void XMLShapeImportHelper::shapeRemoved(const uno::Reference<drawing::XShape>& xShape)
{ auto it = std::find_if(mpImpl->mpGroupContext->maZOrderList.begin(), mpImpl->mpGroupContext->maZOrderList.end(), [&xShape](const ZOrderHint& rHint)
{ return rHint.pShape == xShape.get();
}); if (it == mpImpl->mpGroupContext->maZOrderList.end()) // Part of the unsorted list, nothing to do. return;
sal_Int32 nZIndex = it->nIs;
for (it = mpImpl->mpGroupContext->maZOrderList.begin(); it != mpImpl->mpGroupContext->maZOrderList.end();)
{ if (it->nIs == nZIndex)
{ // This is xShape: remove it and adjust the max of indexes // accordingly.
it = mpImpl->mpGroupContext->maZOrderList.erase(it);
mpImpl->mpGroupContext->mnCurrentZ--; continue;
} elseif (it->nIs > nZIndex) // On top of xShape: adjust actual index to reflect removal.
it->nIs--;
// #86637# simply setting these values WILL force the connector to do // a new layout promptly. So the line delta values have to be rescued // and restored around connector changes.
uno::Reference< drawing::XShape > xShape(
mrImporter.getInterfaceToIdentifierMapper().getReference( rHint.aDestShapeId ), uno::UNO_QUERY ); if( xShape.is() )
{ if (rHint.bStart)
xConnector->setPropertyValue( u"StartShape"_ustr, uno::Any(xShape) ); else
xConnector->setPropertyValue( u"EndShape"_ustr, uno::Any(xShape) );
/** adds a mapping for a gluepoint identifier from an xml file to the identifier created after inserting
the new gluepoint into the core. The saved mappings can be retrieved by getGluePointId() */ void XMLShapeImportHelper::addGluePointMapping( css::uno::Reference< css::drawing::XShape > const & xShape,
sal_Int32 nSourceId, sal_Int32 nDestinnationId )
{ if( mpPageContext )
mpPageContext->maShapeGluePointsMap[xShape][nSourceId] = nDestinnationId;
}
/** moves all current DestinationId's by n */ void XMLShapeImportHelper::moveGluePointMapping( const css::uno::Reference< css::drawing::XShape >& xShape, const sal_Int32 n )
{ if( mpPageContext )
{
ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) ); if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
{ for ( auto& rShapeId : (*aShapeIter).second )
{ if ( rShapeId.second != -1 )
rShapeId.second += n;
}
}
}
}
/** retrieves a mapping for a gluepoint identifier from the current xml file to the identifier created after
inserting the new gluepoint into the core. The mapping must be initialized first with addGluePointMapping() */
sal_Int32 XMLShapeImportHelper::getGluePointId( const css::uno::Reference< css::drawing::XShape >& xShape, sal_Int32 nSourceId )
{ if( mpPageContext )
{
ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) ); if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
{
GluePointIdMap::iterator aIdIter = (*aShapeIter).second.find(nSourceId); if( aIdIter != (*aShapeIter).second.end() ) return (*aIdIter).second;
}
}
return -1;
}
/** this method must be calling before the first shape is imported for the given page */ void XMLShapeImportHelper::startPage( css::uno::Reference< css::drawing::XShapes > const & rShapes )
{ const std::shared_ptr<XMLShapeImportPageContextImpl> pOldContext = mpPageContext;
mpPageContext = std::make_shared<XMLShapeImportPageContextImpl>();
mpPageContext->mpNext = pOldContext;
mpPageContext->mxShapes = rShapes;
}
/** this method must be calling after the last shape is imported for the given page */ void XMLShapeImportHelper::endPage( css::uno::Reference< css::drawing::XShapes > const & rShapes )
{
SAL_WARN_IF( !mpPageContext || (mpPageContext->mxShapes != rShapes), "xmloff", "wrong call to endPage(), no startPage called or wrong page" ); if( nullptr == mpPageContext ) return;
restoreConnections();
mpPageContext = mpPageContext->mpNext;
}
/** defines if the import should increment the progress bar or not */ void XMLShapeImportHelper::enableHandleProgressBar()
{
mpImpl->mbHandleProgressBar = true;
}
/** queries the capability of the current model to create presentation shapes */ bool XMLShapeImportHelper::IsPresentationShapesSupported() const
{ return mpImpl->mbIsPresentationShapesSupported;
}
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.