/* -*- 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 .
*/
// Related tdf#161833: ignore saved polygon for "recreate on edit" contours // tdf#161833 would cause semi-transparent pixels to be treated as fully // transparent pixels when calculating the wrap contour for an image. To // force the correct contour when loading a document, force the contour // to be recalculated by ignoring the saved polygon if the contour is set // to "recreate on edit". if( !bAuto )
{ if( bPath )
{
basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
} else
{
basegfx::B2DPolygon aPolygon;
// anchor type (must be set before any other properties, because // otherwise some orientations cannot be set or will be changed // afterwards)
xPropSet->setPropertyValue( u"AnchorType"_ustr, Any(eAnchorType) );
// hard properties if( pStyle )
pStyle->FillPropertySet( xPropSet );
// x and y
sal_Int16 nHoriOrient = HoriOrientation::NONE;
aAny = xPropSet->getPropertyValue( u"HoriOrient"_ustr );
aAny >>= nHoriOrient; if( HoriOrientation::NONE == nHoriOrient )
{
xPropSet->setPropertyValue( u"HoriOrientPosition"_ustr, Any(nX) );
}
// page number (must be set after the frame is inserted, because it // will be overwritten then inserting the frame. if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 )
{
xPropSet->setPropertyValue( u"AnchorPageNo"_ustr, Any(nPage) );
}
if (m_isDecorative && xPropSetInfo->hasPropertyByName(u"Decorative"_ustr))
{
xPropSet->setPropertyValue(u"Decorative"_ustr, uno::Any(true));
}
if (m_isSplitAllowed && xPropSetInfo->hasPropertyByName(u"IsSplitAllowed"_ustr))
{
xPropSet->setPropertyValue(u"IsSplitAllowed"_ustr, uno::Any(true));
}
if( XML_TEXT_FRAME_OBJECT != nType &&
XML_TEXT_FRAME_OBJECT_OLE != nType &&
XML_TEXT_FRAME_APPLET != nType &&
XML_TEXT_FRAME_PLUGIN!= nType &&
XML_TEXT_FRAME_FLOATING_FRAME != nType)
{
Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY ); try
{
xTextImportHelper->InsertTextContent(xTxtCntnt);
} catch (lang::IllegalArgumentException const&)
{
TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?"); return;
}
}
// Make adding the shape to Z-Ordering dependent from if we are // inside an inside_deleted_section (redlining). That is necessary // since the shape will be removed again later. It would lead to // errors if it would stay inside the Z-Ordering. Thus, the // easiest way to solve that conflict is to not add it here. if(!GetImport().HasTextImport()
|| !GetImport().GetTextImport()->IsInsideDeleteContext())
{
Reference < XShape > xShape( xPropSet, UNO_QUERY );
try
{ // just dispose to delete
uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY);
// Inform shape importer about the removal so it can adjust // z-indexes.
uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
GetImport().GetShapeImport()->shapeRemoved(xShape);
TextContentAnchorType eNew; if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
( TextContentAnchorType_AT_PARAGRAPH == eNew ||
TextContentAnchorType_AT_CHARACTER == eNew ||
TextContentAnchorType_AS_CHARACTER == eNew ||
TextContentAnchorType_AT_PAGE == eNew) )
eAnchorType = eNew;
} break; case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
{
sal_Int32 nTmp;
sal_Int32 nMax = !comphelper::IsFuzzing() ? SHRT_MAX : 100; if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, nMax))
nPage = static_cast<sal_Int16>(nTmp);
} break; case XML_ELEMENT(SVG, XML_X): case XML_ELEMENT(SVG_COMPAT, XML_X):
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nX, aIter.toView()); break; case XML_ELEMENT(SVG, XML_Y): case XML_ELEMENT(SVG_COMPAT, XML_Y):
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nY, aIter.toView() ); break; case XML_ELEMENT(SVG, XML_WIDTH): case XML_ELEMENT(SVG_COMPAT, XML_WIDTH): // relative widths are obsolete since SRC617. Remove them some day! if( aIter.toView().find( '%' ) != std::string_view::npos )
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
nRelWidth = static_cast<sal_Int16>(nTmp);
} else
{
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nWidth, aIter.toView(), 0 );
} break; case XML_ELEMENT(STYLE, XML_REL_WIDTH): if( IsXMLToken(aIter, XML_SCALE) )
{
bSyncWidth = true;
} else
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
nRelWidth = static_cast<sal_Int16>(nTmp);
} break; case XML_ELEMENT(FO, XML_MIN_WIDTH): case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH): if( aIter.toView().find( '%' ) != std::string_view::npos )
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
nRelWidth = static_cast<sal_Int16>(nTmp);
} else
{
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nWidth, aIter.toView(), 0 );
}
bMinWidth = true; break; case XML_ELEMENT(SVG, XML_HEIGHT): case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT): // relative heights are obsolete since SRC617. Remove them some day! if( aIter.toView().find( '%' ) != std::string_view::npos )
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
nRelHeight = static_cast<sal_Int16>(nTmp);
} else
{
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nHeight, aIter.toView(), 0 );
} break; case XML_ELEMENT(STYLE, XML_REL_HEIGHT): if( IsXMLToken( aIter, XML_SCALE ) )
{
bSyncHeight = true;
} elseif( IsXMLToken( aIter, XML_SCALE_MIN ) )
{
bSyncHeight = true;
bMinHeight = true;
} else
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
nRelHeight = static_cast<sal_Int16>(nTmp);
} break; case XML_ELEMENT(FO, XML_MIN_HEIGHT): case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT): if( aIter.toView().find( '%' ) != std::string_view::npos )
{
sal_Int32 nTmp; if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
nRelHeight = static_cast<sal_Int16>(nTmp);
} else
{
GetImport().GetMM100UnitConverter().convertMeasureToCore(
nHeight, aIter.toView(), 0 );
}
bMinHeight = true; break; case XML_ELEMENT(DRAW, XML_ZINDEX):
::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 ); break; case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
sNextName = aIter.toString(); break; case XML_ELEMENT(XLINK, XML_HREF):
sHRef = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_TRANSFORM):
{ // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling // Currently only rotation is used, but combinations with 'draw:transform' // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height // may be extended/replaced with 'draw:transform' (see draw objects)
SdXMLImExTransform2D aSdXMLImExTransform2D;
basegfx::B2DHomMatrix aFullTransform;
// Use SdXMLImExTransform2D to convert to transformation // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed, // but is not generally available (as it should be, a 'current' UnitConverter should // be available at GetExport() - and maybe was once). May have to be addressed as soon // as translate transformations are used here.
aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
aSdXMLImExTransform2D.GetFullTransform(aFullTransform);
// currently we *only* use rotation (and translation indirectly), so warn if *any* // of the other transform parts is used
SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" );
// Translation comes from the translate to RotCenter, rot and BackTranslate. // This means that it represents the translation between unrotated TopLeft // and rotated TopLeft. This may be checked here now, but currently we only // use rotation around center and assume that this *was* a rotation around // center. The check would compare the object's center with the RotCenter // that can be extracted from the transformation in aFullTransform. // The definition contains implicitly the RotationCenter absolute // to the scaled and translated object, so this may be used if needed (see // _exportTextGraphic how the -trans/rot/trans is composed)
if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
{ // rotation is used, set it. Convert from deg to 10th degree integer // CAUTION: due to #i78696# (rotation mirrored using API) the rotate // value is already mirrored, so do not do it again here (to be in sync // with XMLTextParagraphExport::_exportTextGraphic normally it would need // to me mirrored using * -1.0, see conversion there) // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it // with the wrong orientation as in all other cases - ARGH! We will need to // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN constdouble fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate()));
nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600);
// tdf#115529 may be negative, with the above modulo maximal -3599, so // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation") // and *has* to be in the range [0 .. 3600[ if(nRotation < 0)
{
nRotation += 3600;
}
}
}
} break; case XML_ELEMENT(DRAW, XML_CODE):
sCode = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_OBJECT): break; case XML_ELEMENT(DRAW, XML_ARCHIVE): break; case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
bMayScript = IsXMLToken( aIter, XML_TRUE ); break; case XML_ELEMENT(DRAW, XML_MIME_TYPE): case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
sMimeType = aIter.toString(); break; case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES): case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE):
sTblName = aIter.toString(); break; case XML_ELEMENT(LO_EXT, XML_DECORATIVE): case XML_ELEMENT(DRAW, XML_DECORATIVE):
::sax::Converter::convertBool(m_isDecorative, aIter.toString()); break; case XML_ELEMENT(LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES): case XML_ELEMENT(DRAW, XML_MAY_BREAK_BETWEEN_PAGES):
sax::Converter::convertBool(m_isSplitAllowed, aIter.toString()); break; default:
SAL_INFO("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " value=" << aIter.toString());
}
};
// When we are dealing with a textbox, pImpl will be null; // we need to set the hyperlink to the shape instead
Reference<XShape> xShape = GetShape(); if (xShape.is() && m_pHyperlink)
{
Reference<XPropertySet> xProps(xShape, UNO_QUERY); if (xProps.is())
xProps->setPropertyValue(u"Hyperlink"_ustr, Any(m_pHyperlink->GetHRef()));
}
if( !pImpl ) return;
pImpl->CreateIfNotThere();
// fdo#68839: in case the surviving image was not the first one, // it will have a counter added to its name - set the original name if (pMultiContext.is()) // do this only when necessary; esp. not for text
{ // frames that may have entries in GetRenameMap()!
pImpl->SetName();
}
if( !m_xImplContext.is() )
{ // no child exists if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
{
sal_uInt16 nFrameType = USHRT_MAX; switch (nElement & TOKEN_MASK)
{ case XML_TEXT_BOX:
nFrameType = XML_TEXT_FRAME_TEXTBOX; break; case XML_IMAGE:
nFrameType = XML_TEXT_FRAME_GRAPHIC; break; case XML_OBJECT:
nFrameType = XML_TEXT_FRAME_OBJECT; break; case XML_OBJECT_OLE:
nFrameType = XML_TEXT_FRAME_OBJECT_OLE; break; case XML_APPLET:
nFrameType = XML_TEXT_FRAME_APPLET; break; case XML_PLUGIN:
nFrameType = XML_TEXT_FRAME_PLUGIN; break; case XML_FLOATING_FRAME:
nFrameType = XML_TEXT_FRAME_FLOATING_FRAME; break;
}
if( USHRT_MAX != nFrameType )
{ // Shapes in Writer cannot be named via context menu (#i51726#) if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType ||
XML_TEXT_FRAME_GRAPHIC == nFrameType ) &&
m_HasAutomaticStyleWithoutParentStyle )
{
Reference < XShapes > xShapes;
xContext = XMLShapeImportHelper::CreateFrameChildContext(
GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
} elseif( XML_TEXT_FRAME_PLUGIN == nFrameType )
{ bool bMedia = false;
// check, 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()))
bMedia = true;
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.