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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_drawinglayer.hxx"
26 
27 #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
28 #include <drawinglayer/animation/animationtiming.hxx>
29 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
31 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
33 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
34 #include <basegfx/polygon/b2dpolygon.hxx>
35 #include <basegfx/polygon/b2dpolygontools.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 
78 		sal_uInt32 count() const { return maSteps.size(); }
79 		sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); }
80 		sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; }
81 		const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; }
82 	};
83 
84 	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 
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 				Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap(Point(), aVirtualDeviceMask.GetOutputSizePixel());
199 				aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap);
200 
201 				// add to vector
202 				maSteps.push_back(aNextStep);
203 			}
204 		}
205 	}
206 } // end of anonymous namespace
207 
208 //////////////////////////////////////////////////////////////////////////////
209 
210 namespace drawinglayer
211 {
212 	namespace primitive2d
213 	{
214 		Primitive2DSequence create2DDecompositionOfGraphic(
215             const Graphic& rGraphic,
216             const basegfx::B2DHomMatrix& rTransform)
217 		{
218 			Primitive2DSequence aRetval;
219 
220             switch(rGraphic.GetType())
221 			{
222 				case GRAPHIC_BITMAP :
223 				{
224                     if(rGraphic.IsAnimated())
225 					{
226 						// prepare animation data
227 						animatedBitmapExPreparator aData(rGraphic);
228 
229 						if(aData.count())
230 						{
231 							// create sub-primitives for animated bitmap and the needed animation loop
232 							animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff);
233 							Primitive2DSequence aBitmapPrimitives(aData.count());
234 
235 							for(sal_uInt32 a(0); a < aData.count(); a++)
236 							{
237                                 animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count());
238 								aAnimationLoop.append(aTime);
239 								aBitmapPrimitives[a] = new BitmapPrimitive2D(
240                                     aData.stepBitmapEx(a),
241                                     rTransform);
242 							}
243 
244 							// prepare animation list
245 							animation::AnimationEntryList aAnimationList;
246 							aAnimationList.append(aAnimationLoop);
247 
248 							// create and add animated switch primitive
249                             aRetval.realloc(1);
250 							aRetval[0] = new AnimatedSwitchPrimitive2D(
251                                 aAnimationList,
252                                 aBitmapPrimitives,
253                                 false);
254 						}
255 					}
256                     else if(rGraphic.getSvgData().get())
257                     {
258                         // embedded Svg fill, create embed transform
259                         const basegfx::B2DRange& rSvgRange(rGraphic.getSvgData()->getRange());
260 
261                         if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0))
262                         {
263                             // translate back to origin, scale to unit coordinates
264                             basegfx::B2DHomMatrix aEmbedSvg(
265                                 basegfx::tools::createTranslateB2DHomMatrix(
266                                     -rSvgRange.getMinX(),
267                                     -rSvgRange.getMinY()));
268 
269                             aEmbedSvg.scale(
270                                 1.0 / rSvgRange.getWidth(),
271                                 1.0 / rSvgRange.getHeight());
272 
273                             // apply created object transformation
274                             aEmbedSvg = rTransform * aEmbedSvg;
275 
276                             // add Svg primitives embedded
277                             aRetval.realloc(1);
278                             aRetval[0] = new TransformPrimitive2D(
279                                 aEmbedSvg,
280                                 rGraphic.getSvgData()->getPrimitive2DSequence());
281                         }
282                     }
283 					else
284 					{
285                         aRetval.realloc(1);
286 						aRetval[0] = new BitmapPrimitive2D(
287                             rGraphic.GetBitmapEx(),
288                             rTransform);
289 					}
290 
291 					break;
292 				}
293 
294 				case GRAPHIC_GDIMETAFILE :
295 				{
296 #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
297                     static bool bDoTest(false);
298 
299                     if(bDoTest)
300                     {
301 						// All this is/was test code for testing MetafilePrimitive2D::create2DDecomposition
302 						// extensively. It may be needed again when diverse actions need debugging, so i leave
303 						// it in here, but take it out using USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE.
304 						// Use it by compiling with the code, insert any DrawObject, convert to Metafile. The
305 						// debugger will then stop here (when breakpoint set, of course). You may enter single
306 						// parts of actions and/or change to true what You want to check.
307                         GDIMetaFile aMtf;
308 			            VirtualDevice aOut;
309         		        const basegfx::B2DRange aRange(getB2DRange(rViewInformation));
310                         const Rectangle aRectangle(
311                             basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()),
312                             basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY()));
313                         const Point aOrigin(aRectangle.TopLeft());
314                         const Fraction aScaleX(aRectangle.getWidth());
315                         const Fraction aScaleY(aRectangle.getHeight());
316                         MapMode aMapMode(MAP_100TH_MM, aOrigin, aScaleX, aScaleY);
317 
318                         Size aDummySize(2, 2);
319                         aOut.SetOutputSizePixel(aDummySize);
320 			            aOut.EnableOutput(FALSE);
321 			            aOut.SetMapMode(aMapMode);
322 
323                         aMtf.Clear();
324 			            aMtf.Record(&aOut);
325 
326 			            const Fraction aNeutralFraction(1, 1);
327 			            const MapMode aRelativeMapMode(
328                             MAP_RELATIVE,
329                             Point(-aRectangle.Left(), -aRectangle.Top()),
330                             aNeutralFraction, aNeutralFraction);
331 			            aOut.SetMapMode(aRelativeMapMode);
332 
333                         if(false)
334                         {
335                             const sal_Int32 nHor(aRectangle.getWidth() / 4);
336                             const sal_Int32 nVer(aRectangle.getHeight() / 4);
337                             const Rectangle aCenteredRectangle(
338                                 aRectangle.Left() + nHor, aRectangle.Top() + nVer,
339                                 aRectangle.Right() - nHor, aRectangle.Bottom() - nVer);
340                             aOut.SetClipRegion(aCenteredRectangle);
341                         }
342 
343                         if(false)
344                         {
345                             const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight());
346                             aOut.IntersectClipRegion(aRightRectangle);
347                         }
348 
349                         if(false)
350                         {
351                             const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight());
352                             const Rectangle aBottomRectangle(aRectangle.LeftCenter(), aRectangle.BottomRight());
353                             Region aRegion(aRightRectangle);
354                             aRegion.Intersect(aBottomRectangle);
355                             aOut.IntersectClipRegion(aRegion);
356                         }
357 
358                         if(false)
359                         {
360                             const sal_Int32 nHor(aRectangle.getWidth() / 10);
361                             const sal_Int32 nVer(aRectangle.getHeight() / 10);
362                             aOut.MoveClipRegion(nHor, nVer);
363                         }
364 
365                         if(false)
366                         {
367                             Wallpaper aWallpaper(Color(COL_BLACK));
368                             aOut.DrawWallpaper(aRectangle, aWallpaper);
369                         }
370 
371                         if(false)
372                         {
373                             Wallpaper aWallpaper(Gradient(GRADIENT_LINEAR, Color(COL_RED), Color(COL_GREEN)));
374                             aOut.DrawWallpaper(aRectangle, aWallpaper);
375                         }
376 
377                         if(false)
378                         {
379             				SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
380                             vcl::PNGReader aPNGReader(aRead);
381 		                    BitmapEx aBitmapEx(aPNGReader.Read());
382                             Wallpaper aWallpaper(aBitmapEx);
383                             aOut.DrawWallpaper(aRectangle, aWallpaper);
384                         }
385 
386                         if(false)
387                         {
388                             const double fHor(aRectangle.getWidth());
389                             const double fVer(aRectangle.getHeight());
390 							Color aColor(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0));
391 
392 							for(sal_uInt32 a(0); a < 5000; a++)
393 							{
394 								const Point aPoint(
395 									aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
396 									aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
397 
398 								if(!(a % 3))
399 								{
400 									aColor = Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0));
401 								}
402 
403 								aOut.DrawPixel(aPoint, aColor);
404 							}
405 						}
406 
407                         if(false)
408                         {
409                             const double fHor(aRectangle.getWidth());
410                             const double fVer(aRectangle.getHeight());
411 
412 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
413 							aOut.SetFillColor();
414 
415 							for(sal_uInt32 a(0); a < 5000; a++)
416 							{
417 								const Point aPoint(
418 									aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
419 									aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
420 								aOut.DrawPixel(aPoint);
421 							}
422 						}
423 
424                         if(false)
425                         {
426                             const double fHor(aRectangle.getWidth());
427                             const double fVer(aRectangle.getHeight());
428 
429 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
430 							aOut.SetFillColor();
431 
432 							Point aStart(
433 								aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
434 								aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
435 							Point aStop(
436 								aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
437 								aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
438 
439 							LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0));
440 							bool bUseLineInfo(false);
441 
442 							for(sal_uInt32 a(0); a < 20; a++)
443 							{
444 								if(!(a%6))
445 								{
446 									bUseLineInfo = !bUseLineInfo;
447 								}
448 
449 								if(!(a%4))
450 								{
451 									aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
452 								}
453 
454 								if(a%3)
455 								{
456 									aStart = aStop;
457 									aStop = Point(
458 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
459 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
460 								}
461 								else
462 								{
463 									aStart = Point(
464 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
465 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
466 									aStop = Point(
467 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
468 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
469 								}
470 
471 								if(bUseLineInfo)
472 								{
473 									aOut.DrawLine(aStart, aStop, aLineInfo);
474 								}
475 								else
476 								{
477 									aOut.DrawLine(aStart, aStop);
478 								}
479 							}
480 						}
481 
482                         if(false)
483                         {
484 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
485 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
486 							aOut.DrawRect(aRectangle);
487 						}
488 
489                         if(false)
490                         {
491 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
492 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
493                             const sal_uInt32 nHor(aRectangle.getWidth() / 10);
494                             const sal_uInt32 nVer(aRectangle.getHeight() / 10);
495 							aOut.DrawRect(aRectangle, nHor, nVer);
496 						}
497 
498                         if(false)
499                         {
500 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
501 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
502 							aOut.DrawEllipse(aRectangle);
503 						}
504 
505                         if(false)
506                         {
507 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
508 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
509 							aOut.DrawArc(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
510 						}
511 
512                         if(false)
513                         {
514 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
515 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
516 							aOut.DrawPie(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
517 						}
518 
519                         if(false)
520                         {
521 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
522 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
523 							aOut.DrawChord(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
524 						}
525 
526                         if(false)
527                         {
528                             const double fHor(aRectangle.getWidth());
529                             const double fVer(aRectangle.getHeight());
530 
531 							for(sal_uInt32 b(0); b < 5; b++)
532 							{
533 								const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0)));
534 								const bool bClose(basegfx::fround(rand() / 32767.0));
535 								Polygon aPolygon(nCount + (bClose ? 1 : 0));
536 
537 								for(sal_uInt32 a(0); a < nCount; a++)
538 								{
539 									const Point aPoint(
540 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
541 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
542 									aPolygon[a] = aPoint;
543 								}
544 
545 								if(bClose)
546 								{
547 									aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
548 								}
549 
550 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
551 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
552 
553 								if(!(b%2))
554 								{
555 									const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0));
556 									aOut.DrawPolyLine(aPolygon, aLineInfo);
557 								}
558 								else
559 								{
560 									aOut.DrawPolyLine(aPolygon);
561 								}
562 							}
563 						}
564 
565                         if(false)
566                         {
567                             const double fHor(aRectangle.getWidth());
568                             const double fVer(aRectangle.getHeight());
569 
570 							for(sal_uInt32 b(0); b < 5; b++)
571 							{
572 								const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0)));
573 								const bool bClose(basegfx::fround(rand() / 32767.0));
574 								Polygon aPolygon(nCount + (bClose ? 1 : 0));
575 
576 								for(sal_uInt32 a(0); a < nCount; a++)
577 								{
578 									const Point aPoint(
579 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
580 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
581 									aPolygon[a] = aPoint;
582 								}
583 
584 								if(bClose)
585 								{
586 									aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
587 								}
588 
589 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
590 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
591 								aOut.DrawPolygon(aPolygon);
592 							}
593 						}
594 
595                         if(false)
596                         {
597                             const double fHor(aRectangle.getWidth());
598                             const double fVer(aRectangle.getHeight());
599 							PolyPolygon aPolyPolygon;
600 
601 							for(sal_uInt32 b(0); b < 3; b++)
602 							{
603 								const sal_uInt32 nCount(basegfx::fround(rand() * (6 / 32767.0)));
604 								const bool bClose(basegfx::fround(rand() / 32767.0));
605 								Polygon aPolygon(nCount + (bClose ? 1 : 0));
606 
607 								for(sal_uInt32 a(0); a < nCount; a++)
608 								{
609 									const Point aPoint(
610 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
611 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
612 									aPolygon[a] = aPoint;
613 								}
614 
615 								if(bClose)
616 								{
617 									aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
618 								}
619 
620 								aPolyPolygon.Insert(aPolygon);
621 							}
622 
623 							aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
624 							aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
625 							aOut.DrawPolyPolygon(aPolyPolygon);
626 						}
627 
628                         if(false)
629                         {
630             				SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
631                             vcl::PNGReader aPNGReader(aRead);
632 		                    BitmapEx aBitmapEx(aPNGReader.Read());
633 							aOut.DrawBitmapEx(aRectangle.TopLeft(), aBitmapEx);
634 						}
635 
636                         if(false)
637                         {
638             				SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
639                             vcl::PNGReader aPNGReader(aRead);
640 		                    BitmapEx aBitmapEx(aPNGReader.Read());
641 							aOut.DrawBitmapEx(aRectangle.TopLeft(), aRectangle.GetSize(), aBitmapEx);
642 						}
643 
644                         if(false)
645                         {
646             				SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
647                             vcl::PNGReader aPNGReader(aRead);
648 		                    BitmapEx aBitmapEx(aPNGReader.Read());
649 							const Size aSizePixel(aBitmapEx.GetSizePixel());
650 							aOut.DrawBitmapEx(
651 								aRectangle.TopLeft(),
652 								aRectangle.GetSize(),
653 								Point(0, 0),
654 								Size(aSizePixel.Width() /2, aSizePixel.Height() / 2),
655 								aBitmapEx);
656 						}
657 
658                         if(false)
659                         {
660                             const double fHor(aRectangle.getWidth());
661                             const double fVer(aRectangle.getHeight());
662 							const Point aPointA(
663 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
664 								aRectangle.Top() + basegfx::fround(fVer * 0.3));
665 							const Point aPointB(
666 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
667 								aRectangle.Top() + basegfx::fround(fVer * 0.5));
668 							const Point aPointC(
669 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
670 								aRectangle.Top() + basegfx::fround(fVer * 0.7));
671                             const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8);
672 
673                             const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8);
674                             Font aFont(aFontName, Size(0, 1000));
675                             aFont.SetAlign(ALIGN_BASELINE);
676                             aFont.SetColor(COL_RED);
677                             //sal_Int32* pDXArray = new sal_Int32[aText.Len()];
678 
679                             aFont.SetOutline(true);
680                             aOut.SetFont(aFont);
681                             aOut.DrawText(aPointA, aText, 0, aText.Len());
682 
683                             aFont.SetShadow(true);
684                             aOut.SetFont(aFont);
685                             aOut.DrawText(aPointB, aText, 0, aText.Len());
686 
687                             aFont.SetRelief(RELIEF_EMBOSSED);
688                             aOut.SetFont(aFont);
689                             aOut.DrawText(aPointC, aText, 0, aText.Len());
690 
691                             //delete pDXArray;
692                         }
693 
694                         if(false)
695                         {
696                             const double fHor(aRectangle.getWidth());
697                             const double fVer(aRectangle.getHeight());
698 							const Point aPointA(
699 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
700 								aRectangle.Top() + basegfx::fround(fVer * 0.3));
701 							const Point aPointB(
702 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
703 								aRectangle.Top() + basegfx::fround(fVer * 0.5));
704 							const Point aPointC(
705 								aRectangle.Left() + basegfx::fround(fHor * 0.2),
706 								aRectangle.Top() + basegfx::fround(fVer * 0.7));
707                             const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8);
708 
709                             const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8);
710                             Font aFont(aFontName, Size(0, 1000));
711                             aFont.SetAlign(ALIGN_BASELINE);
712                             aFont.SetColor(COL_RED);
713 
714                             aOut.SetFont(aFont);
715 							const sal_Int32 nWidth(aOut.GetTextWidth(aText, 0, aText.Len()));
716                             aOut.DrawText(aPointA, aText, 0, aText.Len());
717                             aOut.DrawTextLine(aPointA, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
718                             aOut.DrawTextLine(aPointB, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
719                             aOut.DrawTextLine(aPointC, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
720                         }
721 
722                         aMtf.Stop();
723 			            aMtf.WindStart();
724 		                aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM));
725 			            aMtf.SetPrefSize(Size(aRectangle.getWidth(), aRectangle.getHeight()));
726 
727                         aRetval.realloc(1);
728                         aRetval[0] = new MetafilePrimitive2D(
729                             rTransform,
730                             aMtf);
731                     }
732                     else
733                     {
734 #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
735                         // create MetafilePrimitive2D
736                         const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile();
737 
738                         aRetval.realloc(1);
739                         aRetval[0] = new MetafilePrimitive2D(
740                             rTransform,
741                             rMetafile);
742 
743                         // #i100357# find out if clipping is needed for this primitive. Unfortunately,
744                         // there exist Metafiles who's content is bigger than the proposed PrefSize set
745                         // at them. This is an error, but we need to work around this
746                         const Size aMetaFilePrefSize(rMetafile.GetPrefSize());
747                         const Size aMetaFileRealSize(
748                             const_cast< GDIMetaFile& >(rMetafile).GetBoundRect(
749                                 *Application::GetDefaultDevice()).GetSize());
750 
751                         if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth()
752                             || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight())
753                         {
754                             // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon
755                             basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon());
756                             aMaskPolygon.transform(rTransform);
757 
758                             aRetval[0] = new MaskPrimitive2D(
759                                 basegfx::B2DPolyPolygon(aMaskPolygon),
760                                 aRetval);
761                         }
762 #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
763                     }
764 #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
765 
766 					break;
767 				}
768 
769 				default:
770 				{
771 					// nothing to create
772 					break;
773 				}
774 			}
775 
776 			return aRetval;
777 		}
778 	} // end of namespace primitive2d
779 } // end of namespace drawinglayer
780 
781 //////////////////////////////////////////////////////////////////////////////
782 // eof
783