/src/libreoffice/svx/source/svdraw/svdoashp.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 <vcl/bitmap/BitmapShadowFilter.hxx> |
21 | | #include <svx/svdoashp.hxx> |
22 | | #include <svx/unoapi.hxx> |
23 | | #include <com/sun/star/loader/CannotActivateFactoryException.hpp> |
24 | | #include <com/sun/star/drawing/XShape.hpp> |
25 | | #include <com/sun/star/drawing/XCustomShapeEngine.hpp> |
26 | | #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> |
27 | | #include <com/sun/star/beans/PropertyValue.hpp> |
28 | | #include <com/sun/star/awt/Rectangle.hpp> |
29 | | #include <com/sun/star/uno/XComponentContext.hpp> |
30 | | #include <comphelper/processfactory.hxx> |
31 | | #include <comphelper/propertyvalue.hxx> |
32 | | #include <comphelper/sequenceashashmap.hxx> |
33 | | #include <com/sun/star/uno/Sequence.h> |
34 | | #include <tools/helpers.hxx> |
35 | | #include <svx/svddrag.hxx> |
36 | | #include <svx/svddrgmt.hxx> |
37 | | #include <svx/svdmodel.hxx> |
38 | | #include <svx/svdpage.hxx> |
39 | | #include <svx/svditer.hxx> |
40 | | #include <svx/svdobj.hxx> |
41 | | #include <svx/svdtrans.hxx> |
42 | | #include <svx/dialmgr.hxx> |
43 | | #include <svx/strings.hrc> |
44 | | #include <editeng/eeitem.hxx> |
45 | | #include <editeng/editstat.hxx> |
46 | | #include <editeng/adjustitem.hxx> |
47 | | #include <svx/svdoutl.hxx> |
48 | | #include <editeng/outlobj.hxx> |
49 | | #include <svx/sdtfchim.hxx> |
50 | | #include <svx/EnhancedCustomShapeGeometry.hxx> |
51 | | #include <svx/EnhancedCustomShapeTypeNames.hxx> |
52 | | #include <svx/EnhancedCustomShape2d.hxx> |
53 | | #include <com/sun/star/beans/PropertyValues.hpp> |
54 | | #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> |
55 | | #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> |
56 | | #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> |
57 | | #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> |
58 | | #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> |
59 | | #include <editeng/writingmodeitem.hxx> |
60 | | #include <svx/xlineit0.hxx> |
61 | | #include <svx/xlnclit.hxx> |
62 | | #include <sdr/properties/customshapeproperties.hxx> |
63 | | #include <sdr/contact/viewcontactofsdrobjcustomshape.hxx> |
64 | | #include <svx/xlntrit.hxx> |
65 | | #include <svx/xfillit0.hxx> |
66 | | #include <svx/xfltrit.hxx> |
67 | | #include <svx/xflclit.hxx> |
68 | | #include <svx/xflgrit.hxx> |
69 | | #include <svx/xflhtit.hxx> |
70 | | #include <svx/xbtmpit.hxx> |
71 | | #include <vcl/virdev.hxx> |
72 | | #include <svx/svdview.hxx> |
73 | | #include <svx/sdmetitm.hxx> |
74 | | #include <svx/sdprcitm.hxx> |
75 | | #include <svx/sdshitm.hxx> |
76 | | #include <svx/sdsxyitm.hxx> |
77 | | #include <svx/sdtmfitm.hxx> |
78 | | #include <svx/sdasitm.hxx> |
79 | | #include <svx/diagram/IDiagramHelper.hxx> |
80 | | #include <basegfx/polygon/b2dpolypolygontools.hxx> |
81 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
82 | | #include <basegfx/matrix/b2dhommatrixtools.hxx> |
83 | | #include <basegfx/polygon/b2dpolygon.hxx> |
84 | | #include <basegfx/polygon/b2dpolygontools.hxx> |
85 | | #include <basegfx/range/b2drange.hxx> |
86 | | #include <svdobjplusdata.hxx> |
87 | | #include <sal/log.hxx> |
88 | | #include <tools/debug.hxx> |
89 | | #include <o3tl/string_view.hxx> |
90 | | #include "presetooxhandleadjustmentrelations.hxx" |
91 | | #include <editeng/frmdiritem.hxx> |
92 | | #include <EnhancedCustomShapeEngine.hxx> |
93 | | |
94 | | using namespace ::com::sun::star; |
95 | | |
96 | | static void lcl_ShapeSegmentFromBinary( drawing::EnhancedCustomShapeSegment& rSegInfo, sal_uInt16 nSDat ) |
97 | 189k | { |
98 | 189k | switch( nSDat >> 8 ) |
99 | 189k | { |
100 | 46.9k | case 0x00 : |
101 | 46.9k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO; |
102 | 46.9k | rSegInfo.Count = nSDat & 0xff; |
103 | 46.9k | if ( !rSegInfo.Count ) |
104 | 0 | rSegInfo.Count = 1; |
105 | 46.9k | break; |
106 | 2.31k | case 0x20 : |
107 | 2.31k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO; |
108 | 2.31k | rSegInfo.Count = nSDat & 0xff; |
109 | 2.31k | if ( !rSegInfo.Count ) |
110 | 0 | rSegInfo.Count = 1; |
111 | 2.31k | break; |
112 | 26.6k | case 0x40 : |
113 | 26.6k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO; |
114 | 26.6k | rSegInfo.Count = nSDat & 0xff; |
115 | 26.6k | if ( !rSegInfo.Count ) |
116 | 26.6k | rSegInfo.Count = 1; |
117 | 26.6k | break; |
118 | 18.0k | case 0x60 : |
119 | 18.0k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH; |
120 | 18.0k | rSegInfo.Count = 0; |
121 | 18.0k | break; |
122 | 38.3k | case 0x80 : |
123 | 38.3k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH; |
124 | 38.3k | rSegInfo.Count = 0; |
125 | 38.3k | break; |
126 | 0 | case 0xa1 : |
127 | 0 | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO; |
128 | 0 | rSegInfo.Count = ( nSDat & 0xff ) / 3; |
129 | 0 | break; |
130 | 1.19k | case 0xa2 : |
131 | 1.19k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE; |
132 | 1.19k | rSegInfo.Count = ( nSDat & 0xff ) / 3; |
133 | 1.19k | break; |
134 | 519 | case 0xa3 : |
135 | 519 | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO; |
136 | 519 | rSegInfo.Count = ( nSDat & 0xff ) >> 2; |
137 | 519 | break; |
138 | 439 | case 0xa4 : |
139 | 439 | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ARC; |
140 | 439 | rSegInfo.Count = ( nSDat & 0xff ) >> 2; |
141 | 439 | break; |
142 | 810 | case 0xa5 : |
143 | 810 | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO; |
144 | 810 | rSegInfo.Count = ( nSDat & 0xff ) >> 2; |
145 | 810 | break; |
146 | 9.82k | case 0xa6 : |
147 | 9.82k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC; |
148 | 9.82k | rSegInfo.Count = ( nSDat & 0xff ) >> 2; |
149 | 9.82k | break; |
150 | 17.0k | case 0xa7 : |
151 | 17.0k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX; |
152 | 17.0k | rSegInfo.Count = nSDat & 0xff; |
153 | 17.0k | break; |
154 | 17.1k | case 0xa8 : |
155 | 17.1k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY; |
156 | 17.1k | rSegInfo.Count = nSDat & 0xff; |
157 | 17.1k | break; |
158 | 5.22k | case 0xaa : |
159 | 5.22k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::NOFILL; |
160 | 5.22k | rSegInfo.Count = 0; |
161 | 5.22k | break; |
162 | 4.87k | case 0xab : |
163 | 4.87k | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE; |
164 | 4.87k | rSegInfo.Count = 0; |
165 | 4.87k | break; |
166 | 0 | default: |
167 | 0 | case 0xf8 : |
168 | 0 | rSegInfo.Command = drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN; |
169 | 0 | rSegInfo.Count = nSDat; |
170 | 0 | break; |
171 | 189k | } |
172 | 189k | } |
173 | | |
174 | | static MSO_SPT ImpGetCustomShapeType( const SdrObjCustomShape& rCustoShape ) |
175 | 22 | { |
176 | 22 | MSO_SPT eRetValue = mso_sptNil; |
177 | | |
178 | 22 | OUString aEngine( rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue() ); |
179 | 22 | if ( aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" ) |
180 | 22 | { |
181 | 22 | OUString sShapeType; |
182 | 22 | const SdrCustomShapeGeometryItem& rGeometryItem( rCustoShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
183 | 22 | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( u"Type"_ustr ); |
184 | 22 | if ( pAny && ( *pAny >>= sShapeType ) ) |
185 | 22 | eRetValue = EnhancedCustomShapeTypeNames::Get( sShapeType ); |
186 | 22 | } |
187 | 22 | return eRetValue; |
188 | 22 | }; |
189 | | |
190 | | static bool ImpVerticalSwitch( const SdrObjCustomShape& rCustoShape ) |
191 | 0 | { |
192 | 0 | bool bRet = false; |
193 | 0 | MSO_SPT eShapeType( ImpGetCustomShapeType( rCustoShape ) ); |
194 | 0 | switch( eShapeType ) |
195 | 0 | { |
196 | 0 | case mso_sptAccentBorderCallout90 : // 2 ortho |
197 | 0 | case mso_sptBorderCallout1 : // 2 diag |
198 | 0 | case mso_sptBorderCallout2 : // 3 |
199 | 0 | { |
200 | 0 | bRet = true; |
201 | 0 | } |
202 | 0 | break; |
203 | 0 | default: break; |
204 | 0 | } |
205 | 0 | return bRet; |
206 | 0 | } |
207 | | |
208 | | // #i37011# create a clone with all attributes changed to shadow attributes |
209 | | // and translation executed, too. |
210 | | static rtl::Reference<SdrObject> ImpCreateShadowObjectClone(const SdrObject& rOriginal, const SfxItemSet& rOriginalSet) |
211 | 0 | { |
212 | 0 | rtl::Reference<SdrObject> pRetval; |
213 | 0 | const bool bShadow(rOriginalSet.Get(SDRATTR_SHADOW).GetValue()); |
214 | |
|
215 | 0 | if(bShadow) |
216 | 0 | { |
217 | | // create a shadow representing object |
218 | 0 | const sal_Int32 nXDist(rOriginalSet.Get(SDRATTR_SHADOWXDIST).GetValue()); |
219 | 0 | const sal_Int32 nYDist(rOriginalSet.Get(SDRATTR_SHADOWYDIST).GetValue()); |
220 | 0 | const ::Color aShadowColor(rOriginalSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue()); |
221 | 0 | const sal_uInt16 nShadowTransparence(rOriginalSet.Get(SDRATTR_SHADOWTRANSPARENCE).GetValue()); |
222 | 0 | pRetval = rOriginal.CloneSdrObject(rOriginal.getSdrModelFromSdrObject()); |
223 | 0 | DBG_ASSERT(pRetval, "ImpCreateShadowObjectClone: Could not clone object (!)"); |
224 | | |
225 | | // look for used stuff |
226 | 0 | SdrObjListIter aIterator(rOriginal); |
227 | 0 | bool bLineUsed(false); |
228 | 0 | bool bAllFillUsed(false); |
229 | 0 | bool bSolidFillUsed(false); |
230 | 0 | bool bGradientFillUsed(false); |
231 | 0 | bool bHatchFillUsed(false); |
232 | 0 | bool bBitmapFillUsed(false); |
233 | |
|
234 | 0 | while(aIterator.IsMore()) |
235 | 0 | { |
236 | 0 | SdrObject* pObj = aIterator.Next(); |
237 | 0 | drawing::FillStyle eFillStyle = pObj->GetMergedItem(XATTR_FILLSTYLE).GetValue(); |
238 | |
|
239 | 0 | if(!bLineUsed) |
240 | 0 | { |
241 | 0 | drawing::LineStyle eLineStyle = pObj->GetMergedItem(XATTR_LINESTYLE).GetValue(); |
242 | |
|
243 | 0 | if(drawing::LineStyle_NONE != eLineStyle) |
244 | 0 | { |
245 | 0 | bLineUsed = true; |
246 | 0 | } |
247 | 0 | } |
248 | |
|
249 | 0 | if(!bAllFillUsed) |
250 | 0 | { |
251 | 0 | if(!bSolidFillUsed && drawing::FillStyle_SOLID == eFillStyle) |
252 | 0 | { |
253 | 0 | bSolidFillUsed = true; |
254 | 0 | bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed); |
255 | 0 | } |
256 | 0 | if(!bGradientFillUsed && drawing::FillStyle_GRADIENT == eFillStyle) |
257 | 0 | { |
258 | 0 | bGradientFillUsed = true; |
259 | 0 | bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed); |
260 | 0 | } |
261 | 0 | if(!bHatchFillUsed && drawing::FillStyle_HATCH == eFillStyle) |
262 | 0 | { |
263 | 0 | bHatchFillUsed = true; |
264 | 0 | bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed); |
265 | 0 | } |
266 | 0 | if(!bBitmapFillUsed && drawing::FillStyle_BITMAP == eFillStyle) |
267 | 0 | { |
268 | 0 | bBitmapFillUsed = true; |
269 | 0 | bAllFillUsed = (bSolidFillUsed && bGradientFillUsed && bHatchFillUsed && bBitmapFillUsed); |
270 | 0 | } |
271 | 0 | } |
272 | 0 | } |
273 | | |
274 | | // translate to shadow coordinates |
275 | 0 | pRetval->NbcMove(Size(nXDist, nYDist)); |
276 | | |
277 | | // set items as needed |
278 | 0 | SfxItemSet aTempSet(rOriginalSet); |
279 | | |
280 | | // if a SvxWritingModeItem (Top->Bottom) is set the text object |
281 | | // is creating a paraobject, but paraobjects can not be created without model. So |
282 | | // we are preventing the crash by setting the writing mode always left to right, |
283 | | // this is not bad since our shadow geometry does not contain text. |
284 | 0 | aTempSet.Put(SvxWritingModeItem(text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION)); |
285 | | |
286 | | // no shadow |
287 | 0 | aTempSet.Put(makeSdrShadowItem(false)); |
288 | 0 | aTempSet.Put(makeSdrShadowXDistItem(0)); |
289 | 0 | aTempSet.Put(makeSdrShadowYDistItem(0)); |
290 | | |
291 | | // line color and transparency like shadow |
292 | 0 | if(bLineUsed) |
293 | 0 | { |
294 | 0 | aTempSet.Put(XLineColorItem(OUString(), aShadowColor)); |
295 | 0 | aTempSet.Put(XLineTransparenceItem(nShadowTransparence)); |
296 | 0 | } |
297 | | |
298 | | // fill color and transparency like shadow |
299 | 0 | if(bSolidFillUsed) |
300 | 0 | { |
301 | 0 | aTempSet.Put(XFillColorItem(OUString(), aShadowColor)); |
302 | 0 | aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); |
303 | 0 | } |
304 | | |
305 | | // gradient and transparency like shadow |
306 | 0 | if(bGradientFillUsed) |
307 | 0 | { |
308 | 0 | basegfx::BGradient aGradient(rOriginalSet.Get(XATTR_FILLGRADIENT).GetGradientValue()); |
309 | 0 | sal_uInt8 nStartLuminance(Color(aGradient.GetColorStops().front().getStopColor()).GetLuminance()); |
310 | 0 | sal_uInt8 nEndLuminance(Color(aGradient.GetColorStops().back().getStopColor()).GetLuminance()); |
311 | |
|
312 | 0 | if(aGradient.GetStartIntens() != 100) |
313 | 0 | { |
314 | 0 | nStartLuminance = static_cast<sal_uInt8>(nStartLuminance * (static_cast<double>(aGradient.GetStartIntens()) / 100.0)); |
315 | 0 | } |
316 | |
|
317 | 0 | if(aGradient.GetEndIntens() != 100) |
318 | 0 | { |
319 | 0 | nEndLuminance = static_cast<sal_uInt8>(nEndLuminance * (static_cast<double>(aGradient.GetEndIntens()) / 100.0)); |
320 | 0 | } |
321 | |
|
322 | 0 | ::Color aStartColor( |
323 | 0 | static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetRed()) / 256), |
324 | 0 | static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetGreen()) / 256), |
325 | 0 | static_cast<sal_uInt8>((nStartLuminance * aShadowColor.GetBlue()) / 256)); |
326 | |
|
327 | 0 | ::Color aEndColor( |
328 | 0 | static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetRed()) / 256), |
329 | 0 | static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetGreen()) / 256), |
330 | 0 | static_cast<sal_uInt8>((nEndLuminance * aShadowColor.GetBlue()) / 256)); |
331 | |
|
332 | 0 | aGradient.SetColorStops( |
333 | 0 | basegfx::BColorStops( |
334 | 0 | aStartColor.getBColor(), |
335 | 0 | aEndColor.getBColor())); |
336 | 0 | aTempSet.Put(XFillGradientItem(aGradient)); |
337 | 0 | aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); |
338 | 0 | } |
339 | | |
340 | | // hatch and transparency like shadow |
341 | 0 | if(bHatchFillUsed) |
342 | 0 | { |
343 | 0 | XHatch aHatch(rOriginalSet.Get(XATTR_FILLHATCH).GetHatchValue()); |
344 | 0 | aHatch.SetColor(aShadowColor); |
345 | 0 | aTempSet.Put(XFillHatchItem(aHatch)); |
346 | 0 | aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); |
347 | 0 | } |
348 | | |
349 | | // bitmap and transparency like shadow |
350 | 0 | if(bBitmapFillUsed) |
351 | 0 | { |
352 | 0 | GraphicObject aGraphicObject(rOriginalSet.Get(XATTR_FILLBITMAP).GetGraphicObject()); |
353 | 0 | Bitmap aBitmap(aGraphicObject.GetGraphic().GetBitmap()); |
354 | |
|
355 | 0 | if(!aBitmap.IsEmpty()) |
356 | 0 | { |
357 | 0 | ScopedVclPtr<VirtualDevice> pVirDev(VclPtr<VirtualDevice>::Create()); |
358 | 0 | pVirDev->SetOutputSizePixel(aBitmap.GetSizePixel()); |
359 | 0 | BitmapFilter::Filter(aBitmap, BitmapShadowFilter(aShadowColor)); |
360 | 0 | pVirDev->DrawBitmap(Point(), aBitmap); |
361 | 0 | aGraphicObject.SetGraphic(Graphic(pVirDev->GetBitmap(Point(0,0), aBitmap.GetSizePixel()))); |
362 | 0 | } |
363 | |
|
364 | 0 | aTempSet.Put(XFillBitmapItem(aGraphicObject)); |
365 | 0 | aTempSet.Put(XFillTransparenceItem(nShadowTransparence)); |
366 | 0 | } |
367 | | |
368 | | // set attributes and paint shadow object |
369 | 0 | pRetval->SetMergedItemSet( aTempSet ); |
370 | 0 | } |
371 | 0 | return pRetval; |
372 | 0 | } |
373 | | |
374 | | |
375 | | rtl::Reference<EnhancedCustomShapeEngine> const & SdrObjCustomShape::GetCustomShapeEngine() const |
376 | 451k | { |
377 | 451k | if (mxCustomShapeEngine.is()) |
378 | 122k | return mxCustomShapeEngine; |
379 | | |
380 | 328k | OUString aEngine(GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue()); |
381 | 328k | if ( aEngine.isEmpty() || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine") |
382 | 328k | { |
383 | 328k | mxCustomShapeEngine = new EnhancedCustomShapeEngine(*const_cast<SdrObjCustomShape*>(this)); |
384 | 328k | } |
385 | | |
386 | 328k | return mxCustomShapeEngine; |
387 | 451k | } |
388 | | |
389 | | const SdrObject* SdrObjCustomShape::GetSdrObjectFromCustomShape() const |
390 | 240k | { |
391 | 240k | if ( !mXRenderedCustomShape.is() ) |
392 | 82.7k | { |
393 | 82.7k | rtl::Reference<EnhancedCustomShapeEngine> xCustomShapeEngine( GetCustomShapeEngine() ); |
394 | 82.7k | if ( xCustomShapeEngine.is() ) |
395 | 82.7k | mXRenderedCustomShape = xCustomShapeEngine->render2(); |
396 | 82.7k | } |
397 | 240k | return mXRenderedCustomShape.get(); |
398 | 240k | } |
399 | | |
400 | | // #i37011# Shadow geometry creation |
401 | | const SdrObject* SdrObjCustomShape::GetSdrObjectShadowFromCustomShape() const |
402 | 0 | { |
403 | 0 | if(!mpLastShadowGeometry) |
404 | 0 | { |
405 | 0 | const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); |
406 | 0 | if(pSdrObject) |
407 | 0 | { |
408 | 0 | const SfxItemSet& rOriginalSet = GetObjectItemSet(); |
409 | 0 | const bool bShadow(rOriginalSet.Get( SDRATTR_SHADOW ).GetValue()); |
410 | |
|
411 | 0 | if(bShadow) |
412 | 0 | { |
413 | | // create a clone with all attributes changed to shadow attributes |
414 | | // and translation executed, too. |
415 | 0 | const_cast<SdrObjCustomShape*>(this)->mpLastShadowGeometry = |
416 | 0 | ImpCreateShadowObjectClone(*pSdrObject, rOriginalSet); |
417 | 0 | } |
418 | 0 | } |
419 | 0 | } |
420 | |
|
421 | 0 | return mpLastShadowGeometry.get(); |
422 | 0 | } |
423 | | |
424 | | bool SdrObjCustomShape::IsTextPath() const |
425 | 1.41k | { |
426 | 1.41k | static constexpr OUString sTextPath( u"TextPath"_ustr ); |
427 | 1.41k | bool bTextPathOn = false; |
428 | 1.41k | const SdrCustomShapeGeometryItem& rGeometryItem = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); |
429 | 1.41k | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sTextPath ); |
430 | 1.41k | if ( pAny ) |
431 | 0 | *pAny >>= bTextPathOn; |
432 | 1.41k | return bTextPathOn; |
433 | 1.41k | } |
434 | | |
435 | | bool SdrObjCustomShape::UseNoFillStyle() const |
436 | 0 | { |
437 | 0 | bool bRet = false; |
438 | 0 | OUString sShapeType; |
439 | 0 | static constexpr OUString sType( u"Type"_ustr ); |
440 | 0 | const SdrCustomShapeGeometryItem& rGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
441 | 0 | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sType ); |
442 | 0 | if ( pAny ) |
443 | 0 | *pAny >>= sShapeType; |
444 | 0 | bRet = !IsCustomShapeFilledByDefault( EnhancedCustomShapeTypeNames::Get( sType ) ); |
445 | |
|
446 | 0 | return bRet; |
447 | 0 | } |
448 | | |
449 | | bool SdrObjCustomShape::IsMirroredX() const |
450 | 170k | { |
451 | 170k | bool bMirroredX = false; |
452 | 170k | const SdrCustomShapeGeometryItem & rGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
453 | 170k | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( u"MirroredX"_ustr ); |
454 | 170k | if ( pAny ) |
455 | 33.8k | *pAny >>= bMirroredX; |
456 | 170k | return bMirroredX; |
457 | 170k | } |
458 | | bool SdrObjCustomShape::IsMirroredY() const |
459 | 175k | { |
460 | 175k | bool bMirroredY = false; |
461 | 175k | const SdrCustomShapeGeometryItem & rGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
462 | 175k | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( u"MirroredY"_ustr ); |
463 | 175k | if ( pAny ) |
464 | 37.3k | *pAny >>= bMirroredY; |
465 | 175k | return bMirroredY; |
466 | 175k | } |
467 | | void SdrObjCustomShape::SetMirroredX( const bool bMirrorX ) |
468 | 7.70k | { |
469 | 7.70k | SdrCustomShapeGeometryItem aGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
470 | 7.70k | beans::PropertyValue aPropVal; |
471 | 7.70k | aPropVal.Name = "MirroredX"; |
472 | 7.70k | aPropVal.Value <<= bMirrorX; |
473 | 7.70k | aGeometryItem.SetPropertyValue( aPropVal ); |
474 | 7.70k | SetMergedItem( aGeometryItem ); |
475 | 7.70k | } |
476 | | void SdrObjCustomShape::SetMirroredY( const bool bMirrorY ) |
477 | 10.9k | { |
478 | 10.9k | SdrCustomShapeGeometryItem aGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
479 | 10.9k | beans::PropertyValue aPropVal; |
480 | 10.9k | aPropVal.Name = "MirroredY"; |
481 | 10.9k | aPropVal.Value <<= bMirrorY; |
482 | 10.9k | aGeometryItem.SetPropertyValue( aPropVal ); |
483 | 10.9k | SetMergedItem( aGeometryItem ); |
484 | 10.9k | } |
485 | | |
486 | | double SdrObjCustomShape::GetExtraTextRotation( const bool bPreRotation ) const |
487 | 12.9k | { |
488 | 12.9k | double fExtraTextRotateAngle = 0.0; |
489 | 12.9k | if (bPreRotation) |
490 | 740 | { |
491 | | // textPreRotateAngle might be set by macro or diagram (SmartArt) import |
492 | 740 | const uno::Any* pAny; |
493 | 740 | const SdrCustomShapeGeometryItem& rGeometryItem = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); |
494 | 740 | pAny = rGeometryItem.GetPropertyValueByName(u"TextPreRotateAngle"_ustr); |
495 | 740 | if ( pAny ) |
496 | 728 | *pAny >>= fExtraTextRotateAngle; |
497 | | |
498 | | // As long as the edit engine is not able to render these text directions we |
499 | | // emulate them by setting a suitable text pre-rotation. |
500 | 740 | const SvxFrameDirectionItem& rDirectionItem = GetMergedItem(SDRATTR_WRITINGMODE2); |
501 | 740 | if (rDirectionItem.GetValue() == SvxFrameDirection::Vertical_RL_TB90) |
502 | 0 | fExtraTextRotateAngle -= 90; |
503 | 740 | else if (rDirectionItem.GetValue() == SvxFrameDirection::Vertical_LR_BT) |
504 | 76 | fExtraTextRotateAngle -=270; |
505 | 740 | } |
506 | 12.2k | else |
507 | 12.2k | { |
508 | 12.2k | const uno::Any* pAny; |
509 | 12.2k | const SdrCustomShapeGeometryItem& rGeometryItem = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); |
510 | 12.2k | pAny = rGeometryItem.GetPropertyValueByName(u"TextRotateAngle"_ustr); |
511 | 12.2k | if ( pAny ) |
512 | 143 | *pAny >>= fExtraTextRotateAngle; |
513 | 12.2k | } |
514 | 12.9k | return fExtraTextRotateAngle; |
515 | 12.9k | } |
516 | | |
517 | | bool SdrObjCustomShape::GetTextBounds( tools::Rectangle& rTextBound ) const |
518 | 357k | { |
519 | 357k | bool bRet = false; |
520 | | |
521 | 357k | rtl::Reference<EnhancedCustomShapeEngine> xCustomShapeEngine( GetCustomShapeEngine() ); |
522 | 357k | if ( xCustomShapeEngine.is() ) |
523 | 357k | { |
524 | 357k | tools::Rectangle aR( xCustomShapeEngine->getTextBounds() ); |
525 | 357k | if ( aR.GetWidth() > 1 && aR.GetHeight() > 1 ) |
526 | 200k | { |
527 | 200k | rTextBound = aR; |
528 | 200k | bRet = true; |
529 | 200k | } |
530 | 357k | } |
531 | 357k | return bRet; |
532 | 357k | } |
533 | | basegfx::B2DPolyPolygon SdrObjCustomShape::GetLineGeometry( const bool bBezierAllowed ) const |
534 | 9.64k | { |
535 | 9.64k | basegfx::B2DPolyPolygon aRetval; |
536 | 9.64k | rtl::Reference<EnhancedCustomShapeEngine> xCustomShapeEngine( GetCustomShapeEngine() ); |
537 | 9.64k | if ( xCustomShapeEngine.is() ) |
538 | 9.64k | { |
539 | 9.64k | aRetval = xCustomShapeEngine->getB2DLineGeometry(); |
540 | 9.64k | try |
541 | 9.64k | { |
542 | 9.64k | if ( !bBezierAllowed && aRetval.areControlPointsUsed()) |
543 | 0 | { |
544 | 0 | aRetval = basegfx::utils::adaptiveSubdivideByAngle(aRetval); |
545 | 0 | } |
546 | 9.64k | } |
547 | 9.64k | catch ( const lang::IllegalArgumentException & ) |
548 | 9.64k | { |
549 | 0 | } |
550 | 9.64k | } |
551 | 9.64k | return aRetval; |
552 | 9.64k | } |
553 | | |
554 | | std::vector< SdrCustomShapeInteraction > SdrObjCustomShape::GetInteractionHandles() const |
555 | 1.76k | { |
556 | 1.76k | std::vector< SdrCustomShapeInteraction > aRet; |
557 | 1.76k | try |
558 | 1.76k | { |
559 | 1.76k | rtl::Reference<EnhancedCustomShapeEngine> xCustomShapeEngine( GetCustomShapeEngine() ); |
560 | 1.76k | if ( !xCustomShapeEngine.is() ) |
561 | 0 | return aRet; |
562 | | |
563 | 1.76k | std::vector<uno::Reference<drawing::XCustomShapeHandle>> xInteractionHandles( xCustomShapeEngine->getInteraction() ); |
564 | 1.78k | for ( size_t i = 0; i < xInteractionHandles.size(); i++ ) |
565 | 22 | { |
566 | 22 | SdrCustomShapeInteraction aSdrCustomShapeInteraction; |
567 | 22 | aSdrCustomShapeInteraction.xInteraction = xInteractionHandles[ i ]; |
568 | 22 | aSdrCustomShapeInteraction.aPosition = xInteractionHandles[ i ]->getPosition(); |
569 | | |
570 | 22 | CustomShapeHandleModes nMode = CustomShapeHandleModes::NONE; |
571 | 22 | switch( ImpGetCustomShapeType( *this ) ) |
572 | 22 | { |
573 | 0 | case mso_sptAccentBorderCallout90 : // 2 ortho |
574 | 0 | { |
575 | 0 | if (i == 0) |
576 | 0 | nMode |= CustomShapeHandleModes::RESIZE_FIXED | CustomShapeHandleModes::CREATE_FIXED; |
577 | 0 | else if (i == 1) |
578 | 0 | nMode |= CustomShapeHandleModes::RESIZE_ABSOLUTE_X | CustomShapeHandleModes::RESIZE_ABSOLUTE_Y | CustomShapeHandleModes::MOVE_SHAPE | CustomShapeHandleModes::ORTHO4; |
579 | 0 | } |
580 | 0 | break; |
581 | | |
582 | 0 | case mso_sptChevron : |
583 | 0 | case mso_sptHomePlate : |
584 | 0 | nMode |= CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX; |
585 | 0 | break; |
586 | | |
587 | 0 | case mso_sptWedgeRectCallout : |
588 | 0 | case mso_sptWedgeRRectCallout : |
589 | 0 | case mso_sptCloudCallout : |
590 | 0 | case mso_sptWedgeEllipseCallout : |
591 | 0 | { |
592 | 0 | if (i == 0) |
593 | 0 | nMode |= CustomShapeHandleModes::RESIZE_FIXED; |
594 | 0 | } |
595 | 0 | break; |
596 | | |
597 | 0 | case mso_sptBorderCallout1 : // 2 diag |
598 | 0 | { |
599 | 0 | if (i == 0) |
600 | 0 | nMode |= CustomShapeHandleModes::RESIZE_FIXED | CustomShapeHandleModes::CREATE_FIXED; |
601 | 0 | else if (i == 1) |
602 | 0 | nMode |= CustomShapeHandleModes::RESIZE_ABSOLUTE_X | CustomShapeHandleModes::RESIZE_ABSOLUTE_Y | CustomShapeHandleModes::MOVE_SHAPE; |
603 | 0 | } |
604 | 0 | break; |
605 | 0 | case mso_sptBorderCallout2 : // 3 |
606 | 0 | { |
607 | 0 | if (i == 0) |
608 | 0 | nMode |= CustomShapeHandleModes::RESIZE_FIXED | CustomShapeHandleModes::CREATE_FIXED; |
609 | 0 | else if (i == 2) |
610 | 0 | nMode |= CustomShapeHandleModes::RESIZE_ABSOLUTE_X | CustomShapeHandleModes::RESIZE_ABSOLUTE_Y | CustomShapeHandleModes::MOVE_SHAPE; |
611 | 0 | } |
612 | 0 | break; |
613 | 0 | case mso_sptCallout90 : |
614 | 0 | case mso_sptAccentCallout90 : |
615 | 0 | case mso_sptBorderCallout90 : |
616 | 0 | case mso_sptCallout1 : |
617 | 0 | case mso_sptCallout2 : |
618 | 0 | case mso_sptCallout3 : |
619 | 0 | case mso_sptAccentCallout1 : |
620 | 0 | case mso_sptAccentCallout2 : |
621 | 0 | case mso_sptAccentCallout3 : |
622 | 0 | case mso_sptBorderCallout3 : |
623 | 0 | case mso_sptAccentBorderCallout1 : |
624 | 0 | case mso_sptAccentBorderCallout2 : |
625 | 0 | case mso_sptAccentBorderCallout3 : |
626 | 0 | { |
627 | 0 | if (i == 0) |
628 | 0 | nMode |= CustomShapeHandleModes::RESIZE_FIXED | CustomShapeHandleModes::CREATE_FIXED; |
629 | 0 | } |
630 | 0 | break; |
631 | 22 | default: break; |
632 | 22 | } |
633 | 22 | aSdrCustomShapeInteraction.nMode = nMode; |
634 | 22 | aRet.push_back( aSdrCustomShapeInteraction ); |
635 | 22 | } |
636 | 1.76k | } |
637 | 1.76k | catch( const uno::RuntimeException& ) |
638 | 1.76k | { |
639 | 0 | } |
640 | 1.76k | return aRet; |
641 | 1.76k | } |
642 | | |
643 | | |
644 | | // BaseProperties section |
645 | 334k | #define DEFAULT_MINIMUM_SIGNED_COMPARE (sal_Int32(0x80000000)) |
646 | 95.6k | #define DEFAULT_MAXIMUM_SIGNED_COMPARE (sal_Int32(0x7fffffff)) |
647 | | |
648 | | static sal_Int32 GetNumberOfProperties ( const SvxMSDffHandle* pData ) |
649 | 35.1k | { |
650 | 35.1k | sal_Int32 nPropertiesNeeded=1; // position is always needed |
651 | 35.1k | SvxMSDffHandleFlags nFlags = pData->nFlags; |
652 | | |
653 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X ) |
654 | 0 | nPropertiesNeeded++; |
655 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y ) |
656 | 0 | nPropertiesNeeded++; |
657 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::SWITCHED ) |
658 | 8.54k | nPropertiesNeeded++; |
659 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::POLAR ) |
660 | 10.1k | { |
661 | 10.1k | nPropertiesNeeded++; |
662 | 10.1k | if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE ) |
663 | 10.0k | { |
664 | 10.0k | if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
665 | 10.0k | nPropertiesNeeded++; |
666 | 10.0k | if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
667 | 10.0k | nPropertiesNeeded++; |
668 | 10.0k | } |
669 | 10.1k | } |
670 | 25.0k | else if ( nFlags & SvxMSDffHandleFlags::RANGE ) |
671 | 18.8k | { |
672 | 18.8k | if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
673 | 12.5k | nPropertiesNeeded++; |
674 | 18.8k | if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
675 | 12.5k | nPropertiesNeeded++; |
676 | 18.8k | if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
677 | 3.24k | nPropertiesNeeded++; |
678 | 18.8k | if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
679 | 3.24k | nPropertiesNeeded++; |
680 | 18.8k | } |
681 | | |
682 | 35.1k | return nPropertiesNeeded; |
683 | 35.1k | } |
684 | | |
685 | | static void lcl_ShapePropertiesFromDFF( const SvxMSDffHandle* pData, beans::PropertyValues& rPropValues ) |
686 | 35.1k | { |
687 | 35.1k | SvxMSDffHandleFlags nFlags = pData->nFlags; |
688 | 35.1k | sal_Int32 n=0; |
689 | 35.1k | auto pPropValues = rPropValues.getArray(); |
690 | | |
691 | | // POSITION |
692 | 35.1k | { |
693 | 35.1k | drawing::EnhancedCustomShapeParameterPair aPosition; |
694 | 35.1k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, pData->nPositionX, true, true ); |
695 | 35.1k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, pData->nPositionY, true, false ); |
696 | 35.1k | pPropValues[ n ].Name = "Position"; |
697 | 35.1k | pPropValues[ n++ ].Value <<= aPosition; |
698 | 35.1k | } |
699 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X ) |
700 | 0 | { |
701 | 0 | pPropValues[ n ].Name = "MirroredX"; |
702 | 0 | pPropValues[ n++ ].Value <<= true; |
703 | 0 | } |
704 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y ) |
705 | 0 | { |
706 | 0 | pPropValues[ n ].Name = "MirroredY"; |
707 | 0 | pPropValues[ n++ ].Value <<= true; |
708 | 0 | } |
709 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::SWITCHED ) |
710 | 8.54k | { |
711 | 8.54k | pPropValues[ n ].Name = "Switched"; |
712 | 8.54k | pPropValues[ n++ ].Value <<= true; |
713 | 8.54k | } |
714 | 35.1k | if ( nFlags & SvxMSDffHandleFlags::POLAR ) |
715 | 10.1k | { |
716 | 10.1k | drawing::EnhancedCustomShapeParameterPair aCenter; |
717 | 10.1k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.First, pData->nCenterX, |
718 | 10.1k | bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true ); |
719 | 10.1k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aCenter.Second, pData->nCenterY, |
720 | 10.1k | bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false ); |
721 | 10.1k | pPropValues[ n ].Name = "Polar"; |
722 | 10.1k | pPropValues[ n++ ].Value <<= aCenter; |
723 | 10.1k | if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE ) |
724 | 10.0k | { |
725 | 10.0k | if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
726 | 10.0k | { |
727 | 10.0k | drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum; |
728 | 10.0k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, pData->nRangeXMin, |
729 | 10.0k | bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true ); |
730 | 10.0k | pPropValues[ n ].Name = "RadiusRangeMinimum"; |
731 | 10.0k | pPropValues[ n++ ].Value <<= aRadiusRangeMinimum; |
732 | 10.0k | } |
733 | 10.0k | if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
734 | 10.0k | { |
735 | 10.0k | drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum; |
736 | 10.0k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, pData->nRangeXMax, |
737 | 10.0k | bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false ); |
738 | 10.0k | pPropValues[ n ].Name = "RadiusRangeMaximum"; |
739 | 10.0k | pPropValues[ n++ ].Value <<= aRadiusRangeMaximum; |
740 | 10.0k | } |
741 | 10.0k | } |
742 | 10.1k | } |
743 | 25.0k | else if ( nFlags & SvxMSDffHandleFlags::RANGE ) |
744 | 18.8k | { |
745 | 18.8k | if ( pData->nRangeXMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
746 | 12.5k | { |
747 | 12.5k | drawing::EnhancedCustomShapeParameter aRangeXMinimum; |
748 | 12.5k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, pData->nRangeXMin, |
749 | 12.5k | bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true ); |
750 | 12.5k | pPropValues[ n ].Name = "RangeXMinimum"; |
751 | 12.5k | pPropValues[ n++ ].Value <<= aRangeXMinimum; |
752 | 12.5k | } |
753 | 18.8k | if ( pData->nRangeXMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
754 | 12.5k | { |
755 | 12.5k | drawing::EnhancedCustomShapeParameter aRangeXMaximum; |
756 | 12.5k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, pData->nRangeXMax, |
757 | 12.5k | bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false ); |
758 | 12.5k | pPropValues[ n ].Name = "RangeXMaximum"; |
759 | 12.5k | pPropValues[ n++ ].Value <<= aRangeXMaximum; |
760 | 12.5k | } |
761 | 18.8k | if ( pData->nRangeYMin != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
762 | 3.24k | { |
763 | 3.24k | drawing::EnhancedCustomShapeParameter aRangeYMinimum; |
764 | 3.24k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, pData->nRangeYMin, |
765 | 3.24k | bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL ), true ); |
766 | 3.24k | pPropValues[ n ].Name = "RangeYMinimum"; |
767 | 3.24k | pPropValues[ n++ ].Value <<= aRangeYMinimum; |
768 | 3.24k | } |
769 | 18.8k | if ( pData->nRangeYMax != DEFAULT_MAXIMUM_SIGNED_COMPARE ) |
770 | 3.24k | { |
771 | 3.24k | drawing::EnhancedCustomShapeParameter aRangeYMaximum; |
772 | 3.24k | EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, pData->nRangeYMax, |
773 | 3.24k | bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL ), false ); |
774 | 3.24k | pPropValues[ n ].Name = "RangeYMaximum"; |
775 | 3.24k | pPropValues[ n++ ].Value <<= aRangeYMaximum; |
776 | 3.24k | } |
777 | 18.8k | } |
778 | 35.1k | } |
779 | | |
780 | | std::unique_ptr<sdr::properties::BaseProperties> SdrObjCustomShape::CreateObjectSpecificProperties() |
781 | 147k | { |
782 | 147k | return std::make_unique<sdr::properties::CustomShapeProperties>(*this); |
783 | 147k | } |
784 | | |
785 | | SdrObjCustomShape::SdrObjCustomShape(SdrModel& rSdrModel) |
786 | 147k | : SdrTextObj(rSdrModel) |
787 | 147k | , m_fObjectRotation(0.0) |
788 | 147k | , mbAdjustingTextFrameWidthAndHeight(false) |
789 | 147k | { |
790 | 147k | m_bClosedObj = true; // custom shapes may be filled |
791 | 147k | mbTextFrame = true; |
792 | 147k | } |
793 | | |
794 | | SdrObjCustomShape::SdrObjCustomShape(SdrModel& rSdrModel, SdrObjCustomShape const & rSource) |
795 | 5.49k | : SdrTextObj(rSdrModel, rSource) |
796 | 5.49k | , m_fObjectRotation(0.0) |
797 | 5.49k | , mbAdjustingTextFrameWidthAndHeight(false) |
798 | 5.49k | { |
799 | 5.49k | m_bClosedObj = true; // custom shapes may be filled |
800 | 5.49k | mbTextFrame = true; |
801 | | |
802 | 5.49k | m_fObjectRotation = rSource.m_fObjectRotation; |
803 | 5.49k | mbAdjustingTextFrameWidthAndHeight = rSource.mbAdjustingTextFrameWidthAndHeight; |
804 | 5.49k | assert(!mbAdjustingTextFrameWidthAndHeight); |
805 | 5.49k | InvalidateRenderGeometry(); |
806 | 5.49k | } |
807 | | |
808 | | SdrObjCustomShape::~SdrObjCustomShape() |
809 | 152k | { |
810 | | // delete buffered display geometry |
811 | 152k | InvalidateRenderGeometry(); |
812 | 152k | } |
813 | | |
814 | | void SdrObjCustomShape::MergeDefaultAttributes( const OUString* pType ) |
815 | 147k | { |
816 | 147k | beans::PropertyValue aPropVal; |
817 | 147k | OUString sShapeType; |
818 | 147k | static constexpr OUString sType( u"Type"_ustr ); |
819 | 147k | SdrCustomShapeGeometryItem aGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
820 | 147k | if ( pType && !pType->isEmpty() ) |
821 | 961 | { |
822 | 961 | sal_Int32 nType = pType->toInt32(); |
823 | 961 | if ( nType ) |
824 | 222 | sShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >( nType ) ); |
825 | 739 | else |
826 | 739 | sShapeType = *pType; |
827 | | |
828 | 961 | aPropVal.Name = sType; |
829 | 961 | aPropVal.Value <<= sShapeType; |
830 | 961 | aGeometryItem.SetPropertyValue( aPropVal ); |
831 | 961 | } |
832 | 146k | else |
833 | 146k | { |
834 | 146k | uno::Any *pAny = aGeometryItem.GetPropertyValueByName( sType ); |
835 | 146k | if ( pAny ) |
836 | 125k | *pAny >>= sShapeType; |
837 | 146k | } |
838 | 147k | MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); |
839 | | |
840 | 147k | const sal_Int32* pDefData = nullptr; |
841 | 147k | const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); |
842 | 147k | if ( pDefCustomShape ) |
843 | 120k | pDefData = pDefCustomShape->pDefData; |
844 | | |
845 | 147k | uno::Sequence<drawing::EnhancedCustomShapeAdjustmentValue> seqAdjustmentValues; |
846 | | |
847 | | |
848 | | // AdjustmentValues |
849 | | |
850 | 147k | static constexpr OUString sAdjustmentValues( u"AdjustmentValues"_ustr ); |
851 | 147k | const uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sAdjustmentValues ); |
852 | 147k | if ( pAny ) |
853 | 19.2k | *pAny >>= seqAdjustmentValues; |
854 | 147k | if ( pDefCustomShape && pDefData ) // now check if we have to default some adjustment values |
855 | 24.7k | { |
856 | | // first check if there are adjustment values are to be appended |
857 | 24.7k | sal_Int32 i, nAdjustmentValues = seqAdjustmentValues.getLength(); |
858 | 24.7k | sal_Int32 nAdjustmentDefaults = *pDefData++; |
859 | 24.7k | if ( nAdjustmentDefaults > nAdjustmentValues ) |
860 | 11.2k | seqAdjustmentValues.realloc( nAdjustmentDefaults ); |
861 | 24.7k | auto pseqAdjustmentValues = seqAdjustmentValues.getArray(); |
862 | 46.5k | for ( i = nAdjustmentValues; i < nAdjustmentDefaults; i++ ) |
863 | 21.8k | { |
864 | 21.8k | pseqAdjustmentValues[ i ].Value <<= pDefData[ i ]; |
865 | 21.8k | pseqAdjustmentValues[ i ].State = beans::PropertyState_DIRECT_VALUE; |
866 | 21.8k | } |
867 | | // check if there are defaulted adjustment values that should be filled the hard coded defaults (pDefValue) |
868 | 24.7k | sal_Int32 nCount = std::min(nAdjustmentValues, nAdjustmentDefaults); |
869 | 45.3k | for ( i = 0; i < nCount; i++ ) |
870 | 20.6k | { |
871 | 20.6k | if ( seqAdjustmentValues[ i ].State != beans::PropertyState_DIRECT_VALUE ) |
872 | 1.12k | { |
873 | 1.12k | pseqAdjustmentValues[ i ].Value <<= pDefData[ i ]; |
874 | 1.12k | pseqAdjustmentValues[ i ].State = beans::PropertyState_DIRECT_VALUE; |
875 | 1.12k | } |
876 | 20.6k | } |
877 | 24.7k | } |
878 | 147k | aPropVal.Name = sAdjustmentValues; |
879 | 147k | aPropVal.Value <<= seqAdjustmentValues; |
880 | 147k | aGeometryItem.SetPropertyValue( aPropVal ); |
881 | | |
882 | | |
883 | | // Coordsize |
884 | | |
885 | 147k | static constexpr OUString sViewBox( u"ViewBox"_ustr ); |
886 | 147k | const uno::Any* pViewBox = aGeometryItem.GetPropertyValueByName( sViewBox ); |
887 | 147k | awt::Rectangle aViewBox; |
888 | 147k | if ( !pViewBox || !(*pViewBox >>= aViewBox ) ) |
889 | 140k | { |
890 | 140k | if ( pDefCustomShape ) |
891 | 118k | { |
892 | 118k | aViewBox.X = 0; |
893 | 118k | aViewBox.Y = 0; |
894 | 118k | aViewBox.Width = pDefCustomShape->nCoordWidth; |
895 | 118k | aViewBox.Height= pDefCustomShape->nCoordHeight; |
896 | 118k | aPropVal.Name = sViewBox; |
897 | 118k | aPropVal.Value <<= aViewBox; |
898 | 118k | aGeometryItem.SetPropertyValue( aPropVal ); |
899 | 118k | } |
900 | 140k | } |
901 | | |
902 | 147k | static constexpr OUString sPath( u"Path"_ustr ); |
903 | | |
904 | | |
905 | | // Path/Coordinates |
906 | | |
907 | 147k | static constexpr OUString sCoordinates( u"Coordinates"_ustr ); |
908 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sCoordinates ); |
909 | 147k | if (!pAny && pDefCustomShape && !pDefCustomShape->pVertices.empty()) |
910 | 119k | { |
911 | 119k | sal_Int32 i, nCount = pDefCustomShape->pVertices.size(); |
912 | 119k | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqCoordinates( nCount ); |
913 | 119k | auto pseqCoordinates = seqCoordinates.getArray(); |
914 | 782k | for ( i = 0; i < nCount; i++ ) |
915 | 663k | { |
916 | 663k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); |
917 | 663k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); |
918 | 663k | } |
919 | 119k | aPropVal.Name = sCoordinates; |
920 | 119k | aPropVal.Value <<= seqCoordinates; |
921 | 119k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
922 | 119k | } |
923 | | |
924 | | // Path/GluePoints |
925 | 147k | static constexpr OUString sGluePoints( u"GluePoints"_ustr ); |
926 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints ); |
927 | 147k | if (!pAny && pDefCustomShape && !pDefCustomShape->pGluePoints.empty()) |
928 | 3.67k | { |
929 | 3.67k | sal_Int32 i, nCount = pDefCustomShape->pGluePoints.size(); |
930 | 3.67k | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqGluePoints( nCount ); |
931 | 3.67k | auto pseqGluePoints = seqGluePoints.getArray(); |
932 | 25.4k | for ( i = 0; i < nCount; i++ ) |
933 | 21.7k | { |
934 | 21.7k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); |
935 | 21.7k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); |
936 | 21.7k | } |
937 | 3.67k | aPropVal.Name = sGluePoints; |
938 | 3.67k | aPropVal.Value <<= seqGluePoints; |
939 | 3.67k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
940 | 3.67k | } |
941 | | |
942 | | // Path/Segments |
943 | 147k | static constexpr OUString sSegments( u"Segments"_ustr ); |
944 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sSegments ); |
945 | 147k | if ( !pAny && pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) |
946 | 27.6k | { |
947 | 27.6k | sal_Int32 i, nCount = pDefCustomShape->nElements; |
948 | 27.6k | uno::Sequence<drawing::EnhancedCustomShapeSegment> seqSegments( nCount ); |
949 | 27.6k | auto pseqSegments = seqSegments.getArray(); |
950 | 216k | for ( i = 0; i < nCount; i++ ) |
951 | 189k | { |
952 | 189k | drawing::EnhancedCustomShapeSegment& rSegInfo = pseqSegments[ i ]; |
953 | 189k | sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; |
954 | 189k | lcl_ShapeSegmentFromBinary( rSegInfo, nSDat ); |
955 | 189k | } |
956 | 27.6k | aPropVal.Name = sSegments; |
957 | 27.6k | aPropVal.Value <<= seqSegments; |
958 | 27.6k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
959 | 27.6k | } |
960 | | |
961 | | // Path/StretchX |
962 | 147k | static constexpr OUString sStretchX( u"StretchX"_ustr ); |
963 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sStretchX ); |
964 | 147k | if ( !pAny && pDefCustomShape ) |
965 | 118k | { |
966 | 118k | sal_Int32 nXRef = pDefCustomShape->nXRef; |
967 | 118k | if ( nXRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
968 | 8.56k | { |
969 | 8.56k | aPropVal.Name = sStretchX; |
970 | 8.56k | aPropVal.Value <<= nXRef; |
971 | 8.56k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
972 | 8.56k | } |
973 | 118k | } |
974 | | |
975 | | // Path/StretchY |
976 | 147k | static constexpr OUString sStretchY( u"StretchY"_ustr ); |
977 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sStretchY ); |
978 | 147k | if ( !pAny && pDefCustomShape ) |
979 | 120k | { |
980 | 120k | sal_Int32 nYRef = pDefCustomShape->nYRef; |
981 | 120k | if ( nYRef != DEFAULT_MINIMUM_SIGNED_COMPARE ) |
982 | 8.55k | { |
983 | 8.55k | aPropVal.Name = sStretchY; |
984 | 8.55k | aPropVal.Value <<= nYRef; |
985 | 8.55k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
986 | 8.55k | } |
987 | 120k | } |
988 | | |
989 | | // Path/TextFrames |
990 | 147k | static constexpr OUString sTextFrames( u"TextFrames"_ustr ); |
991 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sPath, sTextFrames ); |
992 | 147k | if (!pAny && pDefCustomShape && !pDefCustomShape->pTextRect.empty()) |
993 | 15.0k | { |
994 | 15.0k | sal_Int32 i, nCount = pDefCustomShape->pTextRect.size(); |
995 | 15.0k | uno::Sequence<drawing::EnhancedCustomShapeTextFrame> seqTextFrames( nCount ); |
996 | 15.0k | auto pseqTextFrames = seqTextFrames.getArray(); |
997 | 30.3k | for (i = 0; i < nCount; i++) |
998 | 15.2k | { |
999 | 15.2k | const SvxMSDffTextRectangles* pRectangles = &pDefCustomShape->pTextRect[i]; |
1000 | 15.2k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].TopLeft.First, pRectangles->nPairA.nValA ); |
1001 | 15.2k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); |
1002 | 15.2k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].BottomRight.First, pRectangles->nPairB.nValA ); |
1003 | 15.2k | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); |
1004 | 15.2k | } |
1005 | 15.0k | aPropVal.Name = sTextFrames; |
1006 | 15.0k | aPropVal.Value <<= seqTextFrames; |
1007 | 15.0k | aGeometryItem.SetPropertyValue( sPath, aPropVal ); |
1008 | 15.0k | } |
1009 | | |
1010 | | // Equations |
1011 | 147k | static constexpr OUString sEquations( u"Equations"_ustr ); |
1012 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sEquations ); |
1013 | 147k | if (!pAny && pDefCustomShape && !pDefCustomShape->pCalculation.empty() ) |
1014 | 24.2k | { |
1015 | 24.2k | sal_Int32 i, nCount = pDefCustomShape->pCalculation.size(); |
1016 | 24.2k | uno::Sequence< OUString > seqEquations( nCount ); |
1017 | 24.2k | auto pseqEquations = seqEquations.getArray(); |
1018 | 257k | for (i = 0; i < nCount; i++) |
1019 | 232k | { |
1020 | 232k | const SvxMSDffCalculationData* pData = &pDefCustomShape->pCalculation[i]; |
1021 | 232k | pseqEquations[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); |
1022 | 232k | } |
1023 | 24.2k | aPropVal.Name = sEquations; |
1024 | 24.2k | aPropVal.Value <<= seqEquations; |
1025 | 24.2k | aGeometryItem.SetPropertyValue( aPropVal ); |
1026 | 24.2k | } |
1027 | | |
1028 | | // Handles |
1029 | 147k | static constexpr OUString sHandles( u"Handles"_ustr ); |
1030 | 147k | pAny = aGeometryItem.GetPropertyValueByName( sHandles ); |
1031 | 147k | if (!pAny && pDefCustomShape && !pDefCustomShape->pHandles.empty()) |
1032 | 24.4k | { |
1033 | 24.4k | sal_Int32 i, nCount = pDefCustomShape->pHandles.size(); |
1034 | 24.4k | uno::Sequence<beans::PropertyValues> seqHandles( nCount ); |
1035 | 24.4k | auto pseqHandles = seqHandles.getArray(); |
1036 | 59.6k | for (i = 0; i < nCount; i++) |
1037 | 35.1k | { |
1038 | 35.1k | const SvxMSDffHandle* pData = &pDefCustomShape->pHandles[i]; |
1039 | 35.1k | sal_Int32 nPropertiesNeeded; |
1040 | 35.1k | beans::PropertyValues& rPropValues = pseqHandles[ i ]; |
1041 | 35.1k | nPropertiesNeeded = GetNumberOfProperties( pData ); |
1042 | 35.1k | rPropValues.realloc( nPropertiesNeeded ); |
1043 | 35.1k | lcl_ShapePropertiesFromDFF( pData, rPropValues ); |
1044 | 35.1k | } |
1045 | 24.4k | aPropVal.Name = sHandles; |
1046 | 24.4k | aPropVal.Value <<= seqHandles; |
1047 | 24.4k | aGeometryItem.SetPropertyValue( aPropVal ); |
1048 | 24.4k | } |
1049 | 123k | else if (pAny && sShapeType.startsWith("ooxml-") && sShapeType != "ooxml-non-primitive") |
1050 | 0 | { |
1051 | | // ODF is not able to store the ooxml way of connecting handle to an adjustment |
1052 | | // value by name, e.g. attribute RefX="adj". So the information is lost, when exporting |
1053 | | // a pptx to odp, for example. This part reconstructs this information for the |
1054 | | // ooxml preset shapes from their definition. |
1055 | 0 | uno::Sequence<beans::PropertyValues> seqHandles; |
1056 | 0 | *pAny >>= seqHandles; |
1057 | 0 | auto seqHandlesRange = asNonConstRange(seqHandles); |
1058 | 0 | bool bChanged(false); |
1059 | 0 | for (sal_Int32 i = 0; i < seqHandles.getLength(); i++) |
1060 | 0 | { |
1061 | 0 | comphelper::SequenceAsHashMap aHandleProps(seqHandles[i]); |
1062 | 0 | OUString sFirstRefType; |
1063 | 0 | sal_Int32 nFirstAdjRef; |
1064 | 0 | OUString sSecondRefType; |
1065 | 0 | sal_Int32 nSecondAdjRef; |
1066 | 0 | PresetOOXHandleAdj::GetOOXHandleAdjRelation(sShapeType, i, sFirstRefType, nFirstAdjRef, |
1067 | 0 | sSecondRefType, nSecondAdjRef); |
1068 | 0 | if (sFirstRefType != "na" && 0 <= nFirstAdjRef |
1069 | 0 | && nFirstAdjRef < seqAdjustmentValues.getLength()) |
1070 | 0 | { |
1071 | 0 | bChanged |= aHandleProps.createItemIfMissing(sFirstRefType, nFirstAdjRef); |
1072 | 0 | } |
1073 | 0 | if (sSecondRefType != "na" && 0 <= nSecondAdjRef |
1074 | 0 | && nSecondAdjRef < seqAdjustmentValues.getLength()) |
1075 | 0 | { |
1076 | 0 | bChanged |= aHandleProps.createItemIfMissing(sSecondRefType, nSecondAdjRef); |
1077 | 0 | } |
1078 | 0 | aHandleProps >> seqHandlesRange[i]; |
1079 | 0 | } |
1080 | 0 | if (bChanged) |
1081 | 0 | { |
1082 | 0 | aPropVal.Name = sHandles; |
1083 | 0 | aPropVal.Value <<= seqHandles; |
1084 | 0 | aGeometryItem.SetPropertyValue(aPropVal); |
1085 | 0 | } |
1086 | 0 | } |
1087 | | |
1088 | 147k | SetMergedItem( aGeometryItem ); |
1089 | 147k | } |
1090 | | |
1091 | | bool SdrObjCustomShape::IsDefaultGeometry( const DefaultType eDefaultType ) const |
1092 | 0 | { |
1093 | 0 | bool bIsDefaultGeometry = false; |
1094 | |
|
1095 | 0 | OUString sShapeType; |
1096 | 0 | const SdrCustomShapeGeometryItem & rGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
1097 | |
|
1098 | 0 | const uno::Any *pAny = rGeometryItem.GetPropertyValueByName( u"Type"_ustr ); |
1099 | 0 | if ( pAny ) |
1100 | 0 | *pAny >>= sShapeType; |
1101 | |
|
1102 | 0 | MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType ); |
1103 | |
|
1104 | 0 | const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eSpType ); |
1105 | 0 | static constexpr OUString sPath( u"Path"_ustr ); |
1106 | 0 | switch( eDefaultType ) |
1107 | 0 | { |
1108 | 0 | case DefaultType::Viewbox : |
1109 | 0 | { |
1110 | 0 | const uno::Any* pViewBox = rGeometryItem.GetPropertyValueByName( u"ViewBox"_ustr ); |
1111 | 0 | awt::Rectangle aViewBox; |
1112 | 0 | if (pViewBox && (*pViewBox >>= aViewBox) && pDefCustomShape) |
1113 | 0 | { |
1114 | 0 | if ( ( aViewBox.Width == pDefCustomShape->nCoordWidth ) |
1115 | 0 | && ( aViewBox.Height == pDefCustomShape->nCoordHeight ) ) |
1116 | 0 | bIsDefaultGeometry = true; |
1117 | 0 | } |
1118 | 0 | } |
1119 | 0 | break; |
1120 | | |
1121 | 0 | case DefaultType::Path : |
1122 | 0 | { |
1123 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"Coordinates"_ustr ); |
1124 | 0 | if (pAny && pDefCustomShape && !pDefCustomShape->pVertices.empty()) |
1125 | 0 | { |
1126 | 0 | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqCoordinates1; |
1127 | 0 | if ( *pAny >>= seqCoordinates1 ) |
1128 | 0 | { |
1129 | 0 | sal_Int32 i, nCount = pDefCustomShape->pVertices.size(); |
1130 | 0 | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqCoordinates2( nCount ); |
1131 | 0 | auto pseqCoordinates2 = seqCoordinates2.getArray(); |
1132 | 0 | for ( i = 0; i < nCount; i++ ) |
1133 | 0 | { |
1134 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates2[ i ].First, pDefCustomShape->pVertices[ i ].nValA ); |
1135 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqCoordinates2[ i ].Second, pDefCustomShape->pVertices[ i ].nValB ); |
1136 | 0 | } |
1137 | 0 | if ( seqCoordinates1 == seqCoordinates2 ) |
1138 | 0 | bIsDefaultGeometry = true; |
1139 | 0 | } |
1140 | 0 | } |
1141 | 0 | else if (pDefCustomShape && pDefCustomShape->pVertices.empty()) |
1142 | 0 | bIsDefaultGeometry = true; |
1143 | 0 | } |
1144 | 0 | break; |
1145 | | |
1146 | 0 | case DefaultType::Gluepoints : |
1147 | 0 | { |
1148 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"GluePoints"_ustr ); |
1149 | 0 | if (pAny && pDefCustomShape && !pDefCustomShape->pGluePoints.empty()) |
1150 | 0 | { |
1151 | 0 | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqGluePoints1; |
1152 | 0 | if ( *pAny >>= seqGluePoints1 ) |
1153 | 0 | { |
1154 | 0 | sal_Int32 i, nCount = pDefCustomShape->pGluePoints.size(); |
1155 | 0 | uno::Sequence<drawing::EnhancedCustomShapeParameterPair> seqGluePoints2( nCount ); |
1156 | 0 | auto pseqGluePoints2 = seqGluePoints2.getArray(); |
1157 | 0 | for ( i = 0; i < nCount; i++ ) |
1158 | 0 | { |
1159 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints2[ i ].First, pDefCustomShape->pGluePoints[ i ].nValA ); |
1160 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqGluePoints2[ i ].Second, pDefCustomShape->pGluePoints[ i ].nValB ); |
1161 | 0 | } |
1162 | 0 | if ( seqGluePoints1 == seqGluePoints2 ) |
1163 | 0 | bIsDefaultGeometry = true; |
1164 | 0 | } |
1165 | 0 | } |
1166 | 0 | else if (pDefCustomShape && pDefCustomShape->pGluePoints.empty()) |
1167 | 0 | bIsDefaultGeometry = true; |
1168 | 0 | } |
1169 | 0 | break; |
1170 | | |
1171 | 0 | case DefaultType::Segments : |
1172 | 0 | { |
1173 | | // Path/Segments |
1174 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"Segments"_ustr ); |
1175 | 0 | if ( pAny ) |
1176 | 0 | { |
1177 | 0 | uno::Sequence<drawing::EnhancedCustomShapeSegment> seqSegments1; |
1178 | 0 | if ( *pAny >>= seqSegments1 ) |
1179 | 0 | { |
1180 | 0 | if ( pDefCustomShape && pDefCustomShape->nElements && pDefCustomShape->pElements ) |
1181 | 0 | { |
1182 | 0 | sal_Int32 i, nCount = pDefCustomShape->nElements; |
1183 | 0 | if ( nCount ) |
1184 | 0 | { |
1185 | 0 | uno::Sequence<drawing::EnhancedCustomShapeSegment> seqSegments2( nCount ); |
1186 | 0 | auto pseqSegments2 = seqSegments2.getArray(); |
1187 | 0 | for ( i = 0; i < nCount; i++ ) |
1188 | 0 | { |
1189 | 0 | drawing::EnhancedCustomShapeSegment& rSegInfo = pseqSegments2[ i ]; |
1190 | 0 | sal_uInt16 nSDat = pDefCustomShape->pElements[ i ]; |
1191 | 0 | lcl_ShapeSegmentFromBinary( rSegInfo, nSDat ); |
1192 | 0 | } |
1193 | 0 | if ( seqSegments1 == seqSegments2 ) |
1194 | 0 | bIsDefaultGeometry = true; |
1195 | 0 | } |
1196 | 0 | } |
1197 | 0 | else |
1198 | 0 | { |
1199 | | // check if it's the default segment description ( M L Z N ) |
1200 | 0 | if ( seqSegments1.getLength() == 4 ) |
1201 | 0 | { |
1202 | 0 | if ( ( seqSegments1[ 0 ].Command == drawing::EnhancedCustomShapeSegmentCommand::MOVETO ) |
1203 | 0 | && ( seqSegments1[ 1 ].Command == drawing::EnhancedCustomShapeSegmentCommand::LINETO ) |
1204 | 0 | && ( seqSegments1[ 2 ].Command == drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH ) |
1205 | 0 | && ( seqSegments1[ 3 ].Command == drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH ) ) |
1206 | 0 | bIsDefaultGeometry = true; |
1207 | 0 | } |
1208 | 0 | } |
1209 | 0 | } |
1210 | 0 | } |
1211 | 0 | else if ( pDefCustomShape && ( ( pDefCustomShape->nElements == 0 ) || ( pDefCustomShape->pElements == nullptr ) ) ) |
1212 | 0 | bIsDefaultGeometry = true; |
1213 | 0 | } |
1214 | 0 | break; |
1215 | | |
1216 | 0 | case DefaultType::StretchX : |
1217 | 0 | { |
1218 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"StretchX"_ustr ); |
1219 | 0 | if ( pAny && pDefCustomShape ) |
1220 | 0 | { |
1221 | 0 | sal_Int32 nStretchX = 0; |
1222 | 0 | if ( *pAny >>= nStretchX ) |
1223 | 0 | { |
1224 | 0 | if ( pDefCustomShape->nXRef == nStretchX ) |
1225 | 0 | bIsDefaultGeometry = true; |
1226 | 0 | } |
1227 | 0 | } |
1228 | 0 | else if ( pDefCustomShape && ( pDefCustomShape->nXRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) |
1229 | 0 | bIsDefaultGeometry = true; |
1230 | 0 | } |
1231 | 0 | break; |
1232 | | |
1233 | 0 | case DefaultType::StretchY : |
1234 | 0 | { |
1235 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"StretchY"_ustr ); |
1236 | 0 | if ( pAny && pDefCustomShape ) |
1237 | 0 | { |
1238 | 0 | sal_Int32 nStretchY = 0; |
1239 | 0 | if ( *pAny >>= nStretchY ) |
1240 | 0 | { |
1241 | 0 | if ( pDefCustomShape->nYRef == nStretchY ) |
1242 | 0 | bIsDefaultGeometry = true; |
1243 | 0 | } |
1244 | 0 | } |
1245 | 0 | else if ( pDefCustomShape && ( pDefCustomShape->nYRef == DEFAULT_MINIMUM_SIGNED_COMPARE ) ) |
1246 | 0 | bIsDefaultGeometry = true; |
1247 | 0 | } |
1248 | 0 | break; |
1249 | | |
1250 | 0 | case DefaultType::Equations : |
1251 | 0 | { |
1252 | 0 | pAny = rGeometryItem.GetPropertyValueByName( u"Equations"_ustr ); |
1253 | 0 | if (pAny && pDefCustomShape && !pDefCustomShape->pCalculation.empty()) |
1254 | 0 | { |
1255 | 0 | uno::Sequence<OUString> seqEquations1; |
1256 | 0 | if ( *pAny >>= seqEquations1 ) |
1257 | 0 | { |
1258 | 0 | sal_Int32 i, nCount = pDefCustomShape->pCalculation.size(); |
1259 | 0 | uno::Sequence<OUString> seqEquations2( nCount ); |
1260 | 0 | auto pseqEquations2 = seqEquations2.getArray(); |
1261 | |
|
1262 | 0 | for (i = 0; i < nCount; i++) |
1263 | 0 | { |
1264 | 0 | const SvxMSDffCalculationData* pData = &pDefCustomShape->pCalculation[i]; |
1265 | 0 | pseqEquations2[ i ] = EnhancedCustomShape2d::GetEquation( pData->nFlags, pData->nVal[ 0 ], pData->nVal[ 1 ], pData->nVal[ 2 ] ); |
1266 | 0 | } |
1267 | |
|
1268 | 0 | if ( seqEquations1 == seqEquations2 ) |
1269 | 0 | bIsDefaultGeometry = true; |
1270 | 0 | } |
1271 | 0 | } |
1272 | 0 | else if (pDefCustomShape && pDefCustomShape->pCalculation.empty()) |
1273 | 0 | bIsDefaultGeometry = true; |
1274 | 0 | } |
1275 | 0 | break; |
1276 | | |
1277 | 0 | case DefaultType::TextFrames : |
1278 | 0 | { |
1279 | 0 | pAny = rGeometryItem.GetPropertyValueByName( sPath, u"TextFrames"_ustr ); |
1280 | 0 | if (pAny && pDefCustomShape && !pDefCustomShape->pTextRect.empty()) |
1281 | 0 | { |
1282 | 0 | uno::Sequence<drawing::EnhancedCustomShapeTextFrame> seqTextFrames1; |
1283 | 0 | if ( *pAny >>= seqTextFrames1 ) |
1284 | 0 | { |
1285 | 0 | sal_Int32 i, nCount = pDefCustomShape->pTextRect.size(); |
1286 | 0 | uno::Sequence<drawing::EnhancedCustomShapeTextFrame> seqTextFrames2( nCount ); |
1287 | 0 | auto pseqTextFrames2 = seqTextFrames2.getArray(); |
1288 | 0 | for (i = 0; i < nCount; i++) |
1289 | 0 | { |
1290 | 0 | const SvxMSDffTextRectangles* pRectangles = &pDefCustomShape->pTextRect[i]; |
1291 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].TopLeft.First, pRectangles->nPairA.nValA ); |
1292 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].TopLeft.Second, pRectangles->nPairA.nValB ); |
1293 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].BottomRight.First, pRectangles->nPairB.nValA ); |
1294 | 0 | EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pseqTextFrames2[ i ].BottomRight.Second, pRectangles->nPairB.nValB ); |
1295 | 0 | } |
1296 | 0 | if ( seqTextFrames1 == seqTextFrames2 ) |
1297 | 0 | bIsDefaultGeometry = true; |
1298 | 0 | } |
1299 | 0 | } |
1300 | 0 | else if (pDefCustomShape && pDefCustomShape->pTextRect.empty()) |
1301 | 0 | bIsDefaultGeometry = true; |
1302 | 0 | } |
1303 | 0 | break; |
1304 | 0 | } |
1305 | 0 | return bIsDefaultGeometry; |
1306 | 0 | } |
1307 | | |
1308 | | void SdrObjCustomShape::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const |
1309 | 0 | { |
1310 | 0 | rInfo.bResizeFreeAllowed=m_fObjectRotation == 0.0; |
1311 | 0 | rInfo.bResizePropAllowed=true; |
1312 | 0 | rInfo.bRotateFreeAllowed=true; |
1313 | 0 | rInfo.bRotate90Allowed =true; |
1314 | 0 | rInfo.bMirrorFreeAllowed=true; |
1315 | 0 | rInfo.bMirror45Allowed =true; |
1316 | 0 | rInfo.bMirror90Allowed =true; |
1317 | 0 | rInfo.bTransparenceAllowed = false; |
1318 | 0 | rInfo.bShearAllowed =true; |
1319 | 0 | rInfo.bEdgeRadiusAllowed=false; |
1320 | 0 | rInfo.bNoContortion =true; |
1321 | | |
1322 | | // #i37011# |
1323 | 0 | if ( !mXRenderedCustomShape.is() ) |
1324 | 0 | return; |
1325 | | |
1326 | | // #i37262# |
1327 | | // Iterate self over the contained objects, since there are combinations of |
1328 | | // polygon and curve objects. In that case, aInfo.bCanConvToPath and |
1329 | | // aInfo.bCanConvToPoly would be false. What is needed here is an or, not an and. |
1330 | 0 | SdrObjListIter aIterator(*mXRenderedCustomShape); |
1331 | 0 | while(aIterator.IsMore()) |
1332 | 0 | { |
1333 | 0 | SdrObject* pCandidate = aIterator.Next(); |
1334 | 0 | SdrObjTransformInfoRec aInfo; |
1335 | 0 | pCandidate->TakeObjInfo(aInfo); |
1336 | | |
1337 | | // set path and poly conversion if one is possible since |
1338 | | // this object will first be broken |
1339 | 0 | const bool bCanConvToPathOrPoly(aInfo.bCanConvToPath || aInfo.bCanConvToPoly); |
1340 | 0 | if(rInfo.bCanConvToPath != bCanConvToPathOrPoly) |
1341 | 0 | { |
1342 | 0 | rInfo.bCanConvToPath = bCanConvToPathOrPoly; |
1343 | 0 | } |
1344 | |
|
1345 | 0 | if(rInfo.bCanConvToPoly != bCanConvToPathOrPoly) |
1346 | 0 | { |
1347 | 0 | rInfo.bCanConvToPoly = bCanConvToPathOrPoly; |
1348 | 0 | } |
1349 | |
|
1350 | 0 | if(rInfo.bCanConvToContour != aInfo.bCanConvToContour) |
1351 | 0 | { |
1352 | 0 | rInfo.bCanConvToContour = aInfo.bCanConvToContour; |
1353 | 0 | } |
1354 | |
|
1355 | 0 | if(rInfo.bShearAllowed != aInfo.bShearAllowed) |
1356 | 0 | { |
1357 | 0 | rInfo.bShearAllowed = aInfo.bShearAllowed; |
1358 | 0 | } |
1359 | 0 | } |
1360 | 0 | } |
1361 | | |
1362 | | SdrObjKind SdrObjCustomShape::GetObjIdentifier() const |
1363 | 1.34M | { |
1364 | 1.34M | return SdrObjKind::CustomShape; |
1365 | 1.34M | } |
1366 | | |
1367 | | // #115391# This implementation is based on the TextFrame size of the CustomShape and the |
1368 | | // state of the ResizeShapeToFitText flag to correctly set TextMinFrameWidth/Height |
1369 | | void SdrObjCustomShape::AdaptTextMinSize() |
1370 | 427k | { |
1371 | 427k | if (getSdrModelFromSdrObject().IsCreatingDataObj() || getSdrModelFromSdrObject().IsPasteResize()) |
1372 | 0 | return; |
1373 | | |
1374 | | // check if we need to change anything before creating an SfxItemSet, because that is expensive |
1375 | 427k | const bool bResizeShapeToFitText(GetObjectItem(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue()); |
1376 | 427k | tools::Rectangle aTextBound(getRectangle()); |
1377 | 427k | bool bChanged(false); |
1378 | 427k | if(bResizeShapeToFitText) |
1379 | 95.9k | bChanged = true; |
1380 | 331k | else if(GetTextBounds(aTextBound)) |
1381 | 175k | bChanged = true; |
1382 | 427k | if (!bChanged) |
1383 | 155k | return; |
1384 | | |
1385 | 271k | SfxItemSetFixed<SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, |
1386 | 271k | SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH> // contains SDRATTR_TEXT_MAXFRAMEWIDTH |
1387 | 271k | aSet(*GetObjectItemSet().GetPool()); |
1388 | | |
1389 | 271k | if(bResizeShapeToFitText) |
1390 | 95.9k | { |
1391 | | // always reset MinWidthHeight to zero to only rely on text size and frame size |
1392 | | // to allow resizing being completely dependent on text size only |
1393 | 95.9k | aSet.Put(makeSdrTextMinFrameWidthItem(0)); |
1394 | 95.9k | aSet.Put(makeSdrTextMinFrameHeightItem(0)); |
1395 | 95.9k | } |
1396 | 175k | else |
1397 | 175k | { |
1398 | | // recreate from CustomShape-specific TextBounds |
1399 | 175k | const tools::Long nHDist(GetTextLeftDistance() + GetTextRightDistance()); |
1400 | 175k | const tools::Long nVDist(GetTextUpperDistance() + GetTextLowerDistance()); |
1401 | 175k | const tools::Long nTWdt(std::max(tools::Long(0), static_cast<tools::Long>(aTextBound.GetWidth() - 1 - nHDist))); |
1402 | 175k | const tools::Long nTHgt(std::max(tools::Long(0), static_cast<tools::Long>(aTextBound.GetHeight() - 1 - nVDist))); |
1403 | | |
1404 | 175k | aSet.Put(makeSdrTextMinFrameWidthItem(nTWdt)); |
1405 | 175k | aSet.Put(makeSdrTextMinFrameHeightItem(nTHgt)); |
1406 | 175k | } |
1407 | | |
1408 | 271k | SetObjectItemSet(aSet); |
1409 | 271k | } |
1410 | | |
1411 | | void SdrObjCustomShape::NbcSetSnapRect(const tools::Rectangle& rRectangle) |
1412 | 241k | { |
1413 | 241k | tools::Rectangle aRectangle(rRectangle); |
1414 | 241k | ImpJustifyRect(aRectangle); |
1415 | 241k | setRectangle(aRectangle); |
1416 | 241k | InvalidateRenderGeometry(); |
1417 | | |
1418 | 241k | AdaptTextMinSize(); |
1419 | | |
1420 | 241k | ImpCheckShear(); |
1421 | 241k | SetBoundAndSnapRectsDirty(); |
1422 | 241k | SetChanged(); |
1423 | 241k | } |
1424 | | |
1425 | | void SdrObjCustomShape::SetSnapRect( const tools::Rectangle& rRect ) |
1426 | 126k | { |
1427 | 126k | tools::Rectangle aBoundRect0; |
1428 | 126k | if ( m_pUserCall ) |
1429 | 0 | aBoundRect0 = GetLastBoundRect(); |
1430 | 126k | NbcSetSnapRect( rRect ); |
1431 | 126k | BroadcastObjectChange(); |
1432 | 126k | SendUserCall(SdrUserCallType::Resize,aBoundRect0); |
1433 | 126k | } |
1434 | | |
1435 | | void SdrObjCustomShape::NbcSetLogicRect(const tools::Rectangle& rRectangle, bool bAdaptTextMinSize) |
1436 | 44.0k | { |
1437 | 44.0k | tools::Rectangle aRectangle(rRectangle); |
1438 | 44.0k | ImpJustifyRect(aRectangle); |
1439 | 44.0k | setRectangle(aRectangle); |
1440 | 44.0k | InvalidateRenderGeometry(); |
1441 | | |
1442 | 44.0k | if (bAdaptTextMinSize) |
1443 | 44.0k | AdaptTextMinSize(); |
1444 | | |
1445 | 44.0k | SetBoundAndSnapRectsDirty(); |
1446 | 44.0k | SetChanged(); |
1447 | 44.0k | } |
1448 | | |
1449 | | void SdrObjCustomShape::SetLogicRect( const tools::Rectangle& rRect ) |
1450 | 44.0k | { |
1451 | 44.0k | tools::Rectangle aBoundRect0; |
1452 | 44.0k | if ( m_pUserCall ) |
1453 | 1.67k | aBoundRect0 = GetLastBoundRect(); |
1454 | 44.0k | NbcSetLogicRect(rRect); |
1455 | 44.0k | BroadcastObjectChange(); |
1456 | 44.0k | SendUserCall(SdrUserCallType::Resize,aBoundRect0); |
1457 | 44.0k | } |
1458 | | |
1459 | | void SdrObjCustomShape::Move( const Size& rSiz ) |
1460 | 42.5k | { |
1461 | 42.5k | if ( rSiz.Width() || rSiz.Height() ) |
1462 | 19.9k | { |
1463 | 19.9k | tools::Rectangle aBoundRect0; |
1464 | 19.9k | if ( m_pUserCall ) |
1465 | 684 | aBoundRect0 = GetLastBoundRect(); |
1466 | 19.9k | NbcMove(rSiz); |
1467 | 19.9k | SetChanged(); |
1468 | 19.9k | BroadcastObjectChange(); |
1469 | 19.9k | SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0); |
1470 | 19.9k | } |
1471 | 42.5k | } |
1472 | | void SdrObjCustomShape::NbcMove( const Size& rSiz ) |
1473 | 19.9k | { |
1474 | 19.9k | SdrTextObj::NbcMove( rSiz ); |
1475 | 19.9k | if ( mXRenderedCustomShape.is() ) |
1476 | 0 | { |
1477 | | // #i97149# the visualisation shape needs to be informed |
1478 | | // about change, too |
1479 | 0 | mXRenderedCustomShape->ActionChanged(); |
1480 | 0 | mXRenderedCustomShape->NbcMove( rSiz ); |
1481 | 0 | } |
1482 | | |
1483 | | // #i37011# adapt geometry shadow |
1484 | 19.9k | if(mpLastShadowGeometry) |
1485 | 0 | { |
1486 | 0 | mpLastShadowGeometry->NbcMove( rSiz ); |
1487 | 0 | } |
1488 | 19.9k | } |
1489 | | |
1490 | | void SdrObjCustomShape::NbcResize( const Point& rRef, const Fraction& rxFact, const Fraction& ryFact ) |
1491 | 1.51k | { |
1492 | | // taking care of handles that should not been changed |
1493 | 1.51k | tools::Rectangle aOld(getRectangle()); |
1494 | 1.51k | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
1495 | | |
1496 | 1.51k | SdrTextObj::NbcResize( rRef, rxFact, ryFact ); |
1497 | | |
1498 | 1.51k | if ( ( rxFact.GetNumerator() != rxFact.GetDenominator() ) |
1499 | 0 | || ( ryFact.GetNumerator()!= ryFact.GetDenominator() ) ) |
1500 | 1.51k | { |
1501 | 1.51k | if ( ( ( rxFact.GetNumerator() < 0 ) && ( rxFact.GetDenominator() > 0 ) ) || |
1502 | 1.51k | ( ( rxFact.GetNumerator() > 0 ) && ( rxFact.GetDenominator() < 0 ) ) ) |
1503 | 0 | { |
1504 | 0 | SetMirroredX( !IsMirroredX() ); |
1505 | 0 | } |
1506 | 1.51k | if ( ( ( ryFact.GetNumerator() < 0 ) && ( ryFact.GetDenominator() > 0 ) ) || |
1507 | 1.51k | ( ( ryFact.GetNumerator() > 0 ) && ( ryFact.GetDenominator() < 0 ) ) ) |
1508 | 0 | { |
1509 | 0 | SetMirroredY( !IsMirroredY() ); |
1510 | 0 | } |
1511 | 1.51k | } |
1512 | | |
1513 | 1.51k | for (const auto& rInteraction : aInteractionHandles) |
1514 | 0 | { |
1515 | 0 | try |
1516 | 0 | { |
1517 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED ) |
1518 | 0 | rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition ); |
1519 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_X ) |
1520 | 0 | { |
1521 | 0 | sal_Int32 nX = ( rInteraction.aPosition.X - aOld.Left() ) + getRectangle().Left(); |
1522 | 0 | rInteraction.xInteraction->setControllerPosition(awt::Point(nX, rInteraction.xInteraction->getPosition().Y)); |
1523 | 0 | } |
1524 | 0 | else if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX ) |
1525 | 0 | { |
1526 | 0 | sal_Int32 nX = getRectangle().Right() - (aOld.Right() - rInteraction.aPosition.X); |
1527 | 0 | rInteraction.xInteraction->setControllerPosition(awt::Point(nX, rInteraction.xInteraction->getPosition().Y)); |
1528 | 0 | } |
1529 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_Y ) |
1530 | 0 | { |
1531 | 0 | sal_Int32 nY = ( rInteraction.aPosition.Y - aOld.Top() ) + getRectangle().Top(); |
1532 | 0 | rInteraction.xInteraction->setControllerPosition(awt::Point(rInteraction.xInteraction->getPosition().X, nY)); |
1533 | 0 | } |
1534 | 0 | } |
1535 | 0 | catch ( const uno::RuntimeException& ) |
1536 | 0 | { |
1537 | 0 | } |
1538 | 0 | } |
1539 | | |
1540 | | // updating fObjectRotation |
1541 | 1.51k | Degree100 nTextObjRotation = maGeo.m_nRotationAngle; |
1542 | 1.51k | double fAngle = toDegrees(nTextObjRotation); |
1543 | 1.51k | if (IsMirroredX()) |
1544 | 0 | { |
1545 | 0 | if (IsMirroredY()) |
1546 | 0 | m_fObjectRotation = fAngle - 180.0; |
1547 | 0 | else |
1548 | 0 | m_fObjectRotation = -fAngle; |
1549 | 0 | } |
1550 | 1.51k | else |
1551 | 1.51k | { |
1552 | 1.51k | if (IsMirroredY()) |
1553 | 0 | m_fObjectRotation = 180.0 - fAngle; |
1554 | 1.51k | else |
1555 | 1.51k | m_fObjectRotation = fAngle; |
1556 | 1.51k | } |
1557 | 1.51k | while (m_fObjectRotation < 0) |
1558 | 0 | m_fObjectRotation += 360.0; |
1559 | 1.51k | while (m_fObjectRotation >= 360.0) |
1560 | 0 | m_fObjectRotation -= 360.0; |
1561 | | |
1562 | 1.51k | InvalidateRenderGeometry(); |
1563 | 1.51k | } |
1564 | | |
1565 | | void SdrObjCustomShape::NbcRotate( const Point& rRef, Degree100 nAngle, double sn, double cs ) |
1566 | 16.4k | { |
1567 | 16.4k | bool bMirroredX = IsMirroredX(); |
1568 | 16.4k | bool bMirroredY = IsMirroredY(); |
1569 | | |
1570 | 16.4k | m_fObjectRotation = fmod( m_fObjectRotation, 360.0 ); |
1571 | 16.4k | if ( m_fObjectRotation < 0 ) |
1572 | 0 | m_fObjectRotation = 360 + m_fObjectRotation; |
1573 | | |
1574 | | // the rotation angle for ashapes is stored in fObjectRotation, this rotation |
1575 | | // has to be applied to the text object (which is internally using maGeo.nAngle). |
1576 | 16.4k | SdrTextObj::NbcRotate( getRectangle().TopLeft(), -maGeo.m_nRotationAngle, // retrieving the unrotated text object |
1577 | 16.4k | -maGeo.mfSinRotationAngle, |
1578 | 16.4k | maGeo.mfCosRotationAngle ); |
1579 | 16.4k | maGeo.m_nRotationAngle = 0_deg100; // resetting aGeo data |
1580 | 16.4k | maGeo.RecalcSinCos(); |
1581 | | |
1582 | 16.4k | Degree100 nW(static_cast<sal_Int32>( m_fObjectRotation * 100 )); // applying our object rotation |
1583 | 16.4k | if ( bMirroredX ) |
1584 | 86 | nW = 36000_deg100 - nW; |
1585 | 16.4k | if ( bMirroredY ) |
1586 | 115 | nW = 18000_deg100 - nW; |
1587 | 16.4k | nW = nW % 36000_deg100; |
1588 | 16.4k | if ( nW < 0_deg100 ) |
1589 | 38 | nW = 36000_deg100 + nW; |
1590 | 16.4k | SdrTextObj::NbcRotate( getRectangle().TopLeft(), nW, // applying text rotation |
1591 | 16.4k | sin( toRadians(nW) ), |
1592 | 16.4k | cos( toRadians(nW) ) ); |
1593 | | |
1594 | 16.4k | int nSwap = 0; |
1595 | 16.4k | if ( bMirroredX ) |
1596 | 86 | nSwap ^= 1; |
1597 | 16.4k | if ( bMirroredY ) |
1598 | 115 | nSwap ^= 1; |
1599 | | |
1600 | 16.4k | double fAngle = toDegrees(nAngle); // updating to our new object rotation |
1601 | 16.4k | m_fObjectRotation = fmod( nSwap ? m_fObjectRotation - fAngle : m_fObjectRotation + fAngle, 360.0 ); |
1602 | 16.4k | if ( m_fObjectRotation < 0 ) |
1603 | 117 | m_fObjectRotation = 360 + m_fObjectRotation; |
1604 | | |
1605 | 16.4k | SdrTextObj::NbcRotate( rRef, nAngle, sn, cs ); // applying text rotation |
1606 | 16.4k | InvalidateRenderGeometry(); |
1607 | 16.4k | } |
1608 | | |
1609 | | void SdrObjCustomShape::NbcMirror( const Point& rRef1, const Point& rRef2 ) |
1610 | 18.5k | { |
1611 | | // TTTT: Fix for old mirroring, can be removed again in aw080 |
1612 | | // storing horizontal and vertical flipping without modifying the rotate angle |
1613 | | // decompose other flipping to rotation and MirrorX. |
1614 | 18.5k | tools::Long ndx = rRef2.X()-rRef1.X(); |
1615 | 18.5k | tools::Long ndy = rRef2.Y()-rRef1.Y(); |
1616 | | |
1617 | 18.5k | if(!ndx) // MirroredX |
1618 | 7.69k | { |
1619 | 7.69k | SetMirroredX(!IsMirroredX()); |
1620 | 7.69k | SdrTextObj::NbcMirror( rRef1, rRef2 ); |
1621 | 7.69k | } |
1622 | 10.8k | else |
1623 | 10.8k | { |
1624 | 10.8k | if(!ndy) // MirroredY |
1625 | 10.8k | { |
1626 | 10.8k | SetMirroredY(!IsMirroredY()); |
1627 | 10.8k | SdrTextObj::NbcMirror( rRef1, rRef2 ); |
1628 | 10.8k | } |
1629 | 0 | else // neither horizontal nor vertical |
1630 | 0 | { |
1631 | 0 | SetMirroredX(!IsMirroredX()); |
1632 | | |
1633 | | // call parent |
1634 | 0 | SdrTextObj::NbcMirror( rRef1, rRef2 ); |
1635 | | |
1636 | | // update fObjectRotation |
1637 | 0 | Degree100 nTextObjRotation = maGeo.m_nRotationAngle; |
1638 | 0 | double fAngle = toDegrees(nTextObjRotation); |
1639 | |
|
1640 | 0 | bool bSingleFlip = (IsMirroredX()!= IsMirroredY()); |
1641 | |
|
1642 | 0 | m_fObjectRotation = fmod( bSingleFlip ? -fAngle : fAngle, 360.0 ); |
1643 | |
|
1644 | 0 | if ( m_fObjectRotation < 0 ) |
1645 | 0 | { |
1646 | 0 | m_fObjectRotation = 360.0 + m_fObjectRotation; |
1647 | 0 | } |
1648 | 0 | } |
1649 | 10.8k | } |
1650 | | |
1651 | 18.5k | InvalidateRenderGeometry(); |
1652 | 18.5k | } |
1653 | | |
1654 | | void SdrObjCustomShape::Shear( const Point& rRef, Degree100 nAngle, double tn, bool bVShear ) |
1655 | 0 | { |
1656 | 0 | SdrTextObj::Shear( rRef, nAngle, tn, bVShear ); |
1657 | 0 | InvalidateRenderGeometry(); |
1658 | 0 | } |
1659 | | void SdrObjCustomShape::NbcShear( const Point& rRef, Degree100 nAngle, double tn, bool bVShear ) |
1660 | 0 | { |
1661 | | // TTTT: Fix for old mirroring, can be removed again in aw080 |
1662 | 0 | SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear); |
1663 | | |
1664 | | // updating fObjectRotation |
1665 | 0 | Degree100 nTextObjRotation = maGeo.m_nRotationAngle; |
1666 | 0 | double fAngle = toDegrees(nTextObjRotation); |
1667 | 0 | if (IsMirroredX()) |
1668 | 0 | { |
1669 | 0 | if (IsMirroredY()) |
1670 | 0 | m_fObjectRotation = fAngle - 180.0; |
1671 | 0 | else |
1672 | 0 | m_fObjectRotation = -fAngle; |
1673 | 0 | } |
1674 | 0 | else |
1675 | 0 | { |
1676 | 0 | if (IsMirroredY()) |
1677 | 0 | m_fObjectRotation = 180.0 - fAngle; |
1678 | 0 | else |
1679 | 0 | m_fObjectRotation = fAngle; |
1680 | 0 | } |
1681 | 0 | while (m_fObjectRotation < 0) |
1682 | 0 | m_fObjectRotation += 360.0; |
1683 | 0 | while (m_fObjectRotation >= 360.0) |
1684 | 0 | m_fObjectRotation -= 360.0; |
1685 | |
|
1686 | 0 | InvalidateRenderGeometry(); |
1687 | 0 | } |
1688 | | |
1689 | | SdrGluePoint SdrObjCustomShape::GetVertexGluePoint(sal_uInt16 nPosNum) const |
1690 | 375 | { |
1691 | 375 | sal_Int32 nWdt = ImpGetLineWdt(); // #i25616# |
1692 | | |
1693 | | // #i25616# |
1694 | 375 | if(!LineIsOutsideGeometry()) |
1695 | 375 | { |
1696 | 375 | nWdt++; |
1697 | 375 | nWdt /= 2; |
1698 | 375 | } |
1699 | | |
1700 | 375 | Point aPt; |
1701 | 375 | tools::Rectangle aRectangle = getRectangle(); |
1702 | 375 | switch (nPosNum) |
1703 | 375 | { |
1704 | 45 | case 0: aPt = aRectangle.TopCenter(); aPt.AdjustY( -nWdt ); break; |
1705 | 160 | case 1: aPt = aRectangle.RightCenter(); aPt.AdjustX(nWdt ); break; |
1706 | 45 | case 2: aPt = aRectangle.BottomCenter(); aPt.AdjustY(nWdt ); break; |
1707 | 125 | case 3: aPt = aRectangle.LeftCenter(); aPt.AdjustX( -nWdt ); break; |
1708 | 375 | } |
1709 | 375 | if (maGeo.m_nShearAngle != 0_deg100) |
1710 | 0 | ShearPoint(aPt, aRectangle.TopLeft(), maGeo.mfTanShearAngle); |
1711 | 375 | if (maGeo.m_nRotationAngle != 0_deg100) |
1712 | 0 | RotatePoint(aPt, aRectangle.TopLeft(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle); |
1713 | 375 | aPt-=GetSnapRect().Center(); |
1714 | 375 | SdrGluePoint aGP(aPt); |
1715 | 375 | aGP.SetPercent(false); |
1716 | 375 | return aGP; |
1717 | 375 | } |
1718 | | |
1719 | | |
1720 | | // #i38892# |
1721 | | void SdrObjCustomShape::ImpCheckCustomGluePointsAreAdded() |
1722 | 239k | { |
1723 | 239k | const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); |
1724 | | |
1725 | 239k | if(!pSdrObject) |
1726 | 46.8k | return; |
1727 | | |
1728 | 192k | const SdrGluePointList* pSource = pSdrObject->GetGluePointList(); |
1729 | | |
1730 | 192k | if(!(pSource && pSource->GetCount())) |
1731 | 139k | return; |
1732 | | |
1733 | 53.2k | if(!SdrTextObj::GetGluePointList()) |
1734 | 2.87k | { |
1735 | 2.87k | SdrTextObj::ForceGluePointList(); |
1736 | 2.87k | } |
1737 | | |
1738 | 53.2k | const SdrGluePointList* pList = SdrTextObj::GetGluePointList(); |
1739 | | |
1740 | 53.2k | if(!pList) |
1741 | 0 | return; |
1742 | | |
1743 | 53.2k | SdrGluePointList aNewList; |
1744 | 53.2k | sal_uInt16 a; |
1745 | | |
1746 | 2.68M | for(a = 0; a < pSource->GetCount(); a++) |
1747 | 2.63M | { |
1748 | 2.63M | SdrGluePoint aCopy((*pSource)[a]); |
1749 | 2.63M | aCopy.SetUserDefined(false); |
1750 | 2.63M | aNewList.Insert(aCopy); |
1751 | 2.63M | } |
1752 | | |
1753 | 53.2k | bool bMirroredX = IsMirroredX(); |
1754 | 53.2k | bool bMirroredY = IsMirroredY(); |
1755 | | |
1756 | 53.2k | Degree100 nShearAngle = maGeo.m_nShearAngle; |
1757 | 53.2k | double fTan = maGeo.mfTanShearAngle; |
1758 | | |
1759 | 53.2k | if (maGeo.m_nRotationAngle || nShearAngle || bMirroredX || bMirroredY) |
1760 | 24.1k | { |
1761 | 24.1k | tools::Polygon aPoly(getRectangle()); |
1762 | 24.1k | if( nShearAngle ) |
1763 | 0 | { |
1764 | 0 | sal_uInt16 nPointCount=aPoly.GetSize(); |
1765 | 0 | for (sal_uInt16 i=0; i<nPointCount; i++) |
1766 | 0 | ShearPoint(aPoly[i], getRectangle().Center(), fTan ); |
1767 | 0 | } |
1768 | 24.1k | if (maGeo.m_nRotationAngle) |
1769 | 19.1k | aPoly.Rotate( getRectangle().Center(), to<Degree10>(maGeo.m_nRotationAngle) ); |
1770 | | |
1771 | 24.1k | tools::Rectangle aBoundRect( aPoly.GetBoundRect() ); |
1772 | 24.1k | sal_Int32 nXDiff = aBoundRect.Left() - getRectangle().Left(); |
1773 | 24.1k | sal_Int32 nYDiff = aBoundRect.Top() - getRectangle().Top(); |
1774 | | |
1775 | 24.1k | if (nShearAngle && bMirroredX != bMirroredY) |
1776 | 0 | { |
1777 | 0 | nShearAngle = -nShearAngle; |
1778 | 0 | fTan = -fTan; |
1779 | 0 | } |
1780 | | |
1781 | 24.1k | Point aRef( getRectangle().GetWidth() / 2, getRectangle().GetHeight() / 2 ); |
1782 | 1.19M | for ( a = 0; a < aNewList.GetCount(); a++ ) |
1783 | 1.16M | { |
1784 | 1.16M | SdrGluePoint& rPoint = aNewList[ a ]; |
1785 | 1.16M | Point aGlue( rPoint.GetPos() ); |
1786 | 1.16M | if ( nShearAngle ) |
1787 | 0 | ShearPoint( aGlue, aRef, fTan ); |
1788 | | |
1789 | 1.16M | RotatePoint(aGlue, aRef, sin(basegfx::deg2rad(m_fObjectRotation)), |
1790 | 1.16M | cos(basegfx::deg2rad(m_fObjectRotation))); |
1791 | 1.16M | if ( bMirroredX ) |
1792 | 429k | aGlue.setX( getRectangle().GetWidth() - aGlue.X() ); |
1793 | 1.16M | if ( bMirroredY ) |
1794 | 523k | aGlue.setY( getRectangle().GetHeight() - aGlue.Y() ); |
1795 | 1.16M | aGlue.AdjustX( -nXDiff ); |
1796 | 1.16M | aGlue.AdjustY( -nYDiff ); |
1797 | 1.16M | rPoint.SetPos( aGlue ); |
1798 | 1.16M | } |
1799 | 24.1k | } |
1800 | | |
1801 | 2.57M | for(a = 0; a < pList->GetCount(); a++) |
1802 | 2.51M | { |
1803 | 2.51M | const SdrGluePoint& rCandidate = (*pList)[a]; |
1804 | | |
1805 | 2.51M | if(rCandidate.IsUserDefined()) |
1806 | 0 | { |
1807 | 0 | aNewList.Insert(rCandidate); |
1808 | 0 | } |
1809 | 2.51M | } |
1810 | | |
1811 | | // copy new list to local. This is NOT very convenient behavior, the local |
1812 | | // GluePointList should not be set, but we delivered by using GetGluePointList(), |
1813 | | // maybe on demand. Since the local object is changed here, this is assumed to |
1814 | | // be a result of GetGluePointList and thus the list is copied |
1815 | 53.2k | if(m_pPlusData) |
1816 | 53.2k | { |
1817 | 53.2k | m_pPlusData->SetGluePoints(aNewList); |
1818 | 53.2k | } |
1819 | 53.2k | } |
1820 | | |
1821 | | // #i38892# |
1822 | | const SdrGluePointList* SdrObjCustomShape::GetGluePointList() const |
1823 | 204k | { |
1824 | 204k | const_cast<SdrObjCustomShape*>(this)->ImpCheckCustomGluePointsAreAdded(); |
1825 | 204k | return SdrTextObj::GetGluePointList(); |
1826 | 204k | } |
1827 | | |
1828 | | // #i38892# |
1829 | | SdrGluePointList* SdrObjCustomShape::ForceGluePointList() |
1830 | 34.8k | { |
1831 | 34.8k | if(SdrTextObj::ForceGluePointList()) |
1832 | 34.8k | { |
1833 | 34.8k | ImpCheckCustomGluePointsAreAdded(); |
1834 | 34.8k | return SdrTextObj::ForceGluePointList(); |
1835 | 34.8k | } |
1836 | 0 | else |
1837 | 0 | { |
1838 | 0 | return nullptr; |
1839 | 0 | } |
1840 | 34.8k | } |
1841 | | |
1842 | | |
1843 | | sal_uInt32 SdrObjCustomShape::GetHdlCount() const |
1844 | 0 | { |
1845 | 0 | const sal_uInt32 nBasicHdlCount(SdrTextObj::GetHdlCount()); |
1846 | 0 | return ( GetInteractionHandles().size() + nBasicHdlCount ); |
1847 | 0 | } |
1848 | | |
1849 | | void SdrObjCustomShape::AddToHdlList(SdrHdlList& rHdlList) const |
1850 | 0 | { |
1851 | 0 | SdrTextObj::AddToHdlList(rHdlList); |
1852 | |
|
1853 | 0 | int nCustomShapeHdlNum = 0; |
1854 | 0 | for (SdrCustomShapeInteraction const & rInteraction : GetInteractionHandles()) |
1855 | 0 | { |
1856 | 0 | if ( rInteraction.xInteraction.is() ) |
1857 | 0 | { |
1858 | 0 | try |
1859 | 0 | { |
1860 | 0 | awt::Point aPosition( rInteraction.xInteraction->getPosition() ); |
1861 | 0 | std::unique_ptr<SdrHdl> pH(new SdrHdl( Point( aPosition.X, aPosition.Y ), SdrHdlKind::CustomShape1 )); |
1862 | 0 | pH->SetPointNum( nCustomShapeHdlNum ); |
1863 | 0 | pH->SetObj( const_cast<SdrObjCustomShape*>(this) ); |
1864 | 0 | rHdlList.AddHdl(std::move(pH)); |
1865 | 0 | } |
1866 | 0 | catch ( const uno::RuntimeException& ) |
1867 | 0 | { |
1868 | 0 | } |
1869 | 0 | } |
1870 | 0 | ++nCustomShapeHdlNum; |
1871 | 0 | } |
1872 | 0 | } |
1873 | | |
1874 | | bool SdrObjCustomShape::hasSpecialDrag() const |
1875 | 0 | { |
1876 | 0 | return true; |
1877 | 0 | } |
1878 | | |
1879 | | bool SdrObjCustomShape::beginSpecialDrag(SdrDragStat& rDrag) const |
1880 | 0 | { |
1881 | 0 | const SdrHdl* pHdl = rDrag.GetHdl(); |
1882 | |
|
1883 | 0 | if(pHdl && SdrHdlKind::CustomShape1 == pHdl->GetKind()) |
1884 | 0 | { |
1885 | 0 | rDrag.SetEndDragChangesAttributes(true); |
1886 | 0 | rDrag.SetNoSnap(); |
1887 | 0 | } |
1888 | 0 | else |
1889 | 0 | { |
1890 | 0 | const SdrHdl* pHdl2 = rDrag.GetHdl(); |
1891 | 0 | const SdrHdlKind eHdl((pHdl2 == nullptr) ? SdrHdlKind::Move : pHdl2->GetKind()); |
1892 | |
|
1893 | 0 | switch( eHdl ) |
1894 | 0 | { |
1895 | 0 | case SdrHdlKind::UpperLeft : |
1896 | 0 | case SdrHdlKind::Upper : |
1897 | 0 | case SdrHdlKind::UpperRight : |
1898 | 0 | case SdrHdlKind::Left : |
1899 | 0 | case SdrHdlKind::Right : |
1900 | 0 | case SdrHdlKind::LowerLeft : |
1901 | 0 | case SdrHdlKind::Lower : |
1902 | 0 | case SdrHdlKind::LowerRight : |
1903 | 0 | case SdrHdlKind::Move : |
1904 | 0 | { |
1905 | 0 | break; |
1906 | 0 | } |
1907 | 0 | default: |
1908 | 0 | { |
1909 | 0 | return false; |
1910 | 0 | } |
1911 | 0 | } |
1912 | 0 | } |
1913 | | |
1914 | 0 | return true; |
1915 | 0 | } |
1916 | | |
1917 | | void SdrObjCustomShape::DragResizeCustomShape( const tools::Rectangle& rNewRect ) |
1918 | 0 | { |
1919 | 0 | tools::Rectangle aOld(getRectangle()); |
1920 | 0 | bool bOldMirroredX( IsMirroredX() ); |
1921 | 0 | bool bOldMirroredY( IsMirroredY() ); |
1922 | |
|
1923 | 0 | tools::Rectangle aNewRect( rNewRect ); |
1924 | 0 | aNewRect.Normalize(); |
1925 | |
|
1926 | 0 | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
1927 | |
|
1928 | 0 | GeoStat aGeoStat( GetGeoStat() ); |
1929 | 0 | if ( aNewRect.TopLeft() != getRectangle().TopLeft() && |
1930 | 0 | ( maGeo.m_nRotationAngle || maGeo.m_nShearAngle ) ) |
1931 | 0 | { |
1932 | 0 | Point aNewPos( aNewRect.TopLeft() ); |
1933 | 0 | if ( maGeo.m_nShearAngle ) ShearPoint( aNewPos, aOld.TopLeft(), aGeoStat.mfTanShearAngle ); |
1934 | 0 | if ( maGeo.m_nRotationAngle ) RotatePoint(aNewPos, aOld.TopLeft(), aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle ); |
1935 | 0 | aNewRect.SetPos( aNewPos ); |
1936 | 0 | } |
1937 | 0 | if (aNewRect == getRectangle()) |
1938 | 0 | return; |
1939 | | |
1940 | 0 | SetLogicRect( aNewRect ); |
1941 | 0 | InvalidateRenderGeometry(); |
1942 | |
|
1943 | 0 | if ( rNewRect.Left() > rNewRect.Right() ) |
1944 | 0 | { |
1945 | 0 | Point aTop( ( GetSnapRect().Left() + GetSnapRect().Right() ) >> 1, GetSnapRect().Top() ); |
1946 | 0 | Point aBottom( aTop.X(), aTop.Y() + 1000 ); |
1947 | 0 | NbcMirror( aTop, aBottom ); |
1948 | 0 | } |
1949 | 0 | if ( rNewRect.Top() > rNewRect.Bottom() ) |
1950 | 0 | { |
1951 | 0 | Point aLeft( GetSnapRect().Left(), ( GetSnapRect().Top() + GetSnapRect().Bottom() ) >> 1 ); |
1952 | 0 | Point aRight( aLeft.X() + 1000, aLeft.Y() ); |
1953 | 0 | NbcMirror( aLeft, aRight ); |
1954 | 0 | } |
1955 | |
|
1956 | 0 | for (const auto& rInteraction : aInteractionHandles) |
1957 | 0 | { |
1958 | 0 | try |
1959 | 0 | { |
1960 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED ) |
1961 | 0 | rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition ); |
1962 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_X || |
1963 | 0 | rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX ) |
1964 | 0 | { |
1965 | 0 | if (rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_NEGX) |
1966 | 0 | bOldMirroredX = !bOldMirroredX; |
1967 | |
|
1968 | 0 | sal_Int32 nX; |
1969 | 0 | if ( bOldMirroredX ) |
1970 | 0 | { |
1971 | 0 | nX = ( rInteraction.aPosition.X - aOld.Right() ); |
1972 | 0 | if ( rNewRect.Left() > rNewRect.Right() ) |
1973 | 0 | nX = getRectangle().Left() - nX; |
1974 | 0 | else |
1975 | 0 | nX += getRectangle().Right(); |
1976 | 0 | } |
1977 | 0 | else |
1978 | 0 | { |
1979 | 0 | nX = ( rInteraction.aPosition.X - aOld.Left() ); |
1980 | 0 | if ( rNewRect.Left() > rNewRect.Right() ) |
1981 | 0 | nX = getRectangle().Right() - nX; |
1982 | 0 | else |
1983 | 0 | nX += getRectangle().Left(); |
1984 | 0 | } |
1985 | 0 | rInteraction.xInteraction->setControllerPosition(awt::Point(nX, rInteraction.xInteraction->getPosition().Y)); |
1986 | 0 | } |
1987 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_ABSOLUTE_Y ) |
1988 | 0 | { |
1989 | 0 | sal_Int32 nY; |
1990 | 0 | if ( bOldMirroredY ) |
1991 | 0 | { |
1992 | 0 | nY = ( rInteraction.aPosition.Y - aOld.Bottom() ); |
1993 | 0 | if ( rNewRect.Top() > rNewRect.Bottom() ) |
1994 | 0 | nY = getRectangle().Top() - nY; |
1995 | 0 | else |
1996 | 0 | nY += getRectangle().Bottom(); |
1997 | 0 | } |
1998 | 0 | else |
1999 | 0 | { |
2000 | 0 | nY = ( rInteraction.aPosition.Y - aOld.Top() ); |
2001 | 0 | if ( rNewRect.Top() > rNewRect.Bottom() ) |
2002 | 0 | nY = getRectangle().Bottom() - nY; |
2003 | 0 | else |
2004 | 0 | nY += getRectangle().Top(); |
2005 | 0 | } |
2006 | 0 | rInteraction.xInteraction->setControllerPosition(awt::Point(rInteraction.xInteraction->getPosition().X, nY)); |
2007 | 0 | } |
2008 | 0 | } |
2009 | 0 | catch ( const uno::RuntimeException& ) |
2010 | 0 | { |
2011 | 0 | } |
2012 | 0 | } |
2013 | 0 | } |
2014 | | |
2015 | | void SdrObjCustomShape::DragMoveCustomShapeHdl( const Point& rDestination, |
2016 | | const sal_uInt16 nCustomShapeHdlNum, bool bMoveCalloutRectangle ) |
2017 | 0 | { |
2018 | 0 | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
2019 | 0 | if ( nCustomShapeHdlNum >= aInteractionHandles.size() ) |
2020 | 0 | return; |
2021 | | |
2022 | 0 | SdrCustomShapeInteraction aInteractionHandle( aInteractionHandles[ nCustomShapeHdlNum ] ); |
2023 | 0 | if ( !aInteractionHandle.xInteraction.is() ) |
2024 | 0 | return; |
2025 | | |
2026 | 0 | try |
2027 | 0 | { |
2028 | 0 | awt::Point aPt( rDestination.X(), rDestination.Y() ); |
2029 | 0 | if ( aInteractionHandle.nMode & CustomShapeHandleModes::MOVE_SHAPE && bMoveCalloutRectangle ) |
2030 | 0 | { |
2031 | 0 | sal_Int32 nXDiff = aPt.X - aInteractionHandle.aPosition.X; |
2032 | 0 | sal_Int32 nYDiff = aPt.Y - aInteractionHandle.aPosition.Y; |
2033 | |
|
2034 | 0 | moveRectangle(nXDiff, nYDiff); |
2035 | 0 | moveOutRectangle(nXDiff, nYDiff); |
2036 | 0 | maSnapRect.Move( nXDiff, nYDiff ); |
2037 | 0 | SetBoundAndSnapRectsDirty(/*bNotMyself*/true); |
2038 | 0 | InvalidateRenderGeometry(); |
2039 | |
|
2040 | 0 | for (const auto& rInteraction : aInteractionHandles) |
2041 | 0 | { |
2042 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED ) |
2043 | 0 | { |
2044 | 0 | if ( rInteraction.xInteraction.is() ) |
2045 | 0 | rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition ); |
2046 | 0 | } |
2047 | 0 | } |
2048 | 0 | } |
2049 | 0 | aInteractionHandle.xInteraction->setControllerPosition( aPt ); |
2050 | 0 | } |
2051 | 0 | catch ( const uno::RuntimeException& ) |
2052 | 0 | { |
2053 | 0 | } |
2054 | 0 | } |
2055 | | |
2056 | | bool SdrObjCustomShape::applySpecialDrag(SdrDragStat& rDrag) |
2057 | 0 | { |
2058 | 0 | const SdrHdl* pHdl = rDrag.GetHdl(); |
2059 | 0 | const SdrHdlKind eHdl((pHdl == nullptr) ? SdrHdlKind::Move : pHdl->GetKind()); |
2060 | |
|
2061 | 0 | switch(eHdl) |
2062 | 0 | { |
2063 | 0 | case SdrHdlKind::CustomShape1 : |
2064 | 0 | { |
2065 | 0 | rDrag.SetEndDragChangesGeoAndAttributes(true); |
2066 | 0 | DragMoveCustomShapeHdl( rDrag.GetNow(), static_cast<sal_uInt16>(pHdl->GetPointNum()), !rDrag.GetDragMethod()->IsShiftPressed() ); |
2067 | 0 | SetBoundAndSnapRectsDirty(); |
2068 | 0 | InvalidateRenderGeometry(); |
2069 | 0 | SetChanged(); |
2070 | 0 | break; |
2071 | 0 | } |
2072 | | |
2073 | 0 | case SdrHdlKind::UpperLeft : |
2074 | 0 | case SdrHdlKind::Upper : |
2075 | 0 | case SdrHdlKind::UpperRight : |
2076 | 0 | case SdrHdlKind::Left : |
2077 | 0 | case SdrHdlKind::Right : |
2078 | 0 | case SdrHdlKind::LowerLeft : |
2079 | 0 | case SdrHdlKind::Lower : |
2080 | 0 | case SdrHdlKind::LowerRight : |
2081 | 0 | { |
2082 | 0 | DragResizeCustomShape( ImpDragCalcRect(rDrag) ); |
2083 | 0 | break; |
2084 | 0 | } |
2085 | 0 | case SdrHdlKind::Move : |
2086 | 0 | { |
2087 | 0 | Move(Size(rDrag.GetDX(), rDrag.GetDY())); |
2088 | 0 | break; |
2089 | 0 | } |
2090 | 0 | default: break; |
2091 | 0 | } |
2092 | | |
2093 | 0 | return true; |
2094 | 0 | } |
2095 | | |
2096 | | |
2097 | | void SdrObjCustomShape::DragCreateObject( SdrDragStat& rStat ) |
2098 | 0 | { |
2099 | 0 | tools::Rectangle aRect1; |
2100 | 0 | rStat.TakeCreateRect( aRect1 ); |
2101 | |
|
2102 | 0 | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
2103 | |
|
2104 | 0 | constexpr sal_uInt32 nDefaultObjectSizeWidth = 3000; // default width from SDOptions ? |
2105 | 0 | constexpr sal_uInt32 nDefaultObjectSizeHeight= 3000; |
2106 | |
|
2107 | 0 | if ( ImpVerticalSwitch( *this ) ) |
2108 | 0 | { |
2109 | 0 | SetMirroredX( aRect1.Left() > aRect1.Right() ); |
2110 | |
|
2111 | 0 | aRect1 = tools::Rectangle( rStat.GetNow(), Size( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ) ); |
2112 | | // subtracting the horizontal difference of the latest handle from shape position |
2113 | 0 | if ( !aInteractionHandles.empty() ) |
2114 | 0 | { |
2115 | 0 | sal_Int32 nHandlePos = aInteractionHandles[ aInteractionHandles.size() - 1 ].xInteraction->getPosition().X; |
2116 | 0 | aRect1.Move(getRectangle().Left() - nHandlePos, 0); |
2117 | 0 | } |
2118 | 0 | } |
2119 | 0 | ImpJustifyRect( aRect1 ); |
2120 | 0 | rStat.SetActionRect( aRect1 ); |
2121 | 0 | setRectangle(aRect1); |
2122 | 0 | SetBoundAndSnapRectsDirty(); |
2123 | |
|
2124 | 0 | for (const auto& rInteraction : aInteractionHandles) |
2125 | 0 | { |
2126 | 0 | try |
2127 | 0 | { |
2128 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::CREATE_FIXED ) |
2129 | 0 | rInteraction.xInteraction->setControllerPosition( awt::Point( rStat.GetStart().X(), rStat.GetStart().Y() ) ); |
2130 | 0 | } |
2131 | 0 | catch ( const uno::RuntimeException& ) |
2132 | 0 | { |
2133 | 0 | } |
2134 | 0 | } |
2135 | |
|
2136 | 0 | SetBoundRectDirty(); |
2137 | 0 | m_bSnapRectDirty=true; |
2138 | 0 | } |
2139 | | |
2140 | | bool SdrObjCustomShape::MovCreate(SdrDragStat& rStat) |
2141 | 0 | { |
2142 | 0 | SdrView* pView = rStat.GetView(); // #i37448# |
2143 | 0 | if( pView && pView->IsSolidDragging() ) |
2144 | 0 | { |
2145 | 0 | InvalidateRenderGeometry(); |
2146 | 0 | } |
2147 | 0 | DragCreateObject( rStat ); |
2148 | 0 | SetBoundAndSnapRectsDirty(); |
2149 | 0 | return true; |
2150 | 0 | } |
2151 | | |
2152 | | bool SdrObjCustomShape::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd ) |
2153 | 0 | { |
2154 | 0 | DragCreateObject( rStat ); |
2155 | |
|
2156 | 0 | AdaptTextMinSize(); |
2157 | |
|
2158 | 0 | SetBoundAndSnapRectsDirty(); |
2159 | 0 | return ( eCmd == SdrCreateCmd::ForceEnd || rStat.GetPointCount() >= 2 ); |
2160 | 0 | } |
2161 | | |
2162 | | basegfx::B2DPolyPolygon SdrObjCustomShape::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const |
2163 | 0 | { |
2164 | 0 | return GetLineGeometry( false ); |
2165 | 0 | } |
2166 | | |
2167 | | |
2168 | | // in context with the SdrObjCustomShape the SdrTextAutoGrowHeightItem == true -> Resize Shape to fit text, |
2169 | | // the SdrTextAutoGrowWidthItem == true -> Word wrap text in Shape |
2170 | | bool SdrObjCustomShape::IsAutoGrowHeight() const |
2171 | 41.2k | { |
2172 | 41.2k | const SfxItemSet& rSet = GetMergedItemSet(); |
2173 | 41.2k | bool bIsAutoGrowHeight = rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue(); |
2174 | 41.2k | if ( bIsAutoGrowHeight && IsVerticalWriting() ) |
2175 | 4.13k | bIsAutoGrowHeight = !rSet.Get(SDRATTR_TEXT_WORDWRAP).GetValue(); |
2176 | 41.2k | return bIsAutoGrowHeight; |
2177 | 41.2k | } |
2178 | | bool SdrObjCustomShape::IsAutoGrowWidth() const |
2179 | 2.02k | { |
2180 | 2.02k | const SfxItemSet& rSet = GetMergedItemSet(); |
2181 | 2.02k | bool bIsAutoGrowWidth = rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue(); |
2182 | 2.02k | if ( bIsAutoGrowWidth && !IsVerticalWriting() ) |
2183 | 237 | bIsAutoGrowWidth = !rSet.Get(SDRATTR_TEXT_WORDWRAP).GetValue(); |
2184 | 2.02k | return bIsAutoGrowWidth; |
2185 | 2.02k | } |
2186 | | |
2187 | | /* The following method is identical to the SdrTextObj::SetVerticalWriting method, the only difference |
2188 | | is that the SdrAutoGrowWidthItem and SdrAutoGrowHeightItem are not exchanged if the vertical writing |
2189 | | mode has been changed */ |
2190 | | |
2191 | | void SdrObjCustomShape::SetVerticalWriting( bool bVertical ) |
2192 | 174k | { |
2193 | 174k | ForceOutlinerParaObject(); |
2194 | | |
2195 | 174k | OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); |
2196 | | |
2197 | 174k | DBG_ASSERT( pOutlinerParaObject, "SdrTextObj::SetVerticalWriting() without OutlinerParaObject!" ); |
2198 | | |
2199 | 174k | if( !pOutlinerParaObject || |
2200 | 174k | (pOutlinerParaObject->IsEffectivelyVertical() == bVertical) ) |
2201 | 173k | return; |
2202 | | |
2203 | | // get item settings |
2204 | 1.21k | const SfxItemSet& rSet = GetObjectItemSet(); |
2205 | | |
2206 | | // Also exchange horizontal and vertical adjust items |
2207 | 1.21k | SdrTextHorzAdjust eHorz = rSet.Get(SDRATTR_TEXT_HORZADJUST).GetValue(); |
2208 | 1.21k | SdrTextVertAdjust eVert = rSet.Get(SDRATTR_TEXT_VERTADJUST).GetValue(); |
2209 | | |
2210 | | // rescue object size, SetSnapRect below expects logic rect, |
2211 | | // not snap rect. |
2212 | 1.21k | tools::Rectangle aObjectRect = GetLogicRect(); |
2213 | | |
2214 | | // prepare ItemSet to set exchanged width and height items |
2215 | 1.21k | SfxItemSetFixed<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, |
2216 | | // Expanded item ranges to also support horizontal and vertical adjust. |
2217 | 1.21k | SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, |
2218 | 1.21k | SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST> aNewSet(*rSet.GetPool()); |
2219 | | |
2220 | 1.21k | aNewSet.Put(rSet); |
2221 | | |
2222 | | // Exchange horizontal and vertical adjusts |
2223 | 1.21k | switch(eVert) |
2224 | 1.21k | { |
2225 | 1.20k | case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break; |
2226 | 4 | case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break; |
2227 | 9 | case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break; |
2228 | 2 | case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break; |
2229 | 1.21k | } |
2230 | 1.21k | switch(eHorz) |
2231 | 1.21k | { |
2232 | 0 | case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break; |
2233 | 0 | case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break; |
2234 | 0 | case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break; |
2235 | 1.21k | case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break; |
2236 | 1.21k | } |
2237 | | |
2238 | 1.21k | pOutlinerParaObject = GetOutlinerParaObject(); |
2239 | 1.21k | if ( pOutlinerParaObject ) |
2240 | 1.21k | pOutlinerParaObject->SetVertical(bVertical); |
2241 | 1.21k | SetObjectItemSet( aNewSet ); |
2242 | | |
2243 | | // restore object size |
2244 | 1.21k | SetSnapRect(aObjectRect); |
2245 | 1.21k | } |
2246 | | |
2247 | | void SdrObjCustomShape::SuggestTextFrameSize(Size aSuggestedTextFrameSize) |
2248 | 0 | { |
2249 | 0 | m_aSuggestedTextFrameSize = aSuggestedTextFrameSize; |
2250 | 0 | } |
2251 | | |
2252 | | bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(tools::Rectangle& rR, bool bHgt, bool bWdt) const |
2253 | 2.09k | { |
2254 | | // Either we have text or the application has native text and suggested its size to us. |
2255 | 2.09k | bool bHasText = HasText() || !m_aSuggestedTextFrameSize.IsEmpty(); |
2256 | 2.09k | if ( bHasText && !rR.IsEmpty() ) |
2257 | 251 | { |
2258 | 251 | bool bWdtGrow=bWdt && IsAutoGrowWidth(); |
2259 | 251 | bool bHgtGrow=bHgt && IsAutoGrowHeight(); |
2260 | 251 | if ( bWdtGrow || bHgtGrow ) |
2261 | 251 | { |
2262 | 251 | tools::Rectangle aR0(rR); |
2263 | 251 | tools::Long nHgt=0,nMinHgt=0,nMaxHgt=0; |
2264 | 251 | tools::Long nWdt=0,nMinWdt=0,nMaxWdt=0; |
2265 | 251 | Size aSiz(rR.GetSize()); aSiz.AdjustWidth( -1 ); aSiz.AdjustHeight( -1 ); |
2266 | 251 | Size aMaxSiz(100000,100000); |
2267 | 251 | Size aTmpSiz(getSdrModelFromSdrObject().GetMaxObjSize()); |
2268 | 251 | if (aTmpSiz.Width()!=0) aMaxSiz.setWidth(aTmpSiz.Width() ); |
2269 | 251 | if (aTmpSiz.Height()!=0) aMaxSiz.setHeight(aTmpSiz.Height() ); |
2270 | 251 | if (bWdtGrow) |
2271 | 213 | { |
2272 | 213 | nMinWdt=GetMinTextFrameWidth(); |
2273 | 213 | nMaxWdt=GetMaxTextFrameWidth(); |
2274 | 213 | if (nMaxWdt==0 || nMaxWdt>aMaxSiz.Width()) nMaxWdt=aMaxSiz.Width(); |
2275 | 213 | if (nMinWdt<=0) nMinWdt=1; |
2276 | 213 | aSiz.setWidth(nMaxWdt ); |
2277 | 213 | } |
2278 | 251 | if (bHgtGrow) |
2279 | 237 | { |
2280 | 237 | nMinHgt=GetMinTextFrameHeight(); |
2281 | 237 | nMaxHgt=GetMaxTextFrameHeight(); |
2282 | 237 | if (nMaxHgt==0 || nMaxHgt>aMaxSiz.Height()) nMaxHgt=aMaxSiz.Height(); |
2283 | 237 | if (nMinHgt<=0) nMinHgt=1; |
2284 | 237 | aSiz.setHeight(nMaxHgt ); |
2285 | 237 | } |
2286 | 251 | tools::Long nHDist=GetTextLeftDistance()+GetTextRightDistance(); |
2287 | 251 | tools::Long nVDist=GetTextUpperDistance()+GetTextLowerDistance(); |
2288 | 251 | aSiz.AdjustWidth( -nHDist ); |
2289 | 251 | aSiz.AdjustHeight( -nVDist ); |
2290 | 251 | if ( aSiz.Width() < 2 ) |
2291 | 20 | aSiz.setWidth( 2 ); // minimum size=2 |
2292 | 251 | if ( aSiz.Height() < 2 ) |
2293 | 10 | aSiz.setHeight( 2 ); // minimum size=2 |
2294 | | |
2295 | 251 | if (HasText()) |
2296 | 251 | { |
2297 | 251 | if(mpEditingOutliner) |
2298 | 0 | { |
2299 | 0 | mpEditingOutliner->SetMaxAutoPaperSize( aSiz ); |
2300 | 0 | if (bWdtGrow) |
2301 | 0 | { |
2302 | 0 | Size aSiz2(mpEditingOutliner->CalcTextSize()); |
2303 | 0 | nWdt=aSiz2.Width()+1; // a little more tolerance |
2304 | 0 | if (bHgtGrow) nHgt=aSiz2.Height()+1; // a little more tolerance |
2305 | 0 | } else |
2306 | 0 | { |
2307 | 0 | nHgt=mpEditingOutliner->GetTextHeight()+1; // a little more tolerance |
2308 | 0 | } |
2309 | 0 | } |
2310 | 251 | else |
2311 | 251 | { |
2312 | 251 | Outliner& rOutliner=ImpGetDrawOutliner(); |
2313 | 251 | rOutliner.SetPaperSize(aSiz); |
2314 | | // TODO: add the optimization with bPortionInfoChecked again. |
2315 | 251 | OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); |
2316 | 251 | if( pOutlinerParaObject != nullptr ) |
2317 | 251 | { |
2318 | 251 | rOutliner.SetFixedCellHeight( |
2319 | 251 | GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT).GetValue()); |
2320 | 251 | rOutliner.SetText(*pOutlinerParaObject); |
2321 | 251 | } |
2322 | 251 | rOutliner.SetUpdateLayout(true); |
2323 | 251 | if ( bWdtGrow ) |
2324 | 213 | { |
2325 | 213 | Size aSiz2(rOutliner.CalcTextSize()); |
2326 | 213 | nWdt=aSiz2.Width()+1; // a little more tolerance |
2327 | 213 | if ( bHgtGrow ) |
2328 | 199 | nHgt=aSiz2.Height()+1; // a little more tolerance |
2329 | 213 | } |
2330 | 38 | else |
2331 | 38 | { |
2332 | 38 | nHgt = rOutliner.GetTextHeight()+1; // a little more tolerance |
2333 | | |
2334 | 38 | sal_Int16 nColumns = GetMergedItem(SDRATTR_TEXTCOLUMNS_NUMBER).GetValue(); |
2335 | 38 | if (bHgtGrow && nColumns > 1) |
2336 | 0 | { |
2337 | | // Both 'resize shape to fix text' and multiple columns are enabled. The |
2338 | | // first means a dynamic height, the second expects a fixed height. |
2339 | | // Resolve this conflict by going with the original height. |
2340 | 0 | nHgt = rR.getOpenHeight(); |
2341 | 0 | } |
2342 | 38 | } |
2343 | | // cleanup outliner |
2344 | 251 | rOutliner.Clear(); |
2345 | 251 | rOutliner.SetFixedCellHeight(false); |
2346 | 251 | } |
2347 | 251 | } |
2348 | 0 | else |
2349 | 0 | { |
2350 | 0 | nHgt = m_aSuggestedTextFrameSize.Height(); |
2351 | 0 | nWdt = m_aSuggestedTextFrameSize.Width(); |
2352 | 0 | } |
2353 | 251 | if ( nWdt < nMinWdt ) |
2354 | 0 | nWdt = nMinWdt; |
2355 | 251 | if ( nWdt > nMaxWdt ) |
2356 | 0 | nWdt = nMaxWdt; |
2357 | 251 | nWdt += nHDist; |
2358 | 251 | if ( nWdt < 1 ) |
2359 | 0 | nWdt = 1; // nHDist may also be negative |
2360 | 251 | if ( nHgt < nMinHgt ) |
2361 | 0 | nHgt = nMinHgt; |
2362 | 251 | if ( nHgt > nMaxHgt ) |
2363 | 0 | nHgt = nMaxHgt; |
2364 | 251 | nHgt+=nVDist; |
2365 | 251 | if ( nHgt < 1 ) |
2366 | 0 | nHgt = 1; // nVDist may also be negative |
2367 | 251 | tools::Long nWdtGrow = nWdt-(rR.Right()-rR.Left()); |
2368 | 251 | tools::Long nHgtGrow = nHgt-(rR.Bottom()-rR.Top()); |
2369 | 251 | if ( nWdtGrow == 0 ) |
2370 | 7 | bWdtGrow = false; |
2371 | 251 | if ( nHgtGrow == 0 ) |
2372 | 2 | bHgtGrow=false; |
2373 | 251 | if ( bWdtGrow || bHgtGrow || !m_aSuggestedTextFrameSize.IsEmpty()) |
2374 | 242 | { |
2375 | 242 | if ( bWdtGrow || m_aSuggestedTextFrameSize.Width() ) |
2376 | 206 | { |
2377 | 206 | SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); |
2378 | 206 | if (m_aSuggestedTextFrameSize.Width()) |
2379 | 0 | { |
2380 | 0 | rR.SetRight(rR.Left() + m_aSuggestedTextFrameSize.Width()); |
2381 | 0 | } |
2382 | 206 | else if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) |
2383 | 196 | rR.AdjustRight(nWdtGrow ); |
2384 | 10 | else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) |
2385 | 7 | rR.AdjustLeft( -nWdtGrow ); |
2386 | 3 | else |
2387 | 3 | { |
2388 | 3 | tools::Long nWdtGrow2=nWdtGrow/2; |
2389 | 3 | rR.AdjustLeft( -nWdtGrow2 ); |
2390 | 3 | rR.SetRight(rR.Left()+nWdt ); |
2391 | 3 | } |
2392 | 206 | } |
2393 | 242 | if ( bHgtGrow || m_aSuggestedTextFrameSize.Height() ) |
2394 | 235 | { |
2395 | 235 | SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); |
2396 | 235 | if (m_aSuggestedTextFrameSize.Height()) |
2397 | 0 | { |
2398 | 0 | rR.SetBottom(rR.Top() + m_aSuggestedTextFrameSize.Height()); |
2399 | 0 | } |
2400 | 235 | else if ( eVAdj == SDRTEXTVERTADJUST_TOP ) |
2401 | 232 | rR.AdjustBottom(nHgtGrow ); |
2402 | 3 | else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) |
2403 | 0 | rR.AdjustTop( -nHgtGrow ); |
2404 | 3 | else |
2405 | 3 | { |
2406 | 3 | tools::Long nHgtGrow2=nHgtGrow/2; |
2407 | 3 | rR.AdjustTop( -nHgtGrow2 ); |
2408 | 3 | rR.SetBottom(rR.Top()+nHgt ); |
2409 | 3 | } |
2410 | 235 | } |
2411 | 242 | if ( maGeo.m_nRotationAngle ) |
2412 | 40 | { |
2413 | 40 | Point aD1(rR.TopLeft()); |
2414 | 40 | aD1-=aR0.TopLeft(); |
2415 | 40 | Point aD2(aD1); |
2416 | 40 | RotatePoint(aD2,Point(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle); |
2417 | 40 | aD2-=aD1; |
2418 | 40 | rR.Move(aD2.X(),aD2.Y()); |
2419 | 40 | } |
2420 | 242 | return true; |
2421 | 242 | } |
2422 | 251 | } |
2423 | 251 | } |
2424 | 1.85k | return false; |
2425 | 2.09k | } |
2426 | | |
2427 | | tools::Rectangle SdrObjCustomShape::ImpCalculateTextFrame( const bool bHgt, const bool bWdt ) |
2428 | 2.09k | { |
2429 | 2.09k | tools::Rectangle aReturnValue; |
2430 | | |
2431 | 2.09k | tools::Rectangle aOldTextRect(getRectangle()); // <- initial text rectangle |
2432 | | |
2433 | 2.09k | tools::Rectangle aNewTextRect(getRectangle()); // <- new text rectangle returned from the custom shape renderer, |
2434 | 2.09k | GetTextBounds( aNewTextRect ); // it depends to the current logical shape size |
2435 | | |
2436 | 2.09k | tools::Rectangle aAdjustedTextRect( aNewTextRect ); // <- new text rectangle is being tested by AdjustTextFrameWidthAndHeight to ensure |
2437 | 2.09k | if ( AdjustTextFrameWidthAndHeight( aAdjustedTextRect, bHgt, bWdt ) ) // that the new text rectangle is matching the current text size from the outliner |
2438 | 242 | { |
2439 | 242 | if (aAdjustedTextRect != aNewTextRect && aOldTextRect != aAdjustedTextRect && |
2440 | 242 | aNewTextRect.GetWidth() && aNewTextRect.GetHeight()) |
2441 | 242 | { |
2442 | 242 | aReturnValue = getRectangle(); |
2443 | 242 | double fXScale = static_cast<double>(aOldTextRect.GetWidth()) / static_cast<double>(aNewTextRect.GetWidth()); |
2444 | 242 | double fYScale = static_cast<double>(aOldTextRect.GetHeight()) / static_cast<double>(aNewTextRect.GetHeight()); |
2445 | 242 | double fRightDiff = static_cast<double>( aAdjustedTextRect.Right() - aNewTextRect.Right() ) * fXScale; |
2446 | 242 | double fLeftDiff = static_cast<double>( aAdjustedTextRect.Left() - aNewTextRect.Left() ) * fXScale; |
2447 | 242 | double fTopDiff = static_cast<double>( aAdjustedTextRect.Top() - aNewTextRect.Top() ) * fYScale; |
2448 | 242 | double fBottomDiff= static_cast<double>( aAdjustedTextRect.Bottom()- aNewTextRect.Bottom()) * fYScale; |
2449 | 242 | aReturnValue.AdjustLeft(static_cast<sal_Int32>(fLeftDiff) ); |
2450 | 242 | aReturnValue.AdjustRight(static_cast<sal_Int32>(fRightDiff) ); |
2451 | 242 | aReturnValue.AdjustTop(static_cast<sal_Int32>(fTopDiff) ); |
2452 | 242 | aReturnValue.AdjustBottom(static_cast<sal_Int32>(fBottomDiff) ); |
2453 | 242 | } |
2454 | 242 | } |
2455 | 2.09k | return aReturnValue; |
2456 | 2.09k | } |
2457 | | |
2458 | | bool SdrObjCustomShape::NbcAdjustTextFrameWidthAndHeight(bool bHgt, bool bWdt) |
2459 | 2.09k | { |
2460 | 2.09k | tools::Rectangle aNewTextRect = ImpCalculateTextFrame(bHgt, bWdt); |
2461 | 2.09k | const bool bRet = !aNewTextRect.IsEmpty() && aNewTextRect != getRectangle(); |
2462 | 2.09k | if (bRet && !mbAdjustingTextFrameWidthAndHeight) |
2463 | 242 | { |
2464 | 242 | mbAdjustingTextFrameWidthAndHeight = true; |
2465 | | |
2466 | | // taking care of handles that should not been changed |
2467 | 242 | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
2468 | | |
2469 | 242 | setRectangle(aNewTextRect); |
2470 | 242 | SetBoundAndSnapRectsDirty(); |
2471 | 242 | SetChanged(); |
2472 | | |
2473 | 242 | for (const auto& rInteraction : aInteractionHandles) |
2474 | 22 | { |
2475 | 22 | try |
2476 | 22 | { |
2477 | 22 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED ) |
2478 | 0 | rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition ); |
2479 | 22 | } |
2480 | 22 | catch ( const uno::RuntimeException& ) |
2481 | 22 | { |
2482 | 0 | } |
2483 | 22 | } |
2484 | 242 | InvalidateRenderGeometry(); |
2485 | | |
2486 | 242 | mbAdjustingTextFrameWidthAndHeight = false; |
2487 | 242 | } |
2488 | 2.09k | return bRet; |
2489 | 2.09k | } |
2490 | | |
2491 | | bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight() |
2492 | 0 | { |
2493 | 0 | tools::Rectangle aNewTextRect = ImpCalculateTextFrame( true/*bHgt*/, true/*bWdt*/ ); |
2494 | 0 | bool bRet = !aNewTextRect.IsEmpty() && ( aNewTextRect != getRectangle()); |
2495 | 0 | if ( bRet ) |
2496 | 0 | { |
2497 | 0 | tools::Rectangle aBoundRect0; |
2498 | 0 | if ( m_pUserCall ) |
2499 | 0 | aBoundRect0 = GetCurrentBoundRect(); |
2500 | | |
2501 | | // taking care of handles that should not been changed |
2502 | 0 | std::vector< SdrCustomShapeInteraction > aInteractionHandles( GetInteractionHandles() ); |
2503 | |
|
2504 | 0 | setRectangle(aNewTextRect); |
2505 | 0 | SetBoundAndSnapRectsDirty(); |
2506 | |
|
2507 | 0 | for (const auto& rInteraction : aInteractionHandles) |
2508 | 0 | { |
2509 | 0 | try |
2510 | 0 | { |
2511 | 0 | if ( rInteraction.nMode & CustomShapeHandleModes::RESIZE_FIXED ) |
2512 | 0 | rInteraction.xInteraction->setControllerPosition( rInteraction.aPosition ); |
2513 | 0 | } |
2514 | 0 | catch ( const uno::RuntimeException& ) |
2515 | 0 | { |
2516 | 0 | } |
2517 | 0 | } |
2518 | |
|
2519 | 0 | InvalidateRenderGeometry(); |
2520 | 0 | SetChanged(); |
2521 | 0 | BroadcastObjectChange(); |
2522 | 0 | SendUserCall(SdrUserCallType::Resize,aBoundRect0); |
2523 | 0 | } |
2524 | 0 | return bRet; |
2525 | 0 | } |
2526 | | void SdrObjCustomShape::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, tools::Rectangle* pViewInit, tools::Rectangle* pViewMin) const |
2527 | 0 | { |
2528 | 0 | tools::Rectangle aViewInit; |
2529 | 0 | TakeTextAnchorRect( aViewInit ); |
2530 | 0 | if (maGeo.m_nRotationAngle) |
2531 | 0 | { |
2532 | 0 | Point aCenter(aViewInit.Center()); |
2533 | 0 | aCenter-=aViewInit.TopLeft(); |
2534 | 0 | Point aCenter0(aCenter); |
2535 | 0 | RotatePoint(aCenter, Point(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle); |
2536 | 0 | aCenter-=aCenter0; |
2537 | 0 | aViewInit.Move(aCenter.X(),aCenter.Y()); |
2538 | 0 | } |
2539 | 0 | Size aAnkSiz(aViewInit.GetSize()); |
2540 | 0 | aAnkSiz.AdjustWidth( -1 ); aAnkSiz.AdjustHeight( -1 ); // because GetSize() adds 1 |
2541 | 0 | Size aMaxSiz(1000000,1000000); |
2542 | 0 | { |
2543 | 0 | Size aTmpSiz(getSdrModelFromSdrObject().GetMaxObjSize()); |
2544 | 0 | if (aTmpSiz.Width()!=0) aMaxSiz.setWidth(aTmpSiz.Width() ); |
2545 | 0 | if (aTmpSiz.Height()!=0) aMaxSiz.setHeight(aTmpSiz.Height() ); |
2546 | 0 | } |
2547 | 0 | SdrTextHorzAdjust eHAdj(GetTextHorizontalAdjust()); |
2548 | 0 | SdrTextVertAdjust eVAdj(GetTextVerticalAdjust()); |
2549 | |
|
2550 | 0 | tools::Long nMinWdt = GetMinTextFrameWidth(); |
2551 | 0 | tools::Long nMinHgt = GetMinTextFrameHeight(); |
2552 | 0 | tools::Long nMaxWdt = GetMaxTextFrameWidth(); |
2553 | 0 | tools::Long nMaxHgt = GetMaxTextFrameHeight(); |
2554 | 0 | if (nMinWdt<1) nMinWdt=1; |
2555 | 0 | if (nMinHgt<1) nMinHgt=1; |
2556 | 0 | if ( nMaxWdt == 0 || nMaxWdt > aMaxSiz.Width() ) |
2557 | 0 | nMaxWdt = aMaxSiz.Width(); |
2558 | 0 | if ( nMaxHgt == 0 || nMaxHgt > aMaxSiz.Height() ) |
2559 | 0 | nMaxHgt=aMaxSiz.Height(); |
2560 | |
|
2561 | 0 | if (GetMergedItem(SDRATTR_TEXT_WORDWRAP).GetValue()) |
2562 | 0 | { |
2563 | 0 | if ( IsVerticalWriting() ) |
2564 | 0 | { |
2565 | 0 | nMaxHgt = aAnkSiz.Height(); |
2566 | 0 | nMinHgt = nMaxHgt; |
2567 | 0 | } |
2568 | 0 | else |
2569 | 0 | { |
2570 | 0 | nMaxWdt = aAnkSiz.Width(); |
2571 | 0 | nMinWdt = nMaxWdt; |
2572 | 0 | } |
2573 | 0 | } |
2574 | 0 | Size aPaperMax(nMaxWdt, nMaxHgt); |
2575 | 0 | Size aPaperMin(nMinWdt, nMinHgt); |
2576 | |
|
2577 | 0 | if ( pViewMin ) |
2578 | 0 | { |
2579 | 0 | *pViewMin = aViewInit; |
2580 | |
|
2581 | 0 | tools::Long nXFree = aAnkSiz.Width() - aPaperMin.Width(); |
2582 | 0 | if ( eHAdj == SDRTEXTHORZADJUST_LEFT ) |
2583 | 0 | pViewMin->AdjustRight( -nXFree ); |
2584 | 0 | else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT ) |
2585 | 0 | pViewMin->AdjustLeft(nXFree ); |
2586 | 0 | else { pViewMin->AdjustLeft(nXFree / 2 ); pViewMin->SetRight( pViewMin->Left() + aPaperMin.Width() ); } |
2587 | |
|
2588 | 0 | tools::Long nYFree = aAnkSiz.Height() - aPaperMin.Height(); |
2589 | 0 | if ( eVAdj == SDRTEXTVERTADJUST_TOP ) |
2590 | 0 | pViewMin->AdjustBottom( -nYFree ); |
2591 | 0 | else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM ) |
2592 | 0 | pViewMin->AdjustTop(nYFree ); |
2593 | 0 | else { pViewMin->AdjustTop(nYFree / 2 ); pViewMin->SetBottom( pViewMin->Top() + aPaperMin.Height() ); } |
2594 | 0 | } |
2595 | |
|
2596 | 0 | if( IsVerticalWriting() ) |
2597 | 0 | aPaperMin.setWidth( 0 ); |
2598 | 0 | else |
2599 | 0 | aPaperMin.setHeight( 0 ); |
2600 | |
|
2601 | 0 | if( eHAdj != SDRTEXTHORZADJUST_BLOCK ) |
2602 | 0 | aPaperMin.setWidth(0 ); |
2603 | | |
2604 | | // For complete vertical adjust support, set paper min height to 0, here. |
2605 | 0 | if(SDRTEXTVERTADJUST_BLOCK != eVAdj ) |
2606 | 0 | aPaperMin.setHeight( 0 ); |
2607 | |
|
2608 | 0 | if (pPaperMin!=nullptr) *pPaperMin=aPaperMin; |
2609 | 0 | if (pPaperMax!=nullptr) *pPaperMax=aPaperMax; |
2610 | 0 | if (pViewInit!=nullptr) *pViewInit=aViewInit; |
2611 | 0 | } |
2612 | | |
2613 | | void SdrObjCustomShape::EndTextEdit( SdrOutliner& rOutl ) |
2614 | 0 | { |
2615 | 0 | if (!getDiagramDataModelID().isEmpty()) |
2616 | 0 | { |
2617 | 0 | std::shared_ptr< svx::diagram::IDiagramHelper > pIDiagramHelper(getDiagramHelperFromDiagramOrMember()); |
2618 | |
|
2619 | 0 | if (pIDiagramHelper) |
2620 | 0 | { |
2621 | | // try to do the needed changes at the associated DiagramData model |
2622 | 0 | pIDiagramHelper->TextInformationChange(getDiagramDataModelID(), rOutl); |
2623 | 0 | } |
2624 | 0 | } |
2625 | |
|
2626 | 0 | SdrTextObj::EndTextEdit( rOutl ); |
2627 | 0 | InvalidateRenderGeometry(); |
2628 | 0 | } |
2629 | | void SdrObjCustomShape::TakeTextAnchorRect( tools::Rectangle& rAnchorRect ) const |
2630 | 11.4k | { |
2631 | 11.4k | if ( GetTextBounds( rAnchorRect ) ) |
2632 | 11.4k | { |
2633 | 11.4k | Point aRotateRef( maSnapRect.Center() ); |
2634 | 11.4k | const double fExtraTextRotation(GetExtraTextRotation()); |
2635 | 11.4k | AdjustRectToTextDistance(rAnchorRect, fExtraTextRotation); |
2636 | | |
2637 | 11.4k | if ( rAnchorRect.GetWidth() < 2 ) |
2638 | 0 | rAnchorRect.SetRight( rAnchorRect.Left() + 1 ); // minimal width is 2 |
2639 | 11.4k | if ( rAnchorRect.GetHeight() < 2 ) |
2640 | 0 | rAnchorRect.SetBottom( rAnchorRect.Top() + 1 ); // minimal height is 2 |
2641 | 11.4k | if (maGeo.m_nRotationAngle) |
2642 | 332 | { |
2643 | 332 | Point aP( rAnchorRect.TopLeft() ); |
2644 | 332 | RotatePoint(aP, aRotateRef, maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle); |
2645 | 332 | rAnchorRect.SetPos( aP ); |
2646 | 332 | } |
2647 | 11.4k | } |
2648 | 0 | else |
2649 | 0 | SdrTextObj::TakeTextAnchorRect( rAnchorRect ); |
2650 | 11.4k | } |
2651 | | void SdrObjCustomShape::TakeTextRect( SdrOutliner& rOutliner, tools::Rectangle& rTextRect, bool bNoEditText, |
2652 | | tools::Rectangle* pAnchorRect, bool /*bLineWidth*/) const |
2653 | 0 | { |
2654 | 0 | tools::Rectangle aAnkRect; // Rect in which we anchor |
2655 | 0 | TakeTextAnchorRect(aAnkRect); |
2656 | 0 | SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); |
2657 | 0 | SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); |
2658 | 0 | EEControlBits nStat0=rOutliner.GetControlWord(); |
2659 | 0 | Size aNullSize; |
2660 | |
|
2661 | 0 | rOutliner.SetControlWord(nStat0|EEControlBits::AUTOPAGESIZE); |
2662 | 0 | rOutliner.SetMinAutoPaperSize(aNullSize); |
2663 | 0 | sal_Int32 nMaxAutoPaperWidth = 1000000; |
2664 | 0 | sal_Int32 nMaxAutoPaperHeight= 1000000; |
2665 | |
|
2666 | 0 | tools::Long nAnkWdt=aAnkRect.GetWidth(); |
2667 | 0 | tools::Long nAnkHgt=aAnkRect.GetHeight(); |
2668 | |
|
2669 | 0 | if (GetMergedItem(SDRATTR_TEXT_WORDWRAP).GetValue()) |
2670 | 0 | { |
2671 | 0 | if ( IsVerticalWriting() ) |
2672 | 0 | nMaxAutoPaperHeight = nAnkHgt; |
2673 | 0 | else |
2674 | 0 | nMaxAutoPaperWidth = nAnkWdt; |
2675 | 0 | } |
2676 | 0 | if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) |
2677 | 0 | { |
2678 | 0 | rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0)); |
2679 | 0 | } |
2680 | |
|
2681 | 0 | if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()) |
2682 | 0 | { |
2683 | 0 | rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt)); |
2684 | 0 | } |
2685 | 0 | rOutliner.SetMaxAutoPaperSize( Size( nMaxAutoPaperWidth, nMaxAutoPaperHeight ) ); |
2686 | 0 | rOutliner.SetPaperSize( aNullSize ); |
2687 | | |
2688 | | // put text into the Outliner - if necessary the use the text from the EditOutliner |
2689 | 0 | std::optional<OutlinerParaObject> pPara; |
2690 | 0 | if (GetOutlinerParaObject()) |
2691 | 0 | pPara = *GetOutlinerParaObject(); |
2692 | 0 | if (mpEditingOutliner && !bNoEditText) |
2693 | 0 | pPara=mpEditingOutliner->CreateParaObject(); |
2694 | |
|
2695 | 0 | if (pPara) |
2696 | 0 | { |
2697 | 0 | bool bHitTest(&getSdrModelFromSdrObject().GetHitTestOutliner() == &rOutliner); |
2698 | 0 | const SdrTextObj* pTestObj = rOutliner.GetTextObj(); |
2699 | |
|
2700 | 0 | if( !pTestObj || !bHitTest || pTestObj != this || |
2701 | 0 | pTestObj->GetOutlinerParaObject() != GetOutlinerParaObject() ) |
2702 | 0 | { |
2703 | 0 | if( bHitTest ) |
2704 | 0 | rOutliner.SetTextObj( this ); |
2705 | |
|
2706 | 0 | rOutliner.SetUpdateLayout(true); |
2707 | 0 | rOutliner.SetText(*pPara); |
2708 | 0 | } |
2709 | 0 | } |
2710 | 0 | else |
2711 | 0 | { |
2712 | 0 | rOutliner.SetTextObj( nullptr ); |
2713 | 0 | } |
2714 | |
|
2715 | 0 | rOutliner.SetUpdateLayout(true); |
2716 | 0 | rOutliner.SetControlWord(nStat0); |
2717 | |
|
2718 | 0 | SdrText* pText = getActiveText(); |
2719 | 0 | if( pText ) |
2720 | 0 | pText->CheckPortionInfo( rOutliner ); |
2721 | |
|
2722 | 0 | Point aTextPos(aAnkRect.TopLeft()); |
2723 | 0 | Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() has a little added tolerance, no? |
2724 | | |
2725 | | // For draw objects containing text correct horizontal/vertical alignment if text is bigger |
2726 | | // than the object itself. Without that correction, the text would always be |
2727 | | // formatted to the left edge (or top edge when vertical) of the draw object. |
2728 | |
|
2729 | 0 | if( !IsTextFrame() ) |
2730 | 0 | { |
2731 | 0 | if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting()) |
2732 | 0 | { |
2733 | | // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, |
2734 | | // else the alignment is wanted. |
2735 | 0 | if(SDRTEXTHORZADJUST_BLOCK == eHAdj) |
2736 | 0 | { |
2737 | 0 | SvxAdjust eAdjust = GetObjectItemSet().Get(EE_PARA_JUST).GetAdjust(); |
2738 | 0 | switch (eAdjust) |
2739 | 0 | { |
2740 | 0 | case SvxAdjust::Left: eHAdj = SDRTEXTHORZADJUST_LEFT; break; |
2741 | 0 | case SvxAdjust::Right: eHAdj = SDRTEXTHORZADJUST_RIGHT; break; |
2742 | 0 | case SvxAdjust::Center: eHAdj = SDRTEXTHORZADJUST_CENTER; break; |
2743 | 0 | default: break; |
2744 | 0 | } |
2745 | 0 | } |
2746 | 0 | } |
2747 | | |
2748 | 0 | if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting()) |
2749 | 0 | { |
2750 | | // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, |
2751 | | // else the alignment is wanted. |
2752 | 0 | if(SDRTEXTVERTADJUST_BLOCK == eVAdj) |
2753 | 0 | { |
2754 | 0 | eVAdj = SDRTEXTVERTADJUST_CENTER; |
2755 | 0 | } |
2756 | 0 | } |
2757 | 0 | } |
2758 | | |
2759 | 0 | if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT) |
2760 | 0 | { |
2761 | 0 | tools::Long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width(); |
2762 | 0 | if (eHAdj==SDRTEXTHORZADJUST_CENTER) |
2763 | 0 | aTextPos.AdjustX(nFreeWdt/2 ); |
2764 | 0 | if (eHAdj==SDRTEXTHORZADJUST_RIGHT) |
2765 | 0 | aTextPos.AdjustX(nFreeWdt ); |
2766 | 0 | } |
2767 | 0 | if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM) |
2768 | 0 | { |
2769 | 0 | tools::Long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height(); |
2770 | 0 | if (eVAdj==SDRTEXTVERTADJUST_CENTER) |
2771 | 0 | aTextPos.AdjustY(nFreeHgt/2 ); |
2772 | 0 | if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) |
2773 | 0 | aTextPos.AdjustY(nFreeHgt ); |
2774 | 0 | } |
2775 | 0 | if (maGeo.m_nRotationAngle != 0_deg100) |
2776 | 0 | RotatePoint(aTextPos,aAnkRect.TopLeft(), maGeo.mfSinRotationAngle, maGeo.mfCosRotationAngle); |
2777 | |
|
2778 | 0 | if (pAnchorRect) |
2779 | 0 | *pAnchorRect=aAnkRect; |
2780 | | |
2781 | | // using rTextRect together with ContourFrame doesn't always work correctly |
2782 | 0 | rTextRect=tools::Rectangle(aTextPos,aTextSiz); |
2783 | 0 | } |
2784 | | |
2785 | | void SdrObjCustomShape::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObject, bool bAdjustTextFrameWidthAndHeight) |
2786 | 40.1k | { |
2787 | 40.1k | SdrTextObj::NbcSetOutlinerParaObject( std::move(pTextObject), bAdjustTextFrameWidthAndHeight ); |
2788 | 40.1k | SetBoundRectDirty(); |
2789 | 40.1k | SetBoundAndSnapRectsDirty(true); |
2790 | 40.1k | InvalidateRenderGeometry(); |
2791 | 40.1k | } |
2792 | | |
2793 | | rtl::Reference<SdrObject> SdrObjCustomShape::CloneSdrObject(SdrModel& rTargetModel) const |
2794 | 5.49k | { |
2795 | 5.49k | return new SdrObjCustomShape(rTargetModel, *this); |
2796 | 5.49k | } |
2797 | | |
2798 | | OUString SdrObjCustomShape::TakeObjNameSingul() const |
2799 | 0 | { |
2800 | 0 | OUString sName(SvxResId(STR_ObjNameSingulCUSTOMSHAPE)); |
2801 | 0 | OUString aNm(GetName()); |
2802 | 0 | if (!aNm.isEmpty()) |
2803 | 0 | sName += " '" + aNm + "'"; |
2804 | 0 | return sName; |
2805 | 0 | } |
2806 | | |
2807 | | OUString SdrObjCustomShape::TakeObjNamePlural() const |
2808 | 0 | { |
2809 | 0 | return SvxResId(STR_ObjNamePluralCUSTOMSHAPE); |
2810 | 0 | } |
2811 | | |
2812 | | basegfx::B2DPolyPolygon SdrObjCustomShape::TakeXorPoly() const |
2813 | 0 | { |
2814 | 0 | return GetLineGeometry( false ); |
2815 | 0 | } |
2816 | | |
2817 | | basegfx::B2DPolyPolygon SdrObjCustomShape::TakeContour() const |
2818 | 0 | { |
2819 | 0 | const SdrObject* pSdrObject = GetSdrObjectFromCustomShape(); |
2820 | 0 | if ( pSdrObject ) |
2821 | 0 | return pSdrObject->TakeContour(); |
2822 | 0 | return basegfx::B2DPolyPolygon(); |
2823 | 0 | } |
2824 | | |
2825 | | rtl::Reference<SdrObject> SdrObjCustomShape::DoConvertToPolyObj(bool bBezier, bool bAddText) const |
2826 | 0 | { |
2827 | | // #i37011# |
2828 | 0 | rtl::Reference<SdrObject> pRetval; |
2829 | |
|
2830 | 0 | if ( !mXRenderedCustomShape.is() ) |
2831 | 0 | { |
2832 | | // force CustomShape |
2833 | 0 | GetSdrObjectFromCustomShape(); |
2834 | 0 | } |
2835 | |
|
2836 | 0 | SdrObject* pRenderedCustomShape = mXRenderedCustomShape.get(); |
2837 | 0 | if ( pRenderedCustomShape ) |
2838 | 0 | { |
2839 | | // Clone to same SdrModel |
2840 | 0 | rtl::Reference<SdrObject> pCandidate(pRenderedCustomShape->CloneSdrObject(pRenderedCustomShape->getSdrModelFromSdrObject())); |
2841 | 0 | DBG_ASSERT(pCandidate, "SdrObjCustomShape::DoConvertToPolyObj: Could not clone SdrObject (!)"); |
2842 | 0 | pRetval = pCandidate->DoConvertToPolyObj(bBezier, bAddText); |
2843 | 0 | pCandidate.clear(); |
2844 | |
|
2845 | 0 | if(pRetval) |
2846 | 0 | { |
2847 | 0 | const bool bShadow(GetMergedItem(SDRATTR_SHADOW).GetValue()); |
2848 | 0 | if(bShadow) |
2849 | 0 | { |
2850 | 0 | pRetval->SetMergedItem(makeSdrShadowItem(true)); |
2851 | 0 | } |
2852 | 0 | } |
2853 | |
|
2854 | 0 | if(bAddText && HasText() && !IsTextPath()) |
2855 | 0 | { |
2856 | 0 | pRetval = ImpConvertAddText(std::move(pRetval), bBezier); |
2857 | 0 | } |
2858 | 0 | } |
2859 | |
|
2860 | 0 | return pRetval; |
2861 | 0 | } |
2862 | | |
2863 | | void SdrObjCustomShape::InternalSetStyleSheet( SfxStyleSheet* pNewStyleSheet, bool bDontRemoveHardAttr, bool bBroadcast, bool bAdjustTextFrameWidthAndHeight ) |
2864 | 4.07k | { |
2865 | | // #i40944# |
2866 | 4.07k | InvalidateRenderGeometry(); |
2867 | 4.07k | SdrObject::InternalSetStyleSheet( pNewStyleSheet, bDontRemoveHardAttr, bBroadcast, bAdjustTextFrameWidthAndHeight ); |
2868 | 4.07k | } |
2869 | | |
2870 | | void SdrObjCustomShape::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage) |
2871 | 88.0k | { |
2872 | | // call parent |
2873 | 88.0k | SdrTextObj::handlePageChange(pOldPage, pNewPage); |
2874 | | |
2875 | 88.0k | if(nullptr != pNewPage) |
2876 | 80.0k | { |
2877 | | // invalidating rectangles by SetRectsDirty is not sufficient, |
2878 | | // AdjustTextFrameWidthAndHeight() also has to be made, both |
2879 | | // actions are done by NbcSetSnapRect |
2880 | 80.0k | tools::Rectangle aRectangle(getRectangle()); //creating temporary rectangle #i61108# |
2881 | 80.0k | NbcSetSnapRect(aRectangle); |
2882 | 80.0k | } |
2883 | 88.0k | } |
2884 | | |
2885 | | std::unique_ptr<SdrObjGeoData> SdrObjCustomShape::NewGeoData() const |
2886 | 0 | { |
2887 | 0 | return std::make_unique<SdrAShapeObjGeoData>(); |
2888 | 0 | } |
2889 | | |
2890 | | void SdrObjCustomShape::SaveGeoData(SdrObjGeoData& rGeo) const |
2891 | 931 | { |
2892 | 931 | SdrTextObj::SaveGeoData( rGeo ); |
2893 | 931 | SdrAShapeObjGeoData& rAGeo=static_cast<SdrAShapeObjGeoData&>(rGeo); |
2894 | 931 | rAGeo.fObjectRotation = m_fObjectRotation; |
2895 | 931 | rAGeo.bMirroredX = IsMirroredX(); |
2896 | 931 | rAGeo.bMirroredY = IsMirroredY(); |
2897 | | |
2898 | 931 | const uno::Any* pAny = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ).GetPropertyValueByName( u"AdjustmentValues"_ustr ); |
2899 | 931 | if ( pAny ) |
2900 | 0 | *pAny >>= rAGeo.aAdjustmentSeq; |
2901 | 931 | } |
2902 | | |
2903 | | void SdrObjCustomShape::RestoreGeoData(const SdrObjGeoData& rGeo) |
2904 | 0 | { |
2905 | 0 | SdrTextObj::RestoreGeoData( rGeo ); |
2906 | 0 | const SdrAShapeObjGeoData& rAGeo=static_cast<const SdrAShapeObjGeoData&>(rGeo); |
2907 | 0 | m_fObjectRotation = rAGeo.fObjectRotation; |
2908 | 0 | SetMirroredX( rAGeo.bMirroredX ); |
2909 | 0 | SetMirroredY( rAGeo.bMirroredY ); |
2910 | |
|
2911 | 0 | SdrCustomShapeGeometryItem rGeometryItem = GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ); |
2912 | 0 | beans::PropertyValue aPropVal; |
2913 | 0 | aPropVal.Name = "AdjustmentValues"; |
2914 | 0 | aPropVal.Value <<= rAGeo.aAdjustmentSeq; |
2915 | 0 | rGeometryItem.SetPropertyValue( aPropVal ); |
2916 | 0 | SetMergedItem( rGeometryItem ); |
2917 | |
|
2918 | 0 | InvalidateRenderGeometry(); |
2919 | 0 | } |
2920 | | |
2921 | | void SdrObjCustomShape::AdjustToMaxRect(const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */) |
2922 | 23 | { |
2923 | 23 | SAL_INFO_IF(bShrinkOnly, "svx", "Case bShrinkOnly == true is not implemented yet."); |
2924 | | |
2925 | 23 | if (rMaxRect.IsEmpty() || rMaxRect == GetSnapRect()) |
2926 | 0 | return; |
2927 | | |
2928 | | // Get a matrix, that would produce the existing shape, when applied to a unit square |
2929 | 23 | basegfx::B2DPolyPolygon aPolyPolygon; //not used, but formal needed |
2930 | 23 | basegfx::B2DHomMatrix aMatrix; |
2931 | 23 | TRGetBaseGeometry(aMatrix, aPolyPolygon); |
2932 | | // Using TRSetBaseGeometry(aMatrix, aPolyPolygon) would regenerate the current shape. But |
2933 | | // applying aMatrix to a unit square will not generate the current shape. Scaling, |
2934 | | // rotation and translation are correct, but shear angle has wrong sign. So break up |
2935 | | // matrix and create a mathematically correct new one. |
2936 | 23 | basegfx::B2DTuple aScale; |
2937 | 23 | basegfx::B2DTuple aTranslate; |
2938 | 23 | double fRotate, fShearX; |
2939 | 23 | aMatrix.decompose(aScale, aTranslate, fRotate, fShearX); |
2940 | 23 | basegfx::B2DHomMatrix aMathMatrix; |
2941 | 23 | aMathMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
2942 | 23 | aScale, |
2943 | 23 | -fShearX, |
2944 | 23 | fRotate, |
2945 | 23 | aTranslate); |
2946 | | |
2947 | | // Calculate scaling factors from size of the transformed unit polygon as ersatz for the not |
2948 | | // usable current snap rectangle. |
2949 | 23 | basegfx::B2DPolygon aB2DPolygon(basegfx::utils::createUnitPolygon()); |
2950 | 23 | aB2DPolygon.transform(aMathMatrix); |
2951 | 23 | basegfx::B2DRange aB2DRange(aB2DPolygon.getB2DRange()); |
2952 | 23 | double fPolygonWidth = aB2DRange.getWidth(); |
2953 | 23 | if (fPolygonWidth == 0) |
2954 | 0 | fPolygonWidth = 1; |
2955 | 23 | double fPolygonHeight = aB2DRange.getHeight(); |
2956 | 23 | if (fPolygonHeight == 0) |
2957 | 0 | fPolygonHeight = 1; |
2958 | 23 | const double aFactorX = static_cast<double>(rMaxRect.GetWidth()) / fPolygonWidth; |
2959 | 23 | const double aFactorY = static_cast<double>(rMaxRect.GetHeight()) / fPolygonHeight; |
2960 | | |
2961 | | // Generate matrix, that would produce the desired rMaxRect when applied to unit square |
2962 | 23 | aMathMatrix.scale(aFactorX, aFactorY); |
2963 | 23 | aB2DPolygon = basegfx::utils::createUnitPolygon(); |
2964 | 23 | aB2DPolygon.transform(aMathMatrix); |
2965 | 23 | aB2DRange = aB2DPolygon.getB2DRange(); |
2966 | 23 | const double fPolygonLeft = aB2DRange.getMinX(); |
2967 | 23 | const double fPolygonTop = aB2DRange.getMinY(); |
2968 | 23 | aMathMatrix.translate(rMaxRect.Left() - fPolygonLeft, rMaxRect.Top() - fPolygonTop); |
2969 | | |
2970 | | // Create a Matrix from aMathMatrix, which is usable with TRSetBaseGeometry |
2971 | 23 | aMathMatrix.decompose(aScale, aTranslate, fRotate, fShearX); |
2972 | 23 | aMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
2973 | 23 | aScale, |
2974 | 23 | -fShearX, |
2975 | 23 | fRotate, |
2976 | 23 | aTranslate); |
2977 | | |
2978 | | // Now use TRSetBaseGeometry to actually perform scale, shear, rotate and translate |
2979 | | // on the shape. That considers gluepoints, interaction handles and text area, and includes |
2980 | | // setting rectangles dirty and broadcast. |
2981 | 23 | TRSetBaseGeometry(aMatrix, aPolyPolygon); |
2982 | 23 | } |
2983 | | |
2984 | | void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) |
2985 | 21.4k | { |
2986 | | // The shape might have already flipping in its enhanced geometry. LibreOffice applies |
2987 | | // such after all transformations. We remove it, but remember it to apply them later. |
2988 | 21.4k | bool bIsMirroredX = IsMirroredX(); |
2989 | 21.4k | bool bIsMirroredY = IsMirroredY(); |
2990 | 21.4k | if (bIsMirroredX || bIsMirroredY) |
2991 | 0 | { |
2992 | 0 | Point aCurrentCenter = GetSnapRect().Center(); |
2993 | 0 | if (bIsMirroredX) // mirror on the y-axis |
2994 | 0 | { |
2995 | 0 | Mirror(aCurrentCenter, Point(aCurrentCenter.X(), aCurrentCenter.Y() + 1000)); |
2996 | 0 | } |
2997 | 0 | if (bIsMirroredY) // mirror on the x-axis |
2998 | 0 | { |
2999 | 0 | Mirror(aCurrentCenter, Point(aCurrentCenter.X() + 1000, aCurrentCenter.Y())); |
3000 | 0 | } |
3001 | 0 | } |
3002 | | |
3003 | | // break up matrix |
3004 | 21.4k | basegfx::B2DTuple aScale; |
3005 | 21.4k | basegfx::B2DTuple aTranslate; |
3006 | 21.4k | double fRotate, fShearX; |
3007 | 21.4k | rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); |
3008 | | |
3009 | | // reset object shear and rotations |
3010 | 21.4k | m_fObjectRotation = 0.0; |
3011 | 21.4k | maGeo.m_nRotationAngle = 0_deg100; |
3012 | 21.4k | maGeo.RecalcSinCos(); |
3013 | 21.4k | maGeo.m_nShearAngle = 0_deg100; |
3014 | 21.4k | maGeo.RecalcTan(); |
3015 | | |
3016 | | // if anchor is used, make position relative to it |
3017 | 21.4k | if(getSdrModelFromSdrObject().IsWriter()) |
3018 | 2.49k | { |
3019 | 2.49k | if(GetAnchorPos().X() || GetAnchorPos().Y()) |
3020 | 0 | { |
3021 | 0 | aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); |
3022 | 0 | } |
3023 | 2.49k | } |
3024 | | |
3025 | | // scale |
3026 | 21.4k | Size aSize(basegfx::fround<tools::Long>(fabs(aScale.getX())), |
3027 | 21.4k | basegfx::fround<tools::Long>(fabs(aScale.getY()))); |
3028 | | // fdo#47434 We need a valid rectangle here |
3029 | 21.4k | if( !aSize.Height() ) aSize.setHeight( 1 ); |
3030 | 21.4k | if( !aSize.Width() ) aSize.setWidth( 1 ); |
3031 | 21.4k | tools::Rectangle aBaseRect(Point(), aSize); |
3032 | 21.4k | SetLogicRect(aBaseRect); |
3033 | | |
3034 | | // Apply flipping from Matrix, which is a transformation relative to origin |
3035 | 21.4k | if (aScale.getX() < 0.0) |
3036 | 0 | Mirror(Point(0, 0), Point(0, 1000)); // mirror on the y-axis |
3037 | 21.4k | if (aScale.getY() < 0.0) |
3038 | 0 | Mirror(Point(0, 0), Point(1000, 0)); // mirror on the x-axis |
3039 | | |
3040 | | // shear? |
3041 | 21.4k | if(!basegfx::fTools::equalZero(fShearX)) |
3042 | 0 | { |
3043 | 0 | GeoStat aGeoStat; |
3044 | | // #i123181# The fix for #121932# here was wrong, the trunk version does not correct the |
3045 | | // mirrored shear values, neither at the object level, nor on the API or XML level. Taking |
3046 | | // back the mirroring of the shear angle |
3047 | 0 | aGeoStat.m_nShearAngle = Degree100(basegfx::fround(basegfx::rad2deg<100>(atan(fShearX)))); |
3048 | 0 | aGeoStat.RecalcTan(); |
3049 | 0 | Shear(Point(), aGeoStat.m_nShearAngle, aGeoStat.mfTanShearAngle, false); |
3050 | 0 | } |
3051 | | |
3052 | | // rotation? |
3053 | 21.4k | if(!basegfx::fTools::equalZero(fRotate)) |
3054 | 2.30k | { |
3055 | 2.30k | GeoStat aGeoStat; |
3056 | | |
3057 | | // #i78696# |
3058 | | // fRotate is mathematically correct, but aGeoStat.nRotationAngle is |
3059 | | // mirrored -> mirror value here |
3060 | 2.30k | aGeoStat.m_nRotationAngle = NormAngle36000(Degree100(basegfx::fround(-basegfx::rad2deg<100>(fRotate)))); |
3061 | 2.30k | aGeoStat.RecalcSinCos(); |
3062 | 2.30k | Rotate(Point(), aGeoStat.m_nRotationAngle, aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle); |
3063 | 2.30k | } |
3064 | | |
3065 | | // translate? |
3066 | 21.4k | if(!aTranslate.equalZero()) |
3067 | 19.7k | { |
3068 | 19.7k | Move(Size(basegfx::fround<tools::Long>(aTranslate.getX()), |
3069 | 19.7k | basegfx::fround<tools::Long>(aTranslate.getY()))); |
3070 | 19.7k | } |
3071 | | |
3072 | | // Apply flipping from enhanced geometry at center of the shape. |
3073 | 21.4k | if (!(bIsMirroredX || bIsMirroredY)) |
3074 | 21.4k | return; |
3075 | | |
3076 | | // create mathematically matrix for the applied transformations |
3077 | | // aScale was in most cases built from a rectangle including edge |
3078 | | // and is therefore mathematically too large by 1 |
3079 | 0 | if (aScale.getX() > 2.0 && aScale.getY() > 2.0) |
3080 | 0 | aScale -= basegfx::B2DTuple(1.0, 1.0); |
3081 | 0 | basegfx::B2DHomMatrix aMathMat = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
3082 | 0 | aScale, -fShearX, fRotate, |
3083 | 0 | aTranslate); |
3084 | | // Use matrix to get current center |
3085 | 0 | basegfx::B2DPoint aCenter(0.5,0.5); |
3086 | 0 | aCenter = aMathMat * aCenter; |
3087 | 0 | double fCenterX = aCenter.getX(); |
3088 | 0 | double fCenterY = aCenter.getY(); |
3089 | 0 | if (bIsMirroredX) // vertical axis |
3090 | 0 | Mirror(Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY)), |
3091 | 0 | Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY + 1000.0))); |
3092 | 0 | if (bIsMirroredY) // horizontal axis |
3093 | 0 | Mirror(Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY)), |
3094 | 0 | Point(basegfx::fround<tools::Long>(fCenterX + 1000.0), basegfx::fround<tools::Long>(fCenterY))); |
3095 | 0 | } |
3096 | | |
3097 | | // taking fObjectRotation instead of aGeo.nAngle |
3098 | | bool SdrObjCustomShape::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const |
3099 | 21.4k | { |
3100 | | // get turn and shear |
3101 | 21.4k | double fRotate = basegfx::deg2rad(m_fObjectRotation); |
3102 | 21.4k | double fShearX = toRadians(maGeo.m_nShearAngle); |
3103 | | |
3104 | | // get aRectangle, this is the unrotated snaprect |
3105 | 21.4k | tools::Rectangle aRectangle(getRectangle()); |
3106 | | |
3107 | 21.4k | bool bMirroredX = IsMirroredX(); |
3108 | 21.4k | bool bMirroredY = IsMirroredY(); |
3109 | 21.4k | if ( bMirroredX || bMirroredY ) |
3110 | 0 | { // we have to retrieve the unmirrored rect |
3111 | |
|
3112 | 0 | GeoStat aNewGeo(maGeo); |
3113 | |
|
3114 | 0 | if ( bMirroredX ) |
3115 | 0 | { |
3116 | 0 | fShearX = -fShearX; |
3117 | 0 | tools::Polygon aPol = Rect2Poly(getRectangle(), aNewGeo); |
3118 | 0 | tools::Rectangle aBoundRect( aPol.GetBoundRect() ); |
3119 | |
|
3120 | 0 | Point aRef1( ( aBoundRect.Left() + aBoundRect.Right() ) >> 1, aBoundRect.Top() ); |
3121 | 0 | Point aRef2( aRef1.X(), aRef1.Y() + 1000 ); |
3122 | 0 | sal_uInt16 i; |
3123 | 0 | sal_uInt16 nPointCount=aPol.GetSize(); |
3124 | 0 | for (i=0; i<nPointCount; i++) |
3125 | 0 | { |
3126 | 0 | MirrorPoint(aPol[i],aRef1,aRef2); |
3127 | 0 | } |
3128 | | // mirror polygon and move it a bit |
3129 | 0 | tools::Polygon aPol0(aPol); |
3130 | 0 | aPol[0]=aPol0[1]; |
3131 | 0 | aPol[1]=aPol0[0]; |
3132 | 0 | aPol[2]=aPol0[3]; |
3133 | 0 | aPol[3]=aPol0[2]; |
3134 | 0 | aPol[4]=aPol0[1]; |
3135 | 0 | aRectangle = svx::polygonToRectangle(aPol, aNewGeo); |
3136 | 0 | } |
3137 | 0 | if ( bMirroredY ) |
3138 | 0 | { |
3139 | 0 | fShearX = -fShearX; |
3140 | 0 | tools::Polygon aPol( Rect2Poly( aRectangle, aNewGeo ) ); |
3141 | 0 | tools::Rectangle aBoundRect( aPol.GetBoundRect() ); |
3142 | |
|
3143 | 0 | Point aRef1( aBoundRect.Left(), ( aBoundRect.Top() + aBoundRect.Bottom() ) >> 1 ); |
3144 | 0 | Point aRef2( aRef1.X() + 1000, aRef1.Y() ); |
3145 | 0 | sal_uInt16 i; |
3146 | 0 | sal_uInt16 nPointCount=aPol.GetSize(); |
3147 | 0 | for (i=0; i<nPointCount; i++) |
3148 | 0 | { |
3149 | 0 | MirrorPoint(aPol[i],aRef1,aRef2); |
3150 | 0 | } |
3151 | | // mirror polygon and move it a bit |
3152 | 0 | tools::Polygon aPol0(aPol); |
3153 | 0 | aPol[0]=aPol0[1]; // This was WRONG for vertical (!) |
3154 | 0 | aPol[1]=aPol0[0]; // #i121932# Despite my own comment above |
3155 | 0 | aPol[2]=aPol0[3]; // it was *not* wrong even when the reordering |
3156 | 0 | aPol[3]=aPol0[2]; // *seems* to be specific for X-Mirrorings. Oh |
3157 | 0 | aPol[4]=aPol0[1]; // will I be happy when this old stuff is |gone| with aw080 (!) |
3158 | 0 | aRectangle = svx::polygonToRectangle(aPol, aNewGeo); |
3159 | 0 | } |
3160 | 0 | } |
3161 | | |
3162 | | // fill other values |
3163 | 21.4k | basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); |
3164 | 21.4k | basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); |
3165 | | |
3166 | | // position may be relative to anchorpos, convert |
3167 | 21.4k | if(getSdrModelFromSdrObject().IsWriter()) |
3168 | 2.49k | { |
3169 | 2.49k | if(GetAnchorPos().X() || GetAnchorPos().Y()) |
3170 | 0 | { |
3171 | 0 | aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); |
3172 | 0 | } |
3173 | 2.49k | } |
3174 | | |
3175 | | // build matrix |
3176 | 21.4k | rMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
3177 | 21.4k | aScale, |
3178 | 21.4k | basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), |
3179 | 21.4k | -fRotate, |
3180 | 21.4k | aTranslate); |
3181 | | |
3182 | 21.4k | return false; |
3183 | 21.4k | } |
3184 | | |
3185 | | std::unique_ptr<sdr::contact::ViewContact> SdrObjCustomShape::CreateObjectSpecificViewContact() |
3186 | 152k | { |
3187 | 152k | return std::make_unique<sdr::contact::ViewContactOfSdrObjCustomShape>(*this); |
3188 | 152k | } |
3189 | | |
3190 | | // #i33136# |
3191 | | bool SdrObjCustomShape::doConstructOrthogonal(std::u16string_view rName) |
3192 | 0 | { |
3193 | 0 | bool bRetval(false); |
3194 | |
|
3195 | 0 | if(o3tl::equalsIgnoreAsciiCase(rName, u"quadrat")) |
3196 | 0 | { |
3197 | 0 | bRetval = true; |
3198 | 0 | } |
3199 | 0 | else if(o3tl::equalsIgnoreAsciiCase(rName, u"round-quadrat")) |
3200 | 0 | { |
3201 | 0 | bRetval = true; |
3202 | 0 | } |
3203 | 0 | else if(o3tl::equalsIgnoreAsciiCase(rName, u"circle")) |
3204 | 0 | { |
3205 | 0 | bRetval = true; |
3206 | 0 | } |
3207 | 0 | else if(o3tl::equalsIgnoreAsciiCase(rName, u"circle-pie")) |
3208 | 0 | { |
3209 | 0 | bRetval = true; |
3210 | 0 | } |
3211 | 0 | else if(o3tl::equalsIgnoreAsciiCase(rName, u"ring")) |
3212 | 0 | { |
3213 | 0 | bRetval = true; |
3214 | 0 | } |
3215 | |
|
3216 | 0 | return bRetval; |
3217 | 0 | } |
3218 | | |
3219 | | // #i37011# centralize throw-away of render geometry |
3220 | | void SdrObjCustomShape::InvalidateRenderGeometry() |
3221 | 5.88M | { |
3222 | 5.88M | mXRenderedCustomShape = nullptr; |
3223 | 5.88M | mpLastShadowGeometry = nullptr; |
3224 | 5.88M | } |
3225 | | |
3226 | | void SdrObjCustomShape::setUnoShape(const uno::Reference<drawing::XShape>& rxUnoShape) |
3227 | 839k | { |
3228 | 839k | SdrTextObj::setUnoShape(rxUnoShape); |
3229 | | |
3230 | | // The shape engine is created with _current_ shape. This means we |
3231 | | // _must_ reset it when the shape changes. |
3232 | 839k | mxCustomShapeEngine.clear(); |
3233 | 839k | } |
3234 | | |
3235 | | OUString SdrObjCustomShape::GetCustomShapeName() const |
3236 | 0 | { |
3237 | 0 | OUString sShapeName; |
3238 | 0 | OUString aEngine( GetMergedItem( SDRATTR_CUSTOMSHAPE_ENGINE ).GetValue() ); |
3239 | 0 | if ( aEngine.isEmpty() |
3240 | 0 | || aEngine == "com.sun.star.drawing.EnhancedCustomShapeEngine" ) |
3241 | 0 | { |
3242 | 0 | OUString sShapeType; |
3243 | 0 | const SdrCustomShapeGeometryItem& rGeometryItem( GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); |
3244 | 0 | const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( u"Type"_ustr ); |
3245 | 0 | if ( pAny && ( *pAny >>= sShapeType ) ) |
3246 | 0 | sShapeName = EnhancedCustomShapeTypeNames::GetAccName( sShapeType ); |
3247 | 0 | } |
3248 | 0 | return sShapeName; |
3249 | 0 | } |
3250 | | |
3251 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |