Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / sdr / primitive2d / sdrattributecreator.cxx
blob2b9f9b767763858ff6737ef22e4976f6d3b8b972
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 <basegfx/utils/gradienttools.hxx>
66 #include <svx/svx3ditems.hxx>
67 #include <com/sun/star/drawing/ProjectionMode.hpp>
68 #include <com/sun/star/drawing/ShadeMode.hpp>
69 #include <drawinglayer/attribute/sdrallattribute3d.hxx>
70 #include <svx/rectenum.hxx>
71 #include <svx/sdtfchim.hxx>
72 #include <svx/svdoutl.hxx>
73 #include <svx/svdmodel.hxx>
74 #include <svx/xflbmsli.hxx>
75 #include <editeng/editstat.hxx>
76 #include <osl/diagnose.h>
77 #include <drawinglayer/attribute/fillhatchattribute.hxx>
78 #include <drawinglayer/attribute/fillgradientattribute.hxx>
79 #include <sdr/attribute/sdreffectstextattribute.hxx>
80 #include <sdr/attribute/sdrlineeffectstextattribute.hxx>
81 #include <sdr/attribute/sdrformtextattribute.hxx>
82 #include <sdr/attribute/sdrlinefilleffectstextattribute.hxx>
83 #include <drawinglayer/attribute/sdrglowattribute.hxx>
84 #include <drawinglayer/attribute/sdrsceneattribute3d.hxx>
85 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
86 #include <drawinglayer/attribute/sdrlightattribute3d.hxx>
87 #include <sdr/attribute/sdrfilltextattribute.hxx>
88 #include <com/sun/star/drawing/LineCap.hpp>
90 using namespace com::sun::star;
92 namespace drawinglayer
94 namespace
96 attribute::HatchStyle XHatchStyleToHatchStyle(css::drawing::HatchStyle eStyle)
98 switch(eStyle)
100 case css::drawing::HatchStyle_SINGLE :
102 return attribute::HatchStyle::Single;
104 case css::drawing::HatchStyle_DOUBLE :
106 return attribute::HatchStyle::Double;
108 default :
110 return attribute::HatchStyle::Triple; // css::drawing::HatchStyle_TRIPLE
115 basegfx::B2DLineJoin LineJointToB2DLineJoin(css::drawing::LineJoint eLineJoint)
117 switch(eLineJoint)
119 case css::drawing::LineJoint_BEVEL :
121 return basegfx::B2DLineJoin::Bevel;
123 case css::drawing::LineJoint_MIDDLE :
124 case css::drawing::LineJoint_MITER :
126 return basegfx::B2DLineJoin::Miter;
128 case css::drawing::LineJoint_ROUND :
130 return basegfx::B2DLineJoin::Round;
132 default : // css::drawing::LineJoint_NONE
134 return basegfx::B2DLineJoin::NONE;
139 basegfx::B2DVector RectPointToB2DVector(RectPoint eRectPoint)
141 basegfx::B2DVector aRetval(0.0, 0.0);
143 // position changes X
144 switch(eRectPoint)
146 case RectPoint::LT: case RectPoint::LM: case RectPoint::LB:
148 aRetval.setX(-1.0);
149 break;
152 case RectPoint::RT: case RectPoint::RM: case RectPoint::RB:
154 aRetval.setX(1.0);
155 break;
158 default :
160 break;
164 // position changes Y
165 switch(eRectPoint)
167 case RectPoint::LT: case RectPoint::MT: case RectPoint::RT:
169 aRetval.setY(-1.0);
170 break;
173 case RectPoint::LB: case RectPoint::MB: case RectPoint::RB:
175 aRetval.setY(1.0);
176 break;
179 default :
181 break;
185 return aRetval;
188 attribute::SdrGlowAttribute createNewSdrGlowAttribute(const SfxItemSet& rSet)
190 sal_Int32 nRadius = rSet.Get(SDRATTR_GLOW_RADIUS).GetValue();
191 if (!nRadius)
192 return attribute::SdrGlowAttribute();
193 Color aColor(rSet.Get(SDRATTR_GLOW_COLOR).GetColorValue());
194 sal_uInt16 nTransparency(rSet.Get(SDRATTR_GLOW_TRANSPARENCY).GetValue());
195 if (nTransparency)
196 aColor.SetAlpha(255 - std::round(nTransparency / 100.0 * 255.0));
198 attribute::SdrGlowAttribute glowAttr{ nRadius, aColor };
199 return glowAttr;
202 sal_Int32 getSoftEdgeRadius(const SfxItemSet& rSet)
204 return rSet.Get(SDRATTR_SOFTEDGE_RADIUS).GetValue();
206 } // end of anonymous namespace
207 } // end of namespace drawinglayer
210 namespace drawinglayer::primitive2d
212 attribute::SdrLineAttribute createNewSdrLineAttribute(const SfxItemSet& rSet)
214 const css::drawing::LineStyle eStyle(rSet.Get(XATTR_LINESTYLE).GetValue());
216 if(drawing::LineStyle_NONE != eStyle)
218 sal_uInt16 nTransparence(rSet.Get(XATTR_LINETRANSPARENCE).GetValue());
220 if(nTransparence > 100)
222 nTransparence = 100;
225 if(100 != nTransparence)
227 const sal_uInt32 nWidth(rSet.Get(XATTR_LINEWIDTH).GetValue());
228 const Color aColor(rSet.Get(XATTR_LINECOLOR).GetColorValue());
229 const css::drawing::LineJoint eJoint(rSet.Get(XATTR_LINEJOINT).GetValue());
230 const css::drawing::LineCap eCap(rSet.Get(XATTR_LINECAP).GetValue());
231 ::std::vector< double > aDotDashArray;
232 double fFullDotDashLen(0.0);
234 if(drawing::LineStyle_DASH == eStyle)
236 const XDash& rDash = rSet.Get(XATTR_LINEDASH).GetDashValue();
238 if(rDash.GetDots() || rDash.GetDashes())
240 fFullDotDashLen = rDash.CreateDotDashArray(aDotDashArray, static_cast<double>(nWidth));
244 return attribute::SdrLineAttribute(
245 LineJointToB2DLineJoin(eJoint),
246 static_cast<double>(nWidth),
247 static_cast<double>(nTransparence) * 0.01,
248 aColor.getBColor(),
249 eCap,
250 std::move(aDotDashArray),
251 fFullDotDashLen);
255 return attribute::SdrLineAttribute();
258 attribute::SdrLineStartEndAttribute createNewSdrLineStartEndAttribute(
259 const SfxItemSet& rSet,
260 double fWidth)
262 const sal_Int32 nTempStartWidth(rSet.Get(XATTR_LINESTARTWIDTH).GetValue());
263 const sal_Int32 nTempEndWidth(rSet.Get(XATTR_LINEENDWIDTH).GetValue());
264 basegfx::B2DPolyPolygon aStartPolyPolygon;
265 basegfx::B2DPolyPolygon aEndPolyPolygon;
266 double fStartWidth(0.0);
267 double fEndWidth(0.0);
268 bool bStartActive(false);
269 bool bEndActive(false);
270 bool bStartCentered(true);
271 bool bEndCentered(true);
273 if(nTempStartWidth)
275 if(nTempStartWidth < 0)
277 fStartWidth = (static_cast<double>(-nTempStartWidth) * fWidth) * 0.01;
279 else
281 fStartWidth = static_cast<double>(nTempStartWidth);
284 if(0.0 != fStartWidth)
286 aStartPolyPolygon = rSet.Get(XATTR_LINESTART).GetLineStartValue();
288 if(aStartPolyPolygon.count() && aStartPolyPolygon.getB2DPolygon(0).count())
290 bStartActive = true;
291 bStartCentered = rSet.Get(XATTR_LINESTARTCENTER).GetValue();
296 if(nTempEndWidth)
298 if(nTempEndWidth < 0)
300 fEndWidth = (static_cast<double>(-nTempEndWidth) * fWidth) * 0.01;
302 else
304 fEndWidth = static_cast<double>(nTempEndWidth);
307 if(0.0 != fEndWidth)
309 aEndPolyPolygon = rSet.Get(XATTR_LINEEND).GetLineEndValue();
311 if(aEndPolyPolygon.count() && aEndPolyPolygon.getB2DPolygon(0).count())
313 bEndActive = true;
314 bEndCentered = rSet.Get(XATTR_LINEENDCENTER).GetValue();
319 if(bStartActive || bEndActive)
321 return attribute::SdrLineStartEndAttribute(
322 aStartPolyPolygon, aEndPolyPolygon, fStartWidth, fEndWidth,
323 bStartActive, bEndActive, bStartCentered, bEndCentered);
326 return attribute::SdrLineStartEndAttribute();
329 attribute::SdrShadowAttribute createNewSdrShadowAttribute(const SfxItemSet& rSet)
331 const bool bShadow(rSet.Get(SDRATTR_SHADOW).GetValue());
333 if(bShadow)
335 sal_uInt16 nTransparence(rSet.Get(SDRATTR_SHADOWTRANSPARENCE).GetValue());
337 if(nTransparence > 100)
339 nTransparence = 100;
342 if(nTransparence)
344 sal_uInt16 nFillTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
346 if(nFillTransparence > 100)
348 nFillTransparence = 100;
351 if(nTransparence == nFillTransparence)
353 // shadow does not really have an own transparence, but the application
354 // sets the shadow transparence equal to the object transparence for
355 // convenience. This is not useful for primitive creation, so take
356 // this as no shadow transparence
357 nTransparence = 0;
361 if(100 != nTransparence)
363 const basegfx::B2DVector aOffset(
364 static_cast<double>(rSet.Get(SDRATTR_SHADOWXDIST).GetValue()),
365 static_cast<double>(rSet.Get(SDRATTR_SHADOWYDIST).GetValue()));
367 const basegfx::B2DVector aSize(
368 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEX).GetValue()),
369 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEY).GetValue()));
371 const Color aColor(rSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue());
373 sal_Int32 nBlur(rSet.Get(SDRATTR_SHADOWBLUR).GetValue());
375 model::RectangleAlignment eAlignment{rSet.Get(SDRATTR_SHADOWALIGNMENT).GetValue()};
377 return attribute::SdrShadowAttribute(aOffset, aSize, static_cast<double>(nTransparence) * 0.01, nBlur, eAlignment, aColor.getBColor());
381 return attribute::SdrShadowAttribute();
384 attribute::SdrFillAttribute createNewSdrFillAttribute(const SfxItemSet& rSet)
386 const drawing::FillStyle eStyle(rSet.Get(XATTR_FILLSTYLE).GetValue());
388 sal_uInt16 nTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
390 if(nTransparence > 100)
392 nTransparence = 100;
395 if(drawing::FillStyle_NONE == eStyle)
397 XFillUseSlideBackgroundItem aBckItem(rSet.Get(XATTR_FILLUSESLIDEBACKGROUND));
398 const bool bSlideBackgroundFill(aBckItem.GetValue());
400 if(bSlideBackgroundFill)
402 // we have SlideBackgroundFill mode, create a
403 // SdrFillAttribute accordingly
404 return attribute::SdrFillAttribute(true);
408 if(drawing::FillStyle_NONE != eStyle)
410 if(100 != nTransparence)
412 // need to check XFillFloatTransparence, object fill may still be completely transparent
413 const XFillFloatTransparenceItem* pGradientItem;
415 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE, true))
416 && pGradientItem->IsEnabled())
418 const basegfx::BGradient& rGradient = pGradientItem->GetGradientValue();
419 basegfx::BColor aSingleColor;
420 const bool bSingleColor(rGradient.GetColorStops().isSingleColor(aSingleColor));
421 const bool bCompletelyTransparent(bSingleColor && basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
423 if(bCompletelyTransparent)
425 nTransparence = 100;
430 if(100 != nTransparence)
432 const Color aColor(rSet.Get(XATTR_FILLCOLOR).GetColorValue());
433 attribute::FillGradientAttribute aGradient;
434 attribute::FillHatchAttribute aHatch;
435 attribute::SdrFillGraphicAttribute aFillGraphic;
437 switch(eStyle)
439 default:
441 // nothing to do, color is defined
442 break;
444 case drawing::FillStyle_GRADIENT :
446 basegfx::BGradient aBGradient(rSet.Get(XATTR_FILLGRADIENT).GetGradientValue());
447 basegfx::BColorStops aColorStops(aBGradient.GetColorStops());
450 if (aBGradient.GetStartIntens() != 100 || aBGradient.GetEndIntens() != 100)
452 // Need to do the (old, crazy) blend against black for a
453 // used intensity, but now for all ColorStops relative to their
454 // offsets, where 0 means black and 100 means original color
455 aColorStops.blendToIntensity(
456 aBGradient.GetStartIntens() * 0.01,
457 aBGradient.GetEndIntens() * 0.01,
458 basegfx::BColor()); // COL_BLACK
461 aGradient = attribute::FillGradientAttribute(
462 aBGradient.GetGradientStyle(),
463 static_cast<double>(aBGradient.GetBorder()) * 0.01,
464 static_cast<double>(aBGradient.GetXOffset()) * 0.01,
465 static_cast<double>(aBGradient.GetYOffset()) * 0.01,
466 toRadians(aBGradient.GetAngle()),
467 aColorStops,
468 rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue());
470 break;
472 case drawing::FillStyle_HATCH :
474 const XHatch& rHatch(rSet.Get(XATTR_FILLHATCH).GetHatchValue());
475 const Color aColorB(rHatch.GetColor());
477 aHatch = attribute::FillHatchAttribute(
478 XHatchStyleToHatchStyle(rHatch.GetHatchStyle()),
479 static_cast<double>(rHatch.GetDistance()),
480 toRadians(rHatch.GetAngle()),
481 aColorB.getBColor(),
482 3, // same default as VCL, a minimum of three discrete units (pixels) offset
483 rSet.Get(XATTR_FILLBACKGROUND).GetValue());
485 break;
487 case drawing::FillStyle_BITMAP :
489 aFillGraphic = createNewSdrFillGraphicAttribute(rSet);
490 break;
494 return attribute::SdrFillAttribute(
495 static_cast<double>(nTransparence) * 0.01,
496 aColor.getBColor(),
497 aGradient,
498 aHatch,
499 aFillGraphic);
503 if(nTransparence == 100)
505 attribute::FillGradientAttribute aGradient;
506 attribute::FillHatchAttribute aHatch;
507 attribute::SdrFillGraphicAttribute aFillGraphic;
508 return attribute::SdrFillAttribute(
510 basegfx::BColor( 0, 0, 0 ),
511 aGradient,
512 aHatch,
513 aFillGraphic);
516 return attribute::SdrFillAttribute();
519 // #i101508# Support handing over given text-to-border distances
520 attribute::SdrTextAttribute createNewSdrTextAttribute(
521 const SfxItemSet& rSet,
522 const SdrText& rText,
523 const sal_Int32* pLeft,
524 const sal_Int32* pUpper,
525 const sal_Int32* pRight,
526 const sal_Int32* pLower)
528 const SdrTextObj& rTextObj = rText.GetObject();
530 // Save chaining attributes
531 bool bChainable = rTextObj.IsChainable();
534 if(rText.GetOutlinerParaObject())
536 // added TextEdit text suppression
537 bool bInEditMode(false);
539 if(rText.GetObject().getTextCount() > 1)
541 bInEditMode = rTextObj.IsInEditMode() && rText.GetObject().getActiveText() == &rText;
543 else
545 bInEditMode = rTextObj.IsInEditMode();
548 OutlinerParaObject aOutlinerParaObject(*rText.GetOutlinerParaObject());
550 if(bInEditMode)
552 std::optional<OutlinerParaObject> pTempObj = rTextObj.CreateEditOutlinerParaObject();
554 if(pTempObj)
556 aOutlinerParaObject = *pTempObj;
558 else
560 // #i100537#
561 // CreateEditOutlinerParaObject() returning no object does not mean that
562 // text edit mode is not active. Do not reset the flag here
563 // bInEditMode = false;
567 const SdrTextAniKind eAniKind(rTextObj.GetTextAniKind());
569 // #i107346#
570 const SdrOutliner& rDrawTextOutliner(rText.GetObject().getSdrModelFromSdrObject().GetDrawOutliner(&rTextObj));
571 const bool bWrongSpell(rDrawTextOutliner.GetControlWord() & EEControlBits::ONLINESPELLING);
573 return attribute::SdrTextAttribute(
574 rText,
575 aOutlinerParaObject,
576 rSet.Get(XATTR_FORMTXTSTYLE).GetValue(),
577 pLeft ? *pLeft : rTextObj.GetTextLeftDistance(),
578 pUpper ? *pUpper : rTextObj.GetTextUpperDistance(),
579 pRight ? *pRight : rTextObj.GetTextRightDistance(),
580 pLower ? *pLower : rTextObj.GetTextLowerDistance(),
581 rTextObj.GetTextHorizontalAdjust(rSet),
582 rTextObj.GetTextVerticalAdjust(rSet),
583 rSet.Get(SDRATTR_TEXT_CONTOURFRAME).GetValue(),
584 rTextObj.IsFitToSize(),
585 rTextObj.IsAutoFit(),
586 rSet.Get(XATTR_FORMTXTHIDEFORM).GetValue(),
587 SdrTextAniKind::Blink == eAniKind,
588 SdrTextAniKind::Scroll == eAniKind || SdrTextAniKind::Alternate == eAniKind || SdrTextAniKind::Slide == eAniKind,
589 bInEditMode,
590 rSet.Get(SDRATTR_TEXT_USEFIXEDCELLHEIGHT).GetValue(),
591 bWrongSpell,
592 bChainable);
595 return attribute::SdrTextAttribute();
598 attribute::FillGradientAttribute createNewTransparenceGradientAttribute(const SfxItemSet& rSet)
600 const XFillFloatTransparenceItem* pGradientItem;
602 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE))
603 && pGradientItem->IsEnabled())
605 // test if float transparency is completely transparent
606 const basegfx::BGradient& rGradient(pGradientItem->GetGradientValue());
607 basegfx::BColor aSingleColor;
608 const bool bSingleColor(rGradient.GetColorStops().isSingleColor(aSingleColor));
609 const bool bCompletelyTransparent(bSingleColor && basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
610 const bool bNotTransparent(bSingleColor && basegfx::fTools::equalZero(aSingleColor.luminance()));
612 // create nothing when completely transparent: This case is already checked for the
613 // normal fill attributes, XFILL_NONE will be used.
614 // create nothing when not transparent: use normal fill, no need t create a FillGradientAttribute.
615 // Both cases are optimizations, always creating FillGradientAttribute will work, too
616 if (!bNotTransparent && !bCompletelyTransparent)
618 basegfx::BColorStops aColorStops(rGradient.GetColorStops());
620 if (rGradient.GetStartIntens() != 100 || rGradient.GetEndIntens() != 100)
622 // tdf#155913 Start/EndIntens is not used for transparency gradient,
623 // so might even get asserted (?)
624 // this may also be set for transparence, so need to take care of it
625 aColorStops.blendToIntensity(
626 rGradient.GetStartIntens() * 0.01,
627 rGradient.GetEndIntens() * 0.01,
628 basegfx::BColor()); // COL_BLACK
631 // tdf#155913 GradientStepCount is not used for transparency gradient
632 return attribute::FillGradientAttribute(
633 rGradient.GetGradientStyle(),
634 static_cast<double>(rGradient.GetBorder()) * 0.01,
635 static_cast<double>(rGradient.GetXOffset()) * 0.01,
636 static_cast<double>(rGradient.GetYOffset()) * 0.01,
637 toRadians(rGradient.GetAngle()),
638 aColorStops);
642 return attribute::FillGradientAttribute();
645 attribute::SdrFillGraphicAttribute createNewSdrFillGraphicAttribute(const SfxItemSet& rSet)
647 Graphic aGraphic(rSet.Get(XATTR_FILLBITMAP).GetGraphicObject().GetGraphic());
649 OUString aOriginURL = aGraphic.getOriginURL();
650 if (aGraphic.GetType() == GraphicType::Default && !aOriginURL.isEmpty())
652 aGraphic = vcl::graphic::loadFromURL(aGraphic.getOriginURL());
653 aGraphic.setOriginURL(aOriginURL);
656 if(GraphicType::Bitmap != aGraphic.GetType() && GraphicType::GdiMetafile != aGraphic.GetType())
658 // no content if not bitmap or metafile
659 OSL_ENSURE(false, "No fill graphic in SfxItemSet (!)");
660 return attribute::SdrFillGraphicAttribute();
663 Size aPrefSize(aGraphic.GetPrefSize());
665 if(!aPrefSize.Width() || !aPrefSize.Height())
667 // if there is no logical size, create a size from pixel size and set MapMode accordingly
668 if(GraphicType::Bitmap == aGraphic.GetType())
670 aGraphic.SetPrefSize(aGraphic.GetBitmapEx().GetSizePixel());
671 aGraphic.SetPrefMapMode(MapMode(MapUnit::MapPixel));
672 aPrefSize = aGraphic.GetPrefSize();
676 if(!aPrefSize.Width() || !aPrefSize.Height())
678 // no content if no size
679 OSL_ENSURE(false, "Graphic has no size in SfxItemSet (!)");
680 return attribute::SdrFillGraphicAttribute();
683 // convert size and MapMode to destination logical size and MapMode
684 const MapUnit aDestinationMapUnit(rSet.GetPool()->GetMetric(0));
685 basegfx::B2DVector aGraphicLogicSize(aGraphic.GetPrefSize().Width(), aGraphic.GetPrefSize().Height());
687 if (aGraphic.GetPrefMapMode().GetMapUnit() != aDestinationMapUnit)
689 // #i100360# for MapUnit::MapPixel, LogicToLogic will not work properly,
690 // so fallback to Application::GetDefaultDevice()
691 Size aNewSize(0, 0);
693 if(MapUnit::MapPixel == aGraphic.GetPrefMapMode().GetMapUnit())
695 aNewSize = Application::GetDefaultDevice()->PixelToLogic(
696 aGraphic.GetPrefSize(),
697 MapMode(aDestinationMapUnit));
699 else
701 aNewSize = OutputDevice::LogicToLogic(
702 aGraphic.GetPrefSize(),
703 aGraphic.GetPrefMapMode(),
704 MapMode(aDestinationMapUnit));
707 // #i124002# do not set new size using SetPrefSize at the graphic, this will lead to problems.
708 // Instead, adapt the GraphicLogicSize which will be used for further decompositions
709 aGraphicLogicSize = basegfx::B2DVector(aNewSize.Width(), aNewSize.Height());
712 // get size
713 const basegfx::B2DVector aSize(
714 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEX).GetValue()),
715 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEY).GetValue()));
716 const basegfx::B2DVector aOffset(
717 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETX).GetValue()),
718 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETY).GetValue()));
719 const basegfx::B2DVector aOffsetPosition(
720 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETX).GetValue()),
721 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETY).GetValue()));
723 return attribute::SdrFillGraphicAttribute(
724 aGraphic,
725 aGraphicLogicSize,
726 aSize,
727 aOffset,
728 aOffsetPosition,
729 RectPointToB2DVector(rSet.GetItem<XFillBmpPosItem>(XATTR_FILLBMP_POS)->GetValue()),
730 rSet.Get(XATTR_FILLBMP_TILE).GetValue(),
731 rSet.Get(XATTR_FILLBMP_STRETCH).GetValue(),
732 rSet.Get(XATTR_FILLBMP_SIZELOG).GetValue());
735 attribute::SdrEffectsTextAttribute createNewSdrEffectsTextAttribute(
736 const SfxItemSet& rSet,
737 const SdrText* pText,
738 bool bSuppressText)
740 attribute::SdrTextAttribute aText;
742 // #i98072# added option to suppress text
743 // look for text first
744 if(!bSuppressText && pText)
746 aText = createNewSdrTextAttribute(rSet, *pText);
749 // try shadow
750 const attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet));
751 const attribute::SdrGlowAttribute aGlow(createNewSdrGlowAttribute(rSet));
752 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
754 return attribute::SdrEffectsTextAttribute(aShadow, aText, aGlow, nSoftEdgeRadius);
757 attribute::SdrLineEffectsTextAttribute createNewSdrLineEffectsTextAttribute(
758 const SfxItemSet& rSet,
759 const SdrText* pText)
761 attribute::SdrLineAttribute aLine;
762 attribute::SdrLineStartEndAttribute aLineStartEnd;
763 attribute::SdrTextAttribute aText;
764 bool bFontworkHideContour(false);
766 // look for text first
767 if(pText)
769 aText = createNewSdrTextAttribute(rSet, *pText);
771 // when object has text and text is fontwork and hide contour is set for fontwork, force
772 // line and fill style to empty
773 if(!aText.isDefault()
774 && !aText.getSdrFormTextAttribute().isDefault()
775 && aText.isHideContour())
777 bFontworkHideContour = true;
781 // try line style
782 if(!bFontworkHideContour)
784 aLine = createNewSdrLineAttribute(rSet);
786 if(!aLine.isDefault())
788 // try LineStartEnd
789 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
793 if(!aLine.isDefault() || !aText.isDefault())
795 // try shadow
796 const attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet));
797 const attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet);
798 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
800 return attribute::SdrLineEffectsTextAttribute(aLine, aLineStartEnd, aShadow, aText,
801 aGlow, nSoftEdgeRadius);
804 return attribute::SdrLineEffectsTextAttribute();
807 attribute::SdrLineFillEffectsTextAttribute createNewSdrLineFillEffectsTextAttribute(
808 const SfxItemSet& rSet,
809 const SdrText* pText,
810 bool bHasContent,
811 bool bSuppressShadow)
813 attribute::SdrLineAttribute aLine;
814 attribute::SdrFillAttribute aFill;
815 attribute::SdrLineStartEndAttribute aLineStartEnd;
816 attribute::FillGradientAttribute aFillFloatTransGradient;
817 attribute::SdrTextAttribute aText;
818 bool bFontworkHideContour(false);
820 // look for text first
821 if(pText)
823 aText = createNewSdrTextAttribute(rSet, *pText);
825 // when object has text and text is fontwork and hide contour is set for fontwork, force
826 // line and fill style to empty
827 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour())
829 bFontworkHideContour = true;
833 if(!bFontworkHideContour)
835 // try line style
836 aLine = createNewSdrLineAttribute(rSet);
838 if(!aLine.isDefault())
840 // try LineStartEnd
841 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
844 // try fill style
845 aFill = createNewSdrFillAttribute(rSet);
847 if(!aFill.isDefault())
849 // try fillfloattransparence
850 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
854 // bHasContent is used from OLE and graphic objects. Normally a possible shadow
855 // depends on line, fill or text to be set, but for these objects it is possible
856 // to have none of these, but still content which needs to have a shadow (if set),
857 // so shadow needs to be tried
858 if(bHasContent || !aLine.isDefault() || !aFill.isDefault() || !aText.isDefault())
860 // try shadow
861 const attribute::SdrShadowAttribute aShadow = !bSuppressShadow ?
862 createNewSdrShadowAttribute(rSet) : attribute::SdrShadowAttribute();
864 // glow
865 const attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet);
867 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet));
869 return attribute::SdrLineFillEffectsTextAttribute(aLine, aFill, aLineStartEnd,
870 aShadow, aFillFloatTransGradient,
871 aText, aGlow, nSoftEdgeRadius);
874 return attribute::SdrLineFillEffectsTextAttribute();
877 attribute::SdrLineFillShadowAttribute3D createNewSdrLineFillShadowAttribute(const SfxItemSet& rSet, bool bSuppressFill)
879 attribute::SdrFillAttribute aFill;
880 attribute::SdrLineStartEndAttribute aLineStartEnd;
881 attribute::SdrShadowAttribute aShadow;
882 attribute::FillGradientAttribute aFillFloatTransGradient;
884 // try line style
885 const attribute::SdrLineAttribute aLine(createNewSdrLineAttribute(rSet));
887 if(!aLine.isDefault())
889 // try LineStartEnd
890 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth());
893 // try fill style
894 if(!bSuppressFill)
896 aFill = createNewSdrFillAttribute(rSet);
898 if(!aFill.isDefault())
900 // try fillfloattransparence
901 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
905 if(!aLine.isDefault() || !aFill.isDefault())
907 // try shadow
908 aShadow = createNewSdrShadowAttribute(rSet);
910 return attribute::SdrLineFillShadowAttribute3D(
911 aLine, aFill, aLineStartEnd, aShadow, aFillFloatTransGradient);
914 return attribute::SdrLineFillShadowAttribute3D();
917 attribute::SdrSceneAttribute createNewSdrSceneAttribute(const SfxItemSet& rSet)
919 // get perspective
920 css::drawing::ProjectionMode aProjectionMode(css::drawing::ProjectionMode_PARALLEL);
921 const sal_uInt16 nProjectionValue(rSet.Get(SDRATTR_3DSCENE_PERSPECTIVE).GetValue());
923 if(1 == nProjectionValue)
925 aProjectionMode = css::drawing::ProjectionMode_PERSPECTIVE;
928 // get distance
929 const double fDistance(rSet.Get(SDRATTR_3DSCENE_DISTANCE).GetValue());
931 // get shadow slant
932 const double fShadowSlant(
933 basegfx::deg2rad(rSet.Get(SDRATTR_3DSCENE_SHADOW_SLANT).GetValue()));
935 // get shade mode
936 css::drawing::ShadeMode aShadeMode(css::drawing::ShadeMode_FLAT);
937 const sal_uInt16 nShadeValue(rSet.Get(SDRATTR_3DSCENE_SHADE_MODE).GetValue());
939 if(1 == nShadeValue)
941 aShadeMode = css::drawing::ShadeMode_PHONG;
943 else if(2 == nShadeValue)
945 aShadeMode = css::drawing::ShadeMode_SMOOTH;
947 else if(3 == nShadeValue)
949 aShadeMode = css::drawing::ShadeMode_DRAFT;
952 // get two sided lighting
953 const bool bTwoSidedLighting(rSet.Get(SDRATTR_3DSCENE_TWO_SIDED_LIGHTING).GetValue());
955 return attribute::SdrSceneAttribute(fDistance, fShadowSlant, aProjectionMode, aShadeMode, bTwoSidedLighting);
958 attribute::SdrLightingAttribute createNewSdrLightingAttribute(const SfxItemSet& rSet)
960 // extract lights from given SfxItemSet (from scene)
961 ::std::vector< attribute::Sdr3DLightAttribute > aLightVector;
963 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue())
965 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue().getBColor());
966 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue());
967 aLightVector.emplace_back(aColor, aDirection, true);
970 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue())
972 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue().getBColor());
973 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue());
974 aLightVector.emplace_back(aColor, aDirection, false);
977 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue())
979 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue().getBColor());
980 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue());
981 aLightVector.emplace_back(aColor, aDirection, false);
984 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue())
986 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue().getBColor());
987 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue());
988 aLightVector.emplace_back(aColor, aDirection, false);
991 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue())
993 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue().getBColor());
994 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue());
995 aLightVector.emplace_back(aColor, aDirection, false);
998 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue())
1000 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue().getBColor());
1001 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue());
1002 aLightVector.emplace_back(aColor, aDirection, false);
1005 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue())
1007 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue().getBColor());
1008 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue());
1009 aLightVector.emplace_back(aColor, aDirection, false);
1012 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue())
1014 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue().getBColor());
1015 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue());
1016 aLightVector.emplace_back(aColor, aDirection, false);
1019 // get ambient color
1020 const Color aAmbientValue(rSet.Get(SDRATTR_3DSCENE_AMBIENTCOLOR).GetValue());
1021 const basegfx::BColor aAmbientLight(aAmbientValue.getBColor());
1023 return attribute::SdrLightingAttribute(aAmbientLight, std::move(aLightVector));
1026 void calculateRelativeCornerRadius(sal_Int32 nRadius, const basegfx::B2DRange& rObjectRange, double& rfCornerRadiusX, double& rfCornerRadiusY)
1028 rfCornerRadiusX = rfCornerRadiusY = static_cast<double>(nRadius);
1030 if(0.0 != rfCornerRadiusX)
1032 const double fHalfObjectWidth(rObjectRange.getWidth() * 0.5);
1034 if(0.0 != fHalfObjectWidth)
1036 if(rfCornerRadiusX < 0.0)
1038 rfCornerRadiusX = 0.0;
1041 if(rfCornerRadiusX > fHalfObjectWidth)
1043 rfCornerRadiusX = fHalfObjectWidth;
1046 rfCornerRadiusX /= fHalfObjectWidth;
1048 else
1050 rfCornerRadiusX = 0.0;
1054 if(0.0 == rfCornerRadiusY)
1055 return;
1057 const double fHalfObjectHeight(rObjectRange.getHeight() * 0.5);
1059 if(0.0 != fHalfObjectHeight)
1061 if(rfCornerRadiusY < 0.0)
1063 rfCornerRadiusY = 0.0;
1066 if(rfCornerRadiusY > fHalfObjectHeight)
1068 rfCornerRadiusY = fHalfObjectHeight;
1071 rfCornerRadiusY /= fHalfObjectHeight;
1073 else
1075 rfCornerRadiusY = 0.0;
1079 // #i101508# Support handing over given text-to-border distances
1080 attribute::SdrFillTextAttribute createNewSdrFillTextAttribute(
1081 const SfxItemSet& rSet,
1082 const SdrText* pText,
1083 const sal_Int32* pLeft,
1084 const sal_Int32* pUpper,
1085 const sal_Int32* pRight,
1086 const sal_Int32* pLower)
1088 attribute::SdrFillAttribute aFill;
1089 attribute::FillGradientAttribute aFillFloatTransGradient;
1090 attribute::SdrTextAttribute aText;
1091 bool bFontworkHideContour(false);
1093 // look for text first
1094 if(pText)
1096 aText = createNewSdrTextAttribute(rSet, *pText, pLeft, pUpper, pRight, pLower);
1098 // when object has text and text is fontwork and hide contour is set for fontwork, force
1099 // fill style to empty
1100 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour())
1102 bFontworkHideContour = true;
1106 if(!bFontworkHideContour)
1108 // try fill style
1109 aFill = createNewSdrFillAttribute(rSet);
1111 if(!aFill.isDefault())
1113 // try fillfloattransparence
1114 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet);
1118 if(!aFill.isDefault() || !aText.isDefault())
1120 return attribute::SdrFillTextAttribute(aFill, aFillFloatTransGradient, aText);
1123 return attribute::SdrFillTextAttribute();
1126 } // end of namespace
1128 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */