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>
27 #include <boost/optional.hpp>
29 using namespace com::sun::star
;
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
))
57 return new oox::drawingml::ShapePropertiesContext(*this, *mpShape
);
60 return new oox::drawingml::ShapeStyleContext(*this, *mpShape
);
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)));
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
;
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
]);
127 oInsets
[i
] = oox::drawingml::GetCoordinate(oValue
.get());
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
)
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"));
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
));
174 xPropertySet
->setPropertyValue("TextAutoGrowHeight", uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
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()));
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
);
200 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
201 linkedTxtBoxAttr
.id
= id
.get().toInt32();
202 mpShape
->setTxbxHasLinkedTxtBox(true);
203 mpShape
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
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
);
227 SAL_WARN("oox", "WpsContext::createFastChildContext: unhandled element: " << getBaseToken(nElementToken
));
236 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */