/* -*- 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 .
*/
// 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();
}
}
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);
} elseif (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 );
}
}
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)
{ 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)) 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; 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: 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):
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.36 Sekunden
(vorverarbeitet)
¤
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.