1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include "WpsContext.hxx"
11 #include <basegfx/matrix/b2dhommatrix.hxx>
12 #include <basegfx/tuple/b2dtuple.hxx>
13 #include <comphelper/sequenceashashmap.hxx>
14 #include <drawingml/customshapeproperties.hxx>
15 #include <com/sun/star/beans/XPropertySet.hpp>
16 #include <com/sun/star/beans/XPropertyState.hpp>
17 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
18 #include <com/sun/star/lang/XServiceInfo.hpp>
19 #include <com/sun/star/text/XText.hpp>
20 #include <com/sun/star/text/XTextCursor.hpp>
21 #include <svx/svdtrans.hxx>
22 #include <oox/helper/attributelist.hxx>
23 #include <oox/token/namespaces.hxx>
24 #include <oox/token/tokens.hxx>
25 #include <oox/drawingml/shape.hxx>
27 #include <boost/optional.hpp>
29 using namespace com::sun::star
;
35 WpsContext::WpsContext(ContextHandler2Helper
const& rParent
, uno::Reference
<drawing::XShape
> xShape
,
36 const drawingml::ShapePtr
& pMasterShapePtr
,
37 const drawingml::ShapePtr
& pShapePtr
)
38 : ShapeContext(rParent
, pMasterShapePtr
, pShapePtr
)
39 , mxShape(std::move(xShape
))
41 mpShapePtr
->setWps(true);
44 WpsContext::~WpsContext() = default;
46 oox::core::ContextHandlerRef
WpsContext::onCreateContext(sal_Int32 nElementToken
,
47 const oox::AttributeList
& rAttribs
)
49 switch (getBaseToken(nElementToken
))
57 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
58 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
59 sal_Int32 nVert
= rAttribs
.getToken(XML_vert
, XML_horz
);
60 if (nVert
!= XML_horz
)
62 // Get the existing rotation of the shape.
63 drawing::HomogenMatrix3 aMatrix
;
64 xPropertySet
->getPropertyValue("Transformation") >>= aMatrix
;
65 basegfx::B2DHomMatrix aTransformation
;
66 aTransformation
.set(0, 0, aMatrix
.Line1
.Column1
);
67 aTransformation
.set(0, 1, aMatrix
.Line1
.Column2
);
68 aTransformation
.set(0, 2, aMatrix
.Line1
.Column3
);
69 aTransformation
.set(1, 0, aMatrix
.Line1
.Column1
);
70 aTransformation
.set(1, 1, aMatrix
.Line2
.Column2
);
71 aTransformation
.set(1, 2, aMatrix
.Line3
.Column3
);
72 aTransformation
.set(2, 0, aMatrix
.Line1
.Column1
);
73 aTransformation
.set(2, 1, aMatrix
.Line2
.Column2
);
74 aTransformation
.set(2, 2, aMatrix
.Line3
.Column3
);
75 basegfx::B2DTuple aScale
;
76 basegfx::B2DTuple aTranslate
;
79 aTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
81 // If the text is not rotated the way the shape wants it already, set the angle.
82 const sal_Int32 nRotation
= nVert
== XML_vert270
? -270 : -90;
83 if (static_cast<long>(basegfx::rad2deg(fRotate
))
84 != NormAngle36000(static_cast<long>(nRotation
) * 100) / 100)
86 comphelper::SequenceAsHashMap
aCustomShapeGeometry(
87 xPropertySet
->getPropertyValue("CustomShapeGeometry"));
88 aCustomShapeGeometry
["TextPreRotateAngle"] <<= nRotation
;
89 xPropertySet
->setPropertyValue(
90 "CustomShapeGeometry",
91 uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
95 if (xServiceInfo
.is())
97 // Handle inset attributes for Writer textframes.
98 sal_Int32 aInsets
[] = { XML_lIns
, XML_tIns
, XML_rIns
, XML_bIns
};
99 boost::optional
<sal_Int32
> oInsets
[4];
100 for (std::size_t i
= 0; i
< SAL_N_ELEMENTS(aInsets
); ++i
)
102 OptValue
<OUString
> oValue
= rAttribs
.getString(aInsets
[i
]);
104 oInsets
[i
] = oox::drawingml::GetCoordinate(oValue
.get());
106 // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU
108 = (aInsets
[i
] == XML_lIns
|| aInsets
[i
] == XML_rIns
) ? 254 : 127;
110 const OUString aShapeProps
[]
111 = { OUString("TextLeftDistance"), OUString("TextUpperDistance"),
112 OUString("TextRightDistance"), OUString("TextLowerDistance") };
113 for (std::size_t i
= 0; i
< SAL_N_ELEMENTS(aShapeProps
); ++i
)
115 xPropertySet
->setPropertyValue(aShapeProps
[i
],
116 uno::makeAny(*oInsets
[i
]));
119 // Handle text vertical adjustment inside a text frame
120 if (rAttribs
.hasAttribute(XML_anchor
))
122 drawing::TextVerticalAdjust eAdjust
123 = drawingml::GetTextVerticalAdjust(rAttribs
.getToken(XML_anchor
, XML_t
));
124 xPropertySet
->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust
));
127 // Apply character color of the shape to the shape's textbox.
128 uno::Reference
<text::XText
> xText(mxShape
, uno::UNO_QUERY
);
129 uno::Reference
<text::XTextCursor
> xTextCursor
= xText
->createTextCursor();
130 xTextCursor
->gotoStart(false);
131 xTextCursor
->gotoEnd(true);
132 const uno::Reference
<beans::XPropertyState
> xPropertyState(xTextCursor
,
134 const beans::PropertyState ePropertyState
135 = xPropertyState
->getPropertyState("CharColor");
136 if (ePropertyState
== beans::PropertyState_DEFAULT_VALUE
)
138 uno::Reference
<beans::XPropertySet
> xTextBoxPropertySet(xTextCursor
,
140 uno::Any xCharColor
= xPropertySet
->getPropertyValue("CharColor");
141 Color aColor
= COL_AUTO
;
142 if (xCharColor
>>= aColor
)
144 if (aColor
!= COL_AUTO
)
145 xTextBoxPropertySet
->setPropertyValue("CharColor", xCharColor
);
154 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
155 // We can't use oox::drawingml::TextBodyPropertiesContext here, as this
156 // is a child context of bodyPr, so the shape is already sent: we need
157 // to alter the XShape directly.
158 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
159 if (xPropertySet
.is())
161 if (xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
162 xPropertySet
->setPropertyValue(
163 "FrameIsAutomaticHeight",
164 uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
166 xPropertySet
->setPropertyValue(
167 "TextAutoGrowHeight",
168 uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
173 if (rAttribs
.hasAttribute(XML_prst
))
175 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
176 if (xPropertySet
.is())
178 oox::OptValue
<OUString
> presetShapeName
= rAttribs
.getString(XML_prst
);
179 const OUString
& preset
= presetShapeName
.get();
180 comphelper::SequenceAsHashMap
aCustomShapeGeometry(
181 xPropertySet
->getPropertyValue("CustomShapeGeometry"));
182 aCustomShapeGeometry
["PresetTextWarp"] <<= preset
;
183 xPropertySet
->setPropertyValue(
184 "CustomShapeGeometry",
185 uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
191 mpShapePtr
->getCustomShapeProperties()->setShapeTypeOverride(true);
192 mpShapePtr
->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
);
200 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
201 linkedTxtBoxAttr
.id
= id
.get().toInt32();
202 mpShapePtr
->setTxbxHasLinkedTxtBox(true);
203 mpShapePtr
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
211 //in case if the textbox is linked, save the attributes
212 //for further processing.
213 mpShapePtr
->getCustomShapeProperties()->setShapeTypeOverride(true);
214 mpShapePtr
->setTextBox(true);
215 OptValue
<OUString
> id
= rAttribs
.getString(XML_id
);
216 OptValue
<OUString
> seq
= rAttribs
.getString(XML_seq
);
217 if (id
.has() && seq
.has())
219 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
220 linkedTxtBoxAttr
.id
= id
.get().toInt32();
221 linkedTxtBoxAttr
.seq
= seq
.get().toInt32();
222 mpShapePtr
->setTxbxHasLinkedTxtBox(true);
223 mpShapePtr
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
228 return ShapeContext::onCreateContext(nElementToken
, rAttribs
);
235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */