1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_drawinglayer.hxx" 24 25 #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx> 26 #include <drawinglayer/animation/animationtiming.hxx> 27 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 28 #include <drawinglayer/primitive2d/animatedprimitive2d.hxx> 29 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> 30 #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 31 #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 32 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 33 #include <basegfx/polygon/b2dpolygon.hxx> 34 #include <basegfx/polygon/b2dpolygontools.hxx> 35 #include <basegfx/numeric/ftools.hxx> 36 37 ////////////////////////////////////////////////////////////////////////////// 38 // helper class for animated graphics 39 40 #include <vcl/animate.hxx> 41 #include <vcl/graph.hxx> 42 #include <vcl/virdev.hxx> 43 #include <vcl/svapp.hxx> 44 #include <vcl/metaact.hxx> 45 46 ////////////////////////////////////////////////////////////////////////////// 47 // includes for testing MetafilePrimitive2D::create2DDecomposition 48 49 // this switch defines if the test code is included or not 50 #undef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 51 52 #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 53 #include <vcl/gradient.hxx> 54 #include <vcl/pngread.hxx> 55 #include <vcl/lineinfo.hxx> 56 #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 57 58 ////////////////////////////////////////////////////////////////////////////// 59 60 namespace 61 { 62 struct animationStep 63 { 64 BitmapEx maBitmapEx; 65 sal_uInt32 mnTime; 66 }; 67 68 class animatedBitmapExPreparator 69 { 70 ::Animation maAnimation; 71 ::std::vector< animationStep > maSteps; 72 73 sal_uInt32 generateStepTime(sal_uInt32 nIndex) const; 74 75 public: 76 animatedBitmapExPreparator(const Graphic& rGraphic); 77 count() const78 sal_uInt32 count() const { return maSteps.size(); } loopCount() const79 sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); } stepTime(sal_uInt32 a) const80 sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; } stepBitmapEx(sal_uInt32 a) const81 const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; } 82 }; 83 generateStepTime(sal_uInt32 nIndex) const84 sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const 85 { 86 const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex)); 87 sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10); 88 89 // #115934# 90 // Take care of special value for MultiPage TIFFs. ATM these shall just 91 // show their first page. Later we will offer some switching when object 92 // is selected. 93 if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait) 94 { 95 // ATM the huge value would block the timer, so 96 // use a long time to show first page (whole day) 97 nWaitTime = 100 * 60 * 60 * 24; 98 } 99 100 // Bad trap: There are animated gifs with no set WaitTime (!). 101 // In that case use a default value. 102 if(0L == nWaitTime) 103 { 104 nWaitTime = 100L; 105 } 106 107 return nWaitTime; 108 } 109 animatedBitmapExPreparator(const Graphic & rGraphic)110 animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic) 111 : maAnimation(rGraphic.GetAnimation()) 112 { 113 OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)"); 114 115 // #128539# secure access to Animation, looks like there exist animated GIFs out there 116 // with a step count of zero 117 if(maAnimation.Count()) 118 { 119 VirtualDevice aVirtualDevice(*Application::GetDefaultDevice()); 120 VirtualDevice aVirtualDeviceMask(*Application::GetDefaultDevice(), 1L); 121 122 // Prepare VirtualDevices and their states 123 aVirtualDevice.EnableMapMode(sal_False); 124 aVirtualDeviceMask.EnableMapMode(sal_False); 125 aVirtualDevice.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); 126 aVirtualDeviceMask.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); 127 aVirtualDevice.Erase(); 128 aVirtualDeviceMask.Erase(); 129 130 for(sal_uInt16 a(0L); a < maAnimation.Count(); a++) 131 { 132 animationStep aNextStep; 133 aNextStep.mnTime = generateStepTime(a); 134 135 // prepare step 136 const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a)); 137 138 switch(rAnimBitmap.eDisposal) 139 { 140 case DISPOSE_NOT: 141 { 142 aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); 143 Bitmap aMask = rAnimBitmap.aBmpEx.GetMask(); 144 145 if(aMask.IsEmpty()) 146 { 147 const Point aEmpty; 148 const Rectangle aRect(aEmpty, aVirtualDeviceMask.GetOutputSizePixel()); 149 const Wallpaper aWallpaper(COL_BLACK); 150 aVirtualDeviceMask.DrawWallpaper(aRect, aWallpaper); 151 } 152 else 153 { 154 BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask); 155 aVirtualDeviceMask.DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask); 156 } 157 158 break; 159 } 160 case DISPOSE_BACK: 161 { 162 // #i70772# react on no mask, for primitives, too. 163 const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask()); 164 const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap()); 165 166 aVirtualDeviceMask.Erase(); 167 aVirtualDevice.DrawBitmap(rAnimBitmap.aPosPix, aContent); 168 169 if(aMask.IsEmpty()) 170 { 171 const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel()); 172 aVirtualDeviceMask.SetFillColor(COL_BLACK); 173 aVirtualDeviceMask.SetLineColor(); 174 aVirtualDeviceMask.DrawRect(aRect); 175 } 176 else 177 { 178 aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, aMask); 179 } 180 181 break; 182 } 183 case DISPOSE_FULL: 184 { 185 aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); 186 break; 187 } 188 case DISPOSE_PREVIOUS : 189 { 190 aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); 191 aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask()); 192 break; 193 } 194 } 195 196 // create BitmapEx 197 Bitmap aMainBitmap = aVirtualDevice.GetBitmap(Point(), aVirtualDevice.GetOutputSizePixel()); 198 #if defined(MACOSX) 199 AlphaMask aMaskBitmap( aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel())); 200 #else 201 Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel()); 202 #endif 203 aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap); 204 205 // add to vector 206 maSteps.push_back(aNextStep); 207 } 208 } 209 } 210 } // end of anonymous namespace 211 212 ////////////////////////////////////////////////////////////////////////////// 213 214 namespace drawinglayer 215 { 216 namespace primitive2d 217 { create2DDecompositionOfGraphic(const Graphic & rGraphic,const basegfx::B2DHomMatrix & rTransform)218 Primitive2DSequence create2DDecompositionOfGraphic( 219 const Graphic& rGraphic, 220 const basegfx::B2DHomMatrix& rTransform) 221 { 222 Primitive2DSequence aRetval; 223 224 switch(rGraphic.GetType()) 225 { 226 case GRAPHIC_BITMAP : 227 { 228 if(rGraphic.IsAnimated()) 229 { 230 // prepare animation data 231 animatedBitmapExPreparator aData(rGraphic); 232 233 if(aData.count()) 234 { 235 // create sub-primitives for animated bitmap and the needed animation loop 236 animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff); 237 Primitive2DSequence aBitmapPrimitives(aData.count()); 238 239 for(sal_uInt32 a(0); a < aData.count(); a++) 240 { 241 animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count()); 242 aAnimationLoop.append(aTime); 243 aBitmapPrimitives[a] = new BitmapPrimitive2D( 244 aData.stepBitmapEx(a), 245 rTransform); 246 } 247 248 // prepare animation list 249 animation::AnimationEntryList aAnimationList; 250 aAnimationList.append(aAnimationLoop); 251 252 // create and add animated switch primitive 253 aRetval.realloc(1); 254 aRetval[0] = new AnimatedSwitchPrimitive2D( 255 aAnimationList, 256 aBitmapPrimitives, 257 false); 258 } 259 } 260 else if(rGraphic.getSvgData().get()) 261 { 262 // embedded Svg fill, create embed transform 263 const basegfx::B2DRange& rSvgRange(rGraphic.getSvgData()->getRange()); 264 265 if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0)) 266 { 267 // translate back to origin, scale to unit coordinates 268 basegfx::B2DHomMatrix aEmbedSvg( 269 basegfx::tools::createTranslateB2DHomMatrix( 270 -rSvgRange.getMinX(), 271 -rSvgRange.getMinY())); 272 273 aEmbedSvg.scale( 274 1.0 / rSvgRange.getWidth(), 275 1.0 / rSvgRange.getHeight()); 276 277 // apply created object transformation 278 aEmbedSvg = rTransform * aEmbedSvg; 279 280 // add Svg primitives embedded 281 aRetval.realloc(1); 282 aRetval[0] = new TransformPrimitive2D( 283 aEmbedSvg, 284 rGraphic.getSvgData()->getPrimitive2DSequence()); 285 } 286 } 287 else 288 { 289 aRetval.realloc(1); 290 aRetval[0] = new BitmapPrimitive2D( 291 rGraphic.GetBitmapEx(), 292 rTransform); 293 } 294 295 break; 296 } 297 298 case GRAPHIC_GDIMETAFILE : 299 { 300 #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 301 static bool bDoTest(false); 302 303 if(bDoTest) 304 { 305 // All this is/was test code for testing MetafilePrimitive2D::create2DDecomposition 306 // extensively. It may be needed again when diverse actions need debugging, so i leave 307 // it in here, but take it out using USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE. 308 // Use it by compiling with the code, insert any DrawObject, convert to Metafile. The 309 // debugger will then stop here (when breakpoint set, of course). You may enter single 310 // parts of actions and/or change to true what You want to check. 311 GDIMetaFile aMtf; 312 VirtualDevice aOut; 313 const basegfx::B2DRange aRange(getB2DRange(rViewInformation)); 314 const Rectangle aRectangle( 315 basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()), 316 basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY())); 317 const Point aOrigin(aRectangle.TopLeft()); 318 const Fraction aScaleX(aRectangle.getWidth()); 319 const Fraction aScaleY(aRectangle.getHeight()); 320 MapMode aMapMode(MAP_100TH_MM, aOrigin, aScaleX, aScaleY); 321 322 Size aDummySize(2, 2); 323 aOut.SetOutputSizePixel(aDummySize); 324 aOut.EnableOutput(FALSE); 325 aOut.SetMapMode(aMapMode); 326 327 aMtf.Clear(); 328 aMtf.Record(&aOut); 329 330 const Fraction aNeutralFraction(1, 1); 331 const MapMode aRelativeMapMode( 332 MAP_RELATIVE, 333 Point(-aRectangle.Left(), -aRectangle.Top()), 334 aNeutralFraction, aNeutralFraction); 335 aOut.SetMapMode(aRelativeMapMode); 336 337 if(false) 338 { 339 const sal_Int32 nHor(aRectangle.getWidth() / 4); 340 const sal_Int32 nVer(aRectangle.getHeight() / 4); 341 const Rectangle aCenteredRectangle( 342 aRectangle.Left() + nHor, aRectangle.Top() + nVer, 343 aRectangle.Right() - nHor, aRectangle.Bottom() - nVer); 344 aOut.SetClipRegion(aCenteredRectangle); 345 } 346 347 if(false) 348 { 349 const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight()); 350 aOut.IntersectClipRegion(aRightRectangle); 351 } 352 353 if(false) 354 { 355 const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight()); 356 const Rectangle aBottomRectangle(aRectangle.LeftCenter(), aRectangle.BottomRight()); 357 Region aRegion(aRightRectangle); 358 aRegion.Intersect(aBottomRectangle); 359 aOut.IntersectClipRegion(aRegion); 360 } 361 362 if(false) 363 { 364 const sal_Int32 nHor(aRectangle.getWidth() / 10); 365 const sal_Int32 nVer(aRectangle.getHeight() / 10); 366 aOut.MoveClipRegion(nHor, nVer); 367 } 368 369 if(false) 370 { 371 Wallpaper aWallpaper(Color(COL_BLACK)); 372 aOut.DrawWallpaper(aRectangle, aWallpaper); 373 } 374 375 if(false) 376 { 377 Wallpaper aWallpaper(Gradient(GRADIENT_LINEAR, Color(COL_RED), Color(COL_GREEN))); 378 aOut.DrawWallpaper(aRectangle, aWallpaper); 379 } 380 381 if(false) 382 { 383 SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); 384 vcl::PNGReader aPNGReader(aRead); 385 BitmapEx aBitmapEx(aPNGReader.Read()); 386 Wallpaper aWallpaper(aBitmapEx); 387 aOut.DrawWallpaper(aRectangle, aWallpaper); 388 } 389 390 if(false) 391 { 392 const double fHor(aRectangle.getWidth()); 393 const double fVer(aRectangle.getHeight()); 394 Color aColor(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)); 395 396 for(sal_uInt32 a(0); a < 5000; a++) 397 { 398 const Point aPoint( 399 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 400 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 401 402 if(!(a % 3)) 403 { 404 aColor = Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)); 405 } 406 407 aOut.DrawPixel(aPoint, aColor); 408 } 409 } 410 411 if(false) 412 { 413 const double fHor(aRectangle.getWidth()); 414 const double fVer(aRectangle.getHeight()); 415 416 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 417 aOut.SetFillColor(); 418 419 for(sal_uInt32 a(0); a < 5000; a++) 420 { 421 const Point aPoint( 422 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 423 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 424 aOut.DrawPixel(aPoint); 425 } 426 } 427 428 if(false) 429 { 430 const double fHor(aRectangle.getWidth()); 431 const double fVer(aRectangle.getHeight()); 432 433 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 434 aOut.SetFillColor(); 435 436 Point aStart( 437 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 438 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 439 Point aStop( 440 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 441 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 442 443 LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0)); 444 bool bUseLineInfo(false); 445 446 for(sal_uInt32 a(0); a < 20; a++) 447 { 448 if(!(a%6)) 449 { 450 bUseLineInfo = !bUseLineInfo; 451 } 452 453 if(!(a%4)) 454 { 455 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 456 } 457 458 if(a%3) 459 { 460 aStart = aStop; 461 aStop = Point( 462 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 463 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 464 } 465 else 466 { 467 aStart = Point( 468 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 469 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 470 aStop = Point( 471 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 472 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 473 } 474 475 if(bUseLineInfo) 476 { 477 aOut.DrawLine(aStart, aStop, aLineInfo); 478 } 479 else 480 { 481 aOut.DrawLine(aStart, aStop); 482 } 483 } 484 } 485 486 if(false) 487 { 488 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 489 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 490 aOut.DrawRect(aRectangle); 491 } 492 493 if(false) 494 { 495 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 496 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 497 const sal_uInt32 nHor(aRectangle.getWidth() / 10); 498 const sal_uInt32 nVer(aRectangle.getHeight() / 10); 499 aOut.DrawRect(aRectangle, nHor, nVer); 500 } 501 502 if(false) 503 { 504 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 505 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 506 aOut.DrawEllipse(aRectangle); 507 } 508 509 if(false) 510 { 511 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 512 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 513 aOut.DrawArc(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); 514 } 515 516 if(false) 517 { 518 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 519 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 520 aOut.DrawPie(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); 521 } 522 523 if(false) 524 { 525 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 526 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 527 aOut.DrawChord(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); 528 } 529 530 if(false) 531 { 532 const double fHor(aRectangle.getWidth()); 533 const double fVer(aRectangle.getHeight()); 534 535 for(sal_uInt32 b(0); b < 5; b++) 536 { 537 const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0))); 538 const bool bClose(basegfx::fround(rand() / 32767.0)); 539 Polygon aPolygon(nCount + (bClose ? 1 : 0)); 540 541 for(sal_uInt32 a(0); a < nCount; a++) 542 { 543 const Point aPoint( 544 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 545 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 546 aPolygon[a] = aPoint; 547 } 548 549 if(bClose) 550 { 551 aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; 552 } 553 554 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 555 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 556 557 if(!(b%2)) 558 { 559 const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0)); 560 aOut.DrawPolyLine(aPolygon, aLineInfo); 561 } 562 else 563 { 564 aOut.DrawPolyLine(aPolygon); 565 } 566 } 567 } 568 569 if(false) 570 { 571 const double fHor(aRectangle.getWidth()); 572 const double fVer(aRectangle.getHeight()); 573 574 for(sal_uInt32 b(0); b < 5; b++) 575 { 576 const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0))); 577 const bool bClose(basegfx::fround(rand() / 32767.0)); 578 Polygon aPolygon(nCount + (bClose ? 1 : 0)); 579 580 for(sal_uInt32 a(0); a < nCount; a++) 581 { 582 const Point aPoint( 583 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 584 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 585 aPolygon[a] = aPoint; 586 } 587 588 if(bClose) 589 { 590 aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; 591 } 592 593 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 594 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 595 aOut.DrawPolygon(aPolygon); 596 } 597 } 598 599 if(false) 600 { 601 const double fHor(aRectangle.getWidth()); 602 const double fVer(aRectangle.getHeight()); 603 PolyPolygon aPolyPolygon; 604 605 for(sal_uInt32 b(0); b < 3; b++) 606 { 607 const sal_uInt32 nCount(basegfx::fround(rand() * (6 / 32767.0))); 608 const bool bClose(basegfx::fround(rand() / 32767.0)); 609 Polygon aPolygon(nCount + (bClose ? 1 : 0)); 610 611 for(sal_uInt32 a(0); a < nCount; a++) 612 { 613 const Point aPoint( 614 aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), 615 aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); 616 aPolygon[a] = aPoint; 617 } 618 619 if(bClose) 620 { 621 aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; 622 } 623 624 aPolyPolygon.Insert(aPolygon); 625 } 626 627 aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 628 aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); 629 aOut.DrawPolyPolygon(aPolyPolygon); 630 } 631 632 if(false) 633 { 634 SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); 635 vcl::PNGReader aPNGReader(aRead); 636 BitmapEx aBitmapEx(aPNGReader.Read()); 637 aOut.DrawBitmapEx(aRectangle.TopLeft(), aBitmapEx); 638 } 639 640 if(false) 641 { 642 SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); 643 vcl::PNGReader aPNGReader(aRead); 644 BitmapEx aBitmapEx(aPNGReader.Read()); 645 aOut.DrawBitmapEx(aRectangle.TopLeft(), aRectangle.GetSize(), aBitmapEx); 646 } 647 648 if(false) 649 { 650 SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); 651 vcl::PNGReader aPNGReader(aRead); 652 BitmapEx aBitmapEx(aPNGReader.Read()); 653 const Size aSizePixel(aBitmapEx.GetSizePixel()); 654 aOut.DrawBitmapEx( 655 aRectangle.TopLeft(), 656 aRectangle.GetSize(), 657 Point(0, 0), 658 Size(aSizePixel.Width() /2, aSizePixel.Height() / 2), 659 aBitmapEx); 660 } 661 662 if(false) 663 { 664 const double fHor(aRectangle.getWidth()); 665 const double fVer(aRectangle.getHeight()); 666 const Point aPointA( 667 aRectangle.Left() + basegfx::fround(fHor * 0.2), 668 aRectangle.Top() + basegfx::fround(fVer * 0.3)); 669 const Point aPointB( 670 aRectangle.Left() + basegfx::fround(fHor * 0.2), 671 aRectangle.Top() + basegfx::fround(fVer * 0.5)); 672 const Point aPointC( 673 aRectangle.Left() + basegfx::fround(fHor * 0.2), 674 aRectangle.Top() + basegfx::fround(fVer * 0.7)); 675 const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8); 676 677 const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8); 678 Font aFont(aFontName, Size(0, 1000)); 679 aFont.SetAlign(ALIGN_BASELINE); 680 aFont.SetColor(COL_RED); 681 //sal_Int32* pDXArray = new sal_Int32[aText.Len()]; 682 683 aFont.SetOutline(true); 684 aOut.SetFont(aFont); 685 aOut.DrawText(aPointA, aText, 0, aText.Len()); 686 687 aFont.SetShadow(true); 688 aOut.SetFont(aFont); 689 aOut.DrawText(aPointB, aText, 0, aText.Len()); 690 691 aFont.SetRelief(RELIEF_EMBOSSED); 692 aOut.SetFont(aFont); 693 aOut.DrawText(aPointC, aText, 0, aText.Len()); 694 695 //delete pDXArray; 696 } 697 698 if(false) 699 { 700 const double fHor(aRectangle.getWidth()); 701 const double fVer(aRectangle.getHeight()); 702 const Point aPointA( 703 aRectangle.Left() + basegfx::fround(fHor * 0.2), 704 aRectangle.Top() + basegfx::fround(fVer * 0.3)); 705 const Point aPointB( 706 aRectangle.Left() + basegfx::fround(fHor * 0.2), 707 aRectangle.Top() + basegfx::fround(fVer * 0.5)); 708 const Point aPointC( 709 aRectangle.Left() + basegfx::fround(fHor * 0.2), 710 aRectangle.Top() + basegfx::fround(fVer * 0.7)); 711 const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8); 712 713 const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8); 714 Font aFont(aFontName, Size(0, 1000)); 715 aFont.SetAlign(ALIGN_BASELINE); 716 aFont.SetColor(COL_RED); 717 718 aOut.SetFont(aFont); 719 const sal_Int32 nWidth(aOut.GetTextWidth(aText, 0, aText.Len())); 720 aOut.DrawText(aPointA, aText, 0, aText.Len()); 721 aOut.DrawTextLine(aPointA, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); 722 aOut.DrawTextLine(aPointB, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); 723 aOut.DrawTextLine(aPointC, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); 724 } 725 726 aMtf.Stop(); 727 aMtf.WindStart(); 728 aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM)); 729 aMtf.SetPrefSize(Size(aRectangle.getWidth(), aRectangle.getHeight())); 730 731 aRetval.realloc(1); 732 aRetval[0] = new MetafilePrimitive2D( 733 rTransform, 734 aMtf); 735 } 736 else 737 { 738 #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 739 // create MetafilePrimitive2D 740 const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile(); 741 742 aRetval.realloc(1); 743 aRetval[0] = new MetafilePrimitive2D( 744 rTransform, 745 rMetafile); 746 747 // #i100357# find out if clipping is needed for this primitive. Unfortunately, 748 // there exist Metafiles who's content is bigger than the proposed PrefSize set 749 // at them. This is an error, but we need to work around this 750 const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); 751 const Size aMetaFileRealSize( 752 const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( 753 *Application::GetDefaultDevice()).GetSize()); 754 755 if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() 756 || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) 757 { 758 // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon 759 basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon()); 760 aMaskPolygon.transform(rTransform); 761 762 // #124073# the clde below was compiler-dependent. Normally, 763 // a compiler will 764 // - alloc mem 765 // - ececute the constructor 766 // - do the assignment 767 // but the mac compiler does alloc-assign-constructor, thus 768 // modifying aRetval[0] befure aRetval gets used in the 769 // constructor. This creates an endless loop in the primitive 770 // stack. Thus do it the safe way. 771 // 772 // aRetval[0] = new MaskPrimitive2D( 773 // basegfx::B2DPolyPolygon(aMaskPolygon), 774 // aRetval); 775 MaskPrimitive2D* pMaskPrimitive2D = new MaskPrimitive2D( 776 basegfx::B2DPolyPolygon(aMaskPolygon), 777 aRetval); 778 aRetval[0] = pMaskPrimitive2D; 779 } 780 #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 781 } 782 #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE 783 784 break; 785 } 786 787 default: 788 { 789 // nothing to create 790 break; 791 } 792 } 793 794 return aRetval; 795 } 796 } // end of namespace primitive2d 797 } // end of namespace drawinglayer 798 799 ////////////////////////////////////////////////////////////////////////////// 800 801 namespace drawinglayer 802 { 803 namespace primitive2d 804 { create2DColorModifierEmbeddingsAsNeeded(const Primitive2DSequence & rChildren,GraphicDrawMode aGraphicDrawMode,double fLuminance,double fContrast,double fRed,double fGreen,double fBlue,double fGamma,bool bInvert)805 Primitive2DSequence create2DColorModifierEmbeddingsAsNeeded( 806 const Primitive2DSequence& rChildren, 807 GraphicDrawMode aGraphicDrawMode, 808 double fLuminance, 809 double fContrast, 810 double fRed, 811 double fGreen, 812 double fBlue, 813 double fGamma, 814 bool bInvert) 815 { 816 Primitive2DSequence aRetval; 817 818 if(!rChildren.getLength()) 819 { 820 // no child content, done 821 return aRetval; 822 } 823 824 // set child content as retval; that is what will be used as child content in all 825 // embeddings from here 826 aRetval = rChildren; 827 828 if(GRAPHICDRAWMODE_WATERMARK == aGraphicDrawMode) 829 { 830 // this is solved by applying fixed values additionally to luminance 831 // and contrast, do it here and reset DrawMode to GRAPHICDRAWMODE_STANDARD 832 // original in svtools uses: 833 // #define WATERMARK_LUM_OFFSET 50 834 // #define WATERMARK_CON_OFFSET -70 835 fLuminance = basegfx::clamp(fLuminance + 0.5, -1.0, 1.0); 836 fContrast = basegfx::clamp(fContrast - 0.7, -1.0, 1.0); 837 aGraphicDrawMode = GRAPHICDRAWMODE_STANDARD; 838 } 839 840 // DrawMode (GRAPHICDRAWMODE_WATERMARK already handled) 841 switch(aGraphicDrawMode) 842 { 843 case GRAPHICDRAWMODE_GREYS: 844 { 845 // convert to grey 846 const Primitive2DReference aPrimitiveGrey( 847 new ModifiedColorPrimitive2D( 848 aRetval, 849 basegfx::BColorModifierSharedPtr( 850 new basegfx::BColorModifier_gray()))); 851 852 aRetval = Primitive2DSequence(&aPrimitiveGrey, 1); 853 break; 854 } 855 case GRAPHICDRAWMODE_MONO: 856 { 857 // convert to mono (black/white with threshold 0.5) 858 const Primitive2DReference aPrimitiveBlackAndWhite( 859 new ModifiedColorPrimitive2D( 860 aRetval, 861 basegfx::BColorModifierSharedPtr( 862 new basegfx::BColorModifier_black_and_white(0.5)))); 863 864 aRetval = Primitive2DSequence(&aPrimitiveBlackAndWhite, 1); 865 break; 866 } 867 case GRAPHICDRAWMODE_WATERMARK: 868 { 869 OSL_ENSURE(false, "OOps, GRAPHICDRAWMODE_WATERMARK should already be handled (see above)"); 870 // fallthrough intended 871 } 872 default: // case GRAPHICDRAWMODE_STANDARD: 873 { 874 // nothing to do 875 break; 876 } 877 } 878 879 // mnContPercent, mnLumPercent, mnRPercent, mnGPercent, mnBPercent 880 // handled in a single call 881 if(!basegfx::fTools::equalZero(fLuminance) 882 || !basegfx::fTools::equalZero(fContrast) 883 || !basegfx::fTools::equalZero(fRed) 884 || !basegfx::fTools::equalZero(fGreen) 885 || !basegfx::fTools::equalZero(fBlue)) 886 { 887 const Primitive2DReference aPrimitiveRGBLuminannceContrast( 888 new ModifiedColorPrimitive2D( 889 aRetval, 890 basegfx::BColorModifierSharedPtr( 891 new basegfx::BColorModifier_RGBLuminanceContrast( 892 fRed, 893 fGreen, 894 fBlue, 895 fLuminance, 896 fContrast)))); 897 898 aRetval = Primitive2DSequence(&aPrimitiveRGBLuminannceContrast, 1); 899 } 900 901 // gamma (boolean) 902 if(!basegfx::fTools::equal(fGamma, 1.0)) 903 { 904 const Primitive2DReference aPrimitiveGamma( 905 new ModifiedColorPrimitive2D( 906 aRetval, 907 basegfx::BColorModifierSharedPtr( 908 new basegfx::BColorModifier_gamma( 909 fGamma)))); 910 911 aRetval = Primitive2DSequence(&aPrimitiveGamma, 1); 912 } 913 914 // invert (boolean) 915 if(bInvert) 916 { 917 const Primitive2DReference aPrimitiveInvert( 918 new ModifiedColorPrimitive2D( 919 aRetval, 920 basegfx::BColorModifierSharedPtr( 921 new basegfx::BColorModifier_invert()))); 922 923 aRetval = Primitive2DSequence(&aPrimitiveInvert, 1); 924 } 925 926 return aRetval; 927 } 928 929 } // end of namespace primitive2d 930 } // end of namespace drawinglayer 931 932 ////////////////////////////////////////////////////////////////////////////// 933 // eof 934