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