// 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;
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();
}
// #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();
}
}
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,
-fShearX,
fRotate,
aTranslate);
drawing::HomogenMatrix3 aUnoMatrix;
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;
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);
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
// 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 );
} returntrue;
}
// 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 );
} returntrue;
}
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);
// 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 );
} returntrue;
}
// 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).
// 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);
} returntrue;
}
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);
}
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();
// 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 );
} returntrue;
}
// 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);
}
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;
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();
// 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 );
} returntrue;
}
// 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();
// 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 );
} returntrue;
}
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;
namespace
{ bool lcl_IsLikelyOOXMLCurve(const basegfx::B2DPolygon& rPolygon)
{
sal_uInt32 nCount = rPolygon.count(); if (!rPolygon.areControlPointsUsed() or nCount < 2) returnfalse; // 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)
{ case2:
{ // 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)) returnfalse; // 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))) returntrue;
} break; case3: case5: return basegfx::areParallel(aStartVec, aEndVec); break; case4: // start and end direction are orthogonal return basegfx::fTools::equalZero(aStartVec.scalar( aEndVec)); break; default: returnfalse;
} returnfalse;
}
} // 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;
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);
// 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 ( 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 ); constbool 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);
// 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 );
} returntrue;
}
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;
// 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 ); returntrue;
}
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();
// 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 ) );
// 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 );
} returntrue;
}
// 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; case XML_ELEMENT(LO_EXT, XML_PAGE_NUMBER):
mnPage = aIter.toInt32(); break; default: return SdXMLShapeContext::processAttribute(aIter);
} returntrue;
}
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&)
{
}
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;
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);
// 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 );
} returntrue;
}
// A hack: getting the model of newly created OLE object will eventually call // SdrOle2Obj::AddOwnLightClient, which will try to update scaling, using the // incomplete object data. Avoid that by setting the special property.
xPropSet->setPropertyValue(u"IgnoreOLEObjectScale"_ustr, uno::Any(true));
// 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 );
} returntrue;
}
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) );
}
// 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";
// 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 );
} returntrue;
}
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)); // could be from old times when a format was unsupported // likely already guessed a possibly more accurate MIME type from MediaURL, don't override bool bUpdateMimeType = false; if (maMimeType != AVMEDIA_MIMETYPE_COMMON)
bUpdateMimeType = true; else
{
OUString aExistingMimeType;
xProps->getPropertyValue(u"MediaMimeType"_ustr) >>= aExistingMimeType; if (aExistingMimeType.isEmpty())
bUpdateMimeType = true;
} if (bUpdateMimeType)
xProps->setPropertyValue(u"MediaMimeType"_ustr, uno::Any(maMimeType) );
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();
// 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 );
} returntrue;
}
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) );
}
}
// 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; returnnew SvXMLImportContext(GetImport());
} elseif (pPluginContext && ::comphelper::IsMediaMimeType(pPluginContext->getMimeType()))
{ // The media may have a preview, import it.
bMedia = true;
}
}
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 ); returntrue; // 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;
}
}
}
}
}
// 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::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;
if ( !maCustomShapeGeometry.empty() )
{
// converting the vector to a sequence
uno::Sequence< beans::PropertyValue > aSeq( comphelper::containerToSequence(maCustomShapeGeometry) );
// 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);
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.