/src/libreoffice/oox/source/drawingml/shape.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <config_wasm_strip.h> |
21 | | |
22 | | #include <oox/drawingml/shape.hxx> |
23 | | #include <drawingml/customshapeproperties.hxx> |
24 | | #include <oox/drawingml/theme.hxx> |
25 | | #include <drawingml/fillproperties.hxx> |
26 | | #include <drawingml/fontworkhelpers.hxx> |
27 | | #include <drawingml/graphicproperties.hxx> |
28 | | #include <drawingml/lineproperties.hxx> |
29 | | #include <drawingml/presetgeometrynames.hxx> |
30 | | #include <drawingml/shape3dproperties.hxx> |
31 | | #include <drawingml/scene3dhelper.hxx> |
32 | | #include <drawingml/effectproperties.hxx> |
33 | | #include <oox/drawingml/shapepropertymap.hxx> |
34 | | #include <drawingml/textbody.hxx> |
35 | | #include <drawingml/textparagraph.hxx> |
36 | | #include <drawingml/ThemeOverrideFragmentHandler.hxx> |
37 | | #include <drawingml/table/tableproperties.hxx> |
38 | | #include <oox/drawingml/chart/chartconverter.hxx> |
39 | | #include <drawingml/chart/chartspacefragment.hxx> |
40 | | #include <drawingml/chart/stylefragment.hxx> |
41 | | #include <drawingml/chart/stylemodel.hxx> |
42 | | #include <drawingml/chart/colorsmodel.hxx> |
43 | | #include <drawingml/chart/chartspacemodel.hxx> |
44 | | #include <o3tl/safeint.hxx> |
45 | | #include <o3tl/unit_conversion.hxx> |
46 | | #include <oox/ppt/pptimport.hxx> |
47 | | #include <oox/vml/vmldrawing.hxx> |
48 | | #include <oox/vml/vmlshape.hxx> |
49 | | #include <oox/vml/vmlshapecontainer.hxx> |
50 | | #include <oox/core/xmlfilterbase.hxx> |
51 | | #include <oox/helper/graphichelper.hxx> |
52 | | #include <oox/helper/propertyset.hxx> |
53 | | #include <oox/helper/modelobjecthelper.hxx> |
54 | | #include <oox/mathml/imexport.hxx> |
55 | | #include <oox/mathml/importutils.hxx> |
56 | | #include <oox/token/properties.hxx> |
57 | | #include "diagram/datamodel_oox.hxx" |
58 | | #include <oox/drawingml/diagram/diagramhelper_oox.hxx> |
59 | | |
60 | | #include <comphelper/classids.hxx> |
61 | | #include <comphelper/propertysequence.hxx> |
62 | | #include <comphelper/propertyvalue.hxx> |
63 | | #include <comphelper/sequence.hxx> |
64 | | #include <comphelper/diagnose_ex.hxx> |
65 | | #include <comphelper/sequenceashashmap.hxx> |
66 | | #include <tools/gen.hxx> |
67 | | #include <tools/globname.hxx> |
68 | | #include <tools/mapunit.hxx> |
69 | | #include <editeng/unoprnms.hxx> |
70 | | #include <com/sun/star/awt/FontSlant.hpp> |
71 | | #include <com/sun/star/awt/Size.hpp> |
72 | | #include <com/sun/star/awt/XBitmap.hpp> |
73 | | #include <com/sun/star/awt/FontWeight.hpp> |
74 | | #include <com/sun/star/graphic/XGraphic.hpp> |
75 | | #include <com/sun/star/container/XNamed.hpp> |
76 | | #include <com/sun/star/container/XEnumerationAccess.hpp> |
77 | | #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
78 | | #include <com/sun/star/xml/dom/XDocument.hpp> |
79 | | #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> |
80 | | #include <com/sun/star/drawing/FillStyle.hpp> |
81 | | #include <com/sun/star/drawing/HomogenMatrix3.hpp> |
82 | | #include <com/sun/star/drawing/TextVerticalAdjust.hpp> |
83 | | #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> |
84 | | #include <com/sun/star/drawing/GraphicExportFilter.hpp> |
85 | | #include <com/sun/star/drawing/XShapes.hpp> |
86 | | #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> |
87 | | #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> |
88 | | #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> |
89 | | #include <com/sun/star/drawing/ConnectorType.hpp> |
90 | | #include <com/sun/star/embed/XEmbeddedObject.hpp> |
91 | | #include <com/sun/star/text/XText.hpp> |
92 | | #include <com/sun/star/table/BorderLine2.hpp> |
93 | | #include <com/sun/star/table/ShadowFormat.hpp> |
94 | | #include <com/sun/star/chart2/XChartDocument.hpp> |
95 | | #include <com/sun/star/chart2/XChartStyle.hpp> |
96 | | #include <com/sun/star/chart2/XChartColorStyle.hpp> |
97 | | #include <com/sun/star/style/ParagraphAdjust.hpp> |
98 | | #include <com/sun/star/io/XOutputStream.hpp> |
99 | | #include <com/sun/star/lang/Locale.hpp> |
100 | | #include <com/sun/star/i18n/ScriptType.hpp> |
101 | | #include <com/sun/star/text/WritingMode2.hpp> |
102 | | |
103 | | #include <basegfx/point/b2dpoint.hxx> |
104 | | #include <basegfx/polygon/b2dpolygon.hxx> |
105 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
106 | | #include <com/sun/star/document/XActionLockable.hpp> |
107 | | #include <com/sun/star/chart2/data/XDataReceiver.hpp> |
108 | | #include <officecfg/Office/Common.hxx> |
109 | | #include <svx/svdobj.hxx> |
110 | | #include <svx/svdotable.hxx> |
111 | | #include <svx/svdtrans.hxx> |
112 | | #include <tools/stream.hxx> |
113 | | #include <unotools/streamwrap.hxx> |
114 | | #include <unotools/mediadescriptor.hxx> |
115 | | #include <vcl/graph.hxx> |
116 | | #include <vcl/graphicfilter.hxx> |
117 | | #include <vcl/svapp.hxx> |
118 | | #include <vcl/wmfexternal.hxx> |
119 | | #include <sal/log.hxx> |
120 | | #include <svx/sdtaitm.hxx> |
121 | | #include <oox/drawingml/diagram/diagram.hxx> |
122 | | #include <docmodel/theme/Theme.hxx> |
123 | | #include <i18nlangtag/languagetag.hxx> |
124 | | #include <i18nlangtag/mslangid.hxx> |
125 | | |
126 | | using namespace ::oox::core; |
127 | | using namespace ::com::sun::star; |
128 | | using namespace ::com::sun::star::uno; |
129 | | using namespace ::com::sun::star::beans; |
130 | | using namespace ::com::sun::star::frame; |
131 | | using namespace ::com::sun::star::text; |
132 | | using namespace ::com::sun::star::drawing; |
133 | | using namespace ::com::sun::star::style; |
134 | | |
135 | | namespace oox::drawingml { |
136 | | |
137 | | Shape::Shape() |
138 | 28.4k | : mpLinePropertiesPtr( std::make_shared<LineProperties>() ) |
139 | 28.4k | , mpShapeRefLinePropPtr( std::make_shared<LineProperties>() ) |
140 | 28.4k | , mpFillPropertiesPtr( std::make_shared<FillProperties>() ) |
141 | 28.4k | , mpShapeRefFillPropPtr( std::make_shared<FillProperties>() ) |
142 | 28.4k | , mpGraphicPropertiesPtr( std::make_shared<GraphicProperties>() ) |
143 | 28.4k | , mpCustomShapePropertiesPtr( std::make_shared<CustomShapeProperties>() ) |
144 | 28.4k | , mp3DPropertiesPtr( std::make_shared<Shape3DProperties>() ) |
145 | 28.4k | , mpEffectPropertiesPtr( std::make_shared<EffectProperties>() ) |
146 | 28.4k | , mpShapeRefEffectPropPtr( std::make_shared<EffectProperties>() ) |
147 | 28.4k | , mpMasterTextListStyle( std::make_shared<TextListStyle>() ) |
148 | 28.4k | , mnSubType( 0 ) |
149 | 28.4k | , meFrameType( FRAMETYPE_GENERIC ) |
150 | 28.4k | , mnRotation( 0 ) |
151 | 28.4k | , mnDiagramRotation( 0 ) |
152 | 28.4k | , mbFlipH( false ) |
153 | 28.4k | , mbFlipV( false ) |
154 | 28.4k | , mbHidden( false ) |
155 | 28.4k | , mbHiddenMasterShape( false ) |
156 | 28.4k | , mbLocked( false ) |
157 | 28.4k | , mbWPGChild(false) |
158 | 28.4k | , mbLockedCanvas( false ) |
159 | 28.4k | , mbWordprocessingCanvas(false) |
160 | 28.4k | , mbWps( false ) |
161 | 28.4k | , mbTextBox( false ) |
162 | 28.4k | , mbHasLinkedTxbx( false ) |
163 | 28.4k | , mbHasCustomPrompt( false ) |
164 | 28.4k | , mpDiagramHelper( nullptr ) |
165 | 28.4k | { |
166 | 28.4k | setDefaults(/*bDefaultHeight*/true); |
167 | 28.4k | } |
168 | | |
169 | | |
170 | | Shape::Shape( const OUString& rServiceName, bool bDefaultHeight ) |
171 | 143k | : mpLinePropertiesPtr( std::make_shared<LineProperties>() ) |
172 | 143k | , mpShapeRefLinePropPtr( std::make_shared<LineProperties>() ) |
173 | 143k | , mpFillPropertiesPtr( std::make_shared<FillProperties>() ) |
174 | 143k | , mpShapeRefFillPropPtr( std::make_shared<FillProperties>() ) |
175 | 143k | , mpGraphicPropertiesPtr( std::make_shared<GraphicProperties>() ) |
176 | 143k | , mpCustomShapePropertiesPtr( std::make_shared<CustomShapeProperties>() ) |
177 | 143k | , mp3DPropertiesPtr( std::make_shared<Shape3DProperties>() ) |
178 | 143k | , mpEffectPropertiesPtr( std::make_shared<EffectProperties>() ) |
179 | 143k | , mpShapeRefEffectPropPtr( std::make_shared<EffectProperties>() ) |
180 | 143k | , mpMasterTextListStyle( std::make_shared<TextListStyle>() ) |
181 | 143k | , mnSubType( 0 ) |
182 | 143k | , meFrameType( FRAMETYPE_GENERIC ) |
183 | 143k | , mnRotation( 0 ) |
184 | 143k | , mnDiagramRotation( 0 ) |
185 | 143k | , mbFlipH( false ) |
186 | 143k | , mbFlipV( false ) |
187 | 143k | , mbHidden( false ) |
188 | 143k | , mbHiddenMasterShape( false ) |
189 | 143k | , mbLocked( false ) |
190 | 143k | , mbWPGChild(false) |
191 | 143k | , mbLockedCanvas( false ) |
192 | 143k | , mbWordprocessingCanvas(false) |
193 | 143k | , mbWps( false ) |
194 | 143k | , mbTextBox( false ) |
195 | 143k | , mbHasLinkedTxbx( false ) |
196 | 143k | , mbHasCustomPrompt( false ) |
197 | 143k | , mpDiagramHelper( nullptr ) |
198 | 143k | { |
199 | 143k | msServiceName = rServiceName; |
200 | 143k | setDefaults(bDefaultHeight); |
201 | 143k | } |
202 | | |
203 | | Shape::Shape( const ShapePtr& pSourceShape ) |
204 | 532 | : mpTextBody(pSourceShape->mpTextBody) |
205 | 532 | , mpLinePropertiesPtr( pSourceShape->mpLinePropertiesPtr ) |
206 | 532 | , mpShapeRefLinePropPtr( pSourceShape->mpShapeRefLinePropPtr ) |
207 | 532 | , mpFillPropertiesPtr( pSourceShape->mpFillPropertiesPtr ) |
208 | 532 | , mpShapeRefFillPropPtr( pSourceShape->mpShapeRefFillPropPtr ) |
209 | 532 | , mpGraphicPropertiesPtr( pSourceShape->mpGraphicPropertiesPtr ) |
210 | 532 | , mpCustomShapePropertiesPtr( pSourceShape->mpCustomShapePropertiesPtr ) |
211 | 532 | , mpTablePropertiesPtr( pSourceShape->mpTablePropertiesPtr ) |
212 | 532 | , mp3DPropertiesPtr( pSourceShape->mp3DPropertiesPtr ) |
213 | 532 | , mpEffectPropertiesPtr (pSourceShape->mpEffectPropertiesPtr) |
214 | 532 | , mpShapeRefEffectPropPtr(pSourceShape->mpShapeRefEffectPropPtr) |
215 | 532 | , maShapeProperties( pSourceShape->maShapeProperties ) |
216 | 532 | , mpMasterTextListStyle( pSourceShape->mpMasterTextListStyle ) |
217 | 532 | , msServiceName( pSourceShape->msServiceName ) |
218 | 532 | , msName( pSourceShape->msName ) |
219 | 532 | , msInternalName( pSourceShape->msInternalName ) |
220 | 532 | , msId( pSourceShape->msId ) |
221 | 532 | , mnSubType( pSourceShape->mnSubType ) |
222 | 532 | , moSubTypeIndex( pSourceShape->moSubTypeIndex ) |
223 | 532 | , maShapeStyleRefs( pSourceShape->maShapeStyleRefs ) |
224 | 532 | , maSize( pSourceShape->maSize ) |
225 | 532 | , maPosition( pSourceShape->maPosition ) |
226 | 532 | , meFrameType( pSourceShape->meFrameType ) |
227 | 532 | , mnRotation( pSourceShape->mnRotation ) |
228 | 532 | , mnDiagramRotation( pSourceShape->mnDiagramRotation ) |
229 | 532 | , mbFlipH( pSourceShape->mbFlipH ) |
230 | 532 | , mbFlipV( pSourceShape->mbFlipV ) |
231 | 532 | , mbHidden( pSourceShape->mbHidden ) |
232 | 532 | , mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape ) |
233 | 532 | , mbLocked( pSourceShape->mbLocked ) |
234 | 532 | , mbWPGChild( pSourceShape->mbWPGChild ) |
235 | 532 | , mbLockedCanvas( pSourceShape->mbLockedCanvas ) |
236 | 532 | , mbWordprocessingCanvas(pSourceShape->mbWordprocessingCanvas) |
237 | 532 | , mbWps( pSourceShape->mbWps ) |
238 | 532 | , mbTextBox( pSourceShape->mbTextBox ) |
239 | 532 | , mbHasLinkedTxbx(false) |
240 | 532 | , mbHasCustomPrompt( pSourceShape->mbHasCustomPrompt ) |
241 | 532 | , mnZOrder(pSourceShape->mnZOrder) |
242 | 532 | , mnZOrderOff(pSourceShape->mnZOrderOff) |
243 | 532 | , mnDataNodeType(pSourceShape->mnDataNodeType) |
244 | 532 | , mfAspectRatio(pSourceShape->mfAspectRatio) |
245 | 532 | , mpDiagramHelper( nullptr ) |
246 | 532 | , msDiagramDataModelID(pSourceShape->msDiagramDataModelID) |
247 | 532 | {} |
248 | | |
249 | | Shape::~Shape() |
250 | 172k | { |
251 | | // DiagramHelper should not be set here anymore, see |
252 | | // propagateDiagramHelper below (maybe assert..?) |
253 | 172k | delete mpDiagramHelper; |
254 | 172k | } |
255 | | |
256 | | void Shape::prepareDiagramHelper( |
257 | | const std::shared_ptr< SmartArtDiagram >& rDiagramPtr, |
258 | | const std::shared_ptr<::oox::drawingml::Theme>& rTheme) |
259 | 149 | { |
260 | | // Prepare Diagram data collecting for this Shape |
261 | 149 | if( nullptr == mpDiagramHelper && FRAMETYPE_DIAGRAM == meFrameType ) |
262 | 149 | { |
263 | 149 | mpDiagramHelper = new DiagramHelper_oox( |
264 | 149 | rDiagramPtr, |
265 | 149 | rTheme); |
266 | 149 | } |
267 | 149 | } |
268 | | |
269 | | void Shape::propagateDiagramHelper() |
270 | 303 | { |
271 | | // Propagate collected Diagram data to data holder |
272 | 303 | if (FRAMETYPE_DIAGRAM == meFrameType && nullptr != mpDiagramHelper) |
273 | 149 | { |
274 | 149 | if (mxShape) |
275 | 149 | { |
276 | 149 | mpDiagramHelper->doAnchor(mxShape); |
277 | 149 | mpDiagramHelper = nullptr; |
278 | 149 | } |
279 | 149 | } |
280 | | |
281 | | // If propagation failed, delete/cleanup here. Since the DiagramHelper |
282 | | // holds a Diagram and that this Shape it is necessary - the destructor |
283 | | // will not be called and will be too late |
284 | 303 | if (nullptr != mpDiagramHelper) |
285 | 0 | { |
286 | 0 | delete mpDiagramHelper; |
287 | 0 | mpDiagramHelper = nullptr; |
288 | 0 | } |
289 | 303 | } |
290 | | |
291 | | void Shape::migrateDiagramHelperToNewShape(const ShapePtr& pTarget) |
292 | 30 | { |
293 | 30 | if(!mpDiagramHelper) |
294 | 0 | { |
295 | 0 | return; |
296 | 0 | } |
297 | | |
298 | 30 | if(!pTarget) |
299 | 0 | { |
300 | | // no migrate target, but cleanup helper |
301 | 0 | delete mpDiagramHelper; |
302 | 0 | mpDiagramHelper = nullptr; |
303 | 0 | return; |
304 | 0 | } |
305 | | |
306 | 30 | if(pTarget->mpDiagramHelper) |
307 | 0 | { |
308 | | // this should no happen, but if there is already a helper, clean it up |
309 | 0 | delete pTarget->mpDiagramHelper; |
310 | 0 | pTarget->mpDiagramHelper = nullptr; |
311 | 0 | } |
312 | | |
313 | | // exchange and reset to nullptr |
314 | 30 | pTarget->mpDiagramHelper = mpDiagramHelper; |
315 | 30 | mpDiagramHelper = nullptr; |
316 | 30 | } |
317 | | |
318 | | table::TablePropertiesPtr const & Shape::getTableProperties() |
319 | 124 | { |
320 | 124 | if ( !mpTablePropertiesPtr ) |
321 | 124 | mpTablePropertiesPtr = std::make_shared<table::TableProperties>(); |
322 | 124 | return mpTablePropertiesPtr; |
323 | 124 | } |
324 | | |
325 | | void Shape::setDefaults(bool bHeight) |
326 | 172k | { |
327 | 172k | maDefaultShapeProperties.setProperty(PROP_TextAutoGrowHeight, false); |
328 | 172k | maDefaultShapeProperties.setProperty(PROP_TextWordWrap, true); |
329 | 172k | maDefaultShapeProperties.setProperty(PROP_TextLeftDistance, static_cast< sal_Int32 >( 250 )); |
330 | 172k | maDefaultShapeProperties.setProperty(PROP_TextUpperDistance, static_cast< sal_Int32 >( 125 )); |
331 | 172k | maDefaultShapeProperties.setProperty(PROP_TextRightDistance, static_cast< sal_Int32 >( 250 )); |
332 | 172k | maDefaultShapeProperties.setProperty(PROP_TextLowerDistance, static_cast< sal_Int32 >( 125 )); |
333 | 172k | if (bHeight) |
334 | 172k | maDefaultShapeProperties.setProperty(PROP_CharHeight, static_cast< float >( 18.0 )); |
335 | 172k | maDefaultShapeProperties.setProperty(PROP_TextVerticalAdjust, TextVerticalAdjust_TOP); |
336 | 172k | maDefaultShapeProperties.setProperty(PROP_ParaAdjust, |
337 | 172k | static_cast<sal_Int16>(ParagraphAdjust_LEFT)); |
338 | 172k | } |
339 | | |
340 | | ::oox::vml::OleObjectInfo& Shape::setOleObjectType() |
341 | 0 | { |
342 | 0 | OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setOleObjectType - multiple frame types" ); |
343 | 0 | meFrameType = FRAMETYPE_OLEOBJECT; |
344 | 0 | mxOleObjectInfo = std::make_shared<::oox::vml::OleObjectInfo>( true ); |
345 | 0 | return *mxOleObjectInfo; |
346 | 0 | } |
347 | | |
348 | | ChartShapeInfo& Shape::setChartType( bool bEmbedShapes ) |
349 | 431 | { |
350 | 431 | OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setChartType - multiple frame types" ); |
351 | 431 | meFrameType = FRAMETYPE_CHART; |
352 | 431 | if (mbWps) |
353 | 0 | msServiceName = u"com.sun.star.drawing.temporaryForXMLImportOLE2Shape"_ustr; |
354 | 431 | else |
355 | 431 | msServiceName = u"com.sun.star.drawing.OLE2Shape"_ustr; |
356 | 431 | mxChartShapeInfo = std::make_shared<ChartShapeInfo>( bEmbedShapes ); |
357 | 431 | return *mxChartShapeInfo; |
358 | 431 | } |
359 | | |
360 | | void Shape::setDiagramType() |
361 | 446 | { |
362 | 446 | OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setDiagramType - multiple frame types" ); |
363 | 446 | meFrameType = FRAMETYPE_DIAGRAM; |
364 | 446 | msServiceName = u"com.sun.star.drawing.GroupShape"_ustr; |
365 | 446 | mnSubType = 0; |
366 | 446 | } |
367 | | |
368 | | void Shape::setTableType() |
369 | 124 | { |
370 | 124 | OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setTableType - multiple frame types" ); |
371 | 124 | meFrameType = FRAMETYPE_TABLE; |
372 | 124 | msServiceName = u"com.sun.star.drawing.TableShape"_ustr; |
373 | 124 | mnSubType = 0; |
374 | 124 | } |
375 | | |
376 | | const ShapeStyleRef* Shape::getShapeStyleRef( sal_Int32 nRefType ) const |
377 | 408k | { |
378 | 408k | ShapeStyleRefMap::const_iterator aIt = maShapeStyleRefs.find( nRefType ); |
379 | 408k | return (aIt == maShapeStyleRefs.end()) ? nullptr : &aIt->second; |
380 | 408k | } |
381 | | |
382 | | void Shape::addShape( |
383 | | ::oox::core::XmlFilterBase& rFilterBase, |
384 | | const Theme* pTheme, |
385 | | const Reference< XShapes >& rxShapes, |
386 | | const basegfx::B2DHomMatrix& aTransformation, |
387 | | const FillProperties& rShapeOrParentShapeFillProps, |
388 | | ShapeIdMap* pShapeMap, |
389 | | const oox::drawingml::ShapePtr& pParentGroupShape) |
390 | 9.10k | { |
391 | 9.10k | SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId << "'"); |
392 | | |
393 | 9.10k | try |
394 | 9.10k | { |
395 | 9.10k | OUString sServiceName( msServiceName ); |
396 | 9.10k | if( !sServiceName.isEmpty() ) |
397 | 9.10k | { |
398 | 9.10k | basegfx::B2DHomMatrix aMatrix( aTransformation ); |
399 | 9.10k | Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, false, nullptr, aMatrix, rShapeOrParentShapeFillProps, pParentGroupShape) ); |
400 | | |
401 | 9.10k | if( pShapeMap && !msId.isEmpty() ) |
402 | 26 | { |
403 | 26 | (*pShapeMap)[ msId ] = shared_from_this(); |
404 | 26 | } |
405 | | |
406 | | // if this is a group shape, we have to add also each child shape |
407 | 9.10k | Reference< XShapes > xShapes( xShape, UNO_QUERY ); |
408 | 9.10k | if ( xShapes.is() ) |
409 | 628 | addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aMatrix ); |
410 | | |
411 | 9.10k | if (isInWordprocessingCanvas() && !isWPGChild()) |
412 | 0 | { |
413 | | // This is a drawing canvas. In case the canvas has no fill and no stroke, Word does |
414 | | // not render shadow or glow, even if it is set for the canvas. Thus we disable shadow |
415 | | // and glow in this case for the ersatz background shape of the drawing canvas. |
416 | 0 | try |
417 | 0 | { |
418 | 0 | oox::drawingml::ShapePtr pBgShape = getChildren().front(); |
419 | 0 | const Reference<css::drawing::XShape>& xBgShape = pBgShape->getXShape(); |
420 | 0 | Reference<XPropertySet> xBgProps(xBgShape, uno::UNO_QUERY); |
421 | 0 | drawing::FillStyle eFillStyle = drawing::FillStyle_NONE; |
422 | 0 | xBgProps->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle; |
423 | 0 | drawing::LineStyle eLineStyle = drawing::LineStyle_NONE; |
424 | 0 | xBgProps->getPropertyValue(u"LineStyle"_ustr) >>= eLineStyle; |
425 | 0 | if (eFillStyle == drawing::FillStyle_NONE |
426 | 0 | && eLineStyle == drawing::LineStyle_NONE) |
427 | 0 | { |
428 | 0 | xBgProps->setPropertyValue(UNO_NAME_SHADOW, uno::Any(false)); |
429 | 0 | xBgProps->setPropertyValue(u"GlowEffectRadius"_ustr, uno::Any(sal_Int32(0))); |
430 | 0 | } |
431 | 0 | } |
432 | 0 | catch (const Exception&) |
433 | 0 | { |
434 | 0 | TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::addShape mbWordprocessingCanvas"); |
435 | 0 | } |
436 | 0 | } |
437 | | |
438 | 9.10k | if (isWPGChild() && xShape) |
439 | 278 | { |
440 | | // This is a wps shape and it is the child of the WPG, now copy the |
441 | | // the text body properties to the xshape. |
442 | 278 | Reference<XPropertySet> xChildWPSProperties(xShape, uno::UNO_QUERY); |
443 | | |
444 | 278 | if (getTextBody() && xChildWPSProperties) |
445 | 278 | { |
446 | 278 | xChildWPSProperties->setPropertyValue( |
447 | 278 | UNO_NAME_TEXT_VERTADJUST, |
448 | 278 | uno::Any(getTextBody()->getTextProperties().meVA)); |
449 | | |
450 | 278 | xChildWPSProperties->setPropertyValue( |
451 | 278 | UNO_NAME_TEXT_LEFTDIST, |
452 | 278 | uno::Any(getTextBody()->getTextProperties().moInsets[0].has_value() |
453 | 278 | ? *getTextBody()->getTextProperties().moInsets[0] |
454 | 278 | : 0)); |
455 | 278 | xChildWPSProperties->setPropertyValue( |
456 | 278 | UNO_NAME_TEXT_UPPERDIST, |
457 | 278 | uno::Any(getTextBody()->getTextProperties().moInsets[1].has_value() |
458 | 278 | ? *getTextBody()->getTextProperties().moInsets[1] |
459 | 278 | : 0)); |
460 | 278 | xChildWPSProperties->setPropertyValue( |
461 | 278 | UNO_NAME_TEXT_RIGHTDIST, |
462 | 278 | uno::Any(getTextBody()->getTextProperties().moInsets[2].has_value() |
463 | 278 | ? *getTextBody()->getTextProperties().moInsets[2] |
464 | 278 | : 0)); |
465 | 278 | xChildWPSProperties->setPropertyValue( |
466 | 278 | UNO_NAME_TEXT_LOWERDIST, |
467 | 278 | uno::Any(getTextBody()->getTextProperties().moInsets[3].has_value() |
468 | 278 | ? *getTextBody()->getTextProperties().moInsets[3] |
469 | 278 | : 0)); |
470 | 278 | } |
471 | | |
472 | | // tdf#145147 Set the Hyperlink property to the child wps shape. |
473 | 278 | if (getShapeProperties().hasProperty(PROP_URL)) try |
474 | 0 | { |
475 | 0 | uno::Any aAny = getShapeProperties().getProperty(PROP_URL); |
476 | 0 | OUString sUrl = aAny.get<OUString>(); |
477 | 0 | if (!sUrl.isEmpty()) |
478 | 0 | xChildWPSProperties->setPropertyValue(UNO_NAME_HYPERLINK, aAny); |
479 | 0 | } |
480 | 0 | catch (const Exception&) |
481 | 0 | { |
482 | 0 | } |
483 | 278 | } |
484 | | |
485 | 9.10k | if( meFrameType == FRAMETYPE_DIAGRAM ) |
486 | 303 | { |
487 | | // set DiagramHelper at SdrObjGroup |
488 | 303 | propagateDiagramHelper(); |
489 | | |
490 | | // SmartArtToShapes == true means to get the Group while false did |
491 | | // convert that content to a GraphicObject containing a metafile, |
492 | | // and false is the default. |
493 | | // When we have AdvancedDiagramFeatures this destroys part of the model |
494 | | // that is in that group hosting the diagram and it's hierarchy. |
495 | | // At the same time there are UnitTests that use false, but still do want |
496 | | // to export the unchanged diagram, so it is not possible to just |
497 | | // delete the DiagramHelper_svx again, that would also make the |
498 | | // original data DomTrees vanish. |
499 | | // I think best solution is to not convert to graphic object at |
500 | | // all when AdvancedDiagramFeatures are active, that just makes |
501 | | // no longer sense when we want to be able to do more with the |
502 | | // diagram - and is also already deactivated for Draw/Ipress |
503 | 303 | if (!SdrObject::useAdvancedDiagramFeatures()) |
504 | 303 | { |
505 | | // Check if this is the PPTX import, so far converting SmartArt to a non-editable |
506 | | // metafile is only implemented for DOCX. |
507 | 303 | bool bPowerPoint = dynamic_cast<oox::ppt::PowerPointImport*>(&rFilterBase) != nullptr; |
508 | | |
509 | 303 | if (!officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get() && !bPowerPoint) |
510 | 303 | convertSmartArtToMetafile( rFilterBase ); |
511 | 303 | } |
512 | 303 | } |
513 | | |
514 | 9.10k | NamedShapePairs* pNamedShapePairs = rFilterBase.getDiagramFontHeights(); |
515 | 9.10k | if (xShape.is() && pNamedShapePairs) |
516 | 1.07k | { |
517 | 1.07k | auto itPairs = pNamedShapePairs->find(getInternalName()); |
518 | 1.07k | if (itPairs != pNamedShapePairs->end()) |
519 | 9 | { |
520 | 9 | auto it = itPairs->second.find(shared_from_this()); |
521 | 9 | if (it != itPairs->second.end()) |
522 | 0 | { |
523 | | // Our drawingml::Shape is in the list of an internal name, remember the now |
524 | | // inserted XShape. |
525 | 0 | it->second = std::move(xShape); |
526 | 0 | } |
527 | 9 | } |
528 | 1.07k | } |
529 | 9.10k | } |
530 | 9.10k | } |
531 | 9.10k | catch( const Exception& ) |
532 | 9.10k | { |
533 | 0 | TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" ); |
534 | 0 | } |
535 | 9.10k | } |
536 | | |
537 | | void Shape::setLockedCanvas(bool bLockedCanvas) |
538 | 1.20k | { |
539 | 1.20k | mbLockedCanvas = bLockedCanvas; |
540 | 1.20k | } |
541 | | |
542 | | void Shape::setWordprocessingCanvas(bool bWordprocessingCanvas) |
543 | 1.16k | { |
544 | 1.16k | mbWordprocessingCanvas = bWordprocessingCanvas; |
545 | 1.16k | } |
546 | | |
547 | | void Shape::setWPGChild(bool bWPG) |
548 | 278 | { |
549 | 278 | mbWPGChild = bWPG; |
550 | 278 | } |
551 | | |
552 | | void Shape::setWps(bool bWps) |
553 | 22.8k | { |
554 | 22.8k | mbWps = bWps; |
555 | 22.8k | } |
556 | | |
557 | | void Shape::setTextBox(bool bTextBox) |
558 | 324 | { |
559 | 324 | mbTextBox = bTextBox; |
560 | 324 | } |
561 | | |
562 | | void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText ) |
563 | 22.8k | { |
564 | 22.8k | SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape.msId << "' to '" << msId << "'"); |
565 | | |
566 | 22.8k | if ( rReferencedShape.mpTextBody && bUseText ) |
567 | 22.4k | mpTextBody = std::make_shared<TextBody>( *rReferencedShape.mpTextBody ); |
568 | 464 | else |
569 | 464 | mpTextBody.reset(); |
570 | 22.8k | maShapeProperties = rReferencedShape.maShapeProperties; |
571 | 22.8k | mpShapeRefLinePropPtr = std::make_shared<LineProperties>( rReferencedShape.getActualLineProperties(nullptr) ); |
572 | 22.8k | mpShapeRefFillPropPtr = std::make_shared<FillProperties>( rReferencedShape.getActualFillProperties(nullptr, nullptr) ); |
573 | 22.8k | mpCustomShapePropertiesPtr = std::make_shared<CustomShapeProperties>( *rReferencedShape.mpCustomShapePropertiesPtr ); |
574 | 22.8k | mpTablePropertiesPtr = rReferencedShape.mpTablePropertiesPtr ? std::make_shared<table::TableProperties>( *rReferencedShape.mpTablePropertiesPtr ) : nullptr; |
575 | 22.8k | mpShapeRefEffectPropPtr = std::make_shared<EffectProperties>( rReferencedShape.getActualEffectProperties(nullptr) ); |
576 | 22.8k | mpMasterTextListStyle = std::make_shared<TextListStyle>( *rReferencedShape.mpMasterTextListStyle ); |
577 | 22.8k | setSize(rReferencedShape.maSize); |
578 | 22.8k | setPosition(rReferencedShape.maPosition); |
579 | 22.8k | setRotation(rReferencedShape.getRotation()); |
580 | 22.8k | setFlipH(rReferencedShape.getFlipH()); |
581 | 22.8k | setFlipV(rReferencedShape.getFlipV()); |
582 | 22.8k | setHidden(rReferencedShape.getHidden()); |
583 | 22.8k | setLocked(rReferencedShape.getLocked()); |
584 | 22.8k | } |
585 | | |
586 | | namespace { |
587 | | |
588 | | struct ActionLockGuard |
589 | | { |
590 | | explicit ActionLockGuard(Reference<drawing::XShape> const& xShape) |
591 | 64.0k | : m_xLockable(xShape, UNO_QUERY) |
592 | 64.0k | { |
593 | 64.0k | if (m_xLockable.is()) { |
594 | 64.0k | m_xLockable->addActionLock(); |
595 | 64.0k | } |
596 | 64.0k | } |
597 | | ~ActionLockGuard() |
598 | 64.0k | { |
599 | 64.0k | if (m_xLockable.is()) { |
600 | 64.0k | m_xLockable->removeActionLock(); |
601 | 64.0k | } |
602 | 64.0k | } |
603 | | private: |
604 | | Reference<document::XActionLockable> m_xLockable; |
605 | | }; |
606 | | |
607 | | } |
608 | | |
609 | | // for group shapes, the following method is also adding each child |
610 | | void Shape::addChildren( |
611 | | XmlFilterBase& rFilterBase, |
612 | | Shape& rMaster, |
613 | | const Theme* pTheme, |
614 | | const Reference< XShapes >& rxShapes, |
615 | | ShapeIdMap* pShapeMap, |
616 | | const basegfx::B2DHomMatrix& aTransformation ) |
617 | 639 | { |
618 | 639 | for (auto const& child : rMaster.maChildren) |
619 | 3.75k | { |
620 | 3.75k | child->setMasterTextListStyle( mpMasterTextListStyle ); |
621 | 3.75k | child->addShape( rFilterBase, pTheme, rxShapes, aTransformation, getFillProperties(), pShapeMap, rMaster.shared_from_this()); |
622 | 3.75k | } |
623 | 639 | } |
624 | | |
625 | | static SdrTextHorzAdjust lcl_convertAdjust( ParagraphAdjust eAdjust ) |
626 | 0 | { |
627 | 0 | if (eAdjust == ParagraphAdjust_LEFT) |
628 | 0 | return SDRTEXTHORZADJUST_LEFT; |
629 | 0 | else if (eAdjust == ParagraphAdjust_RIGHT) |
630 | 0 | return SDRTEXTHORZADJUST_RIGHT; |
631 | 0 | else if (eAdjust == ParagraphAdjust_CENTER) |
632 | 0 | return SDRTEXTHORZADJUST_CENTER; |
633 | 0 | return SDRTEXTHORZADJUST_LEFT; |
634 | 0 | } |
635 | | |
636 | | static TextHorizontalAdjust lcl_convertTextAdjust(ParagraphAdjust eAdjust) |
637 | 295 | { |
638 | 295 | if (eAdjust == ParagraphAdjust_LEFT) |
639 | 176 | return drawing::TextHorizontalAdjust_LEFT; |
640 | 119 | else if (eAdjust == ParagraphAdjust_RIGHT) |
641 | 116 | return drawing::TextHorizontalAdjust_RIGHT; |
642 | 3 | else |
643 | 3 | return drawing::TextHorizontalAdjust_BLOCK; |
644 | 295 | } |
645 | | |
646 | | // LO does not interpret properties in styles belonging to the text content of a FontWork shape, |
647 | | // but only those in the shape style. This method copies properties from the text content styles to |
648 | | // the shape style. |
649 | | static void lcl_copyCharPropsToShape(const uno::Reference<drawing::XShape>& xShape, |
650 | | const TextBodyPtr& pTextBody, |
651 | | const ::oox::core::XmlFilterBase& rFilter) |
652 | 0 | { |
653 | 0 | if (!xShape.is() || !pTextBody) |
654 | 0 | return; |
655 | | |
656 | 0 | Reference<XPropertySet> xSet(xShape, UNO_QUERY); |
657 | 0 | if (!xSet.is()) |
658 | 0 | return; |
659 | | |
660 | | // Content stretches or scales to given width and height, thus disable autogrow. |
661 | 0 | xSet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::Any(false)); |
662 | 0 | xSet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::Any(false)); |
663 | | |
664 | | // LibreOffice is not able (as of Nov 2022) to use different styles for the paragraphs or |
665 | | // characters in FontWork, since that was not allowed in old binary WordArt. We use the |
666 | | // properties of the first non empty paragraph for now. |
667 | 0 | const TextParagraphVector& rParagraphs = pTextBody->getParagraphs(); |
668 | 0 | auto aParaIt = std::find_if_not(rParagraphs.cbegin(), rParagraphs.cend(), |
669 | 0 | [](const std::shared_ptr<TextParagraph> pParagraph) { |
670 | 0 | return pParagraph->getRuns().empty(); |
671 | 0 | }); |
672 | 0 | if (aParaIt != rParagraphs.cend()) |
673 | 0 | { |
674 | 0 | const std::shared_ptr<TextParagraph>& pParagraph = *aParaIt; |
675 | 0 | const TextRunVector& rRuns = pParagraph->getRuns(); |
676 | 0 | auto aRunIt = std::find_if_not(rRuns.cbegin(), rRuns.cend(), |
677 | 0 | [](const std::shared_ptr<TextRun> pRun) |
678 | 0 | { |
679 | 0 | return pRun->getText().isEmpty() |
680 | 0 | || pRun->getText() == " " |
681 | 0 | || pRun->getText().toChar() == 0xA0; // NBSP |
682 | 0 | }); |
683 | 0 | if (aRunIt != rRuns.cend()) |
684 | 0 | { |
685 | 0 | const std::shared_ptr<TextRun>& pRun = *aRunIt; |
686 | 0 | TextCharacterProperties& rCharProps = pRun->getTextCharacterProperties(); |
687 | | |
688 | | // set language |
689 | 0 | if (rCharProps.moLang.has_value() && !rCharProps.moLang.value().isEmpty()) |
690 | 0 | { |
691 | 0 | LanguageTag aTag(rCharProps.moLang.value()); |
692 | 0 | const css::lang::Locale& aLocale(aTag.getLocale(false)); |
693 | 0 | switch (MsLangId::getScriptType(aTag.getLanguageType())) |
694 | 0 | { |
695 | 0 | case css::i18n::ScriptType::LATIN: |
696 | 0 | xSet->setPropertyValue(u"CharLocale"_ustr, uno::Any(aLocale)); |
697 | 0 | break; |
698 | 0 | case css::i18n::ScriptType::ASIAN: |
699 | 0 | xSet->setPropertyValue(u"CharLocaleAsian"_ustr, uno::Any(aLocale)); |
700 | 0 | break; |
701 | 0 | case css::i18n::ScriptType::COMPLEX: |
702 | 0 | xSet->setPropertyValue(u"CharLocaleComplex"_ustr, uno::Any(aLocale)); |
703 | 0 | break; |
704 | 0 | default:; |
705 | 0 | } |
706 | 0 | } |
707 | | |
708 | | // Font Weight, Posture, Height |
709 | 0 | if (rCharProps.moBold.has_value() && rCharProps.moBold.value()) |
710 | 0 | { |
711 | 0 | xSet->setPropertyValue(UNO_NAME_CHAR_WEIGHT, uno::Any(css::awt::FontWeight::BOLD)); |
712 | 0 | } |
713 | 0 | if (rCharProps.moItalic.has_value() && rCharProps.moItalic.value()) |
714 | 0 | { |
715 | 0 | xSet->setPropertyValue(UNO_NAME_CHAR_POSTURE, |
716 | 0 | uno::Any(css::awt::FontSlant::FontSlant_ITALIC)); |
717 | 0 | } |
718 | 0 | if (rCharProps.moHeight.has_value()) |
719 | 0 | { |
720 | 0 | sal_Int32 nHeight = rCharProps.moHeight.value() / 100; |
721 | 0 | xSet->setPropertyValue(UNO_NAME_CHAR_HEIGHT, uno::Any(nHeight)); |
722 | 0 | } |
723 | | |
724 | | // Put theme fonts into shape properties |
725 | 0 | OUString sFontName; |
726 | 0 | sal_Int16 nFontPitch = 0; |
727 | 0 | sal_Int16 nFontFamily = 0; |
728 | 0 | bool bRet(false); |
729 | 0 | if (const Theme* pTheme = rFilter.getCurrentTheme()) |
730 | 0 | { |
731 | | // minor Latin |
732 | 0 | if (const TextFont* pFont = pTheme->resolveFont(u"+mn-lt")) |
733 | 0 | { |
734 | 0 | bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
735 | 0 | if (bRet) |
736 | 0 | { |
737 | 0 | xSet->setPropertyValue(u"CharFontName"_ustr, uno::Any(sFontName)); |
738 | 0 | xSet->setPropertyValue(u"CharFontPitch"_ustr, uno::Any(nFontPitch)); |
739 | 0 | xSet->setPropertyValue(u"CharFontFamily"_ustr, uno::Any(nFontFamily)); |
740 | 0 | } |
741 | 0 | } |
742 | | // minor Asian |
743 | 0 | if (const TextFont* pFont = pTheme->resolveFont(u"+mn-ea")) |
744 | 0 | { |
745 | 0 | bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
746 | 0 | if (bRet) |
747 | 0 | { |
748 | 0 | xSet->setPropertyValue(u"CharFontNameAsian"_ustr, uno::Any(sFontName)); |
749 | 0 | xSet->setPropertyValue(u"CharFontPitchAsian"_ustr, uno::Any(nFontPitch)); |
750 | 0 | xSet->setPropertyValue(u"CharFontFamilyAsian"_ustr, uno::Any(nFontFamily)); |
751 | 0 | } |
752 | 0 | } |
753 | | // minor Complex |
754 | 0 | if (const TextFont* pFont = pTheme->resolveFont(u"+mn-cs")) |
755 | 0 | { |
756 | 0 | bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
757 | 0 | if (bRet) |
758 | 0 | { |
759 | 0 | xSet->setPropertyValue(u"CharFontNameComplex"_ustr, uno::Any(sFontName)); |
760 | 0 | xSet->setPropertyValue(u"CharFontPitchComplex"_ustr, uno::Any(nFontPitch)); |
761 | 0 | xSet->setPropertyValue(u"CharFontFamilyComplex"_ustr, uno::Any(nFontFamily)); |
762 | 0 | } |
763 | 0 | } |
764 | 0 | } |
765 | | |
766 | | // Replace theme fonts with formatting at run if any. ToDo: Inspect paragraph too? |
767 | | // Latin |
768 | 0 | bRet = rCharProps.maLatinFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
769 | 0 | if (!bRet) |
770 | | // In case there is no direct font, try to look it up as a theme reference. |
771 | 0 | bRet = rCharProps.maLatinThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, |
772 | 0 | rFilter); |
773 | |
|
774 | 0 | if (bRet) |
775 | 0 | { |
776 | 0 | xSet->setPropertyValue(u"CharFontName"_ustr, uno::Any(sFontName)); |
777 | 0 | xSet->setPropertyValue(u"CharFontPitch"_ustr, uno::Any(nFontPitch)); |
778 | 0 | xSet->setPropertyValue(u"CharFontFamily"_ustr, uno::Any(nFontFamily)); |
779 | 0 | } |
780 | | // Asian |
781 | 0 | bRet = rCharProps.maAsianFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
782 | 0 | if (!bRet) |
783 | | // In case there is no direct font, try to look it up as a theme reference. |
784 | 0 | bRet = rCharProps.maAsianThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, |
785 | 0 | rFilter); |
786 | 0 | if (bRet) |
787 | 0 | { |
788 | 0 | xSet->setPropertyValue(u"CharFontNameAsian"_ustr, uno::Any(sFontName)); |
789 | 0 | xSet->setPropertyValue(u"CharFontPitchAsian"_ustr, uno::Any(nFontPitch)); |
790 | 0 | xSet->setPropertyValue(u"CharFontFamilyAsian"_ustr, uno::Any(nFontFamily)); |
791 | 0 | } |
792 | | // Complex |
793 | 0 | bRet |
794 | 0 | = rCharProps.maComplexFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter); |
795 | 0 | if (!bRet) |
796 | | // In case there is no direct font, try to look it up as a theme reference. |
797 | 0 | bRet = rCharProps.maComplexThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, |
798 | 0 | rFilter); |
799 | 0 | if (bRet) |
800 | 0 | { |
801 | 0 | xSet->setPropertyValue(u"CharFontNameComplex"_ustr, uno::Any(sFontName)); |
802 | 0 | xSet->setPropertyValue(u"CharFontPitchComplex"_ustr, uno::Any(nFontPitch)); |
803 | 0 | xSet->setPropertyValue(u"CharFontFamilyComplex"_ustr, uno::Any(nFontFamily)); |
804 | 0 | } |
805 | | |
806 | | // LO uses shape properties, MS Office character properties. Copy them from char to shape. |
807 | | // Outline |
808 | 0 | if (rCharProps.moTextOutlineProperties.has_value()) |
809 | 0 | { |
810 | 0 | oox::drawingml::ShapePropertyMap aStrokeShapeProps(rFilter.getModelObjectHelper()); |
811 | 0 | rCharProps.moTextOutlineProperties.value().pushToPropMap( |
812 | 0 | aStrokeShapeProps, rFilter.getGraphicHelper()); |
813 | 0 | for (const auto& rProp : aStrokeShapeProps.makePropertyValueSequence()) |
814 | 0 | { |
815 | 0 | xSet->setPropertyValue(rProp.Name, rProp.Value); |
816 | 0 | } |
817 | 0 | } |
818 | 0 | else |
819 | 0 | { |
820 | 0 | xSet->setPropertyValue(UNO_NAME_LINESTYLE, uno::Any(drawing::LineStyle_NONE)); |
821 | 0 | } |
822 | | |
823 | | // Fill |
824 | | // ToDo: Replace flip and rotate constants in parameters with actual values. |
825 | | // tdf#155327 If color is not explicitly set, MS Office uses scheme color 'tx1'. |
826 | 0 | oox::drawingml::ShapePropertyMap aFillShapeProps(rFilter.getModelObjectHelper()); |
827 | 0 | if (!rCharProps.maFillProperties.moFillType.has_value()) |
828 | 0 | rCharProps.maFillProperties.moFillType = XML_solidFill; |
829 | 0 | if (!rCharProps.maFillProperties.maFillColor.isUsed()) |
830 | 0 | rCharProps.maFillProperties.maFillColor.setSchemeClr(XML_tx1); |
831 | 0 | rCharProps.maFillProperties.pushToPropMap(aFillShapeProps, rFilter.getGraphicHelper(), |
832 | 0 | /*nShapeRotation*/ 0, |
833 | 0 | /*nPhClr*/ API_RGB_TRANSPARENT, |
834 | 0 | /*aShapeSize*/ css::awt::Size(0, 0), |
835 | 0 | /*nPhClrTheme*/ -1, |
836 | 0 | /*bFlipH*/ false, /*bFlipV*/ false, |
837 | 0 | /*bIsCustomShape*/ true); |
838 | 0 | for (const auto& rProp : aFillShapeProps.makePropertyValueSequence()) |
839 | 0 | { |
840 | 0 | xSet->setPropertyValue(rProp.Name, rProp.Value); |
841 | 0 | } |
842 | | |
843 | | // ToDo: Import WordArt glow and simple shadow effects. They are available in LO. |
844 | 0 | } |
845 | | |
846 | | // LO does not evaluate paragraph alignment in text path mode. Use text area anchor instead. |
847 | 0 | { |
848 | 0 | ParagraphAdjust eAdjust = ParagraphAdjust_LEFT; |
849 | 0 | if (pParagraph->getProperties().getParaAdjust()) |
850 | 0 | eAdjust = *pParagraph->getProperties().getParaAdjust(); |
851 | 0 | xSet->setPropertyValue(u"ParaAdjust"_ustr, uno::Any(eAdjust)); |
852 | 0 | SdrObject* pShape = SdrObject::getSdrObjectFromXShape(xShape); |
853 | 0 | assert(pShape); |
854 | 0 | SdrTextHorzAdjust eHorzAdjust = lcl_convertAdjust(eAdjust); |
855 | 0 | pShape->SetMergedItem(SdrTextHorzAdjustItem(eHorzAdjust)); |
856 | 0 | } |
857 | 0 | } |
858 | | |
859 | | // Vertical adjustment is only meaningful for OOXML WordArt shapes of 'Follow Path' kinds. We set |
860 | | // it so, that text position is approximately same as in MS Office. |
861 | 0 | const OUString sMSPresetType = pTextBody->getTextProperties().msPrst; |
862 | 0 | const OUString sFontworkType = PresetGeometryTypeNames::GetFontworkType(sMSPresetType); |
863 | 0 | SdrObject* pShape = SdrObject::getSdrObjectFromXShape(xShape); |
864 | 0 | assert(pShape); |
865 | 0 | if (sFontworkType == "fontwork-arch-up-curve" || sFontworkType == "fontwork-circle-curve") |
866 | 0 | pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM)); |
867 | 0 | else if (sFontworkType == "fontwork-arch-down-curve") |
868 | 0 | pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP)); |
869 | 0 | else |
870 | 0 | pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_CENTER)); |
871 | 0 | } |
872 | | |
873 | | // Some helper methods for createAndInsert |
874 | | namespace |
875 | | { |
876 | | // mirrors aTransformation at its center axis |
877 | | // only valid if neither rotation or shear included |
878 | | void lcl_mirrorAtCenter(basegfx::B2DHomMatrix& aTransformation, bool bFlipH, bool bFlipV) |
879 | 3.15k | { |
880 | 3.15k | if (!bFlipH && !bFlipV) |
881 | 2.31k | return; |
882 | 844 | basegfx::B2DPoint aCenter(0.5, 0.5); |
883 | 844 | aCenter *= aTransformation; |
884 | 844 | aTransformation.translate(-aCenter); |
885 | 844 | aTransformation.scale(bFlipH ? -1.0 : 1.0, bFlipV ? -1.0 : 1.0); |
886 | 844 | aTransformation.translate(aCenter); |
887 | 844 | return; |
888 | 3.15k | } |
889 | | |
890 | | // only valid if neither rotation or shear included |
891 | | void lcl_doSpecialMSOWidthHeightToggle(basegfx::B2DHomMatrix& aTransformation) |
892 | 0 | { |
893 | | // The values are directly set at the matrix without any matrix multiplication. |
894 | | // That way it is valid for lines too. Those have zero width or height. |
895 | 0 | const double fSx(aTransformation.get(0, 0)); |
896 | 0 | const double fSy(aTransformation.get(1, 1)); |
897 | 0 | const double fTx(aTransformation.get(0, 2)); |
898 | 0 | const double fTy(aTransformation.get(1, 2)); |
899 | 0 | aTransformation.set(0, 0, fSy); |
900 | 0 | aTransformation.set(1, 1, fSx); |
901 | 0 | aTransformation.set(0, 2, fTx + 0.5 * (fSx - fSy)); |
902 | 0 | aTransformation.set(1, 2, fTy + 0.5 * (fSy - fSx)); |
903 | 0 | return; |
904 | 0 | } |
905 | | |
906 | | void lcl_RotateAtCenter(basegfx::B2DHomMatrix& aTransformation, sal_Int32 nMSORotationAngle) |
907 | 2.09k | { |
908 | 2.09k | if (nMSORotationAngle == 0) |
909 | 0 | return; |
910 | 2.09k | double fRad = basegfx::deg2rad<60000>(nMSORotationAngle); |
911 | 2.09k | basegfx::B2DPoint aCenter(0.5, 0.5); |
912 | 2.09k | aCenter *= aTransformation; |
913 | 2.09k | aTransformation.translate(-aCenter); |
914 | 2.09k | aTransformation.rotate(fRad); |
915 | 2.09k | aTransformation.translate(aCenter); |
916 | 2.09k | return; |
917 | 2.09k | } |
918 | | |
919 | | Degree100 lcl_MSORotateAngleToAPIAngle(const sal_Int32 nMSORotationAngle) |
920 | 2.26k | { |
921 | | // Converts a shape rotation angle from MSO to angle for API property RotateAngle |
922 | | // from unit 1/60000 deg to unit 1/100 deg |
923 | 2.26k | Degree100 nAngle(nMSORotationAngle / 600); |
924 | | // API RotateAngle has opposite direction than nMSORotationAngle, thus 'minus'. |
925 | 2.26k | return NormAngle36000(-nAngle); |
926 | 2.26k | } |
927 | | |
928 | | void PushMasterTextListStyleToMasterShapeParagraphs(TextListStyle& rMasterTextListStyle, const uno::Reference<drawing::XShape>& xShape) |
929 | 4.97k | { |
930 | 4.97k | uno::Reference<text::XTextRange> xShapeText(xShape, UNO_QUERY); |
931 | 4.97k | if (!xShapeText.is()) |
932 | 0 | { |
933 | 0 | return; |
934 | 0 | } |
935 | | |
936 | 4.97k | uno::Reference<container::XEnumerationAccess> xText(xShapeText->getText(), uno::UNO_QUERY); |
937 | 4.97k | if (!xText.is()) |
938 | 0 | { |
939 | 0 | return; |
940 | 0 | } |
941 | | |
942 | 4.97k | uno::Reference<container::XEnumeration> xParagraphs = xText->createEnumeration(); |
943 | 4.97k | if (!xParagraphs.is()) |
944 | 0 | { |
945 | 0 | return; |
946 | 0 | } |
947 | | |
948 | 39.4k | while (xParagraphs->hasMoreElements()) |
949 | 34.4k | { |
950 | 34.4k | uno::Reference<beans::XPropertySet> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY); |
951 | 34.4k | if (!xParagraph.is()) |
952 | 0 | { |
953 | 0 | continue; |
954 | 0 | } |
955 | | |
956 | 34.4k | uno::Reference<container::XIndexReplace> xNumberingRules; |
957 | 34.4k | if (!(xParagraph->getPropertyValue("NumberingRules") >>= xNumberingRules)) |
958 | 0 | { |
959 | 0 | continue; |
960 | 0 | } |
961 | | |
962 | 34.4k | rMasterTextListStyle.pushToNumberingRules(xNumberingRules, std::nullopt); |
963 | 34.4k | xParagraph->setPropertyValue("NumberingRules", uno::Any(xNumberingRules)); |
964 | 34.4k | } |
965 | 4.97k | } |
966 | | } |
967 | | |
968 | | Reference< XShape > const & Shape::createAndInsert( |
969 | | ::oox::core::XmlFilterBase& rFilterBase, |
970 | | const OUString& rServiceName, |
971 | | const Theme* pTheme, |
972 | | const css::uno::Reference< css::drawing::XShapes >& rxShapes, |
973 | | bool bClearText, |
974 | | const oox::drawingml::ShapePtr& pPlaceholder, |
975 | | basegfx::B2DHomMatrix& aParentTransformation, |
976 | | const FillProperties& rShapeOrParentShapeFillProps, |
977 | | const oox::drawingml::ShapePtr& pParentGroupShape) |
978 | 64.0k | { |
979 | 64.0k | bool bIsEmbMedia = false; |
980 | 64.0k | SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId << "' service='" << rServiceName << "'"); |
981 | | |
982 | 64.0k | formulaimport::XmlStreamBuilder * pMathXml(nullptr); |
983 | 64.0k | if (mpTextBody) |
984 | 49.2k | { |
985 | 49.2k | for (auto const& it : mpTextBody->getParagraphs()) |
986 | 66.1k | { |
987 | 66.1k | if (it->HasMathXml()) |
988 | 0 | { |
989 | 0 | if (!mpTextBody->isEmpty() || pMathXml != nullptr) |
990 | 0 | { |
991 | 0 | SAL_WARN("oox.drawingml", "losing a Math object..."); |
992 | 0 | } |
993 | 0 | else |
994 | 0 | { |
995 | 0 | pMathXml = &it->GetMathXml(); |
996 | 0 | } |
997 | 0 | } |
998 | 66.1k | } |
999 | 49.2k | } |
1000 | | |
1001 | | // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height |
1002 | 64.0k | if ( mpTablePropertiesPtr && rServiceName == "com.sun.star.drawing.TableShape" ) |
1003 | 124 | { |
1004 | 124 | maSize.Width = 0; |
1005 | 124 | for (auto const& elem : mpTablePropertiesPtr->getTableGrid()) |
1006 | 576 | { |
1007 | 576 | maSize.Width = o3tl::saturating_add(maSize.Width, static_cast<sal_Int32>(elem)); |
1008 | 576 | } |
1009 | 124 | maSize.Height = 0; |
1010 | 124 | for (auto const& elem : mpTablePropertiesPtr->getTableRows()) |
1011 | 597 | { |
1012 | | // WARN: If some rows can't fit the content, this is not the final height |
1013 | 597 | maSize.Height = o3tl::saturating_add(maSize.Height, elem.getHeight()); |
1014 | 597 | } |
1015 | 124 | } |
1016 | | |
1017 | 64.0k | awt::Rectangle aShapeRectHmm( |
1018 | 64.0k | o3tl::convert(maPosition.X, o3tl::Length::emu, o3tl::Length::mm100), |
1019 | 64.0k | o3tl::convert(maPosition.Y, o3tl::Length::emu, o3tl::Length::mm100), |
1020 | 64.0k | o3tl::convert(maSize.Width, o3tl::Length::emu, o3tl::Length::mm100), |
1021 | 64.0k | o3tl::convert(maSize.Height, o3tl::Length::emu, o3tl::Length::mm100)); |
1022 | | |
1023 | 64.0k | OUString aServiceName; |
1024 | 64.0k | if (pMathXml) |
1025 | 0 | { |
1026 | | // convert this shape to OLE |
1027 | 0 | aServiceName = u"com.sun.star.drawing.OLE2Shape"_ustr; |
1028 | 0 | msServiceName = aServiceName; |
1029 | 0 | meFrameType = FRAMETYPE_GENERIC; // not OLEOBJECT, no stream in package |
1030 | 0 | mnSubType = 0; |
1031 | 0 | } |
1032 | 64.0k | else if (rServiceName == "com.sun.star.drawing.GraphicObjectShape" && |
1033 | 3.44k | mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty()) |
1034 | 0 | { |
1035 | 0 | aServiceName = finalizeServiceName( rFilterBase, u"com.sun.star.presentation.MediaShape"_ustr, aShapeRectHmm ); |
1036 | 0 | bIsEmbMedia = true; |
1037 | 0 | } |
1038 | 64.0k | else |
1039 | 64.0k | { |
1040 | 64.0k | aServiceName = finalizeServiceName( rFilterBase, rServiceName, aShapeRectHmm ); |
1041 | 64.0k | } |
1042 | | // Use custom shape instead of GraphicObjectShape if the image is cropped to |
1043 | | // shape. Except rectangle, which does not require further cropping |
1044 | 64.0k | bool bIsCroppedGraphic = (aServiceName == "com.sun.star.drawing.GraphicObjectShape" && |
1045 | 3.44k | !mpCustomShapePropertiesPtr->representsDefaultShape()); |
1046 | | |
1047 | 64.0k | bool bIsCustomShape = (aServiceName == "com.sun.star.drawing.CustomShape" || bIsCroppedGraphic); |
1048 | 64.0k | bool bIsConnectorShape = (aServiceName == "com.sun.star.drawing.ConnectorShape"); |
1049 | | |
1050 | | // Look for 3D. Its z-rotation and extrusion color become shape properties. We consider a |
1051 | | // z-rotation of an image even we currently do not extrude an image to 3D-scene. |
1052 | 64.0k | bool bBlockExtrusion = !bIsCustomShape && mp3DPropertiesPtr->mnPreset.has_value(); |
1053 | 64.0k | double fShapeRotateInclCamera = 0.0; // unit rad; same orientation as shape property RotateAngle |
1054 | 64.0k | Color aExtrusionColor; |
1055 | 64.0k | Scene3DHelper aScene3DHelper; |
1056 | 64.0k | bool bHas3DEffect = aScene3DHelper.setExtrusionProperties( |
1057 | 64.0k | mp3DPropertiesPtr, getRotation(), getCustomShapeProperties()->getExtrusionPropertyMap(), |
1058 | 64.0k | fShapeRotateInclCamera, aExtrusionColor, bBlockExtrusion); |
1059 | | // Currently the other places use unit 1/60000deg and MSO shape rotate orientation. |
1060 | 64.0k | sal_Int32 nShapeRotateInclCamera = -basegfx::rad2deg<60000>(fShapeRotateInclCamera); |
1061 | 64.0k | bool bIs3DGraphic = aServiceName == "com.sun.star.drawing.GraphicObjectShape" && bHas3DEffect; |
1062 | 64.0k | bIsCustomShape |= bIs3DGraphic; |
1063 | | |
1064 | | // The extrusion color does not belong to the extrusion properties but is secondary color in |
1065 | | // the style of the shape, FillColor2 in API. The case that no extrusion color was set is handled |
1066 | | // further down when FillProperties and LineProperties are handled. |
1067 | 64.0k | if (aExtrusionColor.isUsed()) |
1068 | 3 | { |
1069 | | // FillColor2 is not yet transformed to ComplexColor. |
1070 | 3 | ::Color aColor = aExtrusionColor.getColor(rFilterBase.getGraphicHelper()); |
1071 | 3 | maShapeProperties.setProperty(PROP_FillColor2, aColor); |
1072 | 3 | } |
1073 | | |
1074 | 64.0k | if (bHas3DEffect) |
1075 | 3 | { |
1076 | 3 | aScene3DHelper.setLightingProperties(mp3DPropertiesPtr, fShapeRotateInclCamera, |
1077 | 3 | getCustomShapeProperties()->getExtrusionPropertyMap()); |
1078 | 3 | oox::Scene3DHelper::setMaterialProperties( |
1079 | 3 | mp3DPropertiesPtr, getCustomShapeProperties()->getExtrusionPropertyMap()); |
1080 | 3 | } |
1081 | | |
1082 | 64.0k | if (bIsCroppedGraphic || bIs3DGraphic) |
1083 | 0 | { |
1084 | 0 | aServiceName = "com.sun.star.drawing.CustomShape"; |
1085 | 0 | mpGraphicPropertiesPtr->mbIsCustomShape = true; |
1086 | 0 | mpGraphicPropertiesPtr->mbIsExtruded = bIs3DGraphic; |
1087 | 0 | } |
1088 | 64.0k | bool bUseRotationTransform = !getWps() || |
1089 | 1.14k | aServiceName == "com.sun.star.drawing.LineShape" || |
1090 | 1.00k | aServiceName == "com.sun.star.drawing.GroupShape" || |
1091 | 869 | getFlipH() || |
1092 | 869 | getFlipV(); |
1093 | | |
1094 | 64.0k | basegfx::B2DHomMatrix aTransformation; // will be cumulative transformation of this object |
1095 | | |
1096 | | // Special for SmartArt import. Rotate diagram's shape around object's center before sizing. |
1097 | 64.0k | if (bUseRotationTransform && getDiagramRotation() != 0) |
1098 | 0 | { |
1099 | 0 | aTransformation.translate(-0.5, -0.5); |
1100 | 0 | aTransformation.rotate(basegfx::deg2rad<60000>(getDiagramRotation())); |
1101 | 0 | aTransformation.translate(0.5, 0.5); |
1102 | 0 | } |
1103 | | |
1104 | 64.0k | bool bLineShape = aServiceName == "com.sun.star.drawing.LineShape"; |
1105 | 64.0k | bool bTopWriterLine = !pParentGroupShape && getWps() && bLineShape; |
1106 | | // Build object matrix from shape size and position; corresponds to MSO ext and off |
1107 | | // Only LineShape and ConnectorShape may have zero width or height. |
1108 | 64.0k | if (bLineShape || aServiceName == "com.sun.star.drawing.ConnectorShape") |
1109 | 1.75k | { |
1110 | | // For toplevel Writer lines, size is included in the point coordinates. |
1111 | 1.75k | if (!bTopWriterLine) |
1112 | 1.75k | { |
1113 | 1.75k | aTransformation.scale(maSize.Width, maSize.Height); |
1114 | 1.75k | } |
1115 | 1.75k | } |
1116 | 62.3k | else |
1117 | 62.3k | { |
1118 | 62.3k | aTransformation.scale(maSize.Width ? maSize.Width : 1.0, |
1119 | 62.3k | maSize.Height ? maSize.Height : 1.0); |
1120 | 62.3k | } |
1121 | | |
1122 | | // Evaluate object flip. Other shapes than custom shapes have no attribute for flip but use |
1123 | | // negative scale. Flip in MSO is at object center. |
1124 | 64.0k | if (!bIsCustomShape && (getFlipH() || getFlipV())) |
1125 | 844 | lcl_mirrorAtCenter(aTransformation, getFlipH(), getFlipV()); |
1126 | | |
1127 | | // Evaluate parent flip. |
1128 | | // A CustomShape has mirror not as negative scale, but as attributes. |
1129 | 64.0k | basegfx::B2DVector aParentScale(1.0, 1.0); |
1130 | 64.0k | basegfx::B2DVector aParentTranslate(0.0, 0.0); |
1131 | 64.0k | double fParentRotate(0.0); |
1132 | 64.0k | double fParentShearX(0.0); |
1133 | 64.0k | if (pParentGroupShape) |
1134 | 3.75k | { |
1135 | 3.75k | aParentTransformation.decompose(aParentScale, aParentTranslate, fParentRotate, fParentShearX); |
1136 | 3.75k | if (bIsCustomShape) |
1137 | 2.31k | { |
1138 | 2.31k | lcl_mirrorAtCenter(aTransformation, aParentScale.getX() < 0, aParentScale.getY() < 0); |
1139 | 2.31k | if (aParentScale.getX() < 0) |
1140 | 0 | setFlipH(!getFlipH()); |
1141 | 2.31k | if (aParentScale.getY() < 0) |
1142 | 0 | setFlipV(!getFlipV()); |
1143 | 2.31k | } |
1144 | 3.75k | } |
1145 | | |
1146 | 64.0k | if (maPosition.X != 0 || maPosition.Y != 0) |
1147 | 54.7k | { |
1148 | | // if global position is used, add it to transformation |
1149 | 54.7k | if (getWps() && pParentGroupShape == nullptr) |
1150 | 636 | aTransformation.translate( |
1151 | 636 | o3tl::convert(maPosition.X, o3tl::Length::mm100, o3tl::Length::emu), |
1152 | 636 | o3tl::convert(maPosition.Y, o3tl::Length::mm100, o3tl::Length::emu)); |
1153 | 54.1k | else |
1154 | 54.1k | aTransformation.translate(maPosition.X, maPosition.Y); |
1155 | 54.7k | } |
1156 | | |
1157 | | // Apply further parent transformations. First scale object then rotate. Other way round would |
1158 | | // introduce shearing. |
1159 | | |
1160 | | // The attributes chExt and chOff of the group in oox file contain the values on which the size |
1161 | | // and position of the child is based on. If they differ from the actual size of the group as |
1162 | | // given in its ext and off attributes, the child has to be transformed according the new values. |
1163 | 64.0k | if (pParentGroupShape) |
1164 | 3.75k | { |
1165 | | // ToDo: A diagram in a group might need special handling because it cannot flip and only |
1166 | | // resize uniformly. But currently it is imported with zero size, see tdf#139575. That needs |
1167 | | // to be fixed beforehand. |
1168 | | |
1169 | | // Scaling is done from left/top edges of the group. So these need to become coordinate axes. |
1170 | 3.75k | aTransformation.translate(-pParentGroupShape->maChPosition.X, |
1171 | 3.75k | -pParentGroupShape->maChPosition.Y); |
1172 | | |
1173 | | // oox allows zero or missing attribute chExt. In that case the scaling factor is 1. |
1174 | | // Transform2DContext::onCreateContext has set maChSize to maSize for groups in oox file in |
1175 | | // such cases. For own made groups (e.g. diagrams) that is missing. |
1176 | | // The factors cumulate on the way through the parent groups, so we do not use maSize of the |
1177 | | // direct parent group but the cumulated value from aParentScale. |
1178 | 3.75k | double fFactorX = 1.0; |
1179 | 3.75k | double fFactorY = 1.0; |
1180 | 3.75k | if (pParentGroupShape->maChSize.Width != 0) |
1181 | 2.56k | fFactorX = aParentScale.getX() / pParentGroupShape->maChSize.Width; |
1182 | 3.75k | if (pParentGroupShape->maChSize.Height != 0) |
1183 | 2.56k | fFactorY = aParentScale.getY() / pParentGroupShape->maChSize.Height; |
1184 | 3.75k | if (fFactorX != 1 || fFactorY != 1) |
1185 | 89 | { |
1186 | | // It depends on the object rotation angle whether scaling is applied to switched |
1187 | | // width and height. MSO acts strange in that case (as of May 2021). |
1188 | 89 | const sal_Int32 nDeg(getRotation() / 60000); |
1189 | 89 | const bool bNeedsMSOWidthHeightToggle |
1190 | 89 | = (nDeg >= 45 && nDeg < 135) || (nDeg >= 225 && nDeg < 315); |
1191 | 89 | if (bNeedsMSOWidthHeightToggle) |
1192 | 0 | lcl_doSpecialMSOWidthHeightToggle(aTransformation); |
1193 | | |
1194 | 89 | aTransformation.scale(fFactorX, fFactorY); |
1195 | | |
1196 | 89 | if (bNeedsMSOWidthHeightToggle) |
1197 | 0 | { |
1198 | 0 | lcl_doSpecialMSOWidthHeightToggle(aTransformation); |
1199 | | // In case of flip the special case needs an additional 180deg rotation. |
1200 | 0 | if ((aParentScale.getX() < 0) != (aParentScale.getY() < 0)) |
1201 | 0 | lcl_RotateAtCenter(aTransformation, 10800000); |
1202 | 0 | } |
1203 | 89 | } |
1204 | 3.75k | } |
1205 | | |
1206 | | // Apply object rotation at current object center |
1207 | | // The flip contained in aParentScale will affect orientation of object rotation angle. |
1208 | 64.0k | sal_Int16 nOrientation = ((aParentScale.getX() < 0) != (aParentScale.getY() < 0)) ? -1 : 1; |
1209 | | // ToDo: Not sure about the restrictions given by bUseRotationTransform. |
1210 | 64.0k | if (bUseRotationTransform && nShapeRotateInclCamera != 0) |
1211 | 2.09k | { |
1212 | 2.09k | lcl_RotateAtCenter(aTransformation, nOrientation * nShapeRotateInclCamera); |
1213 | 2.09k | } |
1214 | | |
1215 | 64.0k | if (fParentRotate != 0.0) |
1216 | 278 | aTransformation.rotate(fParentRotate); |
1217 | 64.0k | if (!aParentTranslate.equalZero()) |
1218 | 1.23k | aTransformation.translate(aParentTranslate); |
1219 | | |
1220 | 64.0k | aParentTransformation = aTransformation; |
1221 | | |
1222 | 64.0k | constexpr double fEmuToMm100 = o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::mm100); |
1223 | 64.0k | if (!bTopWriterLine) |
1224 | 64.0k | { |
1225 | 64.0k | aTransformation.scale(fEmuToMm100, fEmuToMm100); |
1226 | 64.0k | } |
1227 | | |
1228 | | // OOXML flips shapes before rotating them, so the rotation needs to be inverted |
1229 | 64.0k | if (bIsCustomShape && getFlipH() != getFlipV()) |
1230 | 32 | { |
1231 | 32 | basegfx::B2DVector aScale, aTranslate; |
1232 | 32 | double fRotate, fShearX; |
1233 | 32 | aTransformation.decompose(aScale, aTranslate, fRotate, fShearX); |
1234 | | |
1235 | 32 | if(fRotate != 0) |
1236 | 28 | { |
1237 | 28 | basegfx::B2DPoint aCenter(0.5, 0.5); |
1238 | 28 | aCenter *= aTransformation; |
1239 | 28 | aTransformation.translate( -aCenter.getX(), -aCenter.getY() ); |
1240 | 28 | aTransformation.rotate( fRotate * -2.0 ); |
1241 | 28 | aTransformation.translate( aCenter.getX(), aCenter.getY() ); |
1242 | 28 | } |
1243 | 32 | } |
1244 | | |
1245 | | // special for lineshape |
1246 | 64.0k | uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 ); |
1247 | 64.0k | if (bLineShape) |
1248 | 179 | { |
1249 | 179 | ::basegfx::B2DPolygon aPoly; |
1250 | 179 | aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); |
1251 | 179 | if (bTopWriterLine) |
1252 | 0 | { |
1253 | | // No transform of individual points, everything apart from size is part of the |
1254 | | // transform matrix. |
1255 | 0 | sal_Int32 nMM100Width = o3tl::convert(maSize.Width, o3tl::Length::emu, o3tl::Length::mm100); |
1256 | 0 | sal_Int32 nMM100Height = o3tl::convert(maSize.Height, o3tl::Length::emu, o3tl::Length::mm100); |
1257 | 0 | aPoly.insert(1, ::basegfx::B2DPoint(nMM100Width, nMM100Height)); |
1258 | 0 | } |
1259 | 179 | else |
1260 | 179 | { |
1261 | 179 | aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); |
1262 | 179 | aPoly.transform( aTransformation ); |
1263 | 179 | } |
1264 | | |
1265 | | // now creating the corresponding PolyPolygon |
1266 | 179 | sal_Int32 i, nNumPoints = aPoly.count(); |
1267 | 179 | uno::Sequence< awt::Point > aPointSequence( nNumPoints ); |
1268 | 179 | awt::Point* pPoints = aPointSequence.getArray(); |
1269 | 537 | for( i = 0; i < nNumPoints; ++i ) |
1270 | 358 | { |
1271 | 358 | basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) ); |
1272 | | |
1273 | | // Guard against zero width or height. |
1274 | 358 | if (i) |
1275 | 179 | { |
1276 | 179 | const basegfx::B2DPoint& rPreviousPoint = aPoly.getB2DPoint(i - 1); |
1277 | 179 | if (aPoint.getX() - rPreviousPoint.getX() == 0) |
1278 | 0 | aPoint.setX(aPoint.getX() + 1); |
1279 | 179 | if (aPoint.getY() - rPreviousPoint.getY() == 0) |
1280 | 21 | aPoint.setY(aPoint.getY() + 1); |
1281 | 179 | } |
1282 | | |
1283 | 358 | pPoints[i] = awt::Point(static_cast<sal_Int32>(aPoint.getX()), static_cast<sal_Int32>(aPoint.getY())); |
1284 | 358 | } |
1285 | 179 | aPolyPolySequence.getArray()[ 0 ] = std::move(aPointSequence); |
1286 | | |
1287 | 179 | if (!(bTopWriterLine && !maSize.Width)) |
1288 | 179 | { |
1289 | 179 | maShapeProperties.setProperty(PROP_PolyPolygon, aPolyPolySequence); |
1290 | 179 | } |
1291 | 179 | } |
1292 | 64.0k | HomogenMatrix3 aMatrix; |
1293 | 64.0k | tools::Rectangle aOrigSize; |
1294 | 64.0k | if ( aServiceName == "com.sun.star.drawing.ConnectorShape" ) |
1295 | 1.57k | { |
1296 | 1.57k | ::basegfx::B2DPolygon aPoly; |
1297 | 1.57k | aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); |
1298 | 1.57k | aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); |
1299 | 1.57k | aPoly.transform( aTransformation ); |
1300 | | |
1301 | 1.57k | basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) ); |
1302 | 1.57k | basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) ); |
1303 | 1.57k | awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) ); |
1304 | 1.57k | awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) ); |
1305 | | |
1306 | 1.57k | maShapeProperties.setProperty(PROP_StartPosition, aAWTStartPosition); |
1307 | 1.57k | maShapeProperties.setProperty(PROP_EndPosition, aAWTEndPosition); |
1308 | 1.57k | } |
1309 | 62.5k | else if (!bLineShape || bTopWriterLine) |
1310 | 62.3k | { |
1311 | | // now set transformation for this object |
1312 | | |
1313 | 62.3k | aMatrix.Line1.Column1 = aTransformation.get(0,0); |
1314 | 62.3k | aMatrix.Line1.Column2 = aTransformation.get(0,1); |
1315 | 62.3k | aMatrix.Line1.Column3 = aTransformation.get(0,2); |
1316 | | |
1317 | 62.3k | aMatrix.Line2.Column1 = aTransformation.get(1,0); |
1318 | 62.3k | aMatrix.Line2.Column2 = aTransformation.get(1,1); |
1319 | 62.3k | aMatrix.Line2.Column3 = aTransformation.get(1,2); |
1320 | | |
1321 | 62.3k | aMatrix.Line3.Column1 = 0; |
1322 | 62.3k | aMatrix.Line3.Column2 = 0; |
1323 | 62.3k | aMatrix.Line3.Column3 = 1; |
1324 | | |
1325 | 62.3k | if (!(bTopWriterLine && !maSize.Width)) |
1326 | 62.3k | { |
1327 | 62.3k | maShapeProperties.setProperty(PROP_Transformation, aMatrix); |
1328 | 62.3k | } |
1329 | 62.3k | } |
1330 | | |
1331 | 64.0k | Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); |
1332 | 64.0k | if ( !mxShape.is() ) |
1333 | 64.0k | { |
1334 | 64.0k | mxShape.set( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW ); |
1335 | 64.0k | } |
1336 | | |
1337 | 64.0k | Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); |
1338 | 64.0k | bool bPlaceholderWithCustomPrompt = pPlaceholder && pPlaceholder->getCustomPrompt(); |
1339 | 64.0k | if (xSet.is()) |
1340 | 64.0k | { |
1341 | 64.0k | if (bTopWriterLine && !maSize.Width) |
1342 | 0 | { |
1343 | | // Entirely vertical line, set the points and the transform separately to match the ODF |
1344 | | // import. |
1345 | 0 | xSet->setPropertyValue(u"PolyPolygon"_ustr, Any(aPolyPolySequence)); |
1346 | 0 | xSet->setPropertyValue(u"Transformation"_ustr, Any(aMatrix)); |
1347 | 0 | } |
1348 | | |
1349 | 64.0k | if( !msName.isEmpty() ) |
1350 | 62.0k | { |
1351 | 62.0k | Reference< container::XNamed > xNamed( mxShape, UNO_QUERY ); |
1352 | 62.0k | if( xNamed.is() ) |
1353 | 62.0k | xNamed->setName( msName ); |
1354 | 62.0k | } |
1355 | 64.0k | if( !msDescription.isEmpty() ) |
1356 | 1.50k | { |
1357 | 1.50k | xSet->setPropertyValue( u"Description"_ustr, Any( msDescription ) ); |
1358 | 1.50k | } |
1359 | 64.0k | if (m_isDecorative) |
1360 | 0 | { |
1361 | 0 | xSet->setPropertyValue(u"Decorative"_ustr, Any(m_isDecorative)); |
1362 | 0 | } |
1363 | 64.0k | if (!msMacro.isEmpty()) |
1364 | 0 | { |
1365 | 0 | putPropertyToGrabBag(u"mso-sp-macro"_ustr, Any(msMacro)); |
1366 | 0 | } |
1367 | 64.0k | if (!msMacroExtUrl.isEmpty()) |
1368 | 0 | { |
1369 | 0 | putPropertyToGrabBag(u"mso-sp-macro-url"_ustr, Any(msMacroExtUrl)); |
1370 | 0 | } |
1371 | 64.0k | if (!msTextLink.isEmpty()) |
1372 | 0 | { |
1373 | 0 | putPropertyToGrabBag(u"mso-sp-textlink"_ustr, Any(msTextLink)); |
1374 | 0 | } |
1375 | 64.0k | if (!mbFLocksText) // set only if "false", otherwise it will use "true" by default |
1376 | 5 | { |
1377 | 5 | putPropertyToGrabBag(u"mso-sp-fLocksText"_ustr, Any(mbFLocksText)); |
1378 | 5 | } |
1379 | 64.0k | if (mbFPublished) |
1380 | 0 | { |
1381 | 0 | putPropertyToGrabBag(u"mso-sp-fPublished"_ustr, Any(mbFPublished)); |
1382 | 0 | } |
1383 | 64.0k | if (!msTitle.isEmpty()) |
1384 | 1 | { |
1385 | 1 | xSet->setPropertyValue(u"Title"_ustr, Any(msTitle)); |
1386 | 1 | } |
1387 | | |
1388 | | // get tooltip attribute of <hlinkClick> |
1389 | 64.0k | OUString sTooltip; |
1390 | 64.0k | getShapeProperties().getProperty(PROP_Representation) >>= sTooltip; |
1391 | 64.0k | if (!sTooltip.isEmpty()) |
1392 | 2 | putPropertyToGrabBag(u"mso-hlinkClick-tooltip"_ustr, Any(sTooltip)); |
1393 | | |
1394 | | // Placeholder uses the height set on the slide instead of the height from the master slide, |
1395 | | // if it has the "TextAutoGrowHeight" property |
1396 | 64.0k | if (getTextBody() && mxShape->getShapeType().startsWith("com.sun.star.presentation.")) |
1397 | 38.7k | { |
1398 | 38.7k | bool bAutoGrowHeight = getTextBody() |
1399 | 38.7k | ->getTextProperties() |
1400 | 38.7k | .maPropertyMap.getProperty(PROP_TextAutoGrowHeight) |
1401 | 38.7k | .get<bool>(); |
1402 | 38.7k | if (bAutoGrowHeight) |
1403 | 0 | { |
1404 | 0 | ppt::PowerPointImport* pPPT = dynamic_cast<ppt::PowerPointImport*>(&rFilterBase); |
1405 | 0 | if (!pPPT->getActualSlidePersist()->isMasterPage()) |
1406 | 0 | { |
1407 | 0 | sal_Int32 nUpper = 0; |
1408 | 0 | sal_Int32 nLower = 0; |
1409 | 0 | sal_Int32 nHeight = maSize.Height / 360; |
1410 | 0 | if (getTextBody()->getTextProperties().moInsets[1].has_value() |
1411 | 0 | && getTextBody()->getTextProperties().moInsets[3].has_value()) |
1412 | 0 | { |
1413 | 0 | nUpper = *getTextBody()->getTextProperties().moInsets[1]; |
1414 | 0 | nLower = *getTextBody()->getTextProperties().moInsets[3]; |
1415 | 0 | } |
1416 | 0 | else |
1417 | 0 | { |
1418 | 0 | maDefaultShapeProperties.getProperty(PROP_TextUpperDistance) >>= nUpper; |
1419 | 0 | maDefaultShapeProperties.getProperty(PROP_TextLowerDistance) >>= nLower; |
1420 | 0 | } |
1421 | 0 | nHeight -= (nUpper + nLower); |
1422 | 0 | mxShape->setSize(awt::Size(0, nHeight)); |
1423 | 0 | } |
1424 | 0 | } |
1425 | 38.7k | else // the placeholder uses the height set on the master slide |
1426 | 38.7k | mxShape->setSize(awt::Size(0, 0)); |
1427 | 38.7k | } |
1428 | | |
1429 | 64.0k | if (aServiceName != "com.sun.star.text.TextFrame") |
1430 | 64.0k | rxShapes->add( mxShape ); |
1431 | | |
1432 | 64.0k | if (getHidden() || getHiddenMasterShape()) |
1433 | 1.08k | { |
1434 | 1.08k | SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId << "'"); |
1435 | 1.08k | xSet->setPropertyValue( u"Visible"_ustr, Any( false ) ); |
1436 | | // In Excel hidden means not printed, let's use visibility for now until that's handled separately |
1437 | 1.08k | xSet->setPropertyValue( u"Printable"_ustr, Any( false ) ); |
1438 | 1.08k | } |
1439 | | |
1440 | 64.0k | if (getLocked()) |
1441 | 0 | { |
1442 | 0 | xSet->setPropertyValue(u"MoveProtect"_ustr, Any(true)); |
1443 | 0 | xSet->setPropertyValue(u"SizeProtect"_ustr, Any(true)); |
1444 | 0 | } |
1445 | | |
1446 | 64.0k | ActionLockGuard const alg(mxShape); |
1447 | | |
1448 | 64.0k | if (!getDiagramDataModelID().isEmpty()) |
1449 | 929 | { |
1450 | 929 | SdrObject* pSdrObject(SdrObject::getSdrObjectFromXShape(mxShape)); |
1451 | | |
1452 | 929 | if (nullptr != pSdrObject) |
1453 | 929 | { |
1454 | | // I checked if pSdrObject has a DiagramHelper here once, but this is |
1455 | | // highly dependent on when propagateDiagramHelper() will be called |
1456 | | // and not needed since when a DiagramDataModelID is set locally |
1457 | | // is sufficient to know that we are in a Diagram context. |
1458 | 929 | pSdrObject->setDiagramDataModelID(getDiagramDataModelID()); |
1459 | 929 | } |
1460 | 929 | } |
1461 | | |
1462 | | // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape |
1463 | 64.0k | if ( bClearText ) |
1464 | 14.0k | { |
1465 | 14.0k | uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY ); |
1466 | 14.0k | if ( xText.is() ) |
1467 | 14.0k | { |
1468 | 14.0k | xText->setString( u""_ustr ); |
1469 | 14.0k | } |
1470 | 14.0k | } |
1471 | | |
1472 | 64.0k | if (pMathXml) |
1473 | 0 | { |
1474 | | // the "EmbeddedObject" property is read-only, so we have to create |
1475 | | // the shape first, and it can be read only after the shape is |
1476 | | // inserted into the document, so delay the actual import until here |
1477 | 0 | SvGlobalName name(SO3_SM_CLASSID); |
1478 | 0 | xSet->setPropertyValue(u"CLSID"_ustr, uno::Any(name.GetHexName())); |
1479 | 0 | uno::Reference<embed::XEmbeddedObject> const xObj( |
1480 | 0 | xSet->getPropertyValue(u"EmbeddedObject"_ustr), uno::UNO_QUERY); |
1481 | 0 | if (xObj.is()) |
1482 | 0 | { |
1483 | 0 | uno::Reference<uno::XInterface> const xMathModel(xObj->getComponent()); |
1484 | 0 | oox::FormulaImExportBase *const pMagic( |
1485 | 0 | dynamic_cast<oox::FormulaImExportBase*>(xMathModel.get())); |
1486 | 0 | assert(pMagic); |
1487 | 0 | pMagic->readFormulaOoxml(*pMathXml); |
1488 | 0 | } |
1489 | 0 | } |
1490 | | |
1491 | 64.0k | const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper(); |
1492 | | |
1493 | 64.0k | ::Color nLinePhClr(ColorTransparency, 0xffffffff); |
1494 | 64.0k | ::Color nFillPhClr(ColorTransparency, 0xffffffff); |
1495 | 64.0k | sal_Int16 nFillPhClrTheme = -1; |
1496 | 64.0k | sal_Int16 nLinePhClrTheme = -1; |
1497 | | // TODO: use ph color when applying effect properties |
1498 | | //sal_Int32 nEffectPhClr = -1; |
1499 | | |
1500 | | // dmapper needs the original rotation angle for calculating square wrap. This angle is not |
1501 | | // available as property there, so store it in InteropGrabBag. |
1502 | 64.0k | putPropertyToGrabBag(u"mso-rotation-angle"_ustr, Any(getRotation())); |
1503 | | |
1504 | 64.0k | if( pTheme ) |
1505 | 61.5k | { |
1506 | 61.5k | if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) ) |
1507 | 3.16k | { |
1508 | 3.16k | LineProperties aLineProperties; |
1509 | 3.16k | aLineProperties.maLineFill.moFillType = XML_noFill; |
1510 | 3.16k | if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) ) |
1511 | 954 | aLineProperties.assignUsed( *pLineProps ); |
1512 | 3.16k | nLinePhClr = pLineRef->maPhClr.getColor( rGraphicHelper ); |
1513 | 3.16k | nLinePhClrTheme = pLineRef->maPhClr.getSchemeColorIndex(); |
1514 | | |
1515 | | // Store style-related properties to InteropGrabBag to be able to export them back |
1516 | 3.16k | uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( |
1517 | 3.16k | { |
1518 | 3.16k | {"SchemeClr", uno::Any(pLineRef->maPhClr.getSchemeColorName())}, |
1519 | 3.16k | {"Idx", uno::Any(pLineRef->mnThemedIdx)}, |
1520 | 3.16k | {"Color", uno::Any(nLinePhClr)}, |
1521 | 3.16k | {"LineStyle", uno::Any(aLineProperties.getLineStyle())}, |
1522 | 3.16k | {"LineCap", uno::Any(aLineProperties.getLineCap())}, |
1523 | 3.16k | {"LineJoint", uno::Any(aLineProperties.getLineJoint())}, |
1524 | 3.16k | {"LineWidth", uno::Any(aLineProperties.getLineWidth())}, |
1525 | 3.16k | {"Transformations", uno::Any(pLineRef->maPhClr.getTransformations())} |
1526 | 3.16k | }); |
1527 | 3.16k | putPropertyToGrabBag( u"StyleLnRef"_ustr, Any( aProperties ) ); |
1528 | 3.16k | } |
1529 | 61.5k | if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) ) |
1530 | 3.16k | { |
1531 | 3.16k | if (!getFillProperties().moUseBgFill.value_or(false)) |
1532 | 3.16k | { |
1533 | 3.16k | nFillPhClr = pFillRef->maPhClr.getColor(rGraphicHelper); |
1534 | 3.16k | nFillPhClrTheme = pFillRef->maPhClr.getSchemeColorIndex(); |
1535 | 3.16k | } |
1536 | | |
1537 | 3.16k | OUString sColorScheme = pFillRef->maPhClr.getSchemeColorName(); |
1538 | 3.16k | if( !sColorScheme.isEmpty() ) |
1539 | 1.37k | { |
1540 | 1.37k | uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( |
1541 | 1.37k | { |
1542 | 1.37k | {"SchemeClr", uno::Any(sColorScheme)}, |
1543 | 1.37k | {"Idx", uno::Any(pFillRef->mnThemedIdx)}, |
1544 | 1.37k | {"Color", uno::Any(nFillPhClr)}, |
1545 | 1.37k | {"Transformations", uno::Any(pFillRef->maPhClr.getTransformations())} |
1546 | 1.37k | }); |
1547 | | |
1548 | 1.37k | putPropertyToGrabBag( u"StyleFillRef"_ustr, Any( aProperties ) ); |
1549 | 1.37k | } |
1550 | 3.16k | } |
1551 | 61.5k | if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) ) |
1552 | 3.16k | { |
1553 | | // TODO: use ph color when applying effect properties |
1554 | | // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper ); |
1555 | | |
1556 | | // Store style-related properties to InteropGrabBag to be able to export them back |
1557 | 3.16k | uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( |
1558 | 3.16k | { |
1559 | 3.16k | {"SchemeClr", uno::Any(pEffectRef->maPhClr.getSchemeColorName())}, |
1560 | 3.16k | {"Idx", uno::Any(pEffectRef->mnThemedIdx)}, |
1561 | 3.16k | {"Transformations", uno::Any(pEffectRef->maPhClr.getTransformations())} |
1562 | 3.16k | }); |
1563 | 3.16k | putPropertyToGrabBag( u"StyleEffectRef"_ustr, Any( aProperties ) ); |
1564 | 3.16k | } |
1565 | 61.5k | } |
1566 | 64.0k | ShapePropertyMap aShapeProps( rFilterBase.getModelObjectHelper() ); |
1567 | | |
1568 | | // add properties from textbody to shape properties |
1569 | 64.0k | if( mpTextBody ) |
1570 | 49.2k | { |
1571 | | // tdf#67347: In case of Stacked, PP calculates in the vertical direction with the |
1572 | | // horizontal alignment. |
1573 | | // In LO, we simulate it by setting TextVerticalAdjust based on the ParagraphAdjust |
1574 | | // of the 1. paragraph |
1575 | | // It is not perfect, because we have 1 TextVerticalAdjust / 1 shape, and it |
1576 | | // does not support justified, while we can have many ParagraphAdjust / 1 shape |
1577 | | // (if the shape have more paragraphs) |
1578 | 49.2k | if (mpTextBody->getTextProperties().maPropertyMap.hasProperty(PROP_WritingMode) |
1579 | 16.4k | && mpTextBody->getTextProperties().maPropertyMap.getProperty(PROP_WritingMode) |
1580 | 16.4k | == uno::Any(text::WritingMode2::STACKED) |
1581 | 0 | && mpTextBody->getParagraphs().size() > 0 |
1582 | 0 | && aServiceName != "com.sun.star.drawing.GroupShape") |
1583 | 0 | { |
1584 | 0 | std::optional<css::style::ParagraphAdjust>& oParaAdjust |
1585 | 0 | = mpTextBody->getParagraphs()[0]->getProperties().getParaAdjust(); |
1586 | |
|
1587 | 0 | if (oParaAdjust) |
1588 | 0 | { |
1589 | 0 | switch (*oParaAdjust) |
1590 | 0 | { |
1591 | 0 | case ParagraphAdjust::ParagraphAdjust_LEFT: |
1592 | 0 | mpTextBody->getTextProperties().meVA |
1593 | 0 | = TextVerticalAdjust::TextVerticalAdjust_TOP; |
1594 | 0 | break; |
1595 | 0 | case ParagraphAdjust::ParagraphAdjust_CENTER: |
1596 | 0 | mpTextBody->getTextProperties().meVA |
1597 | 0 | = TextVerticalAdjust::TextVerticalAdjust_CENTER; |
1598 | 0 | break; |
1599 | 0 | case ParagraphAdjust::ParagraphAdjust_RIGHT: |
1600 | 0 | mpTextBody->getTextProperties().meVA |
1601 | 0 | = TextVerticalAdjust::TextVerticalAdjust_BOTTOM; |
1602 | 0 | break; |
1603 | 0 | default: |
1604 | 0 | break; |
1605 | 0 | } |
1606 | 0 | mpTextBody->getTextProperties().maPropertyMap.setProperty( |
1607 | 0 | PROP_TextVerticalAdjust, mpTextBody->getTextProperties().meVA); |
1608 | 0 | } |
1609 | 0 | } |
1610 | | |
1611 | | // tdf#162571: In case of shapes with TextAutoGrowHeight, PP calculates/grow the |
1612 | | // shapes size in edit mode (typing) based on the text horizontal alignment. |
1613 | | // In LO, we simulate it by setting TextHorizontalAdjust based on the ParagraphAdjust |
1614 | | // of the 1. paragraph |
1615 | | // It is not perfect, because we have 1 TextHorizontalAdjust / 1 shape, |
1616 | | // while we can have many ParagraphAdjust / 1 shape |
1617 | 49.2k | if (!mpTextBody->getTextProperties().maPropertyMap.hasProperty(PROP_WritingMode) |
1618 | 32.7k | && mpTextBody->getParagraphs().size() > 0) |
1619 | 32.5k | { |
1620 | 32.5k | std::optional<css::style::ParagraphAdjust>& oParaAdjust |
1621 | 32.5k | = mpTextBody->getParagraphs()[0]->getProperties().getParaAdjust(); |
1622 | | |
1623 | 32.5k | bool bAutoGrowHeight = getTextBody() |
1624 | 32.5k | ->getTextProperties() |
1625 | 32.5k | .maPropertyMap.getProperty(PROP_TextAutoGrowHeight) |
1626 | 32.5k | .get<bool>(); |
1627 | | |
1628 | 32.5k | bool bWrap = getTextBody() |
1629 | 32.5k | ->getTextProperties() |
1630 | 32.5k | .maPropertyMap.getProperty(PROP_TextWordWrap) |
1631 | 32.5k | .get<bool>(); |
1632 | | |
1633 | 32.5k | if (bAutoGrowHeight && !bWrap && nShapeRotateInclCamera == 0) |
1634 | 295 | { |
1635 | 295 | mpTextBody->getTextProperties().maPropertyMap.setProperty( |
1636 | 295 | PROP_TextHorizontalAdjust, lcl_convertTextAdjust( |
1637 | 295 | oParaAdjust ? *oParaAdjust : ParagraphAdjust_LEFT)); |
1638 | 295 | } |
1639 | 32.5k | } |
1640 | | |
1641 | 49.2k | mpTextBody->getTextProperties().pushTextDistances(Size(aShapeRectHmm.Width, aShapeRectHmm.Height)); |
1642 | 49.2k | aShapeProps.assignUsed( mpTextBody->getTextProperties().maPropertyMap ); |
1643 | | // Push char properties as well - specifically useful when this is a placeholder |
1644 | 49.2k | if( mpMasterTextListStyle && mpMasterTextListStyle->getListStyle()[0].getTextCharacterProperties().moHeight.has_value() ) |
1645 | 23.1k | aShapeProps.setProperty(PROP_CharHeight, GetFontHeight( mpMasterTextListStyle->getListStyle()[0].getTextCharacterProperties().moHeight.value() )); |
1646 | 49.2k | } |
1647 | | |
1648 | 64.0k | Sequence<PropertyValue> aCamera3DEffects = get3DProperties().getCameraAttributes(); |
1649 | 64.0k | Sequence<PropertyValue> aLightRig3DEffects = get3DProperties().getLightRigAttributes(); |
1650 | 64.0k | Sequence<PropertyValue> aShape3DEffects |
1651 | 64.0k | = get3DProperties().getShape3DAttributes(rGraphicHelper, nFillPhClr); |
1652 | 64.0k | bool bHas3DProps = aCamera3DEffects.hasElements() || aLightRig3DEffects.hasElements() |
1653 | 64.0k | || aShape3DEffects.hasElements(); |
1654 | 64.0k | if (bHas3DProps && getEffectProperties().maSoftEdge.moRad.has_value()) |
1655 | 0 | { |
1656 | | // 3D properties override softeEdge |
1657 | 0 | getEffectProperties().maSoftEdge.moRad.reset(); |
1658 | 0 | } |
1659 | | |
1660 | | // applying properties |
1661 | 64.0k | aShapeProps.assignUsed( getShapeProperties() ); |
1662 | 64.0k | aShapeProps.assignUsed( maDefaultShapeProperties ); |
1663 | 64.0k | if(nShapeRotateInclCamera != 0 && bIsCustomShape) |
1664 | 2.06k | aShapeProps.setProperty(PROP_RotateAngle, |
1665 | 2.06k | sal_Int32(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera))); |
1666 | 64.0k | if( bIsEmbMedia || |
1667 | 64.0k | bIsCustomShape || |
1668 | 45.1k | aServiceName == "com.sun.star.drawing.GraphicObjectShape" || |
1669 | 41.7k | aServiceName == "com.sun.star.drawing.OLE2Shape") |
1670 | 22.7k | { |
1671 | 22.7k | mpGraphicPropertiesPtr->pushToPropMap(aShapeProps, rGraphicHelper, getFlipH(), getFlipV()); |
1672 | 22.7k | } |
1673 | 64.0k | if ( mpTablePropertiesPtr && aServiceName == "com.sun.star.drawing.TableShape" ) |
1674 | 124 | { |
1675 | 124 | mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle ); |
1676 | 124 | if ( auto* pTableShape = dynamic_cast<sdr::table::SdrTableObj*>(SdrObject::getSdrObjectFromXShape(mxShape)) ) |
1677 | 124 | { |
1678 | | // Disable layouting until table height is expanded to fit the content |
1679 | 124 | pTableShape->SetSkipChangeLayout(true); |
1680 | 124 | } |
1681 | 124 | } |
1682 | | |
1683 | 64.0k | FillProperties aFillProperties = getActualFillProperties(pTheme, &rShapeOrParentShapeFillProps); |
1684 | 64.0k | if ((getFillProperties().moFillType.has_value() && getFillProperties().moFillType.value() == XML_grpFill) || |
1685 | 64.0k | aFillProperties.maFillColor.isPlaceHolder() ) |
1686 | 596 | getFillProperties().assignUsed(aFillProperties); |
1687 | 64.0k | if (!bIsCroppedGraphic && !bIs3DGraphic) |
1688 | 64.0k | { |
1689 | 64.0k | aFillProperties.pushToPropMap(aShapeProps, rGraphicHelper, getRotation(), nFillPhClr, |
1690 | 64.0k | css::awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height), |
1691 | 64.0k | nFillPhClrTheme, getFlipH(), getFlipV(), bIsCustomShape); |
1692 | 64.0k | } |
1693 | 64.0k | LineProperties aLineProperties = getActualLineProperties(pTheme); |
1694 | 64.0k | aLineProperties.pushToPropMap( aShapeProps, rGraphicHelper, nLinePhClr, nLinePhClrTheme); |
1695 | 64.0k | EffectProperties aEffectProperties = getActualEffectProperties(pTheme); |
1696 | | // TODO: use ph color when applying effect properties |
1697 | 64.0k | aEffectProperties.pushToPropMap( aShapeProps, rGraphicHelper ); |
1698 | | |
1699 | | // applying autogrowheight property before setting shape size, because |
1700 | | // the shape size might be changed if currently autogrowheight is true |
1701 | | // we must also check that the PropertySet supports the property. |
1702 | 64.0k | Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); |
1703 | 64.0k | const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight ); |
1704 | 64.0k | if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) ) |
1705 | 63.3k | if( aShapeProps.hasProperty( PROP_TextAutoGrowHeight ) ) |
1706 | 63.2k | xSet->setPropertyValue( rPropName, Any( false ) ); |
1707 | | |
1708 | | // For extruded shapes, MSO uses the line color if no extrusion color is specified. LO uses |
1709 | | // fill color in 'automatic' case. Thus we set extrusion color explicitly. |
1710 | 64.0k | if (bHas3DEffect && !aExtrusionColor.isUsed()) |
1711 | 0 | { |
1712 | 0 | const OUString& rFillColor2PropName = PropertyMap::getPropertyName(PROP_FillColor2); |
1713 | 0 | if (xSetInfo.is() && xSetInfo->hasPropertyByName(rFillColor2PropName)) |
1714 | 0 | { |
1715 | 0 | Color aComplexColor; |
1716 | 0 | if (aLineProperties.maLineFill.moFillType.has_value() |
1717 | 0 | && aLineProperties.maLineFill.moFillType.value() != XML_noFill) |
1718 | 0 | aComplexColor = aLineProperties.maLineFill.getBestSolidColor(); |
1719 | 0 | else if (aFillProperties.moFillType.has_value() |
1720 | 0 | && aFillProperties.moFillType.value() != XML_noFill) |
1721 | 0 | aComplexColor = aFillProperties.getBestSolidColor(); |
1722 | 0 | if (aComplexColor.isUsed()) |
1723 | 0 | { |
1724 | 0 | const ::Color aSimpleColor = aComplexColor.getColor(rFilterBase.getGraphicHelper()); |
1725 | 0 | xSet->setPropertyValue(rFillColor2PropName, Any(aSimpleColor)); |
1726 | 0 | } |
1727 | 0 | } |
1728 | 0 | } |
1729 | | |
1730 | | // do not set properties at a group shape (this causes |
1731 | | // assertions from svx) ... |
1732 | 64.0k | if( aServiceName != "com.sun.star.drawing.GroupShape" ) |
1733 | 63.4k | { |
1734 | 63.4k | if (aServiceName == "com.sun.star.text.TextFrame") |
1735 | 0 | { |
1736 | 0 | if (mpCustomShapePropertiesPtr && mpCustomShapePropertiesPtr->getShapeTypeOverride()) |
1737 | 0 | { |
1738 | 0 | uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); |
1739 | 0 | uno::Sequence<beans::PropertyValue> aGrabBag; |
1740 | 0 | propertySet->getPropertyValue(u"FrameInteropGrabBag"_ustr) >>= aGrabBag; |
1741 | 0 | sal_Int32 length = aGrabBag.getLength(); |
1742 | 0 | aGrabBag.realloc( length+1); |
1743 | 0 | auto pGrabBag = aGrabBag.getArray(); |
1744 | 0 | pGrabBag[length].Name = "mso-orig-shape-type"; |
1745 | 0 | pGrabBag[length].Value <<= mpCustomShapePropertiesPtr->getShapePresetTypeName(); |
1746 | 0 | propertySet->setPropertyValue(u"FrameInteropGrabBag"_ustr,uno::Any(aGrabBag)); |
1747 | 0 | } |
1748 | | //If the text box has links then save the link information so that |
1749 | | //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames. |
1750 | 0 | if (isLinkedTxbx()) |
1751 | 0 | { |
1752 | 0 | uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); |
1753 | 0 | uno::Sequence<beans::PropertyValue> aGrabBag; |
1754 | 0 | propertySet->getPropertyValue(u"FrameInteropGrabBag"_ustr) >>= aGrabBag; |
1755 | 0 | sal_Int32 length = aGrabBag.getLength(); |
1756 | 0 | aGrabBag.realloc( length + 3 ); |
1757 | 0 | auto pGrabBag = aGrabBag.getArray(); |
1758 | 0 | pGrabBag[length].Name = "TxbxHasLink"; |
1759 | 0 | pGrabBag[length].Value <<= isLinkedTxbx(); |
1760 | 0 | pGrabBag[length + 1 ].Name = "Txbx-Id"; |
1761 | 0 | pGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id; |
1762 | 0 | pGrabBag[length + 2 ].Name = "Txbx-Seq"; |
1763 | 0 | pGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq; |
1764 | 0 | propertySet->setPropertyValue(u"FrameInteropGrabBag"_ustr,uno::Any(aGrabBag)); |
1765 | 0 | } |
1766 | | |
1767 | | // TextFrames have BackColor, not FillColor |
1768 | 0 | if (aShapeProps.hasProperty(PROP_FillColor)) |
1769 | 0 | { |
1770 | 0 | aShapeProps.setAnyProperty(PROP_BackColor, aShapeProps.getProperty(PROP_FillColor)); |
1771 | 0 | aShapeProps.erase(PROP_FillColor); |
1772 | 0 | } |
1773 | | // TextFrames have BackColorTransparency, not FillTransparence |
1774 | 0 | if (aShapeProps.hasProperty(PROP_FillTransparence)) |
1775 | 0 | { |
1776 | 0 | aShapeProps.setAnyProperty(PROP_BackColorTransparency, aShapeProps.getProperty(PROP_FillTransparence)); |
1777 | 0 | aShapeProps.erase(PROP_FillTransparence); |
1778 | 0 | } |
1779 | | // TextFrames have BackGraphic, not FillBitmap |
1780 | 0 | if (aShapeProps.hasProperty(PROP_FillBitmap)) |
1781 | 0 | { |
1782 | 0 | aShapeProps.setAnyProperty(PROP_BackGraphic, aShapeProps.getProperty(PROP_FillBitmap)); |
1783 | 0 | aShapeProps.erase(PROP_FillBitmap); |
1784 | 0 | } |
1785 | 0 | if (aShapeProps.hasProperty(PROP_FillBitmapName)) |
1786 | 0 | { |
1787 | 0 | uno::Any aAny = aShapeProps.getProperty(PROP_FillBitmapName); |
1788 | 0 | OUString aFillBitmapName = aAny.get<OUString>(); |
1789 | 0 | uno::Reference<awt::XBitmap> xBitmap = rFilterBase.getModelObjectHelper().getFillBitmap(aFillBitmapName); |
1790 | 0 | uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY); |
1791 | 0 | aShapeProps.setProperty(PROP_BackGraphic, xGraphic); |
1792 | | // aShapeProps.erase(PROP_FillBitmapName); // Maybe, leave the name as well |
1793 | 0 | } |
1794 | | // And no LineColor property; individual borders can have colors |
1795 | 0 | if (aShapeProps.hasProperty(PROP_LineColor)) |
1796 | 0 | { |
1797 | 0 | uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); |
1798 | 0 | static const sal_Int32 aBorders[] = |
1799 | 0 | { |
1800 | 0 | PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder |
1801 | 0 | }; |
1802 | 0 | for (sal_Int32 nBorder : aBorders) |
1803 | 0 | { |
1804 | 0 | css::table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(nBorder)).get<css::table::BorderLine2>(); |
1805 | 0 | aBorderLine.Color = aShapeProps.getProperty(PROP_LineColor).get<sal_Int32>(); |
1806 | 0 | if (aLineProperties.moLineWidth.has_value()) |
1807 | 0 | aBorderLine.LineWidth = convertEmuToHmm(aLineProperties.moLineWidth.value()); |
1808 | 0 | aShapeProps.setProperty(nBorder, aBorderLine); |
1809 | 0 | } |
1810 | 0 | aShapeProps.erase(PROP_LineColor); |
1811 | 0 | } |
1812 | 0 | if (getRotation()) |
1813 | 0 | { |
1814 | 0 | uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); |
1815 | 0 | static constexpr OUString aGrabBagPropName = u"FrameInteropGrabBag"_ustr; |
1816 | 0 | uno::Sequence<beans::PropertyValue> aGrabBag; |
1817 | 0 | xPropertySet->getPropertyValue(aGrabBagPropName) >>= aGrabBag; |
1818 | 0 | beans::PropertyValue aPair(comphelper::makePropertyValue(u"mso-rotation-angle"_ustr, |
1819 | 0 | getRotation())); |
1820 | 0 | if (aGrabBag.hasElements()) |
1821 | 0 | { |
1822 | 0 | sal_Int32 nLength = aGrabBag.getLength(); |
1823 | 0 | aGrabBag.realloc(nLength + 1); |
1824 | 0 | aGrabBag.getArray()[nLength] = std::move(aPair); |
1825 | 0 | } |
1826 | 0 | else |
1827 | 0 | { |
1828 | 0 | aGrabBag = { std::move(aPair) }; |
1829 | 0 | } |
1830 | 0 | xPropertySet->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag)); |
1831 | 0 | } |
1832 | | // TextFrames have ShadowFormat, not individual shadow properties. |
1833 | 0 | std::optional<sal_Int32> oShadowDistance; |
1834 | 0 | if (aShapeProps.hasProperty(PROP_ShadowXDistance)) |
1835 | 0 | { |
1836 | 0 | oShadowDistance = aShapeProps.getProperty(PROP_ShadowXDistance).get<sal_Int32>(); |
1837 | 0 | aShapeProps.erase(PROP_ShadowXDistance); |
1838 | 0 | } |
1839 | 0 | if (aShapeProps.hasProperty(PROP_ShadowYDistance)) |
1840 | 0 | { |
1841 | | // There is a single 'dist' attribute, so no need to count the avg of x and y. |
1842 | 0 | aShapeProps.erase(PROP_ShadowYDistance); |
1843 | 0 | } |
1844 | 0 | std::optional<sal_Int32> oShadowColor; |
1845 | 0 | if (aShapeProps.hasProperty(PROP_ShadowColor)) |
1846 | 0 | { |
1847 | 0 | oShadowColor = aShapeProps.getProperty(PROP_ShadowColor).get<sal_Int32>(); |
1848 | 0 | aShapeProps.erase(PROP_ShadowColor); |
1849 | 0 | } |
1850 | 0 | if (aShapeProps.hasProperty(PROP_Shadow)) |
1851 | 0 | aShapeProps.erase(PROP_Shadow); |
1852 | |
|
1853 | 0 | if (oShadowDistance || oShadowColor || aEffectProperties.maShadow.moShadowDir.has_value()) |
1854 | 0 | { |
1855 | 0 | css::table::ShadowFormat aFormat; |
1856 | 0 | if (oShadowColor) |
1857 | 0 | aFormat.Color = *oShadowColor; |
1858 | 0 | if (aEffectProperties.maShadow.moShadowDir.has_value()) |
1859 | 0 | { |
1860 | 0 | css::table::ShadowLocation nLocation = css::table::ShadowLocation_NONE; |
1861 | 0 | switch (aEffectProperties.maShadow.moShadowDir.value()) |
1862 | 0 | { |
1863 | 0 | case 13500000: |
1864 | 0 | nLocation = css::table::ShadowLocation_TOP_LEFT; |
1865 | 0 | break; |
1866 | 0 | case 18900000: |
1867 | 0 | nLocation = css::table::ShadowLocation_TOP_RIGHT; |
1868 | 0 | break; |
1869 | 0 | case 8100000: |
1870 | 0 | nLocation = css::table::ShadowLocation_BOTTOM_LEFT; |
1871 | 0 | break; |
1872 | 0 | case 2700000: |
1873 | 0 | nLocation = css::table::ShadowLocation_BOTTOM_RIGHT; |
1874 | 0 | break; |
1875 | 0 | } |
1876 | 0 | aFormat.Location = nLocation; |
1877 | 0 | } |
1878 | 0 | aFormat.ShadowWidth = *oShadowDistance; |
1879 | 0 | aShapeProps.setProperty(PROP_ShadowFormat, aFormat); |
1880 | 0 | } |
1881 | |
|
1882 | 0 | } |
1883 | 63.4k | else if (getIsTextBox()) |
1884 | 324 | { |
1885 | | // This introduces a TextBox in a shape in Writer. ToDo: Can we restrict it to cases |
1886 | | // where the TextBox edit engine is really needed? tdf#82627 |
1887 | 324 | aShapeProps.setProperty(PROP_TextBox, true); |
1888 | 324 | } |
1889 | | |
1890 | 63.4k | if (aServiceName != "com.sun.star.text.TextFrame" && isLinkedTxbx()) |
1891 | 0 | { |
1892 | 0 | uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); |
1893 | 0 | uno::Sequence<beans::PropertyValue> aGrabBag; |
1894 | 0 | propertySet->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag; |
1895 | 0 | sal_Int32 length = aGrabBag.getLength(); |
1896 | 0 | aGrabBag.realloc( length + 3 ); |
1897 | 0 | auto pGrabBag = aGrabBag.getArray(); |
1898 | 0 | pGrabBag[length].Name = "TxbxHasLink"; |
1899 | 0 | pGrabBag[length].Value <<= isLinkedTxbx(); |
1900 | 0 | pGrabBag[length + 1 ].Name = "Txbx-Id"; |
1901 | 0 | pGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id; |
1902 | 0 | pGrabBag[length + 2 ].Name = "Txbx-Seq"; |
1903 | 0 | pGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq; |
1904 | 0 | propertySet->setPropertyValue(u"InteropGrabBag"_ustr,uno::Any(aGrabBag)); |
1905 | 0 | } |
1906 | | |
1907 | | // set custom prompt text if available |
1908 | 63.4k | if (getCustomPrompt() && getTextBody() && !getTextBody()->isEmpty()) |
1909 | 0 | { |
1910 | 0 | aShapeProps.setProperty(PROP_CustomPromptText, getTextBody()->firstParatoString()); |
1911 | 0 | } |
1912 | 63.4k | else if (pPlaceholder && pPlaceholder->getCustomPrompt() && pPlaceholder->getTextBody() && !pPlaceholder->getTextBody()->isEmpty()) |
1913 | 0 | { |
1914 | 0 | aShapeProps.setProperty(PROP_CustomPromptText, pPlaceholder->getTextBody()->firstParatoString()); |
1915 | 0 | } |
1916 | | |
1917 | 63.4k | PropertySet( xSet ).setProperties( aShapeProps ); |
1918 | | |
1919 | 63.4k | if (mpTablePropertiesPtr && aServiceName == "com.sun.star.drawing.TableShape") |
1920 | 124 | { |
1921 | | // Powerpoint exports desired row heights (i.e. what user attempted to set it as, not how it appears visually) |
1922 | | // Expand table height if there are rows that can't fit the content |
1923 | 124 | if (auto* pTableShape = dynamic_cast<sdr::table::SdrTableObj*>(SdrObject::getSdrObjectFromXShape(mxShape))) |
1924 | 124 | { |
1925 | 124 | tools::Rectangle aArea{}; |
1926 | 124 | pTableShape->LayoutTableHeight(aArea); |
1927 | 124 | sal_Int32 nCorrectedHeight = aArea.GetHeight(); |
1928 | 124 | const auto aShapeSize = mxShape->getSize(); |
1929 | 124 | if( nCorrectedHeight > aShapeSize.Height ) |
1930 | 0 | mxShape->setSize( {aShapeSize.Width, nCorrectedHeight} ); |
1931 | 124 | pTableShape->SetSkipChangeLayout(false); |
1932 | 124 | } |
1933 | 124 | } |
1934 | | |
1935 | 63.4k | if (getLockedCanvas()) |
1936 | 0 | { |
1937 | 0 | putPropertyToGrabBag( u"LockedCanvas"_ustr, Any( true ) ); |
1938 | 0 | if (aServiceName == "com.sun.star.drawing.LineShape") |
1939 | 0 | { |
1940 | | // It seems the position and size for lines inside a locked canvas is absolute. |
1941 | 0 | mxShape->setPosition(awt::Point(aShapeRectHmm.X, aShapeRectHmm.Y)); |
1942 | 0 | mxShape->setSize(awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height)); |
1943 | 0 | } |
1944 | 0 | } |
1945 | | |
1946 | 63.4k | if (isInWordprocessingCanvas()) |
1947 | 0 | { |
1948 | 0 | putPropertyToGrabBag(u"WordprocessingCanvas"_ustr, Any(true)); |
1949 | 0 | } |
1950 | | |
1951 | | // Store original fill and line colors of the shape and the theme color name to InteropGrabBag |
1952 | 63.4k | std::vector<beans::PropertyValue> aProperties |
1953 | 63.4k | { |
1954 | 63.4k | comphelper::makePropertyValue(u"EmuLineWidth"_ustr, aLineProperties.moLineWidth.value_or(0)), |
1955 | 63.4k | comphelper::makePropertyValue(u"OriginalSolidFillClr"_ustr, aShapeProps.getProperty(PROP_FillColor)), |
1956 | 63.4k | comphelper::makePropertyValue(u"OriginalLnSolidFillClr"_ustr, aShapeProps.getProperty(PROP_LineColor)) |
1957 | 63.4k | }; |
1958 | 63.4k | OUString sColorFillScheme = aFillProperties.maFillColor.getSchemeColorName(); |
1959 | 63.4k | if( !aFillProperties.maFillColor.isPlaceHolder() && !sColorFillScheme.isEmpty() ) |
1960 | 2.61k | { |
1961 | 2.61k | aProperties.push_back(comphelper::makePropertyValue(u"SpPrSolidFillSchemeClr"_ustr, sColorFillScheme)); |
1962 | 2.61k | aProperties.push_back(comphelper::makePropertyValue(u"SpPrSolidFillSchemeClrTransformations"_ustr, aFillProperties.maFillColor.getTransformations())); |
1963 | 2.61k | } |
1964 | 63.4k | OUString sLnColorFillScheme = aLineProperties.maLineFill.maFillColor.getSchemeColorName(); |
1965 | 63.4k | if( !aLineProperties.maLineFill.maFillColor.isPlaceHolder() && !sLnColorFillScheme.isEmpty() ) |
1966 | 2.79k | { |
1967 | 2.79k | aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillSchemeClr"_ustr, sLnColorFillScheme)); |
1968 | 2.79k | auto aResolvedSchemeClr = aLineProperties.maLineFill.maFillColor; |
1969 | 2.79k | aResolvedSchemeClr.clearTransformations(); |
1970 | 2.79k | aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillResolvedSchemeClr"_ustr, aResolvedSchemeClr.getColor(rGraphicHelper, nFillPhClr))); |
1971 | 2.79k | aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillSchemeClrTransformations"_ustr, aLineProperties.maLineFill.maFillColor.getTransformations())); |
1972 | 2.79k | } |
1973 | 63.4k | putPropertiesToGrabBag(comphelper::containerToSequence(aProperties)); |
1974 | | |
1975 | | // Store original gradient fill of the shape to InteropGrabBag |
1976 | | // LibreOffice doesn't support all the kinds of gradient so we save its complete definition |
1977 | 63.4k | if( aShapeProps.hasProperty( PROP_FillGradient ) ) |
1978 | 1.94k | { |
1979 | 1.94k | std::vector<beans::PropertyValue> aGradientStops; |
1980 | 1.94k | size_t i = 0; |
1981 | 1.94k | for( const auto& [rPos, rColor] : aFillProperties.maGradientProps.maGradientStops ) |
1982 | 4.13k | { // for each stop in the gradient definition: |
1983 | | |
1984 | | // save position |
1985 | 4.13k | std::vector<beans::PropertyValue> aGradientStop |
1986 | 4.13k | { |
1987 | 4.13k | comphelper::makePropertyValue(u"Pos"_ustr, rPos) |
1988 | 4.13k | }; |
1989 | | |
1990 | 4.13k | OUString sStopColorScheme = rColor.getSchemeColorName(); |
1991 | 4.13k | if( sStopColorScheme.isEmpty() ) |
1992 | 3.57k | { |
1993 | | // save RGB color |
1994 | 3.57k | aGradientStop.push_back(comphelper::makePropertyValue(u"RgbClr"_ustr, rColor.getColor(rGraphicHelper, nFillPhClr))); |
1995 | | // in the case of a RGB color, transformations are already applied to |
1996 | | // the color with the exception of alpha transformations. We only need |
1997 | | // to keep the transparency value to calculate the alpha value later. |
1998 | 3.57k | if( rColor.hasTransparency() ) |
1999 | 0 | aGradientStop.push_back(comphelper::makePropertyValue(u"Transparency"_ustr, rColor.getTransparency())); |
2000 | 3.57k | } |
2001 | 562 | else |
2002 | 562 | { |
2003 | | // save color with scheme name |
2004 | 562 | aGradientStop.push_back(comphelper::makePropertyValue(u"SchemeClr"_ustr, sStopColorScheme)); |
2005 | | // save all color transformations |
2006 | 562 | aGradientStop.push_back(comphelper::makePropertyValue(u"Transformations"_ustr, rColor.getTransformations())); |
2007 | 562 | } |
2008 | | |
2009 | 4.13k | aGradientStops.push_back(comphelper::makePropertyValue(OUString::number(i), comphelper::containerToSequence(aGradientStop))); |
2010 | 4.13k | ++i; |
2011 | 4.13k | } |
2012 | | // If getFillProperties.moFillType is unused that means gradient is defined by a theme |
2013 | | // which is already saved into StyleFillRef property, so no need to save the explicit values too |
2014 | 1.94k | if( getFillProperties().moFillType.has_value() ) |
2015 | 1.91k | putPropertyToGrabBag( u"GradFillDefinition"_ustr, uno::Any(comphelper::containerToSequence(aGradientStops))); |
2016 | 1.94k | putPropertyToGrabBag( u"OriginalGradFill"_ustr, aShapeProps.getProperty(PROP_FillGradient) ); |
2017 | 1.94k | } |
2018 | | |
2019 | | // store unsupported effect attributes in the grab bag |
2020 | 63.4k | if (!aEffectProperties.m_Effects.empty()) |
2021 | 101 | { |
2022 | 101 | std::vector<beans::PropertyValue> aEffects; |
2023 | 101 | for (auto const& it : aEffectProperties.m_Effects) |
2024 | 101 | { |
2025 | 101 | PropertyValue aEffect = it->getEffect(); |
2026 | 101 | if( !aEffect.Name.isEmpty() ) |
2027 | 101 | { |
2028 | 101 | std::vector<beans::PropertyValue> aEffectsGrabBag |
2029 | 101 | { |
2030 | 101 | comphelper::makePropertyValue(u"Attribs"_ustr, aEffect.Value) |
2031 | 101 | }; |
2032 | | |
2033 | 101 | Color& aColor( it->moColor ); |
2034 | 101 | OUString sColorScheme = aColor.getSchemeColorName(); |
2035 | 101 | if( sColorScheme.isEmpty() ) |
2036 | 90 | { |
2037 | | // RGB color and transparency value |
2038 | 90 | aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"RgbClr"_ustr, aColor.getColor(rGraphicHelper, nFillPhClr))); |
2039 | 90 | aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"RgbClrTransparency"_ustr, aColor.getTransparency())); |
2040 | 90 | } |
2041 | 11 | else |
2042 | 11 | { |
2043 | | // scheme color with name and transformations |
2044 | 11 | aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"SchemeClr"_ustr, sColorScheme)); |
2045 | 11 | aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"SchemeClrTransformations"_ustr, aColor.getTransformations())); |
2046 | 11 | } |
2047 | 101 | aEffects.push_back(comphelper::makePropertyValue(aEffect.Name, comphelper::containerToSequence(aEffectsGrabBag))); |
2048 | 101 | } |
2049 | 101 | } |
2050 | 101 | putPropertyToGrabBag(u"EffectProperties"_ustr, uno::Any(comphelper::containerToSequence(aEffects))); |
2051 | 101 | } |
2052 | | |
2053 | | // add 3D effects if any to GrabBag. They are still used in export. |
2054 | 63.4k | if (bHas3DProps) |
2055 | 15 | { |
2056 | 15 | uno::Sequence<beans::PropertyValue> a3DEffectsGrabBag = comphelper::InitPropertySequence( |
2057 | 15 | { |
2058 | 15 | {"Camera", uno::Any(aCamera3DEffects)}, |
2059 | 15 | {"LightRig", uno::Any(aLightRig3DEffects)}, |
2060 | 15 | {"Shape3D", uno::Any(aShape3DEffects)} |
2061 | 15 | }); |
2062 | 15 | putPropertyToGrabBag( u"3DEffectProperties"_ustr, Any( a3DEffectsGrabBag ) ); |
2063 | 15 | } |
2064 | | |
2065 | 63.4k | if( bIsCustomShape && getTextBody()) |
2066 | 10.3k | { |
2067 | | |
2068 | 10.3k | Sequence< PropertyValue > aTextCamera3DEffects = getTextBody()->get3DProperties().getCameraAttributes(); |
2069 | 10.3k | Sequence< PropertyValue > aTextLightRig3DEffects = getTextBody()->get3DProperties().getLightRigAttributes(); |
2070 | 10.3k | Sequence< PropertyValue > aTextShape3DEffects = getTextBody()->get3DProperties().getShape3DAttributes( rGraphicHelper, nFillPhClr ); |
2071 | 10.3k | if( aTextCamera3DEffects.hasElements() || aTextLightRig3DEffects.hasElements() || aTextShape3DEffects.hasElements() ) |
2072 | 0 | { |
2073 | 0 | uno::Sequence<beans::PropertyValue> aText3DEffectsGrabBag = comphelper::InitPropertySequence( |
2074 | 0 | { |
2075 | 0 | {"Camera", uno::Any(aTextCamera3DEffects)}, |
2076 | 0 | {"LightRig", uno::Any(aTextLightRig3DEffects)}, |
2077 | 0 | {"Shape3D", uno::Any(aTextShape3DEffects)} |
2078 | 0 | }); |
2079 | 0 | putPropertyToGrabBag( u"Text3DEffectProperties"_ustr, Any( aText3DEffectsGrabBag ) ); |
2080 | 0 | } |
2081 | 10.3k | } |
2082 | | |
2083 | | // store bitmap artistic effects in the grab bag |
2084 | 63.4k | if( !mpGraphicPropertiesPtr->maBlipProps.maEffect.isEmpty() ) |
2085 | 0 | putPropertyToGrabBag( u"ArtisticEffectProperties"_ustr, |
2086 | 0 | Any( mpGraphicPropertiesPtr->maBlipProps.maEffect.getEffect() ) ); |
2087 | 63.4k | } |
2088 | | |
2089 | 639 | else if (getLockedCanvas()) |
2090 | 40 | { |
2091 | | //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas |
2092 | 40 | putPropertyToGrabBag( u"LockedCanvas"_ustr, Any( true ) ); |
2093 | 40 | } |
2094 | 599 | else if (isInWordprocessingCanvas()) |
2095 | 0 | { |
2096 | 0 | putPropertyToGrabBag(u"WordprocessingCanvas"_ustr, Any(true)); |
2097 | 0 | putPropertyToGrabBag(u"mso-edit-as"_ustr, Any(u"canvas"_ustr)); // for export VML Fallback |
2098 | 0 | } |
2099 | | |
2100 | | // These can have a custom geometry, so position should be set here, |
2101 | | // after creation but before custom shape handling, using the position |
2102 | | // we got from the caller. |
2103 | 64.0k | if (getWps() && aServiceName == "com.sun.star.drawing.LineShape" && !pParentGroupShape) |
2104 | 0 | mxShape->setPosition(maPosition); |
2105 | | |
2106 | 64.0k | SdrObject* pShape = SdrObject::getSdrObjectFromXShape(mxShape); |
2107 | 64.0k | if (pShape) |
2108 | 64.0k | aOrigSize = pShape->GetLogicRect(); |
2109 | | |
2110 | 64.0k | if (bIsConnectorShape) |
2111 | 1.57k | { |
2112 | 1.57k | msConnectorName = mpCustomShapePropertiesPtr->getShapePresetTypeName(); |
2113 | | |
2114 | 1.57k | const auto& aAdjustmentList = mpCustomShapePropertiesPtr->getAdjustmentGuideList(); |
2115 | 1.59k | for (size_t i = 0; i < aAdjustmentList.size(); i++) |
2116 | 21 | maConnectorAdjustmentList.push_back(aAdjustmentList[i].maFormula); |
2117 | | |
2118 | 1.57k | sal_Int32 nType = mpCustomShapePropertiesPtr->getShapePresetType(); |
2119 | 1.57k | switch (nType) |
2120 | 1.57k | { |
2121 | 1.20k | case XML_line: |
2122 | 1.53k | case XML_straightConnector1: |
2123 | 1.53k | xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_LINE)); |
2124 | 1.53k | break; |
2125 | 24 | case XML_bentConnector2: |
2126 | 45 | case XML_bentConnector3: |
2127 | 45 | case XML_bentConnector4: |
2128 | 45 | case XML_bentConnector5: |
2129 | 45 | xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_STANDARD)); |
2130 | 45 | break; |
2131 | 0 | case XML_curvedConnector2: |
2132 | 0 | case XML_curvedConnector3: |
2133 | 0 | case XML_curvedConnector4: |
2134 | 0 | case XML_curvedConnector5: |
2135 | 0 | xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_CURVE)); |
2136 | 0 | break; |
2137 | 0 | default: |
2138 | 0 | break; |
2139 | 1.57k | } |
2140 | 1.57k | } |
2141 | | |
2142 | 64.0k | if( bIsCustomShape ) |
2143 | 18.9k | { |
2144 | 18.9k | if (getFlipH()) |
2145 | 10 | mpCustomShapePropertiesPtr->setMirroredX( true ); |
2146 | 18.9k | if (getFlipV()) |
2147 | 32 | mpCustomShapePropertiesPtr->setMirroredY( true ); |
2148 | 18.9k | if( getTextBody() ) |
2149 | 10.3k | { |
2150 | 10.3k | sal_Int32 nTextCameraZRotation = getTextBody()->get3DProperties().maCameraRotation.mnRevolution.value_or(0); |
2151 | 10.3k | mpCustomShapePropertiesPtr->setTextCameraZRotateAngle( nTextCameraZRotation / 60000 ); |
2152 | | |
2153 | | // TextPreRotateAngle. Text rotates inside the text area. Might be used for diagram layout 'upr' and 'grav'. |
2154 | 10.3k | sal_Int32 nTextPreRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moTextPreRotation.value_or( 0 ) ); |
2155 | | |
2156 | 10.3k | nTextPreRotateAngle -= getDiagramRotation(); // Use of mnDiagramRotation is unclear. It seems to be always 0 here. |
2157 | | |
2158 | | // TextRotateAngle. The text area rotates. |
2159 | 10.3k | sal_Int32 nTextAreaRotateAngle = getTextBody()->getTextProperties().moTextAreaRotation.value_or(0); |
2160 | 10.3k | if (getTextBody()->getTextProperties().moUpright) |
2161 | 96 | { |
2162 | | // When upright is set, any text area transformation and shape rotation is ignored |
2163 | | // in MS Office. To simulate this behaviour, we rotate the text area into the |
2164 | | // opposite direction of the shape rotation by as much as the shape was rotated |
2165 | | // and so compensate the shape rotation, which is added in rendering. |
2166 | 96 | nTextAreaRotateAngle = -getRotation(); |
2167 | | // If 45° <= shape rotation < 135° or 225° <= shape rotation < 315°, |
2168 | | // then MS Office adds an additional 90° rotation to the text area. |
2169 | 96 | const sal_Int32 nDeg(getRotation() / 60000); |
2170 | 96 | if ((nDeg >= 45 && nDeg < 135) || (nDeg >= 225 && nDeg < 315)) |
2171 | 2 | { |
2172 | 2 | nTextAreaRotateAngle += 5400000; |
2173 | 2 | nTextPreRotateAngle -= 5400000; // compensate the additional text area rotation |
2174 | 2 | } |
2175 | 96 | putPropertyToGrabBag(u"Upright"_ustr, Any(true)); |
2176 | 96 | } |
2177 | | /* OOX measures text rotation clockwise in 1/60000th degrees, |
2178 | | relative to the containing shape. set*Angle wants degrees counter-clockwise. */ |
2179 | 10.3k | mpCustomShapePropertiesPtr->setTextPreRotateAngle(-nTextPreRotateAngle / 60000); |
2180 | 10.3k | if (nTextAreaRotateAngle != 0) |
2181 | 68 | mpCustomShapePropertiesPtr->setTextAreaRotateAngle(-nTextAreaRotateAngle / 60000); |
2182 | | |
2183 | 10.3k | auto sHorzOverflow = getTextBody()->getTextProperties().msHorzOverflow; |
2184 | 10.3k | if (!sHorzOverflow.isEmpty()) |
2185 | 178 | putPropertyToGrabBag(u"horzOverflow"_ustr, uno::Any(getTextBody()->getTextProperties().msHorzOverflow)); |
2186 | 10.3k | if (XML_ellipsis == getTextBody()->getTextProperties().moVertOverflow) |
2187 | 0 | putPropertyToGrabBag(u"vertOverflow"_ustr, uno::Any(u"ellipsis"_ustr)); |
2188 | 10.3k | } |
2189 | | |
2190 | | // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks |
2191 | | // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs |
2192 | 18.9k | SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName << "'"); |
2193 | 18.9k | SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName << "'"); |
2194 | | |
2195 | 18.9k | mpCustomShapePropertiesPtr->pushToPropSet(xSet, maSize); |
2196 | | |
2197 | | // Consider WordArt |
2198 | 18.9k | if (mpTextBody && !mpTextBody->getTextProperties().msPrst.isEmpty() |
2199 | 1.08k | && mpTextBody->getTextProperties().msPrst != u"textNoShape") |
2200 | 0 | { |
2201 | 0 | bool bFromWordArt(aShapeProps.hasProperty(PROP_FromWordArt) |
2202 | 0 | ? aShapeProps.getProperty(PROP_FromWordArt).get<bool>() |
2203 | 0 | : false); |
2204 | 0 | FontworkHelpers::putCustomShapeIntoTextPathMode( |
2205 | 0 | mxShape, mpCustomShapePropertiesPtr, mpTextBody->getTextProperties().msPrst, |
2206 | 0 | bFromWordArt); |
2207 | 0 | } |
2208 | 18.9k | } |
2209 | 45.1k | else if( getTextBody() ) |
2210 | 38.9k | getTextBody()->getTextProperties().pushVertSimulation(); |
2211 | | |
2212 | | // tdf#133037: a bit hackish: force Shape to rotate in the opposite direction the camera would rotate |
2213 | 64.0k | PropertySet aPropertySet(mxShape); |
2214 | 64.0k | if ( !bUseRotationTransform && (nShapeRotateInclCamera !=0) ) |
2215 | 192 | { |
2216 | 192 | Degree100 nAngle(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera)); |
2217 | 192 | aPropertySet.setAnyProperty(PROP_RotateAngle, Any( sal_Int32(nAngle))); |
2218 | 192 | aPropertySet.setAnyProperty( PROP_HoriOrientPosition, Any( maPosition.X ) ); |
2219 | 192 | aPropertySet.setAnyProperty( PROP_VertOrientPosition, Any( maPosition.Y ) ); |
2220 | 192 | } |
2221 | | |
2222 | | // Make sure to not set text to placeholders. Doing it here would eventually call |
2223 | | // SvxTextEditSourceImpl::UpdateData, SdrObject::SetEmptyPresObj(false), and that |
2224 | | // would make the object behave like a standard outline object. |
2225 | | // TODO/FIXME: support custom prompt text in placeholders. |
2226 | 64.0k | if (rServiceName == "com.sun.star.presentation.GraphicObjectShape") |
2227 | 0 | mpTextBody.reset(); |
2228 | | |
2229 | | // in some cases, we don't have any text body. |
2230 | 64.0k | if( mpTextBody && ( !pPlaceholder || !mpTextBody->isEmpty() ) ) |
2231 | 38.4k | { |
2232 | 38.4k | Reference < XText > xText( mxShape, UNO_QUERY ); |
2233 | 38.4k | if ( xText.is() ) // not every shape is supporting an XText interface (e.g. GroupShape) |
2234 | 38.4k | { |
2235 | 38.4k | TextCharacterProperties aCharStyleProperties; |
2236 | 38.4k | if( const ShapeStyleRef* pFontRef = getShapeStyleRef( XML_fontRef ) ) |
2237 | 1.40k | { |
2238 | 1.40k | if( pFontRef->mnThemedIdx != 0 ) |
2239 | 1.40k | { |
2240 | 1.40k | if( pTheme ) |
2241 | 1.31k | if( const TextCharacterProperties* pCharProps = pTheme->getFontStyle( pFontRef->mnThemedIdx ) ) |
2242 | 825 | aCharStyleProperties.assignUsed( *pCharProps ); |
2243 | 1.40k | SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color"); |
2244 | 1.40k | if ( pFontRef->maPhClr.isUsed() ) |
2245 | 1.40k | { |
2246 | 1.40k | aCharStyleProperties.maFillProperties.maFillColor = pFontRef->maPhClr; |
2247 | 1.40k | aCharStyleProperties.maFillProperties.moFillType = XML_solidFill; |
2248 | 1.40k | } |
2249 | 1.40k | } |
2250 | 1.40k | } |
2251 | 38.4k | xText->setString(u""_ustr); |
2252 | 38.4k | Reference < XTextCursor > xAt = xText->createTextCursor(); |
2253 | 38.4k | getTextBody()->insertAt( rFilterBase, xText, xAt, aCharStyleProperties, mpMasterTextListStyle ); |
2254 | | |
2255 | 38.4k | const TextParagraphVector& rParagraphs = getTextBody()->getParagraphs(); |
2256 | 38.4k | if (!rParagraphs.empty()) |
2257 | 38.1k | { |
2258 | 38.1k | const std::shared_ptr<TextParagraph>& pParagraph = rParagraphs[0]; |
2259 | 38.1k | if (pParagraph->getProperties().getParaAdjust()) |
2260 | 8.89k | { |
2261 | 8.89k | style::ParagraphAdjust eAdjust = *pParagraph->getProperties().getParaAdjust(); |
2262 | 8.89k | if (eAdjust == style::ParagraphAdjust_CENTER) |
2263 | 6.68k | { |
2264 | | // If the first paragraph is centered, then set the para adjustment of |
2265 | | // the shape itself to centered as well. |
2266 | 6.68k | aPropertySet.setAnyProperty(PROP_ParaAdjust, uno::Any(eAdjust)); |
2267 | 6.68k | } |
2268 | 8.89k | } |
2269 | | |
2270 | | // tdf#144092 For empty textboxes push character styles & |
2271 | | // endParaRPr into the Shape's properties |
2272 | 38.1k | if (rParagraphs.size() == 1 && pParagraph->getRuns().empty()) |
2273 | 9.77k | { |
2274 | 9.77k | TextCharacterProperties aTextCharacterProps{ pParagraph->getCharacterStyle( |
2275 | 9.77k | aCharStyleProperties, *mpMasterTextListStyle, |
2276 | 9.77k | getTextBody()->getTextListStyle()) }; |
2277 | 9.77k | aTextCharacterProps.assignUsed(pParagraph->getEndProperties()); |
2278 | 9.77k | aTextCharacterProps.pushToPropSet(aPropertySet, rFilterBase); |
2279 | 9.77k | } |
2280 | 38.1k | } |
2281 | | |
2282 | | // MS Office has e.g. fill and stroke of WordArt in the character properties, |
2283 | | // LibreOffice uses shape properties. |
2284 | 38.4k | if (!mpTextBody->getTextProperties().msPrst.isEmpty() |
2285 | 1.61k | && mpTextBody->getTextProperties().msPrst != u"textNoShape") |
2286 | 0 | { |
2287 | 0 | lcl_copyCharPropsToShape(mxShape, mpTextBody, rFilterBase); |
2288 | 0 | } |
2289 | 38.4k | } |
2290 | 38.4k | } |
2291 | 25.6k | else if (mpTextBody && aServiceName == "com.sun.star.presentation.OutlinerShape" |
2292 | 4.97k | && mpMasterTextListStyle && !bPlaceholderWithCustomPrompt) |
2293 | 4.97k | { |
2294 | | // If mpTextBody is not empty, then the insertAt() above inserts formatted text. If it's |
2295 | | // empty, then we format the existing text of the outliner shape here. |
2296 | 4.97k | PushMasterTextListStyleToMasterShapeParagraphs(*mpMasterTextListStyle, mxShape); |
2297 | 4.97k | } |
2298 | 20.6k | else if (getIsTextBox()) |
2299 | 324 | { |
2300 | | // No drawingML text, but WPS text is expected: save the theme |
2301 | | // character color on the shape, then. |
2302 | 324 | if(const ShapeStyleRef* pFontRef = getShapeStyleRef(XML_fontRef)) |
2303 | 172 | { |
2304 | 172 | ::Color nCharColor = pFontRef->maPhClr.getColor(rGraphicHelper); |
2305 | 172 | aPropertySet.setAnyProperty(PROP_CharColor, uno::Any(nCharColor)); |
2306 | 172 | } |
2307 | 324 | } |
2308 | | |
2309 | | // Set glow effect properties |
2310 | 64.0k | if (aEffectProperties.maGlow.moGlowRad.has_value() |
2311 | 12 | && aServiceName != "com.sun.star.drawing.GroupShape") |
2312 | 12 | { |
2313 | 12 | uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); |
2314 | 12 | propertySet->setPropertyValue(u"GlowEffectRadius"_ustr, Any(convertEmuToHmm(aEffectProperties.maGlow.moGlowRad.value()))); |
2315 | 12 | propertySet->setPropertyValue(u"GlowEffectColor"_ustr, Any(aEffectProperties.maGlow.moGlowColor.getColor(rGraphicHelper))); |
2316 | 12 | propertySet->setPropertyValue(u"GlowEffectTransparency"_ustr, Any(aEffectProperties.maGlow.moGlowColor.getTransparency())); |
2317 | 12 | } |
2318 | | |
2319 | | // Set soft edge effect properties |
2320 | 64.0k | if (aEffectProperties.maSoftEdge.moRad.has_value()) |
2321 | 0 | { |
2322 | 0 | uno::Reference<beans::XPropertySet> propertySet(mxShape, uno::UNO_QUERY); |
2323 | 0 | propertySet->setPropertyValue( |
2324 | 0 | u"SoftEdgeRadius"_ustr, Any(convertEmuToHmm(aEffectProperties.maSoftEdge.moRad.value()))); |
2325 | 0 | } |
2326 | | |
2327 | | // Set text glow effect for shapes |
2328 | 64.0k | if (mpTextBody && (!pPlaceholder || !mpTextBody->isEmpty())) |
2329 | 38.4k | { |
2330 | 38.4k | const TextParagraphVector& rParagraphs = mpTextBody->getParagraphs(); |
2331 | 38.4k | if (!rParagraphs.empty()) |
2332 | 38.1k | { |
2333 | 38.1k | EffectProperties aTextEffectProperties; |
2334 | 93.4k | for (TextParagraphVector::const_iterator aPIt = rParagraphs.begin(), aPEnd = rParagraphs.end(); aPIt != aPEnd; ++aPIt) |
2335 | 55.2k | { |
2336 | 55.2k | const TextParagraph& rTextPara = **aPIt; |
2337 | 55.2k | const TextCharacterProperties & rParaProps = rTextPara.getProperties().getTextCharacterProperties(); |
2338 | 55.2k | if (rParaProps.getEffectProperties().maGlow.moGlowRad.has_value()) |
2339 | 0 | { |
2340 | 0 | aTextEffectProperties.assignUsed(rParaProps.getEffectProperties()); |
2341 | 0 | goto found; |
2342 | 0 | } |
2343 | 55.2k | else |
2344 | 55.2k | { |
2345 | 114k | for (TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt) |
2346 | 59.2k | { |
2347 | 59.2k | const TextRun& rTextRun = **aRIt; |
2348 | 59.2k | const TextCharacterProperties& rRunrops = rTextRun.getTextCharacterProperties(); |
2349 | 59.2k | if (rRunrops.getEffectProperties().maGlow.moGlowRad.has_value()) |
2350 | 0 | { |
2351 | 0 | aTextEffectProperties.assignUsed(rRunrops.getEffectProperties()); |
2352 | 0 | goto found; |
2353 | 0 | } |
2354 | 59.2k | } |
2355 | 55.2k | } |
2356 | 55.2k | } |
2357 | | |
2358 | 38.1k | found: |
2359 | 38.1k | if (aTextEffectProperties.maGlow.moGlowRad.has_value()) |
2360 | 0 | { |
2361 | 0 | xSet->setPropertyValue(u"GlowTextEffectRadius"_ustr, |
2362 | 0 | uno::Any(convertEmuToHmm(aTextEffectProperties.maGlow.moGlowRad.value()))); |
2363 | 0 | xSet->setPropertyValue(u"GlowTextEffectColor"_ustr, |
2364 | 0 | uno::Any(aTextEffectProperties.maGlow.moGlowColor.getColor(rGraphicHelper))); |
2365 | 0 | xSet->setPropertyValue(u"GlowTextEffectTransparency"_ustr, |
2366 | 0 | uno::Any(aTextEffectProperties.maGlow.moGlowColor.getTransparency())); |
2367 | 0 | } |
2368 | 38.1k | } |
2369 | 38.4k | } |
2370 | | |
2371 | | // Set the stroke and fill-color properties of the OLE shape |
2372 | 64.0k | if (aServiceName == "com.sun.star.drawing.OLE2Shape" && mxOleObjectInfo |
2373 | 0 | && !mxOleObjectInfo->maShapeId.isEmpty()) |
2374 | 0 | if (::oox::vml::Drawing* pVmlDrawing = rFilterBase.getVmlDrawing()) |
2375 | 0 | if (const ::oox::vml::ShapeBase* pVmlShape |
2376 | 0 | = pVmlDrawing->getShapes().getShapeById(mxOleObjectInfo->maShapeId)) |
2377 | 0 | { |
2378 | | // Apply stroke props from the type model of the related VML shape. |
2379 | 0 | ShapePropertyMap aPropMap(rFilterBase.getModelObjectHelper()); |
2380 | 0 | pVmlShape->getTypeModel().maStrokeModel.pushToPropMap( |
2381 | 0 | aPropMap, rFilterBase.getGraphicHelper()); |
2382 | | // And, fill-color properties as well... |
2383 | 0 | pVmlShape->getTypeModel().maFillModel.pushToPropMap( |
2384 | 0 | aPropMap, rFilterBase.getGraphicHelper()); |
2385 | 0 | PropertySet(xSet).setProperties(aPropMap); |
2386 | 0 | } |
2387 | 64.0k | } |
2388 | | |
2389 | 64.0k | if (mxShape.is()) |
2390 | 64.0k | { |
2391 | 64.0k | finalizeXShape( rFilterBase, rxShapes ); |
2392 | | |
2393 | 64.0k | if (mpTextBody) |
2394 | 49.2k | { |
2395 | | // tdf#151518. The method readjustTextDistances is fix for tdf#148321, but conflicts with |
2396 | | // text position in some of the SmartArt types in Writer. So exclude Writer here. |
2397 | 49.2k | OUString sDocumentService; |
2398 | 49.2k | rFilterBase.getMediaDescriptor()[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] >>= sDocumentService; |
2399 | 49.2k | if (sDocumentService != u"com.sun.star.text.TextDocument") |
2400 | 49.2k | mpTextBody->getTextProperties().readjustTextDistances(mxShape); |
2401 | | |
2402 | | // tdf#156857: ooxml files can have shape size with spAutoFit=true and the first priority of |
2403 | | // shape size is the fix size even if TextAutoGrowHeight is true. |
2404 | 49.2k | bool bAutoHeight = false; |
2405 | 49.2k | Reference< XPropertySetInfo > xSetInfo(xSet->getPropertySetInfo()); |
2406 | 49.2k | const OUString& rPropName = PropertyMap::getPropertyName(PROP_TextAutoGrowHeight); |
2407 | 49.2k | if (xSetInfo.is() && xSetInfo->hasPropertyByName(rPropName)) |
2408 | 49.2k | { |
2409 | 49.2k | uno::Any aTextAutoGrowHeight = xSet->getPropertyValue(u"TextAutoGrowHeight"_ustr); |
2410 | 49.2k | aTextAutoGrowHeight >>= bAutoHeight; |
2411 | 49.2k | } |
2412 | | |
2413 | 49.2k | SdrObject* pShape = SdrObject::getSdrObjectFromXShape(mxShape); |
2414 | 49.2k | if (pShape && bAutoHeight) |
2415 | 409 | { |
2416 | 409 | tools::Rectangle aAutoSize = pShape->GetLogicRect(); |
2417 | | // little tolerance same as in \svx\source\svdraw\svdoashp.cxx:AdjustTextFrameWidthAndHeight |
2418 | 409 | if (!aOrigSize.IsEmpty() && (std::abs(aOrigSize.GetHeight() - aAutoSize.GetHeight()) > 1 || |
2419 | 409 | std::abs(aOrigSize.GetWidth() - aAutoSize.GetWidth()) > 1)) |
2420 | 0 | { |
2421 | 0 | pShape->NbcSetLogicRect(aOrigSize, false); |
2422 | 0 | } |
2423 | 409 | } |
2424 | 49.2k | } |
2425 | 64.0k | } |
2426 | 64.0k | return mxShape; |
2427 | 64.0k | } |
2428 | | |
2429 | | void Shape::keepDiagramDrawing(XmlFilterBase& rFilterBase, const OUString& rFragmentPath) |
2430 | 30 | { |
2431 | 30 | DiagramHelper_oox* pAdvancedDiagramHelper(getDiagramHelper()); |
2432 | 30 | if (nullptr == pAdvancedDiagramHelper) |
2433 | 0 | return; |
2434 | | |
2435 | 30 | pAdvancedDiagramHelper->setOOXDomValue( |
2436 | 30 | svx::diagram::DomMapFlag::OOXDrawing, |
2437 | 30 | uno::Any(rFilterBase.importFragment(rFragmentPath))); |
2438 | 30 | pAdvancedDiagramHelper->setOOXDomValue( |
2439 | 30 | svx::diagram::DomMapFlag::OOXDrawingImageRels, |
2440 | 30 | uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"image"))); |
2441 | 30 | pAdvancedDiagramHelper->setOOXDomValue( |
2442 | 30 | svx::diagram::DomMapFlag::OOXDrawingHlinkRels, |
2443 | 30 | uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"hlink"))); |
2444 | 30 | } |
2445 | | |
2446 | | void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase) |
2447 | 303 | { |
2448 | 303 | try |
2449 | 303 | { |
2450 | 303 | Reference<XPropertySet> xSet(mxShape, UNO_QUERY_THROW); |
2451 | | |
2452 | 303 | xSet->setPropertyValue(u"MoveProtect"_ustr, Any(true)); |
2453 | 303 | xSet->setPropertyValue(u"SizeProtect"_ustr, Any(true)); |
2454 | | |
2455 | | // Replace existing shapes with a new Graphic Object rendered |
2456 | | // from them |
2457 | 303 | Reference<XShape> xShape(renderDiagramToGraphic(rFilterBase)); |
2458 | 303 | Reference<XShapes> xShapes(mxShape, UNO_QUERY_THROW); |
2459 | 303 | tools::Rectangle aBackgroundRect |
2460 | 303 | = SdrObject::getSdrObjectFromXShape( |
2461 | 303 | Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW)) |
2462 | 303 | ->GetLogicRect(); |
2463 | 1.09k | while (xShapes->hasElements()) |
2464 | 789 | xShapes->remove(Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW)); |
2465 | 303 | xShapes->add(xShape); |
2466 | 303 | SdrObject::getSdrObjectFromXShape( |
2467 | 303 | Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW)) |
2468 | 303 | ->NbcSetLogicRect(aBackgroundRect); |
2469 | 303 | } |
2470 | 303 | catch (const Exception&) |
2471 | 303 | { |
2472 | 154 | TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile"); |
2473 | 154 | } |
2474 | 303 | } |
2475 | | |
2476 | | Reference < XShape > Shape::renderDiagramToGraphic( XmlFilterBase const & rFilterBase ) |
2477 | 303 | { |
2478 | 303 | Reference< XShape > xShape; |
2479 | | |
2480 | 303 | try |
2481 | 303 | { |
2482 | 303 | if( nullptr != getDiagramHelper() ) |
2483 | | // if( !maDiagramDoms.hasElements() ) |
2484 | 0 | return xShape; |
2485 | | |
2486 | | // Stream in which to place the rendered shape |
2487 | 303 | SvMemoryStream aTempStream; |
2488 | 303 | Reference < io::XStream > xStream( new utl::OStreamWrapper( aTempStream ) ); |
2489 | 303 | Reference < io::XOutputStream > xOutputStream( xStream->getOutputStream() ); |
2490 | | |
2491 | | // Size of the rendering |
2492 | 303 | awt::Size aActualSize = mxShape->getSize(); |
2493 | 303 | Size aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM))); |
2494 | 303 | double fPixelsPer100thmm = static_cast < double > ( aResolution.Width() ) / 100000.0; |
2495 | 303 | awt::Size aSize( static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Width ) + 0.5 ), |
2496 | 303 | static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Height ) + 0.5 ) ); |
2497 | | |
2498 | 303 | Sequence< PropertyValue > aFilterData{ |
2499 | 303 | comphelper::makePropertyValue(u"PixelWidth"_ustr, aSize.Width), |
2500 | 303 | comphelper::makePropertyValue(u"PixelHeight"_ustr, aSize.Height), |
2501 | 303 | comphelper::makePropertyValue(u"LogicalWidth"_ustr, aActualSize.Width), |
2502 | 303 | comphelper::makePropertyValue(u"LogicalHeight"_ustr, aActualSize.Height) |
2503 | 303 | }; |
2504 | | |
2505 | 303 | Sequence < PropertyValue > aDescriptor{ |
2506 | 303 | comphelper::makePropertyValue(u"OutputStream"_ustr, xOutputStream), |
2507 | 303 | comphelper::makePropertyValue(u"FilterName"_ustr, u"SVM"_ustr), // Rendering format |
2508 | 303 | comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData) |
2509 | 303 | }; |
2510 | | |
2511 | 303 | Reference < lang::XComponent > xSourceDoc( mxShape, UNO_QUERY_THROW ); |
2512 | 303 | Reference < XGraphicExportFilter > xGraphicExporter = GraphicExportFilter::create( rFilterBase.getComponentContext() ); |
2513 | 303 | xGraphicExporter->setSourceDocument( xSourceDoc ); |
2514 | 303 | xGraphicExporter->filter( aDescriptor ); |
2515 | | |
2516 | 303 | aTempStream.Seek( STREAM_SEEK_TO_BEGIN ); |
2517 | | |
2518 | 303 | Graphic aGraphic; |
2519 | 303 | GraphicFilter aFilter; |
2520 | 303 | if ( aFilter.ImportGraphic( aGraphic, u"", aTempStream, GRFILTER_FORMAT_NOTFOUND, nullptr, GraphicFilterImportFlags::NONE ) != ERRCODE_NONE ) |
2521 | 0 | { |
2522 | 0 | SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" ); |
2523 | 0 | return xShape; |
2524 | 0 | } |
2525 | | |
2526 | 303 | Reference < graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() ); |
2527 | 303 | Reference < lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); |
2528 | 303 | xShape.set( xServiceFact->createInstance( u"com.sun.star.drawing.GraphicObjectShape"_ustr ), UNO_QUERY_THROW ); |
2529 | 303 | Reference < XPropertySet > xPropSet( xShape, UNO_QUERY_THROW ); |
2530 | 303 | xPropSet->setPropertyValue( u"Graphic"_ustr, Any( xGraphic ) ); |
2531 | 303 | xPropSet->setPropertyValue( u"MoveProtect"_ustr, Any( true ) ); |
2532 | 303 | xPropSet->setPropertyValue( u"SizeProtect"_ustr, Any( true ) ); |
2533 | 303 | xPropSet->setPropertyValue( u"Name"_ustr, Any( u"RenderedShapes"_ustr ) ); |
2534 | 303 | } |
2535 | 303 | catch( const Exception& ) |
2536 | 303 | { |
2537 | 0 | TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" ); |
2538 | 0 | } |
2539 | | |
2540 | 303 | return xShape; |
2541 | 303 | } |
2542 | | |
2543 | | void Shape::setTextBody(const TextBodyPtr & pTextBody) |
2544 | 89.8k | { |
2545 | 89.8k | mpTextBody = pTextBody; |
2546 | 89.8k | } |
2547 | | |
2548 | | void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle ) |
2549 | 94.6k | { |
2550 | 94.6k | SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId << "'"); |
2551 | | |
2552 | 94.6k | mpMasterTextListStyle = pMasterTextListStyle; |
2553 | 94.6k | } |
2554 | | |
2555 | | OUString Shape::finalizeServiceName( XmlFilterBase& rFilter, const OUString& rServiceName, const awt::Rectangle& rShapeRect ) |
2556 | 64.0k | { |
2557 | 64.0k | OUString aServiceName = rServiceName; |
2558 | 64.0k | switch( meFrameType ) |
2559 | 64.0k | { |
2560 | 0 | case FRAMETYPE_OLEOBJECT: |
2561 | 0 | { |
2562 | 0 | awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height ); |
2563 | 0 | if( rFilter.getOleObjectHelper().importOleObject( maShapeProperties, *mxOleObjectInfo, aOleSize ) ) |
2564 | 0 | aServiceName = "com.sun.star.drawing.OLE2Shape"; |
2565 | | |
2566 | | // get the path to the representation graphic |
2567 | 0 | OUString aGraphicPath; |
2568 | 0 | if( !mxOleObjectInfo->maShapeId.isEmpty() ) |
2569 | 0 | if( ::oox::vml::Drawing* pVmlDrawing = rFilter.getVmlDrawing() ) |
2570 | 0 | if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId ) ) |
2571 | 0 | aGraphicPath = pVmlShape->getGraphicPath(); |
2572 | | |
2573 | | // import and store the graphic |
2574 | 0 | if( !aGraphicPath.isEmpty() ) |
2575 | 0 | { |
2576 | | // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF) |
2577 | 0 | WmfExternal aExtHeader; |
2578 | 0 | aExtHeader.mapMode = 8; // MM_ANISOTROPIC |
2579 | 0 | aExtHeader.xExt = rShapeRect.Width; |
2580 | 0 | aExtHeader.yExt = rShapeRect.Height; |
2581 | |
|
2582 | 0 | Reference< graphic::XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath, &aExtHeader ); |
2583 | 0 | if( xGraphic.is() ) |
2584 | 0 | maShapeProperties.setProperty(PROP_Graphic, xGraphic); |
2585 | 0 | } |
2586 | 0 | } |
2587 | 0 | break; |
2588 | | |
2589 | 64.0k | default:; |
2590 | 64.0k | } |
2591 | 64.0k | return aServiceName; |
2592 | 64.0k | } |
2593 | | |
2594 | | void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes ) |
2595 | 64.0k | { |
2596 | 64.0k | switch( meFrameType ) |
2597 | 64.0k | { |
2598 | 430 | case FRAMETYPE_CHART: |
2599 | 430 | { |
2600 | 430 | OSL_ENSURE( !mxChartShapeInfo->maFragmentPath.isEmpty(), "Shape::finalizeXShape - missing chart fragment" ); |
2601 | 430 | if( mxShape.is() && !mxChartShapeInfo->maFragmentPath.isEmpty() ) try |
2602 | 397 | { |
2603 | | // set the chart2 OLE class ID at the OLE shape |
2604 | 397 | PropertySet aShapeProp( mxShape ); |
2605 | 397 | aShapeProp.setProperty( PROP_CLSID, u"12dcae26-281f-416f-a234-c3086127382e"_ustr ); |
2606 | | |
2607 | | // get the XModel interface of the embedded object from the OLE shape |
2608 | 397 | Reference< frame::XModel > xDocModel; |
2609 | 397 | aShapeProp.getProperty( xDocModel, PROP_Model ); |
2610 | 397 | Reference< chart2::XChartDocument > xChartDoc( xDocModel, UNO_QUERY_THROW ); |
2611 | | |
2612 | | // load the chart data from the XML fragment |
2613 | | #if ENABLE_WASM_STRIP_CHART |
2614 | | (void) rFilter; |
2615 | | (void) rxShapes; |
2616 | | #else |
2617 | | // WASM_CHART change |
2618 | | // TODO: Instead of using convertFromModel an alternative may be |
2619 | | // added to convert not to Chart/OLE SdrObejct, but to GraphicObject |
2620 | | // with the Chart visualization. There should be a preview available |
2621 | | // in the imported chart data |
2622 | 397 | bool bMSO2007Doc = rFilter.isMSO2007Document(); |
2623 | 397 | chart::ChartSpaceModel aModel(bMSO2007Doc); |
2624 | 397 | oox::ppt::PowerPointImport* pPowerPointImport |
2625 | 397 | = dynamic_cast<oox::ppt::PowerPointImport*>(&rFilter); |
2626 | | |
2627 | 397 | ClrMapPtr pClrMap; // The original color map |
2628 | 397 | if (pPowerPointImport) |
2629 | 0 | { |
2630 | | // Use a copy of current color map, which the fragment may override locally |
2631 | 0 | pClrMap = pPowerPointImport->getActualSlidePersist()->getClrMap(); |
2632 | 0 | aModel.mpClrMap = pClrMap ? std::make_shared<ClrMap>(*pClrMap) |
2633 | 0 | : std::make_shared<ClrMap>(); |
2634 | 0 | pPowerPointImport->getActualSlidePersist()->setClrMap(aModel.mpClrMap); |
2635 | 0 | } |
2636 | | |
2637 | 397 | rtl::Reference<chart::ChartSpaceFragment> pChartSpaceFragment = new chart::ChartSpaceFragment( |
2638 | 397 | rFilter, mxChartShapeInfo->maFragmentPath, aModel ); |
2639 | 397 | rFilter.importFragment( pChartSpaceFragment ); |
2640 | | |
2641 | | // Import styles file. |
2642 | | // Create the styles path from the path to the chart*.xml file |
2643 | 397 | sal_Int32 nLastSlash = mxChartShapeInfo->maFragmentPath.lastIndexOf('/'); |
2644 | 397 | const sal_Unicode *pFPath = mxChartShapeInfo->maFragmentPath.getStr(); |
2645 | 397 | OUString sStylePath(pFPath, nLastSlash + 1); |
2646 | 397 | const OUString sFullPath(pFPath); |
2647 | 397 | sStylePath += u"style"_ustr; |
2648 | 397 | OUString sChartFName(sFullPath.copy(nLastSlash + 1, sFullPath.getLength() - nLastSlash - 1)); |
2649 | 397 | OUString sTail; |
2650 | | // Verify that the path is the way we expect it, and extract the |
2651 | | // end bit. Don't put the startsWith() call inside an assert, |
2652 | | // because we don't want it optimized away. |
2653 | 397 | const bool bWellFormed = sChartFName.startsWith(std::u16string_view(u"chart"), &sTail); |
2654 | 397 | if (!bWellFormed) { |
2655 | 0 | assert(false); |
2656 | 0 | } |
2657 | | // We should have something of the form 'chart1234.xml'. We |
2658 | | // want to get the numeric ('1234') part, since it should be |
2659 | | // the same for the style file. |
2660 | 397 | sal_Int32 nPeriod = sTail.indexOf('.'); |
2661 | 397 | OUString sNumber(sTail.copy(0, nPeriod)); |
2662 | | |
2663 | 397 | sStylePath += sNumber; |
2664 | 397 | sStylePath += u".xml"_ustr; |
2665 | | |
2666 | 397 | chart::StyleModel aStyleModel; |
2667 | 397 | rtl::Reference<chart::StyleFragment> pStyleFragment = new chart::StyleFragment( |
2668 | 397 | rFilter, sStylePath, aStyleModel ); |
2669 | 397 | rFilter.importFragment( pStyleFragment ); |
2670 | | |
2671 | | // Import colors file. |
2672 | 397 | OUString sColorPath(pFPath, nLastSlash + 1); |
2673 | 397 | sColorPath += u"colors"_ustr; |
2674 | 397 | sChartFName = sFullPath.copy(nLastSlash + 1, sFullPath.getLength() - nLastSlash - 1); |
2675 | 397 | sColorPath += sNumber; |
2676 | 397 | sColorPath += u".xml"_ustr; |
2677 | | |
2678 | 397 | chart::ColorStyleModel aColorsModel; |
2679 | 397 | rtl::Reference<chart::ColorsFragment> pColorsFragment = |
2680 | 397 | new chart::ColorsFragment( rFilter, sColorPath, aColorsModel ); |
2681 | 397 | rFilter.importFragment( pColorsFragment ); |
2682 | | |
2683 | | |
2684 | | // The original theme. |
2685 | 397 | ThemePtr pTheme; |
2686 | 397 | const OUString aThemeOverrideFragmentPath( pChartSpaceFragment-> |
2687 | 397 | getFragmentPathFromFirstTypeFromOfficeDoc(u"themeOverride") ); |
2688 | | |
2689 | 397 | if (!aThemeOverrideFragmentPath.isEmpty() && pPowerPointImport) |
2690 | 0 | { |
2691 | | // Handle theme override. |
2692 | 0 | uno::Reference< xml::sax::XFastSAXSerializable > xDoc( |
2693 | 0 | rFilter.importFragment(aThemeOverrideFragmentPath), uno::UNO_QUERY_THROW); |
2694 | 0 | pTheme = pPowerPointImport->getActualSlidePersist()->getTheme(); |
2695 | 0 | auto pThemeOverride = std::make_shared<Theme>(*pTheme); |
2696 | 0 | rFilter.importFragment( |
2697 | 0 | new ThemeOverrideFragmentHandler(rFilter, aThemeOverrideFragmentPath, *pThemeOverride, *pThemeOverride->getTheme()), |
2698 | 0 | xDoc); |
2699 | 0 | pPowerPointImport->getActualSlidePersist()->setTheme(pThemeOverride); |
2700 | 0 | } |
2701 | | |
2702 | | // convert imported chart model to chart document |
2703 | 397 | Reference< drawing::XShapes > xExternalPage; |
2704 | 397 | if( !mxChartShapeInfo->mbEmbedShapes ) |
2705 | 0 | xExternalPage = rxShapes; |
2706 | | |
2707 | | // There are several calls to rFilter.getChartConverter() here. |
2708 | | // Doing just one call and storing the result, as in |
2709 | | // chart::ChartConverter *pChartConv = rFilter.getChartConverter(); |
2710 | | // *doesn't work* (tests crash). |
2711 | 397 | if( rFilter.getChartConverter() ) |
2712 | 0 | { |
2713 | 0 | rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() ); |
2714 | 0 | if( !xChartDoc->hasInternalDataProvider() ) |
2715 | 0 | { |
2716 | 0 | Reference< chart2::data::XDataReceiver > xDataRec( xChartDoc, UNO_QUERY ); |
2717 | 0 | Reference< chart2::data::XDataSource > xData = xDataRec->getUsedData(); |
2718 | 0 | if( !xData->getDataSequences().hasElements() || !xData->getDataSequences()[0]->getValues().is() || |
2719 | 0 | !xData->getDataSequences()[0]->getValues()->getData().hasElements() ) |
2720 | 0 | { |
2721 | 0 | rFilter.useInternalChartDataTable( true ); |
2722 | 0 | rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() ); |
2723 | 0 | rFilter.useInternalChartDataTable( false ); |
2724 | 0 | } |
2725 | 0 | } |
2726 | |
|
2727 | 0 | } |
2728 | | |
2729 | | // convert chart style model to docmodel style data |
2730 | 397 | Reference<com::sun::star::chart2::XChartStyle> xStyle = xChartDoc->getStyles(); |
2731 | 397 | oox::drawingml::chart::ChartStyleConverter::convertFromModel(rFilter, aStyleModel, xStyle); |
2732 | | // convert color style model to docmodel colors data |
2733 | 397 | Reference<com::sun::star::chart2::XChartColorStyle> xCStyle = xChartDoc->getColorStyles(); |
2734 | 397 | oox::drawingml::chart::ChartColorStyleConverter::convertFromModel(rFilter, aColorsModel, xCStyle); |
2735 | | |
2736 | 397 | if (pPowerPointImport) |
2737 | 0 | { |
2738 | 0 | if (!aThemeOverrideFragmentPath.isEmpty()) |
2739 | 0 | { |
2740 | | // Restore the original theme. |
2741 | 0 | pPowerPointImport->getActualSlidePersist()->setTheme(pTheme); |
2742 | 0 | } |
2743 | | // Restore the original color map |
2744 | 0 | pPowerPointImport->getActualSlidePersist()->setClrMap(std::move(pClrMap)); |
2745 | 0 | } |
2746 | 397 | #endif |
2747 | 397 | } |
2748 | 397 | catch( Exception& ) |
2749 | 397 | { |
2750 | 397 | } |
2751 | 430 | } |
2752 | 430 | break; |
2753 | | |
2754 | 63.6k | default:; |
2755 | 64.0k | } |
2756 | 64.0k | } |
2757 | | |
2758 | | void Shape::putPropertyToGrabBag( const OUString& sPropertyName, const Any& aPropertyValue ) |
2759 | 76.0k | { |
2760 | 76.0k | PropertyValue aNewProperty; |
2761 | 76.0k | aNewProperty.Name = sPropertyName; |
2762 | 76.0k | aNewProperty.Value = aPropertyValue; |
2763 | 76.0k | putPropertyToGrabBag( aNewProperty ); |
2764 | 76.0k | } |
2765 | | |
2766 | | void Shape::putPropertyToGrabBag( const PropertyValue& pProperty ) |
2767 | 76.0k | { |
2768 | 76.0k | Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); |
2769 | 76.0k | Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); |
2770 | 76.0k | const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; |
2771 | 76.0k | if( mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName ) ) |
2772 | 37.1k | { |
2773 | 37.1k | Sequence< PropertyValue > aGrabBag; |
2774 | 37.1k | xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; |
2775 | | |
2776 | 37.1k | sal_Int32 length = aGrabBag.getLength(); |
2777 | 37.1k | aGrabBag.realloc( length + 1 ); |
2778 | 37.1k | aGrabBag.getArray()[length] = pProperty; |
2779 | | |
2780 | 37.1k | xSet->setPropertyValue( aGrabBagPropName, Any( aGrabBag ) ); |
2781 | 37.1k | } |
2782 | 76.0k | } |
2783 | | |
2784 | | void Shape::putPropertiesToGrabBag( const Sequence< PropertyValue >& aProperties ) |
2785 | 63.4k | { |
2786 | 63.4k | Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); |
2787 | 63.4k | Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); |
2788 | 63.4k | const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; |
2789 | 63.4k | if( !(mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName )) ) |
2790 | 38.9k | return; |
2791 | | |
2792 | | // get existing grab bag |
2793 | 24.5k | Sequence< PropertyValue > aGrabBag; |
2794 | 24.5k | xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; |
2795 | | |
2796 | 24.5k | std::vector<PropertyValue> aVec; |
2797 | 24.5k | aVec.reserve(aProperties.getLength()); |
2798 | | |
2799 | | // put the new items |
2800 | 24.5k | std::transform(aProperties.begin(), aProperties.end(), std::back_inserter(aVec), |
2801 | 87.2k | [](const PropertyValue& rProp) { |
2802 | 87.2k | PropertyValue aProp; |
2803 | 87.2k | aProp.Name = rProp.Name; |
2804 | 87.2k | aProp.Value = rProp.Value; |
2805 | 87.2k | return aProp; |
2806 | 87.2k | }); |
2807 | | |
2808 | | // put it back to the shape |
2809 | 24.5k | xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, aVec) ) ); |
2810 | 24.5k | } |
2811 | | |
2812 | | FillProperties Shape::getActualFillProperties(const Theme* pTheme, const FillProperties* pParentShapeFillProps) const |
2813 | 86.9k | { |
2814 | 86.9k | FillProperties aFillProperties; |
2815 | 86.9k | aFillProperties.moFillType = XML_noFill; |
2816 | | |
2817 | | // Reference shape properties |
2818 | 86.9k | aFillProperties.assignUsed( *mpShapeRefFillPropPtr ); |
2819 | | |
2820 | | // Theme |
2821 | 86.9k | if( pTheme != nullptr ) |
2822 | 61.5k | { |
2823 | 61.5k | if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) ) |
2824 | 3.16k | { |
2825 | 3.16k | if( const FillProperties* pFillProps = pTheme->getFillStyle( pFillRef->mnThemedIdx ) ) |
2826 | 778 | aFillProperties.assignUsed( *pFillProps ); |
2827 | 3.16k | } |
2828 | 61.5k | } |
2829 | | |
2830 | | // Properties specified directly for this shape |
2831 | 86.9k | aFillProperties.assignUsed(getFillProperties()); |
2832 | | |
2833 | | // Parent shape's properties |
2834 | 86.9k | if ( pParentShapeFillProps != nullptr) |
2835 | 64.0k | if( getFillProperties().moFillType.has_value() && getFillProperties().moFillType.value() == XML_grpFill ) |
2836 | 6 | aFillProperties.assignUsed( *pParentShapeFillProps ); |
2837 | | |
2838 | 86.9k | return aFillProperties; |
2839 | 86.9k | } |
2840 | | |
2841 | | LineProperties Shape::getActualLineProperties(const Theme* pTheme) const |
2842 | 86.9k | { |
2843 | 86.9k | LineProperties aLineProperties; |
2844 | 86.9k | aLineProperties.maLineFill.moFillType = XML_noFill; |
2845 | | |
2846 | | // Reference shape properties |
2847 | 86.9k | aLineProperties.assignUsed( *mpShapeRefLinePropPtr ); |
2848 | | |
2849 | | // Theme |
2850 | 86.9k | if( pTheme != nullptr ) |
2851 | 61.5k | { |
2852 | 61.5k | if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) ) |
2853 | 3.16k | { |
2854 | 3.16k | if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) ) |
2855 | 954 | aLineProperties.assignUsed( *pLineProps ); |
2856 | 3.16k | } |
2857 | 61.5k | } |
2858 | | |
2859 | | // Properties specified directly for this shape |
2860 | 86.9k | aLineProperties.assignUsed( getLineProperties() ); |
2861 | | |
2862 | 86.9k | return aLineProperties; |
2863 | 86.9k | } |
2864 | | |
2865 | | EffectProperties Shape::getActualEffectProperties(const Theme* pTheme) const |
2866 | 86.9k | { |
2867 | 86.9k | EffectProperties aEffectProperties; |
2868 | | |
2869 | | // Reference shape properties |
2870 | 86.9k | aEffectProperties.assignUsed( *mpShapeRefEffectPropPtr ); |
2871 | | |
2872 | | // Theme |
2873 | 86.9k | if( pTheme != nullptr ) |
2874 | 61.5k | { |
2875 | 61.5k | if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) ) |
2876 | 3.16k | { |
2877 | 3.16k | if( const EffectProperties* pEffectProps = pTheme->getEffectStyle( pEffectRef->mnThemedIdx ) ) |
2878 | 51 | aEffectProperties.assignUsed( *pEffectProps ); |
2879 | 3.16k | } |
2880 | 61.5k | } |
2881 | | |
2882 | | // Properties specified directly for this shape |
2883 | 86.9k | aEffectProperties.assignUsed ( getEffectProperties() ); |
2884 | | |
2885 | 86.9k | return aEffectProperties; |
2886 | 86.9k | } |
2887 | | |
2888 | | uno::Sequence< uno::Sequence< uno::Any > > Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase& rFilter, const OUString& sFragment, std::u16string_view sType ) |
2889 | 812 | { |
2890 | 812 | uno::Sequence< uno::Sequence< uno::Any > > xRelListTemp; |
2891 | 812 | sal_Int32 counter = 0; |
2892 | | |
2893 | 812 | core::RelationsRef xRels = rFilter.importRelations( sFragment ); |
2894 | 812 | if ( xRels ) |
2895 | 812 | { |
2896 | 812 | if (sType == u"image") |
2897 | 406 | { |
2898 | 406 | core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc(sType); |
2899 | 406 | if (xImageRels) |
2900 | 406 | { |
2901 | 406 | xRelListTemp.realloc(xImageRels->size()); |
2902 | 406 | auto pxRelListTemp = xRelListTemp.getArray(); |
2903 | 406 | for (auto const& imageRel : *xImageRels) |
2904 | 0 | { |
2905 | 0 | uno::Sequence<uno::Any> diagramRelTuple(3); |
2906 | 0 | auto pdiagramRelTuple = diagramRelTuple.getArray(); |
2907 | | // [0] => RID, [1] => InputStream [2] => extension |
2908 | 0 | OUString sRelId = imageRel.second.maId; |
2909 | |
|
2910 | 0 | pdiagramRelTuple[0] <<= sRelId; |
2911 | 0 | OUString sTarget = xImageRels->getFragmentPathFromRelId(sRelId); |
2912 | |
|
2913 | 0 | uno::Reference<io::XInputStream> xImageInputStrm( |
2914 | 0 | rFilter.openInputStream(sTarget), uno::UNO_SET_THROW); |
2915 | 0 | StreamDataSequence dataSeq; |
2916 | 0 | if (rFilter.importBinaryData(dataSeq, sTarget)) |
2917 | 0 | { |
2918 | 0 | pdiagramRelTuple[1] <<= dataSeq; |
2919 | 0 | } |
2920 | |
|
2921 | 0 | pdiagramRelTuple[2] <<= sTarget.copy(sTarget.lastIndexOf(".")); |
2922 | |
|
2923 | 0 | pxRelListTemp[counter] = std::move(diagramRelTuple); |
2924 | 0 | ++counter; |
2925 | 0 | } |
2926 | 406 | } |
2927 | 406 | } |
2928 | 406 | else if (sType == u"hlink") |
2929 | 406 | { |
2930 | | // Hyperlink can be internal or external |
2931 | 406 | core::RelationsRef xSlideRels = xRels->getRelationsFromTypeFromOfficeDoc(u"slide"); |
2932 | 406 | core::RelationsRef xHlinkRels = xRels->getRelationsFromTypeFromOfficeDoc(u"hyperlink"); |
2933 | | |
2934 | 406 | sal_Int32 totalSize |
2935 | 406 | = (xSlideRels ? xSlideRels->size() : 0) + (xHlinkRels ? xHlinkRels->size() : 0); |
2936 | 406 | xRelListTemp.realloc(totalSize); |
2937 | 406 | auto pxRelListTemp = xRelListTemp.getArray(); |
2938 | | |
2939 | | // Helper to create relation tuple |
2940 | 406 | auto addRelation = [&](const auto& rel, const OUString& relType) |
2941 | 406 | { |
2942 | 0 | uno::Sequence<uno::Any> tuple(3); |
2943 | 0 | auto pTuple = tuple.getArray(); |
2944 | 0 | pTuple[0] <<= rel.second.maId; |
2945 | 0 | pTuple[1] <<= rel.second.maTarget; |
2946 | 0 | pTuple[2] <<= relType; |
2947 | 0 | pxRelListTemp[counter++] = std::move(tuple); |
2948 | 0 | }; |
2949 | | |
2950 | 406 | if (xSlideRels) |
2951 | 406 | { |
2952 | 406 | for (auto const& slideRel : *xSlideRels) |
2953 | 0 | addRelation(slideRel, "slide"); |
2954 | 406 | } |
2955 | 406 | if (xHlinkRels) |
2956 | 406 | { |
2957 | 406 | for (auto const& hlinkRel : *xHlinkRels) |
2958 | 0 | addRelation(hlinkRel, "hyperlink"); |
2959 | 406 | } |
2960 | 406 | } |
2961 | 812 | xRelListTemp.realloc(counter); |
2962 | 812 | } |
2963 | 812 | return xRelListTemp; |
2964 | 812 | } |
2965 | | |
2966 | | void Shape::cloneFillProperties() |
2967 | 532 | { |
2968 | 532 | auto pFillProperties = std::make_shared<FillProperties>(); |
2969 | 532 | pFillProperties->assignUsed(*mpFillPropertiesPtr); |
2970 | 532 | mpFillPropertiesPtr = std::move(pFillProperties); |
2971 | 532 | } |
2972 | | } |
2973 | | |
2974 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |