cid#1606940 Check of thread-shared field evades lock acquisition
[LibreOffice.git] / svx / source / sdr / primitive2d / sdrattributecreator.cxx
blob185f691e38891b4bae8932d952395d769f0037a5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sdr/primitive2d/sdrattributecreator.hxx>
21 #include <svl/itemset.hxx>
22 #include <svx/sdmetitm.hxx>
23 #include <svx/sdooitm.hxx>
24 #include <svx/sdprcitm.hxx>
25 #include <svx/xdef.hxx>
26 #include <basegfx/polygon/b2dpolygon.hxx>
27 #include <svx/xlineit0.hxx>
28 #include <svx/xfillit0.hxx>
29 #include <svx/xflbmpit.hxx>
30 #include <svx/xlntrit.hxx>
31 #include <svx/xlnwtit.hxx>
32 #include <svx/xlinjoit.hxx>
33 #include <svx/xlncapit.hxx>
34 #include <svx/xlnclit.hxx>
35 #include <svx/xlnstwit.hxx>
36 #include <svx/xlnedwit.hxx>
37 #include <svx/xlnstit.hxx>
38 #include <svx/xlnstcit.hxx>
39 #include <svx/xlnedit.hxx>
40 #include <svx/xlnedcit.hxx>
41 #include <svx/xdash.hxx>
42 #include <svx/xlndsit.hxx>
43 #include <svx/xfilluseslidebackgrounditem.hxx>
44 #include <svx/xfltrit.hxx>
45 #include <svx/xflftrit.hxx>
46 #include <svx/xflclit.hxx>
47 #include <svx/xgrscit.hxx>
48 #include <svx/xflhtit.hxx>
49 #include <svx/xflbckit.hxx>
50 #include <svx/xflbmsxy.hxx>
51 #include <svx/xflbtoxy.hxx>
52 #include <svx/xflboxy.hxx>
53 #include <svx/xflbmtit.hxx>
54 #include <svx/xflbstit.hxx>
55 #include <svx/xtextit0.hxx>
56 #include <svx/RectangleAlignmentItem.hxx>
57 #include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
58 #include <svx/svdotext.hxx>
59 #include <sdr/attribute/sdrtextattribute.hxx>
60 #include <svx/xbtmpit.hxx>
61 #include <svl/itempool.hxx>
62 #include <vcl/svapp.hxx>
63 #include <vcl/GraphicLoader.hxx>
64 #include <basegfx/range/b2drange.hxx>
65 #include <svx/svx3ditems.hxx>
66 #include <com/sun/star/drawing/ProjectionMode.hpp>
67 #include <com/sun/star/drawing/ShadeMode.hpp>
68 #include <drawinglayer/attribute/sdrallattribute3d.hxx>
69 #include <svx/rectenum.hxx>
70 #include <svx/sdtfchim.hxx>
71 #include <svx/svdoutl.hxx>
72 #include <svx/svdmodel.hxx>
73 #include <svx/xflbmsli.hxx>
74 #include <editeng/editstat.hxx>
75 #include <editeng/eeitem.hxx>
76 #include <editeng/fhgtitem.hxx>
77 #include <editeng/editobj.hxx>
78 #include <osl/diagnose.h>
79 #include <drawinglayer/attribute/fillhatchattribute.hxx>
80 #include <drawinglayer/attribute/fillgradientattribute.hxx>
81 #include <sdr/attribute/sdreffectstextattribute.hxx>
82 #include <sdr/attribute/sdrlineeffectstextattribute.hxx>
83 #include <sdr/attribute/sdrformtextattribute.hxx>
84 #include <sdr/attribute/sdrlinefilleffectstextattribute.hxx>
85 #include <drawinglayer/attribute/sdrglowattribute.hxx>
86 #include <drawinglayer/attribute/sdrglowtextattribute.hxx>
87 #include <drawinglayer/attribute/sdrsceneattribute3d.hxx>
88 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
89 #include <drawinglayer/attribute/sdrlightattribute3d.hxx>
90 #include <sdr/attribute/sdrfilltextattribute.hxx>
91 #include <com/sun/star/drawing/LineCap.hpp>
93 #include <math.h>
95 using namespace com::sun::star;
97 namespace drawinglayer
99 namespace
101 attribute::HatchStyle XHatchStyleToHatchStyle(css::drawing::HatchStyle eStyle)
103 switch(eStyle)
105 case css::drawing::HatchStyle_SINGLE :
107 return attribute::HatchStyle::Single;
109 case css::drawing::HatchStyle_DOUBLE :
111 return attribute::HatchStyle::Double;
113 default :
115 return attribute::HatchStyle::Triple; // css::drawing::HatchStyle_TRIPLE
120 basegfx::B2DLineJoin LineJointToB2DLineJoin(css::drawing::LineJoint eLineJoint)
122 switch(eLineJoint)
124 case css::drawing::LineJoint_BEVEL :
126 return basegfx::B2DLineJoin::Bevel;
128 case css::drawing::LineJoint_MIDDLE :
129 case css::drawing::LineJoint_MITER :
131 return basegfx::B2DLineJoin::Miter;
133 case css::drawing::LineJoint_ROUND :
135 return basegfx::B2DLineJoin::Round;
137 default : // css::drawing::LineJoint_NONE
139 return basegfx::B2DLineJoin::NONE;
144 basegfx::B2DVector RectPointToB2DVector(RectPoint eRectPoint)
146 basegfx::B2DVector aRetval(0.0, 0.0);
148 // position changes X
149 switch(eRectPoint)
151 case RectPoint::LT: case RectPoint::LM: case RectPoint::LB:
153 aRetval.setX(-1.0);
154 break;
157 case RectPoint::RT: case RectPoint::RM: case RectPoint::RB:
159 aRetval.setX(1.0);
160 break;
163 default :
165 break;
169 // position changes Y
170 switch(eRectPoint)
172 case RectPoint::LT: case RectPoint::MT: case RectPoint::RT:
174 aRetval.setY(-1.0);
175 break;
178 case RectPoint::LB: case RectPoint::MB: case RectPoint::RB:
180 aRetval.setY(1.0);
181 break;
184 default :
186 break;
190 return aRetval;
193 attribute::SdrGlowAttribute createNewSdrGlowAttribute(const SfxItemSet& rSet)
195 sal_Int32 nRadius = rSet.Get(SDRATTR_GLOW_RADIUS).GetValue();
197 if (!nRadius)
198 return attribute::SdrGlowAttribute();
200 Color aColor(rSet.Get(SDRATTR_GLOW_COLOR).GetColorValue());
202 sal_uInt16 nTransparency(rSet.Get(SDRATTR_GLOW_TRANSPARENCY).GetValue());
203 if (nTransparency)
204 aColor.SetAlpha(255 - std::round(nTransparency / 100.0 * 255.0));
206 attribute::SdrGlowAttribute glowAttr{ nRadius, aColor };
207 return glowAttr;
210 attribute::SdrGlowTextAttribute createNewSdrGlowTextAttribute(const SfxItemSet& rSet, const OutlinerParaObject* pOutliner)
212 sal_Int32 nTextRadius = rSet.Get(SDRATTR_GLOW_TEXT_RADIUS).GetValue();
214 if (!nTextRadius)
215 return attribute::SdrGlowTextAttribute();
217 Color aTextColor(rSet.Get(SDRATTR_GLOW_TEXT_COLOR).GetColorValue());
219 sal_uInt16 nTextTransparency(rSet.Get(SDRATTR_GLOW_TEXT_TRANSPARENCY).GetValue());
220 if (nTextTransparency)
221 aTextColor.SetAlpha(255 - std::round(nTextTransparency / 100.0 * 255.0));
223 // calculate rendering text glow radius from biggest Char size for the full text in shape
224 double nRadius = 0.0;
225 sal_uInt32 nFontSize = 0;
226 if (const SvxFontHeightItem* pItem = rSet.GetItemIfSet(EE_CHAR_FONTHEIGHT))
227 nFontSize = pItem->GetHeight();
229 if (pOutliner)
231 const EditTextObject& aEdit = pOutliner->GetTextObject();
232 for (sal_Int32 i = 0; i < aEdit.GetParagraphCount(); i++)
234 std::vector<EECharAttrib> aAttribs;
235 aEdit.GetCharAttribs(i, aAttribs);
236 for (const auto& attrib : aAttribs)
238 if (const SvxFontHeightItem* pFontHeight = dynamic_cast<const SvxFontHeightItem*>(attrib.pAttr))
240 if (nFontSize < pFontHeight->GetHeight())
241 nFontSize = pFontHeight->GetHeight();
247 if (nFontSize)
249 // Rendering_glow_size = Original_glow_size / (154.39 * FontSize ^ -0,575)
250 // This is an approximate calculation similar to MSO text glow size which is
251 // depending on font size
252 nRadius = nTextRadius / (154.39 * pow(nFontSize, -0.575));
253 nTextRadius = std::round(nRadius);
256 attribute::SdrGlowTextAttribute glowTextAttr{ nTextRadius, aTextColor };
257 return glowTextAttr;
260 sal_Int32 getSoftEdgeRadius(const SfxItemSet& rSet)
262 return rSet.Get(SDRATTR_SOFTEDGE_RADIUS).GetValue();
264 } // end of anonymous namespace
265 } // end of namespace drawinglayer
268 namespace drawinglayer::primitive2d
270 attribute::SdrLineAttribute createNewSdrLineAttribute(const SfxItemSet& rSet)
272 const css::drawing::LineStyle eStyle(rSet.Get(XATTR_LINESTYLE).GetValue());
274 if(drawing::LineStyle_NONE != eStyle)
276 sal_uInt16 nTransparence(rSet.Get(XATTR_LINETRANSPARENCE).GetValue());
278 if(nTransparence > 100)
280 nTransparence = 100;
283 if(100 != nTransparence)
285 const sal_uInt32 nWidth(rSet.Get(XATTR_LINEWIDTH).GetValue());
286 const Color aColor(rSet.Get(XATTR_LINECOLOR).GetColorValue());
287 const css::drawing::LineJoint eJoint(rSet.Get(XATTR_LINEJOINT).GetValue());
288 const css::drawing::LineCap eCap(rSet.Get(XATTR_LINECAP).GetValue());
289 ::std::vector< double > aDotDashArray;
290 double fFullDotDashLen(0.0);
292 if(drawing::LineStyle_DASH == eStyle)
294 const XDash& rDash = rSet.Get(XATTR_LINEDASH).GetDashValue();
296 if(rDash.GetDots() || rDash.GetDashes())
298 fFullDotDashLen = rDash.CreateDotDashArray(aDotDashArray, static_cast<double>(nWidth));
302 return attribute::SdrLineAttribute(
303 LineJointToB2DLineJoin(eJoint),
304 static_cast<double>(nWidth),
305 static_cast<double>(nTransparence) * 0.01,
306 aColor.getBColor(),
307 eCap,
308 std::move(aDotDashArray),
309 fFullDotDashLen);
313 return attribute::SdrLineAttribute();
316 attribute::SdrLineStartEndAttribute createNewSdrLineStartEndAttribute(
317 const SfxItemSet& rSet,
318 double fWidth)
320 const sal_Int32 nTempStartWidth(rSet.Get(XATTR_LINESTARTWIDTH).GetValue());
321 const sal_Int32 nTempEndWidth(rSet.Get(XATTR_LINEENDWIDTH).GetValue());
322 basegfx::B2DPolyPolygon aStartPolyPolygon;
323 basegfx::B2DPolyPolygon aEndPolyPolygon;
324 double fStartWidth(0.0);
325 double fEndWidth(0.0);
326 bool bStartActive(false);
327 bool bEndActive(false);
328 bool bStartCentered(true);
329 bool bEndCentered(true);
331 if(nTempStartWidth)
333 if(nTempStartWidth < 0)
335 fStartWidth = (static_cast<double>(-nTempStartWidth) * fWidth) * 0.01;
337 else
339 fStartWidth = static_cast<double>(nTempStartWidth);
342 if(0.0 != fStartWidth)
344 aStartPolyPolygon = rSet.Get(XATTR_LINESTART).GetLineStartValue();
346 if(aStartPolyPolygon.count() && aStartPolyPolygon.getB2DPolygon(0).count())
348 bStartActive = true;
349 bStartCentered = rSet.Get(XATTR_LINESTARTCENTER).GetValue();
354 if(nTempEndWidth)
356 if(nTempEndWidth < 0)
358 fEndWidth = (static_cast<double>(-nTempEndWidth) * fWidth) * 0.01;
360 else
362 fEndWidth = static_cast<double>(nTempEndWidth);
365 if(0.0 != fEndWidth)
367 aEndPolyPolygon = rSet.Get(XATTR_LINEEND).GetLineEndValue();
369 if(aEndPolyPolygon.count() && aEndPolyPolygon.getB2DPolygon(0).count())
371 bEndActive = true;
372 bEndCentered = rSet.Get(XATTR_LINEENDCENTER).GetValue();
377 if(bStartActive || bEndActive)
379 return attribute::SdrLineStartEndAttribute(
380 aStartPolyPolygon, aEndPolyPolygon, fStartWidth, fEndWidth,
381 bStartActive, bEndActive, bStartCentered, bEndCentered);
384 return attribute::SdrLineStartEndAttribute();
387 attribute::SdrShadowAttribute createNewSdrShadowAttribute(const SfxItemSet& rSet)
389 const bool bShadow(rSet.Get(SDRATTR_SHADOW).GetValue());
391 if(bShadow)
393 sal_uInt16 nTransparence(rSet.Get(SDRATTR_SHADOWTRANSPARENCE).GetValue());
395 if(nTransparence > 100)
397 nTransparence = 100;
400 if(nTransparence)
402 sal_uInt16 nFillTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
404 if(nFillTransparence > 100)
406 nFillTransparence = 100;
409 if(nTransparence == nFillTransparence)
411 // shadow does not really have an own transparence, but the application
412 // sets the shadow transparence equal to the object transparence for
413 // convenience. This is not useful for primitive creation, so take
414 // this as no shadow transparence
415 nTransparence = 0;
419 if(100 != nTransparence)
421 const basegfx::B2DVector aOffset(
422 static_cast<double>(rSet.Get(SDRATTR_SHADOWXDIST).GetValue()),
423 static_cast<double>(rSet.Get(SDRATTR_SHADOWYDIST).GetValue()));
425 const basegfx::B2DVector aSize(
426 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEX).GetValue()),
427 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEY).GetValue()));
429 const Color aColor(rSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue());
431 sal_Int32 nBlur(rSet.Get(SDRATTR_SHADOWBLUR).GetValue());
433 model::RectangleAlignment eAlignment{rSet.Get(SDRATTR_SHADOWALIGNMENT).GetValue()};
435 return attribute::SdrShadowAttribute(aOffset, aSize, static_cast<double>(nTransparence) * 0.01, nBlur, eAlignment, aColor.getBColor());
439 return attribute::SdrShadowAttribute();
442 attribute::SdrFillAttribute createNewSdrFillAttribute(const SfxItemSet& rSet)
444 const drawing::FillStyle eStyle(rSet.Get(XATTR_FILLSTYLE).GetValue());
446 sal_uInt16 nTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
448 if(nTransparence > 100)
450 nTransparence = 100;
453 if(drawing::FillStyle_NONE == eStyle)
455 const XFillUseSlideBackgroundItem& aBckItem(rSet.Get(XATTR_FILLUSESLIDEBACKGROUND));
456 const bool bSlideBackgroundFill(aBckItem.GetValue());
458 if(bSlideBackgroundFill)
460 // we have SlideBackgroundFill mode, create a
461 // SdrFillAttribute accordingly
462 return attribute::SdrFillAttribute(true);
466 if(drawing::FillStyle_NONE != eStyle)
468 if(100 != nTransparence)
470 // need to check XFillFloatTransparence, object fill may still be completely transparent
471 const XFillFloatTransparenceItem* pGradientItem;
473 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE, true))
474 && pGradientItem->IsEnabled())
476 const basegfx::BGradient& rGradient = pGradientItem->GetGradientValue();
477 basegfx::BColor aSingleColor;
478 const bool bSingleColor(rGradient.GetColorStops().isSingleColor(aSingleColor));
479 const bool bCompletelyTransparent(bSingleColor && basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
481 if(bCompletelyTransparent)
483 nTransparence = 100;
488 if(100 != nTransparence)
490 const Color aColor(rSet.Get(XATTR_FILLCOLOR).GetColorValue());
491 attribute::FillGradientAttribute aGradient;
492 attribute::FillHatchAttribute aHatch;
493 attribute::SdrFillGraphicAttribute aFillGraphic;
495 switch(eStyle)
497 default:
499 // nothing to do, color is defined
500 break;
502 case drawing::FillStyle_GRADIENT :
504 basegfx::BGradient aBGradient(rSet.Get(XATTR_FILLGRADIENT).GetGradientValue());
505 basegfx::BColorStops aColorStops(aBGradient.GetColorStops());
508 if (aBGradient.GetStartIntens() != 100 || aBGradient.GetEndIntens() != 100)
510 // Need to do the (old, crazy) blend against black for a
511 // used intensity, but now for all ColorStops relative to their
512 // offsets, where 0 means black and 100 means original color
513 aColorStops.blendToIntensity(
514 aBGradient.GetStartIntens() * 0.01,
515 aBGradient.GetEndIntens() * 0.01,
516 basegfx::BColor()); // COL_BLACK
519 aGradient = attribute::FillGradientAttribute(
520 aBGradient.GetGradientStyle(),
521 static_cast<double>(aBGradient.GetBorder()) * 0.01,
522 static_cast<double>(aBGradient.GetXOffset()) * 0.01,
523 static_cast<double>(aBGradient.GetYOffset()) * 0.01,
524 toRadians(aBGradient.GetAngle()),
525 aColorStops,
526 rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue());
528 break;
530 case drawing::FillStyle_HATCH :
532 const XHatch& rHatch(rSet.Get(XATTR_FILLHATCH).GetHatchValue());
533 const Color aColorB(rHatch.GetColor());
535 aHatch = attribute::FillHatchAttribute(
536 XHatchStyleToHatchStyle(rHatch.GetHatchStyle()),
537 static_cast<double>(rHatch.GetDistance()),
538 toRadians(rHatch.GetAngle()),
539 aColorB.getBColor(),
540 3, // same default as VCL, a minimum of three discrete units (pixels) offset
541 rSet.Get(XATTR_FILLBACKGROUND).GetValue());
543 break;
545 case drawing::FillStyle_BITMAP :
547 aFillGraphic = createNewSdrFillGraphicAttribute(rSet);
548 break;
552 return attribute::SdrFillAttribute(
553 static_cast<double>(nTransparence) * 0.01,
554 aColor.getBColor(),
555 aGradient,
556 aHatch,
557 aFillGraphic);
561 if(nTransparence == 100)
563 attribute::FillGradientAttribute aGradient;
564 attribute::FillHatchAttribute aHatch;
565 attribute::SdrFillGraphicAttribute aFillGraphic;
566 return attribute::SdrFillAttribute(
568 basegfx::BColor( 0, 0, 0 ),
569 aGradient,
570 aHatch,
571 aFillGraphic);
574 return attribute::SdrFillAttribute();
577 // #i101508# Support handing over given text-to-border distances
578 attribute::SdrTextAttribute createNewSdrTextAttribute(
579 const SfxItemSet& rSet,
580 const SdrText& rText,
581 const sal_Int32* pLeft,
582 const sal_Int32* pUpper,
583 const sal_Int32* pRight,
584 const sal_Int32* pLower)
586 const SdrTextObj& rTextObj = rText.GetObject();
588 // Save chaining attributes
589 bool bChainable = rTextObj.IsChainable();
591 // get OutlinerParaObject
592 std::optional<OutlinerParaObject> aOutlinerParaObject;
594 // 1st try to get from rText
595 if(rText.GetOutlinerParaObject())
597 aOutlinerParaObject.emplace(*rText.GetOutlinerParaObject());
600 // added TextEdit text suppression - check if rText is in EditMode
601 bool bInEditMode(false);
603 if(rText.GetObject().getTextCount() > 1)
605 bInEditMode = rTextObj.IsInEditMode() && rText.GetObject().getActiveText() == &rText;
607 else
609 bInEditMode = rTextObj.IsInEditMode();
612 if(bInEditMode)
614 // if yes, try to get OutlinerParaObject from active TextEdit
615 std::optional<OutlinerParaObject> aTextEditOutlinerParaObject(rTextObj.CreateEditOutlinerParaObject());
617 if (aTextEditOutlinerParaObject)
619 // if we got one, prefer text from active TextEdit
620 aOutlinerParaObject = std::move(aTextEditOutlinerParaObject);
624 if(aOutlinerParaObject)
626 const SdrTextAniKind eAniKind(rTextObj.GetTextAniKind());
628 // #i107346#
629 const SdrOutliner& rDrawTextOutliner(rText.GetObject().getSdrModelFromSdrObject().GetDrawOutliner(&rTextObj));
630 const bool bWrongSpell(rDrawTextOutliner.GetControlWord() & EEControlBits::ONLINESPELLING);
632 return attribute::SdrTextAttribute(
633 rText,
634 *aOutlinerParaObject,
635 rSet.Get(XATTR_FORMTXTSTYLE).GetValue(),
636 pLeft ? *pLeft : rTextObj.GetTextLeftDistance(),
637 pUpper ? *pUpper : rTextObj.GetTextUpperDistance(),
638 pRight ? *pRight : rTextObj.GetTextRightDistance(),
639 pLower ? *pLower : rTextObj.GetTextLowerDistance(),
640 rTextObj.GetTextHorizontalAdjust(rSet),
641 rTextObj.GetTextVerticalAdjust(rSet),
642 rSet.Get(SDRATTR_TEXT_CONTOURFRAME).GetValue(),
643 rTextObj.IsFitToSize(),
644 rTextObj.IsAutoFit(),
645 rSet.Get(XATTR_FORMTXTHIDEFORM).GetValue(),
646 SdrTextAniKind::Blink == eAniKind,
647 SdrTextAniKind::Scroll == eAniKind || SdrTextAniKind::Alternate == eAniKind || SdrTextAniKind::Slide == eAniKind,
648 bInEditMode,
649 rSet.Get(SDRATTR_TEXT_USEFIXEDCELLHEIGHT).GetValue(),
650 bWrongSpell,
651 bChainable);
654 return attribute::SdrTextAttribute();
657 attribute::FillGradientAttribute createNewTransparenceGradientAttribute(const SfxItemSet& rSet)
659 const XFillFloatTransparenceItem* pGradientItem;
661 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE))
662 && pGradientItem->IsEnabled())
664 // test if float transparency is completely transparent
665 const basegfx::BGradient& rGradient(pGradientItem->GetGradientValue());
666 basegfx::BColor aSingleColor;
667 const bool bSingleColor(rGradient.GetColorStops().isSingleColor(aSingleColor));
668 const bool bCompletelyTransparent(bSingleColor && basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
669 const bool bNotTransparent(bSingleColor && basegfx::fTools::equalZero(aSingleColor.luminance()));
671 // create nothing when completely transparent: This case is already checked for the
672 // normal fill attributes, XFILL_NONE will be used.
673 // create nothing when not transparent: use normal fill, no need t create a FillGradientAttribute.
674 // Both cases are optimizations, always creating FillGradientAttribute will work, too
675 if (!bNotTransparent && !bCompletelyTransparent)
677 basegfx::BColorStops aColorStops(rGradient.GetColorStops());
679 if (rGradient.GetStartIntens() != 100 || rGradient.GetEndIntens() != 100)
681 // tdf#155913 Start/EndIntens is not used for transparency gradient,
682 // so might even get asserted (?)
683 // this may also be set for transparence, so need to take care of it
684 aColorStops.blendToIntensity(
685 rGradient.GetStartIntens() * 0.01,
686 rGradient.GetEndIntens() * 0.01,
687 basegfx::BColor()); // COL_BLACK
690 // tdf#155913 GradientStepCount is not used for transparency gradient
691 return attribute::FillGradientAttribute(
692 rGradient.GetGradientStyle(),
693 static_cast<double>(rGradient.GetBorder()) * 0.01,
694 static_cast<double>(rGradient.GetXOffset()) * 0.01,
695 static_cast<double>(rGradient.GetYOffset()) * 0.01,
696 toRadians(rGradient.GetAngle()),
697 aColorStops);
701 return attribute::FillGradientAttribute();
704 attribute::SdrFillGraphicAttribute createNewSdrFillGraphicAttribute(const SfxItemSet& rSet)
706 Graphic aGraphic(rSet.Get(XATTR_FILLBITMAP).GetGraphicObject().GetGraphic());
708 OUString aOriginURL = aGraphic.getOriginURL();
709 if (aGraphic.GetType() == GraphicType::Default && !aOriginURL.isEmpty())
711 aGraphic = vcl::graphic::loadFromURL(aGraphic.getOriginURL());
712 aGraphic.setOriginURL(aOriginURL);
715 if(GraphicType::Bitmap != aGraphic.GetType() && GraphicType::GdiMetafile != aGraphic.GetType())
717 // no content if not bitmap or metafile
718 OSL_ENSURE(false, "No fill graphic in SfxItemSet (!)");
719 return attribute::SdrFillGraphicAttribute();
722 Size aPrefSize(aGraphic.GetPrefSize());
724 if(!aPrefSize.Width() || !aPrefSize.Height())
726 // if there is no logical size, create a size from pixel size and set MapMode accordingly
727 if(GraphicType::Bitmap == aGraphic.GetType())
729 aGraphic.SetPrefSize(aGraphic.GetBitmapEx().GetSizePixel());
730 aGraphic.SetPrefMapMode(MapMode(MapUnit::MapPixel));
731 aPrefSize = aGraphic.GetPrefSize();
735 if(!aPrefSize.Width() || !aPrefSize.Height())
737 // no content if no size
738 OSL_ENSURE(false, "Graphic has no size in SfxItemSet (!)");
739 return attribute::SdrFillGraphicAttribute();
742 // convert size and MapMode to destination logical size and MapMode
743 const MapUnit aDestinationMapUnit(rSet.GetPool()->GetMetric(0));
744 basegfx::B2DVector aGraphicLogicSize(aGraphic.GetPrefSize().Width(), aGraphic.GetPrefSize().Height());
746 if (aGraphic.GetPrefMapMode().GetMapUnit() != aDestinationMapUnit)
748 // #i100360# for MapUnit::MapPixel, LogicToLogic will not work properly,
749 // so fallback to Application::GetDefaultDevice()
750 Size aNewSize(0, 0);
752 if(MapUnit::MapPixel == aGraphic.GetPrefMapMode().GetMapUnit())
754 aNewSize = Application::GetDefaultDevice()->PixelToLogic(
755 aGraphic.GetPrefSize(),
756 MapMode(aDestinationMapUnit));
758 else
760 aNewSize = OutputDevice::LogicToLogic(
761 aGraphic.GetPrefSize(),
762 aGraphic.GetPrefMapMode(),
763 MapMode(aDestinationMapUnit));
766 // #i124002# do not set new size using SetPrefSize at the graphic, this will lead to problems.
767 // Instead, adapt the GraphicLogicSize which will be used for further decompositions
768 aGraphicLogicSize = basegfx::B2DVector(aNewSize.Width(), aNewSize.Height());
771 // get size
772 const basegfx::B2DVector aSize(
773 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEX).GetValue()),
774 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEY).GetValue()));
775 const basegfx::B2DVector aOffset(
776 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETX).GetValue()),
777 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETY).GetValue()));
778 const basegfx::B2DVector aOffsetPosition(
779 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETX).GetValue()),
780 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETY).GetValue()));
782 return attribute::SdrFillGraphicAttribute(
783 aGraphic,
784 aGraphicLogicSize,
785 aSize,
786 aOffset,
787 aOffsetPosition,
788 RectPointToB2DVector(rSet.GetItem<XFillBmpPosItem>(XATTR_FILLBMP_POS)->GetValue()),
789 rSet.Get(XATTR_FILLBMP_TILE).GetValue(),
790 rSet.Get(XATTR_FILLBMP_STRETCH).GetValue(),
791 rSet.Get(XATTR_FILLBMP_SIZELOG).GetValue());
794 attribute::SdrEffectsTextAttribute createNewSdrEffectsTextAttribute(
795 const SfxItemSet& rSet,
796 const SdrText* pText,
797 bool bSuppressText)
799 attribute::SdrTextAttribute aText;
801 // #i98072# added option to suppress text
802 // look for text first
803 if(!bSuppressText && pText)
805 aText = createNewSdrTextAttribute(rSet, *pText);
808 // try shadow
809 const attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet));
810 const attribute::SdrGlowAttribute aGlow(createNewSdrGlowAttribute(rSet));
811 const OutlinerParaObject* pOutliner = pText ? pText->GetObject().GetOutlinerParaObject() : nullptr;
812 const attribute::SdrGlowTextAttribute aGlowText(createNewSdrGlowTextAttribute(rSet, pOutliner));
813 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
815 return attribute::SdrEffectsTextAttribute(aShadow, std::move(aText),
816 aGlow, aGlowText, nSoftEdgeRadius);
819 attribute::SdrLineEffectsTextAttribute createNewSdrLineEffectsTextAttribute(
820 const SfxItemSet& rSet,
821 const SdrText* pText)
823 attribute::SdrLineAttribute aLine;
824 attribute::SdrLineStartEndAttribute aLineStartEnd;
825 attribute::SdrTextAttribute aText;
826 bool bFontworkHideContour(false);
828 // look for text first
829 if(pText)
831 aText = createNewSdrTextAttribute(rSet, *pText);
833 // when object has text and text is fontwork and hide contour is set for fontwork, force
834 // line and fill style to empty
835 if(!aText.isDefault()
836 && !aText.getSdrFormTextAttribute().isDefault()
837 && aText.isHideContour())
839 bFontworkHideContour = true;
843 // try line style
844 if(!bFontworkHideContour)
846 aLine = createNewSdrLineAttribute(rSet);
848 if(!aLine.isDefault())
850 // try LineStartEnd
851 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
855 if(!aLine.isDefault() || !aText.isDefault())
857 // try shadow
858 attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet));
859 attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet);
860 const OutlinerParaObject* pOutliner = pText ? pText->GetObject().GetOutlinerParaObject() : nullptr;
861 attribute::SdrGlowTextAttribute aGlowText = createNewSdrGlowTextAttribute(rSet, pOutliner);
862 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
864 return attribute::SdrLineEffectsTextAttribute(std::move(aLine),
865 std::move(aLineStartEnd),
866 std::move(aShadow),
867 std::move(aText),
868 std::move(aGlow),
869 std::move(aGlowText), nSoftEdgeRadius);
872 return attribute::SdrLineEffectsTextAttribute();
875 attribute::SdrLineFillEffectsTextAttribute createNewSdrLineFillEffectsTextAttribute(
876 const SfxItemSet& rSet,
877 const SdrText* pText,
878 bool bHasContent,
879 bool bSuppressShadow)
881 attribute::SdrLineAttribute aLine;
882 attribute::SdrFillAttribute aFill;
883 attribute::SdrLineStartEndAttribute aLineStartEnd;
884 attribute::FillGradientAttribute aFillFloatTransGradient;
885 attribute::SdrTextAttribute aText;
886 bool bFontworkHideContour(false);
888 // look for text first
889 if(pText)
891 aText = createNewSdrTextAttribute(rSet, *pText);
893 // when object has text and text is fontwork and hide contour is set for fontwork, force
894 // line and fill style to empty
895 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour())
897 bFontworkHideContour = true;
901 if(!bFontworkHideContour)
903 // try line style
904 aLine = createNewSdrLineAttribute(rSet);
906 if(!aLine.isDefault())
908 // try LineStartEnd
909 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
912 // try fill style
913 aFill = createNewSdrFillAttribute(rSet);
915 if(!aFill.isDefault())
917 // try fillfloattransparence
918 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
922 // bHasContent is used from OLE and graphic objects. Normally a possible shadow
923 // depends on line, fill or text to be set, but for these objects it is possible
924 // to have none of these, but still content which needs to have a shadow (if set),
925 // so shadow needs to be tried
926 if(bHasContent || !aLine.isDefault() || !aFill.isDefault() || !aText.isDefault())
928 // try shadow
929 const attribute::SdrShadowAttribute aShadow = !bSuppressShadow ?
930 createNewSdrShadowAttribute(rSet) : attribute::SdrShadowAttribute();
932 // glow
933 const attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet);
935 // text glow
936 const OutlinerParaObject* pOutliner = pText ? pText->GetObject().GetOutlinerParaObject() : nullptr;
937 const attribute::SdrGlowTextAttribute aGlowText = createNewSdrGlowTextAttribute(rSet, pOutliner);
939 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
941 return attribute::SdrLineFillEffectsTextAttribute(aLine, std::move(aFill), aLineStartEnd,
942 aShadow, std::move(aFillFloatTransGradient),
943 aText, aGlow, aGlowText, nSoftEdgeRadius);
946 return attribute::SdrLineFillEffectsTextAttribute();
949 attribute::SdrLineFillShadowAttribute3D createNewSdrLineFillShadowAttribute(const SfxItemSet& rSet, bool bSuppressFill)
951 attribute::SdrFillAttribute aFill;
952 attribute::SdrLineStartEndAttribute aLineStartEnd;
953 attribute::SdrShadowAttribute aShadow;
954 attribute::FillGradientAttribute aFillFloatTransGradient;
956 // try line style
957 attribute::SdrLineAttribute aLine(createNewSdrLineAttribute(rSet));
959 if(!aLine.isDefault())
961 // try LineStartEnd
962 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
965 // try fill style
966 if(!bSuppressFill)
968 aFill = createNewSdrFillAttribute(rSet);
970 if(!aFill.isDefault())
972 // try fillfloattransparence
973 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
977 if(!aLine.isDefault() || !aFill.isDefault())
979 // try shadow
980 aShadow = createNewSdrShadowAttribute(rSet);
982 return attribute::SdrLineFillShadowAttribute3D(
983 std::move(aLine), std::move(aFill), std::move(aLineStartEnd),
984 std::move(aShadow), std::move(aFillFloatTransGradient));
987 return attribute::SdrLineFillShadowAttribute3D();
990 attribute::SdrSceneAttribute createNewSdrSceneAttribute(const SfxItemSet& rSet)
992 // get perspective
993 css::drawing::ProjectionMode aProjectionMode(css::drawing::ProjectionMode_PARALLEL);
994 const sal_uInt16 nProjectionValue(rSet.Get(SDRATTR_3DSCENE_PERSPECTIVE).GetValue());
996 if(1 == nProjectionValue)
998 aProjectionMode = css::drawing::ProjectionMode_PERSPECTIVE;
1001 // get distance
1002 const double fDistance(rSet.Get(SDRATTR_3DSCENE_DISTANCE).GetValue());
1004 // get shadow slant
1005 const double fShadowSlant(
1006 basegfx::deg2rad(rSet.Get(SDRATTR_3DSCENE_SHADOW_SLANT).GetValue()));
1008 // get shade mode
1009 css::drawing::ShadeMode aShadeMode(css::drawing::ShadeMode_FLAT);
1010 const sal_uInt16 nShadeValue(rSet.Get(SDRATTR_3DSCENE_SHADE_MODE).GetValue());
1012 if(1 == nShadeValue)
1014 aShadeMode = css::drawing::ShadeMode_PHONG;
1016 else if(2 == nShadeValue)
1018 aShadeMode = css::drawing::ShadeMode_SMOOTH;
1020 else if(3 == nShadeValue)
1022 aShadeMode = css::drawing::ShadeMode_DRAFT;
1025 // get two sided lighting
1026 const bool bTwoSidedLighting(rSet.Get(SDRATTR_3DSCENE_TWO_SIDED_LIGHTING).GetValue());
1028 return attribute::SdrSceneAttribute(fDistance, fShadowSlant, aProjectionMode, aShadeMode, bTwoSidedLighting);
1031 attribute::SdrLightingAttribute createNewSdrLightingAttribute(const SfxItemSet& rSet)
1033 // extract lights from given SfxItemSet (from scene)
1034 ::std::vector< attribute::Sdr3DLightAttribute > aLightVector;
1036 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue())
1038 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue().getBColor());
1039 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue());
1040 aLightVector.emplace_back(aColor, aDirection, true);
1043 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue())
1045 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue().getBColor());
1046 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue());
1047 aLightVector.emplace_back(aColor, aDirection, false);
1050 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue())
1052 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue().getBColor());
1053 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue());
1054 aLightVector.emplace_back(aColor, aDirection, false);
1057 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue())
1059 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue().getBColor());
1060 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue());
1061 aLightVector.emplace_back(aColor, aDirection, false);
1064 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue())
1066 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue().getBColor());
1067 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue());
1068 aLightVector.emplace_back(aColor, aDirection, false);
1071 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue())
1073 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue().getBColor());
1074 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue());
1075 aLightVector.emplace_back(aColor, aDirection, false);
1078 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue())
1080 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue().getBColor());
1081 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue());
1082 aLightVector.emplace_back(aColor, aDirection, false);
1085 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue())
1087 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue().getBColor());
1088 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue());
1089 aLightVector.emplace_back(aColor, aDirection, false);
1092 // get ambient color
1093 const Color aAmbientValue(rSet.Get(SDRATTR_3DSCENE_AMBIENTCOLOR).GetValue());
1094 const basegfx::BColor aAmbientLight(aAmbientValue.getBColor());
1096 return attribute::SdrLightingAttribute(aAmbientLight, std::move(aLightVector));
1099 void calculateRelativeCornerRadius(sal_Int32 nRadius, const basegfx::B2DRange& rObjectRange, double& rfCornerRadiusX, double& rfCornerRadiusY)
1101 rfCornerRadiusX = rfCornerRadiusY = static_cast<double>(nRadius);
1103 if(0.0 != rfCornerRadiusX)
1105 const double fHalfObjectWidth(rObjectRange.getWidth() * 0.5);
1107 if(0.0 != fHalfObjectWidth)
1109 if(rfCornerRadiusX < 0.0)
1111 rfCornerRadiusX = 0.0;
1114 if(rfCornerRadiusX > fHalfObjectWidth)
1116 rfCornerRadiusX = fHalfObjectWidth;
1119 rfCornerRadiusX /= fHalfObjectWidth;
1121 else
1123 rfCornerRadiusX = 0.0;
1127 if(0.0 == rfCornerRadiusY)
1128 return;
1130 const double fHalfObjectHeight(rObjectRange.getHeight() * 0.5);
1132 if(0.0 != fHalfObjectHeight)
1134 if(rfCornerRadiusY < 0.0)
1136 rfCornerRadiusY = 0.0;
1139 if(rfCornerRadiusY > fHalfObjectHeight)
1141 rfCornerRadiusY = fHalfObjectHeight;
1144 rfCornerRadiusY /= fHalfObjectHeight;
1146 else
1148 rfCornerRadiusY = 0.0;
1152 // #i101508# Support handing over given text-to-border distances
1153 attribute::SdrFillTextAttribute createNewSdrFillTextAttribute(
1154 const SfxItemSet& rSet,
1155 const SdrText* pText,
1156 const sal_Int32* pLeft,
1157 const sal_Int32* pUpper,
1158 const sal_Int32* pRight,
1159 const sal_Int32* pLower)
1161 attribute::SdrFillAttribute aFill;
1162 attribute::FillGradientAttribute aFillFloatTransGradient;
1163 attribute::SdrTextAttribute aText;
1164 bool bFontworkHideContour(false);
1166 // look for text first
1167 if(pText)
1169 aText = createNewSdrTextAttribute(rSet, *pText, pLeft, pUpper, pRight, pLower);
1171 // when object has text and text is fontwork and hide contour is set for fontwork, force
1172 // fill style to empty
1173 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour())
1175 bFontworkHideContour = true;
1179 if(!bFontworkHideContour)
1181 // try fill style
1182 aFill = createNewSdrFillAttribute(rSet);
1184 if(!aFill.isDefault())
1186 // try fillfloattransparence
1187 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
1191 if (!aFill.isDefault() || !aText.isDefault())
1193 return attribute::SdrFillTextAttribute(std::move(aFill),
1194 std::move(aFillFloatTransGradient),
1195 std::move(aText));
1198 return attribute::SdrFillTextAttribute();
1201 } // end of namespace
1203 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */