/* -*- 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/. */ #include "WpsContext.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; namespace oox { namespace shape { WpsContext::WpsContext(ContextHandler2Helper const& rParent, uno::Reference xShape, const drawingml::ShapePtr& pMasterShapePtr, const drawingml::ShapePtr& pShapePtr) : ShapeContext(rParent, pMasterShapePtr, pShapePtr) , mxShape(std::move(xShape)) { mpShapePtr->setWps(true); } WpsContext::~WpsContext() = default; oox::core::ContextHandlerRef WpsContext::onCreateContext(sal_Int32 nElementToken, const oox::AttributeList& rAttribs) { switch (getBaseToken(nElementToken)) { case XML_wsp: break; case XML_cNvCnPr: break; case XML_bodyPr: if (mxShape.is()) { uno::Reference xServiceInfo(mxShape, uno::UNO_QUERY); uno::Reference xPropertySet(mxShape, uno::UNO_QUERY); sal_Int32 nVert = rAttribs.getToken(XML_vert, XML_horz); if (nVert != XML_horz) { // Get the existing rotation of the shape. drawing::HomogenMatrix3 aMatrix; xPropertySet->getPropertyValue("Transformation") >>= aMatrix; basegfx::B2DHomMatrix aTransformation; aTransformation.set(0, 0, aMatrix.Line1.Column1); aTransformation.set(0, 1, aMatrix.Line1.Column2); aTransformation.set(0, 2, aMatrix.Line1.Column3); aTransformation.set(1, 0, aMatrix.Line1.Column1); aTransformation.set(1, 1, aMatrix.Line2.Column2); aTransformation.set(1, 2, aMatrix.Line3.Column3); aTransformation.set(2, 0, aMatrix.Line1.Column1); aTransformation.set(2, 1, aMatrix.Line2.Column2); aTransformation.set(2, 2, aMatrix.Line3.Column3); basegfx::B2DTuple aScale; basegfx::B2DTuple aTranslate; double fRotate = 0; double fShearX = 0; aTransformation.decompose(aScale, aTranslate, fRotate, fShearX); // If the text is not rotated the way the shape wants it already, set the angle. const sal_Int32 nRotation = nVert == XML_vert270 ? -270 : -90; if (static_cast(basegfx::rad2deg(fRotate)) != NormAngle36000(static_cast(nRotation) * 100) / 100) { comphelper::SequenceAsHashMap aCustomShapeGeometry( xPropertySet->getPropertyValue("CustomShapeGeometry")); aCustomShapeGeometry["TextPreRotateAngle"] <<= nRotation; xPropertySet->setPropertyValue( "CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList())); } } if (xServiceInfo.is()) { // Handle inset attributes for Writer textframes. sal_Int32 aInsets[] = { XML_lIns, XML_tIns, XML_rIns, XML_bIns }; boost::optional oInsets[4]; for (std::size_t i = 0; i < SAL_N_ELEMENTS(aInsets); ++i) { OptValue oValue = rAttribs.getString(aInsets[i]); if (oValue.has()) oInsets[i] = oox::drawingml::GetCoordinate(oValue.get()); else // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU oInsets[i] = (aInsets[i] == XML_lIns || aInsets[i] == XML_rIns) ? 254 : 127; } const OUString aShapeProps[] = { OUString("TextLeftDistance"), OUString("TextUpperDistance"), OUString("TextRightDistance"), OUString("TextLowerDistance") }; for (std::size_t i = 0; i < SAL_N_ELEMENTS(aShapeProps); ++i) if (oInsets[i]) xPropertySet->setPropertyValue(aShapeProps[i], uno::makeAny(*oInsets[i])); } // Handle text vertical adjustment inside a text frame if (rAttribs.hasAttribute(XML_anchor)) { drawing::TextVerticalAdjust eAdjust = drawingml::GetTextVerticalAdjust(rAttribs.getToken(XML_anchor, XML_t)); xPropertySet->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust)); } // Apply character color of the shape to the shape's textbox. uno::Reference xText(mxShape, uno::UNO_QUERY); uno::Reference xTextCursor = xText->createTextCursor(); xTextCursor->gotoStart(false); xTextCursor->gotoEnd(true); const uno::Reference xPropertyState(xTextCursor, uno::UNO_QUERY); const beans::PropertyState ePropertyState = xPropertyState->getPropertyState("CharColor"); if (ePropertyState == beans::PropertyState_DEFAULT_VALUE) { uno::Reference xTextBoxPropertySet(xTextCursor, uno::UNO_QUERY); uno::Any xCharColor = xPropertySet->getPropertyValue("CharColor"); Color aColor = COL_AUTO; if (xCharColor >>= aColor) { if (aColor != COL_AUTO) xTextBoxPropertySet->setPropertyValue("CharColor", xCharColor); } } return this; } break; case XML_noAutofit: case XML_spAutoFit: { uno::Reference xServiceInfo(mxShape, uno::UNO_QUERY); // We can't use oox::drawingml::TextBodyPropertiesContext here, as this // is a child context of bodyPr, so the shape is already sent: we need // to alter the XShape directly. uno::Reference xPropertySet(mxShape, uno::UNO_QUERY); if (xPropertySet.is()) { if (xServiceInfo->supportsService("com.sun.star.text.TextFrame")) xPropertySet->setPropertyValue( "FrameIsAutomaticHeight", uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit)); else xPropertySet->setPropertyValue( "TextAutoGrowHeight", uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit)); } } break; case XML_prstTxWarp: if (rAttribs.hasAttribute(XML_prst)) { uno::Reference xPropertySet(mxShape, uno::UNO_QUERY); if (xPropertySet.is()) { oox::OptValue presetShapeName = rAttribs.getString(XML_prst); const OUString& preset = presetShapeName.get(); comphelper::SequenceAsHashMap aCustomShapeGeometry( xPropertySet->getPropertyValue("CustomShapeGeometry")); aCustomShapeGeometry["PresetTextWarp"] <<= preset; xPropertySet->setPropertyValue( "CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList())); } } break; case XML_txbx: { mpShapePtr->getCustomShapeProperties()->setShapeTypeOverride(true); mpShapePtr->setTextBox(true); //in case if the textbox is linked, save the attributes //for further processing. if (rAttribs.hasAttribute(XML_id)) { OptValue id = rAttribs.getString(XML_id); if (id.has()) { oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr; linkedTxtBoxAttr.id = id.get().toInt32(); mpShapePtr->setTxbxHasLinkedTxtBox(true); mpShapePtr->setLinkedTxbxAttributes(linkedTxtBoxAttr); } } return this; } break; case XML_linkedTxbx: { //in case if the textbox is linked, save the attributes //for further processing. mpShapePtr->getCustomShapeProperties()->setShapeTypeOverride(true); mpShapePtr->setTextBox(true); OptValue id = rAttribs.getString(XML_id); OptValue seq = rAttribs.getString(XML_seq); if (id.has() && seq.has()) { oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr; linkedTxtBoxAttr.id = id.get().toInt32(); linkedTxtBoxAttr.seq = seq.get().toInt32(); mpShapePtr->setTxbxHasLinkedTxtBox(true); mpShapePtr->setLinkedTxbxAttributes(linkedTxtBoxAttr); } } break; default: return ShapeContext::onCreateContext(nElementToken, rAttribs); } return nullptr; } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */