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 <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>
26 #include <oox/drawingml/shape.hxx>
27 #include <sal/log.hxx>
29 #include <boost/optional.hpp>
31 using namespace com::sun::star
;
37 WpsContext::WpsContext(ContextHandler2Helper
const& rParent
, uno::Reference
<drawing::XShape
> xShape
,
38 const drawingml::ShapePtr
& pMasterShapePtr
,
39 const drawingml::ShapePtr
& pShapePtr
)
40 : ShapeContext(rParent
, pMasterShapePtr
, pShapePtr
)
41 , mxShape(std::move(xShape
))
43 mpShapePtr
->setWps(true);
46 WpsContext::~WpsContext() = default;
48 oox::core::ContextHandlerRef
WpsContext::onCreateContext(sal_Int32 nElementToken
,
49 const oox::AttributeList
& rAttribs
)
51 switch (getBaseToken(nElementToken
))
60 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
61 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
62 sal_Int32 nVert
= rAttribs
.getToken(XML_vert
, XML_horz
);
63 if (nVert
!= XML_horz
)
65 // Get the existing rotation of the shape.
66 drawing::HomogenMatrix3 aMatrix
;
67 xPropertySet
->getPropertyValue("Transformation") >>= aMatrix
;
68 basegfx::B2DHomMatrix aTransformation
;
69 aTransformation
.set(0, 0, aMatrix
.Line1
.Column1
);
70 aTransformation
.set(0, 1, aMatrix
.Line1
.Column2
);
71 aTransformation
.set(0, 2, aMatrix
.Line1
.Column3
);
72 aTransformation
.set(1, 0, aMatrix
.Line1
.Column1
);
73 aTransformation
.set(1, 1, aMatrix
.Line2
.Column2
);
74 aTransformation
.set(1, 2, aMatrix
.Line3
.Column3
);
75 aTransformation
.set(2, 0, aMatrix
.Line1
.Column1
);
76 aTransformation
.set(2, 1, aMatrix
.Line2
.Column2
);
77 aTransformation
.set(2, 2, aMatrix
.Line3
.Column3
);
78 basegfx::B2DTuple aScale
;
79 basegfx::B2DTuple aTranslate
;
82 aTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
84 // If the text is not rotated the way the shape wants it already, set the angle.
85 const sal_Int32 nRotation
= nVert
== XML_vert270
? -270 : -90;
86 if (static_cast<long>(basegfx::rad2deg(fRotate
))
87 != NormAngle36000(static_cast<long>(nRotation
) * 100) / 100)
89 comphelper::SequenceAsHashMap
aCustomShapeGeometry(
90 xPropertySet
->getPropertyValue("CustomShapeGeometry"));
91 aCustomShapeGeometry
["TextPreRotateAngle"] <<= nRotation
;
92 xPropertySet
->setPropertyValue(
93 "CustomShapeGeometry",
94 uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
98 if (xServiceInfo
.is())
100 // Handle inset attributes for Writer textframes.
101 sal_Int32 aInsets
[] = { XML_lIns
, XML_tIns
, XML_rIns
, XML_bIns
};
102 boost::optional
<sal_Int32
> oInsets
[4];
103 for (std::size_t i
= 0; i
< SAL_N_ELEMENTS(aInsets
); ++i
)
105 OptValue
<OUString
> oValue
= rAttribs
.getString(aInsets
[i
]);
107 oInsets
[i
] = oox::drawingml::GetCoordinate(oValue
.get());
109 // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU
111 = (aInsets
[i
] == XML_lIns
|| aInsets
[i
] == XML_rIns
) ? 254 : 127;
113 const OUString aShapeProps
[]
114 = { OUString("TextLeftDistance"), OUString("TextUpperDistance"),
115 OUString("TextRightDistance"), OUString("TextLowerDistance") };
116 for (std::size_t i
= 0; i
< SAL_N_ELEMENTS(aShapeProps
); ++i
)
118 xPropertySet
->setPropertyValue(aShapeProps
[i
],
119 uno::makeAny(*oInsets
[i
]));
122 // Handle text vertical adjustment inside a text frame
123 if (rAttribs
.hasAttribute(XML_anchor
))
125 drawing::TextVerticalAdjust eAdjust
126 = drawingml::GetTextVerticalAdjust(rAttribs
.getToken(XML_anchor
, XML_t
));
127 xPropertySet
->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust
));
130 // Apply character color of the shape to the shape's textbox.
131 uno::Reference
<text::XText
> xText(mxShape
, uno::UNO_QUERY
);
132 uno::Reference
<text::XTextCursor
> xTextCursor
= xText
->createTextCursor();
133 xTextCursor
->gotoStart(false);
134 xTextCursor
->gotoEnd(true);
135 const uno::Reference
<beans::XPropertyState
> xPropertyState(xTextCursor
,
137 const beans::PropertyState ePropertyState
138 = xPropertyState
->getPropertyState("CharColor");
139 if (ePropertyState
== beans::PropertyState_DEFAULT_VALUE
)
141 uno::Reference
<beans::XPropertySet
> xTextBoxPropertySet(xTextCursor
,
143 uno::Any xCharColor
= xPropertySet
->getPropertyValue("CharColor");
144 Color aColor
= COL_AUTO
;
145 if (xCharColor
>>= aColor
)
147 if (aColor
!= COL_AUTO
)
148 xTextBoxPropertySet
->setPropertyValue("CharColor", xCharColor
);
157 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
158 // We can't use oox::drawingml::TextBodyPropertiesContext here, as this
159 // is a child context of bodyPr, so the shape is already sent: we need
160 // to alter the XShape directly.
161 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
162 if (xPropertySet
.is())
164 if (xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
165 xPropertySet
->setPropertyValue(
166 "FrameIsAutomaticHeight",
167 uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
169 xPropertySet
->setPropertyValue(
170 "TextAutoGrowHeight",
171 uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
176 if (rAttribs
.hasAttribute(XML_prst
))
178 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
179 if (xPropertySet
.is())
181 oox::OptValue
<OUString
> presetShapeName
= rAttribs
.getString(XML_prst
);
182 const OUString
& preset
= presetShapeName
.get();
183 comphelper::SequenceAsHashMap
aCustomShapeGeometry(
184 xPropertySet
->getPropertyValue("CustomShapeGeometry"));
185 aCustomShapeGeometry
["PresetTextWarp"] <<= preset
;
186 xPropertySet
->setPropertyValue(
187 "CustomShapeGeometry",
188 uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
194 mpShapePtr
->getCustomShapeProperties()->setShapeTypeOverride(true);
195 mpShapePtr
->setTextBox(true);
196 //in case if the textbox is linked, save the attributes
197 //for further processing.
198 if (rAttribs
.hasAttribute(XML_id
))
200 OptValue
<OUString
> id
= rAttribs
.getString(XML_id
);
203 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
204 linkedTxtBoxAttr
.id
= id
.get().toInt32();
205 mpShapePtr
->setTxbxHasLinkedTxtBox(true);
206 mpShapePtr
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
214 //in case if the textbox is linked, save the attributes
215 //for further processing.
216 mpShapePtr
->getCustomShapeProperties()->setShapeTypeOverride(true);
217 mpShapePtr
->setTextBox(true);
218 OptValue
<OUString
> id
= rAttribs
.getString(XML_id
);
219 OptValue
<OUString
> seq
= rAttribs
.getString(XML_seq
);
220 if (id
.has() && seq
.has())
222 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
223 linkedTxtBoxAttr
.id
= id
.get().toInt32();
224 linkedTxtBoxAttr
.seq
= seq
.get().toInt32();
225 mpShapePtr
->setTxbxHasLinkedTxtBox(true);
226 mpShapePtr
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
231 return ShapeContext::onCreateContext(nElementToken
, rAttribs
);
238 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */