1464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5464702f4SAndrew Rist  * distributed with this work for additional information
6464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10464702f4SAndrew Rist  *
11464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12464702f4SAndrew Rist  *
13464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14464702f4SAndrew Rist  * software distributed under the License is distributed on an
15464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17464702f4SAndrew Rist  * specific language governing permissions and limitations
18464702f4SAndrew Rist  * under the License.
19464702f4SAndrew Rist  *
20464702f4SAndrew Rist  *************************************************************/
21464702f4SAndrew Rist 
22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
23cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
24cdf0e10cSrcweir 
25cdf0e10cSrcweir #include <drawinglayer/processor2d/vclmetafileprocessor2d.hxx>
26cdf0e10cSrcweir #include <tools/gen.hxx>
27cdf0e10cSrcweir #include <vcl/virdev.hxx>
28cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
29cdf0e10cSrcweir #include <vcl/gradient.hxx>
30cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
31cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx>
32cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
33cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
34cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
35cdf0e10cSrcweir #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
36cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx>
37cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
38cdf0e10cSrcweir #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
39cdf0e10cSrcweir #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
40cdf0e10cSrcweir #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
41cdf0e10cSrcweir #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
42cdf0e10cSrcweir #include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
43cdf0e10cSrcweir #include <tools/stream.hxx>
44cdf0e10cSrcweir #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
45cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
46cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
47cdf0e10cSrcweir #include <vcl/graphictools.hxx>
48cdf0e10cSrcweir #include <vcl/metaact.hxx>
49cdf0e10cSrcweir #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
50cdf0e10cSrcweir #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
51cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
52cdf0e10cSrcweir #include <rtl/ustring.hxx>
53cdf0e10cSrcweir #include <com/sun/star/i18n/CharacterIteratorMode.hdl>
54cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
55cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
56cdf0e10cSrcweir #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
57cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
58cdf0e10cSrcweir #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
59cdf0e10cSrcweir #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
60cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx>
61*45fd3b9aSArmin Le Grand #include <vcl/dibtools.hxx>
62cdf0e10cSrcweir 
63cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
64cdf0e10cSrcweir // for PDFExtOutDevData Graphic support
65cdf0e10cSrcweir 
66cdf0e10cSrcweir #include <vcl/graph.hxx>
67cdf0e10cSrcweir #include <vcl/svapp.hxx>
68cdf0e10cSrcweir #include <toolkit/helper/formpdfexport.hxx>
69cdf0e10cSrcweir 
70cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
71cdf0e10cSrcweir // for Control printing
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
74cdf0e10cSrcweir 
75cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
76cdf0e10cSrcweir // for StructureTagPrimitive support in sd's unomodel.cxx
77cdf0e10cSrcweir 
78cdf0e10cSrcweir #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
79cdf0e10cSrcweir 
80cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
81cdf0e10cSrcweir 
82cdf0e10cSrcweir using namespace com::sun::star;
83cdf0e10cSrcweir 
84cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
85cdf0e10cSrcweir // #112245# definition for maximum allowed point count due to Metafile target.
86cdf0e10cSrcweir // To be on the safe side with the old tools polygon, use slightly less then
87cdf0e10cSrcweir // the theoretical maximum (bad experiences with tools polygon)
88cdf0e10cSrcweir 
89cdf0e10cSrcweir #define MAX_POLYGON_POINT_COUNT_METAFILE    (0x0000fff0)
90cdf0e10cSrcweir 
91cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
92cdf0e10cSrcweir 
93cdf0e10cSrcweir namespace
94cdf0e10cSrcweir {
95cdf0e10cSrcweir     // #112245# helper to split line polygon in half
96cdf0e10cSrcweir     void splitLinePolygon(
97cdf0e10cSrcweir         const basegfx::B2DPolygon& rBasePolygon,
98cdf0e10cSrcweir         basegfx::B2DPolygon& o_aLeft,
99cdf0e10cSrcweir         basegfx::B2DPolygon& o_aRight)
100cdf0e10cSrcweir     {
101cdf0e10cSrcweir         const sal_uInt32 nCount(rBasePolygon.count());
102cdf0e10cSrcweir 
103cdf0e10cSrcweir         if(nCount)
104cdf0e10cSrcweir         {
105cdf0e10cSrcweir             const sal_uInt32 nHalfCount((nCount - 1) >> 1);
106cdf0e10cSrcweir 
107cdf0e10cSrcweir             o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
108cdf0e10cSrcweir             o_aLeft.setClosed(false);
109cdf0e10cSrcweir 
110cdf0e10cSrcweir             o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
111cdf0e10cSrcweir             o_aRight.setClosed(false);
112cdf0e10cSrcweir 
113cdf0e10cSrcweir             if(rBasePolygon.isClosed())
114cdf0e10cSrcweir             {
115cdf0e10cSrcweir                 o_aRight.append(rBasePolygon.getB2DPoint(0));
116cdf0e10cSrcweir 
117cdf0e10cSrcweir                 if(rBasePolygon.areControlPointsUsed())
118cdf0e10cSrcweir                 {
119cdf0e10cSrcweir                     o_aRight.setControlPoints(
120cdf0e10cSrcweir                         o_aRight.count() - 1,
121cdf0e10cSrcweir                         rBasePolygon.getPrevControlPoint(0),
122cdf0e10cSrcweir                         rBasePolygon.getNextControlPoint(0));
123cdf0e10cSrcweir                 }
124cdf0e10cSrcweir             }
125cdf0e10cSrcweir         }
126cdf0e10cSrcweir         else
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             o_aLeft.clear();
129cdf0e10cSrcweir             o_aRight.clear();
130cdf0e10cSrcweir         }
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     // #112245# helper to evtl. split filled polygons to maximum metafile point count
134cdf0e10cSrcweir     bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
135cdf0e10cSrcweir     {
136cdf0e10cSrcweir         bool bRetval(false);
137cdf0e10cSrcweir         const sal_uInt32 nPolyCount(rPolyPolygon.count());
138cdf0e10cSrcweir 
139cdf0e10cSrcweir         if(nPolyCount)
140cdf0e10cSrcweir         {
141cdf0e10cSrcweir             basegfx::B2DPolyPolygon aSplitted;
142cdf0e10cSrcweir 
143cdf0e10cSrcweir             for(sal_uInt32 a(0); a < nPolyCount; a++)
144cdf0e10cSrcweir             {
145cdf0e10cSrcweir                 const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
146cdf0e10cSrcweir                 const sal_uInt32 nPointCount(aCandidate.count());
147cdf0e10cSrcweir                 bool bNeedToSplit(false);
148cdf0e10cSrcweir 
149cdf0e10cSrcweir                 if(aCandidate.areControlPointsUsed())
150cdf0e10cSrcweir                 {
151cdf0e10cSrcweir                     // compare with the maximum for bezier curved polygons
152cdf0e10cSrcweir             		bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L);
153cdf0e10cSrcweir                 }
154cdf0e10cSrcweir                 else
155cdf0e10cSrcweir                 {
156cdf0e10cSrcweir                     // compare with the maximum for simple point polygons
157cdf0e10cSrcweir                     bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
158cdf0e10cSrcweir                 }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir                 if(bNeedToSplit)
161cdf0e10cSrcweir                 {
162cdf0e10cSrcweir                     // need to split the partial polygon
163cdf0e10cSrcweir                     const basegfx::B2DRange aRange(aCandidate.getB2DRange());
164cdf0e10cSrcweir             		const basegfx::B2DPoint aCenter(aRange.getCenter());
165cdf0e10cSrcweir 
166cdf0e10cSrcweir                     if(aRange.getWidth() > aRange.getHeight())
167cdf0e10cSrcweir                     {
168cdf0e10cSrcweir                         // clip in left and right
169cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aLeft(
170cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
171cdf0e10cSrcweir                                 aCandidate,
172cdf0e10cSrcweir                                 false,
173cdf0e10cSrcweir                                 true,
174cdf0e10cSrcweir                                 aCenter.getX(),
175cdf0e10cSrcweir                                 false));
176cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aRight(
177cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
178cdf0e10cSrcweir                                 aCandidate,
179cdf0e10cSrcweir                                 false,
180cdf0e10cSrcweir                                 false,
181cdf0e10cSrcweir                                 aCenter.getX(),
182cdf0e10cSrcweir                                 false));
183cdf0e10cSrcweir 
184cdf0e10cSrcweir                         aSplitted.append(aLeft);
185cdf0e10cSrcweir                         aSplitted.append(aRight);
186cdf0e10cSrcweir                     }
187cdf0e10cSrcweir                     else
188cdf0e10cSrcweir                     {
189cdf0e10cSrcweir                         // clip in top and bottom
190cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aTop(
191cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
192cdf0e10cSrcweir                                 aCandidate,
193cdf0e10cSrcweir                                 true,
194cdf0e10cSrcweir                                 true,
195cdf0e10cSrcweir                                 aCenter.getY(),
196cdf0e10cSrcweir                                 false));
197cdf0e10cSrcweir                         const basegfx::B2DPolyPolygon aBottom(
198cdf0e10cSrcweir                             basegfx::tools::clipPolygonOnParallelAxis(
199cdf0e10cSrcweir                                 aCandidate,
200cdf0e10cSrcweir                                 true,
201cdf0e10cSrcweir                                 false,
202cdf0e10cSrcweir                                 aCenter.getY(),
203cdf0e10cSrcweir                                 false));
204cdf0e10cSrcweir 
205cdf0e10cSrcweir                         aSplitted.append(aTop);
206cdf0e10cSrcweir                         aSplitted.append(aBottom);
207cdf0e10cSrcweir                     }
208cdf0e10cSrcweir                 }
209cdf0e10cSrcweir                 else
210cdf0e10cSrcweir                 {
211cdf0e10cSrcweir                     aSplitted.append(aCandidate);
212cdf0e10cSrcweir                 }
213cdf0e10cSrcweir             }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir             if(aSplitted.count() != nPolyCount)
216cdf0e10cSrcweir             {
217cdf0e10cSrcweir                 rPolyPolygon = aSplitted;
218cdf0e10cSrcweir             }
219cdf0e10cSrcweir         }
220cdf0e10cSrcweir 
221cdf0e10cSrcweir         return bRetval;
222cdf0e10cSrcweir     }
223cdf0e10cSrcweir } // end of anonymous namespace
224cdf0e10cSrcweir 
225cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
226cdf0e10cSrcweir 
227cdf0e10cSrcweir namespace drawinglayer
228cdf0e10cSrcweir {
229cdf0e10cSrcweir 	namespace processor2d
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir         Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
232cdf0e10cSrcweir 			const primitive2d::Primitive2DSequence& rContent,
233cdf0e10cSrcweir 			GDIMetaFile& o_rContentMetafile)
234cdf0e10cSrcweir         {
235cdf0e10cSrcweir             // Prepare VDev, MetaFile and connections
236cdf0e10cSrcweir 			OutputDevice* pLastOutputDevice = mpOutputDevice;
237cdf0e10cSrcweir             GDIMetaFile* pLastMetafile = mpMetaFile;
238cdf0e10cSrcweir 			basegfx::B2DRange aPrimitiveRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
239cdf0e10cSrcweir 
240cdf0e10cSrcweir 			// transform primitive range with current transformation (e.g shadow offset)
241cdf0e10cSrcweir 			aPrimitiveRange.transform(maCurrentTransformation);
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 			const Rectangle aPrimitiveRectangle(
244cdf0e10cSrcweir 				basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
245cdf0e10cSrcweir 				basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
246cdf0e10cSrcweir 			VirtualDevice aContentVDev;
247cdf0e10cSrcweir 			MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 			mpOutputDevice = &aContentVDev;
250cdf0e10cSrcweir             mpMetaFile = &o_rContentMetafile;
251cdf0e10cSrcweir 			aContentVDev.EnableOutput(false);
252cdf0e10cSrcweir 			aContentVDev.SetMapMode(pLastOutputDevice->GetMapMode());
253cdf0e10cSrcweir 			o_rContentMetafile.Record(&aContentVDev);
254cdf0e10cSrcweir 			aContentVDev.SetLineColor(pLastOutputDevice->GetLineColor());
255cdf0e10cSrcweir 			aContentVDev.SetFillColor(pLastOutputDevice->GetFillColor());
256cdf0e10cSrcweir 			aContentVDev.SetFont(pLastOutputDevice->GetFont());
257cdf0e10cSrcweir 			aContentVDev.SetDrawMode(pLastOutputDevice->GetDrawMode());
258cdf0e10cSrcweir 			aContentVDev.SetSettings(pLastOutputDevice->GetSettings());
259cdf0e10cSrcweir 			aContentVDev.SetRefPoint(pLastOutputDevice->GetRefPoint());
260cdf0e10cSrcweir 
261cdf0e10cSrcweir             // dump to MetaFile
262cdf0e10cSrcweir 			process(rContent);
263cdf0e10cSrcweir 
264cdf0e10cSrcweir             // cleanups
265cdf0e10cSrcweir 			o_rContentMetafile.Stop();
266cdf0e10cSrcweir 			o_rContentMetafile.WindStart();
267cdf0e10cSrcweir 			aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
268cdf0e10cSrcweir 			o_rContentMetafile.SetPrefMapMode(aNewMapMode);
269cdf0e10cSrcweir 			o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
270cdf0e10cSrcweir 			mpOutputDevice = pLastOutputDevice;
271cdf0e10cSrcweir             mpMetaFile = pLastMetafile;
272cdf0e10cSrcweir 
273cdf0e10cSrcweir             return aPrimitiveRectangle;
274cdf0e10cSrcweir         }
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 		void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
277cdf0e10cSrcweir 			Gradient& o_rVCLGradient,
278cdf0e10cSrcweir 			const attribute::FillGradientAttribute& rFiGrAtt,
279cdf0e10cSrcweir 			bool bIsTransparenceGradient)
280cdf0e10cSrcweir         {
281cdf0e10cSrcweir 			if(bIsTransparenceGradient)
282cdf0e10cSrcweir 			{
283cdf0e10cSrcweir 				// it's about transparence channel intensities (black/white), do not use color modifier
284cdf0e10cSrcweir 			    o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
285cdf0e10cSrcweir 			    o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
286cdf0e10cSrcweir 			}
287cdf0e10cSrcweir 			else
288cdf0e10cSrcweir 			{
289cdf0e10cSrcweir 				// use color modifier to influence start/end color of gradient
290cdf0e10cSrcweir 			    o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
291cdf0e10cSrcweir 			    o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
292cdf0e10cSrcweir 			}
293cdf0e10cSrcweir 
294cdf0e10cSrcweir             o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
295cdf0e10cSrcweir             o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
296cdf0e10cSrcweir 		    o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
297cdf0e10cSrcweir 		    o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
298cdf0e10cSrcweir 		    o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
299cdf0e10cSrcweir 
300cdf0e10cSrcweir             // defaults for intensity; those were computed into the start/end colors already
301cdf0e10cSrcweir 		    o_rVCLGradient.SetStartIntensity(100);
302cdf0e10cSrcweir 		    o_rVCLGradient.SetEndIntensity(100);
303cdf0e10cSrcweir 
304cdf0e10cSrcweir             switch(rFiGrAtt.getStyle())
305cdf0e10cSrcweir             {
306cdf0e10cSrcweir                 default : // attribute::GRADIENTSTYLE_LINEAR :
307cdf0e10cSrcweir                 {
308cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_LINEAR);
309cdf0e10cSrcweir                     break;
310cdf0e10cSrcweir                 }
311cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_AXIAL :
312cdf0e10cSrcweir                 {
313cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_AXIAL);
314cdf0e10cSrcweir                     break;
315cdf0e10cSrcweir                 }
316cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_RADIAL :
317cdf0e10cSrcweir                 {
318cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_RADIAL);
319cdf0e10cSrcweir                     break;
320cdf0e10cSrcweir                 }
321cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_ELLIPTICAL :
322cdf0e10cSrcweir                 {
323cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_ELLIPTICAL);
324cdf0e10cSrcweir                     break;
325cdf0e10cSrcweir                 }
326cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_SQUARE :
327cdf0e10cSrcweir                 {
328cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_SQUARE);
329cdf0e10cSrcweir                     break;
330cdf0e10cSrcweir                 }
331cdf0e10cSrcweir                 case attribute::GRADIENTSTYLE_RECT :
332cdf0e10cSrcweir                 {
333cdf0e10cSrcweir                     o_rVCLGradient.SetStyle(GRADIENT_RECT);
334cdf0e10cSrcweir                     break;
335cdf0e10cSrcweir                 }
336cdf0e10cSrcweir             }
337cdf0e10cSrcweir         }
338cdf0e10cSrcweir 
339cdf0e10cSrcweir 		void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
340cdf0e10cSrcweir 		{
341cdf0e10cSrcweir 			if(pSvtGraphicFill && !mnSvtGraphicFillCount)
342cdf0e10cSrcweir 			{
343cdf0e10cSrcweir 				SvMemoryStream aMemStm;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 				aMemStm << *pSvtGraphicFill;
346cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
347cdf0e10cSrcweir 				mnSvtGraphicFillCount++;
348cdf0e10cSrcweir 			}
349cdf0e10cSrcweir 		}
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 		void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill* pSvtGraphicFill)
352cdf0e10cSrcweir 		{
353cdf0e10cSrcweir 			if(pSvtGraphicFill && mnSvtGraphicFillCount)
354cdf0e10cSrcweir 			{
355cdf0e10cSrcweir 				mnSvtGraphicFillCount--;
356cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
357cdf0e10cSrcweir 				delete pSvtGraphicFill;
358cdf0e10cSrcweir 			}
359cdf0e10cSrcweir 		}
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 		SvtGraphicStroke* VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
362cdf0e10cSrcweir 			const basegfx::B2DPolygon& rB2DPolygon,
363cdf0e10cSrcweir 			const basegfx::BColor* pColor,
364cdf0e10cSrcweir 			const attribute::LineAttribute* pLineAttribute,
365cdf0e10cSrcweir 			const attribute::StrokeAttribute* pStrokeAttribute,
366cdf0e10cSrcweir 			const attribute::LineStartEndAttribute* pStart,
367cdf0e10cSrcweir 			const attribute::LineStartEndAttribute* pEnd)
368cdf0e10cSrcweir 		{
369cdf0e10cSrcweir 			SvtGraphicStroke* pRetval = 0;
370cdf0e10cSrcweir 
371cdf0e10cSrcweir 			if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
372cdf0e10cSrcweir 			{
373cdf0e10cSrcweir 				basegfx::BColor aStrokeColor;
374cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aStartArrow;
375cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aEndArrow;
376cdf0e10cSrcweir 
377cdf0e10cSrcweir 				if(pColor)
378cdf0e10cSrcweir 				{
379cdf0e10cSrcweir 					aStrokeColor = *pColor;
380cdf0e10cSrcweir 				}
381cdf0e10cSrcweir 				else if(pLineAttribute)
382cdf0e10cSrcweir 				{
383cdf0e10cSrcweir 					aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
384cdf0e10cSrcweir 				}
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 				// It IS needed to record the stroke color at all in the metafile,
387cdf0e10cSrcweir 				// SvtGraphicStroke has NO entry for stroke color(!)
388cdf0e10cSrcweir 				mpOutputDevice->SetLineColor(Color(aStrokeColor));
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 				if(!rB2DPolygon.isClosed())
391cdf0e10cSrcweir 				{
392cdf0e10cSrcweir 					double fPolyLength(0.0);
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 					if(pStart && pStart->isActive())
395cdf0e10cSrcweir 					{
396cdf0e10cSrcweir 						fPolyLength = basegfx::tools::getLength(rB2DPolygon);
397cdf0e10cSrcweir 
398cdf0e10cSrcweir 						aStartArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
399cdf0e10cSrcweir 							rB2DPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
400cdf0e10cSrcweir 							fPolyLength, pStart->isCentered() ? 0.5 : 0.0, 0);
401cdf0e10cSrcweir 					}
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 					if(pEnd && pEnd->isActive())
404cdf0e10cSrcweir 					{
405cdf0e10cSrcweir 						if(basegfx::fTools::equalZero(fPolyLength))
406cdf0e10cSrcweir 						{
407cdf0e10cSrcweir 							fPolyLength = basegfx::tools::getLength(rB2DPolygon);
408cdf0e10cSrcweir 						}
409cdf0e10cSrcweir 
410cdf0e10cSrcweir 						aEndArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
411cdf0e10cSrcweir 							rB2DPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
412cdf0e10cSrcweir 							fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, 0);
413cdf0e10cSrcweir 					}
414cdf0e10cSrcweir 				}
415cdf0e10cSrcweir 
4165aaf853bSArmin Le Grand                 SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
4175aaf853bSArmin Le Grand                 SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt);
418cdf0e10cSrcweir 				double fLineWidth(0.0);
419cdf0e10cSrcweir 				double fMiterLength(0.0);
420cdf0e10cSrcweir 				SvtGraphicStroke::DashArray aDashArray;
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 				if(pLineAttribute)
423cdf0e10cSrcweir 				{
424b22f5784SArmin Le Grand 					// pre-fill fLineWidth #119198# Need to apply maCurrentTransformation, too (!)
425b22f5784SArmin Le Grand 					const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(pLineAttribute->getWidth(), 0.0));
426b22f5784SArmin Le Grand 					fLineWidth = aDiscreteUnit.getLength();
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 					// pre-fill fMiterLength
429cdf0e10cSrcweir 					fMiterLength = fLineWidth;
430cdf0e10cSrcweir 
431cdf0e10cSrcweir 					// get Join
432cdf0e10cSrcweir 					switch(pLineAttribute->getLineJoin())
433cdf0e10cSrcweir 					{
434cdf0e10cSrcweir 						default : // basegfx::B2DLINEJOIN_NONE :
435cdf0e10cSrcweir 						{
436cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinNone;
437cdf0e10cSrcweir 							break;
438cdf0e10cSrcweir 						}
439cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_BEVEL :
440cdf0e10cSrcweir 						{
441cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinBevel;
442cdf0e10cSrcweir 							break;
443cdf0e10cSrcweir 						}
444cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_MIDDLE :
445cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_MITER :
446cdf0e10cSrcweir 						{
447cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinMiter;
448cdf0e10cSrcweir 							// ATM 15 degrees is assumed
449cdf0e10cSrcweir 							fMiterLength /= rtl::math::sin(M_PI * (15.0 / 360.0));
450cdf0e10cSrcweir 							break;
451cdf0e10cSrcweir 						}
452cdf0e10cSrcweir 						case basegfx::B2DLINEJOIN_ROUND :
453cdf0e10cSrcweir 						{
454cdf0e10cSrcweir 							eJoin = SvtGraphicStroke::joinRound;
455cdf0e10cSrcweir 							break;
456cdf0e10cSrcweir 						}
457cdf0e10cSrcweir 					}
4585aaf853bSArmin Le Grand 
4595aaf853bSArmin Le Grand                     // get stroke
4605aaf853bSArmin Le Grand                     switch(pLineAttribute->getLineCap())
4615aaf853bSArmin Le Grand                     {
4625aaf853bSArmin Le Grand                         default: /* com::sun::star::drawing::LineCap_BUTT */
4635aaf853bSArmin Le Grand                         {
4645aaf853bSArmin Le Grand                             eCap = SvtGraphicStroke::capButt;
4655aaf853bSArmin Le Grand                             break;
4665aaf853bSArmin Le Grand                         }
4675aaf853bSArmin Le Grand                         case com::sun::star::drawing::LineCap_ROUND:
4685aaf853bSArmin Le Grand                         {
4695aaf853bSArmin Le Grand                             eCap = SvtGraphicStroke::capRound;
4705aaf853bSArmin Le Grand                             break;
4715aaf853bSArmin Le Grand                         }
4725aaf853bSArmin Le Grand                         case com::sun::star::drawing::LineCap_SQUARE:
4735aaf853bSArmin Le Grand                         {
4745aaf853bSArmin Le Grand                             eCap = SvtGraphicStroke::capSquare;
4755aaf853bSArmin Le Grand                             break;
4765aaf853bSArmin Le Grand                         }
4775aaf853bSArmin Le Grand                     }
478cdf0e10cSrcweir                 }
479cdf0e10cSrcweir 
480cdf0e10cSrcweir 				if(pStrokeAttribute)
481cdf0e10cSrcweir 				{
482cdf0e10cSrcweir 					// copy dash array
483cdf0e10cSrcweir 					aDashArray = pStrokeAttribute->getDotDashArray();
484cdf0e10cSrcweir 				}
485cdf0e10cSrcweir 
486cdf0e10cSrcweir 				// #i101734# apply current object transformation to created geometry.
487cdf0e10cSrcweir 				// This is a partial fix. When a object transformation is used which
488cdf0e10cSrcweir 				// e.g. contains a scaleX != scaleY, an unproportional scaling would
489cdf0e10cSrcweir 				// have to be applied to the evtl. existing fat line. The current
490cdf0e10cSrcweir 				// concept of PDF export and SvtGraphicStroke usage does simply not
491cdf0e10cSrcweir 				// allow handling such definitions. The only clean way would be to
492cdf0e10cSrcweir 				// add the transformation to SvtGraphicStroke and to handle it there
493cdf0e10cSrcweir 				basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 				aB2DPolygon.transform(maCurrentTransformation);
496cdf0e10cSrcweir 				aStartArrow.transform(maCurrentTransformation);
497cdf0e10cSrcweir 				aEndArrow.transform(maCurrentTransformation);
498cdf0e10cSrcweir 
499cdf0e10cSrcweir 				pRetval = new SvtGraphicStroke(
500cdf0e10cSrcweir 					Polygon(aB2DPolygon),
501cdf0e10cSrcweir 					PolyPolygon(aStartArrow),
502cdf0e10cSrcweir 					PolyPolygon(aEndArrow),
503cdf0e10cSrcweir 					mfCurrentUnifiedTransparence,
504cdf0e10cSrcweir 					fLineWidth,
5055aaf853bSArmin Le Grand 					eCap,
506cdf0e10cSrcweir 					eJoin,
507cdf0e10cSrcweir 					fMiterLength,
508cdf0e10cSrcweir 					aDashArray);
509cdf0e10cSrcweir 			}
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 			return pRetval;
512cdf0e10cSrcweir 		}
513cdf0e10cSrcweir 
514cdf0e10cSrcweir 		void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
515cdf0e10cSrcweir 		{
516cdf0e10cSrcweir 			if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
517cdf0e10cSrcweir 			{
518cdf0e10cSrcweir 				SvMemoryStream aMemStm;
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 				aMemStm << *pSvtGraphicStroke;
521cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.Seek(STREAM_SEEK_TO_END)));
522cdf0e10cSrcweir 				mnSvtGraphicStrokeCount++;
523cdf0e10cSrcweir 			}
524cdf0e10cSrcweir 		}
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 		void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke* pSvtGraphicStroke)
527cdf0e10cSrcweir 		{
528cdf0e10cSrcweir 			if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
529cdf0e10cSrcweir 			{
530cdf0e10cSrcweir 				mnSvtGraphicStrokeCount--;
531cdf0e10cSrcweir 				mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
532cdf0e10cSrcweir 				delete pSvtGraphicStroke;
533cdf0e10cSrcweir 			}
534cdf0e10cSrcweir 		}
535cdf0e10cSrcweir 
536cdf0e10cSrcweir         // init static break iterator
537cdf0e10cSrcweir         uno::Reference< ::com::sun::star::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
538cdf0e10cSrcweir 
539cdf0e10cSrcweir 		VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
540cdf0e10cSrcweir 		:	VclProcessor2D(rViewInformation, rOutDev),
541cdf0e10cSrcweir 			mpMetaFile(rOutDev.GetConnectMetaFile()),
542cdf0e10cSrcweir 			mnSvtGraphicFillCount(0),
543cdf0e10cSrcweir 			mnSvtGraphicStrokeCount(0),
544cdf0e10cSrcweir 			mfCurrentUnifiedTransparence(0.0),
545cdf0e10cSrcweir 			mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData()))
546cdf0e10cSrcweir 		{
547cdf0e10cSrcweir 			OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
548cdf0e10cSrcweir 			// draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
549cdf0e10cSrcweir             // but only to ObjectTransformation. Do not change MapMode of destination.
550cdf0e10cSrcweir 			maCurrentTransformation = rViewInformation.getObjectTransformation();
551cdf0e10cSrcweir 		}
552cdf0e10cSrcweir 
553cdf0e10cSrcweir 		VclMetafileProcessor2D::~VclMetafileProcessor2D()
554cdf0e10cSrcweir 		{
555cdf0e10cSrcweir 			// MapMode was not changed, no restore necessary
556cdf0e10cSrcweir 		}
557cdf0e10cSrcweir 
558cdf0e10cSrcweir         /***********************************************************************************************
559cdf0e10cSrcweir 
560cdf0e10cSrcweir             Support of MetaCommentActions in the VclMetafileProcessor2D
561cdf0e10cSrcweir             Found MetaCommentActions and how they are supported:
562cdf0e10cSrcweir 
563cdf0e10cSrcweir             XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 			Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
566cdf0e10cSrcweir             It is used in various exporters/importers to have direct access to the gradient before it
567cdf0e10cSrcweir             is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
568cdf0e10cSrcweir             the Metafile to SdrObject import creates it's gradient objects.
569cdf0e10cSrcweir             Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
570cdf0e10cSrcweir             map it back to the corresponding tools PolyPolygon and the Gradient and just call
571cdf0e10cSrcweir             OutputDevice::DrawGradient which creates the necessary compatible actions.
572cdf0e10cSrcweir 
573cdf0e10cSrcweir             XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
574cdf0e10cSrcweir 
575cdf0e10cSrcweir 			Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
576cdf0e10cSrcweir             inside GDIMetaFile::Rotate, nothing to take care of here.
577cdf0e10cSrcweir             The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
578cdf0e10cSrcweir             with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
579cdf0e10cSrcweir             XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
580cdf0e10cSrcweir             to the comment action. A closing end token is created in the destructor.
581cdf0e10cSrcweir 			Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
582cdf0e10cSrcweir 			SdrRectObj.
583cdf0e10cSrcweir             The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
584cdf0e10cSrcweir             of filled objects, even simple colored polygons. It is added as extra information; the
585cdf0e10cSrcweir             Metafile actions between the two tokens are interpreted as output generated from those
586cdf0e10cSrcweir             fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
587cdf0e10cSrcweir             actions.
588cdf0e10cSrcweir             Even for XFillTransparenceItem it is used, thus it may need to be supported in
589cdf0e10cSrcweir             UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
590cdf0e10cSrcweir 			Implemented for:
591035a2f44SArmin Le Grand 				PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D,
592cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
593cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
594cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
595cdf0e10cSrcweir 				and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
596cdf0e10cSrcweir 
597cdf0e10cSrcweir             XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
598cdf0e10cSrcweir 
599cdf0e10cSrcweir 			Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
600cdf0e10cSrcweir 			is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
601cdf0e10cSrcweir 			contained path accordingly.
602cdf0e10cSrcweir 			The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
603cdf0e10cSrcweir 			only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
604cdf0e10cSrcweir 			would hinder to make use of PolyPolygon strokes. I will need to add support at:
605cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
606cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
607cdf0e10cSrcweir 				PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
608cdf0e10cSrcweir 			This can be done hierarchical, too.
609cdf0e10cSrcweir 			Okay, base implementation done based on those three primitives.
610cdf0e10cSrcweir 
611cdf0e10cSrcweir             FIELD_SEQ_BEGIN, FIELD_SEQ_END
612cdf0e10cSrcweir 
613cdf0e10cSrcweir             Used from slideshow for URLs, created from diverse SvxField implementations inside
614cdf0e10cSrcweir             createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
615cdf0e10cSrcweir             inside ImpEditEngine::Paint.
616cdf0e10cSrcweir             Created TextHierarchyFieldPrimitive2D and added needed infos there; it is an group primitive and wraps
617cdf0e10cSrcweir             text primitives (but is not limited to that). It contains the field type if special actions for the
618cdf0e10cSrcweir 			support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
619cdf0e10cSrcweir 			needed, it may be supported there.
620cdf0e10cSrcweir             FIELD_SEQ_BEGIN;PageField
621cdf0e10cSrcweir             FIELD_SEQ_END
622cdf0e10cSrcweir             Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
623cdf0e10cSrcweir 
624cdf0e10cSrcweir             XTEXT
625cdf0e10cSrcweir 
626cdf0e10cSrcweir             XTEXT_EOC(i) end of character
627cdf0e10cSrcweir             XTEXT_EOW(i) end of word
628cdf0e10cSrcweir             XTEXT_EOS(i) end of sentence
629cdf0e10cSrcweir 
630cdf0e10cSrcweir             this three are with index and are created with the help of a i18n::XBreakIterator in
631cdf0e10cSrcweir             ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
632cdf0e10cSrcweir             data structure for holding those TEXT infos.
633cdf0e10cSrcweir             Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
634cdf0e10cSrcweir             primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
635cdf0e10cSrcweir             that this creations do not need to be done for all paints all the time. This would be
636cdf0e10cSrcweir             expensive since the BreakIterator and it's usage is expensive and for each paint also the
637cdf0e10cSrcweir             whole character stops would need to be created.
638cdf0e10cSrcweir             Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
639cdf0e10cSrcweir 
640cdf0e10cSrcweir             XTEXT_EOL() end of line
641cdf0e10cSrcweir             XTEXT_EOP() end of paragraph
642cdf0e10cSrcweir 
643cdf0e10cSrcweir             First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
644cdf0e10cSrcweir 			i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
645cdf0e10cSrcweir 			namely:
646cdf0e10cSrcweir 			- TextHierarchyLinePrimitive2D: Encapsulates single line
647cdf0e10cSrcweir 			- TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
648cdf0e10cSrcweir 			- TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
649cdf0e10cSrcweir 			Those are now supported in hierarchy. This means the MetaFile renderer will support them
650cdf0e10cSrcweir 			by using them, reculrively using their content and adding MetaFile comments as needed.
651cdf0e10cSrcweir 			This also means that when another text layouter will be used it will be necessary to
652cdf0e10cSrcweir 			create/support the same HierarchyPrimitives to support users.
653cdf0e10cSrcweir 			To transport the information using this hierarchy is best suited to all future needs;
654cdf0e10cSrcweir 			the slideshow will be able to profit from it directly when using primitives; all other
655cdf0e10cSrcweir 			renderers not interested in the text structure will just ignore the encapsulations.
656cdf0e10cSrcweir 
657cdf0e10cSrcweir             XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
658cdf0e10cSrcweir 			Supported now by the TextHierarchyBlockPrimitive2D.
659cdf0e10cSrcweir 
660cdf0e10cSrcweir             EPSReplacementGraphic:
661cdf0e10cSrcweir 			Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
662cdf0e10cSrcweir 			hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
663cdf0e10cSrcweir 			used to export the original again (if exists).
664cdf0e10cSrcweir 			Not necessary to support with MetaFuleRenderer.
665cdf0e10cSrcweir 
666cdf0e10cSrcweir             XTEXT_SCROLLRECT, XTEXT_PAINTRECT
667cdf0e10cSrcweir 			Currently used to get extra MetaFile infos using GraphicExporter which again uses
668cdf0e10cSrcweir 			SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
669cdf0e10cSrcweir 			the rectangle data is added directly by the GraphicsExporter as comment. Does not need
670cdf0e10cSrcweir 			to be adapted at once.
671cdf0e10cSrcweir 			When adapting later, the only user - the diashow - should directly use the provided
672cdf0e10cSrcweir 			Anination infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
673cdf0e10cSrcweir 
674cdf0e10cSrcweir             PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
675cdf0e10cSrcweir 			VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
676cdf0e10cSrcweir 			a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
677cdf0e10cSrcweir 			was explicitely created for the printer already again to some default maximum
678cdf0e10cSrcweir 			bitmap sizes.
679cdf0e10cSrcweir 			Nothing to do here for the primitive renderer.
680cdf0e10cSrcweir 
681cdf0e10cSrcweir 			Support for vcl::PDFExtOutDevData:
682cdf0e10cSrcweir 			PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
683cdf0e10cSrcweir 			the OutDev. When set, some extra data is written there. Trying simple PDF export and
684cdf0e10cSrcweir 			watching if i get those infos.
685cdf0e10cSrcweir 			Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
686cdf0e10cSrcweir 			the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
687cdf0e10cSrcweir 			if i get a PDFExtOutDevData at the target output device.
688cdf0e10cSrcweir 			Indeed, i get one. Checking what all may be done when that extra-device-info is there.
689cdf0e10cSrcweir 
690cdf0e10cSrcweir 		    All in all i have to talk to SJ. I will need to emulate some of those actions, but
691cdf0e10cSrcweir 			i need to discuss which ones.
692cdf0e10cSrcweir 			In the future, all those infos would be taken from the primitive sequence anyways,
693cdf0e10cSrcweir 			thus these extensions would potentially be temporary, too.
694cdf0e10cSrcweir             Discussed with SJ, added the necessary support and tested it. Details follow.
695cdf0e10cSrcweir 
696cdf0e10cSrcweir 			- In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
697cdf0e10cSrcweir 			  Added in primitive MetaFile renderer.
698cdf0e10cSrcweir 			  Checking URL: Indeed, current version exports it, but it is missing in primitive
699cdf0e10cSrcweir 			  CWS version. Adding support.
700cdf0e10cSrcweir 			  Okay, URLs work. Checked, Done.
701cdf0e10cSrcweir 
702cdf0e10cSrcweir             - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
703cdf0e10cSrcweir 			  target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
704cdf0e10cSrcweir 			  This may be added in primitive MetaFile renderer.
705cdf0e10cSrcweir 			  Adding support...
706cdf0e10cSrcweir 			  OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
707cdf0e10cSrcweir 			  svxform. Have to talk to FS if this has to be like that. Especially since
708cdf0e10cSrcweir 			  ::vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
709cdf0e10cSrcweir 			  Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
710cdf0e10cSrcweir 			  that stuff to somewhere else, maybe tools or svtools ?!? We will see...
711cdf0e10cSrcweir               Moved to toolkit, so i have to link against it. I tried VCL first, but it did
712cdf0e10cSrcweir               not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other then the name
713cdf0e10cSrcweir               may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
714cdf0e10cSrcweir               the lowest move,ment plave is toolkit.
715cdf0e10cSrcweir               Checked form control export, it works well. Done.
716cdf0e10cSrcweir 
717cdf0e10cSrcweir 		    - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
718cdf0e10cSrcweir 			  generated. I will need to check what happens here with primitives.
719cdf0e10cSrcweir 			  To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
720cdf0e10cSrcweir 			  Added support, but feature is broken in main version, so i cannot test at all.
721cdf0e10cSrcweir 			  Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
722cdf0e10cSrcweir               SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
723cdf0e10cSrcweir               as intended, the original file is exported. Works, Done.
724cdf0e10cSrcweir 
725cdf0e10cSrcweir 
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 
728cdf0e10cSrcweir             To be done:
729cdf0e10cSrcweir 
730cdf0e10cSrcweir             - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 
733cdf0e10cSrcweir 
734cdf0e10cSrcweir         ****************************************************************************************************/
735cdf0e10cSrcweir 
736cdf0e10cSrcweir 		void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
737cdf0e10cSrcweir 		{
738cdf0e10cSrcweir             switch(rCandidate.getPrimitive2DID())
739cdf0e10cSrcweir 			{
740cdf0e10cSrcweir                 case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
741cdf0e10cSrcweir                 {
742cdf0e10cSrcweir 					// directdraw of wrong spell primitive
743cdf0e10cSrcweir                     // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
744cdf0e10cSrcweir                     break;
745cdf0e10cSrcweir                 }
746cdf0e10cSrcweir 				case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
747cdf0e10cSrcweir 				{
748cdf0e10cSrcweir                     const primitive2d::GraphicPrimitive2D& rGraphicPrimitive = static_cast< const primitive2d::GraphicPrimitive2D& >(rCandidate);
749cdf0e10cSrcweir 					bool bUsingPDFExtOutDevData(false);
750cdf0e10cSrcweir 					basegfx::B2DVector aTranslate, aScale;
751cdf0e10cSrcweir 					static bool bSuppressPDFExtOutDevDataSupport(false);
752cdf0e10cSrcweir 
753cdf0e10cSrcweir 					if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
754cdf0e10cSrcweir 					{
755cdf0e10cSrcweir 						// emulate data handling from UnoControlPDFExportContact, original see
756cdf0e10cSrcweir 						// svtools/source/graphic/grfmgr.cxx
757cdf0e10cSrcweir 						const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
758cdf0e10cSrcweir 
759cdf0e10cSrcweir 						if(rGraphic.IsLink())
760cdf0e10cSrcweir 						{
761cdf0e10cSrcweir 							const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
762cdf0e10cSrcweir 
763cdf0e10cSrcweir 							if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
764cdf0e10cSrcweir 							{
765cdf0e10cSrcweir 								const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
766cdf0e10cSrcweir 								double fRotate, fShearX;
767cdf0e10cSrcweir 								rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
768cdf0e10cSrcweir 
769cdf0e10cSrcweir 								if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
770cdf0e10cSrcweir 								{
771cdf0e10cSrcweir 									bUsingPDFExtOutDevData = true;
772cdf0e10cSrcweir 									mpPDFExtOutDevData->BeginGroup();
773cdf0e10cSrcweir 								}
774cdf0e10cSrcweir 							}
775cdf0e10cSrcweir 						}
776cdf0e10cSrcweir 					}
777cdf0e10cSrcweir 
778cdf0e10cSrcweir 					// process recursively and add MetaFile comment
779cdf0e10cSrcweir 					process(rGraphicPrimitive.get2DDecomposition(getViewInformation2D()));
780cdf0e10cSrcweir 
781cdf0e10cSrcweir 					if(bUsingPDFExtOutDevData)
782cdf0e10cSrcweir 					{
783cdf0e10cSrcweir 						// emulate data handling from UnoControlPDFExportContact, original see
784cdf0e10cSrcweir 						// svtools/source/graphic/grfmgr.cxx
785cdf0e10cSrcweir 						const basegfx::B2DRange aCurrentRange(
786cdf0e10cSrcweir 							aTranslate.getX(), aTranslate.getY(),
787cdf0e10cSrcweir 							aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
788cdf0e10cSrcweir 						const Rectangle aCurrentRect(
789cdf0e10cSrcweir 							sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
790cdf0e10cSrcweir 							sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
791cdf0e10cSrcweir 						const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
792cdf0e10cSrcweir 						Rectangle aCropRect;
793cdf0e10cSrcweir 
794cdf0e10cSrcweir 						if(rAttr.IsCropped())
795cdf0e10cSrcweir 						{
796cdf0e10cSrcweir 							// calculate scalings between real image size and logic object size. This
797cdf0e10cSrcweir 							// is necessary since the crop values are relative to original bitmap size
798cdf0e10cSrcweir 							double fFactorX(1.0);
799cdf0e10cSrcweir 							double fFactorY(1.0);
800cdf0e10cSrcweir 
801cdf0e10cSrcweir 							{
802cdf0e10cSrcweir 								const MapMode aMapMode100thmm(MAP_100TH_MM);
803cdf0e10cSrcweir 								const Size aBitmapSize(Application::GetDefaultDevice()->LogicToLogic(
804cdf0e10cSrcweir 									rGraphicPrimitive.getGraphicObject().GetPrefSize(),
805cdf0e10cSrcweir 									rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
806cdf0e10cSrcweir 								const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
807cdf0e10cSrcweir 								const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
808cdf0e10cSrcweir 
809cdf0e10cSrcweir 								if(!basegfx::fTools::equalZero(fDivX))
810cdf0e10cSrcweir 								{
811cdf0e10cSrcweir 									fFactorX = aScale.getX() / fDivX;
812cdf0e10cSrcweir 								}
813cdf0e10cSrcweir 
814cdf0e10cSrcweir 								if(!basegfx::fTools::equalZero(fDivY))
815cdf0e10cSrcweir 								{
816cdf0e10cSrcweir 									fFactorY = aScale.getY() / fDivY;
817cdf0e10cSrcweir 								}
818cdf0e10cSrcweir 							}
819cdf0e10cSrcweir 
820cdf0e10cSrcweir 							// calculate crop range and rect
821cdf0e10cSrcweir 							basegfx::B2DRange aCropRange;
822cdf0e10cSrcweir 							aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
823cdf0e10cSrcweir 							aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
824cdf0e10cSrcweir 
825cdf0e10cSrcweir 							aCropRect = Rectangle(
826cdf0e10cSrcweir 								sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
827cdf0e10cSrcweir 								sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
828cdf0e10cSrcweir 						}
829cdf0e10cSrcweir 
830cdf0e10cSrcweir 						mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
831cdf0e10cSrcweir 							rAttr.GetTransparency(),
832cdf0e10cSrcweir 							aCurrentRect,
833cdf0e10cSrcweir 							aCropRect);
834cdf0e10cSrcweir 					}
835cdf0e10cSrcweir 
836cdf0e10cSrcweir 					break;
837cdf0e10cSrcweir 				}
838cdf0e10cSrcweir 				case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
839cdf0e10cSrcweir 				{
840cdf0e10cSrcweir                     const primitive2d::ControlPrimitive2D& rControlPrimitive = static_cast< const primitive2d::ControlPrimitive2D& >(rCandidate);
841cdf0e10cSrcweir         			const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
842cdf0e10cSrcweir 					bool bIsPrintableControl(false);
843cdf0e10cSrcweir 
844cdf0e10cSrcweir                     // find out if control is printable
845cdf0e10cSrcweir 					if(rXControl.is())
846cdf0e10cSrcweir 					{
847cdf0e10cSrcweir 						try
848cdf0e10cSrcweir 						{
849cdf0e10cSrcweir 							uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
850cdf0e10cSrcweir 							uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
851cdf0e10cSrcweir 								? xModelProperties->getPropertySetInfo()
852cdf0e10cSrcweir 								: uno::Reference< beans::XPropertySetInfo >());
853cdf0e10cSrcweir 							const ::rtl::OUString sPrintablePropertyName(RTL_CONSTASCII_USTRINGPARAM("Printable"));
854cdf0e10cSrcweir 
855cdf0e10cSrcweir 							if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
856cdf0e10cSrcweir 							{
857cdf0e10cSrcweir 								OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
858cdf0e10cSrcweir 							}
859cdf0e10cSrcweir 						}
860cdf0e10cSrcweir 						catch(const uno::Exception&)
861cdf0e10cSrcweir 						{
862cdf0e10cSrcweir 				            OSL_ENSURE(false, "VclMetafileProcessor2D: No access to printable flag of Control, caught an exception!");
863cdf0e10cSrcweir 						}
864cdf0e10cSrcweir 					}
865cdf0e10cSrcweir 
866cdf0e10cSrcweir                     // PDF export and printing only for printable controls
867cdf0e10cSrcweir                     if(bIsPrintableControl)
868cdf0e10cSrcweir                     {
869cdf0e10cSrcweir                         const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
870cdf0e10cSrcweir                         bool bDoProcessRecursively(true);
871cdf0e10cSrcweir 
872cdf0e10cSrcweir                         if(bPDFExport)
873cdf0e10cSrcweir 					    {
874cdf0e10cSrcweir 						    // PDF export. Emulate data handling from UnoControlPDFExportContact
875cdf0e10cSrcweir                             // I have now moved describePDFControl to toolkit, thus i can implement the PDF
876cdf0e10cSrcweir                             // form control support now as follows
877cdf0e10cSrcweir                             ::std::auto_ptr< ::vcl::PDFWriter::AnyWidget > pPDFControl;
878cdf0e10cSrcweir                             ::toolkitform::describePDFControl( rXControl, pPDFControl, *mpPDFExtOutDevData );
879cdf0e10cSrcweir 
880cdf0e10cSrcweir                             if(pPDFControl.get())
881cdf0e10cSrcweir                             {
882cdf0e10cSrcweir                                 // still need to fill in the location (is a class Rectangle)
883cdf0e10cSrcweir 			                    const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
884cdf0e10cSrcweir 	                            const Rectangle aRectLogic(
885cdf0e10cSrcweir 		                            (sal_Int32)floor(aRangeLogic.getMinX()), (sal_Int32)floor(aRangeLogic.getMinY()),
886cdf0e10cSrcweir 		                            (sal_Int32)ceil(aRangeLogic.getMaxX()), (sal_Int32)ceil(aRangeLogic.getMaxY()));
887cdf0e10cSrcweir                                 pPDFControl->Location = aRectLogic;
888cdf0e10cSrcweir 
889cdf0e10cSrcweir                                 Size aFontSize(pPDFControl->TextFont.GetSize());
890cdf0e10cSrcweir                                 aFontSize = mpOutputDevice->LogicToLogic(aFontSize, MapMode(MAP_POINT), mpOutputDevice->GetMapMode());
891cdf0e10cSrcweir                                 pPDFControl->TextFont.SetSize(aFontSize);
892cdf0e10cSrcweir 
893cdf0e10cSrcweir                                 mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
894cdf0e10cSrcweir                                 mpPDFExtOutDevData->CreateControl(*pPDFControl.get());
895cdf0e10cSrcweir                                 mpPDFExtOutDevData->EndStructureElement();
896cdf0e10cSrcweir 
897cdf0e10cSrcweir                                 // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
898cdf0e10cSrcweir                                 // do not process recursively
899cdf0e10cSrcweir                                 bDoProcessRecursively = false;
900cdf0e10cSrcweir                             }
901cdf0e10cSrcweir                             else
902cdf0e10cSrcweir                             {
903cdf0e10cSrcweir                                 // PDF export did not work, try simple output.
904cdf0e10cSrcweir                                 // Fallback to printer output by not setting bDoProcessRecursively
905cdf0e10cSrcweir                                 // to false.
906cdf0e10cSrcweir                             }
907cdf0e10cSrcweir 					    }
908cdf0e10cSrcweir 
909cdf0e10cSrcweir                         // #i93169# used flag the wrong way; true means that nothing was done yet
910cdf0e10cSrcweir                         if(bDoProcessRecursively)
911cdf0e10cSrcweir 					    {
912cdf0e10cSrcweir     					    // printer output
913cdf0e10cSrcweir 					        try
914cdf0e10cSrcweir 					        {
915cdf0e10cSrcweir                                 // remember old graphics and create new
916cdf0e10cSrcweir 					            uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
917cdf0e10cSrcweir                                 const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
918cdf0e10cSrcweir 					            const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
919cdf0e10cSrcweir 
920cdf0e10cSrcweir                                 if(xNewGraphics.is())
921cdf0e10cSrcweir                                 {
922cdf0e10cSrcweir 				                    // link graphics and view
923cdf0e10cSrcweir 				                    xControlView->setGraphics(xNewGraphics);
924cdf0e10cSrcweir 
925cdf0e10cSrcweir                                     // get position
926cdf0e10cSrcweir                                     const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
927cdf0e10cSrcweir                                     const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
928cdf0e10cSrcweir 
929cdf0e10cSrcweir                                     // draw it
930cdf0e10cSrcweir                                     xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
931cdf0e10cSrcweir                                     bDoProcessRecursively = false;
932cdf0e10cSrcweir 
933cdf0e10cSrcweir                                     // restore original graphics
934cdf0e10cSrcweir 				                    xControlView->setGraphics(xOriginalGraphics);
935cdf0e10cSrcweir                                 }
936cdf0e10cSrcweir 					        }
937cdf0e10cSrcweir 					        catch( const uno::Exception& )
938cdf0e10cSrcweir 					        {
939cdf0e10cSrcweir 			                    OSL_ENSURE(false, "VclMetafileProcessor2D: Printing of Control failed, caught an exception!");
940cdf0e10cSrcweir 					        }
941cdf0e10cSrcweir 					    }
942cdf0e10cSrcweir 
943cdf0e10cSrcweir 					    // process recursively if not done yet to export as decomposition (bitmap)
944cdf0e10cSrcweir                         if(bDoProcessRecursively)
945cdf0e10cSrcweir                         {
946cdf0e10cSrcweir     					    process(rControlPrimitive.get2DDecomposition(getViewInformation2D()));
947cdf0e10cSrcweir                         }
948cdf0e10cSrcweir                     }
949cdf0e10cSrcweir 
950cdf0e10cSrcweir 					break;
951cdf0e10cSrcweir 				}
952cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
953cdf0e10cSrcweir                 {
954cdf0e10cSrcweir                     // support for FIELD_SEQ_BEGIN, FIELD_SEQ_END and URL. It wraps text primitives (but is not limited to)
955cdf0e10cSrcweir                     // thus do the MetafileAction embedding stuff but just handle recursively.
956cdf0e10cSrcweir 					const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive = static_cast< const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate);
957cdf0e10cSrcweir                     static const ByteString aCommentStringCommon("FIELD_SEQ_BEGIN");
958cdf0e10cSrcweir 					static const ByteString aCommentStringPage("FIELD_SEQ_BEGIN;PageField");
959cdf0e10cSrcweir 					static const ByteString aCommentStringEnd("FIELD_SEQ_END");
960cdf0e10cSrcweir 
961cdf0e10cSrcweir 					switch(rFieldPrimitive.getType())
962cdf0e10cSrcweir 					{
963cdf0e10cSrcweir 						default : // case drawinglayer::primitive2d::FIELD_TYPE_COMMON :
964cdf0e10cSrcweir 						{
965cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon));
966cdf0e10cSrcweir 							break;
967cdf0e10cSrcweir 						}
968cdf0e10cSrcweir 						case drawinglayer::primitive2d::FIELD_TYPE_PAGE :
969cdf0e10cSrcweir 						{
970cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringPage));
971cdf0e10cSrcweir 							break;
972cdf0e10cSrcweir 						}
973cdf0e10cSrcweir 						case drawinglayer::primitive2d::FIELD_TYPE_URL :
974cdf0e10cSrcweir 						{
975cdf0e10cSrcweir 							const rtl::OUString& rURL = rFieldPrimitive.getString();
976cdf0e10cSrcweir                             const String aOldString(rURL);
977cdf0e10cSrcweir 		                    mpMetaFile->AddAction(new MetaCommentAction(aCommentStringCommon, 0, reinterpret_cast< const sal_uInt8* >(aOldString.GetBuffer()), 2 * aOldString.Len()));
978cdf0e10cSrcweir 							break;
979cdf0e10cSrcweir 						}
980cdf0e10cSrcweir 					}
981cdf0e10cSrcweir 
982cdf0e10cSrcweir 					// process recursively
983cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rFieldPrimitive.get2DDecomposition(getViewInformation2D());
984cdf0e10cSrcweir 					process(rContent);
985cdf0e10cSrcweir 
986cdf0e10cSrcweir 					// for the end comment the type is not relevant yet, they are all the same. Just add.
987cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd));
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 					if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())
990cdf0e10cSrcweir 					{
991cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
992cdf0e10cSrcweir 			            const basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
993cdf0e10cSrcweir 	                    const Rectangle aRectLogic(
994cdf0e10cSrcweir 		                    (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
995cdf0e10cSrcweir 		                    (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
996cdf0e10cSrcweir 						vcl::PDFExtOutDevBookmarkEntry aBookmark;
997cdf0e10cSrcweir 						aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic);
998cdf0e10cSrcweir 						aBookmark.aBookmark = rFieldPrimitive.getString();
999cdf0e10cSrcweir 						std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks();
1000cdf0e10cSrcweir 						rBookmarks.push_back( aBookmark );
1001cdf0e10cSrcweir 					}
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir                     break;
1004cdf0e10cSrcweir                 }
1005cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
1006cdf0e10cSrcweir                 {
1007cdf0e10cSrcweir                     const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive = static_cast< const primitive2d::TextHierarchyLinePrimitive2D& >(rCandidate);
1008cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOL");
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1011cdf0e10cSrcweir 					process(rLinePrimitive.get2DDecomposition(getViewInformation2D()));
1012cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir                     break;
1015cdf0e10cSrcweir                 }
1016cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
1017cdf0e10cSrcweir                 {
1018cdf0e10cSrcweir                     // in Outliner::PaintBullet(), a MetafileComment for bullets is added, too. The
1019cdf0e10cSrcweir                     // "XTEXT_EOC" is used, use here, too.
1020cdf0e10cSrcweir 					const primitive2d::TextHierarchyBulletPrimitive2D& rBulletPrimitive = static_cast< const primitive2d::TextHierarchyBulletPrimitive2D& >(rCandidate);
1021cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOC");
1022cdf0e10cSrcweir 
1023cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1024cdf0e10cSrcweir 					process(rBulletPrimitive.get2DDecomposition(getViewInformation2D()));
1025cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir                     break;
1028cdf0e10cSrcweir                 }
1029cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
1030cdf0e10cSrcweir                 {
1031cdf0e10cSrcweir                     const primitive2d::TextHierarchyParagraphPrimitive2D& rParagraphPrimitive = static_cast< const primitive2d::TextHierarchyParagraphPrimitive2D& >(rCandidate);
1032cdf0e10cSrcweir                     static const ByteString aCommentString("XTEXT_EOP");
1033cdf0e10cSrcweir 
1034cdf0e10cSrcweir 					if(mpPDFExtOutDevData)
1035cdf0e10cSrcweir 					{
1036cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
1037cdf0e10cSrcweir 						mpPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
1038cdf0e10cSrcweir 					}
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir                     // process recursively and add MetaFile comment
1041cdf0e10cSrcweir 					process(rParagraphPrimitive.get2DDecomposition(getViewInformation2D()));
1042cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentString));
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir 					if(mpPDFExtOutDevData)
1045cdf0e10cSrcweir 					{
1046cdf0e10cSrcweir 						// emulate data handling from ImpEditEngine::Paint
1047cdf0e10cSrcweir 						mpPDFExtOutDevData->EndStructureElement();
1048cdf0e10cSrcweir 					}
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir 					break;
1051cdf0e10cSrcweir                 }
1052cdf0e10cSrcweir                 case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
1053cdf0e10cSrcweir                 {
1054cdf0e10cSrcweir                     const primitive2d::TextHierarchyBlockPrimitive2D& rBlockPrimitive = static_cast< const primitive2d::TextHierarchyBlockPrimitive2D& >(rCandidate);
1055cdf0e10cSrcweir                     static const ByteString aCommentStringA("XTEXT_PAINTSHAPE_BEGIN");
1056cdf0e10cSrcweir                     static const ByteString aCommentStringB("XTEXT_PAINTSHAPE_END");
1057cdf0e10cSrcweir 
1058cdf0e10cSrcweir                     // add MetaFile comment, process recursively and add MetaFile comment
1059cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA));
1060cdf0e10cSrcweir 					process(rBlockPrimitive.get2DDecomposition(getViewInformation2D()));
1061cdf0e10cSrcweir                     mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB));
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir                     break;
1064cdf0e10cSrcweir                 }
1065cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
1066cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
1067cdf0e10cSrcweir 				{
1068cdf0e10cSrcweir                     // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
1069cdf0e10cSrcweir 					const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate);
1070cdf0e10cSrcweir 					// const primitive2d::TextDecoratedPortionPrimitive2D* pTextDecoratedCandidate = dynamic_cast< const primitive2d::TextDecoratedPortionPrimitive2D* >(&rCandidate);
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 					// Adapt evtl. used special DrawMode
1073cdf0e10cSrcweir 					const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
1074cdf0e10cSrcweir 					adaptTextToFillDrawMode();
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir 					// directdraw of text simple portion; use default processing
1077cdf0e10cSrcweir 					RenderTextSimpleOrDecoratedPortionPrimitive2D(rTextCandidate);
1078cdf0e10cSrcweir 
1079cdf0e10cSrcweir 					// restore DrawMode
1080cdf0e10cSrcweir 					mpOutputDevice->SetDrawMode(nOriginalDrawMode);
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir 					// #i101169# if(pTextDecoratedCandidate)
1083cdf0e10cSrcweir                     {
1084cdf0e10cSrcweir                         // support for TEXT_ MetaFile actions only for decorated texts
1085cdf0e10cSrcweir                         if(!mxBreakIterator.is())
1086cdf0e10cSrcweir                         {
1087cdf0e10cSrcweir                             uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF(::comphelper::getProcessServiceFactory());
1088cdf0e10cSrcweir                             mxBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), uno::UNO_QUERY);
1089cdf0e10cSrcweir                         }
1090cdf0e10cSrcweir 
1091cdf0e10cSrcweir                         if(mxBreakIterator.is())
1092cdf0e10cSrcweir                         {
1093cdf0e10cSrcweir                             const rtl::OUString& rTxt = rTextCandidate.getText();
1094cdf0e10cSrcweir                             const sal_Int32 nTextLength(rTextCandidate.getTextLength()); // rTxt.getLength());
1095cdf0e10cSrcweir 
1096cdf0e10cSrcweir                             if(nTextLength)
1097cdf0e10cSrcweir                             {
1098cdf0e10cSrcweir                                 const ::com::sun::star::lang::Locale& rLocale = rTextCandidate.getLocale();
1099cdf0e10cSrcweir                                 const sal_Int32 nTextPosition(rTextCandidate.getTextPosition());
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir                                 sal_Int32 nDone;
1102cdf0e10cSrcweir                                 sal_Int32 nNextCellBreak(mxBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
1103cdf0e10cSrcweir                                 ::com::sun::star::i18n::Boundary nNextWordBoundary(mxBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True));
1104cdf0e10cSrcweir                                 sal_Int32 nNextSentenceBreak(mxBreakIterator->endOfSentence(rTxt, nTextPosition, rLocale));
1105cdf0e10cSrcweir                                 static const ByteString aCommentStringA("XTEXT_EOC");
1106cdf0e10cSrcweir                                 static const ByteString aCommentStringB("XTEXT_EOW");
1107cdf0e10cSrcweir                                 static const ByteString aCommentStringC("XTEXT_EOS");
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir                                 for(sal_Int32 i(nTextPosition); i < nTextPosition + nTextLength; i++)
1110cdf0e10cSrcweir                                 {
1111cdf0e10cSrcweir                                     // create the entries for the respective break positions
1112cdf0e10cSrcweir                                     if(i == nNextCellBreak)
1113cdf0e10cSrcweir                                     {
1114cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringA, i - nTextPosition));
1115cdf0e10cSrcweir                                         nNextCellBreak = mxBreakIterator->nextCharacters(rTxt, i, rLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
1116cdf0e10cSrcweir                                     }
1117cdf0e10cSrcweir                                     if(i == nNextWordBoundary.endPos)
1118cdf0e10cSrcweir                                     {
1119cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringB, i - nTextPosition));
1120cdf0e10cSrcweir                                         nNextWordBoundary = mxBreakIterator->getWordBoundary(rTxt, i + 1, rLocale, ::com::sun::star::i18n::WordType::ANY_WORD, sal_True);
1121cdf0e10cSrcweir                                     }
1122cdf0e10cSrcweir                                     if(i == nNextSentenceBreak)
1123cdf0e10cSrcweir                                     {
1124cdf0e10cSrcweir                                         mpMetaFile->AddAction(new MetaCommentAction(aCommentStringC, i - nTextPosition));
1125cdf0e10cSrcweir                                         nNextSentenceBreak = mxBreakIterator->endOfSentence(rTxt, i + 1, rLocale);
1126cdf0e10cSrcweir                                     }
1127cdf0e10cSrcweir                                 }
1128cdf0e10cSrcweir                             }
1129cdf0e10cSrcweir                         }
1130cdf0e10cSrcweir                     }
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir                     break;
1133cdf0e10cSrcweir 				}
1134cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
1135cdf0e10cSrcweir 				{
1136cdf0e10cSrcweir 					const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
1137cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1140cdf0e10cSrcweir                     {
1141cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1142cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1143cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1144cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1145cdf0e10cSrcweir                         const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor());
1146cdf0e10cSrcweir                         const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor());
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1149cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1150cdf0e10cSrcweir                     }
1151cdf0e10cSrcweir                     else
1152cdf0e10cSrcweir                     {
1153cdf0e10cSrcweir     					// direct draw of hairline; use default processing
1154cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1155cdf0e10cSrcweir 					    const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
11564665f8d3SArmin Le Grand                         SvtGraphicStroke* pSvtGraphicStroke = 0;
11574665f8d3SArmin Le Grand 
11584665f8d3SArmin Le Grand                         // #121267# Not needed, does not give better quality compared with
11594665f8d3SArmin Le Grand                         // the META_POLYPOLYGON_ACTION written by RenderPolygonHairlinePrimitive2D
11604665f8d3SArmin Le Grand                         // below
11614665f8d3SArmin Le Grand                         bool bSupportSvtGraphicStroke(false);
11624665f8d3SArmin Le Grand 
11634665f8d3SArmin Le Grand                         if(bSupportSvtGraphicStroke)
11644665f8d3SArmin Le Grand                         {
11654665f8d3SArmin Le Grand                             pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
11664665f8d3SArmin Le Grand                                 rHairlinePrimitive.getB2DPolygon(),
11674665f8d3SArmin Le Grand                                 &aLineColor,
11684665f8d3SArmin Le Grand                                 0, 0, 0, 0);
11694665f8d3SArmin Le Grand 
11704665f8d3SArmin Le Grand     					    impStartSvtGraphicStroke(pSvtGraphicStroke);
11714665f8d3SArmin Le Grand                         }
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir 					    RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
11744665f8d3SArmin Le Grand 
11754665f8d3SArmin Le Grand                         if(bSupportSvtGraphicStroke)
11764665f8d3SArmin Le Grand                         {
11774665f8d3SArmin Le Grand                             impEndSvtGraphicStroke(pSvtGraphicStroke);
11784665f8d3SArmin Le Grand                         }
1179cdf0e10cSrcweir                     }
1180cdf0e10cSrcweir 					break;
1181cdf0e10cSrcweir 				}
1182cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
1183cdf0e10cSrcweir 				{
1184cdf0e10cSrcweir 					const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
1185cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
1186cdf0e10cSrcweir 
1187cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1188cdf0e10cSrcweir                     {
1189cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1190cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1191cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1192cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1193cdf0e10cSrcweir                         const primitive2d::PolygonStrokePrimitive2D aPLeft(
1194cdf0e10cSrcweir                             aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1195cdf0e10cSrcweir                         const primitive2d::PolygonStrokePrimitive2D aPRight(
1196cdf0e10cSrcweir                             aRight, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1199cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1200cdf0e10cSrcweir                     }
1201cdf0e10cSrcweir                     else
1202cdf0e10cSrcweir                     {
1203cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1204cdf0e10cSrcweir 					    SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1205cdf0e10cSrcweir                             rBasePolygon, 0,
1206cdf0e10cSrcweir                             &rStrokePrimitive.getLineAttribute(),
1207cdf0e10cSrcweir                             &rStrokePrimitive.getStrokeAttribute(),
1208cdf0e10cSrcweir                             0, 0);
1209cdf0e10cSrcweir 
1210cdf0e10cSrcweir 					    impStartSvtGraphicStroke(pSvtGraphicStroke);
1211cdf0e10cSrcweir 					    const attribute::LineAttribute& rLine = rStrokePrimitive.getLineAttribute();
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir 					    // create MetaPolyLineActions, but without LINE_DASH
1214cdf0e10cSrcweir 					    if(basegfx::fTools::more(rLine.getWidth(), 0.0))
1215cdf0e10cSrcweir 					    {
1216cdf0e10cSrcweir 						    const attribute::StrokeAttribute& rStroke = rStrokePrimitive.getStrokeAttribute();
1217cdf0e10cSrcweir 						    basegfx::B2DPolyPolygon aHairLinePolyPolygon;
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir 						    if(0.0 == rStroke.getFullDotDashLen())
1220cdf0e10cSrcweir 						    {
1221cdf0e10cSrcweir 							    aHairLinePolyPolygon.append(rBasePolygon);
1222cdf0e10cSrcweir 						    }
1223cdf0e10cSrcweir 						    else
1224cdf0e10cSrcweir 						    {
1225cdf0e10cSrcweir 							    basegfx::tools::applyLineDashing(
1226cdf0e10cSrcweir 								    rBasePolygon, rStroke.getDotDashArray(),
1227cdf0e10cSrcweir 								    &aHairLinePolyPolygon, 0, rStroke.getFullDotDashLen());
1228cdf0e10cSrcweir 						    }
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir 						    const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLine.getColor()));
1231cdf0e10cSrcweir 						    mpOutputDevice->SetLineColor(Color(aHairlineColor));
1232cdf0e10cSrcweir 						    mpOutputDevice->SetFillColor();
1233cdf0e10cSrcweir 						    aHairLinePolyPolygon.transform(maCurrentTransformation);
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir 							// #i113922# LineWidth needs to be transformed, too
1236cdf0e10cSrcweir 							const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(rLine.getWidth(), 0.0));
1237cdf0e10cSrcweir 							const double fDiscreteLineWidth(aDiscreteUnit.getLength());
1238cdf0e10cSrcweir 
1239cdf0e10cSrcweir 							LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fDiscreteLineWidth));
1240cdf0e10cSrcweir 						    aLineInfo.SetLineJoin(rLine.getLineJoin());
12415aaf853bSArmin Le Grand                             aLineInfo.SetLineCap(rLine.getLineCap());
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir 						    for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++)
1244cdf0e10cSrcweir 						    {
1245cdf0e10cSrcweir 							    const basegfx::B2DPolygon aCandidate(aHairLinePolyPolygon.getB2DPolygon(a));
1246cdf0e10cSrcweir 
1247cdf0e10cSrcweir 							    if(aCandidate.count() > 1)
1248cdf0e10cSrcweir 							    {
1249cdf0e10cSrcweir 								    const Polygon aToolsPolygon(aCandidate);
1250cdf0e10cSrcweir 
1251cdf0e10cSrcweir                 				    mpMetaFile->AddAction(new MetaPolyLineAction(aToolsPolygon, aLineInfo));
1252cdf0e10cSrcweir 							    }
1253cdf0e10cSrcweir 						    }
1254cdf0e10cSrcweir 					    }
1255cdf0e10cSrcweir 					    else
1256cdf0e10cSrcweir 					    {
1257cdf0e10cSrcweir 						    process(rCandidate.get2DDecomposition(getViewInformation2D()));
1258cdf0e10cSrcweir 					    }
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 					    impEndSvtGraphicStroke(pSvtGraphicStroke);
1261cdf0e10cSrcweir                     }
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir 					break;
1264cdf0e10cSrcweir 				}
1265cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
1266cdf0e10cSrcweir 				{
1267cdf0e10cSrcweir 					const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
1268cdf0e10cSrcweir         			const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir                     if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
1271cdf0e10cSrcweir                     {
1272cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1273cdf0e10cSrcweir                         // per polygon. If there are more, split the polygon in half and call recursively
1274cdf0e10cSrcweir                         basegfx::B2DPolygon aLeft, aRight;
1275cdf0e10cSrcweir                         splitLinePolygon(rBasePolygon, aLeft, aRight);
1276cdf0e10cSrcweir                         const attribute::LineStartEndAttribute aEmpty;
1277cdf0e10cSrcweir                         const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft(
1278cdf0e10cSrcweir                             aLeft,
1279cdf0e10cSrcweir                             rStrokeArrowPrimitive.getLineAttribute(),
1280cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStrokeAttribute(),
1281cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStart(),
1282cdf0e10cSrcweir                             aEmpty);
1283cdf0e10cSrcweir                         const primitive2d::PolygonStrokeArrowPrimitive2D aPRight(
1284cdf0e10cSrcweir                             aRight,
1285cdf0e10cSrcweir                             rStrokeArrowPrimitive.getLineAttribute(),
1286cdf0e10cSrcweir                             rStrokeArrowPrimitive.getStrokeAttribute(),
1287cdf0e10cSrcweir                             aEmpty,
1288cdf0e10cSrcweir                             rStrokeArrowPrimitive.getEnd());
1289cdf0e10cSrcweir 
1290cdf0e10cSrcweir                         processBasePrimitive2D(aPLeft);
1291cdf0e10cSrcweir                         processBasePrimitive2D(aPRight);
1292cdf0e10cSrcweir                     }
1293cdf0e10cSrcweir                     else
1294cdf0e10cSrcweir                     {
1295cdf0e10cSrcweir     					// support SvtGraphicStroke MetaCommentAction
1296cdf0e10cSrcweir 	    				SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
1297cdf0e10cSrcweir                             rBasePolygon, 0,
1298cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getLineAttribute(),
1299cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getStrokeAttribute(),
1300cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getStart(),
1301cdf0e10cSrcweir                             &rStrokeArrowPrimitive.getEnd());
1302cdf0e10cSrcweir 
130378137d97SArmin Le Grand                         // write LineGeometry start marker
1304cdf0e10cSrcweir 			    		impStartSvtGraphicStroke(pSvtGraphicStroke);
130578137d97SArmin Le Grand 
130678137d97SArmin Le Grand                         // #116162# When B&W is set as DrawMode, DRAWMODE_WHITEFILL is used
130778137d97SArmin Le Grand                         // to let all fills be just white; for lines DRAWMODE_BLACKLINE is used
130878137d97SArmin Le Grand                         // so all line geometry is supposed to get black. Since in the in-between
130978137d97SArmin Le Grand                         // stages of line geometry drawing filled polygons are used (e.g. line
131078137d97SArmin Le Grand                         // start/ends) it is necessary to change these drawmodes to preserve
131178137d97SArmin Le Grand                         // that lines shall be black; thus change DRAWMODE_WHITEFILL to
131278137d97SArmin Le Grand                         // DRAWMODE_BLACKFILL during line geometry processing to have line geometry
131378137d97SArmin Le Grand                         // parts filled black.
131478137d97SArmin Le Grand                         const sal_uLong nOldDrawMode(mpOutputDevice->GetDrawMode());
131578137d97SArmin Le Grand                         const bool bDrawmodeChange(nOldDrawMode & DRAWMODE_WHITEFILL && mnSvtGraphicStrokeCount);
131678137d97SArmin Le Grand 
131778137d97SArmin Le Grand                         if(bDrawmodeChange)
131878137d97SArmin Le Grand                         {
131978137d97SArmin Le Grand                             mpOutputDevice->SetDrawMode((nOldDrawMode & ~DRAWMODE_WHITEFILL) | DRAWMODE_BLACKFILL);
132078137d97SArmin Le Grand                         }
132178137d97SArmin Le Grand 
132278137d97SArmin Le Grand                         // process sub-line geometry (evtl. filled PolyPolygons)
132378137d97SArmin Le Grand                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
132478137d97SArmin Le Grand 
132578137d97SArmin Le Grand                         if(bDrawmodeChange)
132678137d97SArmin Le Grand                         {
132778137d97SArmin Le Grand                             mpOutputDevice->SetDrawMode(nOldDrawMode);
132878137d97SArmin Le Grand                         }
132978137d97SArmin Le Grand 
133078137d97SArmin Le Grand                         // write LineGeometry end marker
133178137d97SArmin Le Grand                         impEndSvtGraphicStroke(pSvtGraphicStroke);
1332cdf0e10cSrcweir                     }
1333cdf0e10cSrcweir 
1334cdf0e10cSrcweir                     break;
1335cdf0e10cSrcweir 				}
1336cdf0e10cSrcweir 				case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
1337cdf0e10cSrcweir 				{
1338cdf0e10cSrcweir                     // direct draw of transformed BitmapEx primitive; use default processing
1339cdf0e10cSrcweir 					RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
1340cdf0e10cSrcweir 					break;
1341cdf0e10cSrcweir 				}
1342035a2f44SArmin Le Grand 				case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
1343cdf0e10cSrcweir 				{
1344035a2f44SArmin Le Grand 					// need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1345035a2f44SArmin Le Grand 					const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate);
1346cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
1347cdf0e10cSrcweir 
1348cdf0e10cSrcweir                     if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1349cdf0e10cSrcweir                     {
1350cdf0e10cSrcweir                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1351cdf0e10cSrcweir                         // per polygon. If there are more use the splitted polygon and call recursively
1352035a2f44SArmin Le Grand                         const primitive2d::PolyPolygonGraphicPrimitive2D aSplitted(
1353cdf0e10cSrcweir                             aLocalPolyPolygon,
1354035a2f44SArmin Le Grand                             rBitmapCandidate.getFillGraphic());
1355cdf0e10cSrcweir 
1356cdf0e10cSrcweir                         processBasePrimitive2D(aSplitted);
1357cdf0e10cSrcweir                     }
1358cdf0e10cSrcweir                     else
1359cdf0e10cSrcweir                     {
1360cdf0e10cSrcweir                         SvtGraphicFill* pSvtGraphicFill = 0;
1361cdf0e10cSrcweir 
1362cdf0e10cSrcweir 					    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1363cdf0e10cSrcweir 					    {
1364035a2f44SArmin Le Grand                             // #121194# Changed implementation and checked usages fo convert to metafile,
1365035a2f44SArmin Le Grand                             // presentation start (uses SvtGraphicFill) and printing.
1366cdf0e10cSrcweir 
1367035a2f44SArmin Le Grand                             // calculate transformation. Get real object size, all values in FillGraphicAttribute
1368035a2f44SArmin Le Grand 						    // are relative to the unified object
1369035a2f44SArmin Le Grand 						    aLocalPolyPolygon.transform(maCurrentTransformation);
1370035a2f44SArmin Le Grand                             const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange());
1371cdf0e10cSrcweir 
1372cdf0e10cSrcweir 						    // the scaling needs scale from pixel to logic coordinate system
1373035a2f44SArmin Le Grand 						    const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic();
1374035a2f44SArmin Le Grand 						    const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel());
1375035a2f44SArmin Le Grand 
1376035a2f44SArmin Le Grand 						    // setup transformation like in impgrfll. Multiply with aOutlineSize
1377035a2f44SArmin Le Grand                             // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange()
1378035a2f44SArmin Le Grand                             // to object coordinates with object's top left being at (0,0). Divide
1379035a2f44SArmin Le Grand                             // by pixel size so that scale from pixel to logic will work in SvtGraphicFill.
1380035a2f44SArmin Le Grand                             const basegfx::B2DVector aTransformScale(
1381035a2f44SArmin Le Grand                                 rFillGraphicAttribute.getGraphicRange().getRange() /
1382035a2f44SArmin Le Grand                                 basegfx::B2DVector(
1383035a2f44SArmin Le Grand                                     std::max(1.0, double(aBmpSizePixel.Width())),
1384035a2f44SArmin Le Grand                                     std::max(1.0, double(aBmpSizePixel.Height()))) *
1385035a2f44SArmin Le Grand                                 aOutlineSize);
1386035a2f44SArmin Le Grand                             const basegfx::B2DPoint aTransformPosition(
1387035a2f44SArmin Le Grand                                 rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize);
1388cdf0e10cSrcweir 
1389cdf0e10cSrcweir 						    // setup transformation like in impgrfll
1390cdf0e10cSrcweir 						    SvtGraphicFill::Transform aTransform;
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir 						    // scale values are divided by bitmap pixel sizes
1393035a2f44SArmin Le Grand 						    aTransform.matrix[0] = aTransformScale.getX();
1394035a2f44SArmin Le Grand 						    aTransform.matrix[4] = aTransformScale.getY();
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir                             // translates are absolute
1397035a2f44SArmin Le Grand                             aTransform.matrix[2] = aTransformPosition.getX();
1398035a2f44SArmin Le Grand 						    aTransform.matrix[5] = aTransformPosition.getY();
1399cdf0e10cSrcweir 
1400035a2f44SArmin Le Grand                             pSvtGraphicFill = new SvtGraphicFill(
1401cdf0e10cSrcweir 							    PolyPolygon(aLocalPolyPolygon),
1402cdf0e10cSrcweir 							    Color(),
1403cdf0e10cSrcweir 							    0.0,
1404cdf0e10cSrcweir 							    SvtGraphicFill::fillEvenOdd,
1405cdf0e10cSrcweir 							    SvtGraphicFill::fillTexture,
1406cdf0e10cSrcweir 							    aTransform,
1407035a2f44SArmin Le Grand 							    rFillGraphicAttribute.getTiling(),
1408cdf0e10cSrcweir 							    SvtGraphicFill::hatchSingle,
1409cdf0e10cSrcweir 							    Color(),
1410cdf0e10cSrcweir 							    SvtGraphicFill::gradientLinear,
1411cdf0e10cSrcweir 							    Color(),
1412cdf0e10cSrcweir 							    Color(),
1413cdf0e10cSrcweir 							    0,
1414035a2f44SArmin Le Grand 							    rFillGraphicAttribute.getGraphic());
1415cdf0e10cSrcweir 					    }
1416cdf0e10cSrcweir 
1417cdf0e10cSrcweir 					    // Do use decomposition; encapsulate with SvtGraphicFill
1418cdf0e10cSrcweir 					    impStartSvtGraphicFill(pSvtGraphicFill);
1419cdf0e10cSrcweir 					    process(rCandidate.get2DDecomposition(getViewInformation2D()));
1420cdf0e10cSrcweir 					    impEndSvtGraphicFill(pSvtGraphicFill);
1421cdf0e10cSrcweir                     }
1422cdf0e10cSrcweir 
1423cdf0e10cSrcweir 					break;
1424cdf0e10cSrcweir 				}
1425cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
1426cdf0e10cSrcweir 				{
1427cdf0e10cSrcweir 					// need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
1428cdf0e10cSrcweir 					const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
1429cdf0e10cSrcweir 				    const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
1430cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1433cdf0e10cSrcweir                     // per polygon. Split polygon until there are less than that
1434cdf0e10cSrcweir                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1435cdf0e10cSrcweir                         ;
1436cdf0e10cSrcweir 
1437cdf0e10cSrcweir 					if(rFillHatchAttribute.isFillBackground())
1438cdf0e10cSrcweir 					{
1439cdf0e10cSrcweir 						// with fixing #i111954# (see below) the possible background
1440cdf0e10cSrcweir 						// fill of a hatched object was lost.Generate a background fill
1441cdf0e10cSrcweir 						// primitive and render it
1442cdf0e10cSrcweir 					    const primitive2d::Primitive2DReference xBackground(
1443cdf0e10cSrcweir 							new primitive2d::PolyPolygonColorPrimitive2D(
1444cdf0e10cSrcweir 								aLocalPolyPolygon,
1445cdf0e10cSrcweir 								rHatchCandidate.getBackgroundColor()));
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 						process(primitive2d::Primitive2DSequence(&xBackground, 1));
1448cdf0e10cSrcweir 					}
1449cdf0e10cSrcweir 
1450cdf0e10cSrcweir                     SvtGraphicFill* pSvtGraphicFill = 0;
1451cdf0e10cSrcweir 				    aLocalPolyPolygon.transform(maCurrentTransformation);
1452cdf0e10cSrcweir 
1453cdf0e10cSrcweir 				    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1454cdf0e10cSrcweir 				    {
1455cdf0e10cSrcweir 					    // re-create a VCL hatch as base data
1456cdf0e10cSrcweir 					    SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir 					    switch(rFillHatchAttribute.getStyle())
1459cdf0e10cSrcweir 					    {
1460cdf0e10cSrcweir 						    default: // attribute::HATCHSTYLE_SINGLE :
1461cdf0e10cSrcweir 						    {
1462cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchSingle;
1463cdf0e10cSrcweir 							    break;
1464cdf0e10cSrcweir 						    }
1465cdf0e10cSrcweir 						    case attribute::HATCHSTYLE_DOUBLE :
1466cdf0e10cSrcweir 						    {
1467cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchDouble;
1468cdf0e10cSrcweir 							    break;
1469cdf0e10cSrcweir 						    }
1470cdf0e10cSrcweir 						    case attribute::HATCHSTYLE_TRIPLE :
1471cdf0e10cSrcweir 						    {
1472cdf0e10cSrcweir 							    eHatch = SvtGraphicFill::hatchTriple;
1473cdf0e10cSrcweir 							    break;
1474cdf0e10cSrcweir 						    }
1475cdf0e10cSrcweir 					    }
1476cdf0e10cSrcweir 
1477cdf0e10cSrcweir 					    SvtGraphicFill::Transform aTransform;
1478cdf0e10cSrcweir 
1479cdf0e10cSrcweir 					    // scale
1480cdf0e10cSrcweir 					    aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
1481cdf0e10cSrcweir 					    aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir 					    // rotate (was never correct in impgrfll anyways, use correct angle now)
1484cdf0e10cSrcweir 					    aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
1485cdf0e10cSrcweir 					    aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
1486cdf0e10cSrcweir 					    aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
1487cdf0e10cSrcweir 					    aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
1488cdf0e10cSrcweir 
1489cdf0e10cSrcweir 					    pSvtGraphicFill = new SvtGraphicFill(
1490cdf0e10cSrcweir 						    PolyPolygon(aLocalPolyPolygon),
1491cdf0e10cSrcweir 						    Color(),
1492cdf0e10cSrcweir 						    0.0,
1493cdf0e10cSrcweir 						    SvtGraphicFill::fillEvenOdd,
1494cdf0e10cSrcweir 						    SvtGraphicFill::fillHatch,
1495cdf0e10cSrcweir 						    aTransform,
1496cdf0e10cSrcweir 						    false,
1497cdf0e10cSrcweir 						    eHatch,
1498cdf0e10cSrcweir 						    Color(rFillHatchAttribute.getColor()),
1499cdf0e10cSrcweir 						    SvtGraphicFill::gradientLinear,
1500cdf0e10cSrcweir 						    Color(),
1501cdf0e10cSrcweir 						    Color(),
1502cdf0e10cSrcweir 						    0,
1503cdf0e10cSrcweir 						    Graphic());
1504cdf0e10cSrcweir 				    }
1505cdf0e10cSrcweir 
1506cdf0e10cSrcweir 				    // Do use decomposition; encapsulate with SvtGraphicFill
1507cdf0e10cSrcweir 				    impStartSvtGraphicFill(pSvtGraphicFill);
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir                     // #i111954# do NOT use decomposition, but use direct VCL-command
1510cdf0e10cSrcweir 			        // process(rCandidate.get2DDecomposition(getViewInformation2D()));
1511cdf0e10cSrcweir 			        const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
1512cdf0e10cSrcweir                     const HatchStyle aHatchStyle(
1513cdf0e10cSrcweir                         attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
1514cdf0e10cSrcweir                         attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
1515cdf0e10cSrcweir                         HATCH_TRIPLE);
1516cdf0e10cSrcweir 
1517cdf0e10cSrcweir                     mpOutputDevice->DrawHatch(aToolsPolyPolygon,
1518cdf0e10cSrcweir                         Hatch(aHatchStyle,
1519cdf0e10cSrcweir                             Color(rFillHatchAttribute.getColor()),
1520cdf0e10cSrcweir                             basegfx::fround(rFillHatchAttribute.getDistance()),
1521cdf0e10cSrcweir                             basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir                     impEndSvtGraphicFill(pSvtGraphicFill);
1524cdf0e10cSrcweir 
1525cdf0e10cSrcweir 					break;
1526cdf0e10cSrcweir 				}
1527cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
1528cdf0e10cSrcweir                 {
15296d3fd5d0SArmin Le Grand                     basegfx::B2DVector aScale, aTranslate;
15306d3fd5d0SArmin Le Grand                     double fRotate, fShearX;
1531cdf0e10cSrcweir 
15326d3fd5d0SArmin Le Grand                     maCurrentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
1533cdf0e10cSrcweir 
15346d3fd5d0SArmin Le Grand                     if(!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
15356d3fd5d0SArmin Le Grand                     {
15366d3fd5d0SArmin Le Grand                         // #121185# When rotation or shear is used, a VCL Gradient cannot be used directly.
15376d3fd5d0SArmin Le Grand                         // This is because VCL Gradient mechanism does *not* support to rotate the gradient
15386d3fd5d0SArmin Le Grand                         // with objects and this case is not expressable in a Metafile (and cannot be added
15396d3fd5d0SArmin Le Grand                         // since the FileFormats used, e.g. *.wmf, do not support it either).
15406d3fd5d0SArmin Le Grand                         // Such cases happen when a graphic object uses a Metafile as graphic information or
15416d3fd5d0SArmin Le Grand                         // a fill style definition uses a Metafile. In this cases the graphic content is
15426d3fd5d0SArmin Le Grand                         // rotated with the graphic or filled object; this is not supported by the target
15436d3fd5d0SArmin Le Grand                         // format of this conversion renderer - Metafiles.
15446d3fd5d0SArmin Le Grand                         // To solve this, not a Gradient is written, but the decomposition of this object
15456d3fd5d0SArmin Le Grand                         // is written to the Metafile. This is the PolyPolygons building the gradient fill.
15466d3fd5d0SArmin Le Grand                         // These will need more space and time, but the result will be as if the Gradient
15476d3fd5d0SArmin Le Grand                         // was rotated with the object.
15486d3fd5d0SArmin Le Grand                         // This mechanism is used by all exporters still not using Primtives (e.g. Print,
15496d3fd5d0SArmin Le Grand                         // Slideshow, Export rto PDF, export to Picture, ...) but relying on Metafile
15506d3fd5d0SArmin Le Grand                         // transfers. One more reason to *change* these to primitives.
15516d3fd5d0SArmin Le Grand                         // BTW: One more example how useful the principles of primitives are; the decomposition
15526d3fd5d0SArmin Le Grand                         // is by definition a simpler, maybe more expensive representation of the same content.
15536d3fd5d0SArmin Le Grand                         process(rCandidate.get2DDecomposition(getViewInformation2D()));
15546d3fd5d0SArmin Le Grand                     }
15556d3fd5d0SArmin Le Grand                     else
15566d3fd5d0SArmin Le Grand                     {
15576d3fd5d0SArmin Le Grand 					    const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
15586d3fd5d0SArmin Le Grand 			            basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
1559cdf0e10cSrcweir 
15606d3fd5d0SArmin Le Grand                         // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
15616d3fd5d0SArmin Le Grand                         // per polygon. Split polygon until there are less than that
15626d3fd5d0SArmin Le Grand                         while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
15636d3fd5d0SArmin Le Grand                             ;
15646d3fd5d0SArmin Le Grand 
15656d3fd5d0SArmin Le Grand                         // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
15666d3fd5d0SArmin Le Grand                         // it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
15676d3fd5d0SArmin Le Grand                         // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
15686d3fd5d0SArmin Le Grand 				        Gradient aVCLGradient;
15696d3fd5d0SArmin Le Grand                         impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
15706d3fd5d0SArmin Le Grand 		                aLocalPolyPolygon.transform(maCurrentTransformation);
15716d3fd5d0SArmin Le Grand 
15726d3fd5d0SArmin Le Grand 				        // #i82145# ATM VCL printing of gradients using curved shapes does not work,
15736d3fd5d0SArmin Le Grand 				        // i submitted the bug with the given ID to THB. When that task is fixed it is
15746d3fd5d0SArmin Le Grand 				        // necessary to again remove this subdivision since it decreases possible
15756d3fd5d0SArmin Le Grand 				        // printing quality (not even resolution-dependent for now). THB will tell
15766d3fd5d0SArmin Le Grand 				        // me when that task is fixed in the master
15776d3fd5d0SArmin Le Grand 				        const PolyPolygon aToolsPolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(aLocalPolyPolygon));
15786d3fd5d0SArmin Le Grand 
15796d3fd5d0SArmin Le Grand 				        // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
15806d3fd5d0SArmin Le Grand 				        SvtGraphicFill* pSvtGraphicFill = 0;
15816d3fd5d0SArmin Le Grand 
15826d3fd5d0SArmin Le Grand 				        if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
15836d3fd5d0SArmin Le Grand 				        {
15846d3fd5d0SArmin Le Grand 					        // setup gradient stuff like in like in impgrfll
15856d3fd5d0SArmin Le Grand 					        SvtGraphicFill::GradientType eGrad(SvtGraphicFill::gradientLinear);
15866d3fd5d0SArmin Le Grand 
15876d3fd5d0SArmin Le Grand 					        switch(aVCLGradient.GetStyle())
15886d3fd5d0SArmin Le Grand 					        {
15896d3fd5d0SArmin Le Grand 						        default : // GRADIENT_LINEAR:
15906d3fd5d0SArmin Le Grand 						        case GRADIENT_AXIAL:
15916d3fd5d0SArmin Le Grand 							        eGrad = SvtGraphicFill::gradientLinear;
15926d3fd5d0SArmin Le Grand 							        break;
15936d3fd5d0SArmin Le Grand 						        case GRADIENT_RADIAL:
15946d3fd5d0SArmin Le Grand 						        case GRADIENT_ELLIPTICAL:
15956d3fd5d0SArmin Le Grand 							        eGrad = SvtGraphicFill::gradientRadial;
15966d3fd5d0SArmin Le Grand 							        break;
15976d3fd5d0SArmin Le Grand 						        case GRADIENT_SQUARE:
15986d3fd5d0SArmin Le Grand 						        case GRADIENT_RECT:
15996d3fd5d0SArmin Le Grand 							        eGrad = SvtGraphicFill::gradientRectangular;
16006d3fd5d0SArmin Le Grand 							        break;
16016d3fd5d0SArmin Le Grand 					        }
1602cdf0e10cSrcweir 
16036d3fd5d0SArmin Le Grand 					        pSvtGraphicFill = new SvtGraphicFill(
16046d3fd5d0SArmin Le Grand 						        aToolsPolyPolygon,
16056d3fd5d0SArmin Le Grand 						        Color(),
16066d3fd5d0SArmin Le Grand 						        0.0,
16076d3fd5d0SArmin Le Grand 						        SvtGraphicFill::fillEvenOdd,
16086d3fd5d0SArmin Le Grand 						        SvtGraphicFill::fillGradient,
16096d3fd5d0SArmin Le Grand 						        SvtGraphicFill::Transform(),
16106d3fd5d0SArmin Le Grand 						        false,
16116d3fd5d0SArmin Le Grand 						        SvtGraphicFill::hatchSingle,
16126d3fd5d0SArmin Le Grand 						        Color(),
16136d3fd5d0SArmin Le Grand 						        eGrad,
16146d3fd5d0SArmin Le Grand 						        aVCLGradient.GetStartColor(),
16156d3fd5d0SArmin Le Grand 						        aVCLGradient.GetEndColor(),
16166d3fd5d0SArmin Le Grand 						        aVCLGradient.GetSteps(),
16176d3fd5d0SArmin Le Grand 						        Graphic());
16186d3fd5d0SArmin Le Grand 				        }
16196d3fd5d0SArmin Le Grand 
16206d3fd5d0SArmin Le Grand 				        // call VCL directly; encapsulate with SvtGraphicFill
16216d3fd5d0SArmin Le Grand 				        impStartSvtGraphicFill(pSvtGraphicFill);
16226d3fd5d0SArmin Le Grand 		                mpOutputDevice->DrawGradient(aToolsPolyPolygon, aVCLGradient);
16236d3fd5d0SArmin Le Grand 				        impEndSvtGraphicFill(pSvtGraphicFill);
16246d3fd5d0SArmin Le Grand                     }
1625cdf0e10cSrcweir 
1626cdf0e10cSrcweir                     break;
1627cdf0e10cSrcweir                 }
1628cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
1629cdf0e10cSrcweir 				{
1630cdf0e10cSrcweir 					const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
1631cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
1632cdf0e10cSrcweir 
1633cdf0e10cSrcweir                     // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1634cdf0e10cSrcweir                     // per polygon. Split polygon until there are less than that
1635cdf0e10cSrcweir                     while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1636cdf0e10cSrcweir                         ;
1637cdf0e10cSrcweir 
1638cdf0e10cSrcweir 				    const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
1639cdf0e10cSrcweir 				    aLocalPolyPolygon.transform(maCurrentTransformation);
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir 				    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1642cdf0e10cSrcweir 				    SvtGraphicFill* pSvtGraphicFill = 0;
1643cdf0e10cSrcweir 
16444665f8d3SArmin Le Grand                     // #121267# Not needed, does not give better quality compared with
16454665f8d3SArmin Le Grand                     // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
16464665f8d3SArmin Le Grand                     // below
16474665f8d3SArmin Le Grand                     bool bSupportSvtGraphicFill(false);
16484665f8d3SArmin Le Grand 
16494665f8d3SArmin Le Grand 				    if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1650cdf0e10cSrcweir 				    {
1651cdf0e10cSrcweir 					    // setup simple color fill stuff like in impgrfll
1652cdf0e10cSrcweir 					    pSvtGraphicFill = new SvtGraphicFill(
1653cdf0e10cSrcweir 						    PolyPolygon(aLocalPolyPolygon),
1654cdf0e10cSrcweir 						    Color(aPolygonColor),
1655cdf0e10cSrcweir 						    0.0,
1656cdf0e10cSrcweir 						    SvtGraphicFill::fillEvenOdd,
1657cdf0e10cSrcweir 						    SvtGraphicFill::fillSolid,
1658cdf0e10cSrcweir 						    SvtGraphicFill::Transform(),
1659cdf0e10cSrcweir 						    false,
1660cdf0e10cSrcweir 						    SvtGraphicFill::hatchSingle,
1661cdf0e10cSrcweir 						    Color(),
1662cdf0e10cSrcweir 						    SvtGraphicFill::gradientLinear,
1663cdf0e10cSrcweir 						    Color(),
1664cdf0e10cSrcweir 						    Color(),
1665cdf0e10cSrcweir 						    0,
1666cdf0e10cSrcweir 						    Graphic());
1667cdf0e10cSrcweir 				    }
1668cdf0e10cSrcweir 
1669cdf0e10cSrcweir                     // set line and fill color
1670cdf0e10cSrcweir 				    mpOutputDevice->SetFillColor(Color(aPolygonColor));
1671cdf0e10cSrcweir 				    mpOutputDevice->SetLineColor();
1672cdf0e10cSrcweir 
1673cdf0e10cSrcweir 				    // call VCL directly; encapsulate with SvtGraphicFill
16744665f8d3SArmin Le Grand                     if(bSupportSvtGraphicFill)
16754665f8d3SArmin Le Grand                     {
16764665f8d3SArmin Le Grand                             impStartSvtGraphicFill(pSvtGraphicFill);
16774665f8d3SArmin Le Grand                     }
16784665f8d3SArmin Le Grand 
16794665f8d3SArmin Le Grand                     mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
16804665f8d3SArmin Le Grand 
16814665f8d3SArmin Le Grand                     if(bSupportSvtGraphicFill)
16824665f8d3SArmin Le Grand                     {
16834665f8d3SArmin Le Grand                         impEndSvtGraphicFill(pSvtGraphicFill);
16844665f8d3SArmin Le Grand                     }
1685cdf0e10cSrcweir 
1686cdf0e10cSrcweir 					break;
1687cdf0e10cSrcweir 				}
1688cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
1689cdf0e10cSrcweir 				{
1690cdf0e10cSrcweir                     // mask group. Special handling for MetaFiles.
1691cdf0e10cSrcweir 					const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate);
1692cdf0e10cSrcweir 
1693cdf0e10cSrcweir                     if(rMaskCandidate.getChildren().hasElements())
1694cdf0e10cSrcweir 			        {
1695cdf0e10cSrcweir 				        basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
1696cdf0e10cSrcweir 
1697cdf0e10cSrcweir 				        if(aMask.count())
1698cdf0e10cSrcweir 				        {
1699cdf0e10cSrcweir 							// prepare new mask polygon and rescue current one
1700cdf0e10cSrcweir 					        aMask.transform(maCurrentTransformation);
1701cdf0e10cSrcweir                             const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
1702cdf0e10cSrcweir 
1703cdf0e10cSrcweir                             if(maClipPolyPolygon.count())
1704cdf0e10cSrcweir                             {
1705cdf0e10cSrcweir 								// there is already a clip polygon set; build clipped union of
1706cdf0e10cSrcweir 								// current mask polygon and new one
1707cdf0e10cSrcweir 								maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
1708cdf0e10cSrcweir                                     aMask,
1709cdf0e10cSrcweir                                     maClipPolyPolygon,
1710cdf0e10cSrcweir                                     true, // #i106516# we want the inside of aMask, not the outside
1711cdf0e10cSrcweir                                     false);
1712cdf0e10cSrcweir                             }
1713cdf0e10cSrcweir                             else
1714cdf0e10cSrcweir                             {
1715cdf0e10cSrcweir                                 // use mask directly
1716cdf0e10cSrcweir                                 maClipPolyPolygon = aMask;
1717cdf0e10cSrcweir                             }
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir                             if(maClipPolyPolygon.count())
1720cdf0e10cSrcweir                             {
1721cdf0e10cSrcweir                                 // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
1722cdf0e10cSrcweir                                 // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
1723cdf0e10cSrcweir                                 // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
1724cdf0e10cSrcweir                                 mpOutputDevice->Push(PUSH_CLIPREGION);
17254665f8d3SArmin Le Grand                                 mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
17264665f8d3SArmin Le Grand 
17274665f8d3SArmin Le Grand                                 // recursively paint content
17284665f8d3SArmin Le Grand                                 // #121267# Only need to process sub-content when clip polygon is *not* empty.
17294665f8d3SArmin Le Grand                                 // If it is empty, the clip is empty and there can be nothing inside.
17304665f8d3SArmin Le Grand                                 process(rMaskCandidate.getChildren());
1731cdf0e10cSrcweir 
1732cdf0e10cSrcweir                                 // restore VCL clip region
1733cdf0e10cSrcweir                                 mpOutputDevice->Pop();
1734cdf0e10cSrcweir                             }
1735cdf0e10cSrcweir 
1736cdf0e10cSrcweir                             // restore to rescued clip polygon
1737cdf0e10cSrcweir                             maClipPolyPolygon = aLastClipPolyPolygon;
1738cdf0e10cSrcweir 				        }
1739cdf0e10cSrcweir                         else
1740cdf0e10cSrcweir                         {
1741cdf0e10cSrcweir                             // no mask, no clipping. recursively paint content
1742cdf0e10cSrcweir 					        process(rMaskCandidate.getChildren());
1743cdf0e10cSrcweir                         }
1744cdf0e10cSrcweir 			        }
1745cdf0e10cSrcweir 
1746cdf0e10cSrcweir                     break;
1747cdf0e10cSrcweir 				}
1748cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
1749cdf0e10cSrcweir 				{
1750cdf0e10cSrcweir 					// modified color group. Force output to unified color. Use default pocessing.
1751cdf0e10cSrcweir 					RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
1752cdf0e10cSrcweir 					break;
1753cdf0e10cSrcweir 				}
1754cdf0e10cSrcweir                 case PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D :
1755cdf0e10cSrcweir 				{
1756cdf0e10cSrcweir                     // HiddenGeometryPrimitive2D; to rebuilt the old MetaFile creation, it is necessary to
1757cdf0e10cSrcweir                     // not ignore them (as it was thought), but to add a MetaFile entry for them.
1758cdf0e10cSrcweir         		    basegfx::B2DRange aInvisibleRange(rCandidate.getB2DRange(getViewInformation2D()));
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir                     if(!aInvisibleRange.isEmpty())
1761cdf0e10cSrcweir                     {
1762cdf0e10cSrcweir 		                aInvisibleRange.transform(maCurrentTransformation);
1763cdf0e10cSrcweir                         const Rectangle aRectLogic(
1764cdf0e10cSrcweir 	                        (sal_Int32)floor(aInvisibleRange.getMinX()), (sal_Int32)floor(aInvisibleRange.getMinY()),
1765cdf0e10cSrcweir 	                        (sal_Int32)ceil(aInvisibleRange.getMaxX()), (sal_Int32)ceil(aInvisibleRange.getMaxY()));
1766cdf0e10cSrcweir 
1767cdf0e10cSrcweir                         mpOutputDevice->SetFillColor();
1768cdf0e10cSrcweir 		                mpOutputDevice->SetLineColor();
1769cdf0e10cSrcweir 		                mpOutputDevice->DrawRect(aRectLogic);
1770cdf0e10cSrcweir                     }
1771cdf0e10cSrcweir 
1772cdf0e10cSrcweir 					break;
1773cdf0e10cSrcweir 				}
1774cdf0e10cSrcweir 				case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
1775cdf0e10cSrcweir 				{
1776cdf0e10cSrcweir 					// for metafile: Need to examine what the pure vcl version is doing here actually
1777cdf0e10cSrcweir 					// - uses DrawTransparent with metafile for content and a gradient
1778cdf0e10cSrcweir 					// - uses DrawTransparent for single PolyPoylgons directly. Can be detected by
1779cdf0e10cSrcweir 					//   checking the content for single PolyPolygonColorPrimitive2D
1780cdf0e10cSrcweir 					const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate = static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate);
1781cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rUniTransparenceCandidate.getChildren();
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir 					if(rContent.hasElements())
1784cdf0e10cSrcweir 					{
1785cdf0e10cSrcweir                         if(0.0 == rUniTransparenceCandidate.getTransparence())
1786cdf0e10cSrcweir                         {
1787cdf0e10cSrcweir                             // not transparent at all, use content
1788cdf0e10cSrcweir 	                        process(rUniTransparenceCandidate.getChildren());
1789cdf0e10cSrcweir                         }
1790cdf0e10cSrcweir 			            else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
1791cdf0e10cSrcweir 			            {
1792cdf0e10cSrcweir 						    // try to identify a single PolyPolygonColorPrimitive2D in the
1793cdf0e10cSrcweir 						    // content part of the transparence primitive
1794cdf0e10cSrcweir 						    const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0;
1795cdf0e10cSrcweir 						    static bool bForceToMetafile(false);
1796cdf0e10cSrcweir 
1797cdf0e10cSrcweir 						    if(!bForceToMetafile && 1 == rContent.getLength())
1798cdf0e10cSrcweir 						    {
1799cdf0e10cSrcweir 							    const primitive2d::Primitive2DReference xReference(rContent[0]);
1800cdf0e10cSrcweir 							    pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
1801cdf0e10cSrcweir 						    }
1802cdf0e10cSrcweir 
1803cdf0e10cSrcweir 						    // PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
1804035a2f44SArmin Le Grand 						    // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D.
1805cdf0e10cSrcweir 						    // Check also for correct ID to exclude derived implementations
1806cdf0e10cSrcweir 						    if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
1807cdf0e10cSrcweir 						    {
1808cdf0e10cSrcweir 							    // single transparent PolyPolygon identified, use directly
1809cdf0e10cSrcweir 							    const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
1810cdf0e10cSrcweir 							    basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
1811cdf0e10cSrcweir 
1812cdf0e10cSrcweir                                 // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
1813cdf0e10cSrcweir                                 // per polygon. Split polygon until there are less than that
1814cdf0e10cSrcweir                                 while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
1815cdf0e10cSrcweir                                     ;
1816cdf0e10cSrcweir 
1817cdf0e10cSrcweir                                 // now transform
1818cdf0e10cSrcweir                                 aLocalPolyPolygon.transform(maCurrentTransformation);
1819cdf0e10cSrcweir 
1820cdf0e10cSrcweir 							    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
1821cdf0e10cSrcweir 							    SvtGraphicFill* pSvtGraphicFill = 0;
18224665f8d3SArmin Le Grand 
18234665f8d3SArmin Le Grand                                 // #121267# Not needed, does not give better quality compared with
18244665f8d3SArmin Le Grand                                 // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
18254665f8d3SArmin Le Grand                                 // below
18264665f8d3SArmin Le Grand                                 bool bSupportSvtGraphicFill(false);
1827cdf0e10cSrcweir 
18284665f8d3SArmin Le Grand 							    if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
1829cdf0e10cSrcweir 							    {
1830cdf0e10cSrcweir 								    // setup simple color with transparence fill stuff like in impgrfll
1831cdf0e10cSrcweir 								    pSvtGraphicFill = new SvtGraphicFill(
1832cdf0e10cSrcweir 									    PolyPolygon(aLocalPolyPolygon),
1833cdf0e10cSrcweir 									    Color(aPolygonColor),
1834cdf0e10cSrcweir 									    rUniTransparenceCandidate.getTransparence(),
1835cdf0e10cSrcweir 									    SvtGraphicFill::fillEvenOdd,
1836cdf0e10cSrcweir 									    SvtGraphicFill::fillSolid,
1837cdf0e10cSrcweir 									    SvtGraphicFill::Transform(),
1838cdf0e10cSrcweir 									    false,
1839cdf0e10cSrcweir 									    SvtGraphicFill::hatchSingle,
1840cdf0e10cSrcweir 									    Color(),
1841cdf0e10cSrcweir 									    SvtGraphicFill::gradientLinear,
1842cdf0e10cSrcweir 									    Color(),
1843cdf0e10cSrcweir 									    Color(),
1844cdf0e10cSrcweir 									    0,
1845cdf0e10cSrcweir 									    Graphic());
1846cdf0e10cSrcweir 							    }
1847cdf0e10cSrcweir 
1848cdf0e10cSrcweir                                 // set line and fill color
1849cdf0e10cSrcweir 							    const sal_uInt16 nTransPercentVcl((sal_uInt16)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 100.0));
1850cdf0e10cSrcweir 							    mpOutputDevice->SetFillColor(Color(aPolygonColor));
1851cdf0e10cSrcweir 							    mpOutputDevice->SetLineColor();
1852cdf0e10cSrcweir 
1853cdf0e10cSrcweir 							    // call VCL directly; encapsulate with SvtGraphicFill
18544665f8d3SArmin Le Grand                                 if(bSupportSvtGraphicFill)
18554665f8d3SArmin Le Grand                                 {
18564665f8d3SArmin Le Grand                                     impStartSvtGraphicFill(pSvtGraphicFill);
18574665f8d3SArmin Le Grand                                 }
18584665f8d3SArmin Le Grand 
1859cdf0e10cSrcweir 							    mpOutputDevice->DrawTransparent(
1860cdf0e10cSrcweir 								    PolyPolygon(aLocalPolyPolygon),
1861cdf0e10cSrcweir 								    nTransPercentVcl);
18624665f8d3SArmin Le Grand 
18634665f8d3SArmin Le Grand                                 if(bSupportSvtGraphicFill)
18644665f8d3SArmin Le Grand                                 {
18654665f8d3SArmin Le Grand                                     impEndSvtGraphicFill(pSvtGraphicFill);
18664665f8d3SArmin Le Grand                                 }
1867cdf0e10cSrcweir 						    }
1868cdf0e10cSrcweir 						    else
1869cdf0e10cSrcweir 						    {
1870cdf0e10cSrcweir 							    // svae old mfCurrentUnifiedTransparence and set new one
1871cdf0e10cSrcweir 							    // so that contained SvtGraphicStroke may use the current one
1872cdf0e10cSrcweir 							    const double fLastCurrentUnifiedTransparence(mfCurrentUnifiedTransparence);
1873cdf0e10cSrcweir                                 // #i105377# paint the content metafile opaque as the transparency gets
1874cdf0e10cSrcweir                                 // split of into the gradient below
1875cdf0e10cSrcweir 							    // mfCurrentUnifiedTransparence = rUniTransparenceCandidate.getTransparence();
1876cdf0e10cSrcweir 							    mfCurrentUnifiedTransparence = 0;
1877cdf0e10cSrcweir 
1878cdf0e10cSrcweir 							    // various content, create content-metafile
1879cdf0e10cSrcweir 							    GDIMetaFile aContentMetafile;
1880cdf0e10cSrcweir                                 const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1881cdf0e10cSrcweir 
1882cdf0e10cSrcweir 							    // restore mfCurrentUnifiedTransparence; it may have been used
1883cdf0e10cSrcweir 							    // while processing the sub-content in impDumpToMetaFile
1884cdf0e10cSrcweir 							    mfCurrentUnifiedTransparence = fLastCurrentUnifiedTransparence;
1885cdf0e10cSrcweir 
1886cdf0e10cSrcweir 							    // create uniform VCL gradient for uniform transparency
1887cdf0e10cSrcweir 							    Gradient aVCLGradient;
1888cdf0e10cSrcweir 							    const sal_uInt8 nTransPercentVcl((sal_uInt8)basegfx::fround(rUniTransparenceCandidate.getTransparence() * 255.0));
1889cdf0e10cSrcweir 							    const Color aTransColor(nTransPercentVcl, nTransPercentVcl, nTransPercentVcl);
1890cdf0e10cSrcweir 
1891cdf0e10cSrcweir 							    aVCLGradient.SetStyle(GRADIENT_LINEAR);
1892cdf0e10cSrcweir 							    aVCLGradient.SetStartColor(aTransColor);
1893cdf0e10cSrcweir 							    aVCLGradient.SetEndColor(aTransColor);
1894cdf0e10cSrcweir 							    aVCLGradient.SetAngle(0);
1895cdf0e10cSrcweir 							    aVCLGradient.SetBorder(0);
1896cdf0e10cSrcweir 							    aVCLGradient.SetOfsX(0);
1897cdf0e10cSrcweir 							    aVCLGradient.SetOfsY(0);
1898cdf0e10cSrcweir 							    aVCLGradient.SetStartIntensity(100);
1899cdf0e10cSrcweir 							    aVCLGradient.SetEndIntensity(100);
1900cdf0e10cSrcweir 							    aVCLGradient.SetSteps(2);
1901cdf0e10cSrcweir 
1902cdf0e10cSrcweir 							    // render it to VCL
1903cdf0e10cSrcweir 							    mpOutputDevice->DrawTransparent(
1904cdf0e10cSrcweir 								    aContentMetafile, aPrimitiveRectangle.TopLeft(),
1905cdf0e10cSrcweir 								    aPrimitiveRectangle.GetSize(), aVCLGradient);
1906cdf0e10cSrcweir 						    }
1907cdf0e10cSrcweir 					    }
1908cdf0e10cSrcweir                     }
1909cdf0e10cSrcweir 
1910cdf0e10cSrcweir 					break;
1911cdf0e10cSrcweir 				}
1912cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
1913cdf0e10cSrcweir 				{
1914cdf0e10cSrcweir 					// for metafile: Need to examine what the pure vcl version is doing here actually
1915cdf0e10cSrcweir 					// - uses DrawTransparent with metafile for content and a gradient
1916cdf0e10cSrcweir 					// i can detect this here with checking the gradient part for a single
1917cdf0e10cSrcweir 					// FillGradientPrimitive2D and reconstruct the gradient.
1918cdf0e10cSrcweir 					// If that detection goes wrong, i have to create an transparence-blended bitmap. Eventually
1919cdf0e10cSrcweir 					// do that in stripes, else RenderTransparencePrimitive2D may just be used
1920cdf0e10cSrcweir 					const primitive2d::TransparencePrimitive2D& rTransparenceCandidate = static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate);
1921cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rContent = rTransparenceCandidate.getChildren();
1922cdf0e10cSrcweir 					const primitive2d::Primitive2DSequence rTransparence = rTransparenceCandidate.getTransparence();
1923cdf0e10cSrcweir 
1924cdf0e10cSrcweir 					if(rContent.hasElements() && rTransparence.hasElements())
1925cdf0e10cSrcweir 					{
1926cdf0e10cSrcweir 						// try to identify a single FillGradientPrimitive2D in the
1927cdf0e10cSrcweir 						// transparence part of the primitive
1928cdf0e10cSrcweir 						const primitive2d::FillGradientPrimitive2D* pFiGradient = 0;
1929cdf0e10cSrcweir 						static bool bForceToBigTransparentVDev(false);
1930cdf0e10cSrcweir 
1931cdf0e10cSrcweir 						if(!bForceToBigTransparentVDev && 1 == rTransparence.getLength())
1932cdf0e10cSrcweir 						{
1933cdf0e10cSrcweir 							const primitive2d::Primitive2DReference xReference(rTransparence[0]);
1934cdf0e10cSrcweir 							pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get());
1935cdf0e10cSrcweir 						}
1936cdf0e10cSrcweir 
1937cdf0e10cSrcweir 						// Check also for correct ID to exclude derived implementations
1938cdf0e10cSrcweir 						if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID())
1939cdf0e10cSrcweir 						{
1940cdf0e10cSrcweir 							// various content, create content-metafile
1941cdf0e10cSrcweir 							GDIMetaFile aContentMetafile;
1942cdf0e10cSrcweir                             const Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile));
1943cdf0e10cSrcweir 
1944cdf0e10cSrcweir 							// re-create a VCL-gradient from FillGradientPrimitive2D
1945cdf0e10cSrcweir 							Gradient aVCLGradient;
1946cdf0e10cSrcweir                             impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true);
1947cdf0e10cSrcweir 
1948cdf0e10cSrcweir 							// render it to VCL
1949cdf0e10cSrcweir 							mpOutputDevice->DrawTransparent(
1950cdf0e10cSrcweir 								aContentMetafile, aPrimitiveRectangle.TopLeft(),
1951cdf0e10cSrcweir 								aPrimitiveRectangle.GetSize(), aVCLGradient);
1952cdf0e10cSrcweir                         }
1953cdf0e10cSrcweir                         else
1954cdf0e10cSrcweir                         {
1955cdf0e10cSrcweir 	    				    // sub-transparence group. Draw to VDev first.
1956cdf0e10cSrcweir                             // this may get refined to tiling when resolution is too big here
1957cdf0e10cSrcweir 
1958cdf0e10cSrcweir                             // need to avoid switching off MapMode stuff here; maybe need another
1959cdf0e10cSrcweir                             // tooling class, cannot just do the same as with the pixel renderer.
1960cdf0e10cSrcweir                             // Need to experiment...
1961cdf0e10cSrcweir 
1962cdf0e10cSrcweir                             // Okay, basic implementation finished and tested. The DPI stuff was hard
1963cdf0e10cSrcweir                             // and not easy to find out that it's needed.
1964cdf0e10cSrcweir                             // Since this will not yet happen normally (as long as noone constructs
1965cdf0e10cSrcweir                             // transparence primitives with non-trivial transparence content) i will for now not
1966cdf0e10cSrcweir                             // refine to tiling here.
1967cdf0e10cSrcweir 
1968cdf0e10cSrcweir 				            basegfx::B2DRange aViewRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rContent, getViewInformation2D()));
1969cdf0e10cSrcweir 				            aViewRange.transform(maCurrentTransformation);
1970cdf0e10cSrcweir 		                    const Rectangle aRectLogic(
1971cdf0e10cSrcweir 			                    (sal_Int32)floor(aViewRange.getMinX()), (sal_Int32)floor(aViewRange.getMinY()),
1972cdf0e10cSrcweir 			                    (sal_Int32)ceil(aViewRange.getMaxX()), (sal_Int32)ceil(aViewRange.getMaxY()));
1973cdf0e10cSrcweir 		                    const Rectangle aRectPixel(mpOutputDevice->LogicToPixel(aRectLogic));
197489cebadeSArmin Le Grand                             Size aSizePixel(aRectPixel.GetSize());
1975cdf0e10cSrcweir                     		const Point aEmptyPoint;
1976cdf0e10cSrcweir                             VirtualDevice aBufferDevice;
197789cebadeSArmin Le Grand                             const sal_uInt32 nMaxQuadratPixels(500000);
197889cebadeSArmin Le Grand                             const sal_uInt32 nViewVisibleArea(aSizePixel.getWidth() * aSizePixel.getHeight());
197989cebadeSArmin Le Grand                             double fReduceFactor(1.0);
198089cebadeSArmin Le Grand 
198189cebadeSArmin Le Grand                             if(nViewVisibleArea > nMaxQuadratPixels)
198289cebadeSArmin Le Grand                             {
198389cebadeSArmin Le Grand                                 // reduce render size
198489cebadeSArmin Le Grand                                 fReduceFactor = sqrt((double)nMaxQuadratPixels / (double)nViewVisibleArea);
198589cebadeSArmin Le Grand                                 aSizePixel = Size(basegfx::fround((double)aSizePixel.getWidth() * fReduceFactor),
198689cebadeSArmin Le Grand                                     basegfx::fround((double)aSizePixel.getHeight() * fReduceFactor));
198789cebadeSArmin Le Grand                             }
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir                             if(aBufferDevice.SetOutputSizePixel(aSizePixel))
1990cdf0e10cSrcweir                             {
1991cdf0e10cSrcweir                                 // create and set MapModes for target devices
1992cdf0e10cSrcweir 		                        MapMode aNewMapMode(mpOutputDevice->GetMapMode());
1993cdf0e10cSrcweir 		                        aNewMapMode.SetOrigin(Point(-aRectLogic.Left(), -aRectLogic.Top()));
1994cdf0e10cSrcweir 		                        aBufferDevice.SetMapMode(aNewMapMode);
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir                                 // prepare view transformation for target renderers
1997cdf0e10cSrcweir                                 // ATTENTION! Need to apply another scaling because of the potential DPI differences
1998cdf0e10cSrcweir                                 // between Printer and VDev (mpOutputDevice and aBufferDevice here).
1999cdf0e10cSrcweir                                 // To get the DPI, LogicToPixel from (1,1) from MAP_INCH needs to be used.
2000cdf0e10cSrcweir                                 basegfx::B2DHomMatrix aViewTransform(aBufferDevice.GetViewTransformation());
2001cdf0e10cSrcweir                                 const Size aDPIOld(mpOutputDevice->LogicToPixel(Size(1, 1), MAP_INCH));
2002cdf0e10cSrcweir                                 const Size aDPINew(aBufferDevice.LogicToPixel(Size(1, 1), MAP_INCH));
2003cdf0e10cSrcweir                                 const double fDPIXChange((double)aDPIOld.getWidth() / (double)aDPINew.getWidth());
2004cdf0e10cSrcweir                                 const double fDPIYChange((double)aDPIOld.getHeight() / (double)aDPINew.getHeight());
2005cdf0e10cSrcweir 
2006cdf0e10cSrcweir                                 if(!basegfx::fTools::equal(fDPIXChange, 1.0) || !basegfx::fTools::equal(fDPIYChange, 1.0))
2007cdf0e10cSrcweir                                 {
2008cdf0e10cSrcweir                                     aViewTransform.scale(fDPIXChange, fDPIYChange);
2009cdf0e10cSrcweir                                 }
2010cdf0e10cSrcweir 
201189cebadeSArmin Le Grand                                 // also take scaling from Size reduction into acount
201289cebadeSArmin Le Grand                                 if(!basegfx::fTools::equal(fReduceFactor, 1.0))
201389cebadeSArmin Le Grand                                 {
201489cebadeSArmin Le Grand                                     aViewTransform.scale(fReduceFactor, fReduceFactor);
201589cebadeSArmin Le Grand                                 }
201689cebadeSArmin Le Grand 
2017cdf0e10cSrcweir                                 // create view information and pixel renderer. Reuse known ViewInformation
2018cdf0e10cSrcweir 								// except new transformation and range
2019cdf0e10cSrcweir                                 const geometry::ViewInformation2D aViewInfo(
2020cdf0e10cSrcweir 									getViewInformation2D().getObjectTransformation(),
2021cdf0e10cSrcweir 									aViewTransform,
2022cdf0e10cSrcweir 									aViewRange,
2023cdf0e10cSrcweir 									getViewInformation2D().getVisualizedPage(),
2024cdf0e10cSrcweir 									getViewInformation2D().getViewTime(),
2025cdf0e10cSrcweir 									getViewInformation2D().getExtendedInformationSequence());
2026cdf0e10cSrcweir 
2027cdf0e10cSrcweir 								VclPixelProcessor2D aBufferProcessor(aViewInfo, aBufferDevice);
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir                                 // draw content using pixel renderer
2030cdf0e10cSrcweir 				                aBufferProcessor.process(rContent);
2031cdf0e10cSrcweir 	                            const Bitmap aBmContent(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
2032cdf0e10cSrcweir 
2033cdf0e10cSrcweir                                 // draw transparence using pixel renderer
2034cdf0e10cSrcweir                                 aBufferDevice.Erase();
2035cdf0e10cSrcweir 				                aBufferProcessor.process(rTransparence);
2036cdf0e10cSrcweir                         		const AlphaMask aBmAlpha(aBufferDevice.GetBitmap(aEmptyPoint, aSizePixel));
2037cdf0e10cSrcweir 
2038cdf0e10cSrcweir #ifdef DBG_UTIL
2039cdf0e10cSrcweir                                 static bool bDoSaveForVisualControl(false);
2040cdf0e10cSrcweir 			                    if(bDoSaveForVisualControl)
2041cdf0e10cSrcweir 			                    {
2042cdf0e10cSrcweir 				                    SvFileStream aNew(String(ByteString( "c:\\test.bmp" ), RTL_TEXTENCODING_UTF8), STREAM_WRITE|STREAM_TRUNC);
2043*45fd3b9aSArmin Le Grand 
2044*45fd3b9aSArmin Le Grand                                     WriteDIB(aBmContent, aNew, false, true);
2045cdf0e10cSrcweir 			                    }
2046cdf0e10cSrcweir #endif
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir                                 // paint
2049cdf0e10cSrcweir                                 mpOutputDevice->DrawBitmapEx(
2050cdf0e10cSrcweir                                     aRectLogic.TopLeft(),
2051cdf0e10cSrcweir                                     aRectLogic.GetSize(),
2052cdf0e10cSrcweir                                     BitmapEx(aBmContent, aBmAlpha));
2053cdf0e10cSrcweir                             }
2054cdf0e10cSrcweir                         }
2055cdf0e10cSrcweir                     }
2056cdf0e10cSrcweir 
2057cdf0e10cSrcweir 					break;
2058cdf0e10cSrcweir 				}
2059cdf0e10cSrcweir 				case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
2060cdf0e10cSrcweir 				{
2061cdf0e10cSrcweir 					// use default transform group pocessing
2062cdf0e10cSrcweir 					RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
2063cdf0e10cSrcweir 					break;
2064cdf0e10cSrcweir 				}
2065cdf0e10cSrcweir                 case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
2066cdf0e10cSrcweir 				{
2067cdf0e10cSrcweir 					// new XDrawPage for ViewInformation2D
2068cdf0e10cSrcweir 					RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
2069cdf0e10cSrcweir 					break;
2070cdf0e10cSrcweir 				}
2071cdf0e10cSrcweir 				case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
2072cdf0e10cSrcweir 				{
2073cdf0e10cSrcweir 					// use default marker array pocessing
2074cdf0e10cSrcweir 					RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
2075cdf0e10cSrcweir 					break;
2076cdf0e10cSrcweir 				}
2077cdf0e10cSrcweir 				case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
2078cdf0e10cSrcweir 				{
2079cdf0e10cSrcweir 					// use default point array pocessing
2080cdf0e10cSrcweir 					RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
2081cdf0e10cSrcweir 					break;
2082cdf0e10cSrcweir 				}
2083cdf0e10cSrcweir 				case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
2084cdf0e10cSrcweir 				{
2085cdf0e10cSrcweir 					// structured tag primitive
2086cdf0e10cSrcweir 					const primitive2d::StructureTagPrimitive2D& rStructureTagCandidate = static_cast< const primitive2d::StructureTagPrimitive2D& >(rCandidate);
2087cdf0e10cSrcweir 					const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
2088cdf0e10cSrcweir 					const bool bTagUsed(vcl::PDFWriter::NonStructElement != rTagElement);
2089cdf0e10cSrcweir 
2090cdf0e10cSrcweir 					if(mpPDFExtOutDevData &&  bTagUsed)
2091cdf0e10cSrcweir 					{
2092cdf0e10cSrcweir 						// write start tag
2093cdf0e10cSrcweir 						mpPDFExtOutDevData->BeginStructureElement(rTagElement);
2094cdf0e10cSrcweir 					}
2095cdf0e10cSrcweir 
2096cdf0e10cSrcweir 					// proccess childs normally
2097cdf0e10cSrcweir 					process(rStructureTagCandidate.getChildren());
2098cdf0e10cSrcweir 
2099cdf0e10cSrcweir 					if(mpPDFExtOutDevData &&  bTagUsed)
2100cdf0e10cSrcweir 					{
2101cdf0e10cSrcweir 						// write end tag
2102cdf0e10cSrcweir 						mpPDFExtOutDevData->EndStructureElement();
2103cdf0e10cSrcweir 					}
2104cdf0e10cSrcweir 
2105cdf0e10cSrcweir 					break;
2106cdf0e10cSrcweir 				}
2107cdf0e10cSrcweir                 case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
2108cdf0e10cSrcweir                 {
2109cdf0e10cSrcweir 					RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
2110cdf0e10cSrcweir                     break;
2111cdf0e10cSrcweir                 }
2112cdf0e10cSrcweir 				default :
2113cdf0e10cSrcweir 				{
2114cdf0e10cSrcweir                     // process recursively
2115cdf0e10cSrcweir 					process(rCandidate.get2DDecomposition(getViewInformation2D()));
2116cdf0e10cSrcweir 					break;
2117cdf0e10cSrcweir 				}
2118cdf0e10cSrcweir 			}
2119cdf0e10cSrcweir 		}
2120cdf0e10cSrcweir 	} // end of namespace processor2d
2121cdf0e10cSrcweir } // end of namespace drawinglayer
2122cdf0e10cSrcweir 
2123cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
2124cdf0e10cSrcweir // eof
2125