1*4665f8d3SArmin Le Grand /**************************************************************
2*4665f8d3SArmin Le Grand  *
3*4665f8d3SArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4*4665f8d3SArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5*4665f8d3SArmin Le Grand  * distributed with this work for additional information
6*4665f8d3SArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7*4665f8d3SArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8*4665f8d3SArmin Le Grand  * "License"); you may not use this file except in compliance
9*4665f8d3SArmin Le Grand  * with the License.  You may obtain a copy of the License at
10*4665f8d3SArmin Le Grand  *
11*4665f8d3SArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12*4665f8d3SArmin Le Grand  *
13*4665f8d3SArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14*4665f8d3SArmin Le Grand  * software distributed under the License is distributed on an
15*4665f8d3SArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*4665f8d3SArmin Le Grand  * KIND, either express or implied.  See the License for the
17*4665f8d3SArmin Le Grand  * specific language governing permissions and limitations
18*4665f8d3SArmin Le Grand  * under the License.
19*4665f8d3SArmin Le Grand  *
20*4665f8d3SArmin Le Grand  *************************************************************/
21*4665f8d3SArmin Le Grand 
22*4665f8d3SArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
23*4665f8d3SArmin Le Grand #include "precompiled_vcl.hxx"
24*4665f8d3SArmin Le Grand 
25*4665f8d3SArmin Le Grand #include <vcl/gdimetafiletools.hxx>
26*4665f8d3SArmin Le Grand #include <vcl/metaact.hxx>
27*4665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolygonclipper.hxx>
28*4665f8d3SArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
29*4665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolypolygontools.hxx>
30*4665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx>
31*4665f8d3SArmin Le Grand #include <vcl/virdev.hxx>
32*4665f8d3SArmin Le Grand #include <vcl/svapp.hxx>
33*4665f8d3SArmin Le Grand #include <vcl/graphictools.hxx>
34*4665f8d3SArmin Le Grand 
35*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
36*4665f8d3SArmin Le Grand // helpers
37*4665f8d3SArmin Le Grand 
38*4665f8d3SArmin Le Grand namespace
39*4665f8d3SArmin Le Grand {
handleGeometricContent(const basegfx::B2DPolyPolygon & rClip,const basegfx::B2DPolyPolygon & rSource,GDIMetaFile & rTarget,bool bStroke)40*4665f8d3SArmin Le Grand     bool handleGeometricContent(
41*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
42*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rSource,
43*4665f8d3SArmin Le Grand         GDIMetaFile& rTarget,
44*4665f8d3SArmin Le Grand         bool bStroke)
45*4665f8d3SArmin Le Grand     {
46*4665f8d3SArmin Le Grand         if(rSource.count() && rClip.count())
47*4665f8d3SArmin Le Grand         {
48*4665f8d3SArmin Le Grand             const basegfx::B2DPolyPolygon aResult(
49*4665f8d3SArmin Le Grand                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
50*4665f8d3SArmin Le Grand                     rSource,
51*4665f8d3SArmin Le Grand                     rClip,
52*4665f8d3SArmin Le Grand                     true, // inside
53*4665f8d3SArmin Le Grand                     bStroke));
54*4665f8d3SArmin Le Grand 
55*4665f8d3SArmin Le Grand             if(aResult.count())
56*4665f8d3SArmin Le Grand             {
57*4665f8d3SArmin Le Grand                 if(aResult == rSource)
58*4665f8d3SArmin Le Grand                 {
59*4665f8d3SArmin Le Grand                     // not clipped, but inside. Add original
60*4665f8d3SArmin Le Grand                     return false;
61*4665f8d3SArmin Le Grand                 }
62*4665f8d3SArmin Le Grand                 else
63*4665f8d3SArmin Le Grand                 {
64*4665f8d3SArmin Le Grand                     // add clipped geometry
65*4665f8d3SArmin Le Grand                     if(bStroke)
66*4665f8d3SArmin Le Grand                     {
67*4665f8d3SArmin Le Grand                         for(sal_uInt32 a(0); a < aResult.count(); a++)
68*4665f8d3SArmin Le Grand                         {
69*4665f8d3SArmin Le Grand                             rTarget.AddAction(
70*4665f8d3SArmin Le Grand                                 new MetaPolyLineAction(
71*4665f8d3SArmin Le Grand                                     Polygon(aResult.getB2DPolygon(a))));
72*4665f8d3SArmin Le Grand                         }
73*4665f8d3SArmin Le Grand                     }
74*4665f8d3SArmin Le Grand                     else
75*4665f8d3SArmin Le Grand                     {
76*4665f8d3SArmin Le Grand                         rTarget.AddAction(
77*4665f8d3SArmin Le Grand                             new MetaPolyPolygonAction(
78*4665f8d3SArmin Le Grand                                 PolyPolygon(aResult)));
79*4665f8d3SArmin Le Grand                     }
80*4665f8d3SArmin Le Grand                 }
81*4665f8d3SArmin Le Grand             }
82*4665f8d3SArmin Le Grand         }
83*4665f8d3SArmin Le Grand 
84*4665f8d3SArmin Le Grand         return true;
85*4665f8d3SArmin Le Grand     }
86*4665f8d3SArmin Le Grand 
handleGradientContent(const basegfx::B2DPolyPolygon & rClip,const basegfx::B2DPolyPolygon & rSource,const Gradient & rGradient,GDIMetaFile & rTarget)87*4665f8d3SArmin Le Grand     bool handleGradientContent(
88*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
89*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rSource,
90*4665f8d3SArmin Le Grand         const Gradient& rGradient,
91*4665f8d3SArmin Le Grand         GDIMetaFile& rTarget)
92*4665f8d3SArmin Le Grand     {
93*4665f8d3SArmin Le Grand         if(rSource.count() && rClip.count())
94*4665f8d3SArmin Le Grand         {
95*4665f8d3SArmin Le Grand             const basegfx::B2DPolyPolygon aResult(
96*4665f8d3SArmin Le Grand                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
97*4665f8d3SArmin Le Grand                     rSource,
98*4665f8d3SArmin Le Grand                     rClip,
99*4665f8d3SArmin Le Grand                     true, // inside
100*4665f8d3SArmin Le Grand                     false)); // stroke
101*4665f8d3SArmin Le Grand 
102*4665f8d3SArmin Le Grand             if(aResult.count())
103*4665f8d3SArmin Le Grand             {
104*4665f8d3SArmin Le Grand                 if(aResult == rSource)
105*4665f8d3SArmin Le Grand                 {
106*4665f8d3SArmin Le Grand                     // not clipped, but inside. Add original
107*4665f8d3SArmin Le Grand                     return false;
108*4665f8d3SArmin Le Grand                 }
109*4665f8d3SArmin Le Grand                 else
110*4665f8d3SArmin Le Grand                 {
111*4665f8d3SArmin Le Grand                     // add clipped geometry
112*4665f8d3SArmin Le Grand                     rTarget.AddAction(
113*4665f8d3SArmin Le Grand                         new MetaGradientExAction(
114*4665f8d3SArmin Le Grand                             PolyPolygon(aResult),
115*4665f8d3SArmin Le Grand                             rGradient));
116*4665f8d3SArmin Le Grand                 }
117*4665f8d3SArmin Le Grand             }
118*4665f8d3SArmin Le Grand         }
119*4665f8d3SArmin Le Grand 
120*4665f8d3SArmin Le Grand         return true;
121*4665f8d3SArmin Le Grand     }
122*4665f8d3SArmin Le Grand 
handleBitmapContent(const basegfx::B2DPolyPolygon & rClip,const Point & rPoint,const Size & rSize,const BitmapEx & rBitmapEx,GDIMetaFile & rTarget)123*4665f8d3SArmin Le Grand     bool handleBitmapContent(
124*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
125*4665f8d3SArmin Le Grand         const Point& rPoint,
126*4665f8d3SArmin Le Grand         const Size& rSize,
127*4665f8d3SArmin Le Grand         const BitmapEx& rBitmapEx,
128*4665f8d3SArmin Le Grand         GDIMetaFile& rTarget)
129*4665f8d3SArmin Le Grand     {
130*4665f8d3SArmin Le Grand         if(!rSize.Width() || !rSize.Height() || rBitmapEx.IsEmpty())
131*4665f8d3SArmin Le Grand         {
132*4665f8d3SArmin Le Grand             // bitmap or size is empty
133*4665f8d3SArmin Le Grand             return true;
134*4665f8d3SArmin Le Grand         }
135*4665f8d3SArmin Le Grand 
136*4665f8d3SArmin Le Grand         const basegfx::B2DRange aLogicBitmapRange(
137*4665f8d3SArmin Le Grand             rPoint.X(), rPoint.Y(),
138*4665f8d3SArmin Le Grand             rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height());
139*4665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon aClipOfBitmap(
140*4665f8d3SArmin Le Grand             basegfx::tools::clipPolyPolygonOnRange(
141*4665f8d3SArmin Le Grand                 rClip,
142*4665f8d3SArmin Le Grand                 aLogicBitmapRange,
143*4665f8d3SArmin Le Grand                 true,
144*4665f8d3SArmin Le Grand                 false)); // stroke
145*4665f8d3SArmin Le Grand 
146*4665f8d3SArmin Le Grand         if(!aClipOfBitmap.count())
147*4665f8d3SArmin Le Grand         {
148*4665f8d3SArmin Le Grand             // outside clip region
149*4665f8d3SArmin Le Grand             return true;
150*4665f8d3SArmin Le Grand         }
151*4665f8d3SArmin Le Grand 
152*4665f8d3SArmin Le Grand         // inside or overlapping. Use area to find out if it is completely
153*4665f8d3SArmin Le Grand         // covering (inside) or overlapping
154*4665f8d3SArmin Le Grand         const double fClipArea(basegfx::tools::getArea(aClipOfBitmap));
155*4665f8d3SArmin Le Grand         const double fBitmapArea(
156*4665f8d3SArmin Le Grand             aLogicBitmapRange.getWidth() * aLogicBitmapRange.getWidth() +
157*4665f8d3SArmin Le Grand             aLogicBitmapRange.getHeight() * aLogicBitmapRange.getHeight());
158*4665f8d3SArmin Le Grand         const double fFactor(fClipArea / fBitmapArea);
159*4665f8d3SArmin Le Grand 
160*4665f8d3SArmin Le Grand         if(basegfx::fTools::more(fFactor, 1.0 - 0.001))
161*4665f8d3SArmin Le Grand         {
162*4665f8d3SArmin Le Grand             // completely covering (with 0.1% tolerance)
163*4665f8d3SArmin Le Grand             return false;
164*4665f8d3SArmin Le Grand         }
165*4665f8d3SArmin Le Grand 
166*4665f8d3SArmin Le Grand         // needs clipping (with 0.1% tolerance). Prepare VirtualDevice
167*4665f8d3SArmin Le Grand         // in pixel mode for alpha channel painting (black is transparent,
168*4665f8d3SArmin Le Grand         // white to paint 100% opacity)
169*4665f8d3SArmin Le Grand         const Size aSizePixel(rBitmapEx.GetSizePixel());
170*4665f8d3SArmin Le Grand         VirtualDevice aVDev;
171*4665f8d3SArmin Le Grand 
172*4665f8d3SArmin Le Grand         aVDev.SetOutputSizePixel(aSizePixel);
173*4665f8d3SArmin Le Grand         aVDev.EnableMapMode(false);
174*4665f8d3SArmin Le Grand         aVDev.SetFillColor(COL_WHITE);
175*4665f8d3SArmin Le Grand         aVDev.SetLineColor();
176*4665f8d3SArmin Le Grand 
177*4665f8d3SArmin Le Grand         if(rBitmapEx.IsTransparent())
178*4665f8d3SArmin Le Grand         {
179*4665f8d3SArmin Le Grand             // use given alpha channel
180*4665f8d3SArmin Le Grand             aVDev.DrawBitmap(Point(0, 0), rBitmapEx.GetAlpha().GetBitmap());
181*4665f8d3SArmin Le Grand         }
182*4665f8d3SArmin Le Grand         else
183*4665f8d3SArmin Le Grand         {
184*4665f8d3SArmin Le Grand             // reset alpha channel
185*4665f8d3SArmin Le Grand             aVDev.SetBackground(Wallpaper(Color(COL_BLACK)));
186*4665f8d3SArmin Le Grand             aVDev.Erase();
187*4665f8d3SArmin Le Grand         }
188*4665f8d3SArmin Le Grand 
189*4665f8d3SArmin Le Grand         // transform polygon from clipping to pixel coordinates
190*4665f8d3SArmin Le Grand         basegfx::B2DPolyPolygon aPixelPoly(aClipOfBitmap);
191*4665f8d3SArmin Le Grand         basegfx::B2DHomMatrix aTransform;
192*4665f8d3SArmin Le Grand 
193*4665f8d3SArmin Le Grand         aTransform.translate(-aLogicBitmapRange.getMinX(), -aLogicBitmapRange.getMinY());
194*4665f8d3SArmin Le Grand         aTransform.scale(
195*4665f8d3SArmin Le Grand             static_cast< double >(aSizePixel.Width()) / aLogicBitmapRange.getWidth(),
196*4665f8d3SArmin Le Grand             static_cast< double >(aSizePixel.Height()) / aLogicBitmapRange.getHeight());
197*4665f8d3SArmin Le Grand         aPixelPoly.transform(aTransform);
198*4665f8d3SArmin Le Grand 
199*4665f8d3SArmin Le Grand         // to fill the non-covered parts, use the Xor fill rule of
200*4665f8d3SArmin Le Grand         // PolyPolygon painting. Start with a all-covering polygon and
201*4665f8d3SArmin Le Grand         // add the clip polygon one
202*4665f8d3SArmin Le Grand         basegfx::B2DPolyPolygon aInvertPixelPoly;
203*4665f8d3SArmin Le Grand 
204*4665f8d3SArmin Le Grand         aInvertPixelPoly.append(
205*4665f8d3SArmin Le Grand             basegfx::tools::createPolygonFromRect(
206*4665f8d3SArmin Le Grand                 basegfx::B2DRange(
207*4665f8d3SArmin Le Grand                     0.0, 0.0,
208*4665f8d3SArmin Le Grand                     aSizePixel.Width(), aSizePixel.Height())));
209*4665f8d3SArmin Le Grand         aInvertPixelPoly.append(aPixelPoly);
210*4665f8d3SArmin Le Grand 
211*4665f8d3SArmin Le Grand         // paint as alpha
212*4665f8d3SArmin Le Grand         aVDev.DrawPolyPolygon(aInvertPixelPoly);
213*4665f8d3SArmin Le Grand 
214*4665f8d3SArmin Le Grand         // get created alpha mask and set defaults
215*4665f8d3SArmin Le Grand         AlphaMask aAlpha(
216*4665f8d3SArmin Le Grand             aVDev.GetBitmap(
217*4665f8d3SArmin Le Grand                 Point(0, 0),
218*4665f8d3SArmin Le Grand                 aSizePixel));
219*4665f8d3SArmin Le Grand 
220*4665f8d3SArmin Le Grand         aAlpha.SetPrefSize(rBitmapEx.GetPrefSize());
221*4665f8d3SArmin Le Grand         aAlpha.SetPrefMapMode(rBitmapEx.GetPrefMapMode());
222*4665f8d3SArmin Le Grand 
223*4665f8d3SArmin Le Grand         // add new action replacing the old one
224*4665f8d3SArmin Le Grand         rTarget.AddAction(
225*4665f8d3SArmin Le Grand             new MetaBmpExScaleAction(
226*4665f8d3SArmin Le Grand                 Point(
227*4665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getMinX()),
228*4665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getMinY())),
229*4665f8d3SArmin Le Grand                 Size(
230*4665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getWidth()),
231*4665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getHeight())),
232*4665f8d3SArmin Le Grand                 BitmapEx(rBitmapEx.GetBitmap(), aAlpha)));
233*4665f8d3SArmin Le Grand 
234*4665f8d3SArmin Le Grand         return true;
235*4665f8d3SArmin Le Grand     }
236*4665f8d3SArmin Le Grand 
addSvtGraphicStroke(const SvtGraphicStroke & rStroke,GDIMetaFile & rTarget)237*4665f8d3SArmin Le Grand     void addSvtGraphicStroke(const SvtGraphicStroke& rStroke, GDIMetaFile& rTarget)
238*4665f8d3SArmin Le Grand     {
239*4665f8d3SArmin Le Grand         // write SvtGraphicFill
240*4665f8d3SArmin Le Grand         SvMemoryStream aMemStm;
241*4665f8d3SArmin Le Grand         aMemStm << rStroke;
242*4665f8d3SArmin Le Grand         rTarget.AddAction(
243*4665f8d3SArmin Le Grand             new MetaCommentAction(
244*4665f8d3SArmin Le Grand                 "XPATHSTROKE_SEQ_BEGIN",
245*4665f8d3SArmin Le Grand                 0,
246*4665f8d3SArmin Le Grand                 static_cast< const sal_uInt8* >(aMemStm.GetData()),
247*4665f8d3SArmin Le Grand                 aMemStm.Seek(STREAM_SEEK_TO_END)));
248*4665f8d3SArmin Le Grand     }
249*4665f8d3SArmin Le Grand 
addSvtGraphicFill(const SvtGraphicFill & rFilling,GDIMetaFile & rTarget)250*4665f8d3SArmin Le Grand     void addSvtGraphicFill(const SvtGraphicFill &rFilling, GDIMetaFile& rTarget)
251*4665f8d3SArmin Le Grand     {
252*4665f8d3SArmin Le Grand         // write SvtGraphicFill
253*4665f8d3SArmin Le Grand         SvMemoryStream aMemStm;
254*4665f8d3SArmin Le Grand         aMemStm << rFilling;
255*4665f8d3SArmin Le Grand         rTarget.AddAction(
256*4665f8d3SArmin Le Grand             new MetaCommentAction(
257*4665f8d3SArmin Le Grand                 "XPATHFILL_SEQ_BEGIN",
258*4665f8d3SArmin Le Grand                 0,
259*4665f8d3SArmin Le Grand                 static_cast< const sal_uInt8* >(aMemStm.GetData()),
260*4665f8d3SArmin Le Grand                 aMemStm.Seek(STREAM_SEEK_TO_END)));
261*4665f8d3SArmin Le Grand     }
262*4665f8d3SArmin Le Grand } // end of anonymous namespace
263*4665f8d3SArmin Le Grand 
264*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
265*4665f8d3SArmin Le Grand // #121267# Tooling to internally clip geometry against internal clip regions
266*4665f8d3SArmin Le Grand 
clipMetafileContentAgainstOwnRegions(GDIMetaFile & rSource)267*4665f8d3SArmin Le Grand void clipMetafileContentAgainstOwnRegions(GDIMetaFile& rSource)
268*4665f8d3SArmin Le Grand {
269*4665f8d3SArmin Le Grand     const sal_uLong nObjCount(rSource.GetActionCount());
270*4665f8d3SArmin Le Grand 
271*4665f8d3SArmin Le Grand     if(!nObjCount)
272*4665f8d3SArmin Le Grand     {
273*4665f8d3SArmin Le Grand         return;
274*4665f8d3SArmin Le Grand     }
275*4665f8d3SArmin Le Grand 
276*4665f8d3SArmin Le Grand     // prepare target data container and push/pop stack data
277*4665f8d3SArmin Le Grand     GDIMetaFile aTarget;
278*4665f8d3SArmin Le Grand     bool bChanged(false);
279*4665f8d3SArmin Le Grand     std::vector< basegfx::B2DPolyPolygon > aClips;
280*4665f8d3SArmin Le Grand     std::vector< sal_uInt16 > aPushFlags;
281*4665f8d3SArmin Le Grand     std::vector< MapMode > aMapModes;
282*4665f8d3SArmin Le Grand 
283*4665f8d3SArmin Le Grand     // start with empty region
284*4665f8d3SArmin Le Grand     aClips.push_back(basegfx::B2DPolyPolygon());
285*4665f8d3SArmin Le Grand 
286*4665f8d3SArmin Le Grand     // start with default MapMode (MAP_PIXEL)
287*4665f8d3SArmin Le Grand     aMapModes.push_back(MapMode());
288*4665f8d3SArmin Le Grand 
289*4665f8d3SArmin Le Grand     for(sal_uLong i(0); i < nObjCount; ++i)
290*4665f8d3SArmin Le Grand     {
291*4665f8d3SArmin Le Grand         const MetaAction* pAction(rSource.GetAction(i));
292*4665f8d3SArmin Le Grand         const sal_uInt16 nType(pAction->GetType());
293*4665f8d3SArmin Le Grand         bool bDone(false);
294*4665f8d3SArmin Le Grand 
295*4665f8d3SArmin Le Grand         // basic operation takes care of clipregion actions (four) and push/pop of these
296*4665f8d3SArmin Le Grand         // to steer the currently set clip region. There *is* an active
297*4665f8d3SArmin Le Grand         // clip region when (aClips.size() && aClips.back().count()), see
298*4665f8d3SArmin Le Grand         // below
299*4665f8d3SArmin Le Grand         switch(nType)
300*4665f8d3SArmin Le Grand         {
301*4665f8d3SArmin Le Grand             case META_CLIPREGION_ACTION :
302*4665f8d3SArmin Le Grand             {
303*4665f8d3SArmin Le Grand                 const MetaClipRegionAction* pA = static_cast< const MetaClipRegionAction* >(pAction);
304*4665f8d3SArmin Le Grand 
305*4665f8d3SArmin Le Grand                 if(pA->IsClipping())
306*4665f8d3SArmin Le Grand                 {
307*4665f8d3SArmin Le Grand                     const Region& rRegion = pA->GetRegion();
308*4665f8d3SArmin Le Grand                     const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
309*4665f8d3SArmin Le Grand 
310*4665f8d3SArmin Le Grand                     aClips.back() = aNewClip;
311*4665f8d3SArmin Le Grand                 }
312*4665f8d3SArmin Le Grand                 else
313*4665f8d3SArmin Le Grand                 {
314*4665f8d3SArmin Le Grand                     aClips.back() = basegfx::B2DPolyPolygon();
315*4665f8d3SArmin Le Grand                 }
316*4665f8d3SArmin Le Grand 
317*4665f8d3SArmin Le Grand                 break;
318*4665f8d3SArmin Le Grand             }
319*4665f8d3SArmin Le Grand 
320*4665f8d3SArmin Le Grand             case META_ISECTRECTCLIPREGION_ACTION :
321*4665f8d3SArmin Le Grand             {
322*4665f8d3SArmin Le Grand                 const MetaISectRectClipRegionAction* pA = static_cast< const MetaISectRectClipRegionAction* >(pAction);
323*4665f8d3SArmin Le Grand                 const Rectangle& rRect = pA->GetRect();
324*4665f8d3SArmin Le Grand 
325*4665f8d3SArmin Le Grand                 if(!rRect.IsEmpty() && aClips.size() && aClips.back().count())
326*4665f8d3SArmin Le Grand                 {
327*4665f8d3SArmin Le Grand                     const basegfx::B2DRange aClipRange(
328*4665f8d3SArmin Le Grand                         rRect.Left(), rRect.Top(),
329*4665f8d3SArmin Le Grand                         rRect.Right(), rRect.Bottom());
330*4665f8d3SArmin Le Grand 
331*4665f8d3SArmin Le Grand                     aClips.back() = basegfx::tools::clipPolyPolygonOnRange(
332*4665f8d3SArmin Le Grand                         aClips.back(),
333*4665f8d3SArmin Le Grand                         aClipRange,
334*4665f8d3SArmin Le Grand                         true, // inside
335*4665f8d3SArmin Le Grand                         false); // stroke
336*4665f8d3SArmin Le Grand                 }
337*4665f8d3SArmin Le Grand                 break;
338*4665f8d3SArmin Le Grand             }
339*4665f8d3SArmin Le Grand 
340*4665f8d3SArmin Le Grand             case META_ISECTREGIONCLIPREGION_ACTION :
341*4665f8d3SArmin Le Grand             {
342*4665f8d3SArmin Le Grand                 const MetaISectRegionClipRegionAction* pA = static_cast< const MetaISectRegionClipRegionAction* >(pAction);
343*4665f8d3SArmin Le Grand                 const Region& rRegion = pA->GetRegion();
344*4665f8d3SArmin Le Grand 
345*4665f8d3SArmin Le Grand                 if(!rRegion.IsEmpty() && aClips.size() && aClips.back().count())
346*4665f8d3SArmin Le Grand                 {
347*4665f8d3SArmin Le Grand                     const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
348*4665f8d3SArmin Le Grand 
349*4665f8d3SArmin Le Grand                     aClips.back() = basegfx::tools::clipPolyPolygonOnPolyPolygon(
350*4665f8d3SArmin Le Grand                         aClips.back(),
351*4665f8d3SArmin Le Grand                         aNewClip,
352*4665f8d3SArmin Le Grand                         true,  // inside
353*4665f8d3SArmin Le Grand                         false); // stroke
354*4665f8d3SArmin Le Grand                 }
355*4665f8d3SArmin Le Grand                 break;
356*4665f8d3SArmin Le Grand             }
357*4665f8d3SArmin Le Grand 
358*4665f8d3SArmin Le Grand             case META_MOVECLIPREGION_ACTION :
359*4665f8d3SArmin Le Grand             {
360*4665f8d3SArmin Le Grand                 const MetaMoveClipRegionAction* pA = static_cast< const MetaMoveClipRegionAction* >(pAction);
361*4665f8d3SArmin Le Grand                 const long aHorMove(pA->GetHorzMove());
362*4665f8d3SArmin Le Grand                 const long aVerMove(pA->GetVertMove());
363*4665f8d3SArmin Le Grand 
364*4665f8d3SArmin Le Grand                 if((aHorMove || aVerMove) && aClips.size() && aClips.back().count())
365*4665f8d3SArmin Le Grand                 {
366*4665f8d3SArmin Le Grand                     aClips.back().transform(
367*4665f8d3SArmin Le Grand                         basegfx::tools::createTranslateB2DHomMatrix(
368*4665f8d3SArmin Le Grand                             aHorMove,
369*4665f8d3SArmin Le Grand                             aVerMove));
370*4665f8d3SArmin Le Grand                 }
371*4665f8d3SArmin Le Grand                 break;
372*4665f8d3SArmin Le Grand             }
373*4665f8d3SArmin Le Grand 
374*4665f8d3SArmin Le Grand             case META_PUSH_ACTION :
375*4665f8d3SArmin Le Grand             {
376*4665f8d3SArmin Le Grand                 const MetaPushAction* pA = static_cast< const MetaPushAction* >(pAction);
377*4665f8d3SArmin Le Grand                 const sal_uInt16 nFlags(pA->GetFlags());
378*4665f8d3SArmin Le Grand 
379*4665f8d3SArmin Le Grand                 aPushFlags.push_back(nFlags);
380*4665f8d3SArmin Le Grand 
381*4665f8d3SArmin Le Grand                 if(nFlags & PUSH_CLIPREGION)
382*4665f8d3SArmin Le Grand                 {
383*4665f8d3SArmin Le Grand                     aClips.push_back(aClips.back());
384*4665f8d3SArmin Le Grand                 }
385*4665f8d3SArmin Le Grand 
386*4665f8d3SArmin Le Grand                 if(nFlags & PUSH_MAPMODE)
387*4665f8d3SArmin Le Grand                 {
388*4665f8d3SArmin Le Grand                     aMapModes.push_back(aMapModes.back());
389*4665f8d3SArmin Le Grand                 }
390*4665f8d3SArmin Le Grand                 break;
391*4665f8d3SArmin Le Grand             }
392*4665f8d3SArmin Le Grand 
393*4665f8d3SArmin Le Grand             case META_POP_ACTION :
394*4665f8d3SArmin Le Grand             {
395*4665f8d3SArmin Le Grand 
396*4665f8d3SArmin Le Grand                 if(aPushFlags.size())
397*4665f8d3SArmin Le Grand                 {
398*4665f8d3SArmin Le Grand                     const sal_uInt16 nFlags(aPushFlags.back());
399*4665f8d3SArmin Le Grand                     aPushFlags.pop_back();
400*4665f8d3SArmin Le Grand 
401*4665f8d3SArmin Le Grand                     if(nFlags & PUSH_CLIPREGION)
402*4665f8d3SArmin Le Grand                     {
403*4665f8d3SArmin Le Grand                         if(aClips.size() > 1)
404*4665f8d3SArmin Le Grand                         {
405*4665f8d3SArmin Le Grand                             aClips.pop_back();
406*4665f8d3SArmin Le Grand                         }
407*4665f8d3SArmin Le Grand                         else
408*4665f8d3SArmin Le Grand                         {
409*4665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in ClipRegions (!)");
410*4665f8d3SArmin Le Grand                         }
411*4665f8d3SArmin Le Grand                     }
412*4665f8d3SArmin Le Grand 
413*4665f8d3SArmin Le Grand                     if(nFlags & PUSH_MAPMODE)
414*4665f8d3SArmin Le Grand                     {
415*4665f8d3SArmin Le Grand                         if(aMapModes.size() > 1)
416*4665f8d3SArmin Le Grand                         {
417*4665f8d3SArmin Le Grand                             aMapModes.pop_back();
418*4665f8d3SArmin Le Grand                         }
419*4665f8d3SArmin Le Grand                         else
420*4665f8d3SArmin Le Grand                         {
421*4665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in MapModes (!)");
422*4665f8d3SArmin Le Grand                         }
423*4665f8d3SArmin Le Grand                     }
424*4665f8d3SArmin Le Grand                 }
425*4665f8d3SArmin Le Grand                 else
426*4665f8d3SArmin Le Grand                 {
427*4665f8d3SArmin Le Grand                     OSL_ENSURE(false, "Invalid pop() without push() (!)");
428*4665f8d3SArmin Le Grand                 }
429*4665f8d3SArmin Le Grand 
430*4665f8d3SArmin Le Grand                 break;
431*4665f8d3SArmin Le Grand             }
432*4665f8d3SArmin Le Grand 
433*4665f8d3SArmin Le Grand             case META_MAPMODE_ACTION :
434*4665f8d3SArmin Le Grand             {
435*4665f8d3SArmin Le Grand                 const MetaMapModeAction* pA = static_cast< const MetaMapModeAction* >(pAction);
436*4665f8d3SArmin Le Grand 
437*4665f8d3SArmin Le Grand                 aMapModes.back() = pA->GetMapMode();
438*4665f8d3SArmin Le Grand                 break;
439*4665f8d3SArmin Le Grand             }
440*4665f8d3SArmin Le Grand 
441*4665f8d3SArmin Le Grand             default:
442*4665f8d3SArmin Le Grand             {
443*4665f8d3SArmin Le Grand                 break;
444*4665f8d3SArmin Le Grand             }
445*4665f8d3SArmin Le Grand         }
446*4665f8d3SArmin Le Grand 
447*4665f8d3SArmin Le Grand         // this area contains all actions which could potentially be clipped. Since
448*4665f8d3SArmin Le Grand         // this tooling is only a fallback (see comments in header), only the needed
449*4665f8d3SArmin Le Grand         // actions will be implemented. Extend using the pattern for the already
450*4665f8d3SArmin Le Grand         // implemented actions.
451*4665f8d3SArmin Le Grand         if(aClips.size() && aClips.back().count())
452*4665f8d3SArmin Le Grand         {
453*4665f8d3SArmin Le Grand             switch(nType)
454*4665f8d3SArmin Le Grand             {
455*4665f8d3SArmin Le Grand                 //
456*4665f8d3SArmin Le Grand                 // pixel actions, just check on inside
457*4665f8d3SArmin Le Grand                 //
458*4665f8d3SArmin Le Grand                 case META_PIXEL_ACTION :
459*4665f8d3SArmin Le Grand                 {
460*4665f8d3SArmin Le Grand                     const MetaPixelAction* pA = static_cast< const MetaPixelAction* >(pAction);
461*4665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
462*4665f8d3SArmin Le Grand 
463*4665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
464*4665f8d3SArmin Le Grand                         aClips.back(),
465*4665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
466*4665f8d3SArmin Le Grand                     {
467*4665f8d3SArmin Le Grand                         // when not inside, do not add original
468*4665f8d3SArmin Le Grand                         bDone = true;
469*4665f8d3SArmin Le Grand                     }
470*4665f8d3SArmin Le Grand                     break;
471*4665f8d3SArmin Le Grand                 }
472*4665f8d3SArmin Le Grand 
473*4665f8d3SArmin Le Grand                 case META_POINT_ACTION :
474*4665f8d3SArmin Le Grand                 {
475*4665f8d3SArmin Le Grand                     const MetaPointAction* pA = static_cast< const MetaPointAction* >(pAction);
476*4665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
477*4665f8d3SArmin Le Grand 
478*4665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
479*4665f8d3SArmin Le Grand                         aClips.back(),
480*4665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
481*4665f8d3SArmin Le Grand                     {
482*4665f8d3SArmin Le Grand                         // when not inside, do not add original
483*4665f8d3SArmin Le Grand                         bDone = true;
484*4665f8d3SArmin Le Grand                     }
485*4665f8d3SArmin Le Grand                     break;
486*4665f8d3SArmin Le Grand                 }
487*4665f8d3SArmin Le Grand 
488*4665f8d3SArmin Le Grand                 //
489*4665f8d3SArmin Le Grand                 // geometry actions
490*4665f8d3SArmin Le Grand                 //
491*4665f8d3SArmin Le Grand                 case META_LINE_ACTION :
492*4665f8d3SArmin Le Grand                 {
493*4665f8d3SArmin Le Grand                     const MetaLineAction* pA = static_cast< const MetaLineAction* >(pAction);
494*4665f8d3SArmin Le Grand                     const Point& rStart(pA->GetStartPoint());
495*4665f8d3SArmin Le Grand                     const Point& rEnd(pA->GetEndPoint());
496*4665f8d3SArmin Le Grand                     basegfx::B2DPolygon aLine;
497*4665f8d3SArmin Le Grand 
498*4665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
499*4665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
500*4665f8d3SArmin Le Grand 
501*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
502*4665f8d3SArmin Le Grand                         aClips.back(),
503*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(aLine),
504*4665f8d3SArmin Le Grand                         aTarget,
505*4665f8d3SArmin Le Grand                         true); // stroke
506*4665f8d3SArmin Le Grand                     break;
507*4665f8d3SArmin Le Grand                 }
508*4665f8d3SArmin Le Grand 
509*4665f8d3SArmin Le Grand                 case META_RECT_ACTION :
510*4665f8d3SArmin Le Grand                 {
511*4665f8d3SArmin Le Grand                     const MetaRectAction* pA = static_cast< const MetaRectAction* >(pAction);
512*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
513*4665f8d3SArmin Le Grand 
514*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
515*4665f8d3SArmin Le Grand                     {
516*4665f8d3SArmin Le Grand                         bDone = true;
517*4665f8d3SArmin Le Grand                     }
518*4665f8d3SArmin Le Grand                     else
519*4665f8d3SArmin Le Grand                     {
520*4665f8d3SArmin Le Grand 
521*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
522*4665f8d3SArmin Le Grand                             aClips.back(),
523*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
524*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
525*4665f8d3SArmin Le Grand                                     basegfx::B2DRange(
526*4665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
527*4665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
528*4665f8d3SArmin Le Grand                             aTarget,
529*4665f8d3SArmin Le Grand                             false); // stroke
530*4665f8d3SArmin Le Grand                     }
531*4665f8d3SArmin Le Grand                     break;
532*4665f8d3SArmin Le Grand                 }
533*4665f8d3SArmin Le Grand 
534*4665f8d3SArmin Le Grand                 case META_ROUNDRECT_ACTION :
535*4665f8d3SArmin Le Grand                 {
536*4665f8d3SArmin Le Grand                     const MetaRoundRectAction* pA = static_cast< const MetaRoundRectAction* >(pAction);
537*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
538*4665f8d3SArmin Le Grand 
539*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
540*4665f8d3SArmin Le Grand                     {
541*4665f8d3SArmin Le Grand                         bDone = true;
542*4665f8d3SArmin Le Grand                     }
543*4665f8d3SArmin Le Grand                     else
544*4665f8d3SArmin Le Grand                     {
545*4665f8d3SArmin Le Grand                         const sal_uInt32 nHor(pA->GetHorzRound());
546*4665f8d3SArmin Le Grand                         const sal_uInt32 nVer(pA->GetVertRound());
547*4665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
548*4665f8d3SArmin Le Grand                         basegfx::B2DPolygon aOutline;
549*4665f8d3SArmin Le Grand 
550*4665f8d3SArmin Le Grand                         if(nHor || nVer)
551*4665f8d3SArmin Le Grand                         {
552*4665f8d3SArmin Le Grand                             double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
553*4665f8d3SArmin Le Grand                             double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
554*4665f8d3SArmin Le Grand                             fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
555*4665f8d3SArmin Le Grand                             fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
556*4665f8d3SArmin Le Grand 
557*4665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
558*4665f8d3SArmin Le Grand                         }
559*4665f8d3SArmin Le Grand                         else
560*4665f8d3SArmin Le Grand                         {
561*4665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange);
562*4665f8d3SArmin Le Grand                         }
563*4665f8d3SArmin Le Grand 
564*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
565*4665f8d3SArmin Le Grand                             aClips.back(),
566*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aOutline),
567*4665f8d3SArmin Le Grand                             aTarget,
568*4665f8d3SArmin Le Grand                             false); // stroke
569*4665f8d3SArmin Le Grand                     }
570*4665f8d3SArmin Le Grand                     break;
571*4665f8d3SArmin Le Grand                 }
572*4665f8d3SArmin Le Grand 
573*4665f8d3SArmin Le Grand                 case META_ELLIPSE_ACTION :
574*4665f8d3SArmin Le Grand                 {
575*4665f8d3SArmin Le Grand                     const MetaEllipseAction* pA = static_cast< const MetaEllipseAction* >(pAction);
576*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
577*4665f8d3SArmin Le Grand 
578*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
579*4665f8d3SArmin Le Grand                     {
580*4665f8d3SArmin Le Grand                         bDone = true;
581*4665f8d3SArmin Le Grand                     }
582*4665f8d3SArmin Le Grand                     else
583*4665f8d3SArmin Le Grand                     {
584*4665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
585*4665f8d3SArmin Le Grand 
586*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
587*4665f8d3SArmin Le Grand                             aClips.back(),
588*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
589*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromEllipse(
590*4665f8d3SArmin Le Grand                                     aRange.getCenter(),
591*4665f8d3SArmin Le Grand                                     aRange.getWidth() * 0.5,
592*4665f8d3SArmin Le Grand                                     aRange.getHeight() * 0.5)),
593*4665f8d3SArmin Le Grand                             aTarget,
594*4665f8d3SArmin Le Grand                             false); // stroke
595*4665f8d3SArmin Le Grand                     }
596*4665f8d3SArmin Le Grand                     break;
597*4665f8d3SArmin Le Grand                 }
598*4665f8d3SArmin Le Grand 
599*4665f8d3SArmin Le Grand                 case META_ARC_ACTION :
600*4665f8d3SArmin Le Grand                 {
601*4665f8d3SArmin Le Grand                     const MetaArcAction* pA = static_cast< const MetaArcAction* >(pAction);
602*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
603*4665f8d3SArmin Le Grand 
604*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
605*4665f8d3SArmin Le Grand                     {
606*4665f8d3SArmin Le Grand                         bDone = true;
607*4665f8d3SArmin Le Grand                     }
608*4665f8d3SArmin Le Grand                     else
609*4665f8d3SArmin Le Grand                     {
610*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
611*4665f8d3SArmin Le Grand                             rRect,
612*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
613*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
614*4665f8d3SArmin Le Grand                             POLY_ARC);
615*4665f8d3SArmin Le Grand 
616*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
617*4665f8d3SArmin Le Grand                             aClips.back(),
618*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
619*4665f8d3SArmin Le Grand                             aTarget,
620*4665f8d3SArmin Le Grand                             true); // stroke
621*4665f8d3SArmin Le Grand                     }
622*4665f8d3SArmin Le Grand                     break;
623*4665f8d3SArmin Le Grand                 }
624*4665f8d3SArmin Le Grand 
625*4665f8d3SArmin Le Grand                 case META_PIE_ACTION :
626*4665f8d3SArmin Le Grand                 {
627*4665f8d3SArmin Le Grand                     const MetaPieAction* pA = static_cast< const MetaPieAction* >(pAction);
628*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
629*4665f8d3SArmin Le Grand 
630*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
631*4665f8d3SArmin Le Grand                     {
632*4665f8d3SArmin Le Grand                         bDone = true;
633*4665f8d3SArmin Le Grand                     }
634*4665f8d3SArmin Le Grand                     else
635*4665f8d3SArmin Le Grand                     {
636*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
637*4665f8d3SArmin Le Grand                             rRect,
638*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
639*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
640*4665f8d3SArmin Le Grand                             POLY_PIE);
641*4665f8d3SArmin Le Grand 
642*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
643*4665f8d3SArmin Le Grand                             aClips.back(),
644*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
645*4665f8d3SArmin Le Grand                             aTarget,
646*4665f8d3SArmin Le Grand                             false); // stroke
647*4665f8d3SArmin Le Grand                     }
648*4665f8d3SArmin Le Grand                     break;
649*4665f8d3SArmin Le Grand                 }
650*4665f8d3SArmin Le Grand 
651*4665f8d3SArmin Le Grand                 case META_CHORD_ACTION :
652*4665f8d3SArmin Le Grand                 {
653*4665f8d3SArmin Le Grand                     const MetaChordAction* pA = static_cast< const MetaChordAction* >(pAction);
654*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
655*4665f8d3SArmin Le Grand 
656*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
657*4665f8d3SArmin Le Grand                     {
658*4665f8d3SArmin Le Grand                         bDone = true;
659*4665f8d3SArmin Le Grand                     }
660*4665f8d3SArmin Le Grand                     else
661*4665f8d3SArmin Le Grand                     {
662*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
663*4665f8d3SArmin Le Grand                             rRect,
664*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
665*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
666*4665f8d3SArmin Le Grand                             POLY_CHORD);
667*4665f8d3SArmin Le Grand 
668*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
669*4665f8d3SArmin Le Grand                             aClips.back(),
670*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
671*4665f8d3SArmin Le Grand                             aTarget,
672*4665f8d3SArmin Le Grand                             false); // stroke
673*4665f8d3SArmin Le Grand                     }
674*4665f8d3SArmin Le Grand                     break;
675*4665f8d3SArmin Le Grand                 }
676*4665f8d3SArmin Le Grand 
677*4665f8d3SArmin Le Grand                 case META_POLYLINE_ACTION :
678*4665f8d3SArmin Le Grand                 {
679*4665f8d3SArmin Le Grand                     const MetaPolyLineAction* pA = static_cast< const MetaPolyLineAction* >(pAction);
680*4665f8d3SArmin Le Grand 
681*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
682*4665f8d3SArmin Le Grand                         aClips.back(),
683*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
684*4665f8d3SArmin Le Grand                         aTarget,
685*4665f8d3SArmin Le Grand                         true); // stroke
686*4665f8d3SArmin Le Grand                     break;
687*4665f8d3SArmin Le Grand                 }
688*4665f8d3SArmin Le Grand 
689*4665f8d3SArmin Le Grand                 case META_POLYGON_ACTION :
690*4665f8d3SArmin Le Grand                 {
691*4665f8d3SArmin Le Grand                     const MetaPolygonAction* pA = static_cast< const MetaPolygonAction* >(pAction);
692*4665f8d3SArmin Le Grand 
693*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
694*4665f8d3SArmin Le Grand                         aClips.back(),
695*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
696*4665f8d3SArmin Le Grand                         aTarget,
697*4665f8d3SArmin Le Grand                         false); // stroke
698*4665f8d3SArmin Le Grand                     break;
699*4665f8d3SArmin Le Grand                 }
700*4665f8d3SArmin Le Grand 
701*4665f8d3SArmin Le Grand                 case META_POLYPOLYGON_ACTION :
702*4665f8d3SArmin Le Grand                 {
703*4665f8d3SArmin Le Grand                     const MetaPolyPolygonAction* pA = static_cast< const MetaPolyPolygonAction* >(pAction);
704*4665f8d3SArmin Le Grand                     const PolyPolygon& rPoly = pA->GetPolyPolygon();
705*4665f8d3SArmin Le Grand 
706*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
707*4665f8d3SArmin Le Grand                         aClips.back(),
708*4665f8d3SArmin Le Grand                         rPoly.getB2DPolyPolygon(),
709*4665f8d3SArmin Le Grand                         aTarget,
710*4665f8d3SArmin Le Grand                         false); // stroke
711*4665f8d3SArmin Le Grand                     break;
712*4665f8d3SArmin Le Grand                 }
713*4665f8d3SArmin Le Grand 
714*4665f8d3SArmin Le Grand                 //
715*4665f8d3SArmin Le Grand                 // bitmap actions, create BitmapEx with alpha channel derived
716*4665f8d3SArmin Le Grand                 // from clipping
717*4665f8d3SArmin Le Grand                 //
718*4665f8d3SArmin Le Grand                 case META_BMPEX_ACTION :
719*4665f8d3SArmin Le Grand                 {
720*4665f8d3SArmin Le Grand                     const MetaBmpExAction* pA = static_cast< const MetaBmpExAction* >(pAction);
721*4665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
722*4665f8d3SArmin Le Grand 
723*4665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
724*4665f8d3SArmin Le Grand                     // combination with the current MapMode
725*4665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmapEx.GetPrefSize());
726*4665f8d3SArmin Le Grand 
727*4665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmapEx.GetPrefMapMode().GetMapUnit())
728*4665f8d3SArmin Le Grand                     {
729*4665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
730*4665f8d3SArmin Le Grand                     }
731*4665f8d3SArmin Le Grand                     else
732*4665f8d3SArmin Le Grand                     {
733*4665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmapEx.GetPrefMapMode(), aMapModes.back().GetMapUnit());
734*4665f8d3SArmin Le Grand                     }
735*4665f8d3SArmin Le Grand 
736*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
737*4665f8d3SArmin Le Grand                         aClips.back(),
738*4665f8d3SArmin Le Grand                         pA->GetPoint(),
739*4665f8d3SArmin Le Grand                         aLogicalSize,
740*4665f8d3SArmin Le Grand                         rBitmapEx,
741*4665f8d3SArmin Le Grand                         aTarget);
742*4665f8d3SArmin Le Grand                     break;
743*4665f8d3SArmin Le Grand                 }
744*4665f8d3SArmin Le Grand 
745*4665f8d3SArmin Le Grand                 case META_BMP_ACTION :
746*4665f8d3SArmin Le Grand                 {
747*4665f8d3SArmin Le Grand                     const MetaBmpAction* pA = static_cast< const MetaBmpAction* >(pAction);
748*4665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
749*4665f8d3SArmin Le Grand 
750*4665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
751*4665f8d3SArmin Le Grand                     // combination with the current MapMode
752*4665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmap.GetPrefSize());
753*4665f8d3SArmin Le Grand 
754*4665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmap.GetPrefMapMode().GetMapUnit())
755*4665f8d3SArmin Le Grand                     {
756*4665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
757*4665f8d3SArmin Le Grand                     }
758*4665f8d3SArmin Le Grand                     else
759*4665f8d3SArmin Le Grand                     {
760*4665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmap.GetPrefMapMode(), aMapModes.back().GetMapUnit());
761*4665f8d3SArmin Le Grand                     }
762*4665f8d3SArmin Le Grand 
763*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
764*4665f8d3SArmin Le Grand                         aClips.back(),
765*4665f8d3SArmin Le Grand                         pA->GetPoint(),
766*4665f8d3SArmin Le Grand                         aLogicalSize,
767*4665f8d3SArmin Le Grand                         BitmapEx(rBitmap),
768*4665f8d3SArmin Le Grand                         aTarget);
769*4665f8d3SArmin Le Grand                     break;
770*4665f8d3SArmin Le Grand                 }
771*4665f8d3SArmin Le Grand 
772*4665f8d3SArmin Le Grand                 case META_BMPEXSCALE_ACTION :
773*4665f8d3SArmin Le Grand                 {
774*4665f8d3SArmin Le Grand                     const MetaBmpExScaleAction* pA = static_cast< const MetaBmpExScaleAction* >(pAction);
775*4665f8d3SArmin Le Grand 
776*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
777*4665f8d3SArmin Le Grand                         aClips.back(),
778*4665f8d3SArmin Le Grand                         pA->GetPoint(),
779*4665f8d3SArmin Le Grand                         pA->GetSize(),
780*4665f8d3SArmin Le Grand                         pA->GetBitmapEx(),
781*4665f8d3SArmin Le Grand                         aTarget);
782*4665f8d3SArmin Le Grand                     break;
783*4665f8d3SArmin Le Grand                 }
784*4665f8d3SArmin Le Grand 
785*4665f8d3SArmin Le Grand                 case META_BMPSCALE_ACTION :
786*4665f8d3SArmin Le Grand                 {
787*4665f8d3SArmin Le Grand                     const MetaBmpScaleAction* pA = static_cast< const MetaBmpScaleAction* >(pAction);
788*4665f8d3SArmin Le Grand 
789*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
790*4665f8d3SArmin Le Grand                         aClips.back(),
791*4665f8d3SArmin Le Grand                         pA->GetPoint(),
792*4665f8d3SArmin Le Grand                         pA->GetSize(),
793*4665f8d3SArmin Le Grand                         BitmapEx(pA->GetBitmap()),
794*4665f8d3SArmin Le Grand                         aTarget);
795*4665f8d3SArmin Le Grand                     break;
796*4665f8d3SArmin Le Grand                 }
797*4665f8d3SArmin Le Grand 
798*4665f8d3SArmin Le Grand                 case META_BMPEXSCALEPART_ACTION :
799*4665f8d3SArmin Le Grand                 {
800*4665f8d3SArmin Le Grand                     const MetaBmpExScalePartAction* pA = static_cast< const MetaBmpExScalePartAction* >(pAction);
801*4665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
802*4665f8d3SArmin Le Grand 
803*4665f8d3SArmin Le Grand                     if(rBitmapEx.IsEmpty())
804*4665f8d3SArmin Le Grand                     {
805*4665f8d3SArmin Le Grand                         // empty content
806*4665f8d3SArmin Le Grand                         bDone = true;
807*4665f8d3SArmin Le Grand                     }
808*4665f8d3SArmin Le Grand                     else
809*4665f8d3SArmin Le Grand                     {
810*4665f8d3SArmin Le Grand                         BitmapEx aCroppedBitmapEx(rBitmapEx);
811*4665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
812*4665f8d3SArmin Le Grand 
813*4665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
814*4665f8d3SArmin Le Grand                         {
815*4665f8d3SArmin Le Grand                             // empty content
816*4665f8d3SArmin Le Grand                             bDone = true;
817*4665f8d3SArmin Le Grand                         }
818*4665f8d3SArmin Le Grand                         else
819*4665f8d3SArmin Le Grand                         {
820*4665f8d3SArmin Le Grand                             aCroppedBitmapEx.Crop(aCropRectangle);
821*4665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
822*4665f8d3SArmin Le Grand                                 aClips.back(),
823*4665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
824*4665f8d3SArmin Le Grand                                 pA->GetDestSize(),
825*4665f8d3SArmin Le Grand                                 aCroppedBitmapEx,
826*4665f8d3SArmin Le Grand                                 aTarget);
827*4665f8d3SArmin Le Grand                         }
828*4665f8d3SArmin Le Grand                     }
829*4665f8d3SArmin Le Grand                     break;
830*4665f8d3SArmin Le Grand                 }
831*4665f8d3SArmin Le Grand 
832*4665f8d3SArmin Le Grand                 case META_BMPSCALEPART_ACTION :
833*4665f8d3SArmin Le Grand                 {
834*4665f8d3SArmin Le Grand                     const MetaBmpScalePartAction* pA = static_cast< const MetaBmpScalePartAction* >(pAction);
835*4665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
836*4665f8d3SArmin Le Grand 
837*4665f8d3SArmin Le Grand                     if(rBitmap.IsEmpty())
838*4665f8d3SArmin Le Grand                     {
839*4665f8d3SArmin Le Grand                         // empty content
840*4665f8d3SArmin Le Grand                         bDone = true;
841*4665f8d3SArmin Le Grand                     }
842*4665f8d3SArmin Le Grand                     else
843*4665f8d3SArmin Le Grand                     {
844*4665f8d3SArmin Le Grand                         Bitmap aCroppedBitmap(rBitmap);
845*4665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
846*4665f8d3SArmin Le Grand 
847*4665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
848*4665f8d3SArmin Le Grand                         {
849*4665f8d3SArmin Le Grand                             // empty content
850*4665f8d3SArmin Le Grand                             bDone = true;
851*4665f8d3SArmin Le Grand                         }
852*4665f8d3SArmin Le Grand                         else
853*4665f8d3SArmin Le Grand                         {
854*4665f8d3SArmin Le Grand                             aCroppedBitmap.Crop(aCropRectangle);
855*4665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
856*4665f8d3SArmin Le Grand                                 aClips.back(),
857*4665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
858*4665f8d3SArmin Le Grand                                 pA->GetDestSize(),
859*4665f8d3SArmin Le Grand                                 BitmapEx(aCroppedBitmap),
860*4665f8d3SArmin Le Grand                                 aTarget);
861*4665f8d3SArmin Le Grand                         }
862*4665f8d3SArmin Le Grand                     }
863*4665f8d3SArmin Le Grand                     break;
864*4665f8d3SArmin Le Grand                 }
865*4665f8d3SArmin Le Grand 
866*4665f8d3SArmin Le Grand                 //
867*4665f8d3SArmin Le Grand                 // need to handle all those 'hacks' which hide data in comments
868*4665f8d3SArmin Le Grand                 //
869*4665f8d3SArmin Le Grand                 case META_COMMENT_ACTION :
870*4665f8d3SArmin Le Grand                 {
871*4665f8d3SArmin Le Grand                     const MetaCommentAction* pA = static_cast< const MetaCommentAction* >(pAction);
872*4665f8d3SArmin Le Grand                     const ByteString& rComment = pA->GetComment();
873*4665f8d3SArmin Le Grand 
874*4665f8d3SArmin Le Grand                     if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XGRAD_SEQ_BEGIN"))
875*4665f8d3SArmin Le Grand                     {
876*4665f8d3SArmin Le Grand                         // nothing to do; this just means that between here and XGRAD_SEQ_END
877*4665f8d3SArmin Le Grand                         // exists a META_GRADIENTEX_ACTION mixed with Xor-tricked painiting
878*4665f8d3SArmin Le Grand                         // commands. This comment is used to scan over these and filter for
879*4665f8d3SArmin Le Grand                         // the gradient action. It is needed to support META_GRADIENTEX_ACTION
880*4665f8d3SArmin Le Grand                         // in this processor to solve usages.
881*4665f8d3SArmin Le Grand                     }
882*4665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHFILL_SEQ_BEGIN"))
883*4665f8d3SArmin Le Grand                     {
884*4665f8d3SArmin Le Grand                         SvtGraphicFill aFilling;
885*4665f8d3SArmin Le Grand                         PolyPolygon aPath;
886*4665f8d3SArmin Le Grand 
887*4665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
888*4665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
889*4665f8d3SArmin Le Grand                             aMemStm >> aFilling;
890*4665f8d3SArmin Le Grand                         }
891*4665f8d3SArmin Le Grand 
892*4665f8d3SArmin Le Grand                         aFilling.getPath(aPath);
893*4665f8d3SArmin Le Grand 
894*4665f8d3SArmin Le Grand                         if(aPath.Count())
895*4665f8d3SArmin Le Grand                         {
896*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aSource(aPath.getB2DPolyPolygon());
897*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
898*4665f8d3SArmin Le Grand                                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
899*4665f8d3SArmin Le Grand                                     aSource,
900*4665f8d3SArmin Le Grand                                     aClips.back(),
901*4665f8d3SArmin Le Grand                                     true, // inside
902*4665f8d3SArmin Le Grand                                     false)); // stroke
903*4665f8d3SArmin Le Grand 
904*4665f8d3SArmin Le Grand                             if(aResult.count())
905*4665f8d3SArmin Le Grand                             {
906*4665f8d3SArmin Le Grand                                 if(aResult != aSource)
907*4665f8d3SArmin Le Grand                                 {
908*4665f8d3SArmin Le Grand                                     // add clipped geometry
909*4665f8d3SArmin Le Grand                                     aFilling.setPath(PolyPolygon(aResult));
910*4665f8d3SArmin Le Grand                                     addSvtGraphicFill(aFilling, aTarget);
911*4665f8d3SArmin Le Grand                                     bDone = true;
912*4665f8d3SArmin Le Grand                                 }
913*4665f8d3SArmin Le Grand                             }
914*4665f8d3SArmin Le Grand                             else
915*4665f8d3SArmin Le Grand                             {
916*4665f8d3SArmin Le Grand                                 // exchange with empty polygon
917*4665f8d3SArmin Le Grand                                 aFilling.setPath(PolyPolygon());
918*4665f8d3SArmin Le Grand                                 addSvtGraphicFill(aFilling, aTarget);
919*4665f8d3SArmin Le Grand                                 bDone = true;
920*4665f8d3SArmin Le Grand                             }
921*4665f8d3SArmin Le Grand                         }
922*4665f8d3SArmin Le Grand                     }
923*4665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHSTROKE_SEQ_BEGIN"))
924*4665f8d3SArmin Le Grand                     {
925*4665f8d3SArmin Le Grand                         SvtGraphicStroke aStroke;
926*4665f8d3SArmin Le Grand                         Polygon aPath;
927*4665f8d3SArmin Le Grand 
928*4665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
929*4665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
930*4665f8d3SArmin Le Grand                             aMemStm >> aStroke;
931*4665f8d3SArmin Le Grand                         }
932*4665f8d3SArmin Le Grand 
933*4665f8d3SArmin Le Grand                         aStroke.getPath(aPath);
934*4665f8d3SArmin Le Grand 
935*4665f8d3SArmin Le Grand                         if(aPath.GetSize())
936*4665f8d3SArmin Le Grand                         {
937*4665f8d3SArmin Le Grand                             const basegfx::B2DPolygon aSource(aPath.getB2DPolygon());
938*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
939*4665f8d3SArmin Le Grand                                 basegfx::tools::clipPolygonOnPolyPolygon(
940*4665f8d3SArmin Le Grand                                     aSource,
941*4665f8d3SArmin Le Grand                                     aClips.back(),
942*4665f8d3SArmin Le Grand                                     true, // inside
943*4665f8d3SArmin Le Grand                                     true)); // stroke
944*4665f8d3SArmin Le Grand 
945*4665f8d3SArmin Le Grand                             if(aResult.count())
946*4665f8d3SArmin Le Grand                             {
947*4665f8d3SArmin Le Grand                                 if(aResult.count() > 1 || aResult.getB2DPolygon(0) != aSource)
948*4665f8d3SArmin Le Grand                                 {
949*4665f8d3SArmin Le Grand                                     // add clipped geometry
950*4665f8d3SArmin Le Grand                                     for(sal_uInt32 a(0); a < aResult.count(); a++)
951*4665f8d3SArmin Le Grand                                     {
952*4665f8d3SArmin Le Grand                                         aStroke.setPath(Polygon(aResult.getB2DPolygon(a)));
953*4665f8d3SArmin Le Grand                                         addSvtGraphicStroke(aStroke, aTarget);
954*4665f8d3SArmin Le Grand                                     }
955*4665f8d3SArmin Le Grand 
956*4665f8d3SArmin Le Grand                                     bDone = true;
957*4665f8d3SArmin Le Grand                                 }
958*4665f8d3SArmin Le Grand                             }
959*4665f8d3SArmin Le Grand                             else
960*4665f8d3SArmin Le Grand                             {
961*4665f8d3SArmin Le Grand                                 // exchange with empty polygon
962*4665f8d3SArmin Le Grand                                 aStroke.setPath(Polygon());
963*4665f8d3SArmin Le Grand                                 addSvtGraphicStroke(aStroke, aTarget);
964*4665f8d3SArmin Le Grand                                 bDone = true;
965*4665f8d3SArmin Le Grand                             }
966*4665f8d3SArmin Le Grand 
967*4665f8d3SArmin Le Grand                         }
968*4665f8d3SArmin Le Grand                     }
969*4665f8d3SArmin Le Grand                     break;
970*4665f8d3SArmin Le Grand                 }
971*4665f8d3SArmin Le Grand 
972*4665f8d3SArmin Le Grand                 //
973*4665f8d3SArmin Le Grand                 // need to handle gradient fills (hopefully only unroated ones)
974*4665f8d3SArmin Le Grand                 //
975*4665f8d3SArmin Le Grand 
976*4665f8d3SArmin Le Grand                 case META_GRADIENT_ACTION :
977*4665f8d3SArmin Le Grand                 {
978*4665f8d3SArmin Le Grand                     const MetaGradientAction* pA = static_cast< const MetaGradientAction* >(pAction);
979*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
980*4665f8d3SArmin Le Grand 
981*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
982*4665f8d3SArmin Le Grand                     {
983*4665f8d3SArmin Le Grand                         bDone = true;
984*4665f8d3SArmin Le Grand                     }
985*4665f8d3SArmin Le Grand                     else
986*4665f8d3SArmin Le Grand                     {
987*4665f8d3SArmin Le Grand                         bDone = handleGradientContent(
988*4665f8d3SArmin Le Grand                             aClips.back(),
989*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
990*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
991*4665f8d3SArmin Le Grand                                     basegfx::B2DRange(
992*4665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
993*4665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
994*4665f8d3SArmin Le Grand                             pA->GetGradient(),
995*4665f8d3SArmin Le Grand                             aTarget);
996*4665f8d3SArmin Le Grand                     }
997*4665f8d3SArmin Le Grand 
998*4665f8d3SArmin Le Grand 
999*4665f8d3SArmin Le Grand                     break;
1000*4665f8d3SArmin Le Grand                 }
1001*4665f8d3SArmin Le Grand 
1002*4665f8d3SArmin Le Grand                 case META_GRADIENTEX_ACTION :
1003*4665f8d3SArmin Le Grand                 {
1004*4665f8d3SArmin Le Grand                     const MetaGradientExAction* pA = static_cast< const MetaGradientExAction* >(pAction);
1005*4665f8d3SArmin Le Grand                     const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1006*4665f8d3SArmin Le Grand 
1007*4665f8d3SArmin Le Grand                     bDone = handleGradientContent(
1008*4665f8d3SArmin Le Grand                         aClips.back(),
1009*4665f8d3SArmin Le Grand                         rPolyPoly.getB2DPolyPolygon(),
1010*4665f8d3SArmin Le Grand                         pA->GetGradient(),
1011*4665f8d3SArmin Le Grand                         aTarget);
1012*4665f8d3SArmin Le Grand                     break;
1013*4665f8d3SArmin Le Grand                 }
1014*4665f8d3SArmin Le Grand 
1015*4665f8d3SArmin Le Grand                 // not (yet) supported actions
1016*4665f8d3SArmin Le Grand                 //
1017*4665f8d3SArmin Le Grand                 // META_NULL_ACTION
1018*4665f8d3SArmin Le Grand                 // META_TEXT_ACTION
1019*4665f8d3SArmin Le Grand                 // META_TEXTARRAY_ACTION
1020*4665f8d3SArmin Le Grand                 // META_STRETCHTEXT_ACTION
1021*4665f8d3SArmin Le Grand                 // META_TEXTRECT_ACTION
1022*4665f8d3SArmin Le Grand                 // META_MASK_ACTION
1023*4665f8d3SArmin Le Grand                 // META_MASKSCALE_ACTION
1024*4665f8d3SArmin Le Grand                 // META_MASKSCALEPART_ACTION
1025*4665f8d3SArmin Le Grand                 // META_HATCH_ACTION
1026*4665f8d3SArmin Le Grand                 // META_WALLPAPER_ACTION
1027*4665f8d3SArmin Le Grand                 // META_FILLCOLOR_ACTION
1028*4665f8d3SArmin Le Grand                 // META_TEXTCOLOR_ACTION
1029*4665f8d3SArmin Le Grand                 // META_TEXTFILLCOLOR_ACTION
1030*4665f8d3SArmin Le Grand                 // META_TEXTALIGN_ACTION
1031*4665f8d3SArmin Le Grand                 // META_MAPMODE_ACTION
1032*4665f8d3SArmin Le Grand                 // META_FONT_ACTION
1033*4665f8d3SArmin Le Grand                 // META_TRANSPARENT_ACTION
1034*4665f8d3SArmin Le Grand                 // META_EPS_ACTION
1035*4665f8d3SArmin Le Grand                 // META_REFPOINT_ACTION
1036*4665f8d3SArmin Le Grand                 // META_TEXTLINECOLOR_ACTION
1037*4665f8d3SArmin Le Grand                 // META_TEXTLINE_ACTION
1038*4665f8d3SArmin Le Grand                 // META_FLOATTRANSPARENT_ACTION
1039*4665f8d3SArmin Le Grand                 // META_LAYOUTMODE_ACTION
1040*4665f8d3SArmin Le Grand                 // META_TEXTLANGUAGE_ACTION
1041*4665f8d3SArmin Le Grand                 // META_OVERLINECOLOR_ACTION
1042*4665f8d3SArmin Le Grand 
1043*4665f8d3SArmin Le Grand                 // if an action is not handled at all, it will simply get copied to the
1044*4665f8d3SArmin Le Grand                 // target (see below). This is the default for all non-implemented actions
1045*4665f8d3SArmin Le Grand                 default:
1046*4665f8d3SArmin Le Grand                 {
1047*4665f8d3SArmin Le Grand                     break;
1048*4665f8d3SArmin Le Grand                 }
1049*4665f8d3SArmin Le Grand             }
1050*4665f8d3SArmin Le Grand         }
1051*4665f8d3SArmin Le Grand 
1052*4665f8d3SArmin Le Grand         if(bDone)
1053*4665f8d3SArmin Le Grand         {
1054*4665f8d3SArmin Le Grand             bChanged = true;
1055*4665f8d3SArmin Le Grand         }
1056*4665f8d3SArmin Le Grand         else
1057*4665f8d3SArmin Le Grand         {
1058*4665f8d3SArmin Le Grand             const_cast< MetaAction* >(pAction)->Duplicate();
1059*4665f8d3SArmin Le Grand             aTarget.AddAction(const_cast< MetaAction* >(pAction));
1060*4665f8d3SArmin Le Grand         }
1061*4665f8d3SArmin Le Grand     }
1062*4665f8d3SArmin Le Grand 
1063*4665f8d3SArmin Le Grand     if(bChanged)
1064*4665f8d3SArmin Le Grand     {
1065*4665f8d3SArmin Le Grand         // when changed, copy back and do not forget to set MapMode
1066*4665f8d3SArmin Le Grand         // and PrefSize
1067*4665f8d3SArmin Le Grand         aTarget.SetPrefMapMode(rSource.GetPrefMapMode());
1068*4665f8d3SArmin Le Grand         aTarget.SetPrefSize(rSource.GetPrefSize());
1069*4665f8d3SArmin Le Grand         rSource = aTarget;
1070*4665f8d3SArmin Le Grand     }
1071*4665f8d3SArmin Le Grand }
1072*4665f8d3SArmin Le Grand 
1073*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1074*4665f8d3SArmin Le Grand 
usesClipActions(const GDIMetaFile & rSource)1075*4665f8d3SArmin Le Grand bool VCL_DLLPUBLIC usesClipActions(const GDIMetaFile& rSource)
1076*4665f8d3SArmin Le Grand {
1077*4665f8d3SArmin Le Grand     const sal_uLong nObjCount(rSource.GetActionCount());
1078*4665f8d3SArmin Le Grand 
1079*4665f8d3SArmin Le Grand     for(sal_uLong i(0); i < nObjCount; ++i)
1080*4665f8d3SArmin Le Grand     {
1081*4665f8d3SArmin Le Grand         const MetaAction* pAction(rSource.GetAction(i));
1082*4665f8d3SArmin Le Grand         const sal_uInt16 nType(pAction->GetType());
1083*4665f8d3SArmin Le Grand 
1084*4665f8d3SArmin Le Grand         switch(nType)
1085*4665f8d3SArmin Le Grand         {
1086*4665f8d3SArmin Le Grand             case META_CLIPREGION_ACTION :
1087*4665f8d3SArmin Le Grand             case META_ISECTRECTCLIPREGION_ACTION :
1088*4665f8d3SArmin Le Grand             case META_ISECTREGIONCLIPREGION_ACTION :
1089*4665f8d3SArmin Le Grand             case META_MOVECLIPREGION_ACTION :
1090*4665f8d3SArmin Le Grand             {
1091*4665f8d3SArmin Le Grand                 return true;
1092*4665f8d3SArmin Le Grand                 break;
1093*4665f8d3SArmin Le Grand             }
1094*4665f8d3SArmin Le Grand 
1095*4665f8d3SArmin Le Grand             default: break;
1096*4665f8d3SArmin Le Grand         }
1097*4665f8d3SArmin Le Grand     }
1098*4665f8d3SArmin Le Grand 
1099*4665f8d3SArmin Le Grand     return false;
1100*4665f8d3SArmin Le Grand }
1101*4665f8d3SArmin Le Grand 
1102*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1103*4665f8d3SArmin Le Grand // eof
1104