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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/text/WritingMode.hpp>
21 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
22 #include <drawingml/textbodyproperties.hxx>
23 #include <oox/token/properties.hxx>
24 #include <oox/token/tokens.hxx>
25 #include <tools/gen.hxx>
26 #include <svx/svdobj.hxx>
27 #include <svx/svdotext.hxx>
28 #include <svx/svdoashp.hxx>
29 #include <svx/sdtditm.hxx>
33 using namespace ::com::sun::star::drawing
;
34 using namespace ::com::sun::star::text
;
37 namespace oox::drawingml
{
39 TextBodyProperties::TextBodyProperties()
41 , meVA( TextVerticalAdjust_TOP
)
45 /* For Legacy purposes: TODO: Check if it is required at all! */
46 void TextBodyProperties::pushVertSimulation()
48 sal_Int32 tVert
= moVert
.value_or( XML_horz
);
49 if( !(tVert
== XML_vert
|| tVert
== XML_eaVert
|| tVert
== XML_vert270
|| tVert
== XML_mongolianVert
) )
52 // #160799# fake different vertical text modes by top-bottom writing mode
53 maPropertyMap
.setProperty( PROP_TextWritingMode
, WritingMode_TB_RL
);
55 // workaround for TB_LR as using WritingMode2 doesn't work
56 if( meVA
!= TextVerticalAdjust_CENTER
)
57 maPropertyMap
.setProperty( PROP_TextHorizontalAdjust
,
58 (tVert
== XML_vert270
) ? TextHorizontalAdjust_RIGHT
: TextHorizontalAdjust_LEFT
);
59 if( tVert
== XML_vert270
)
60 maPropertyMap
.setProperty( PROP_TextVerticalAdjust
, TextVerticalAdjust_BOTTOM
);
61 if( ( tVert
== XML_vert
&& meVA
== TextVerticalAdjust_TOP
) ||
62 ( tVert
== XML_vert270
&& meVA
== TextVerticalAdjust_BOTTOM
) )
63 maPropertyMap
.setProperty( PROP_TextHorizontalAdjust
, TextHorizontalAdjust_RIGHT
);
64 else if( meVA
== TextVerticalAdjust_CENTER
)
65 maPropertyMap
.setProperty( PROP_TextHorizontalAdjust
, TextHorizontalAdjust_CENTER
);
68 /* Push text distances / insets, taking into consideration text rotation */
69 void TextBodyProperties::pushTextDistances(Size
const& rTextAreaSize
)
71 for (auto & rValue
: maTextDistanceValues
)
75 static constexpr const std::array
<sal_Int32
, 4> aProps
{
76 PROP_TextLeftDistance
,
77 PROP_TextUpperDistance
,
78 PROP_TextRightDistance
,
79 PROP_TextLowerDistance
82 switch (moTextPreRotation
.value_or(0))
84 case 90*1*60000: nOff
= 3; break;
85 case 90*2*60000: nOff
= 2; break;
86 case 90*3*60000: nOff
= 1; break;
90 if (moVert
&& (moVert
.value() == XML_eaVert
|| moVert
.value() == XML_vert
))
91 nOff
= (nOff
+ 3) % aProps
.size();
92 else if (moVert
&& moVert
.value() == XML_vert270
)
93 nOff
= (nOff
+ 1) % aProps
.size();
95 for (size_t i
= 0; i
< aProps
.size(); i
++)
100 // TODO: Preferred method would be to have a textbox on top
101 // of the shape and the place it according to the (off,ext)
102 if (nOff
== 0 && moTextOffLeft
)
103 nVal
= *moTextOffLeft
;
105 if (nOff
== 1 && moTextOffUpper
)
106 nVal
= *moTextOffUpper
;
108 if (nOff
== 2 && moTextOffRight
)
109 nVal
= *moTextOffRight
;
111 if (nOff
== 3 && moTextOffLower
)
112 nVal
= *moTextOffLower
;
114 sal_Int32 nTextOffsetValue
= nVal
;
118 nTextOffsetValue
= *moInsets
[i
] + nVal
;
121 // if inset is set, then always set the value
122 // this prevents the default to be set (0 is a valid value)
123 if (moInsets
[i
] || nTextOffsetValue
)
125 maTextDistanceValues
[nOff
] = nTextOffsetValue
;
128 nOff
= (nOff
+ 1) % aProps
.size();
131 // Check if bottom and top are set
132 if (maTextDistanceValues
[1] && maTextDistanceValues
[3])
134 double nHeight
= rTextAreaSize
.getHeight();
136 double nTop
= *maTextDistanceValues
[1];
137 double nBottom
= *maTextDistanceValues
[3];
139 // Check if top + bottom is more than text area height.
140 // If yes, we need to adjust the values as defined in OOXML.
141 if (nTop
+ nBottom
>= nHeight
)
143 double diffFactor
= (nTop
+ nBottom
- nHeight
) / 2.0;
145 maTextDistanceValues
[1] = nTop
- diffFactor
;
146 maTextDistanceValues
[3] = nBottom
- diffFactor
;
150 for (size_t i
= 0; i
< aProps
.size(); i
++)
152 if (maTextDistanceValues
[i
])
153 maPropertyMap
.setProperty(aProps
[i
], *maTextDistanceValues
[i
]);
157 /* Readjust the text distances / insets if necessary to take
158 the text area into account, not just the shape area*/
159 void TextBodyProperties::readjustTextDistances(uno::Reference
<drawing::XShape
> const& xShape
)
161 // Only for custom shapes (for now)
162 auto* pCustomShape
= dynamic_cast<SdrObjCustomShape
*>(SdrObject::getSdrObjectFromXShape(xShape
));
165 sal_Int32 nLower
= pCustomShape
->GetTextLowerDistance();
166 sal_Int32 nUpper
= pCustomShape
->GetTextUpperDistance();
168 pCustomShape
->SetMergedItem(makeSdrTextUpperDistItem(0));
169 pCustomShape
->SetMergedItem(makeSdrTextLowerDistItem(0));
171 tools::Rectangle aAnchorRect
;
172 pCustomShape
->TakeTextAnchorRect(aAnchorRect
);
173 Size aAnchorSize
= aAnchorRect
.GetSize();
175 pushTextDistances(aAnchorSize
);
176 if (maTextDistanceValues
[1] && maTextDistanceValues
[3])
178 nLower
= *maTextDistanceValues
[3];
179 nUpper
= *maTextDistanceValues
[1];
182 pCustomShape
->SetMergedItem(makeSdrTextLowerDistItem(nLower
));
183 pCustomShape
->SetMergedItem(makeSdrTextUpperDistItem(nUpper
));
188 } // namespace oox::drawingml
190 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */