1cdf0e10cSrcweir /*************************************************************************
2cdf0e10cSrcweir  *
3cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4cdf0e10cSrcweir  *
5cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6cdf0e10cSrcweir  *
7cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8cdf0e10cSrcweir  *
9cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10cdf0e10cSrcweir  *
11cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14cdf0e10cSrcweir  *
15cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20cdf0e10cSrcweir  *
21cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25cdf0e10cSrcweir  *
26cdf0e10cSrcweir  ************************************************************************/
27cdf0e10cSrcweir 
28cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <drawinglayer/processor2d/vclmetafileprocessor2d.hxx>
32cdf0e10cSrcweir #include <tools/gen.hxx>
33cdf0e10cSrcweir #include <vcl/virdev.hxx>
34cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
35cdf0e10cSrcweir #include <vcl/gradient.hxx>
36cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
37cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx>
38cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
39cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
40cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
41cdf0e10cSrcweir #include <drawinglayer/primitive2d/rendergraphicprimitive2d.hxx>
42cdf0e10cSrcweir #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
43cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
44cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx>
45cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
46cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
47cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
48cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
49cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
50cdf0e10cSrcweir #include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
51cdf0e10cSrcweir #include <tools/stream.hxx>
52cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
53cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
54cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
55cdf0e10cSrcweir #include <vcl/graphictools.hxx>
56cdf0e10cSrcweir #include <vcl/metaact.hxx>
57cdf0e10cSrcweir #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
58cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
59cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
60cdf0e10cSrcweir #include <rtl/ustring.hxx>
61cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hdl>
62cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
63cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
64cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
65cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
66cdf0e10cSrcweir #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
67cdf0e10cSrcweir #include <helperchartrenderer.hxx>
68cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
69cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx>
70cdf0e10cSrcweir 
71cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
72cdf0e10cSrcweir // for PDFExtOutDevData Graphic support
73cdf0e10cSrcweir 
74cdf0e10cSrcweir #include <vcl/graph.hxx>
75cdf0e10cSrcweir #include <vcl/svapp.hxx>
76cdf0e10cSrcweir #include <toolkit/helper/formpdfexport.hxx>
77cdf0e10cSrcweir 
78cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
79cdf0e10cSrcweir // for Control printing
80cdf0e10cSrcweir 
81cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
82cdf0e10cSrcweir 
83cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
84cdf0e10cSrcweir // for current chart PrettyPrinting support
85cdf0e10cSrcweir 
86cdf0e10cSrcweir #include <drawinglayer/primitive2d/chartprimitive2d.hxx>
87cdf0e10cSrcweir 
88cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
89cdf0e10cSrcweir // for StructureTagPrimitive support in sd's unomodel.cxx
90cdf0e10cSrcweir 
91cdf0e10cSrcweir #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
92cdf0e10cSrcweir 
93cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
94cdf0e10cSrcweir 
95cdf0e10cSrcweir using namespace com::sun::star;
96cdf0e10cSrcweir 
97cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
98cdf0e10cSrcweir // #112245# definition for maximum allowed point count due to Metafile target.
99cdf0e10cSrcweir // To be on the safe side with the old tools polygon, use slightly less then
100cdf0e10cSrcweir // the theoretical maximum (bad experiences with tools polygon)
101cdf0e10cSrcweir 
102cdf0e10cSrcweir #define MAX_POLYGON_POINT_COUNT_METAFILE    (0x0000fff0)
103cdf0e10cSrcweir 
104cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
105cdf0e10cSrcweir 
106cdf0e10cSrcweir namespace
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     // #112245# helper to split line polygon in half
109cdf0e10cSrcweir     void splitLinePolygon(
110cdf0e10cSrcweir         const basegfx::B2DPolygon& rBasePolygon,
111cdf0e10cSrcweir         basegfx::B2DPolygon& o_aLeft,
112cdf0e10cSrcweir         basegfx::B2DPolygon& o_aRight)
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         const sal_uInt32 nCount(rBasePolygon.count());
115cdf0e10cSrcweir 
116cdf0e10cSrcweir         if(nCount)
117cdf0e10cSrcweir         {
118cdf0e10cSrcweir             const sal_uInt32 nHalfCount((nCount - 1) >> 1);
119cdf0e10cSrcweir 
120cdf0e10cSrcweir             o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
121cdf0e10cSrcweir             o_aLeft.setClosed(false);
122cdf0e10cSrcweir 
123cdf0e10cSrcweir             o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
124cdf0e10cSrcweir             o_aRight.setClosed(false);
125cdf0e10cSrcweir 
126cdf0e10cSrcweir             if(rBasePolygon.isClosed())
127cdf0e10cSrcweir             {
128cdf0e10cSrcweir                 o_aRight.append(rBasePolygon.getB2DPoint(0));
129cdf0e10cSrcweir 
130cdf0e10cSrcweir                 if(rBasePolygon.areControlPointsUsed())
131cdf0e10cSrcweir                 {
132cdf0e10cSrcweir                     o_aRight.setControlPoints(
133cdf0e10cSrcweir                         o_aRight.count() - 1,
134cdf0e10cSrcweir                         rBasePolygon.getPrevControlPoint(0),
135cdf0e10cSrcweir                         rBasePolygon.getNextControlPoint(0));
136cdf0e10cSrcweir                 }
137cdf0e10cSrcweir             }
138cdf0e10cSrcweir         }
139cdf0e10cSrcweir         else
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             o_aLeft.clear();
142cdf0e10cSrcweir             o_aRight.clear();
143cdf0e10cSrcweir         }
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     // #112245# helper to evtl. split filled polygons to maximum metafile point count
147cdf0e10cSrcweir     bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
148cdf0e10cSrcweir     {
149cdf0e10cSrcweir         bool bRetval(false);
150cdf0e10cSrcweir         const sal_uInt32 nPolyCount(rPolyPolygon.count());
151cdf0e10cSrcweir 
152cdf0e10cSrcweir         if(nPolyCount)
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             basegfx::B2DPolyPolygon aSplitted;
155cdf0e10cSrcweir 
156cdf0e10cSrcweir             for(sal_uInt32 a(0); a < nPolyCount; a++)
157cdf0e10cSrcweir             {
158cdf0e10cSrcweir                 const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
159cdf0e10cSrcweir                 const sal_uInt32 nPointCount(aCandidate.count());
160cdf0e10cSrcweir                 bool bNeedToSplit(false);
161cdf0e10cSrcweir 
162cdf0e10cSrcweir                 if(aCandidate.areControlPointsUsed())
163cdf0e10cSrcweir                 {
164cdf0e10cSrcweir                     // compare with the maximum for bezier curved polygons
165cdf0e10cSrcweir             		bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L);
166cdf0e10cSrcweir                 }
167cdf0e10cSrcweir                 else
168cdf0e10cSrcweir                 {
169cdf0e10cSrcweir                     // compare with the maximum for simple point polygons
170cdf0e10cSrcweir                     bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
171cdf0e10cSrcweir                 }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir                 if(bNeedToSplit)
174cdf0e10cSrcweir                 {
175cdf0e10cSrcweir                     // need to split the partial polygon
176cdf0e10cSrcweir                     const basegfx::B2DRange aRange(aCandidate.getB2DRange());
177cdf0e10cSrcweir             		const basegfx::B2DPoint aCenter(aRange.getCenter());
178cdf0e10cSrcweir 
179cdf0e10cSrcweir                     if(aRange.getWidth() > aRange.getHeight())
180cdf0e10cSrcweir                     {
181cdf0e10cSrcweir                         // clip in left and right
182cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aLeft(
183cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
184cdf0e10cSrcweir                                 aCandidate,
185cdf0e10cSrcweir                                 false,
186cdf0e10cSrcweir                                 true,
187cdf0e10cSrcweir                                 aCenter.getX(),
188cdf0e10cSrcweir                                 false));
189cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aRight(
190cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
191cdf0e10cSrcweir                                 aCandidate,
192cdf0e10cSrcweir                                 false,
193cdf0e10cSrcweir                                 false,
194cdf0e10cSrcweir                                 aCenter.getX(),
195cdf0e10cSrcweir                                 false));
196cdf0e10cSrcweir 
197cdf0e10cSrcweir                         aSplitted.append(aLeft);
198cdf0e10cSrcweir                         aSplitted.append(aRight);
199cdf0e10cSrcweir                     }
200cdf0e10cSrcweir                     else
201cdf0e10cSrcweir                     {
202cdf0e10cSrcweir                         // clip in top and bottom
203cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aTop(
204cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
205cdf0e10cSrcweir                                 aCandidate,
206cdf0e10cSrcweir                                 true,
207cdf0e10cSrcweir                                 true,
208cdf0e10cSrcweir                                 aCenter.getY(),
209cdf0e10cSrcweir                                 false));
210cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aBottom(
211cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
212cdf0e10cSrcweir                                 aCandidate,
213cdf0e10cSrcweir                                 true,
214cdf0e10cSrcweir                                 false,
215cdf0e10cSrcweir                                 aCenter.getY(),
216cdf0e10cSrcweir                                 false));
217cdf0e10cSrcweir 
218cdf0e10cSrcweir                         aSplitted.append(aTop);
219cdf0e10cSrcweir                         aSplitted.append(aBottom);
220cdf0e10cSrcweir                     }
221cdf0e10cSrcweir                 }
222cdf0e10cSrcweir                 else
223cdf0e10cSrcweir                 {
224cdf0e10cSrcweir                     aSplitted.append(aCandidate);
225cdf0e10cSrcweir                 }
226cdf0e10cSrcweir             }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir             if(aSplitted.count() != nPolyCount)
229cdf0e10cSrcweir             {
230cdf0e10cSrcweir                 rPolyPolygon = aSplitted;
231cdf0e10cSrcweir             }
232cdf0e10cSrcweir         }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir         return bRetval;
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir } // end of anonymous namespace
237cdf0e10cSrcweir 
238cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
239cdf0e10cSrcweir 
240cdf0e10cSrcweir namespace drawinglayer
241cdf0e10cSrcweir {
242cdf0e10cSrcweir 	namespace processor2d
243cdf0e10cSrcweir 	{
244cdf0e10cSrcweir         Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
245cdf0e10cSrcweir 			const primitive2d::Primitive2DSequence& rContent,
246cdf0e10cSrcweir 			GDIMetaFile& o_rContentMetafile)
247cdf0e10cSrcweir         {
248cdf0e10cSrcweir             // Prepare VDev, MetaFile and connections
249cdf0e10cSrcweir 			OutputDevice* pLastOutputDevice = mpOutputDevice;
250cdf0e10cSrcweir             GDIMetaFile* pLastMetafile = mpMetaFile;
251cdf0e10cSrcweir 			basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
252cdf0e10cSrcweir 
253cdf0e10cSrcweir 			// transform primitive range with current transformation (e.g shadow offset)
254cdf0e10cSrcweir 			aPrimitiveRange.transform(maCurrentTransformation);
255cdf0e10cSrcweir 
256cdf0e10cSrcweir 			const Rectangle aPrimitiveRectangle(
257cdf0e10cSrcweir 				basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
258cdf0e10cSrcweir 				basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
259cdf0e10cSrcweir 			VirtualDevice aContentVDev;
260cdf0e10cSrcweir 			MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 			mpOutputDevice = &aContentVDev;
263cdf0e10cSrcweir             mpMetaFile = &o_rContentMetafile;
264cdf0e10cSrcweir 			aContentVDev.EnableOutput(false);
265cdf0e10cSrcweir 			aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode());
266cdf0e10cSrcweir 			o_rContentMetafile.Record(&aContentVDev);
267cdf0e10cSrcweir 			aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor());
268cdf0e10cSrcweir 			aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor());
269cdf0e10cSrcweir 			aContentVDev.SetFont(pLastOutputDevice->GetFont());
270cdf0e10cSrcweir 			aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode());
271cdf0e10cSrcweir 			aContentVDev.SetSettings(pLastOutputDevice->GetSettings());
272cdf0e10cSrcweir 			aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint());
273cdf0e10cSrcweir 
274cdf0e10cSrcweir             // dump to MetaFile
275cdf0e10cSrcweir 			process(rContent);
276cdf0e10cSrcweir 
277cdf0e10cSrcweir             // cleanups
278cdf0e10cSrcweir 			o_rContentMetafile.Stop();
279cdf0e10cSrcweir 			o_rContentMetafile.WindStart();
280cdf0e10cSrcweir 			aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
281cdf0e10cSrcweir 			o_rContentMetafile.SetPrefMapMode(aNewMapMode);
282cdf0e10cSrcweir 			o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
283cdf0e10cSrcweir 			mpOutputDevice = pLastOutputDevice;
284cdf0e10cSrcweir             mpMetaFile = pLastMetafile;
285cdf0e10cSrcweir 
286cdf0e10cSrcweir             return aPrimitiveRectangle;
287cdf0e10cSrcweir         }
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 		void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
290cdf0e10cSrcweir 			Gradient& o_rVCLGradient,
291cdf0e10cSrcweir 			const attribute::FillGradientAttribute& rFiGrAtt,
292cdf0e10cSrcweir 			bool bIsTransparenceGradient)
293cdf0e10cSrcweir         {
294cdf0e10cSrcweir 			if(bIsTransparenceGradient)
295cdf0e10cSrcweir 			{
296cdf0e10cSrcweir 				// it's about transparence channel intensities (black/white), do not use color modifier
297cdf0e10cSrcweir 			    o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
298cdf0e10cSrcweir 			    o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
299cdf0e10cSrcweir 			}
300cdf0e10cSrcweir 			else
301cdf0e10cSrcweir 			{
302cdf0e10cSrcweir 				// use color modifier to influence start/end color of gradient
303cdf0e10cSrcweir 			    o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
304cdf0e10cSrcweir 			    o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
305cdf0e10cSrcweir 			}
306cdf0e10cSrcweir 
307cdf0e10cSrcweir             o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
308cdf0e10cSrcweir             o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
309cdf0e10cSrcweir 		    o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
310cdf0e10cSrcweir 		    o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
311cdf0e10cSrcweir 		    o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
312cdf0e10cSrcweir 
313cdf0e10cSrcweir             // defaults for intensity; those were computed into the start/end colors already
314cdf0e10cSrcweir 		    o_rVCLGradient.SetStartIntensity(100);
315cdf0e10cSrcweir 		    o_rVCLGradient.SetEndIntensity(100);
316cdf0e10cSrcweir 
317cdf0e10cSrcweir             switch(rFiGrAtt.getStyle())
318cdf0e10cSrcweir             {
319cdf0e10cSrcweir                 default : // attribute::GRADIENTSTYLE_LINEAR :
320cdf0e10cSrcweir                 {
321cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_LINEAR);
322cdf0e10cSrcweir                     break;
323cdf0e10cSrcweir                 }
324cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_AXIAL :
325cdf0e10cSrcweir                 {
326cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_AXIAL);
327cdf0e10cSrcweir                     break;
328cdf0e10cSrcweir                 }
329cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_RADIAL :
330cdf0e10cSrcweir                 {
331cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_RADIAL);
332cdf0e10cSrcweir                     break;
333cdf0e10cSrcweir                 }
334cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_ELLIPTICAL :
335cdf0e10cSrcweir                 {
336cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_ELLIPTICAL);
337cdf0e10cSrcweir                     break;
338cdf0e10cSrcweir                 }
339cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_SQUARE :
340cdf0e10cSrcweir                 {
341cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_SQUARE);
342cdf0e10cSrcweir                     break;
343cdf0e10cSrcweir                 }
344cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_RECT :
345cdf0e10cSrcweir                 {
346cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_RECT);
347cdf0e10cSrcweir                     break;
348cdf0e10cSrcweir                 }
349cdf0e10cSrcweir             }
350cdf0e10cSrcweir         }
351cdf0e10cSrcweir 
352cdf0e10cSrcweir 		void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
353cdf0e10cSrcweir 		{
354cdf0e10cSrcweir 			if(pSvtGraphicFill && !mnSvtGraphicFillCount)
355cdf0e10cSrcweir 			{
356cdf0e10cSrcweir 				SvMemoryStream aMemStm;
357cdf0e10cSrcweir 
358cdf0e10cSrcweir 				aMemStm << *pSvtGraphicFill;
359cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
360cdf0e10cSrcweir 				mnSvtGraphicFillCount++;
361cdf0e10cSrcweir 			}
362cdf0e10cSrcweir 		}
363cdf0e10cSrcweir 
364cdf0e10cSrcweir 		void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
365cdf0e10cSrcweir 		{
366cdf0e10cSrcweir 			if(pSvtGraphicFill && mnSvtGraphicFillCount)
367cdf0e10cSrcweir 			{
368cdf0e10cSrcweir 				mnSvtGraphicFillCount--;
369cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
370cdf0e10cSrcweir 				delete pSvtGraphicFill;
371cdf0e10cSrcweir 			}
372cdf0e10cSrcweir 		}
373cdf0e10cSrcweir 
374cdf0e10cSrcweir 		SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
375cdf0e10cSrcweir 			const basegfx::B2DPolygon& rB2DPolygon,
376cdf0e10cSrcweir 			const basegfx::BColor* pColor,
377cdf0e10cSrcweir 			const attribute::LineAttribute* pLineAttribute,
378cdf0e10cSrcweir 			const attribute::StrokeAttribute* pStrokeAttribute,
379cdf0e10cSrcweir 			const attribute::LineStartEndAttribute* pStart,
380cdf0e10cSrcweir 			const attribute::LineStartEndAttribute* pEnd)
381cdf0e10cSrcweir 		{
382cdf0e10cSrcweir 			SvtGraphicStroke* pRetval = 0;
383cdf0e10cSrcweir 
384cdf0e10cSrcweir 			if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
385cdf0e10cSrcweir 			{
386cdf0e10cSrcweir 				basegfx::BColor aStrokeColor;
387cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aStartArrow;
388cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aEndArrow;
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 				if(pColor)
391cdf0e10cSrcweir 				{
392cdf0e10cSrcweir 					aStrokeColor = *pColor;
393cdf0e10cSrcweir 				}
394cdf0e10cSrcweir 				else if(pLineAttribute)
395cdf0e10cSrcweir 				{
396cdf0e10cSrcweir 					aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
397cdf0e10cSrcweir 				}
398cdf0e10cSrcweir 
399cdf0e10cSrcweir 				// It IS needed to record the stroke color at all in the metafile,
400cdf0e10cSrcweir 				// SvtGraphicStroke has NO entry for stroke color(!)
401cdf0e10cSrcweir 				mpOutputDevice->SetLineColor(Color(aStrokeColor));
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 				if(!rB2DPolygon.isClosed())
404cdf0e10cSrcweir 				{
405cdf0e10cSrcweir 					double fPolyLength(0.0);
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 					if(pStart && pStart->isActive())
408cdf0e10cSrcweir 					{
409cdf0e10cSrcweir 						fPolyLength = basegfx::tools::getLength(rB2DPolygon);
410cdf0e10cSrcweir 
411cdf0e10cSrcweir 						aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
412cdf0e10cSrcweir 							rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
413cdf0e10cSrcweir 							fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0);
414cdf0e10cSrcweir 					}
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 					if(pEnd && pEnd->isActive())
417cdf0e10cSrcweir 					{
418cdf0e10cSrcweir 						if(basegfx::fTools::equalZero(fPolyLength))
419cdf0e10cSrcweir 						{
420cdf0e10cSrcweir 							fPolyLength = basegfx::tools::getLength(rB2DPolygon);
421cdf0e10cSrcweir 						}
422cdf0e10cSrcweir 
423cdf0e10cSrcweir 						aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
424cdf0e10cSrcweir 							rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
425cdf0e10cSrcweir 							fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0);
426cdf0e10cSrcweir 					}
427cdf0e10cSrcweir 				}
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 	            SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
430cdf0e10cSrcweir 				double fLineWidth(0.0);
431cdf0e10cSrcweir 				double fMiterLength(0.0);
432cdf0e10cSrcweir 				SvtGraphicStroke::DashArray aDashArray;
433cdf0e10cSrcweir 
434cdf0e10cSrcweir 				if(pLineAttribute)
435cdf0e10cSrcweir 				{
436cdf0e10cSrcweir 					// pre-fill fLineWidth
437cdf0e10cSrcweir 					fLineWidth = pLineAttribute->getWidth();
438cdf0e10cSrcweir 
439cdf0e10cSrcweir 					// pre-fill fMiterLength
440cdf0e10cSrcweir 					fMiterLength = fLineWidth;
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 					// get Join
443cdf0e10cSrcweir 					switch(pLineAttribute->getLineJoin())
444cdf0e10cSrcweir 					{
445cdf0e10cSrcweir 						default : // basegfx::B2DLINEJOIN_NONE :
446cdf0e10cSrcweir 						{
447cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinNone;
448cdf0e10cSrcweir 							break;
449cdf0e10cSrcweir 						}
450cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_BEVEL :
451cdf0e10cSrcweir 						{
452cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinBevel;
453cdf0e10cSrcweir 							break;
454cdf0e10cSrcweir 						}
455cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_MIDDLE :
456cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_MITER :
457cdf0e10cSrcweir 						{
458cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinMiter;
459cdf0e10cSrcweir 							// ATM 15 degrees is assumed
460cdf0e10cSrcweir 							fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0));
461cdf0e10cSrcweir 							break;
462cdf0e10cSrcweir 						}
463cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_ROUND :
464cdf0e10cSrcweir 						{
465cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinRound;
466cdf0e10cSrcweir 							break;
467cdf0e10cSrcweir 						}
468cdf0e10cSrcweir 					}
469cdf0e10cSrcweir                 }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir 				if(pStrokeAttribute)
472cdf0e10cSrcweir 				{
473cdf0e10cSrcweir 					// copy dash array
474cdf0e10cSrcweir 					aDashArray = pStrokeAttribute->getDotDashArray();
475cdf0e10cSrcweir 				}
476cdf0e10cSrcweir 
477cdf0e10cSrcweir 				// #i101734# apply current object transformation to created geometry.
478cdf0e10cSrcweir 				// This is a partial fix. When a object transformation is used which
479cdf0e10cSrcweir 				// e.g. contains a scaleX != scaleY, an unproportional scaling would
480cdf0e10cSrcweir 				// have to be applied to the evtl. existing fat line. The current
481cdf0e10cSrcweir 				// concept of PDF export and SvtGraphicStroke usage does simply not
482cdf0e10cSrcweir 				// allow handling such definitions. The only clean way would be to
483cdf0e10cSrcweir 				// add the transformation to SvtGraphicStroke and to handle it there
484cdf0e10cSrcweir 				basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 				aB2DPolygon.transform(maCurrentTransformation);
487cdf0e10cSrcweir 				aStartArrow.transform(maCurrentTransformation);
488cdf0e10cSrcweir 				aEndArrow.transform(maCurrentTransformation);
489cdf0e10cSrcweir 
490cdf0e10cSrcweir 				pRetval = new SvtGraphicStroke(
491cdf0e10cSrcweir 					Polygon(aB2DPolygon),
492cdf0e10cSrcweir 					PolyPolygon(aStartArrow),
493cdf0e10cSrcweir 					PolyPolygon(aEndArrow),
494cdf0e10cSrcweir 					mfCurrentUnifiedTransparence,
495cdf0e10cSrcweir 					fLineWidth,
496cdf0e10cSrcweir 					SvtGraphicStroke::capButt,
497cdf0e10cSrcweir 					eJoin,
498cdf0e10cSrcweir 					fMiterLength,
499cdf0e10cSrcweir 					aDashArray);
500cdf0e10cSrcweir 			}
501cdf0e10cSrcweir 
502cdf0e10cSrcweir 			return pRetval;
503cdf0e10cSrcweir 		}
504cdf0e10cSrcweir 
505cdf0e10cSrcweir 		void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
506cdf0e10cSrcweir 		{
507cdf0e10cSrcweir 			if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
508cdf0e10cSrcweir 			{
509cdf0e10cSrcweir 				SvMemoryStream aMemStm;
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 				aMemStm << *pSvtGraphicStroke;
512cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
513cdf0e10cSrcweir 				mnSvtGraphicStrokeCount++;
514cdf0e10cSrcweir 			}
515cdf0e10cSrcweir 		}
516cdf0e10cSrcweir 
517cdf0e10cSrcweir 		void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
518cdf0e10cSrcweir 		{
519cdf0e10cSrcweir 			if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
520cdf0e10cSrcweir 			{
521cdf0e10cSrcweir 				mnSvtGraphicStrokeCount--;
522cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
523cdf0e10cSrcweir 				delete pSvtGraphicStroke;
524cdf0e10cSrcweir 			}
525cdf0e10cSrcweir 		}
526cdf0e10cSrcweir 
527cdf0e10cSrcweir         // init static break iterator
528cdf0e10cSrcweir         uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
529cdf0e10cSrcweir 
530cdf0e10cSrcweir 		VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
531cdf0e10cSrcweir 		:	VclProcessor2D(rViewInformation, rOutDev),
532cdf0e10cSrcweir 			mpMetaFile(rOutDev.GetConnectMetaFile()),
533cdf0e10cSrcweir 			mnSvtGraphicFillCount(0),
534cdf0e10cSrcweir 			mnSvtGraphicStrokeCount(0),
535cdf0e10cSrcweir 			mfCurrentUnifiedTransparence(0.0),
536cdf0e10cSrcweir 			mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData()))
537cdf0e10cSrcweir 		{
538cdf0e10cSrcweir 			OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
539cdf0e10cSrcweir 			// draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
540cdf0e10cSrcweir             // but only to ObjectTransformation. Do not change MapMode of destination.
541cdf0e10cSrcweir 			maCurrentTransformation = rViewInformation.getObjectTransformation();
542cdf0e10cSrcweir 		}
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 		VclMetafileProcessor2D::~VclMetafileProcessor2D()
545cdf0e10cSrcweir 		{
546cdf0e10cSrcweir 			// MapMode was not changed, no restore necessary
547cdf0e10cSrcweir 		}
548cdf0e10cSrcweir 
549cdf0e10cSrcweir         /***********************************************************************************************
550cdf0e10cSrcweir 
551cdf0e10cSrcweir             Support of MetaCommentActions in the VclMetafileProcessor2D
552cdf0e10cSrcweir             Found MetaCommentActions and how they are supported:
553cdf0e10cSrcweir 
554cdf0e10cSrcweir             XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
555cdf0e10cSrcweir 
556cdf0e10cSrcweir 			Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
557cdf0e10cSrcweir             It is used in various exporters/importers to have direct access to the gradient before it
558cdf0e10cSrcweir             is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
559cdf0e10cSrcweir             the Metafile to SdrObject import creates it's gradient objects.
560cdf0e10cSrcweir             Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
561cdf0e10cSrcweir             map it back to the corresponding tools PolyPolygon and the Gradient and just call
562cdf0e10cSrcweir             OutputDevice::DrawGradient which creates the necessary compatible actions.
563cdf0e10cSrcweir 
564cdf0e10cSrcweir             XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
565cdf0e10cSrcweir 
566cdf0e10cSrcweir 			Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
567cdf0e10cSrcweir             inside GDIMetaFile::Rotate, nothing to take care of here.
568cdf0e10cSrcweir             The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
569cdf0e10cSrcweir             with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
570cdf0e10cSrcweir             XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
571cdf0e10cSrcweir             to the comment action. A closing end token is created in the destructor.
572cdf0e10cSrcweir 			Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
573cdf0e10cSrcweir 			SdrRectObj.
574cdf0e10cSrcweir             The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
575cdf0e10cSrcweir             of filled objects, even simple colored polygons. It is added as extra information; the
576cdf0e10cSrcweir             Metafile actions between the two tokens are interpreted as output generated from those
577cdf0e10cSrcweir             fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
578cdf0e10cSrcweir             actions.
579cdf0e10cSrcweir             Even for XFillTransparenceItem it is used, thus it may need to be supported in
580cdf0e10cSrcweir             UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
581cdf0e10cSrcweir 			Implemented for:
582cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D,
583cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
584cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
585cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
586cdf0e10cSrcweir 				and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
587cdf0e10cSrcweir 
588cdf0e10cSrcweir             XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 			Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
591cdf0e10cSrcweir 			is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
592cdf0e10cSrcweir 			contained path accordingly.
593cdf0e10cSrcweir 			The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
594cdf0e10cSrcweir 			only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
595cdf0e10cSrcweir 			would hinder to make use of PolyPolygon strokes. I will need to add support at:
596cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
597cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
598cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
599cdf0e10cSrcweir 			This can be done hierarchical, too.
600cdf0e10cSrcweir 			Okay, base implementation done based on those three primitives.
601cdf0e10cSrcweir 
602cdf0e10cSrcweir             FIELD_SEQ_BEGIN, FIELD_SEQ_END
603cdf0e10cSrcweir 
604cdf0e10cSrcweir             Used from slideshow for URLs, created from diverse SvxField implementations inside
605cdf0e10cSrcweir             createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
606cdf0e10cSrcweir             inside ImpEditEngine::Paint.
607cdf0e10cSrcweir             Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps
608cdf0e10cSrcweir             text primitives (but is not limited to that). It contains the field type if special actions for the
609cdf0e10cSrcweir 			support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
610cdf0e10cSrcweir 			needed, it may be supported there.
611cdf0e10cSrcweir             FIELD_SEQ_BEGIN;PageField
612cdf0e10cSrcweir             FIELD_SEQ_END
613cdf0e10cSrcweir             Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
614cdf0e10cSrcweir 
615cdf0e10cSrcweir             XTEXT
616cdf0e10cSrcweir 
617cdf0e10cSrcweir             XTEXT_EOC(i) end of character
618cdf0e10cSrcweir             XTEXT_EOW(i) end of word
619cdf0e10cSrcweir             XTEXT_EOS(i) end of sentence
620cdf0e10cSrcweir 
621cdf0e10cSrcweir             this three are with index and are created with the help of a i18n::XBreakIterator in
622cdf0e10cSrcweir             ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
623cdf0e10cSrcweir             data structure for holding those TEXT infos.
624cdf0e10cSrcweir             Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
625cdf0e10cSrcweir             primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
626cdf0e10cSrcweir             that this creations do not need to be done for all paints all the time. This would be
627cdf0e10cSrcweir             expensive since the BreakIterator and it's usage is expensive and for each paint also the
628cdf0e10cSrcweir             whole character stops would need to be created.
629cdf0e10cSrcweir             Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
630cdf0e10cSrcweir 
631cdf0e10cSrcweir             XTEXT_EOL() end of line
632cdf0e10cSrcweir             XTEXT_EOP() end of paragraph
633cdf0e10cSrcweir 
634cdf0e10cSrcweir             First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
635cdf0e10cSrcweir 			i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
636cdf0e10cSrcweir 			namely:
637cdf0e10cSrcweir 			- TextHierarchyLinePrimitive2D: Encapsulates single line
638cdf0e10cSrcweir 			- TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
639cdf0e10cSrcweir 			- TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
640cdf0e10cSrcweir 			Those are now supported in hierarchy. This means the MetaFile renderer will support them
641cdf0e10cSrcweir 			by using them, reculrively using their content and adding MetaFile comments as needed.
642cdf0e10cSrcweir 			This also means that when another text layouter will be used it will be necessary to
643cdf0e10cSrcweir 			create/support the same HierarchyPrimitives to support users.
644cdf0e10cSrcweir 			To transport the information using this hierarchy is best suited to all future needs;
645cdf0e10cSrcweir 			the slideshow will be able to profit from it directly when using primitives; all other
646cdf0e10cSrcweir 			renderers not interested in the text structure will just ignore the encapsulations.
647cdf0e10cSrcweir 
648cdf0e10cSrcweir             XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
649cdf0e10cSrcweir 			Supported now by the TextHierarchyBlockPrimitive2D.
650cdf0e10cSrcweir 
651cdf0e10cSrcweir             EPSReplacementGraphic:
652cdf0e10cSrcweir 			Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
653cdf0e10cSrcweir 			hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
654cdf0e10cSrcweir 			used to export the original again (if exists).
655cdf0e10cSrcweir 			Not necessary to support with MetaFuleRenderer.
656cdf0e10cSrcweir 
657cdf0e10cSrcweir             XTEXT_SCROLLRECT, XTEXT_PAINTRECT
658cdf0e10cSrcweir 			Currently used to get extra MetaFile infos using GraphicExporter which again uses
659cdf0e10cSrcweir 			SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
660cdf0e10cSrcweir 			the rectangle data is added directly by the GraphicsExporter as comment. Does not need
661cdf0e10cSrcweir 			to be adapted at once.
662cdf0e10cSrcweir 			When adapting later, the only user - the diashow - should directly use the provided
663cdf0e10cSrcweir 			Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
664cdf0e10cSrcweir 
665cdf0e10cSrcweir             PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
666cdf0e10cSrcweir 			VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
667cdf0e10cSrcweir 			a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
668cdf0e10cSrcweir 			was explicitely created for the printer already again to some default maximum
669cdf0e10cSrcweir 			bitmap sizes.
670cdf0e10cSrcweir 			Nothing to do here for the primitive renderer.
671cdf0e10cSrcweir 
672cdf0e10cSrcweir 			Support for vcl::PDFExtOutDevData:
673cdf0e10cSrcweir 			PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
674cdf0e10cSrcweir 			the OutDev. When set, some extra data is written there. Trying simple PDF export and
675cdf0e10cSrcweir 			watching if i get those infos.
676cdf0e10cSrcweir 			Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
677cdf0e10cSrcweir 			the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
678cdf0e10cSrcweir 			if i get a PDFExtOutDevData at the target output device.
679cdf0e10cSrcweir 			Indeed, i get one. Checking what all may be done when that extra-device-info is there.
680cdf0e10cSrcweir 
681cdf0e10cSrcweir 		    All in all i have to talk to SJ. I will need to emulate some of those actions, but
682cdf0e10cSrcweir 			i need to discuss which ones.
683cdf0e10cSrcweir 			In the future, all those infos would be taken from the primitive sequence anyways,
684cdf0e10cSrcweir 			thus these extensions would potentially be temporary, too.
685cdf0e10cSrcweir             Discussed with SJ, added the necessary support and tested it. Details follow.
686cdf0e10cSrcweir 
687cdf0e10cSrcweir 			- In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
688cdf0e10cSrcweir 			  Added in primitive MetaFile renderer.
689cdf0e10cSrcweir 			  Checking URL: Indeed, current version exports it, but it is missing in primitive
690cdf0e10cSrcweir 			  CWS version. Adding support.
691cdf0e10cSrcweir 			  Okay, URLs work. Checked, Done.
692cdf0e10cSrcweir 
693cdf0e10cSrcweir             - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
694cdf0e10cSrcweir 			  target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
695cdf0e10cSrcweir 			  This may be added in primitive MetaFile renderer.
696cdf0e10cSrcweir 			  Adding support...
697cdf0e10cSrcweir 			  OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
698cdf0e10cSrcweir 			  svxform. Have to talk to FS if this has to be like that. Especially since
699cdf0e10cSrcweir 			  ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
700cdf0e10cSrcweir 			  Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
701cdf0e10cSrcweir 			  that stuff to somewhere else, maybe tools or svtools ?!? We will see...
702cdf0e10cSrcweir               Moved to toolkit, so i have to link against it. I tried VCL first, but it did
703cdf0e10cSrcweir               not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name
704cdf0e10cSrcweir               may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
705cdf0e10cSrcweir               the lowest move,ment plave is toolkit.
706cdf0e10cSrcweir               Checked form control export, it works well. Done.
707cdf0e10cSrcweir 
708cdf0e10cSrcweir 		    - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
709cdf0e10cSrcweir 			  generated. I will need to check what happens here with primitives.
710cdf0e10cSrcweir 			  To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
711cdf0e10cSrcweir 			  Added support, but feature is broken in main version, so i cannot test at all.
712cdf0e10cSrcweir 			  Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
713cdf0e10cSrcweir               SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
714cdf0e10cSrcweir               as intended, the original file is exported. Works, Done.
715cdf0e10cSrcweir 
716cdf0e10cSrcweir 
717cdf0e10cSrcweir 
718cdf0e10cSrcweir 
719cdf0e10cSrcweir             To be done:
720cdf0e10cSrcweir 
721cdf0e10cSrcweir             - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
722cdf0e10cSrcweir 
723cdf0e10cSrcweir 
724cdf0e10cSrcweir 
725cdf0e10cSrcweir         ****************************************************************************************************/
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 		void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
728cdf0e10cSrcweir 		{
729cdf0e10cSrcweir             switch(rCandidate.getPrimitive2DID())
730cdf0e10cSrcweir 			{
731cdf0e10cSrcweir                 case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
732cdf0e10cSrcweir                 {
733cdf0e10cSrcweir 					// directdraw of wrong spell primitive
734cdf0e10cSrcweir                     // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
735cdf0e10cSrcweir                     break;
736cdf0e10cSrcweir                 }
737cdf0e10cSrcweir 				case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
738cdf0e10cSrcweir 				{
739cdf0e10cSrcweir                     const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
740cdf0e10cSrcweir 					bool bUsingPDFExtOutDevData(false);
741cdf0e10cSrcweir 					basegfx::B2DVector aTranslate, aScale;
742cdf0e10cSrcweir 					static bool bSuppressPDFExtOutDevDataSupport(false);
743cdf0e10cSrcweir 
744cdf0e10cSrcweir 					if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
745cdf0e10cSrcweir 					{
746cdf0e10cSrcweir 						// emulate data handling from UnoControlPDFExportContact, original see
747cdf0e10cSrcweir 						// svtools/source/graphic/grfmgr.cxx
748cdf0e10cSrcweir 						const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
749cdf0e10cSrcweir 
750cdf0e10cSrcweir 						if(rGraphic.IsLink())
751cdf0e10cSrcweir 						{
752cdf0e10cSrcweir 							const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
753cdf0e10cSrcweir 
754cdf0e10cSrcweir 							if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
755cdf0e10cSrcweir 							{
756cdf0e10cSrcweir 								const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
757cdf0e10cSrcweir 								double fRotate, fShearX;
758cdf0e10cSrcweir 								rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
759cdf0e10cSrcweir 
760cdf0e10cSrcweir 								if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
761cdf0e10cSrcweir 								{
762cdf0e10cSrcweir 									bUsingPDFExtOutDevData = true;
763cdf0e10cSrcweir 									mpPDFExtOutDevData->BeginGroup();
764cdf0e10cSrcweir 								}
765cdf0e10cSrcweir 							}
766cdf0e10cSrcweir 						}
767cdf0e10cSrcweir 					}
768cdf0e10cSrcweir 
769cdf0e10cSrcweir 					// process recursively and add MetaFile comment
770cdf0e10cSrcweir 					process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D()));
771cdf0e10cSrcweir 
772cdf0e10cSrcweir 					if(bUsingPDFExtOutDevData)
773cdf0e10cSrcweir 					{
774cdf0e10cSrcweir 						// emulate data handling from UnoControlPDFExportContact, original see
775cdf0e10cSrcweir 						// svtools/source/graphic/grfmgr.cxx
776cdf0e10cSrcweir 						const basegfx::B2DRange aCurrentRange(
777cdf0e10cSrcweir 							aTranslate.getX(), aTranslate.getY(),
778cdf0e10cSrcweir 							aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
779cdf0e10cSrcweir 						const Rectangle aCurrentRect(
780cdf0e10cSrcweir 							sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
781cdf0e10cSrcweir 							sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
782cdf0e10cSrcweir 						const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
783cdf0e10cSrcweir 						Rectangle aCropRect;
784cdf0e10cSrcweir 
785cdf0e10cSrcweir 						if(rAttr.IsCropped())
786cdf0e10cSrcweir 						{
787cdf0e10cSrcweir 							// calculate scalings between real image size and logic object size. This
788cdf0e10cSrcweir 							// is necessary since the crop values are relative to original bitmap size
789cdf0e10cSrcweir 							double fFactorX(1.0);
790cdf0e10cSrcweir 							double fFactorY(1.0);
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 							{
793cdf0e10cSrcweir 								const MapMode aMapMode100thmm(MAP_100TH_MM);
794cdf0e10cSrcweir 								const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic(
795cdf0e10cSrcweir 									rGraphicPrimitive.getGraphicObject().GetPrefSize(),
796cdf0e10cSrcweir 									rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
797cdf0e10cSrcweir 								const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
798cdf0e10cSrcweir 								const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
799cdf0e10cSrcweir 
800cdf0e10cSrcweir 								if(!basegfx::fTools::equalZero(fDivX))
801cdf0e10cSrcweir 								{
802cdf0e10cSrcweir 									fFactorX = aScale.getX() / fDivX;
803cdf0e10cSrcweir 								}
804cdf0e10cSrcweir 
805cdf0e10cSrcweir 								if(!basegfx::fTools::equalZero(fDivY))
806cdf0e10cSrcweir 								{
807cdf0e10cSrcweir 									fFactorY = aScale.getY() / fDivY;
808cdf0e10cSrcweir 								}
809cdf0e10cSrcweir 							}
810cdf0e10cSrcweir 
811cdf0e10cSrcweir 							// calculate crop range and rect
812cdf0e10cSrcweir 							basegfx::B2DRange aCropRange;
813cdf0e10cSrcweir 							aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
814cdf0e10cSrcweir 							aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
815cdf0e10cSrcweir 
816cdf0e10cSrcweir 							aCropRect = Rectangle(
817cdf0e10cSrcweir 								sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
818cdf0e10cSrcweir 								sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
819cdf0e10cSrcweir 						}
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 						mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
822cdf0e10cSrcweir 							rAttr.GetTransparency(),
823cdf0e10cSrcweir 							aCurrentRect,
824cdf0e10cSrcweir 							aCropRect);
825cdf0e10cSrcweir 					}
826cdf0e10cSrcweir 
827cdf0e10cSrcweir 					break;
828cdf0e10cSrcweir 				}
829cdf0e10cSrcweir 				case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
830cdf0e10cSrcweir 				{
831cdf0e10cSrcweir                     const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
832cdf0e10cSrcweir         			const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
833cdf0e10cSrcweir 					bool bIsPrintableControl(false);
834cdf0e10cSrcweir 
835cdf0e10cSrcweir                     // find out if control is printable
836cdf0e10cSrcweir 					if(rXControl.is())
837cdf0e10cSrcweir 					{
838cdf0e10cSrcweir 						try
839cdf0e10cSrcweir 						{
840cdf0e10cSrcweir 							uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
841cdf0e10cSrcweir 							uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
842cdf0e10cSrcweir 								? xModelProperties->getPropertySetInfo()
843cdf0e10cSrcweir 								: uno::Reference< beans::XPropertySetInfo >());
844cdf0e10cSrcweir 							const ::rtl::OUString sPrintablePropertyName(RTL_CONSTASCII_USTRINGPARAM("Printable"));
845cdf0e10cSrcweir 
846cdf0e10cSrcweir 							if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
847cdf0e10cSrcweir 							{
848cdf0e10cSrcweir 								OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
849cdf0e10cSrcweir 							}
850cdf0e10cSrcweir 						}
851cdf0e10cSrcweir 						catch(const uno::Exception&)
852cdf0e10cSrcweir 						{
853cdf0e10cSrcweir 				            OSL_ENSURE(false, "VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
854cdf0e10cSrcweir 						}
855cdf0e10cSrcweir 					}
856cdf0e10cSrcweir 
857cdf0e10cSrcweir                     // PDF export and printing only for printable controls
858cdf0e10cSrcweir                     if(bIsPrintableControl)
859cdf0e10cSrcweir                     {
860cdf0e10cSrcweir                         const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
861cdf0e10cSrcweir                         bool bDoProcessRecursively(true);
862cdf0e10cSrcweir 
863cdf0e10cSrcweir                         if(bPDFExport)
864cdf0e10cSrcweir 					    {
865cdf0e10cSrcweir 						    // PDF export. Emulate data handling from UnoControlPDFExportContact
866cdf0e10cSrcweir                             // I have now moved describePDFControl to toolkit, thus i can implement the PDF
867cdf0e10cSrcweir                             // form control support now as follows
868cdf0e10cSrcweir                             ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl;
869cdf0e10cSrcweir                             ::toolkitform::describePDFControl( rXControl, pPDFControl, *mpPDFExtOutDevData );
870cdf0e10cSrcweir 
871cdf0e10cSrcweir                             if(pPDFControl.get())
872cdf0e10cSrcweir                             {
873cdf0e10cSrcweir                                 // still need to fill in the location (is a class Rectangle)
874cdf0e10cSrcweir 			                    const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
875cdf0e10cSrcweir 	                            const Rectangle aRectLogic(
876cdf0e10cSrcweir 		                            (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()),
877cdf0e10cSrcweir 		                            (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY()));
878cdf0e10cSrcweir                                 pPDFControl->Location = aRectLogic;
879cdf0e10cSrcweir 
880cdf0e10cSrcweir                                 Size aFontSize(pPDFControl->TextFont.GetSize());
881cdf0e10cSrcweir                                 aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode());
882cdf0e10cSrcweir                                 pPDFControl->TextFont.SetSize(aFontSize);
883cdf0e10cSrcweir 
884cdf0e10cSrcweir                                 mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
885cdf0e10cSrcweir                                 mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
886cdf0e10cSrcweir                                 mpPDFExtOutDevData->EndStructureElement();
887cdf0e10cSrcweir 
888cdf0e10cSrcweir                                 // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
889cdf0e10cSrcweir                                 // do not process recursively
890cdf0e10cSrcweir                                 bDoProcessRecursively = false;
891cdf0e10cSrcweir                             }
892cdf0e10cSrcweir                             else
893cdf0e10cSrcweir                             {
894cdf0e10cSrcweir                                 // PDF export did not work, try simple output.
895cdf0e10cSrcweir                                 // Fallback to printer output by not setting bDoProcessRecursively
896cdf0e10cSrcweir                                 // to false.
897cdf0e10cSrcweir                             }
898cdf0e10cSrcweir 					    }
899cdf0e10cSrcweir 
900cdf0e10cSrcweir                         // #i93169# used flag the wrong way; true means that nothing was done yet
901cdf0e10cSrcweir                         if(bDoProcessRecursively)
902cdf0e10cSrcweir 					    {
903cdf0e10cSrcweir     					    // printer output
904cdf0e10cSrcweir 					        try
905cdf0e10cSrcweir 					        {
906cdf0e10cSrcweir                                 // remember old graphics and create new
907cdf0e10cSrcweir 					            uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
908cdf0e10cSrcweir                                 const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
909cdf0e10cSrcweir 					            const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
910cdf0e10cSrcweir 
911cdf0e10cSrcweir                                 if(xNewGraphics.is())
912cdf0e10cSrcweir                                 {
913cdf0e10cSrcweir 				                    // link graphics and view
914cdf0e10cSrcweir 				                    xControlView->setGraphics(xNewGraphics);
915cdf0e10cSrcweir 
916cdf0e10cSrcweir                                     // get position
917cdf0e10cSrcweir                                     const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
918cdf0e10cSrcweir                                     const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
919cdf0e10cSrcweir 
920cdf0e10cSrcweir                                     // draw it
921cdf0e10cSrcweir                                     xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
922cdf0e10cSrcweir                                     bDoProcessRecursively = false;
923cdf0e10cSrcweir 
924cdf0e10cSrcweir                                     // restore original graphics
925cdf0e10cSrcweir 				                    xControlView->setGraphics(xOriginalGraphics);
926cdf0e10cSrcweir                                 }
927cdf0e10cSrcweir 					        }
928cdf0e10cSrcweir 					        catch( const uno::Exception& )
929cdf0e10cSrcweir 					        {
930cdf0e10cSrcweir 			                    OSL_ENSURE(false, "VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
931cdf0e10cSrcweir 					        }
932cdf0e10cSrcweir 					    }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 					    // process recursively if not done yet to export as decomposition (bitmap)
935cdf0e10cSrcweir                         if(bDoProcessRecursively)
936cdf0e10cSrcweir                         {
937cdf0e10cSrcweir     					    process(rControlPrimitive.get2DDecomposition(getViewInformation2D()));
938cdf0e10cSrcweir                         }
939cdf0e10cSrcweir                     }
940cdf0e10cSrcweir 
941cdf0e10cSrcweir 					break;
942cdf0e10cSrcweir 				}
943cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
944cdf0e10cSrcweir                 {
945cdf0e10cSrcweir                     // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
946cdf0e10cSrcweir                     // thus do the MetafileAction embedding stuff but just handle recursively.
947cdf0e10cSrcweir 					const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
948cdf0e10cSrcweir                     static const ByteString aCommentStringCommon("FIELD_SEQ_BEGIN");
949cdf0e10cSrcweir 					static const ByteString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
950cdf0e10cSrcweir 					static const ByteString aCommentStringEnd("FIELD_SEQ_END");
951cdf0e10cSrcweir 
952cdf0e10cSrcweir 					switch(rFieldPrimitive.getType())
953cdf0e10cSrcweir 					{
954cdf0e10cSrcweir 						default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
955cdf0e10cSrcweir 						{
956cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
957cdf0e10cSrcweir 							break;
958cdf0e10cSrcweir 						}
959cdf0e10cSrcweir 						case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
960cdf0e10cSrcweir 						{
961cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
962cdf0e10cSrcweir 							break;
963cdf0e10cSrcweir 						}
964cdf0e10cSrcweir 						case drawinglayer::primitive2d::FIELD_TYPE_URL :
965cdf0e10cSrcweir 						{
966cdf0e10cSrcweir 							const rtl::OUString& rURL = rFieldPrimitive.getString();
967cdf0e10cSrcweir                             const String aOldString(rURL);
968cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.GetBuffer()), 2 * aOldString.Len()));
969cdf0e10cSrcweir 							break;
970cdf0e10cSrcweir 						}
971cdf0e10cSrcweir 					}
972cdf0e10cSrcweir 
973cdf0e10cSrcweir 					// process recursively
974cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D());
975cdf0e10cSrcweir 					process(rContent);
976cdf0e10cSrcweir 
977cdf0e10cSrcweir 					// for the end comment the type is not relevant yet, they are all the same. Just add.
978cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
979cdf0e10cSrcweir 
980cdf0e10cSrcweir 					if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
981cdf0e10cSrcweir 					{
982cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
983cdf0e10cSrcweir 			            const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
984cdf0e10cSrcweir 	                    const Rectangle aRectLogic(
985cdf0e10cSrcweir 		                    (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
986cdf0e10cSrcweir 		                    (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
987cdf0e10cSrcweir 						vcl::PDFExtOutDevBookmarkEntry aBookmark;
988cdf0e10cSrcweir 						aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
989cdf0e10cSrcweir 						aBookmark.aBookmark = rFieldPrimitive.getString();
990cdf0e10cSrcweir 						std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
991cdf0e10cSrcweir 						rBookmarks.push_back( aBookmark );
992cdf0e10cSrcweir 					}
993cdf0e10cSrcweir 
994cdf0e10cSrcweir                     break;
995cdf0e10cSrcweir                 }
996cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
997cdf0e10cSrcweir                 {
998cdf0e10cSrcweir                     const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
999cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOL");
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1002cdf0e10cSrcweir 					process(rLinePrimitive.get2DDecomposition(getViewInformation2D()));
1003cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir                     break;
1006cdf0e10cSrcweir                 }
1007cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
1008cdf0e10cSrcweir                 {
1009cdf0e10cSrcweir                     // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
1010cdf0e10cSrcweir                     // "XTEXT_EOC" is used, use here, too.
1011cdf0e10cSrcweir 					const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
1012cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOC");
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1015cdf0e10cSrcweir 					process(rBulletPrimitive.get2DDecomposition(getViewInformation2D()));
1016cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir                     break;
1019cdf0e10cSrcweir                 }
1020cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
1021cdf0e10cSrcweir                 {
1022cdf0e10cSrcweir                     const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
1023cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOP");
1024cdf0e10cSrcweir 
1025cdf0e10cSrcweir 					if(mpPDFExtOutDevData)
1026cdf0e10cSrcweir 					{
1027cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
1028cdf0e10cSrcweir 						mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
1029cdf0e10cSrcweir 					}
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1032cdf0e10cSrcweir 					process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D()));
1033cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1034cdf0e10cSrcweir 
1035cdf0e10cSrcweir 					if(mpPDFExtOutDevData)
1036cdf0e10cSrcweir 					{
1037cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
1038cdf0e10cSrcweir 						mpPDFExtOutDevData->EndStructureElement();
1039cdf0e10cSrcweir 					}
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir 					break;
1042cdf0e10cSrcweir                 }
1043cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
1044cdf0e10cSrcweir                 {
1045cdf0e10cSrcweir                     const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
1046cdf0e10cSrcweir                     static const ByteString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
1047cdf0e10cSrcweir                     static const ByteString aCommentStringB("XTEXT_PAINTSHAPE_END");
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir                     // add MetaFile comment, process recursively and add MetaFile comment
1050cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
1051cdf0e10cSrcweir 					process(rBlockPrimitive.get2DDecomposition(getViewInformation2D()));
1052cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir                     break;
1055cdf0e10cSrcweir                 }
1056cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
1057cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
1058cdf0e10cSrcweir 				{
1059cdf0e10cSrcweir                     // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
1060cdf0e10cSrcweir 					const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
1061cdf0e10cSrcweir 					// const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 					// Adapt evtl. used special DrawMode
1064cdf0e10cSrcweir 					const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
1065cdf0e10cSrcweir 					adaptTextToFillDrawMode();
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir 					// directdraw of text simple portion; use default processing
1068cdf0e10cSrcweir 					RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
1069cdf0e10cSrcweir 
1070cdf0e10cSrcweir 					// restore DrawMode
1071cdf0e10cSrcweir 					mpOutputDevice->SetDrawMode(nOriginalDrawMode);
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir 					// #i101169# if(pTextDecoratedCandidate)
1074cdf0e10cSrcweir                     {
1075cdf0e10cSrcweir                         // support for TEXT_ MetaFile actions only for decorated texts
1076cdf0e10cSrcweir                         if(!mxBreakIterator.is())
1077cdf0e10cSrcweir                         {
1078cdf0e10cSrcweir                             uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
1079cdf0e10cSrcweir                             mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), uno::UNO_QUERY);
1080cdf0e10cSrcweir                         }
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir                         if(mxBreakIterator.is())
1083cdf0e10cSrcweir                         {
1084cdf0e10cSrcweir                             const rtl::OUString& rTxt = rTextCandidate.getText();
1085cdf0e10cSrcweir                             const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir                             if(nTextLength)
1088cdf0e10cSrcweir                             {
1089cdf0e10cSrcweir                                 const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale();
1090cdf0e10cSrcweir                                 const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir                                 sal_Int32 nDone;
1093cdf0e10cSrcweir                                 sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
1094cdf0e10cSrcweir                                 ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
1095cdf0e10cSrcweir                                 sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
1096cdf0e10cSrcweir                                 static const ByteString aCommentStringA("XTEXT_EOC");
1097cdf0e10cSrcweir                                 static const ByteString aCommentStringB("XTEXT_EOW");
1098cdf0e10cSrcweir                                 static const ByteString aCommentStringC("XTEXT_EOS");
1099cdf0e10cSrcweir 
1100cdf0e10cSrcweir                                 for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
1101cdf0e10cSrcweir                                 {
1102cdf0e10cSrcweir                                     // create the entries for the respective break positions
1103cdf0e10cSrcweir                                     if(i == nNextCellBreak)
1104cdf0e10cSrcweir                                     {
1105cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
1106cdf0e10cSrcweir                                         nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
1107cdf0e10cSrcweir                                     }
1108cdf0e10cSrcweir                                     if(i == nNextWordBoundary.endPos)
1109cdf0e10cSrcweir                                     {
1110cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
1111cdf0e10cSrcweir                                         nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
1112cdf0e10cSrcweir                                     }
1113cdf0e10cSrcweir                                     if(i == nNextSentenceBreak)
1114cdf0e10cSrcweir                                     {
1115cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
1116cdf0e10cSrcweir                                         nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
1117cdf0e10cSrcweir                                     }
1118cdf0e10cSrcweir                                 }
1119cdf0e10cSrcweir                             }
1120cdf0e10cSrcweir                         }
1121cdf0e10cSrcweir                     }
1122cdf0e10cSrcweir 
1123cdf0e10cSrcweir                     break;
1124cdf0e10cSrcweir 				}
1125cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
1126cdf0e10cSrcweir 				{
1127cdf0e10cSrcweir 					const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
1128cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1131cdf0e10cSrcweir                     {
1132cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1133cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1134cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1135cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1136cdf0e10cSrcweir                         const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor());
1137cdf0e10cSrcweir                         const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor());
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1140cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1141cdf0e10cSrcweir                     }
1142cdf0e10cSrcweir                     else
1143cdf0e10cSrcweir                     {
1144cdf0e10cSrcweir     					// direct draw of hairline; use default processing
1145cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1146cdf0e10cSrcweir 					    const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
1147cdf0e10cSrcweir 					    SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1148cdf0e10cSrcweir                             rHairlinePrimitive.getB2DPolygon(),
1149cdf0e10cSrcweir                             &aLineColor,
1150cdf0e10cSrcweir                             0, 0, 0, 0);
1151cdf0e10cSrcweir 
1152cdf0e10cSrcweir 					    impStartSvtGraphicStroke(pSvtGraphicStroke);
1153cdf0e10cSrcweir 					    RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
1154cdf0e10cSrcweir 					    impEndSvtGraphicStroke(pSvtGraphicStroke);
1155cdf0e10cSrcweir                     }
1156cdf0e10cSrcweir 					break;
1157cdf0e10cSrcweir 				}
1158cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
1159cdf0e10cSrcweir 				{
1160cdf0e10cSrcweir 					const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
1161cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1164cdf0e10cSrcweir                     {
1165cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1166cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1167cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1168cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1169cdf0e10cSrcweir                         const primitive2d::PolygonStrokePrimitive2D aPLeft(
1170cdf0e10cSrcweir                             aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1171cdf0e10cSrcweir                         const primitive2d::PolygonStrokePrimitive2D aPRight(
1172cdf0e10cSrcweir                             aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1175cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1176cdf0e10cSrcweir                     }
1177cdf0e10cSrcweir                     else
1178cdf0e10cSrcweir                     {
1179cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1180cdf0e10cSrcweir 					    SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1181cdf0e10cSrcweir                             rBasePolygon, 0,
1182cdf0e10cSrcweir                             &rStrokePrimitive.getLineAttribute(),
1183cdf0e10cSrcweir                             &rStrokePrimitive.getStrokeAttribute(),
1184cdf0e10cSrcweir                             0, 0);
1185cdf0e10cSrcweir 
1186cdf0e10cSrcweir 					    impStartSvtGraphicStroke(pSvtGraphicStroke);
1187cdf0e10cSrcweir 					    const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir 					    // create MetaPolyLineActions, but without LINE_DASH
1190cdf0e10cSrcweir 					    if(basegfx::fTools::more(rLine.getWidth(), 0.0))
1191cdf0e10cSrcweir 					    {
1192cdf0e10cSrcweir 						    const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
1193cdf0e10cSrcweir 						    basegfx::B2DPolyPolygon aHairLinePolyPolygon;
1194cdf0e10cSrcweir 
1195cdf0e10cSrcweir 						    if(0.0 == rStroke.getFullDotDashLen())
1196cdf0e10cSrcweir 						    {
1197cdf0e10cSrcweir 							    aHairLinePolyPolygon.append(rBasePolygon);
1198cdf0e10cSrcweir 						    }
1199cdf0e10cSrcweir 						    else
1200cdf0e10cSrcweir 						    {
1201cdf0e10cSrcweir 							    basegfx::tools::applyLineDashing(
1202cdf0e10cSrcweir 								    rBasePolygon, rStroke.getDotDashArray(),
1203cdf0e10cSrcweir 								    &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen());
1204cdf0e10cSrcweir 						    }
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir 						    const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
1207cdf0e10cSrcweir 						    mpOutputDevice->SetLineColor(Color(aHairlineColor));
1208cdf0e10cSrcweir 						    mpOutputDevice->SetFillColor();
1209cdf0e10cSrcweir 						    aHairLinePolyPolygon.transform(maCurrentTransformation);
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir 							// #i113922# LineWidth needs to be transformed, too
1212cdf0e10cSrcweir 							const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0));
1213cdf0e10cSrcweir 							const double fDiscreteLineWidth(aDiscreteUnit.getLength());
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir 							LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth));
1216cdf0e10cSrcweir 						    aLineInfo.SetLineJoin(rLine.getLineJoin());
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir 						    for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
1219cdf0e10cSrcweir 						    {
1220cdf0e10cSrcweir 							    const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
1221cdf0e10cSrcweir 
1222cdf0e10cSrcweir 							    if(aCandidate.count() > 1)
1223cdf0e10cSrcweir 							    {
1224cdf0e10cSrcweir 								    const Polygon aToolsPolygon(aCandidate);
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir                 				    mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
1227cdf0e10cSrcweir 							    }
1228cdf0e10cSrcweir 						    }
1229cdf0e10cSrcweir 					    }
1230cdf0e10cSrcweir 					    else
1231cdf0e10cSrcweir 					    {
1232cdf0e10cSrcweir 						    process(rCandidate.get2DDecomposition(getViewInformation2D()));
1233cdf0e10cSrcweir 					    }
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir 					    impEndSvtGraphicStroke(pSvtGraphicStroke);
1236cdf0e10cSrcweir                     }
1237cdf0e10cSrcweir 
1238cdf0e10cSrcweir 					break;
1239cdf0e10cSrcweir 				}
1240cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
1241cdf0e10cSrcweir 				{
1242cdf0e10cSrcweir 					const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
1243cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
1244cdf0e10cSrcweir 
1245cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1246cdf0e10cSrcweir                     {
1247cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1248cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1249cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1250cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1251cdf0e10cSrcweir                         const attribute::LineStartEndAttribute aEmpty;
1252cdf0e10cSrcweir                         const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft(
1253cdf0e10cSrcweir                             aLeft,
1254cdf0e10cSrcweir                             rStrokeArrowPrimitive.getLineAttribute(),
1255cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStrokeAttribute(),
1256cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStart(),
1257cdf0e10cSrcweir                             aEmpty);
1258cdf0e10cSrcweir                         const primitive2d::PolygonStrokeArrowPrimitive2D aPRight(
1259cdf0e10cSrcweir                             aRight,
1260cdf0e10cSrcweir                             rStrokeArrowPrimitive.getLineAttribute(),
1261cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStrokeAttribute(),
1262cdf0e10cSrcweir                             aEmpty,
1263cdf0e10cSrcweir                             rStrokeArrowPrimitive.getEnd());
1264cdf0e10cSrcweir 
1265cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1266cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1267cdf0e10cSrcweir                     }
1268cdf0e10cSrcweir                     else
1269cdf0e10cSrcweir                     {
1270cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1271cdf0e10cSrcweir 	    				SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1272cdf0e10cSrcweir                             rBasePolygon, 0,
1273cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getLineAttribute(),
1274cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getStrokeAttribute(),
1275cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getStart(),
1276cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getEnd());
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir 			    		impStartSvtGraphicStroke(pSvtGraphicStroke);
1279cdf0e10cSrcweir 				    	process(rCandidate.get2DDecomposition(getViewInformation2D()));
1280cdf0e10cSrcweir 					    impEndSvtGraphicStroke(pSvtGraphicStroke);
1281cdf0e10cSrcweir                     }
1282cdf0e10cSrcweir 
1283cdf0e10cSrcweir                     break;
1284cdf0e10cSrcweir 				}
1285cdf0e10cSrcweir 				case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
1286cdf0e10cSrcweir 				{
1287cdf0e10cSrcweir                     // direct draw of transformed BitmapEx primitive; use default processing
1288cdf0e10cSrcweir 					RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
1289cdf0e10cSrcweir 					break;
1290cdf0e10cSrcweir 				}
1291cdf0e10cSrcweir 				case PRIMITIVE2D_ID_RENDERGRAPHICPRIMITIVE2D :
1292cdf0e10cSrcweir 				{
1293cdf0e10cSrcweir                     // direct draw of transformed RenderGraphic primitive; use default processing
1294cdf0e10cSrcweir 					RenderRenderGraphicPrimitive2D(static_cast< const primitive2d::RenderGraphicPrimitive2D& >(rCandidate));
1295cdf0e10cSrcweir 					break;
1296cdf0e10cSrcweir 				}
1297cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
1298cdf0e10cSrcweir 				{
1299cdf0e10cSrcweir 					// need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1300cdf0e10cSrcweir 					const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
1301cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
1302cdf0e10cSrcweir 
1303cdf0e10cSrcweir                     if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1304cdf0e10cSrcweir                     {
1305cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1306cdf0e10cSrcweir                         // per polygon. If there are more use the splitted polygon and call recursively
1307cdf0e10cSrcweir                         const primitive2d::PolyPolygonBitmapPrimitive2D aSplitted(
1308cdf0e10cSrcweir                             aLocalPolyPolygon,
1309cdf0e10cSrcweir                             rBitmapCandidate.getFillBitmap());
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir                         processBasePrimitive2D(aSplitted);
1312cdf0e10cSrcweir                     }
1313cdf0e10cSrcweir                     else
1314cdf0e10cSrcweir                     {
1315cdf0e10cSrcweir                         SvtGraphicFill* pSvtGraphicFill = 0;
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir 					    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1318cdf0e10cSrcweir 					    {
1319cdf0e10cSrcweir 						    aLocalPolyPolygon.transform(maCurrentTransformation);
1320cdf0e10cSrcweir 						    // calculate transformation. Get real object size, all values in FillBitmapAttribute
1321cdf0e10cSrcweir 						    // are relative to the unified object
1322cdf0e10cSrcweir 						    const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap();
1323cdf0e10cSrcweir 						    const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aLocalPolyPolygon));
1324cdf0e10cSrcweir 						    const basegfx::B2DVector aOutlineSize(aOutlineRange.getRange());
1325cdf0e10cSrcweir 
1326cdf0e10cSrcweir 						    // get absolute values
1327cdf0e10cSrcweir 						    const basegfx::B2DVector aFillBitmapSize(rFillBitmapAttribute.getSize() * aOutlineSize);
1328cdf0e10cSrcweir 						    const basegfx::B2DPoint aFillBitmapTopLeft(rFillBitmapAttribute.getTopLeft() * aOutlineSize);
1329cdf0e10cSrcweir 
1330cdf0e10cSrcweir 						    // the scaling needs scale from pixel to logic coordinate system
1331cdf0e10cSrcweir 						    const BitmapEx& rBitmapEx = rFillBitmapAttribute.getBitmapEx();
1332cdf0e10cSrcweir 						    Size aBmpSizePixel(rBitmapEx.GetSizePixel());
1333cdf0e10cSrcweir 
1334cdf0e10cSrcweir 						    if(!aBmpSizePixel.Width())
1335cdf0e10cSrcweir 						    {
1336cdf0e10cSrcweir 							    aBmpSizePixel.Width() = 1;
1337cdf0e10cSrcweir 						    }
1338cdf0e10cSrcweir 
1339cdf0e10cSrcweir 						    if(!aBmpSizePixel.Height())
1340cdf0e10cSrcweir 						    {
1341cdf0e10cSrcweir 							    aBmpSizePixel.Height() = 1;
1342cdf0e10cSrcweir 						    }
1343cdf0e10cSrcweir 
1344cdf0e10cSrcweir 						    // setup transformation like in impgrfll
1345cdf0e10cSrcweir 						    SvtGraphicFill::Transform aTransform;
1346cdf0e10cSrcweir 
1347cdf0e10cSrcweir 						    // scale values are divided by bitmap pixel sizes
1348cdf0e10cSrcweir 						    aTransform.matrix[0] = aFillBitmapSize.getX() / aBmpSizePixel.Width();
1349cdf0e10cSrcweir 						    aTransform.matrix[4] = aFillBitmapSize.getY() / aBmpSizePixel.Height();
1350cdf0e10cSrcweir 
1351cdf0e10cSrcweir                             // translates are absolute
1352cdf0e10cSrcweir                             aTransform.matrix[2] = aFillBitmapTopLeft.getX();
1353cdf0e10cSrcweir 						    aTransform.matrix[5] = aFillBitmapTopLeft.getY();
1354cdf0e10cSrcweir 
1355cdf0e10cSrcweir 						    // setup fill graphic like in impgrfll
1356cdf0e10cSrcweir 						    Graphic aFillGraphic = Graphic(rBitmapEx);
1357cdf0e10cSrcweir 						    aFillGraphic.SetPrefMapMode(MapMode(MAP_PIXEL));
1358cdf0e10cSrcweir 						    aFillGraphic.SetPrefSize(aBmpSizePixel);
1359cdf0e10cSrcweir 
1360cdf0e10cSrcweir 						    pSvtGraphicFill = new SvtGraphicFill(
1361cdf0e10cSrcweir 							    PolyPolygon(aLocalPolyPolygon),
1362cdf0e10cSrcweir 							    Color(),
1363cdf0e10cSrcweir 							    0.0,
1364cdf0e10cSrcweir 							    SvtGraphicFill::fillEvenOdd,
1365cdf0e10cSrcweir 							    SvtGraphicFill::fillTexture,
1366cdf0e10cSrcweir 							    aTransform,
1367cdf0e10cSrcweir 							    rFillBitmapAttribute.getTiling(),
1368cdf0e10cSrcweir 							    SvtGraphicFill::hatchSingle,
1369cdf0e10cSrcweir 							    Color(),
1370cdf0e10cSrcweir 							    SvtGraphicFill::gradientLinear,
1371cdf0e10cSrcweir 							    Color(),
1372cdf0e10cSrcweir 							    Color(),
1373cdf0e10cSrcweir 							    0,
1374cdf0e10cSrcweir 							    aFillGraphic);
1375cdf0e10cSrcweir 					    }
1376cdf0e10cSrcweir 
1377cdf0e10cSrcweir 					    // Do use decomposition; encapsulate with SvtGraphicFill
1378cdf0e10cSrcweir 					    impStartSvtGraphicFill(pSvtGraphicFill);
1379cdf0e10cSrcweir 					    process(rCandidate.get2DDecomposition(getViewInformation2D()));
1380cdf0e10cSrcweir 					    impEndSvtGraphicFill(pSvtGraphicFill);
1381cdf0e10cSrcweir                     }
1382cdf0e10cSrcweir 
1383cdf0e10cSrcweir 					break;
1384cdf0e10cSrcweir 				}
1385cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
1386cdf0e10cSrcweir 				{
1387cdf0e10cSrcweir 					// need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1388cdf0e10cSrcweir 					const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
1389cdf0e10cSrcweir 				    const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
1390cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1393cdf0e10cSrcweir                     // per polygon. Split polygon until there are less than that
1394cdf0e10cSrcweir                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1395cdf0e10cSrcweir                         ;
1396cdf0e10cSrcweir 
1397cdf0e10cSrcweir 					if(rFillHatchAttribute.isFillBackground())
1398cdf0e10cSrcweir 					{
1399cdf0e10cSrcweir 						// with fixing #i111954# (see below) the possible background
1400cdf0e10cSrcweir 						// fill of a hatched object was lost.Generate a background fill
1401cdf0e10cSrcweir 						// primitive and render it
1402cdf0e10cSrcweir 					    const primitive2d::Primitive2DReference xBackground(
1403cdf0e10cSrcweir 							new primitive2d::PolyPolygonColorPrimitive2D(
1404cdf0e10cSrcweir 								aLocalPolyPolygon,
1405cdf0e10cSrcweir 								rHatchCandidate.getBackgroundColor()));
1406cdf0e10cSrcweir 
1407cdf0e10cSrcweir 						process(primitive2d::Primitive2DSequence(&xBackground, 1));
1408cdf0e10cSrcweir 					}
1409cdf0e10cSrcweir 
1410cdf0e10cSrcweir                     SvtGraphicFill* pSvtGraphicFill = 0;
1411cdf0e10cSrcweir 				    aLocalPolyPolygon.transform(maCurrentTransformation);
1412cdf0e10cSrcweir 
1413cdf0e10cSrcweir 				    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1414cdf0e10cSrcweir 				    {
1415cdf0e10cSrcweir 					    // re-create a VCL hatch as base data
1416cdf0e10cSrcweir 					    SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
1417cdf0e10cSrcweir 
1418cdf0e10cSrcweir 					    switch(rFillHatchAttribute.getStyle())
1419cdf0e10cSrcweir 					    {
1420cdf0e10cSrcweir 						    default: // attribute::HATCHSTYLE_SINGLE :
1421cdf0e10cSrcweir 						    {
1422cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchSingle;
1423cdf0e10cSrcweir 							    break;
1424cdf0e10cSrcweir 						    }
1425cdf0e10cSrcweir 						    case attribute::HATCHSTYLE_DOUBLE :
1426cdf0e10cSrcweir 						    {
1427cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchDouble;
1428cdf0e10cSrcweir 							    break;
1429cdf0e10cSrcweir 						    }
1430cdf0e10cSrcweir 						    case attribute::HATCHSTYLE_TRIPLE :
1431cdf0e10cSrcweir 						    {
1432cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchTriple;
1433cdf0e10cSrcweir 							    break;
1434cdf0e10cSrcweir 						    }
1435cdf0e10cSrcweir 					    }
1436cdf0e10cSrcweir 
1437cdf0e10cSrcweir 					    SvtGraphicFill::Transform aTransform;
1438cdf0e10cSrcweir 
1439cdf0e10cSrcweir 					    // scale
1440cdf0e10cSrcweir 					    aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
1441cdf0e10cSrcweir 					    aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
1442cdf0e10cSrcweir 
1443cdf0e10cSrcweir 					    // rotate (was never correct in impgrfll anyways, use correct angle now)
1444cdf0e10cSrcweir 					    aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
1445cdf0e10cSrcweir 					    aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
1446cdf0e10cSrcweir 					    aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
1447cdf0e10cSrcweir 					    aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
1448cdf0e10cSrcweir 
1449cdf0e10cSrcweir 					    pSvtGraphicFill = new SvtGraphicFill(
1450cdf0e10cSrcweir 						    PolyPolygon(aLocalPolyPolygon),
1451cdf0e10cSrcweir 						    Color(),
1452cdf0e10cSrcweir 						    0.0,
1453cdf0e10cSrcweir 						    SvtGraphicFill::fillEvenOdd,
1454cdf0e10cSrcweir 						    SvtGraphicFill::fillHatch,
1455cdf0e10cSrcweir 						    aTransform,
1456cdf0e10cSrcweir 						    false,
1457cdf0e10cSrcweir 						    eHatch,
1458cdf0e10cSrcweir 						    Color(rFillHatchAttribute.getColor()),
1459cdf0e10cSrcweir 						    SvtGraphicFill::gradientLinear,
1460cdf0e10cSrcweir 						    Color(),
1461cdf0e10cSrcweir 						    Color(),
1462cdf0e10cSrcweir 						    0,
1463cdf0e10cSrcweir 						    Graphic());
1464cdf0e10cSrcweir 				    }
1465cdf0e10cSrcweir 
1466cdf0e10cSrcweir 				    // Do use decomposition; encapsulate with SvtGraphicFill
1467cdf0e10cSrcweir 				    impStartSvtGraphicFill(pSvtGraphicFill);
1468cdf0e10cSrcweir 
1469cdf0e10cSrcweir                     // #i111954# do NOT use decomposition, but use direct VCL-command
1470cdf0e10cSrcweir 			        // process(rCandidate.get2DDecomposition(getViewInformation2D()));
1471cdf0e10cSrcweir 			        const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
1472cdf0e10cSrcweir                     const HatchStyle aHatchStyle(
1473cdf0e10cSrcweir                         attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
1474cdf0e10cSrcweir                         attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
1475cdf0e10cSrcweir                         HATCH_TRIPLE);
1476cdf0e10cSrcweir 
1477cdf0e10cSrcweir                     mpOutputDevice->DrawHatch(aToolsPolyPolygon,
1478cdf0e10cSrcweir                         Hatch(aHatchStyle,
1479cdf0e10cSrcweir                             Color(rFillHatchAttribute.getColor()),
1480cdf0e10cSrcweir                             basegfx::fround(rFillHatchAttribute.getDistance()),
1481cdf0e10cSrcweir                             basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir                     impEndSvtGraphicFill(pSvtGraphicFill);
1484cdf0e10cSrcweir 
1485cdf0e10cSrcweir 					break;
1486cdf0e10cSrcweir 				}
1487cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
1488cdf0e10cSrcweir                 {
1489cdf0e10cSrcweir 					const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
1490cdf0e10cSrcweir 			        basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
1491cdf0e10cSrcweir 
1492cdf0e10cSrcweir                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1493cdf0e10cSrcweir                     // per polygon. Split polygon until there are less than that
1494cdf0e10cSrcweir                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1495cdf0e10cSrcweir                         ;
1496cdf0e10cSrcweir 
1497cdf0e10cSrcweir                     // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
1498cdf0e10cSrcweir                     // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
1499cdf0e10cSrcweir                     // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
1500cdf0e10cSrcweir 				    Gradient aVCLGradient;
1501cdf0e10cSrcweir                     impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
1502cdf0e10cSrcweir 		            aLocalPolyPolygon.transform(maCurrentTransformation);
1503cdf0e10cSrcweir 
1504cdf0e10cSrcweir 				    // #i82145# ATM VCL printing of gradients using curved shapes does not work,
1505cdf0e10cSrcweir 				    // i submitted the bug with the given ID to THB. When that task is fixed it is
1506cdf0e10cSrcweir 				    // necessary to again remove this subdivision since it decreases possible
1507cdf0e10cSrcweir 				    // printing quality (not even resolution-dependent for now). THB will tell
1508cdf0e10cSrcweir 				    // me when that task is fixed in the master
1509cdf0e10cSrcweir 				    const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
1510cdf0e10cSrcweir 
1511cdf0e10cSrcweir 				    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1512cdf0e10cSrcweir 				    SvtGraphicFill* pSvtGraphicFill = 0;
1513cdf0e10cSrcweir 
1514cdf0e10cSrcweir 				    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1515cdf0e10cSrcweir 				    {
1516cdf0e10cSrcweir 					    // setup gradient stuff like in like in impgrfll
1517cdf0e10cSrcweir 					    SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
1518cdf0e10cSrcweir 
1519cdf0e10cSrcweir 					    switch(aVCLGradient.GetStyle())
1520cdf0e10cSrcweir 					    {
1521cdf0e10cSrcweir 						    default : // GRADIENT_LINEAR:
1522cdf0e10cSrcweir 						    case GRADIENT_AXIAL:
1523cdf0e10cSrcweir 							    eGrad = SvtGraphicFill::gradientLinear;
1524cdf0e10cSrcweir 							    break;
1525cdf0e10cSrcweir 						    case GRADIENT_RADIAL:
1526cdf0e10cSrcweir 						    case GRADIENT_ELLIPTICAL:
1527cdf0e10cSrcweir 							    eGrad = SvtGraphicFill::gradientRadial;
1528cdf0e10cSrcweir 							    break;
1529cdf0e10cSrcweir 						    case GRADIENT_SQUARE:
1530cdf0e10cSrcweir 						    case GRADIENT_RECT:
1531cdf0e10cSrcweir 							    eGrad = SvtGraphicFill::gradientRectangular;
1532cdf0e10cSrcweir 							    break;
1533cdf0e10cSrcweir 					    }
1534cdf0e10cSrcweir 
1535cdf0e10cSrcweir 					    pSvtGraphicFill = new SvtGraphicFill(
1536cdf0e10cSrcweir 						    aToolsPolyPolygon,
1537cdf0e10cSrcweir 						    Color(),
1538cdf0e10cSrcweir 						    0.0,
1539cdf0e10cSrcweir 						    SvtGraphicFill::fillEvenOdd,
1540cdf0e10cSrcweir 						    SvtGraphicFill::fillGradient,
1541cdf0e10cSrcweir 						    SvtGraphicFill::Transform(),
1542cdf0e10cSrcweir 						    false,
1543cdf0e10cSrcweir 						    SvtGraphicFill::hatchSingle,
1544cdf0e10cSrcweir 						    Color(),
1545cdf0e10cSrcweir 						    eGrad,
1546cdf0e10cSrcweir 						    aVCLGradient.GetStartColor(),
1547cdf0e10cSrcweir 						    aVCLGradient.GetEndColor(),
1548cdf0e10cSrcweir 						    aVCLGradient.GetSteps(),
1549cdf0e10cSrcweir 						    Graphic());
1550cdf0e10cSrcweir 				    }
1551cdf0e10cSrcweir 
1552cdf0e10cSrcweir 				    // call VCL directly; encapsulate with SvtGraphicFill
1553cdf0e10cSrcweir 				    impStartSvtGraphicFill(pSvtGraphicFill);
1554cdf0e10cSrcweir 		            mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
1555cdf0e10cSrcweir 				    impEndSvtGraphicFill(pSvtGraphicFill);
1556cdf0e10cSrcweir 
1557cdf0e10cSrcweir 				    // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above
1558cdf0e10cSrcweir 				    // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
1559cdf0e10cSrcweir 
1560cdf0e10cSrcweir                     break;
1561cdf0e10cSrcweir                 }
1562cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
1563cdf0e10cSrcweir 				{
1564cdf0e10cSrcweir 					const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
1565cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
1566cdf0e10cSrcweir 
1567cdf0e10cSrcweir                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1568cdf0e10cSrcweir                     // per polygon. Split polygon until there are less than that
1569cdf0e10cSrcweir                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1570cdf0e10cSrcweir                         ;
1571cdf0e10cSrcweir 
1572cdf0e10cSrcweir 				    const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
1573cdf0e10cSrcweir 				    aLocalPolyPolygon.transform(maCurrentTransformation);
1574cdf0e10cSrcweir 
1575cdf0e10cSrcweir 				    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1576cdf0e10cSrcweir 				    SvtGraphicFill* pSvtGraphicFill = 0;
1577cdf0e10cSrcweir 
1578cdf0e10cSrcweir 				    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1579cdf0e10cSrcweir 				    {
1580cdf0e10cSrcweir 					    // setup simple color fill stuff like in impgrfll
1581cdf0e10cSrcweir 					    pSvtGraphicFill = new SvtGraphicFill(
1582cdf0e10cSrcweir 						    PolyPolygon(aLocalPolyPolygon),
1583cdf0e10cSrcweir 						    Color(aPolygonColor),
1584cdf0e10cSrcweir 						    0.0,
1585cdf0e10cSrcweir 						    SvtGraphicFill::fillEvenOdd,
1586cdf0e10cSrcweir 						    SvtGraphicFill::fillSolid,
1587cdf0e10cSrcweir 						    SvtGraphicFill::Transform(),
1588cdf0e10cSrcweir 						    false,
1589cdf0e10cSrcweir 						    SvtGraphicFill::hatchSingle,
1590cdf0e10cSrcweir 						    Color(),
1591cdf0e10cSrcweir 						    SvtGraphicFill::gradientLinear,
1592cdf0e10cSrcweir 						    Color(),
1593cdf0e10cSrcweir 						    Color(),
1594cdf0e10cSrcweir 						    0,
1595cdf0e10cSrcweir 						    Graphic());
1596cdf0e10cSrcweir 				    }
1597cdf0e10cSrcweir 
1598cdf0e10cSrcweir                     // set line and fill color
1599cdf0e10cSrcweir 				    mpOutputDevice->SetFillColor(Color(aPolygonColor));
1600cdf0e10cSrcweir 				    mpOutputDevice->SetLineColor();
1601cdf0e10cSrcweir 
1602cdf0e10cSrcweir 				    // call VCL directly; encapsulate with SvtGraphicFill
1603cdf0e10cSrcweir                     impStartSvtGraphicFill(pSvtGraphicFill);
1604cdf0e10cSrcweir 				    mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
1605cdf0e10cSrcweir 				    impEndSvtGraphicFill(pSvtGraphicFill);
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 					break;
1608cdf0e10cSrcweir 				}
1609cdf0e10cSrcweir 				case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
1610cdf0e10cSrcweir 				{
1611*dfe9de19SHerbert Dürr                     static bool bUseMetaFilePrimitiveDecomposition(true);
1612*dfe9de19SHerbert Dürr 
1613*dfe9de19SHerbert Dürr                     if(bUseMetaFilePrimitiveDecomposition)
1614*dfe9de19SHerbert Dürr                     {
1615*dfe9de19SHerbert Dürr                         // use new Metafile decomposition
1616*dfe9de19SHerbert Dürr     					process(rCandidate.get2DDecomposition(getViewInformation2D()));
1617*dfe9de19SHerbert Dürr                     }
1618*dfe9de19SHerbert Dürr                     else
1619*dfe9de19SHerbert Dürr                     {
1620*dfe9de19SHerbert Dürr                         // direct draw of MetaFile, use default pocessing
1621*dfe9de19SHerbert Dürr 					    RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
1622*dfe9de19SHerbert Dürr                     }
1623*dfe9de19SHerbert Dürr 
1624*dfe9de19SHerbert Dürr                     break;
1625cdf0e10cSrcweir 				}
1626cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
1627cdf0e10cSrcweir 				{
1628cdf0e10cSrcweir                     // mask group. Special handling for MetaFiles.
1629cdf0e10cSrcweir 					const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
1630cdf0e10cSrcweir 
1631cdf0e10cSrcweir                     if(rMaskCandidate.getChildren().hasElements())
1632cdf0e10cSrcweir 			        {
1633cdf0e10cSrcweir 				        basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
1634cdf0e10cSrcweir 
1635cdf0e10cSrcweir 				        if(aMask.count())
1636cdf0e10cSrcweir 				        {
1637cdf0e10cSrcweir 							// prepare new mask polygon and rescue current one
1638cdf0e10cSrcweir 					        aMask.transform(maCurrentTransformation);
1639cdf0e10cSrcweir                             const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir                             if(maClipPolyPolygon.count())
1642cdf0e10cSrcweir                             {
1643cdf0e10cSrcweir 								// there is already a clip polygon set; build clipped union of
1644cdf0e10cSrcweir 								// current mask polygon and new one
1645cdf0e10cSrcweir 								maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
1646cdf0e10cSrcweir                                     aMask,
1647cdf0e10cSrcweir                                     maClipPolyPolygon,
1648cdf0e10cSrcweir                                     true, // #i106516# we want the inside of aMask, not the outside
1649cdf0e10cSrcweir                                     false);
1650cdf0e10cSrcweir                             }
1651cdf0e10cSrcweir                             else
1652cdf0e10cSrcweir                             {
1653cdf0e10cSrcweir                                 // use mask directly
1654cdf0e10cSrcweir                                 maClipPolyPolygon = aMask;
1655cdf0e10cSrcweir                             }
1656cdf0e10cSrcweir 
1657cdf0e10cSrcweir                             if(maClipPolyPolygon.count())
1658cdf0e10cSrcweir                             {
1659cdf0e10cSrcweir                                 // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
1660cdf0e10cSrcweir                                 // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
1661cdf0e10cSrcweir                                 // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
1662cdf0e10cSrcweir                                 mpOutputDevice->Push(PUSH_CLIPREGION);
1663cdf0e10cSrcweir 								//mpOutputDevice->SetClipRegion(Region(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon))));
1664cdf0e10cSrcweir 								mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
1665cdf0e10cSrcweir                             }
1666cdf0e10cSrcweir 
1667cdf0e10cSrcweir 					        // recursively paint content
1668cdf0e10cSrcweir 					        process(rMaskCandidate.getChildren());
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir                             if(maClipPolyPolygon.count())
1671cdf0e10cSrcweir                             {
1672cdf0e10cSrcweir                                 // restore VCL clip region
1673cdf0e10cSrcweir                                 mpOutputDevice->Pop();
1674cdf0e10cSrcweir                             }
1675cdf0e10cSrcweir 
1676cdf0e10cSrcweir                             // restore to rescued clip polygon
1677cdf0e10cSrcweir                             maClipPolyPolygon = aLastClipPolyPolygon;
1678cdf0e10cSrcweir 				        }
1679cdf0e10cSrcweir                         else
1680cdf0e10cSrcweir                         {
1681cdf0e10cSrcweir                             // no mask, no clipping. recursively paint content
1682cdf0e10cSrcweir 					        process(rMaskCandidate.getChildren());
1683cdf0e10cSrcweir                         }
1684cdf0e10cSrcweir 			        }
1685cdf0e10cSrcweir 
1686cdf0e10cSrcweir                     break;
1687cdf0e10cSrcweir 				}
1688cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
1689cdf0e10cSrcweir 				{
1690cdf0e10cSrcweir 					// modified color group. Force output to unified color. Use default pocessing.
1691cdf0e10cSrcweir 					RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
1692cdf0e10cSrcweir 					break;
1693cdf0e10cSrcweir 				}
1694cdf0e10cSrcweir                 case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D :
1695cdf0e10cSrcweir 				{
1696cdf0e10cSrcweir                     // HiddenGeometryPrimitive2D; to rebuilt the old MetaFile creation, it is necessary to
1697cdf0e10cSrcweir                     // not ignore them (as it was thought), but to add a MetaFile entry for them.
1698cdf0e10cSrcweir         		    basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D()));
1699cdf0e10cSrcweir 
1700cdf0e10cSrcweir                     if(!aInvisibleRange.isEmpty())
1701cdf0e10cSrcweir                     {
1702cdf0e10cSrcweir 		                aInvisibleRange.transform(maCurrentTransformation);
1703cdf0e10cSrcweir                         const Rectangle aRectLogic(
1704cdf0e10cSrcweir 	                        (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()),
1705cdf0e10cSrcweir 	                        (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY()));
1706cdf0e10cSrcweir 
1707cdf0e10cSrcweir                         mpOutputDevice->SetFillColor();
1708cdf0e10cSrcweir 		                mpOutputDevice->SetLineColor();
1709cdf0e10cSrcweir 		                mpOutputDevice->DrawRect(aRectLogic);
1710cdf0e10cSrcweir                     }
1711cdf0e10cSrcweir 
1712cdf0e10cSrcweir 					break;
1713cdf0e10cSrcweir 				}
1714cdf0e10cSrcweir 				case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
1715cdf0e10cSrcweir 				{
1716cdf0e10cSrcweir 					// for metafile: Need to examine what the pure vcl version is doing here actually
1717cdf0e10cSrcweir 					// - uses DrawTransparent with metafile for content and a gradient
1718cdf0e10cSrcweir 					// - uses DrawTransparent for single PolyPoylgons directly. Can be detected by
1719cdf0e10cSrcweir 					//   checking the content for single PolyPolygonColorPrimitive2D
1720cdf0e10cSrcweir 					const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate);
1721cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren();
1722cdf0e10cSrcweir 
1723cdf0e10cSrcweir 					if(rContent.hasElements())
1724cdf0e10cSrcweir 					{
1725cdf0e10cSrcweir                         if(0.0 == rUniTransparenceCandidate.getTransparence())
1726cdf0e10cSrcweir                         {
1727cdf0e10cSrcweir                             // not transparent at all, use content
1728cdf0e10cSrcweir 	                        process(rUniTransparenceCandidate.getChildren());
1729cdf0e10cSrcweir                         }
1730cdf0e10cSrcweir 			            else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
1731cdf0e10cSrcweir 			            {
1732cdf0e10cSrcweir 						    // try to identify a single PolyPolygonColorPrimitive2D in the
1733cdf0e10cSrcweir 						    // content part of the transparence primitive
1734cdf0e10cSrcweir 						    const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0;
1735cdf0e10cSrcweir 						    static bool bForceToMetafile(false);
1736cdf0e10cSrcweir 
1737cdf0e10cSrcweir 						    if(!bForceToMetafile && 1 == rContent.getLength())
1738cdf0e10cSrcweir 						    {
1739cdf0e10cSrcweir 							    const primitive2d::Primitive2DReference xReference(rContent[0]);
1740cdf0e10cSrcweir 							    pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
1741cdf0e10cSrcweir 						    }
1742cdf0e10cSrcweir 
1743cdf0e10cSrcweir 						    // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
1744cdf0e10cSrcweir 						    // PolyPolygonBitmapPrimitive2D are derived from PolyPolygonColorPrimitive2D.
1745cdf0e10cSrcweir 						    // Check also for correct ID to exclude derived implementations
1746cdf0e10cSrcweir 						    if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
1747cdf0e10cSrcweir 						    {
1748cdf0e10cSrcweir 							    // single transparent PolyPolygon identified, use directly
1749cdf0e10cSrcweir 							    const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
1750cdf0e10cSrcweir 							    basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir                                 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1753cdf0e10cSrcweir                                 // per polygon. Split polygon until there are less than that
1754cdf0e10cSrcweir                                 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1755cdf0e10cSrcweir                                     ;
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir                                 // now transform
1758cdf0e10cSrcweir                                 aLocalPolyPolygon.transform(maCurrentTransformation);
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir 							    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1761cdf0e10cSrcweir 							    SvtGraphicFill* pSvtGraphicFill = 0;
1762cdf0e10cSrcweir 
1763cdf0e10cSrcweir 							    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1764cdf0e10cSrcweir 							    {
1765cdf0e10cSrcweir 								    // setup simple color with transparence fill stuff like in impgrfll
1766cdf0e10cSrcweir 								    pSvtGraphicFill = new SvtGraphicFill(
1767cdf0e10cSrcweir 									    PolyPolygon(aLocalPolyPolygon),
1768cdf0e10cSrcweir 									    Color(aPolygonColor),
1769cdf0e10cSrcweir 									    rUniTransparenceCandidate.getTransparence(),
1770cdf0e10cSrcweir 									    SvtGraphicFill::fillEvenOdd,
1771cdf0e10cSrcweir 									    SvtGraphicFill::fillSolid,
1772cdf0e10cSrcweir 									    SvtGraphicFill::Transform(),
1773cdf0e10cSrcweir 									    false,
1774cdf0e10cSrcweir 									    SvtGraphicFill::hatchSingle,
1775cdf0e10cSrcweir 									    Color(),
1776cdf0e10cSrcweir 									    SvtGraphicFill::gradientLinear,
1777cdf0e10cSrcweir 									    Color(),
1778cdf0e10cSrcweir 									    Color(),
1779cdf0e10cSrcweir 									    0,
1780cdf0e10cSrcweir 									    Graphic());
1781cdf0e10cSrcweir 							    }
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir                                 // set line and fill color
1784cdf0e10cSrcweir 							    const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0));
1785cdf0e10cSrcweir 							    mpOutputDevice->SetFillColor(Color(aPolygonColor));
1786cdf0e10cSrcweir 							    mpOutputDevice->SetLineColor();
1787cdf0e10cSrcweir 
1788cdf0e10cSrcweir 							    // call VCL directly; encapsulate with SvtGraphicFill
1789cdf0e10cSrcweir                                 impStartSvtGraphicFill(pSvtGraphicFill);
1790cdf0e10cSrcweir 							    mpOutputDevice->DrawTransparent(
1791cdf0e10cSrcweir 								    PolyPolygon(aLocalPolyPolygon),
1792cdf0e10cSrcweir 								    nTransPercentVcl);
1793cdf0e10cSrcweir 							    impEndSvtGraphicFill(pSvtGraphicFill);
1794cdf0e10cSrcweir 						    }
1795cdf0e10cSrcweir 						    else
1796cdf0e10cSrcweir 						    {
1797cdf0e10cSrcweir 							    // svae old mfCurrentUnifiedTransparence and set new one
1798cdf0e10cSrcweir 							    // so that contained SvtGraphicStroke may use the current one
1799cdf0e10cSrcweir 							    const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
1800cdf0e10cSrcweir                                 // #i105377# paint the content metafile opaque as the transparency gets
1801cdf0e10cSrcweir                                 // split of into the gradient below
1802cdf0e10cSrcweir 							    // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence();
1803cdf0e10cSrcweir 							    mfCurrentUnifiedTransparence = 0;
1804cdf0e10cSrcweir 
1805cdf0e10cSrcweir 							    // various content, create content-metafile
1806cdf0e10cSrcweir 							    GDIMetaFile aContentMetafile;
1807cdf0e10cSrcweir                                 const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1808cdf0e10cSrcweir 
1809cdf0e10cSrcweir 							    // restore mfCurrentUnifiedTransparence; it may have been used
1810cdf0e10cSrcweir 							    // while processing the sub-content in impDumpToMetaFile
1811cdf0e10cSrcweir 							    mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
1812cdf0e10cSrcweir 
1813cdf0e10cSrcweir 							    // create uniform VCL gradient for uniform transparency
1814cdf0e10cSrcweir 							    Gradient aVCLGradient;
1815cdf0e10cSrcweir 							    const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0));
1816cdf0e10cSrcweir 							    const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
1817cdf0e10cSrcweir 
1818cdf0e10cSrcweir 							    aVCLGradient.SetStyle(GRADIENT_LINEAR);
1819cdf0e10cSrcweir 							    aVCLGradient.SetStartColor(aTransColor);
1820cdf0e10cSrcweir 							    aVCLGradient.SetEndColor(aTransColor);
1821cdf0e10cSrcweir 							    aVCLGradient.SetAngle(0);
1822cdf0e10cSrcweir 							    aVCLGradient.SetBorder(0);
1823cdf0e10cSrcweir 							    aVCLGradient.SetOfsX(0);
1824cdf0e10cSrcweir 							    aVCLGradient.SetOfsY(0);
1825cdf0e10cSrcweir 							    aVCLGradient.SetStartIntensity(100);
1826cdf0e10cSrcweir 							    aVCLGradient.SetEndIntensity(100);
1827cdf0e10cSrcweir 							    aVCLGradient.SetSteps(2);
1828cdf0e10cSrcweir 
1829cdf0e10cSrcweir 							    // render it to VCL
1830cdf0e10cSrcweir 							    mpOutputDevice->DrawTransparent(
1831cdf0e10cSrcweir 								    aContentMetafile, aPrimitiveRectangle.TopLeft(),
1832cdf0e10cSrcweir 								    aPrimitiveRectangle.GetSize(), aVCLGradient);
1833cdf0e10cSrcweir 						    }
1834cdf0e10cSrcweir 					    }
1835cdf0e10cSrcweir                     }
1836cdf0e10cSrcweir 
1837cdf0e10cSrcweir 					break;
1838cdf0e10cSrcweir 				}
1839cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
1840cdf0e10cSrcweir 				{
1841cdf0e10cSrcweir 					// for metafile: Need to examine what the pure vcl version is doing here actually
1842cdf0e10cSrcweir 					// - uses DrawTransparent with metafile for content and a gradient
1843cdf0e10cSrcweir 					// i can detect this here with checking the gradient part for a single
1844cdf0e10cSrcweir 					// FillGradientPrimitive2D and reconstruct the gradient.
1845cdf0e10cSrcweir 					// If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually
1846cdf0e10cSrcweir 					// do that in stripes, else RenderTransparencePrimitive2D may just be used
1847cdf0e10cSrcweir 					const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate);
1848cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren();
1849cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence();
1850cdf0e10cSrcweir 
1851cdf0e10cSrcweir 					if(rContent.hasElements() && rTransparence.hasElements())
1852cdf0e10cSrcweir 					{
1853cdf0e10cSrcweir 						// try to identify a single FillGradientPrimitive2D in the
1854cdf0e10cSrcweir 						// transparence part of the primitive
1855cdf0e10cSrcweir 						const primitive2d::FillGradientPrimitive2D* pFiGradient = 0;
1856cdf0e10cSrcweir 						static bool bForceToBigTransparentVDev(false);
1857cdf0e10cSrcweir 
1858cdf0e10cSrcweir 						if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength())
1859cdf0e10cSrcweir 						{
1860cdf0e10cSrcweir 							const primitive2d::Primitive2DReference xReference(rTransparence[0]);
1861cdf0e10cSrcweir 							pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
1862cdf0e10cSrcweir 						}
1863cdf0e10cSrcweir 
1864cdf0e10cSrcweir 						// Check also for correct ID to exclude derived implementations
1865cdf0e10cSrcweir 						if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
1866cdf0e10cSrcweir 						{
1867cdf0e10cSrcweir 							// various content, create content-metafile
1868cdf0e10cSrcweir 							GDIMetaFile aContentMetafile;
1869cdf0e10cSrcweir                             const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1870cdf0e10cSrcweir 
1871cdf0e10cSrcweir 							// re-create a VCL-gradient from FillGradientPrimitive2D
1872cdf0e10cSrcweir 							Gradient aVCLGradient;
1873cdf0e10cSrcweir                             impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
1874cdf0e10cSrcweir 
1875cdf0e10cSrcweir 							// render it to VCL
1876cdf0e10cSrcweir 							mpOutputDevice->DrawTransparent(
1877cdf0e10cSrcweir 								aContentMetafile, aPrimitiveRectangle.TopLeft(),
1878cdf0e10cSrcweir 								aPrimitiveRectangle.GetSize(), aVCLGradient);
1879cdf0e10cSrcweir                         }
1880cdf0e10cSrcweir                         else
1881cdf0e10cSrcweir                         {
1882cdf0e10cSrcweir 	    				    // sub-transparence group. Draw to VDev first.
1883cdf0e10cSrcweir                             // this may get refined to tiling when resolution is too big here
1884cdf0e10cSrcweir 
1885cdf0e10cSrcweir                             // need to avoid switching off MapMode stuff here; maybe need another
1886cdf0e10cSrcweir                             // tooling class, cannot just do the same as with the pixel renderer.
1887cdf0e10cSrcweir                             // Need to experiment...
1888cdf0e10cSrcweir 
1889cdf0e10cSrcweir                             // Okay, basic implementation finished and tested. The DPI stuff was hard
1890cdf0e10cSrcweir                             // and not easy to find out that it's needed.
1891cdf0e10cSrcweir                             // Since this will not yet happen normally (as long as noone constructs
1892cdf0e10cSrcweir                             // transparence primitives with non-trivial transparence content) i will for now not
1893cdf0e10cSrcweir                             // refine to tiling here.
1894cdf0e10cSrcweir 
1895cdf0e10cSrcweir 				            basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
1896cdf0e10cSrcweir 				            aViewRange.transform(maCurrentTransformation);
1897cdf0e10cSrcweir 		                    const Rectangle aRectLogic(
1898cdf0e10cSrcweir 			                    (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
1899cdf0e10cSrcweir 			                    (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
1900cdf0e10cSrcweir 		                    const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
1901cdf0e10cSrcweir                             const Size aSizePixel(aRectPixel.GetSize());
1902cdf0e10cSrcweir                     		const Point aEmptyPoint;
1903cdf0e10cSrcweir                             VirtualDevice aBufferDevice;
1904cdf0e10cSrcweir 
1905cdf0e10cSrcweir                             if(aBufferDevice.SetOutputSizePixel(aSizePixel))
1906cdf0e10cSrcweir                             {
1907cdf0e10cSrcweir                                 // create and set MapModes for target devices
1908cdf0e10cSrcweir 		                        MapMode aNewMapMode(mpOutputDevice->GetMapMode());
1909cdf0e10cSrcweir 		                        aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
1910cdf0e10cSrcweir 		                        aBufferDevice.SetMapMode(aNewMapMode);
1911cdf0e10cSrcweir 
1912cdf0e10cSrcweir                                 // prepare view transformation for target renderers
1913cdf0e10cSrcweir                                 // ATTENTION! Need to apply another scaling because of the potential DPI differences
1914cdf0e10cSrcweir                                 // between Printer and VDev (mpOutputDevice and aBufferDevice here).
1915cdf0e10cSrcweir                                 // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used.
1916cdf0e10cSrcweir                                 basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation());
1917cdf0e10cSrcweir                                 const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH));
1918cdf0e10cSrcweir                                 const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH));
1919cdf0e10cSrcweir                                 const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth());
1920cdf0e10cSrcweir                                 const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight());
1921cdf0e10cSrcweir 
1922cdf0e10cSrcweir                                 if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
1923cdf0e10cSrcweir                                 {
1924cdf0e10cSrcweir                                     aViewTransform.scale(fDPIXChange, fDPIYChange);
1925cdf0e10cSrcweir                                 }
1926cdf0e10cSrcweir 
1927cdf0e10cSrcweir                                 // create view information and pixel renderer. Reuse known ViewInformation
1928cdf0e10cSrcweir 								// except new transformation and range
1929cdf0e10cSrcweir                                 const geometry::ViewInformation2D aViewInfo(
1930cdf0e10cSrcweir 									getViewInformation2D().getObjectTransformation(),
1931cdf0e10cSrcweir 									aViewTransform,
1932cdf0e10cSrcweir 									aViewRange,
1933cdf0e10cSrcweir 									getViewInformation2D().getVisualizedPage(),
1934cdf0e10cSrcweir 									getViewInformation2D().getViewTime(),
1935cdf0e10cSrcweir 									getViewInformation2D().getExtendedInformationSequence());
1936cdf0e10cSrcweir 
1937cdf0e10cSrcweir 								VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice);
1938cdf0e10cSrcweir 
1939cdf0e10cSrcweir                                 // draw content using pixel renderer
1940cdf0e10cSrcweir 				                aBufferProcessor.process(rContent);
1941cdf0e10cSrcweir 	                            const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
1942cdf0e10cSrcweir 
1943cdf0e10cSrcweir                                 // draw transparence using pixel renderer
1944cdf0e10cSrcweir                                 aBufferDevice.Erase();
1945cdf0e10cSrcweir 				                aBufferProcessor.process(rTransparence);
1946cdf0e10cSrcweir                         		const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
1947cdf0e10cSrcweir 
1948cdf0e10cSrcweir #ifdef DBG_UTIL
1949cdf0e10cSrcweir                                 static bool bDoSaveForVisualControl(false);
1950cdf0e10cSrcweir 			                    if(bDoSaveForVisualControl)
1951cdf0e10cSrcweir 			                    {
1952cdf0e10cSrcweir 				                    SvFileStream aNew(String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
1953cdf0e10cSrcweir 				                    aNew << aBmContent;
1954cdf0e10cSrcweir 			                    }
1955cdf0e10cSrcweir #endif
1956cdf0e10cSrcweir 
1957cdf0e10cSrcweir                                 // paint
1958cdf0e10cSrcweir                                 mpOutputDevice->DrawBitmapEx(
1959cdf0e10cSrcweir                                     aRectLogic.TopLeft(),
1960cdf0e10cSrcweir                                     aRectLogic.GetSize(),
1961cdf0e10cSrcweir                                     BitmapEx(aBmContent, aBmAlpha));
1962cdf0e10cSrcweir                             }
1963cdf0e10cSrcweir                         }
1964cdf0e10cSrcweir                     }
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir 					break;
1967cdf0e10cSrcweir 				}
1968cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
1969cdf0e10cSrcweir 				{
1970cdf0e10cSrcweir 					// use default transform group pocessing
1971cdf0e10cSrcweir 					RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
1972cdf0e10cSrcweir 					break;
1973cdf0e10cSrcweir 				}
1974cdf0e10cSrcweir                 case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
1975cdf0e10cSrcweir 				{
1976cdf0e10cSrcweir 					// new XDrawPage for ViewInformation2D
1977cdf0e10cSrcweir 					RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
1978cdf0e10cSrcweir 					break;
1979cdf0e10cSrcweir 				}
1980cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
1981cdf0e10cSrcweir 				{
1982cdf0e10cSrcweir 					// use default marker array pocessing
1983cdf0e10cSrcweir 					RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
1984cdf0e10cSrcweir 					break;
1985cdf0e10cSrcweir 				}
1986cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
1987cdf0e10cSrcweir 				{
1988cdf0e10cSrcweir 					// use default point array pocessing
1989cdf0e10cSrcweir 					RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
1990cdf0e10cSrcweir 					break;
1991cdf0e10cSrcweir 				}
1992cdf0e10cSrcweir 				case PRIMITIVE2D_ID_CHARTPRIMITIVE2D :
1993cdf0e10cSrcweir 				{
1994cdf0e10cSrcweir 					// ChartPrimitive2D
1995cdf0e10cSrcweir 					const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate);
1996cdf0e10cSrcweir 
1997cdf0e10cSrcweir 					if(!renderChartPrimitive2D(
1998cdf0e10cSrcweir 						rChartPrimitive,
1999cdf0e10cSrcweir 						*mpOutputDevice,
2000cdf0e10cSrcweir 						getViewInformation2D()))
2001cdf0e10cSrcweir 					{
2002cdf0e10cSrcweir 						// fallback to decomposition (MetaFile)
2003cdf0e10cSrcweir 						process(rChartPrimitive.get2DDecomposition(getViewInformation2D()));
2004cdf0e10cSrcweir 					}
2005cdf0e10cSrcweir 					break;
2006cdf0e10cSrcweir 				}
2007cdf0e10cSrcweir 				case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
2008cdf0e10cSrcweir 				{
2009cdf0e10cSrcweir 					// structured tag primitive
2010cdf0e10cSrcweir 					const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
2011cdf0e10cSrcweir 					const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
2012cdf0e10cSrcweir 					const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
2013cdf0e10cSrcweir 
2014cdf0e10cSrcweir 					if(mpPDFExtOutDevData &&  bTagUsed)
2015cdf0e10cSrcweir 					{
2016cdf0e10cSrcweir 						// write start tag
2017cdf0e10cSrcweir 						mpPDFExtOutDevData->BeginStructureElement(rTagElement);
2018cdf0e10cSrcweir 					}
2019cdf0e10cSrcweir 
2020cdf0e10cSrcweir 					// proccess childs normally
2021cdf0e10cSrcweir 					process(rStructureTagCandidate.getChildren());
2022cdf0e10cSrcweir 
2023cdf0e10cSrcweir 					if(mpPDFExtOutDevData &&  bTagUsed)
2024cdf0e10cSrcweir 					{
2025cdf0e10cSrcweir 						// write end tag
2026cdf0e10cSrcweir 						mpPDFExtOutDevData->EndStructureElement();
2027cdf0e10cSrcweir 					}
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir 					break;
2030cdf0e10cSrcweir 				}
2031cdf0e10cSrcweir                 case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
2032cdf0e10cSrcweir                 {
2033cdf0e10cSrcweir 					RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
2034cdf0e10cSrcweir                     break;
2035cdf0e10cSrcweir                 }
2036cdf0e10cSrcweir 				default :
2037cdf0e10cSrcweir 				{
2038cdf0e10cSrcweir                     // process recursively
2039cdf0e10cSrcweir 					process(rCandidate.get2DDecomposition(getViewInformation2D()));
2040cdf0e10cSrcweir 					break;
2041cdf0e10cSrcweir 				}
2042cdf0e10cSrcweir 			}
2043cdf0e10cSrcweir 		}
2044cdf0e10cSrcweir 	} // end of namespace processor2d
2045cdf0e10cSrcweir } // end of namespace drawinglayer
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
2048cdf0e10cSrcweir // eof
2049