Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / oox / source / shape / WpsContext.cxx
blobb26ce06562b097d0c41687768eac7c0ade6ba4fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include "WpsContext.hxx"
11 #include <basegfx/matrix/b2dhommatrix.hxx>
12 #include <comphelper/sequenceashashmap.hxx>
13 #include <drawingml/customshapeproperties.hxx>
14 #include <drawingml/shapepropertiescontext.hxx>
15 #include <drawingml/shapestylecontext.hxx>
16 #include <com/sun/star/beans/XPropertySet.hpp>
17 #include <com/sun/star/beans/XPropertyState.hpp>
18 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
19 #include <com/sun/star/lang/XServiceInfo.hpp>
20 #include <com/sun/star/text/XText.hpp>
21 #include <com/sun/star/text/XTextCursor.hpp>
22 #include <svx/svdtrans.hxx>
23 #include <oox/helper/attributelist.hxx>
24 #include <oox/token/namespaces.hxx>
25 #include <oox/token/tokens.hxx>
27 #include <boost/optional.hpp>
29 using namespace com::sun::star;
31 namespace oox
33 namespace shape
36 WpsContext::WpsContext(ContextHandler2Helper& rParent, uno::Reference<drawing::XShape> xShape)
37 : ContextHandler2(rParent),
38 mxShape(std::move(xShape))
40 mpShape.reset(new oox::drawingml::Shape("com.sun.star.drawing.CustomShape"));
41 mpShape->setWps(true);
44 WpsContext::~WpsContext() = default;
46 oox::core::ContextHandlerRef WpsContext::onCreateContext(sal_Int32 nElementToken, const oox::AttributeList& rAttribs)
48 switch (getBaseToken(nElementToken))
50 case XML_wsp:
51 break;
52 case XML_cNvCnPr:
53 break;
54 case XML_cNvSpPr:
55 break;
56 case XML_spPr:
57 return new oox::drawingml::ShapePropertiesContext(*this, *mpShape);
58 break;
59 case XML_style:
60 return new oox::drawingml::ShapeStyleContext(*this, *mpShape);
61 break;
62 case XML_bodyPr:
63 if (mxShape.is())
65 uno::Reference<lang::XServiceInfo> xServiceInfo(mxShape, uno::UNO_QUERY);
66 uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
67 OptValue<OUString> oVert = rAttribs.getString(XML_vert);
68 if (oVert.has() && oVert.get() == "vert270")
70 if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
72 // No support for this in core, work around by char rotation, as we do so for table cells already.
73 uno::Reference<text::XText> xText(mxShape, uno::UNO_QUERY);
74 uno::Reference<text::XTextCursor> xTextCursor = xText->createTextCursor();
75 xTextCursor->gotoStart(false);
76 xTextCursor->gotoEnd(true);
77 uno::Reference<beans::XPropertyState> xPropertyState(xTextCursor, uno::UNO_QUERY);
78 beans::PropertyState aState = xPropertyState->getPropertyState("CharRotation");
79 if (aState == beans::PropertyState_DEFAULT_VALUE)
81 uno::Reference<beans::XPropertySet> xTextCursorPropertySet(xTextCursor, uno::UNO_QUERY);
82 xTextCursorPropertySet->setPropertyValue("CharRotation", uno::makeAny(sal_Int16(900)));
85 else
87 // Get the existing rotation of the shape.
88 drawing::HomogenMatrix3 aMatrix;
89 xPropertySet->getPropertyValue("Transformation") >>= aMatrix;
90 basegfx::B2DHomMatrix aTransformation;
91 aTransformation.set(0, 0, aMatrix.Line1.Column1);
92 aTransformation.set(0, 1, aMatrix.Line1.Column2);
93 aTransformation.set(0, 2, aMatrix.Line1.Column3);
94 aTransformation.set(1, 0, aMatrix.Line1.Column1);
95 aTransformation.set(1, 1, aMatrix.Line2.Column2);
96 aTransformation.set(1, 2, aMatrix.Line3.Column3);
97 aTransformation.set(2, 0, aMatrix.Line1.Column1);
98 aTransformation.set(2, 1, aMatrix.Line2.Column2);
99 aTransformation.set(2, 2, aMatrix.Line3.Column3);
100 basegfx::B2DTuple aScale;
101 basegfx::B2DTuple aTranslate;
102 double fRotate = 0;
103 double fShearX = 0;
104 aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
106 // If the text is not rotated the way the shape wants it already, set the angle.
107 const sal_Int32 nRotation = -270;
108 if (static_cast<long>(basegfx::rad2deg(fRotate)) != NormAngle360(static_cast<long>(nRotation) * 100) / 100)
110 comphelper::SequenceAsHashMap aCustomShapeGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
111 aCustomShapeGeometry["TextPreRotateAngle"] <<= nRotation;
112 xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList()));
117 if (xServiceInfo.is())
119 bool bTextFrame = xServiceInfo->supportsService("com.sun.star.text.TextFrame");
120 // Handle inset attributes for Writer textframes.
121 sal_Int32 aInsets[] = { XML_lIns, XML_tIns, XML_rIns, XML_bIns };
122 boost::optional<sal_Int32> oInsets[4];
123 for (std::size_t i = 0; i < SAL_N_ELEMENTS(aInsets); ++i)
125 OptValue<OUString> oValue = rAttribs.getString(aInsets[i]);
126 if (oValue.has())
127 oInsets[i] = oox::drawingml::GetCoordinate(oValue.get());
128 else
129 // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU
130 oInsets[i] = (aInsets[i] == XML_lIns || aInsets[i] == XML_rIns) ? 254 : 127;
132 OUString aProps[] = { OUString("LeftBorderDistance"), OUString("TopBorderDistance"), OUString("RightBorderDistance"), OUString("BottomBorderDistance") };
133 OUString aShapeProps[] = { OUString("TextLeftDistance"), OUString("TextUpperDistance"), OUString("TextRightDistance"), OUString("TextLowerDistance") };
134 for (std::size_t i = 0; i < SAL_N_ELEMENTS(bTextFrame ? aProps : aShapeProps); ++i)
135 if (oInsets[i])
136 xPropertySet->setPropertyValue((bTextFrame ? aProps : aShapeProps)[i], uno::makeAny(*oInsets[i]));
139 // Handle text vertical adjustment inside a text frame
140 if (rAttribs.hasAttribute(XML_anchor))
142 drawing::TextVerticalAdjust eAdjust = drawingml::GetTextVerticalAdjust(rAttribs.getToken(XML_anchor, XML_t));
143 xPropertySet->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust));
146 // Apply character color of the shape to the shape's textbox.
147 uno::Reference<text::XText> xText(mxShape, uno::UNO_QUERY);
148 uno::Reference<text::XTextCursor> xTextCursor = xText->createTextCursor();
149 xTextCursor->gotoStart(false);
150 xTextCursor->gotoEnd(true);
151 const uno::Reference<beans::XPropertyState> xPropertyState(xTextCursor, uno::UNO_QUERY);
152 const beans::PropertyState ePropertyState = xPropertyState->getPropertyState("CharColor");
153 if (ePropertyState == beans::PropertyState_DEFAULT_VALUE)
155 uno::Reference<beans::XPropertySet> xTextBoxPropertySet(xTextCursor, uno::UNO_QUERY);
156 xTextBoxPropertySet->setPropertyValue("CharColor", xPropertySet->getPropertyValue("CharColor"));
158 return this;
160 break;
161 case XML_noAutofit:
162 case XML_spAutoFit:
164 uno::Reference<lang::XServiceInfo> xServiceInfo(mxShape, uno::UNO_QUERY);
165 // We can't use oox::drawingml::TextBodyPropertiesContext here, as this
166 // is a child context of bodyPr, so the shape is already sent: we need
167 // to alter the XShape directly.
168 uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
169 if (xPropertySet.is())
171 if (xServiceInfo->supportsService("com.sun.star.text.TextFrame"))
172 xPropertySet->setPropertyValue("FrameIsAutomaticHeight", uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit));
173 else
174 xPropertySet->setPropertyValue("TextAutoGrowHeight", uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit));
177 break;
178 case XML_prstTxWarp:
179 if (rAttribs.hasAttribute(XML_prst))
181 uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
182 oox::OptValue<OUString> presetShapeName = rAttribs.getString(XML_prst);
183 const OUString& preset = presetShapeName.get();
184 comphelper::SequenceAsHashMap aCustomShapeGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
185 aCustomShapeGeometry["PresetTextWarp"] <<= preset;
186 xPropertySet->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList()));
188 break;
189 case XML_txbx:
191 mpShape->getCustomShapeProperties()->setShapeTypeOverride(true);
192 mpShape->setTextBox(true);
193 //in case if the textbox is linked, save the attributes
194 //for further processing.
195 if (rAttribs.hasAttribute(XML_id))
197 OptValue<OUString> id = rAttribs.getString(XML_id);
198 if (id.has())
200 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr ;
201 linkedTxtBoxAttr.id = id.get().toInt32();
202 mpShape->setTxbxHasLinkedTxtBox(true);
203 mpShape->setLinkedTxbxAttributes(linkedTxtBoxAttr);
207 break;
208 case XML_linkedTxbx:
210 //in case if the textbox is linked, save the attributes
211 //for further processing.
212 mpShape->getCustomShapeProperties()->setShapeTypeOverride(true);
213 mpShape->setTextBox(true);
214 OptValue<OUString> id = rAttribs.getString(XML_id);
215 OptValue<OUString> seq = rAttribs.getString(XML_seq);
216 if (id.has() && seq.has())
218 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr ;
219 linkedTxtBoxAttr.id = id.get().toInt32();
220 linkedTxtBoxAttr.seq = seq.get().toInt32();
221 mpShape->setTxbxHasLinkedTxtBox(true);
222 mpShape->setLinkedTxbxAttributes(linkedTxtBoxAttr);
225 break;
226 default:
227 SAL_WARN("oox", "WpsContext::createFastChildContext: unhandled element: " << getBaseToken(nElementToken));
228 break;
230 return nullptr;
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */