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