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