xref: /AOO41X/main/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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