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 <drawingml/customshapeproperties.hxx>
12 #include <drawingml/shapepropertiescontext.hxx>
13 #include <drawingml/shapestylecontext.hxx>
14 #include <com/sun/star/beans/XPropertySet.hpp>
15 #include <com/sun/star/beans/XPropertyState.hpp>
16 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
17 #include <basegfx/tuple/b2dtuple.hxx>
18 #include <svx/svdtrans.hxx>
20 #include <boost/optional.hpp>
22 using namespace com::sun::star
;
29 WpsContext::WpsContext(ContextHandler2Helper
& rParent
, uno::Reference
<drawing::XShape
> xShape
)
30 : ContextHandler2(rParent
),
33 mpShape
.reset(new oox::drawingml::Shape("com.sun.star.drawing.CustomShape"));
34 mpShape
->setWps(true);
37 WpsContext::~WpsContext()
41 oox::core::ContextHandlerRef
WpsContext::onCreateContext(sal_Int32 nElementToken
, const oox::AttributeList
& rAttribs
)
43 switch (getBaseToken(nElementToken
))
52 return new oox::drawingml::ShapePropertiesContext(*this, *mpShape
);
55 return new oox::drawingml::ShapeStyleContext(*this, *mpShape
);
60 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
61 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
62 OptValue
<OUString
> oVert
= rAttribs
.getString(XML_vert
);
63 if (oVert
.has() && oVert
.get() == "vert270")
65 if (xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
67 // No support for this in core, work around by char rotation, as we do so for table cells already.
68 uno::Reference
<text::XText
> xText(mxShape
, uno::UNO_QUERY
);
69 uno::Reference
<text::XTextCursor
> xTextCursor
= xText
->createTextCursor();
70 xTextCursor
->gotoStart(false);
71 xTextCursor
->gotoEnd(true);
72 uno::Reference
<beans::XPropertyState
> xPropertyState(xTextCursor
, uno::UNO_QUERY
);
73 beans::PropertyState aState
= xPropertyState
->getPropertyState("CharRotation");
74 if (aState
== beans::PropertyState_DEFAULT_VALUE
)
76 uno::Reference
<beans::XPropertySet
> xTextCursorPropertySet(xTextCursor
, uno::UNO_QUERY
);
77 xTextCursorPropertySet
->setPropertyValue("CharRotation", uno::makeAny(sal_Int16(900)));
82 // Get the existing rotation of the shape.
83 drawing::HomogenMatrix3 aMatrix
;
84 xPropertySet
->getPropertyValue("Transformation") >>= aMatrix
;
85 basegfx::B2DHomMatrix aTransformation
;
86 aTransformation
.set(0, 0, aMatrix
.Line1
.Column1
);
87 aTransformation
.set(0, 1, aMatrix
.Line1
.Column2
);
88 aTransformation
.set(0, 2, aMatrix
.Line1
.Column3
);
89 aTransformation
.set(1, 0, aMatrix
.Line1
.Column1
);
90 aTransformation
.set(1, 1, aMatrix
.Line2
.Column2
);
91 aTransformation
.set(1, 2, aMatrix
.Line3
.Column3
);
92 aTransformation
.set(2, 0, aMatrix
.Line1
.Column1
);
93 aTransformation
.set(2, 1, aMatrix
.Line2
.Column2
);
94 aTransformation
.set(2, 2, aMatrix
.Line3
.Column3
);
95 basegfx::B2DTuple aScale
;
96 basegfx::B2DTuple aTranslate
;
99 aTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
101 // If the text is not rotated the way the shape wants it already, set the angle.
102 const sal_Int32 nRotation
= -270;
103 if (basegfx::rad2deg(fRotate
) != static_cast<double>(NormAngle360(nRotation
* 100)) / 100)
105 comphelper::SequenceAsHashMap
aCustomShapeGeometry(xPropertySet
->getPropertyValue("CustomShapeGeometry"));
106 aCustomShapeGeometry
["TextPreRotateAngle"] = uno::makeAny(nRotation
);
107 xPropertySet
->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
112 if (xServiceInfo
.is())
114 bool bTextFrame
= xServiceInfo
->supportsService("com.sun.star.text.TextFrame");
115 // Handle inset attributes for Writer textframes.
116 sal_Int32 aInsets
[] = { XML_lIns
, XML_tIns
, XML_rIns
, XML_bIns
};
117 boost::optional
<sal_Int32
> oInsets
[4];
118 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aInsets
); ++i
)
120 OptValue
<OUString
> oValue
= rAttribs
.getString(aInsets
[i
]);
122 oInsets
[i
] = oox::drawingml::GetCoordinate(oValue
.get());
124 // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU
125 oInsets
[i
] = (aInsets
[i
] == XML_lIns
|| aInsets
[i
] == XML_rIns
) ? 254 : 127;
127 OUString aProps
[] = { OUString("LeftBorderDistance"), OUString("TopBorderDistance"), OUString("RightBorderDistance"), OUString("BottomBorderDistance") };
128 OUString aShapeProps
[] = { OUString("TextLeftDistance"), OUString("TextUpperDistance"), OUString("TextRightDistance"), OUString("TextLowerDistance") };
129 for (size_t i
= 0; i
< SAL_N_ELEMENTS(bTextFrame
? aProps
: aShapeProps
); ++i
)
131 xPropertySet
->setPropertyValue((bTextFrame
? aProps
: aShapeProps
)[i
], uno::makeAny(*oInsets
[i
]));
134 // Handle text vertical adjustment inside a text frame
135 if (rAttribs
.hasAttribute(XML_anchor
))
137 drawing::TextVerticalAdjust eAdjust
= drawingml::GetTextVerticalAdjust(rAttribs
.getToken(XML_anchor
, XML_t
));
138 xPropertySet
->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust
));
141 // Apply character color of the shape to the shape's textbox.
142 uno::Reference
<text::XText
> xText(mxShape
, uno::UNO_QUERY
);
143 uno::Reference
<text::XTextCursor
> xTextCursor
= xText
->createTextCursor();
144 xTextCursor
->gotoStart(false);
145 xTextCursor
->gotoEnd(true);
146 const uno::Reference
<beans::XPropertyState
> xPropertyState(xTextCursor
, uno::UNO_QUERY
);
147 const beans::PropertyState ePropertyState
= xPropertyState
->getPropertyState("CharColor");
148 if (ePropertyState
== beans::PropertyState_DEFAULT_VALUE
)
150 uno::Reference
<beans::XPropertySet
> xTextBoxPropertySet(xTextCursor
, uno::UNO_QUERY
);
151 xTextBoxPropertySet
->setPropertyValue("CharColor", xPropertySet
->getPropertyValue("CharColor"));
159 uno::Reference
<lang::XServiceInfo
> xServiceInfo(mxShape
, uno::UNO_QUERY
);
160 // We can't use oox::drawingml::TextBodyPropertiesContext here, as this
161 // is a child context of bodyPr, so the shape is already sent: we need
162 // to alter the XShape directly.
163 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
164 if (xPropertySet
.is())
166 if (xServiceInfo
->supportsService("com.sun.star.text.TextFrame"))
167 xPropertySet
->setPropertyValue("FrameIsAutomaticHeight", uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
169 xPropertySet
->setPropertyValue("TextAutoGrowHeight", uno::makeAny(getBaseToken(nElementToken
) == XML_spAutoFit
));
174 if (rAttribs
.hasAttribute(XML_prst
))
176 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
177 oox::OptValue
<OUString
> presetShapeName
= rAttribs
.getString(XML_prst
);
178 OUString preset
= presetShapeName
.get();
179 comphelper::SequenceAsHashMap
aCustomShapeGeometry(xPropertySet
->getPropertyValue("CustomShapeGeometry"));
180 aCustomShapeGeometry
["PresetTextWarp"] = uno::makeAny(preset
);
181 xPropertySet
->setPropertyValue("CustomShapeGeometry", uno::makeAny(aCustomShapeGeometry
.getAsConstPropertyValueList()));
186 mpShape
->getCustomShapeProperties()->setShapeTypeOverride(true);
187 mpShape
->setTextBox(true);
188 //in case if the textbox is linked, save the attributes
189 //for further processing.
190 if (rAttribs
.hasAttribute(XML_id
))
192 OptValue
<OUString
> id
= rAttribs
.getString(XML_id
);
195 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
196 linkedTxtBoxAttr
.id
= id
.get().toInt32();
197 mpShape
->setTxbxHasLinkedTxtBox(true);
198 mpShape
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
205 //in case if the textbox is linked, save the attributes
206 //for further processing.
207 mpShape
->getCustomShapeProperties()->setShapeTypeOverride(true);
208 mpShape
->setTextBox(true);
209 OptValue
<OUString
> id
= rAttribs
.getString(XML_id
);
210 OptValue
<OUString
> seq
= rAttribs
.getString(XML_seq
);
211 if (id
.has() && seq
.has())
213 oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr
;
214 linkedTxtBoxAttr
.id
= id
.get().toInt32();
215 linkedTxtBoxAttr
.seq
= seq
.get().toInt32();
216 mpShape
->setTxbxHasLinkedTxtBox(true);
217 mpShape
->setLinkedTxbxAttributes(linkedTxtBoxAttr
);
222 SAL_WARN("oox", "WpsContext::createFastChildContext: unhandled element: " << getBaseToken(nElementToken
));
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */