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 <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> 89 90 using namespace com::sun::star; 91 92 namespace drawinglayer 93 { 94 namespace 95 { 96 attribute::HatchStyle XHatchStyleToHatchStyle(css::drawing::HatchStyle eStyle) 97 { 98 switch(eStyle) 99 { 100 case css::drawing::HatchStyle_SINGLE : 101 { 102 return attribute::HatchStyle::Single; 103 } 104 case css::drawing::HatchStyle_DOUBLE : 105 { 106 return attribute::HatchStyle::Double; 107 } 108 default : 109 { 110 return attribute::HatchStyle::Triple; // css::drawing::HatchStyle_TRIPLE 111 } 112 } 113 } 114 115 basegfx::B2DLineJoin LineJointToB2DLineJoin(css::drawing::LineJoint eLineJoint) 116 { 117 switch(eLineJoint) 118 { 119 case css::drawing::LineJoint_BEVEL : 120 { 121 return basegfx::B2DLineJoin::Bevel; 122 } 123 case css::drawing::LineJoint_MIDDLE : 124 case css::drawing::LineJoint_MITER : 125 { 126 return basegfx::B2DLineJoin::Miter; 127 } 128 case css::drawing::LineJoint_ROUND : 129 { 130 return basegfx::B2DLineJoin::Round; 131 } 132 default : // css::drawing::LineJoint_NONE 133 { 134 return basegfx::B2DLineJoin::NONE; 135 } 136 } 137 } 138 139 basegfx::B2DVector RectPointToB2DVector(RectPoint eRectPoint) 140 { 141 basegfx::B2DVector aRetval(0.0, 0.0); 142 143 // position changes X 144 switch(eRectPoint) 145 { 146 case RectPoint::LT: case RectPoint::LM: case RectPoint::LB: 147 { 148 aRetval.setX(-1.0); 149 break; 150 } 151 152 case RectPoint::RT: case RectPoint::RM: case RectPoint::RB: 153 { 154 aRetval.setX(1.0); 155 break; 156 } 157 158 default : 159 { 160 break; 161 } 162 } 163 164 // position changes Y 165 switch(eRectPoint) 166 { 167 case RectPoint::LT: case RectPoint::MT: case RectPoint::RT: 168 { 169 aRetval.setY(-1.0); 170 break; 171 } 172 173 case RectPoint::LB: case RectPoint::MB: case RectPoint::RB: 174 { 175 aRetval.setY(1.0); 176 break; 177 } 178 179 default : 180 { 181 break; 182 } 183 } 184 185 return aRetval; 186 } 187 188 attribute::SdrGlowAttribute createNewSdrGlowAttribute(const SfxItemSet& rSet) 189 { 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)); 197 198 attribute::SdrGlowAttribute glowAttr{ nRadius, aColor }; 199 return glowAttr; 200 } 201 202 sal_Int32 getSoftEdgeRadius(const SfxItemSet& rSet) 203 { 204 return rSet.Get(SDRATTR_SOFTEDGE_RADIUS).GetValue(); 205 } 206 } // end of anonymous namespace 207 } // end of namespace drawinglayer 208 209 210 namespace drawinglayer::primitive2d 211 { 212 attribute::SdrLineAttribute createNewSdrLineAttribute(const SfxItemSet& rSet) 213 { 214 const css::drawing::LineStyle eStyle(rSet.Get(XATTR_LINESTYLE).GetValue()); 215 216 if(drawing::LineStyle_NONE != eStyle) 217 { 218 sal_uInt16 nTransparence(rSet.Get(XATTR_LINETRANSPARENCE).GetValue()); 219 220 if(nTransparence > 100) 221 { 222 nTransparence = 100; 223 } 224 225 if(100 != nTransparence) 226 { 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); 233 234 if(drawing::LineStyle_DASH == eStyle) 235 { 236 const XDash& rDash = rSet.Get(XATTR_LINEDASH).GetDashValue(); 237 238 if(rDash.GetDots() || rDash.GetDashes()) 239 { 240 fFullDotDashLen = rDash.CreateDotDashArray(aDotDashArray, static_cast<double>(nWidth)); 241 } 242 } 243 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); 252 } 253 } 254 255 return attribute::SdrLineAttribute(); 256 } 257 258 attribute::SdrLineStartEndAttribute createNewSdrLineStartEndAttribute( 259 const SfxItemSet& rSet, 260 double fWidth) 261 { 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); 272 273 if(nTempStartWidth) 274 { 275 if(nTempStartWidth < 0) 276 { 277 fStartWidth = (static_cast<double>(-nTempStartWidth) * fWidth) * 0.01; 278 } 279 else 280 { 281 fStartWidth = static_cast<double>(nTempStartWidth); 282 } 283 284 if(0.0 != fStartWidth) 285 { 286 aStartPolyPolygon = rSet.Get(XATTR_LINESTART).GetLineStartValue(); 287 288 if(aStartPolyPolygon.count() && aStartPolyPolygon.getB2DPolygon(0).count()) 289 { 290 bStartActive = true; 291 bStartCentered = rSet.Get(XATTR_LINESTARTCENTER).GetValue(); 292 } 293 } 294 } 295 296 if(nTempEndWidth) 297 { 298 if(nTempEndWidth < 0) 299 { 300 fEndWidth = (static_cast<double>(-nTempEndWidth) * fWidth) * 0.01; 301 } 302 else 303 { 304 fEndWidth = static_cast<double>(nTempEndWidth); 305 } 306 307 if(0.0 != fEndWidth) 308 { 309 aEndPolyPolygon = rSet.Get(XATTR_LINEEND).GetLineEndValue(); 310 311 if(aEndPolyPolygon.count() && aEndPolyPolygon.getB2DPolygon(0).count()) 312 { 313 bEndActive = true; 314 bEndCentered = rSet.Get(XATTR_LINEENDCENTER).GetValue(); 315 } 316 } 317 } 318 319 if(bStartActive || bEndActive) 320 { 321 return attribute::SdrLineStartEndAttribute( 322 aStartPolyPolygon, aEndPolyPolygon, fStartWidth, fEndWidth, 323 bStartActive, bEndActive, bStartCentered, bEndCentered); 324 } 325 326 return attribute::SdrLineStartEndAttribute(); 327 } 328 329 attribute::SdrShadowAttribute createNewSdrShadowAttribute(const SfxItemSet& rSet) 330 { 331 const bool bShadow(rSet.Get(SDRATTR_SHADOW).GetValue()); 332 333 if(bShadow) 334 { 335 sal_uInt16 nTransparence(rSet.Get(SDRATTR_SHADOWTRANSPARENCE).GetValue()); 336 337 if(nTransparence > 100) 338 { 339 nTransparence = 100; 340 } 341 342 if(nTransparence) 343 { 344 sal_uInt16 nFillTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue()); 345 346 if(nFillTransparence > 100) 347 { 348 nFillTransparence = 100; 349 } 350 351 if(nTransparence == nFillTransparence) 352 { 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; 358 } 359 } 360 361 if(100 != nTransparence) 362 { 363 const basegfx::B2DVector aOffset( 364 static_cast<double>(rSet.Get(SDRATTR_SHADOWXDIST).GetValue()), 365 static_cast<double>(rSet.Get(SDRATTR_SHADOWYDIST).GetValue())); 366 367 const basegfx::B2DVector aSize( 368 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEX).GetValue()), 369 static_cast<double>(rSet.Get(SDRATTR_SHADOWSIZEY).GetValue())); 370 371 const Color aColor(rSet.Get(SDRATTR_SHADOWCOLOR).GetColorValue()); 372 373 sal_Int32 nBlur(rSet.Get(SDRATTR_SHADOWBLUR).GetValue()); 374 375 model::RectangleAlignment eAlignment{rSet.Get(SDRATTR_SHADOWALIGNMENT).GetValue()}; 376 377 return attribute::SdrShadowAttribute(aOffset, aSize, static_cast<double>(nTransparence) * 0.01, nBlur, eAlignment, aColor.getBColor()); 378 } 379 } 380 381 return attribute::SdrShadowAttribute(); 382 } 383 384 attribute::SdrFillAttribute createNewSdrFillAttribute(const SfxItemSet& rSet) 385 { 386 const drawing::FillStyle eStyle(rSet.Get(XATTR_FILLSTYLE).GetValue()); 387 388 sal_uInt16 nTransparence(rSet.Get(XATTR_FILLTRANSPARENCE).GetValue()); 389 390 if(nTransparence > 100) 391 { 392 nTransparence = 100; 393 } 394 395 if(drawing::FillStyle_NONE == eStyle) 396 { 397 XFillUseSlideBackgroundItem aBckItem(rSet.Get(XATTR_FILLUSESLIDEBACKGROUND)); 398 const bool bSlideBackgroundFill(aBckItem.GetValue()); 399 400 if(bSlideBackgroundFill) 401 { 402 // we have SlideBackgroundFill mode, create a 403 // SdrFillAttribute accordingly 404 return attribute::SdrFillAttribute(true); 405 } 406 } 407 408 if(drawing::FillStyle_NONE != eStyle) 409 { 410 if(100 != nTransparence) 411 { 412 // need to check XFillFloatTransparence, object fill may still be completely transparent 413 const XFillFloatTransparenceItem* pGradientItem; 414 415 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE, true)) 416 && pGradientItem->IsEnabled()) 417 { 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)); 422 423 if(bCompletelyTransparent) 424 { 425 nTransparence = 100; 426 } 427 } 428 } 429 430 if(100 != nTransparence) 431 { 432 const Color aColor(rSet.Get(XATTR_FILLCOLOR).GetColorValue()); 433 attribute::FillGradientAttribute aGradient; 434 attribute::FillHatchAttribute aHatch; 435 attribute::SdrFillGraphicAttribute aFillGraphic; 436 437 switch(eStyle) 438 { 439 default: 440 { 441 // nothing to do, color is defined 442 break; 443 } 444 case drawing::FillStyle_GRADIENT : 445 { 446 basegfx::BGradient aBGradient(rSet.Get(XATTR_FILLGRADIENT).GetGradientValue()); 447 basegfx::BColorStops aColorStops(aBGradient.GetColorStops()); 448 449 450 if (aBGradient.GetStartIntens() != 100 || aBGradient.GetEndIntens() != 100) 451 { 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 459 } 460 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()); 469 470 break; 471 } 472 case drawing::FillStyle_HATCH : 473 { 474 const XHatch& rHatch(rSet.Get(XATTR_FILLHATCH).GetHatchValue()); 475 const Color aColorB(rHatch.GetColor()); 476 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()); 484 485 break; 486 } 487 case drawing::FillStyle_BITMAP : 488 { 489 aFillGraphic = createNewSdrFillGraphicAttribute(rSet); 490 break; 491 } 492 } 493 494 return attribute::SdrFillAttribute( 495 static_cast<double>(nTransparence) * 0.01, 496 aColor.getBColor(), 497 aGradient, 498 aHatch, 499 aFillGraphic); 500 } 501 } 502 503 if(nTransparence == 100) 504 { 505 attribute::FillGradientAttribute aGradient; 506 attribute::FillHatchAttribute aHatch; 507 attribute::SdrFillGraphicAttribute aFillGraphic; 508 return attribute::SdrFillAttribute( 509 1, 510 basegfx::BColor( 0, 0, 0 ), 511 aGradient, 512 aHatch, 513 aFillGraphic); 514 } 515 516 return attribute::SdrFillAttribute(); 517 } 518 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) 527 { 528 const SdrTextObj& rTextObj = rText.GetObject(); 529 530 // Save chaining attributes 531 bool bChainable = rTextObj.IsChainable(); 532 533 534 if(rText.GetOutlinerParaObject()) 535 { 536 // added TextEdit text suppression 537 bool bInEditMode(false); 538 539 if(rText.GetObject().getTextCount() > 1) 540 { 541 bInEditMode = rTextObj.IsInEditMode() && rText.GetObject().getActiveText() == &rText; 542 } 543 else 544 { 545 bInEditMode = rTextObj.IsInEditMode(); 546 } 547 548 OutlinerParaObject aOutlinerParaObject(*rText.GetOutlinerParaObject()); 549 550 if(bInEditMode) 551 { 552 std::optional<OutlinerParaObject> pTempObj = rTextObj.CreateEditOutlinerParaObject(); 553 554 if(pTempObj) 555 { 556 aOutlinerParaObject = *pTempObj; 557 } 558 else 559 { 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; 564 } 565 } 566 567 const SdrTextAniKind eAniKind(rTextObj.GetTextAniKind()); 568 569 // #i107346# 570 const SdrOutliner& rDrawTextOutliner(rText.GetObject().getSdrModelFromSdrObject().GetDrawOutliner(&rTextObj)); 571 const bool bWrongSpell(rDrawTextOutliner.GetControlWord() & EEControlBits::ONLINESPELLING); 572 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); 593 } 594 595 return attribute::SdrTextAttribute(); 596 } 597 598 attribute::FillGradientAttribute createNewTransparenceGradientAttribute(const SfxItemSet& rSet) 599 { 600 const XFillFloatTransparenceItem* pGradientItem; 601 602 if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE)) 603 && pGradientItem->IsEnabled()) 604 { 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())); 611 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) 617 { 618 basegfx::BColorStops aColorStops(rGradient.GetColorStops()); 619 620 if (rGradient.GetStartIntens() != 100 || rGradient.GetEndIntens() != 100) 621 { 622 // this may also be set for transparence, so need to take care of it 623 aColorStops.blendToIntensity( 624 rGradient.GetStartIntens() * 0.01, 625 rGradient.GetEndIntens() * 0.01, 626 basegfx::BColor()); // COL_BLACK 627 } 628 629 return attribute::FillGradientAttribute( 630 rGradient.GetGradientStyle(), 631 static_cast<double>(rGradient.GetBorder()) * 0.01, 632 static_cast<double>(rGradient.GetXOffset()) * 0.01, 633 static_cast<double>(rGradient.GetYOffset()) * 0.01, 634 toRadians(rGradient.GetAngle()), 635 aColorStops, 636 // oops - the gradientStepCount was missing here. If we want to use 637 // a combination of gradient & transparencyGradient to represent 638 // imported gradients of formats which do originally support transparency 639 // in gradients, then the gradient has to be exactly defined the same, 640 // including the (evtl. used) gradientStepCount 641 rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue()); 642 } 643 } 644 645 return attribute::FillGradientAttribute(); 646 } 647 648 attribute::SdrFillGraphicAttribute createNewSdrFillGraphicAttribute(const SfxItemSet& rSet) 649 { 650 Graphic aGraphic(rSet.Get(XATTR_FILLBITMAP).GetGraphicObject().GetGraphic()); 651 652 OUString aOriginURL = aGraphic.getOriginURL(); 653 if (aGraphic.GetType() == GraphicType::Default && !aOriginURL.isEmpty()) 654 { 655 aGraphic = vcl::graphic::loadFromURL(aGraphic.getOriginURL()); 656 aGraphic.setOriginURL(aOriginURL); 657 } 658 659 if(GraphicType::Bitmap != aGraphic.GetType() && GraphicType::GdiMetafile != aGraphic.GetType()) 660 { 661 // no content if not bitmap or metafile 662 OSL_ENSURE(false, "No fill graphic in SfxItemSet (!)"); 663 return attribute::SdrFillGraphicAttribute(); 664 } 665 666 Size aPrefSize(aGraphic.GetPrefSize()); 667 668 if(!aPrefSize.Width() || !aPrefSize.Height()) 669 { 670 // if there is no logical size, create a size from pixel size and set MapMode accordingly 671 if(GraphicType::Bitmap == aGraphic.GetType()) 672 { 673 aGraphic.SetPrefSize(aGraphic.GetBitmapEx().GetSizePixel()); 674 aGraphic.SetPrefMapMode(MapMode(MapUnit::MapPixel)); 675 aPrefSize = aGraphic.GetPrefSize(); 676 } 677 } 678 679 if(!aPrefSize.Width() || !aPrefSize.Height()) 680 { 681 // no content if no size 682 OSL_ENSURE(false, "Graphic has no size in SfxItemSet (!)"); 683 return attribute::SdrFillGraphicAttribute(); 684 } 685 686 // convert size and MapMode to destination logical size and MapMode 687 const MapUnit aDestinationMapUnit(rSet.GetPool()->GetMetric(0)); 688 basegfx::B2DVector aGraphicLogicSize(aGraphic.GetPrefSize().Width(), aGraphic.GetPrefSize().Height()); 689 690 if (aGraphic.GetPrefMapMode().GetMapUnit() != aDestinationMapUnit) 691 { 692 // #i100360# for MapUnit::MapPixel, LogicToLogic will not work properly, 693 // so fallback to Application::GetDefaultDevice() 694 Size aNewSize(0, 0); 695 696 if(MapUnit::MapPixel == aGraphic.GetPrefMapMode().GetMapUnit()) 697 { 698 aNewSize = Application::GetDefaultDevice()->PixelToLogic( 699 aGraphic.GetPrefSize(), 700 MapMode(aDestinationMapUnit)); 701 } 702 else 703 { 704 aNewSize = OutputDevice::LogicToLogic( 705 aGraphic.GetPrefSize(), 706 aGraphic.GetPrefMapMode(), 707 MapMode(aDestinationMapUnit)); 708 } 709 710 // #i124002# do not set new size using SetPrefSize at the graphic, this will lead to problems. 711 // Instead, adapt the GraphicLogicSize which will be used for further decompositions 712 aGraphicLogicSize = basegfx::B2DVector(aNewSize.Width(), aNewSize.Height()); 713 } 714 715 // get size 716 const basegfx::B2DVector aSize( 717 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEX).GetValue()), 718 static_cast<double>(rSet.Get(XATTR_FILLBMP_SIZEY).GetValue())); 719 const basegfx::B2DVector aOffset( 720 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETX).GetValue()), 721 static_cast<double>(rSet.Get(XATTR_FILLBMP_TILEOFFSETY).GetValue())); 722 const basegfx::B2DVector aOffsetPosition( 723 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETX).GetValue()), 724 static_cast<double>(rSet.Get(XATTR_FILLBMP_POSOFFSETY).GetValue())); 725 726 return attribute::SdrFillGraphicAttribute( 727 aGraphic, 728 aGraphicLogicSize, 729 aSize, 730 aOffset, 731 aOffsetPosition, 732 RectPointToB2DVector(rSet.GetItem<XFillBmpPosItem>(XATTR_FILLBMP_POS)->GetValue()), 733 rSet.Get(XATTR_FILLBMP_TILE).GetValue(), 734 rSet.Get(XATTR_FILLBMP_STRETCH).GetValue(), 735 rSet.Get(XATTR_FILLBMP_SIZELOG).GetValue()); 736 } 737 738 attribute::SdrEffectsTextAttribute createNewSdrEffectsTextAttribute( 739 const SfxItemSet& rSet, 740 const SdrText* pText, 741 bool bSuppressText) 742 { 743 attribute::SdrTextAttribute aText; 744 745 // #i98072# added option to suppress text 746 // look for text first 747 if(!bSuppressText && pText) 748 { 749 aText = createNewSdrTextAttribute(rSet, *pText); 750 } 751 752 // try shadow 753 const attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet)); 754 const attribute::SdrGlowAttribute aGlow(createNewSdrGlowAttribute(rSet)); 755 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet)); 756 757 return attribute::SdrEffectsTextAttribute(aShadow, aText, aGlow, nSoftEdgeRadius); 758 } 759 760 attribute::SdrLineEffectsTextAttribute createNewSdrLineEffectsTextAttribute( 761 const SfxItemSet& rSet, 762 const SdrText* pText) 763 { 764 attribute::SdrLineAttribute aLine; 765 attribute::SdrLineStartEndAttribute aLineStartEnd; 766 attribute::SdrTextAttribute aText; 767 bool bFontworkHideContour(false); 768 769 // look for text first 770 if(pText) 771 { 772 aText = createNewSdrTextAttribute(rSet, *pText); 773 774 // when object has text and text is fontwork and hide contour is set for fontwork, force 775 // line and fill style to empty 776 if(!aText.isDefault() 777 && !aText.getSdrFormTextAttribute().isDefault() 778 && aText.isHideContour()) 779 { 780 bFontworkHideContour = true; 781 } 782 } 783 784 // try line style 785 if(!bFontworkHideContour) 786 { 787 aLine = createNewSdrLineAttribute(rSet); 788 789 if(!aLine.isDefault()) 790 { 791 // try LineStartEnd 792 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth()); 793 } 794 } 795 796 if(!aLine.isDefault() || !aText.isDefault()) 797 { 798 // try shadow 799 const attribute::SdrShadowAttribute aShadow(createNewSdrShadowAttribute(rSet)); 800 const attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet); 801 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet)); 802 803 return attribute::SdrLineEffectsTextAttribute(aLine, aLineStartEnd, aShadow, aText, 804 aGlow, nSoftEdgeRadius); 805 } 806 807 return attribute::SdrLineEffectsTextAttribute(); 808 } 809 810 attribute::SdrLineFillEffectsTextAttribute createNewSdrLineFillEffectsTextAttribute( 811 const SfxItemSet& rSet, 812 const SdrText* pText, 813 bool bHasContent, 814 bool bSuppressShadow) 815 { 816 attribute::SdrLineAttribute aLine; 817 attribute::SdrFillAttribute aFill; 818 attribute::SdrLineStartEndAttribute aLineStartEnd; 819 attribute::FillGradientAttribute aFillFloatTransGradient; 820 attribute::SdrTextAttribute aText; 821 bool bFontworkHideContour(false); 822 823 // look for text first 824 if(pText) 825 { 826 aText = createNewSdrTextAttribute(rSet, *pText); 827 828 // when object has text and text is fontwork and hide contour is set for fontwork, force 829 // line and fill style to empty 830 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour()) 831 { 832 bFontworkHideContour = true; 833 } 834 } 835 836 if(!bFontworkHideContour) 837 { 838 // try line style 839 aLine = createNewSdrLineAttribute(rSet); 840 841 if(!aLine.isDefault()) 842 { 843 // try LineStartEnd 844 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth()); 845 } 846 847 // try fill style 848 aFill = createNewSdrFillAttribute(rSet); 849 850 if(!aFill.isDefault()) 851 { 852 // try fillfloattransparence 853 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet); 854 } 855 } 856 857 // bHasContent is used from OLE and graphic objects. Normally a possible shadow 858 // depends on line, fill or text to be set, but for these objects it is possible 859 // to have none of these, but still content which needs to have a shadow (if set), 860 // so shadow needs to be tried 861 if(bHasContent || !aLine.isDefault() || !aFill.isDefault() || !aText.isDefault()) 862 { 863 // try shadow 864 const attribute::SdrShadowAttribute aShadow = !bSuppressShadow ? 865 createNewSdrShadowAttribute(rSet) : attribute::SdrShadowAttribute(); 866 867 // glow 868 const attribute::SdrGlowAttribute aGlow = createNewSdrGlowAttribute(rSet); 869 870 const sal_Int32 nSoftEdgeRadius(getSoftEdgeRadius(rSet)); 871 872 return attribute::SdrLineFillEffectsTextAttribute(aLine, aFill, aLineStartEnd, 873 aShadow, aFillFloatTransGradient, 874 aText, aGlow, nSoftEdgeRadius); 875 } 876 877 return attribute::SdrLineFillEffectsTextAttribute(); 878 } 879 880 attribute::SdrLineFillShadowAttribute3D createNewSdrLineFillShadowAttribute(const SfxItemSet& rSet, bool bSuppressFill) 881 { 882 attribute::SdrFillAttribute aFill; 883 attribute::SdrLineStartEndAttribute aLineStartEnd; 884 attribute::SdrShadowAttribute aShadow; 885 attribute::FillGradientAttribute aFillFloatTransGradient; 886 887 // try line style 888 const attribute::SdrLineAttribute aLine(createNewSdrLineAttribute(rSet)); 889 890 if(!aLine.isDefault()) 891 { 892 // try LineStartEnd 893 aLineStartEnd = createNewSdrLineStartEndAttribute(rSet, aLine.getWidth()); 894 } 895 896 // try fill style 897 if(!bSuppressFill) 898 { 899 aFill = createNewSdrFillAttribute(rSet); 900 901 if(!aFill.isDefault()) 902 { 903 // try fillfloattransparence 904 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet); 905 } 906 } 907 908 if(!aLine.isDefault() || !aFill.isDefault()) 909 { 910 // try shadow 911 aShadow = createNewSdrShadowAttribute(rSet); 912 913 return attribute::SdrLineFillShadowAttribute3D( 914 aLine, aFill, aLineStartEnd, aShadow, aFillFloatTransGradient); 915 } 916 917 return attribute::SdrLineFillShadowAttribute3D(); 918 } 919 920 attribute::SdrSceneAttribute createNewSdrSceneAttribute(const SfxItemSet& rSet) 921 { 922 // get perspective 923 css::drawing::ProjectionMode aProjectionMode(css::drawing::ProjectionMode_PARALLEL); 924 const sal_uInt16 nProjectionValue(rSet.Get(SDRATTR_3DSCENE_PERSPECTIVE).GetValue()); 925 926 if(1 == nProjectionValue) 927 { 928 aProjectionMode = css::drawing::ProjectionMode_PERSPECTIVE; 929 } 930 931 // get distance 932 const double fDistance(rSet.Get(SDRATTR_3DSCENE_DISTANCE).GetValue()); 933 934 // get shadow slant 935 const double fShadowSlant( 936 basegfx::deg2rad(rSet.Get(SDRATTR_3DSCENE_SHADOW_SLANT).GetValue())); 937 938 // get shade mode 939 css::drawing::ShadeMode aShadeMode(css::drawing::ShadeMode_FLAT); 940 const sal_uInt16 nShadeValue(rSet.Get(SDRATTR_3DSCENE_SHADE_MODE).GetValue()); 941 942 if(1 == nShadeValue) 943 { 944 aShadeMode = css::drawing::ShadeMode_PHONG; 945 } 946 else if(2 == nShadeValue) 947 { 948 aShadeMode = css::drawing::ShadeMode_SMOOTH; 949 } 950 else if(3 == nShadeValue) 951 { 952 aShadeMode = css::drawing::ShadeMode_DRAFT; 953 } 954 955 // get two sided lighting 956 const bool bTwoSidedLighting(rSet.Get(SDRATTR_3DSCENE_TWO_SIDED_LIGHTING).GetValue()); 957 958 return attribute::SdrSceneAttribute(fDistance, fShadowSlant, aProjectionMode, aShadeMode, bTwoSidedLighting); 959 } 960 961 attribute::SdrLightingAttribute createNewSdrLightingAttribute(const SfxItemSet& rSet) 962 { 963 // extract lights from given SfxItemSet (from scene) 964 ::std::vector< attribute::Sdr3DLightAttribute > aLightVector; 965 966 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue()) 967 { 968 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue().getBColor()); 969 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue()); 970 aLightVector.emplace_back(aColor, aDirection, true); 971 } 972 973 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue()) 974 { 975 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue().getBColor()); 976 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue()); 977 aLightVector.emplace_back(aColor, aDirection, false); 978 } 979 980 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue()) 981 { 982 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue().getBColor()); 983 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue()); 984 aLightVector.emplace_back(aColor, aDirection, false); 985 } 986 987 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue()) 988 { 989 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue().getBColor()); 990 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue()); 991 aLightVector.emplace_back(aColor, aDirection, false); 992 } 993 994 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue()) 995 { 996 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue().getBColor()); 997 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue()); 998 aLightVector.emplace_back(aColor, aDirection, false); 999 } 1000 1001 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue()) 1002 { 1003 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue().getBColor()); 1004 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue()); 1005 aLightVector.emplace_back(aColor, aDirection, false); 1006 } 1007 1008 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue()) 1009 { 1010 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue().getBColor()); 1011 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue()); 1012 aLightVector.emplace_back(aColor, aDirection, false); 1013 } 1014 1015 if(rSet.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue()) 1016 { 1017 const basegfx::BColor aColor(rSet.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue().getBColor()); 1018 const basegfx::B3DVector aDirection(rSet.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue()); 1019 aLightVector.emplace_back(aColor, aDirection, false); 1020 } 1021 1022 // get ambient color 1023 const Color aAmbientValue(rSet.Get(SDRATTR_3DSCENE_AMBIENTCOLOR).GetValue()); 1024 const basegfx::BColor aAmbientLight(aAmbientValue.getBColor()); 1025 1026 return attribute::SdrLightingAttribute(aAmbientLight, std::move(aLightVector)); 1027 } 1028 1029 void calculateRelativeCornerRadius(sal_Int32 nRadius, const basegfx::B2DRange& rObjectRange, double& rfCornerRadiusX, double& rfCornerRadiusY) 1030 { 1031 rfCornerRadiusX = rfCornerRadiusY = static_cast<double>(nRadius); 1032 1033 if(0.0 != rfCornerRadiusX) 1034 { 1035 const double fHalfObjectWidth(rObjectRange.getWidth() * 0.5); 1036 1037 if(0.0 != fHalfObjectWidth) 1038 { 1039 if(rfCornerRadiusX < 0.0) 1040 { 1041 rfCornerRadiusX = 0.0; 1042 } 1043 1044 if(rfCornerRadiusX > fHalfObjectWidth) 1045 { 1046 rfCornerRadiusX = fHalfObjectWidth; 1047 } 1048 1049 rfCornerRadiusX /= fHalfObjectWidth; 1050 } 1051 else 1052 { 1053 rfCornerRadiusX = 0.0; 1054 } 1055 } 1056 1057 if(0.0 == rfCornerRadiusY) 1058 return; 1059 1060 const double fHalfObjectHeight(rObjectRange.getHeight() * 0.5); 1061 1062 if(0.0 != fHalfObjectHeight) 1063 { 1064 if(rfCornerRadiusY < 0.0) 1065 { 1066 rfCornerRadiusY = 0.0; 1067 } 1068 1069 if(rfCornerRadiusY > fHalfObjectHeight) 1070 { 1071 rfCornerRadiusY = fHalfObjectHeight; 1072 } 1073 1074 rfCornerRadiusY /= fHalfObjectHeight; 1075 } 1076 else 1077 { 1078 rfCornerRadiusY = 0.0; 1079 } 1080 } 1081 1082 // #i101508# Support handing over given text-to-border distances 1083 attribute::SdrFillTextAttribute createNewSdrFillTextAttribute( 1084 const SfxItemSet& rSet, 1085 const SdrText* pText, 1086 const sal_Int32* pLeft, 1087 const sal_Int32* pUpper, 1088 const sal_Int32* pRight, 1089 const sal_Int32* pLower) 1090 { 1091 attribute::SdrFillAttribute aFill; 1092 attribute::FillGradientAttribute aFillFloatTransGradient; 1093 attribute::SdrTextAttribute aText; 1094 bool bFontworkHideContour(false); 1095 1096 // look for text first 1097 if(pText) 1098 { 1099 aText = createNewSdrTextAttribute(rSet, *pText, pLeft, pUpper, pRight, pLower); 1100 1101 // when object has text and text is fontwork and hide contour is set for fontwork, force 1102 // fill style to empty 1103 if(!aText.getSdrFormTextAttribute().isDefault() && aText.isHideContour()) 1104 { 1105 bFontworkHideContour = true; 1106 } 1107 } 1108 1109 if(!bFontworkHideContour) 1110 { 1111 // try fill style 1112 aFill = createNewSdrFillAttribute(rSet); 1113 1114 if(!aFill.isDefault()) 1115 { 1116 // try fillfloattransparence 1117 aFillFloatTransGradient = createNewTransparenceGradientAttribute(rSet); 1118 } 1119 } 1120 1121 if(!aFill.isDefault() || !aText.isDefault()) 1122 { 1123 return attribute::SdrFillTextAttribute(aFill, aFillFloatTransGradient, aText); 1124 } 1125 1126 return attribute::SdrFillTextAttribute(); 1127 } 1128 1129 } // end of namespace 1130 1131 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1132
