xref: /AOO41X/main/drawinglayer/source/primitive2d/graphicprimitive2d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
32*cdf0e10cSrcweir #include <drawinglayer/animation/animationtiming.hxx>
33*cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
34*cdf0e10cSrcweir #include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
35*cdf0e10cSrcweir #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
36*cdf0e10cSrcweir #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
37*cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
38*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
39*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
40*cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
41*cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
44*cdf0e10cSrcweir // helper class for animated graphics
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #include <vcl/animate.hxx>
47*cdf0e10cSrcweir #include <vcl/graph.hxx>
48*cdf0e10cSrcweir #include <vcl/virdev.hxx>
49*cdf0e10cSrcweir #include <vcl/svapp.hxx>
50*cdf0e10cSrcweir #include <vcl/metaact.hxx>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
53*cdf0e10cSrcweir // includes for testing MetafilePrimitive2D::create2DDecomposition
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir // this switch defines if the test code is included or not
56*cdf0e10cSrcweir #undef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
59*cdf0e10cSrcweir #include <vcl/gradient.hxx>
60*cdf0e10cSrcweir #include <vcl/pngread.hxx>
61*cdf0e10cSrcweir #include <vcl/lineinfo.hxx>
62*cdf0e10cSrcweir #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir namespace
67*cdf0e10cSrcweir {
68*cdf0e10cSrcweir 	struct animationStep
69*cdf0e10cSrcweir 	{
70*cdf0e10cSrcweir 		BitmapEx								maBitmapEx;
71*cdf0e10cSrcweir 		sal_uInt32								mnTime;
72*cdf0e10cSrcweir 	};
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir 	class animatedBitmapExPreparator
75*cdf0e10cSrcweir 	{
76*cdf0e10cSrcweir 		::Animation								maAnimation;
77*cdf0e10cSrcweir 		::std::vector< animationStep >			maSteps;
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir 		sal_uInt32 generateStepTime(sal_uInt32 nIndex) const;
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 	public:
82*cdf0e10cSrcweir 		animatedBitmapExPreparator(const Graphic& rGraphic);
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir 		sal_uInt32 count() const { return maSteps.size(); }
85*cdf0e10cSrcweir 		sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); }
86*cdf0e10cSrcweir 		sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; }
87*cdf0e10cSrcweir 		const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; }
88*cdf0e10cSrcweir 	};
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir 	sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const
91*cdf0e10cSrcweir 	{
92*cdf0e10cSrcweir 		const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex));
93*cdf0e10cSrcweir 		sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10);
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir 		// #115934#
96*cdf0e10cSrcweir 		// Take care of special value for MultiPage TIFFs. ATM these shall just
97*cdf0e10cSrcweir 		// show their first page. Later we will offer some switching when object
98*cdf0e10cSrcweir 		// is selected.
99*cdf0e10cSrcweir 		if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait)
100*cdf0e10cSrcweir 		{
101*cdf0e10cSrcweir 			// ATM the huge value would block the timer, so
102*cdf0e10cSrcweir 			// use a long time to show first page (whole day)
103*cdf0e10cSrcweir 			nWaitTime = 100 * 60 * 60 * 24;
104*cdf0e10cSrcweir 		}
105*cdf0e10cSrcweir 
106*cdf0e10cSrcweir 		// Bad trap: There are animated gifs with no set WaitTime (!).
107*cdf0e10cSrcweir 		// In that case use a default value.
108*cdf0e10cSrcweir 		if(0L == nWaitTime)
109*cdf0e10cSrcweir 		{
110*cdf0e10cSrcweir 			nWaitTime = 100L;
111*cdf0e10cSrcweir 		}
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir 		return nWaitTime;
114*cdf0e10cSrcweir 	}
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir 	animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic)
117*cdf0e10cSrcweir 	:	maAnimation(rGraphic.GetAnimation())
118*cdf0e10cSrcweir 	{
119*cdf0e10cSrcweir 		OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)");
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir 		// #128539# secure access to Animation, looks like there exist animated GIFs out there
122*cdf0e10cSrcweir 		// with a step count of zero
123*cdf0e10cSrcweir 		if(maAnimation.Count())
124*cdf0e10cSrcweir 		{
125*cdf0e10cSrcweir 			VirtualDevice aVirtualDevice(*Application::GetDefaultDevice());
126*cdf0e10cSrcweir 			VirtualDevice aVirtualDeviceMask(*Application::GetDefaultDevice(), 1L);
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir 			// Prepare VirtualDevices and their states
129*cdf0e10cSrcweir 			aVirtualDevice.EnableMapMode(sal_False);
130*cdf0e10cSrcweir 			aVirtualDeviceMask.EnableMapMode(sal_False);
131*cdf0e10cSrcweir 			aVirtualDevice.SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
132*cdf0e10cSrcweir 			aVirtualDeviceMask.SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
133*cdf0e10cSrcweir 			aVirtualDevice.Erase();
134*cdf0e10cSrcweir 			aVirtualDeviceMask.Erase();
135*cdf0e10cSrcweir 
136*cdf0e10cSrcweir 			for(sal_uInt16 a(0L); a < maAnimation.Count(); a++)
137*cdf0e10cSrcweir 			{
138*cdf0e10cSrcweir 				animationStep aNextStep;
139*cdf0e10cSrcweir 				aNextStep.mnTime = generateStepTime(a);
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir 				// prepare step
142*cdf0e10cSrcweir 				const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a));
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir 				switch(rAnimBitmap.eDisposal)
145*cdf0e10cSrcweir 				{
146*cdf0e10cSrcweir 					case DISPOSE_NOT:
147*cdf0e10cSrcweir 					{
148*cdf0e10cSrcweir 						aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
149*cdf0e10cSrcweir 						Bitmap aMask = rAnimBitmap.aBmpEx.GetMask();
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir 						if(aMask.IsEmpty())
152*cdf0e10cSrcweir 						{
153*cdf0e10cSrcweir 							const Point aEmpty;
154*cdf0e10cSrcweir 							const Rectangle aRect(aEmpty, aVirtualDeviceMask.GetOutputSizePixel());
155*cdf0e10cSrcweir 							const Wallpaper aWallpaper(COL_BLACK);
156*cdf0e10cSrcweir 							aVirtualDeviceMask.DrawWallpaper(aRect, aWallpaper);
157*cdf0e10cSrcweir 						}
158*cdf0e10cSrcweir 						else
159*cdf0e10cSrcweir 						{
160*cdf0e10cSrcweir 							BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask);
161*cdf0e10cSrcweir 							aVirtualDeviceMask.DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask);
162*cdf0e10cSrcweir 						}
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir 						break;
165*cdf0e10cSrcweir 					}
166*cdf0e10cSrcweir 					case DISPOSE_BACK:
167*cdf0e10cSrcweir 					{
168*cdf0e10cSrcweir 						// #i70772# react on no mask, for primitives, too.
169*cdf0e10cSrcweir 						const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask());
170*cdf0e10cSrcweir 						const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap());
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir 						aVirtualDeviceMask.Erase();
173*cdf0e10cSrcweir 						aVirtualDevice.DrawBitmap(rAnimBitmap.aPosPix, aContent);
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir 						if(aMask.IsEmpty())
176*cdf0e10cSrcweir 						{
177*cdf0e10cSrcweir 							const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel());
178*cdf0e10cSrcweir 							aVirtualDeviceMask.SetFillColor(COL_BLACK);
179*cdf0e10cSrcweir 							aVirtualDeviceMask.SetLineColor();
180*cdf0e10cSrcweir 							aVirtualDeviceMask.DrawRect(aRect);
181*cdf0e10cSrcweir 						}
182*cdf0e10cSrcweir 						else
183*cdf0e10cSrcweir 						{
184*cdf0e10cSrcweir 							aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, aMask);
185*cdf0e10cSrcweir 						}
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir 						break;
188*cdf0e10cSrcweir 					}
189*cdf0e10cSrcweir 					case DISPOSE_FULL:
190*cdf0e10cSrcweir 					{
191*cdf0e10cSrcweir 						aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
192*cdf0e10cSrcweir 						break;
193*cdf0e10cSrcweir 					}
194*cdf0e10cSrcweir 					case DISPOSE_PREVIOUS :
195*cdf0e10cSrcweir 					{
196*cdf0e10cSrcweir 						aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
197*cdf0e10cSrcweir 						aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask());
198*cdf0e10cSrcweir 						break;
199*cdf0e10cSrcweir 					}
200*cdf0e10cSrcweir 				}
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir 				// create BitmapEx
203*cdf0e10cSrcweir 				Bitmap aMainBitmap = aVirtualDevice.GetBitmap(Point(), aVirtualDevice.GetOutputSizePixel());
204*cdf0e10cSrcweir 				Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap(Point(), aVirtualDeviceMask.GetOutputSizePixel());
205*cdf0e10cSrcweir 				aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap);
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir 				// add to vector
208*cdf0e10cSrcweir 				maSteps.push_back(aNextStep);
209*cdf0e10cSrcweir 			}
210*cdf0e10cSrcweir 		}
211*cdf0e10cSrcweir 	}
212*cdf0e10cSrcweir } // end of anonymous namespace
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir namespace drawinglayer
217*cdf0e10cSrcweir {
218*cdf0e10cSrcweir 	namespace primitive2d
219*cdf0e10cSrcweir 	{
220*cdf0e10cSrcweir 		Primitive2DSequence GraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D&
221*cdf0e10cSrcweir #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
222*cdf0e10cSrcweir             rViewInformation
223*cdf0e10cSrcweir #else
224*cdf0e10cSrcweir             /*rViewInformation*/
225*cdf0e10cSrcweir #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
226*cdf0e10cSrcweir             ) const
227*cdf0e10cSrcweir 		{
228*cdf0e10cSrcweir 			Primitive2DSequence aRetval;
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir 			if(255L != getGraphicAttr().GetTransparency())
231*cdf0e10cSrcweir 			{
232*cdf0e10cSrcweir 				Primitive2DReference xPrimitive;
233*cdf0e10cSrcweir 
234*cdf0e10cSrcweir                 // do not apply mirroring from GraphicAttr to the Metafile by calling
235*cdf0e10cSrcweir                 // GetTransformedGraphic, this will try to mirror the Metafile using Scale()
236*cdf0e10cSrcweir                 // at the Metafile. This again calls Scale at the single MetaFile actions,
237*cdf0e10cSrcweir                 // but this implementation never worked. I reworked that implementations,
238*cdf0e10cSrcweir                 // but for security reasons i will try not to use it.
239*cdf0e10cSrcweir                 basegfx::B2DHomMatrix aTransform(getTransform());
240*cdf0e10cSrcweir 
241*cdf0e10cSrcweir                 if(getGraphicAttr().IsMirrored())
242*cdf0e10cSrcweir                 {
243*cdf0e10cSrcweir                     // content needs mirroring
244*cdf0e10cSrcweir                     const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_HORZ);
245*cdf0e10cSrcweir                     const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_VERT);
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir                     // mirror by applying negative scale to the unit primitive and
248*cdf0e10cSrcweir                     // applying the object transformation on it.
249*cdf0e10cSrcweir                     aTransform = basegfx::tools::createScaleB2DHomMatrix(
250*cdf0e10cSrcweir                         bHMirr ? -1.0 : 1.0,
251*cdf0e10cSrcweir                         bVMirr ? -1.0 : 1.0);
252*cdf0e10cSrcweir                     aTransform.translate(
253*cdf0e10cSrcweir                         bHMirr ? 1.0 : 0.0,
254*cdf0e10cSrcweir                         bVMirr ? 1.0 : 0.0);
255*cdf0e10cSrcweir                     aTransform = getTransform() * aTransform;
256*cdf0e10cSrcweir                 }
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir 		        // Get transformed graphic. Suppress rotation and cropping, only filtering is needed
259*cdf0e10cSrcweir 		        // here (and may be replaced later on). Cropping is handled below as mask primitive (if set).
260*cdf0e10cSrcweir                 // Also need to suppress mirroring, it is part of the transformation now (see above).
261*cdf0e10cSrcweir 		        GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
262*cdf0e10cSrcweir 		        aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
263*cdf0e10cSrcweir 		        aSuppressGraphicAttr.SetRotation(0);
264*cdf0e10cSrcweir 		        aSuppressGraphicAttr.SetMirrorFlags(0);
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir                 const GraphicObject&    rGraphicObject = getGraphicObject();
267*cdf0e10cSrcweir                 const Graphic           aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr));
268*cdf0e10cSrcweir 
269*cdf0e10cSrcweir                 switch(aTransformedGraphic.GetType())
270*cdf0e10cSrcweir 				{
271*cdf0e10cSrcweir 					case GRAPHIC_BITMAP :
272*cdf0e10cSrcweir 					{
273*cdf0e10cSrcweir                         if(aTransformedGraphic.IsAnimated())
274*cdf0e10cSrcweir 						{
275*cdf0e10cSrcweir 							// prepare animation data
276*cdf0e10cSrcweir 							animatedBitmapExPreparator aData(aTransformedGraphic);
277*cdf0e10cSrcweir 
278*cdf0e10cSrcweir 							if(aData.count())
279*cdf0e10cSrcweir 							{
280*cdf0e10cSrcweir 								// create sub-primitives for animated bitmap and the needed animation loop
281*cdf0e10cSrcweir 								animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff);
282*cdf0e10cSrcweir 								Primitive2DSequence aBitmapPrimitives(aData.count());
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir 								for(sal_uInt32 a(0L); a < aData.count(); a++)
285*cdf0e10cSrcweir 								{
286*cdf0e10cSrcweir                                     animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count());
287*cdf0e10cSrcweir 									aAnimationLoop.append(aTime);
288*cdf0e10cSrcweir 									const Primitive2DReference xRef(new BitmapPrimitive2D(aData.stepBitmapEx(a), aTransform));
289*cdf0e10cSrcweir 									aBitmapPrimitives[a] = xRef;
290*cdf0e10cSrcweir 								}
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir 								// prepare animation list
293*cdf0e10cSrcweir 								animation::AnimationEntryList aAnimationList;
294*cdf0e10cSrcweir 								aAnimationList.append(aAnimationLoop);
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 								// create and add animated switch primitive
297*cdf0e10cSrcweir 								xPrimitive = Primitive2DReference(new AnimatedSwitchPrimitive2D(aAnimationList, aBitmapPrimitives, false));
298*cdf0e10cSrcweir 							}
299*cdf0e10cSrcweir 						}
300*cdf0e10cSrcweir 						else
301*cdf0e10cSrcweir 						{
302*cdf0e10cSrcweir 							xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), aTransform));
303*cdf0e10cSrcweir 						}
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir 						break;
306*cdf0e10cSrcweir 					}
307*cdf0e10cSrcweir 
308*cdf0e10cSrcweir 					case GRAPHIC_GDIMETAFILE :
309*cdf0e10cSrcweir 					{
310*cdf0e10cSrcweir #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
311*cdf0e10cSrcweir                         static bool bDoTest(false);
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir                         if(bDoTest)
314*cdf0e10cSrcweir                         {
315*cdf0e10cSrcweir 							// All this is/was test code for testing MetafilePrimitive2D::create2DDecomposition
316*cdf0e10cSrcweir 							// extensively. It may be needed again when diverse actions need debugging, so i leave
317*cdf0e10cSrcweir 							// it in here, but take it out using USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE.
318*cdf0e10cSrcweir 							// Use it by compiling with the code, insert any DrawObject, convert to Metafile. The
319*cdf0e10cSrcweir 							// debugger will then stop here (when breakpoint set, of course). You may enter single
320*cdf0e10cSrcweir 							// parts of actions and/or change to true what You want to check.
321*cdf0e10cSrcweir                             GDIMetaFile aMtf;
322*cdf0e10cSrcweir 			                VirtualDevice aOut;
323*cdf0e10cSrcweir         		            const basegfx::B2DRange aRange(getB2DRange(rViewInformation));
324*cdf0e10cSrcweir                             const Rectangle aRectangle(
325*cdf0e10cSrcweir                                 basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()),
326*cdf0e10cSrcweir                                 basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY()));
327*cdf0e10cSrcweir                             const Point aOrigin(aRectangle.TopLeft());
328*cdf0e10cSrcweir                             const Fraction aScaleX(aRectangle.getWidth());
329*cdf0e10cSrcweir                             const Fraction aScaleY(aRectangle.getHeight());
330*cdf0e10cSrcweir                             MapMode aMapMode(MAP_100TH_MM, aOrigin, aScaleX, aScaleY);
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir                             Size aDummySize(2, 2);
333*cdf0e10cSrcweir                             aOut.SetOutputSizePixel(aDummySize);
334*cdf0e10cSrcweir 			                aOut.EnableOutput(FALSE);
335*cdf0e10cSrcweir 			                aOut.SetMapMode(aMapMode);
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir                             aMtf.Clear();
338*cdf0e10cSrcweir 			                aMtf.Record(&aOut);
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir 			                const Fraction aNeutralFraction(1, 1);
341*cdf0e10cSrcweir 			                const MapMode aRelativeMapMode(
342*cdf0e10cSrcweir                                 MAP_RELATIVE,
343*cdf0e10cSrcweir                                 Point(-aRectangle.Left(), -aRectangle.Top()),
344*cdf0e10cSrcweir                                 aNeutralFraction, aNeutralFraction);
345*cdf0e10cSrcweir 			                aOut.SetMapMode(aRelativeMapMode);
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir                             if(false)
348*cdf0e10cSrcweir                             {
349*cdf0e10cSrcweir                                 const sal_Int32 nHor(aRectangle.getWidth() / 4);
350*cdf0e10cSrcweir                                 const sal_Int32 nVer(aRectangle.getHeight() / 4);
351*cdf0e10cSrcweir                                 const Rectangle aCenteredRectangle(
352*cdf0e10cSrcweir                                     aRectangle.Left() + nHor, aRectangle.Top() + nVer,
353*cdf0e10cSrcweir                                     aRectangle.Right() - nHor, aRectangle.Bottom() - nVer);
354*cdf0e10cSrcweir                                 aOut.SetClipRegion(aCenteredRectangle);
355*cdf0e10cSrcweir                             }
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir                             if(false)
358*cdf0e10cSrcweir                             {
359*cdf0e10cSrcweir                                 const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight());
360*cdf0e10cSrcweir                                 aOut.IntersectClipRegion(aRightRectangle);
361*cdf0e10cSrcweir                             }
362*cdf0e10cSrcweir 
363*cdf0e10cSrcweir                             if(false)
364*cdf0e10cSrcweir                             {
365*cdf0e10cSrcweir                                 const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight());
366*cdf0e10cSrcweir                                 const Rectangle aBottomRectangle(aRectangle.LeftCenter(), aRectangle.BottomRight());
367*cdf0e10cSrcweir                                 Region aRegion(aRightRectangle);
368*cdf0e10cSrcweir                                 aRegion.Intersect(aBottomRectangle);
369*cdf0e10cSrcweir                                 aOut.IntersectClipRegion(aRegion);
370*cdf0e10cSrcweir                             }
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir                             if(false)
373*cdf0e10cSrcweir                             {
374*cdf0e10cSrcweir                                 const sal_Int32 nHor(aRectangle.getWidth() / 10);
375*cdf0e10cSrcweir                                 const sal_Int32 nVer(aRectangle.getHeight() / 10);
376*cdf0e10cSrcweir                                 aOut.MoveClipRegion(nHor, nVer);
377*cdf0e10cSrcweir                             }
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir                             if(false)
380*cdf0e10cSrcweir                             {
381*cdf0e10cSrcweir                                 Wallpaper aWallpaper(Color(COL_BLACK));
382*cdf0e10cSrcweir                                 aOut.DrawWallpaper(aRectangle, aWallpaper);
383*cdf0e10cSrcweir                             }
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir                             if(false)
386*cdf0e10cSrcweir                             {
387*cdf0e10cSrcweir                                 Wallpaper aWallpaper(Gradient(GRADIENT_LINEAR, Color(COL_RED), Color(COL_GREEN)));
388*cdf0e10cSrcweir                                 aOut.DrawWallpaper(aRectangle, aWallpaper);
389*cdf0e10cSrcweir                             }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir                             if(false)
392*cdf0e10cSrcweir                             {
393*cdf0e10cSrcweir             					SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
394*cdf0e10cSrcweir                                 vcl::PNGReader aPNGReader(aRead);
395*cdf0e10cSrcweir 		                        BitmapEx aBitmapEx(aPNGReader.Read());
396*cdf0e10cSrcweir                                 Wallpaper aWallpaper(aBitmapEx);
397*cdf0e10cSrcweir                                 aOut.DrawWallpaper(aRectangle, aWallpaper);
398*cdf0e10cSrcweir                             }
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir                             if(false)
401*cdf0e10cSrcweir                             {
402*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
403*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
404*cdf0e10cSrcweir 								Color aColor(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0));
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir 								for(sal_uInt32 a(0); a < 5000; a++)
407*cdf0e10cSrcweir 								{
408*cdf0e10cSrcweir 									const Point aPoint(
409*cdf0e10cSrcweir 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
410*cdf0e10cSrcweir 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir 									if(!(a % 3))
413*cdf0e10cSrcweir 									{
414*cdf0e10cSrcweir 										aColor = Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0));
415*cdf0e10cSrcweir 									}
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir 									aOut.DrawPixel(aPoint, aColor);
418*cdf0e10cSrcweir 								}
419*cdf0e10cSrcweir 							}
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir                             if(false)
422*cdf0e10cSrcweir                             {
423*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
424*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
425*cdf0e10cSrcweir 
426*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
427*cdf0e10cSrcweir 								aOut.SetFillColor();
428*cdf0e10cSrcweir 
429*cdf0e10cSrcweir 								for(sal_uInt32 a(0); a < 5000; a++)
430*cdf0e10cSrcweir 								{
431*cdf0e10cSrcweir 									const Point aPoint(
432*cdf0e10cSrcweir 										aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
433*cdf0e10cSrcweir 										aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
434*cdf0e10cSrcweir 									aOut.DrawPixel(aPoint);
435*cdf0e10cSrcweir 								}
436*cdf0e10cSrcweir 							}
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir                             if(false)
439*cdf0e10cSrcweir                             {
440*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
441*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
444*cdf0e10cSrcweir 								aOut.SetFillColor();
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir 								Point aStart(
447*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
448*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
449*cdf0e10cSrcweir 								Point aStop(
450*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
451*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
452*cdf0e10cSrcweir 
453*cdf0e10cSrcweir 								LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0));
454*cdf0e10cSrcweir 								bool bUseLineInfo(false);
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir 								for(sal_uInt32 a(0); a < 20; a++)
457*cdf0e10cSrcweir 								{
458*cdf0e10cSrcweir 									if(!(a%6))
459*cdf0e10cSrcweir 									{
460*cdf0e10cSrcweir 										bUseLineInfo = !bUseLineInfo;
461*cdf0e10cSrcweir 									}
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir 									if(!(a%4))
464*cdf0e10cSrcweir 									{
465*cdf0e10cSrcweir 										aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
466*cdf0e10cSrcweir 									}
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir 									if(a%3)
469*cdf0e10cSrcweir 									{
470*cdf0e10cSrcweir 										aStart = aStop;
471*cdf0e10cSrcweir 										aStop = Point(
472*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
473*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
474*cdf0e10cSrcweir 									}
475*cdf0e10cSrcweir 									else
476*cdf0e10cSrcweir 									{
477*cdf0e10cSrcweir 										aStart = Point(
478*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
479*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
480*cdf0e10cSrcweir 										aStop = Point(
481*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
482*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
483*cdf0e10cSrcweir 									}
484*cdf0e10cSrcweir 
485*cdf0e10cSrcweir 									if(bUseLineInfo)
486*cdf0e10cSrcweir 									{
487*cdf0e10cSrcweir 										aOut.DrawLine(aStart, aStop, aLineInfo);
488*cdf0e10cSrcweir 									}
489*cdf0e10cSrcweir 									else
490*cdf0e10cSrcweir 									{
491*cdf0e10cSrcweir 										aOut.DrawLine(aStart, aStop);
492*cdf0e10cSrcweir 									}
493*cdf0e10cSrcweir 								}
494*cdf0e10cSrcweir 							}
495*cdf0e10cSrcweir 
496*cdf0e10cSrcweir                             if(false)
497*cdf0e10cSrcweir                             {
498*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
499*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
500*cdf0e10cSrcweir 								aOut.DrawRect(aRectangle);
501*cdf0e10cSrcweir 							}
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir                             if(false)
504*cdf0e10cSrcweir                             {
505*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
506*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
507*cdf0e10cSrcweir                                 const sal_uInt32 nHor(aRectangle.getWidth() / 10);
508*cdf0e10cSrcweir                                 const sal_uInt32 nVer(aRectangle.getHeight() / 10);
509*cdf0e10cSrcweir 								aOut.DrawRect(aRectangle, nHor, nVer);
510*cdf0e10cSrcweir 							}
511*cdf0e10cSrcweir 
512*cdf0e10cSrcweir                             if(false)
513*cdf0e10cSrcweir                             {
514*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
515*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
516*cdf0e10cSrcweir 								aOut.DrawEllipse(aRectangle);
517*cdf0e10cSrcweir 							}
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir                             if(false)
520*cdf0e10cSrcweir                             {
521*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
522*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
523*cdf0e10cSrcweir 								aOut.DrawArc(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
524*cdf0e10cSrcweir 							}
525*cdf0e10cSrcweir 
526*cdf0e10cSrcweir                             if(false)
527*cdf0e10cSrcweir                             {
528*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
529*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
530*cdf0e10cSrcweir 								aOut.DrawPie(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
531*cdf0e10cSrcweir 							}
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir                             if(false)
534*cdf0e10cSrcweir                             {
535*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
536*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
537*cdf0e10cSrcweir 								aOut.DrawChord(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter());
538*cdf0e10cSrcweir 							}
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir                             if(false)
541*cdf0e10cSrcweir                             {
542*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
543*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir 								for(sal_uInt32 b(0); b < 5; b++)
546*cdf0e10cSrcweir 								{
547*cdf0e10cSrcweir 									const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0)));
548*cdf0e10cSrcweir 									const bool bClose(basegfx::fround(rand() / 32767.0));
549*cdf0e10cSrcweir 									Polygon aPolygon(nCount + (bClose ? 1 : 0));
550*cdf0e10cSrcweir 
551*cdf0e10cSrcweir 									for(sal_uInt32 a(0); a < nCount; a++)
552*cdf0e10cSrcweir 									{
553*cdf0e10cSrcweir 										const Point aPoint(
554*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
555*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
556*cdf0e10cSrcweir 										aPolygon[a] = aPoint;
557*cdf0e10cSrcweir 									}
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir 									if(bClose)
560*cdf0e10cSrcweir 									{
561*cdf0e10cSrcweir 										aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
562*cdf0e10cSrcweir 									}
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir 									aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
565*cdf0e10cSrcweir 									aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir 									if(!(b%2))
568*cdf0e10cSrcweir 									{
569*cdf0e10cSrcweir 										const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0));
570*cdf0e10cSrcweir 										aOut.DrawPolyLine(aPolygon, aLineInfo);
571*cdf0e10cSrcweir 									}
572*cdf0e10cSrcweir 									else
573*cdf0e10cSrcweir 									{
574*cdf0e10cSrcweir 										aOut.DrawPolyLine(aPolygon);
575*cdf0e10cSrcweir 									}
576*cdf0e10cSrcweir 								}
577*cdf0e10cSrcweir 							}
578*cdf0e10cSrcweir 
579*cdf0e10cSrcweir                             if(false)
580*cdf0e10cSrcweir                             {
581*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
582*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir 								for(sal_uInt32 b(0); b < 5; b++)
585*cdf0e10cSrcweir 								{
586*cdf0e10cSrcweir 									const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0)));
587*cdf0e10cSrcweir 									const bool bClose(basegfx::fround(rand() / 32767.0));
588*cdf0e10cSrcweir 									Polygon aPolygon(nCount + (bClose ? 1 : 0));
589*cdf0e10cSrcweir 
590*cdf0e10cSrcweir 									for(sal_uInt32 a(0); a < nCount; a++)
591*cdf0e10cSrcweir 									{
592*cdf0e10cSrcweir 										const Point aPoint(
593*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
594*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
595*cdf0e10cSrcweir 										aPolygon[a] = aPoint;
596*cdf0e10cSrcweir 									}
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir 									if(bClose)
599*cdf0e10cSrcweir 									{
600*cdf0e10cSrcweir 										aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
601*cdf0e10cSrcweir 									}
602*cdf0e10cSrcweir 
603*cdf0e10cSrcweir 									aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
604*cdf0e10cSrcweir 									aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
605*cdf0e10cSrcweir 									aOut.DrawPolygon(aPolygon);
606*cdf0e10cSrcweir 								}
607*cdf0e10cSrcweir 							}
608*cdf0e10cSrcweir 
609*cdf0e10cSrcweir                             if(false)
610*cdf0e10cSrcweir                             {
611*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
612*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
613*cdf0e10cSrcweir 								PolyPolygon aPolyPolygon;
614*cdf0e10cSrcweir 
615*cdf0e10cSrcweir 								for(sal_uInt32 b(0); b < 3; b++)
616*cdf0e10cSrcweir 								{
617*cdf0e10cSrcweir 									const sal_uInt32 nCount(basegfx::fround(rand() * (6 / 32767.0)));
618*cdf0e10cSrcweir 									const bool bClose(basegfx::fround(rand() / 32767.0));
619*cdf0e10cSrcweir 									Polygon aPolygon(nCount + (bClose ? 1 : 0));
620*cdf0e10cSrcweir 
621*cdf0e10cSrcweir 									for(sal_uInt32 a(0); a < nCount; a++)
622*cdf0e10cSrcweir 									{
623*cdf0e10cSrcweir 										const Point aPoint(
624*cdf0e10cSrcweir 											aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)),
625*cdf0e10cSrcweir 											aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0)));
626*cdf0e10cSrcweir 										aPolygon[a] = aPoint;
627*cdf0e10cSrcweir 									}
628*cdf0e10cSrcweir 
629*cdf0e10cSrcweir 									if(bClose)
630*cdf0e10cSrcweir 									{
631*cdf0e10cSrcweir 										aPolygon[aPolygon.GetSize() - 1] = aPolygon[0];
632*cdf0e10cSrcweir 									}
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir 									aPolyPolygon.Insert(aPolygon);
635*cdf0e10cSrcweir 								}
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir 								aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
638*cdf0e10cSrcweir 								aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)));
639*cdf0e10cSrcweir 								aOut.DrawPolyPolygon(aPolyPolygon);
640*cdf0e10cSrcweir 							}
641*cdf0e10cSrcweir 
642*cdf0e10cSrcweir                             if(false)
643*cdf0e10cSrcweir                             {
644*cdf0e10cSrcweir             					SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
645*cdf0e10cSrcweir                                 vcl::PNGReader aPNGReader(aRead);
646*cdf0e10cSrcweir 		                        BitmapEx aBitmapEx(aPNGReader.Read());
647*cdf0e10cSrcweir 								aOut.DrawBitmapEx(aRectangle.TopLeft(), aBitmapEx);
648*cdf0e10cSrcweir 							}
649*cdf0e10cSrcweir 
650*cdf0e10cSrcweir                             if(false)
651*cdf0e10cSrcweir                             {
652*cdf0e10cSrcweir             					SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
653*cdf0e10cSrcweir                                 vcl::PNGReader aPNGReader(aRead);
654*cdf0e10cSrcweir 		                        BitmapEx aBitmapEx(aPNGReader.Read());
655*cdf0e10cSrcweir 								aOut.DrawBitmapEx(aRectangle.TopLeft(), aRectangle.GetSize(), aBitmapEx);
656*cdf0e10cSrcweir 							}
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir                             if(false)
659*cdf0e10cSrcweir                             {
660*cdf0e10cSrcweir             					SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ);
661*cdf0e10cSrcweir                                 vcl::PNGReader aPNGReader(aRead);
662*cdf0e10cSrcweir 		                        BitmapEx aBitmapEx(aPNGReader.Read());
663*cdf0e10cSrcweir 								const Size aSizePixel(aBitmapEx.GetSizePixel());
664*cdf0e10cSrcweir 								aOut.DrawBitmapEx(
665*cdf0e10cSrcweir 									aRectangle.TopLeft(),
666*cdf0e10cSrcweir 									aRectangle.GetSize(),
667*cdf0e10cSrcweir 									Point(0, 0),
668*cdf0e10cSrcweir 									Size(aSizePixel.Width() /2, aSizePixel.Height() / 2),
669*cdf0e10cSrcweir 									aBitmapEx);
670*cdf0e10cSrcweir 							}
671*cdf0e10cSrcweir 
672*cdf0e10cSrcweir                             if(false)
673*cdf0e10cSrcweir                             {
674*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
675*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
676*cdf0e10cSrcweir 								const Point aPointA(
677*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
678*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.3));
679*cdf0e10cSrcweir 								const Point aPointB(
680*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
681*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.5));
682*cdf0e10cSrcweir 								const Point aPointC(
683*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
684*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.7));
685*cdf0e10cSrcweir                                 const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8);
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir                                 const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8);
688*cdf0e10cSrcweir                                 Font aFont(aFontName, Size(0, 1000));
689*cdf0e10cSrcweir                                 aFont.SetAlign(ALIGN_BASELINE);
690*cdf0e10cSrcweir                                 aFont.SetColor(COL_RED);
691*cdf0e10cSrcweir                                 //sal_Int32* pDXArray = new sal_Int32[aText.Len()];
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir                                 aFont.SetOutline(true);
694*cdf0e10cSrcweir                                 aOut.SetFont(aFont);
695*cdf0e10cSrcweir                                 aOut.DrawText(aPointA, aText, 0, aText.Len());
696*cdf0e10cSrcweir 
697*cdf0e10cSrcweir                                 aFont.SetShadow(true);
698*cdf0e10cSrcweir                                 aOut.SetFont(aFont);
699*cdf0e10cSrcweir                                 aOut.DrawText(aPointB, aText, 0, aText.Len());
700*cdf0e10cSrcweir 
701*cdf0e10cSrcweir                                 aFont.SetRelief(RELIEF_EMBOSSED);
702*cdf0e10cSrcweir                                 aOut.SetFont(aFont);
703*cdf0e10cSrcweir                                 aOut.DrawText(aPointC, aText, 0, aText.Len());
704*cdf0e10cSrcweir 
705*cdf0e10cSrcweir                                 //delete pDXArray;
706*cdf0e10cSrcweir                             }
707*cdf0e10cSrcweir 
708*cdf0e10cSrcweir                             if(false)
709*cdf0e10cSrcweir                             {
710*cdf0e10cSrcweir                                 const double fHor(aRectangle.getWidth());
711*cdf0e10cSrcweir                                 const double fVer(aRectangle.getHeight());
712*cdf0e10cSrcweir 								const Point aPointA(
713*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
714*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.3));
715*cdf0e10cSrcweir 								const Point aPointB(
716*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
717*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.5));
718*cdf0e10cSrcweir 								const Point aPointC(
719*cdf0e10cSrcweir 									aRectangle.Left() + basegfx::fround(fHor * 0.2),
720*cdf0e10cSrcweir 									aRectangle.Top() + basegfx::fround(fVer * 0.7));
721*cdf0e10cSrcweir                                 const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8);
722*cdf0e10cSrcweir 
723*cdf0e10cSrcweir                                 const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8);
724*cdf0e10cSrcweir                                 Font aFont(aFontName, Size(0, 1000));
725*cdf0e10cSrcweir                                 aFont.SetAlign(ALIGN_BASELINE);
726*cdf0e10cSrcweir                                 aFont.SetColor(COL_RED);
727*cdf0e10cSrcweir 
728*cdf0e10cSrcweir                                 aOut.SetFont(aFont);
729*cdf0e10cSrcweir 								const sal_Int32 nWidth(aOut.GetTextWidth(aText, 0, aText.Len()));
730*cdf0e10cSrcweir                                 aOut.DrawText(aPointA, aText, 0, aText.Len());
731*cdf0e10cSrcweir                                 aOut.DrawTextLine(aPointA, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
732*cdf0e10cSrcweir                                 aOut.DrawTextLine(aPointB, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
733*cdf0e10cSrcweir                                 aOut.DrawTextLine(aPointC, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE);
734*cdf0e10cSrcweir                             }
735*cdf0e10cSrcweir 
736*cdf0e10cSrcweir                             aMtf.Stop();
737*cdf0e10cSrcweir 			                aMtf.WindStart();
738*cdf0e10cSrcweir 		                    aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM));
739*cdf0e10cSrcweir 			                aMtf.SetPrefSize(Size(aRectangle.getWidth(), aRectangle.getHeight()));
740*cdf0e10cSrcweir 
741*cdf0e10cSrcweir                             xPrimitive = Primitive2DReference(
742*cdf0e10cSrcweir                                 new MetafilePrimitive2D(
743*cdf0e10cSrcweir                                     aTransform,
744*cdf0e10cSrcweir                                     aMtf));
745*cdf0e10cSrcweir                         }
746*cdf0e10cSrcweir                         else
747*cdf0e10cSrcweir                         {
748*cdf0e10cSrcweir #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
749*cdf0e10cSrcweir 	                        // create MetafilePrimitive2D
750*cdf0e10cSrcweir                             const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile();
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir                             if( aTransformedGraphic.IsRenderGraphic() )
753*cdf0e10cSrcweir                             {
754*cdf0e10cSrcweir                                 xPrimitive = Primitive2DReference(
755*cdf0e10cSrcweir                                     new RenderGraphicPrimitive2D(
756*cdf0e10cSrcweir                                         static_cast< MetaRenderGraphicAction* >(rMetafile.GetAction(0))->GetRenderGraphic(),
757*cdf0e10cSrcweir                                         aTransform));
758*cdf0e10cSrcweir                             }
759*cdf0e10cSrcweir                             else
760*cdf0e10cSrcweir                             {
761*cdf0e10cSrcweir                                 xPrimitive = Primitive2DReference(
762*cdf0e10cSrcweir                                     new MetafilePrimitive2D(
763*cdf0e10cSrcweir                                         aTransform,
764*cdf0e10cSrcweir                                         rMetafile));
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir                                 // #i100357# find out if clipping is needed for this primitive. Unfortunately,
767*cdf0e10cSrcweir                                 // there exist Metafiles who's content is bigger than the proposed PrefSize set
768*cdf0e10cSrcweir                                 // at them. This is an error, but we need to work around this
769*cdf0e10cSrcweir                                 const Size aMetaFilePrefSize(rMetafile.GetPrefSize());
770*cdf0e10cSrcweir                                 const Size aMetaFileRealSize(
771*cdf0e10cSrcweir                                     const_cast< GDIMetaFile& >(rMetafile).GetBoundRect(
772*cdf0e10cSrcweir                                         *Application::GetDefaultDevice()).GetSize());
773*cdf0e10cSrcweir 
774*cdf0e10cSrcweir                                 if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth()
775*cdf0e10cSrcweir                                     || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight())
776*cdf0e10cSrcweir                                 {
777*cdf0e10cSrcweir                                     // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon
778*cdf0e10cSrcweir                                     const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1);
779*cdf0e10cSrcweir                                     basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon());
780*cdf0e10cSrcweir                                     aMaskPolygon.transform(aTransform);
781*cdf0e10cSrcweir 
782*cdf0e10cSrcweir                                     xPrimitive = Primitive2DReference(
783*cdf0e10cSrcweir                                         new MaskPrimitive2D(
784*cdf0e10cSrcweir                                             basegfx::B2DPolyPolygon(aMaskPolygon),
785*cdf0e10cSrcweir                                             aChildContent));
786*cdf0e10cSrcweir                                 }
787*cdf0e10cSrcweir                             }
788*cdf0e10cSrcweir #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
789*cdf0e10cSrcweir                         }
790*cdf0e10cSrcweir #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE
791*cdf0e10cSrcweir 
792*cdf0e10cSrcweir 						break;
793*cdf0e10cSrcweir 					}
794*cdf0e10cSrcweir 
795*cdf0e10cSrcweir 					default:
796*cdf0e10cSrcweir 					{
797*cdf0e10cSrcweir 						// nothing to create
798*cdf0e10cSrcweir 						break;
799*cdf0e10cSrcweir 					}
800*cdf0e10cSrcweir 				}
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir 				if(xPrimitive.is())
803*cdf0e10cSrcweir 				{
804*cdf0e10cSrcweir 					// check for cropping
805*cdf0e10cSrcweir 					if(getGraphicAttr().IsCropped())
806*cdf0e10cSrcweir 					{
807*cdf0e10cSrcweir 						// decompose to get current pos and size
808*cdf0e10cSrcweir 						basegfx::B2DVector aScale, aTranslate;
809*cdf0e10cSrcweir 						double fRotate, fShearX;
810*cdf0e10cSrcweir 						getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
811*cdf0e10cSrcweir 
812*cdf0e10cSrcweir 						// create ranges. The current object range is just scale and translate
813*cdf0e10cSrcweir 						const basegfx::B2DRange aCurrent(
814*cdf0e10cSrcweir 							aTranslate.getX(), aTranslate.getY(),
815*cdf0e10cSrcweir 							aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
816*cdf0e10cSrcweir 
817*cdf0e10cSrcweir 						// calculate scalings between real image size and logic object size. This
818*cdf0e10cSrcweir 						// is necessary since the crop values are relative to original bitmap size
819*cdf0e10cSrcweir 						double fFactorX(1.0);
820*cdf0e10cSrcweir 						double fFactorY(1.0);
821*cdf0e10cSrcweir 
822*cdf0e10cSrcweir 						{
823*cdf0e10cSrcweir 							const MapMode aMapMode100thmm(MAP_100TH_MM);
824*cdf0e10cSrcweir 							Size aBitmapSize(rGraphicObject.GetPrefSize());
825*cdf0e10cSrcweir 
826*cdf0e10cSrcweir 							// #i95968# better support PrefMapMode; special for MAP_PIXEL was missing
827*cdf0e10cSrcweir 							if(MAP_PIXEL == rGraphicObject.GetPrefMapMode().GetMapUnit())
828*cdf0e10cSrcweir 							{
829*cdf0e10cSrcweir 								aBitmapSize = Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, aMapMode100thmm);
830*cdf0e10cSrcweir 							}
831*cdf0e10cSrcweir 							else
832*cdf0e10cSrcweir 							{
833*cdf0e10cSrcweir 								aBitmapSize = Application::GetDefaultDevice()->LogicToLogic(aBitmapSize, rGraphicObject.GetPrefMapMode(), aMapMode100thmm);
834*cdf0e10cSrcweir 							}
835*cdf0e10cSrcweir 
836*cdf0e10cSrcweir 							const double fDivX(aBitmapSize.Width() - getGraphicAttr().GetLeftCrop() - getGraphicAttr().GetRightCrop());
837*cdf0e10cSrcweir 							const double fDivY(aBitmapSize.Height() - getGraphicAttr().GetTopCrop() - getGraphicAttr().GetBottomCrop());
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir 							if(!basegfx::fTools::equalZero(fDivX))
840*cdf0e10cSrcweir 							{
841*cdf0e10cSrcweir 								fFactorX = aScale.getX() / fDivX;
842*cdf0e10cSrcweir 							}
843*cdf0e10cSrcweir 
844*cdf0e10cSrcweir 							if(!basegfx::fTools::equalZero(fDivY))
845*cdf0e10cSrcweir 							{
846*cdf0e10cSrcweir 								fFactorY = aScale.getY() / fDivY;
847*cdf0e10cSrcweir 							}
848*cdf0e10cSrcweir 						}
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir 						// Create cropped range, describes the bounds of the original graphic
851*cdf0e10cSrcweir 						basegfx::B2DRange aCropped;
852*cdf0e10cSrcweir 						aCropped.expand(aCurrent.getMinimum() - basegfx::B2DPoint(getGraphicAttr().GetLeftCrop() * fFactorX, getGraphicAttr().GetTopCrop() * fFactorY));
853*cdf0e10cSrcweir 						aCropped.expand(aCurrent.getMaximum() + basegfx::B2DPoint(getGraphicAttr().GetRightCrop() * fFactorX, getGraphicAttr().GetBottomCrop() * fFactorY));
854*cdf0e10cSrcweir 
855*cdf0e10cSrcweir 						if(aCropped.isEmpty())
856*cdf0e10cSrcweir 						{
857*cdf0e10cSrcweir 							// nothing to add since cropped bitmap is completely empty
858*cdf0e10cSrcweir 							// xPrimitive will not be used
859*cdf0e10cSrcweir 						}
860*cdf0e10cSrcweir 						else
861*cdf0e10cSrcweir 						{
862*cdf0e10cSrcweir 							// build new object transformation for transform primitive which contains xPrimitive
863*cdf0e10cSrcweir 							basegfx::B2DHomMatrix aNewObjectTransform(getTransform());
864*cdf0e10cSrcweir 							aNewObjectTransform.invert();
865*cdf0e10cSrcweir 							aNewObjectTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
866*cdf0e10cSrcweir 								aCropped.getWidth(), aCropped.getHeight(),
867*cdf0e10cSrcweir 								aCropped.getMinX() - aCurrent.getMinX(), aCropped.getMinY() - aCurrent.getMinY())
868*cdf0e10cSrcweir 								* aNewObjectTransform;
869*cdf0e10cSrcweir 
870*cdf0e10cSrcweir 							// add shear, rotate and translate using combined matrix to speedup
871*cdf0e10cSrcweir 							const basegfx::B2DHomMatrix aCombinedMatrix(basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
872*cdf0e10cSrcweir 								fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
873*cdf0e10cSrcweir 							aNewObjectTransform = aCombinedMatrix * aNewObjectTransform;
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir 							// prepare TransformPrimitive2D with xPrimitive
876*cdf0e10cSrcweir 							const Primitive2DReference xTransformPrimitive(new TransformPrimitive2D(aNewObjectTransform, Primitive2DSequence(&xPrimitive, 1L)));
877*cdf0e10cSrcweir 
878*cdf0e10cSrcweir 							if(aCurrent.isInside(aCropped))
879*cdf0e10cSrcweir 							{
880*cdf0e10cSrcweir 								// cropped just got smaller, no need to really use a mask. Add to destination directly
881*cdf0e10cSrcweir 								appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xTransformPrimitive);
882*cdf0e10cSrcweir 							}
883*cdf0e10cSrcweir 							else
884*cdf0e10cSrcweir 							{
885*cdf0e10cSrcweir 								// cropped got bigger, mask it with original object's bounds
886*cdf0e10cSrcweir 								basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
887*cdf0e10cSrcweir 								aMaskPolyPolygon.transform(getTransform());
888*cdf0e10cSrcweir 
889*cdf0e10cSrcweir 								// create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
890*cdf0e10cSrcweir 								const Primitive2DReference xRefB(new MaskPrimitive2D(aMaskPolyPolygon, Primitive2DSequence(&xTransformPrimitive, 1L)));
891*cdf0e10cSrcweir 								appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRefB);
892*cdf0e10cSrcweir 							}
893*cdf0e10cSrcweir 						}
894*cdf0e10cSrcweir 					}
895*cdf0e10cSrcweir 					else
896*cdf0e10cSrcweir 					{
897*cdf0e10cSrcweir 						// add to decomposition
898*cdf0e10cSrcweir 						appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xPrimitive);
899*cdf0e10cSrcweir 					}
900*cdf0e10cSrcweir 				}
901*cdf0e10cSrcweir 			}
902*cdf0e10cSrcweir 
903*cdf0e10cSrcweir 			return aRetval;
904*cdf0e10cSrcweir 		}
905*cdf0e10cSrcweir 
906*cdf0e10cSrcweir 		GraphicPrimitive2D::GraphicPrimitive2D(
907*cdf0e10cSrcweir 			const basegfx::B2DHomMatrix& rTransform,
908*cdf0e10cSrcweir 			const GraphicObject& rGraphicObject,
909*cdf0e10cSrcweir 			const GraphicAttr& rGraphicAttr)
910*cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
911*cdf0e10cSrcweir 			maTransform(rTransform),
912*cdf0e10cSrcweir 			maGraphicObject(rGraphicObject),
913*cdf0e10cSrcweir 			maGraphicAttr(rGraphicAttr)
914*cdf0e10cSrcweir 		{
915*cdf0e10cSrcweir 		}
916*cdf0e10cSrcweir 
917*cdf0e10cSrcweir 		GraphicPrimitive2D::GraphicPrimitive2D(
918*cdf0e10cSrcweir 			const basegfx::B2DHomMatrix& rTransform,
919*cdf0e10cSrcweir 			const GraphicObject& rGraphicObject)
920*cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
921*cdf0e10cSrcweir 			maTransform(rTransform),
922*cdf0e10cSrcweir 			maGraphicObject(rGraphicObject),
923*cdf0e10cSrcweir 			maGraphicAttr()
924*cdf0e10cSrcweir 		{
925*cdf0e10cSrcweir 		}
926*cdf0e10cSrcweir 
927*cdf0e10cSrcweir 		bool GraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
928*cdf0e10cSrcweir 		{
929*cdf0e10cSrcweir 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
930*cdf0e10cSrcweir 			{
931*cdf0e10cSrcweir 				const GraphicPrimitive2D& rCompare = (GraphicPrimitive2D&)rPrimitive;
932*cdf0e10cSrcweir 
933*cdf0e10cSrcweir 				return (getTransform() == rCompare.getTransform()
934*cdf0e10cSrcweir 					&& getGraphicObject() == rCompare.getGraphicObject()
935*cdf0e10cSrcweir 					&& getGraphicAttr() == rCompare.getGraphicAttr());
936*cdf0e10cSrcweir 			}
937*cdf0e10cSrcweir 
938*cdf0e10cSrcweir 			return false;
939*cdf0e10cSrcweir 		}
940*cdf0e10cSrcweir 
941*cdf0e10cSrcweir 		basegfx::B2DRange GraphicPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
942*cdf0e10cSrcweir 		{
943*cdf0e10cSrcweir 			basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
944*cdf0e10cSrcweir 			aRetval.transform(getTransform());
945*cdf0e10cSrcweir 			return aRetval;
946*cdf0e10cSrcweir 		}
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir 		// provide unique ID
949*cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(GraphicPrimitive2D, PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D)
950*cdf0e10cSrcweir 
951*cdf0e10cSrcweir 	} // end of namespace primitive2d
952*cdf0e10cSrcweir } // end of namespace drawinglayer
953*cdf0e10cSrcweir 
954*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
955*cdf0e10cSrcweir // eof
956