xref: /AOO41X/main/vcl/source/gdi/gdimetafiletools.cxx (revision 4665f8d3402ef83d47f8e4f2b7a9eaf8c9cfb078)
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 {
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 
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 
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 
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 
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 
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                 const MetaPopAction* pA = static_cast< const MetaPopAction* >(pAction);
396*4665f8d3SArmin Le Grand 
397*4665f8d3SArmin Le Grand                 if(aPushFlags.size())
398*4665f8d3SArmin Le Grand                 {
399*4665f8d3SArmin Le Grand                     const sal_uInt16 nFlags(aPushFlags.back());
400*4665f8d3SArmin Le Grand                     aPushFlags.pop_back();
401*4665f8d3SArmin Le Grand 
402*4665f8d3SArmin Le Grand                     if(nFlags & PUSH_CLIPREGION)
403*4665f8d3SArmin Le Grand                     {
404*4665f8d3SArmin Le Grand                         if(aClips.size() > 1)
405*4665f8d3SArmin Le Grand                         {
406*4665f8d3SArmin Le Grand                             aClips.pop_back();
407*4665f8d3SArmin Le Grand                         }
408*4665f8d3SArmin Le Grand                         else
409*4665f8d3SArmin Le Grand                         {
410*4665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in ClipRegions (!)");
411*4665f8d3SArmin Le Grand                         }
412*4665f8d3SArmin Le Grand                     }
413*4665f8d3SArmin Le Grand 
414*4665f8d3SArmin Le Grand                     if(nFlags & PUSH_MAPMODE)
415*4665f8d3SArmin Le Grand                     {
416*4665f8d3SArmin Le Grand                         if(aMapModes.size() > 1)
417*4665f8d3SArmin Le Grand                         {
418*4665f8d3SArmin Le Grand                             aMapModes.pop_back();
419*4665f8d3SArmin Le Grand                         }
420*4665f8d3SArmin Le Grand                         else
421*4665f8d3SArmin Le Grand                         {
422*4665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in MapModes (!)");
423*4665f8d3SArmin Le Grand                         }
424*4665f8d3SArmin Le Grand                     }
425*4665f8d3SArmin Le Grand                 }
426*4665f8d3SArmin Le Grand                 else
427*4665f8d3SArmin Le Grand                 {
428*4665f8d3SArmin Le Grand                     OSL_ENSURE(false, "Invalid pop() without push() (!)");
429*4665f8d3SArmin Le Grand                 }
430*4665f8d3SArmin Le Grand 
431*4665f8d3SArmin Le Grand                 break;
432*4665f8d3SArmin Le Grand             }
433*4665f8d3SArmin Le Grand 
434*4665f8d3SArmin Le Grand             case META_MAPMODE_ACTION :
435*4665f8d3SArmin Le Grand             {
436*4665f8d3SArmin Le Grand                 const MetaMapModeAction* pA = static_cast< const MetaMapModeAction* >(pAction);
437*4665f8d3SArmin Le Grand 
438*4665f8d3SArmin Le Grand                 aMapModes.back() = pA->GetMapMode();
439*4665f8d3SArmin Le Grand                 break;
440*4665f8d3SArmin Le Grand             }
441*4665f8d3SArmin Le Grand 
442*4665f8d3SArmin Le Grand             default:
443*4665f8d3SArmin Le Grand             {
444*4665f8d3SArmin Le Grand                 break;
445*4665f8d3SArmin Le Grand             }
446*4665f8d3SArmin Le Grand         }
447*4665f8d3SArmin Le Grand 
448*4665f8d3SArmin Le Grand         // this area contains all actions which could potentially be clipped. Since
449*4665f8d3SArmin Le Grand         // this tooling is only a fallback (see comments in header), only the needed
450*4665f8d3SArmin Le Grand         // actions will be implemented. Extend using the pattern for the already
451*4665f8d3SArmin Le Grand         // implemented actions.
452*4665f8d3SArmin Le Grand         if(aClips.size() && aClips.back().count())
453*4665f8d3SArmin Le Grand         {
454*4665f8d3SArmin Le Grand             switch(nType)
455*4665f8d3SArmin Le Grand             {
456*4665f8d3SArmin Le Grand                 //
457*4665f8d3SArmin Le Grand                 // pixel actions, just check on inside
458*4665f8d3SArmin Le Grand                 //
459*4665f8d3SArmin Le Grand                 case META_PIXEL_ACTION :
460*4665f8d3SArmin Le Grand                 {
461*4665f8d3SArmin Le Grand                     const MetaPixelAction* pA = static_cast< const MetaPixelAction* >(pAction);
462*4665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
463*4665f8d3SArmin Le Grand 
464*4665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
465*4665f8d3SArmin Le Grand                         aClips.back(),
466*4665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
467*4665f8d3SArmin Le Grand                     {
468*4665f8d3SArmin Le Grand                         // when not inside, do not add original
469*4665f8d3SArmin Le Grand                         bDone = true;
470*4665f8d3SArmin Le Grand                     }
471*4665f8d3SArmin Le Grand                     break;
472*4665f8d3SArmin Le Grand                 }
473*4665f8d3SArmin Le Grand 
474*4665f8d3SArmin Le Grand                 case META_POINT_ACTION :
475*4665f8d3SArmin Le Grand                 {
476*4665f8d3SArmin Le Grand                     const MetaPointAction* pA = static_cast< const MetaPointAction* >(pAction);
477*4665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
478*4665f8d3SArmin Le Grand 
479*4665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
480*4665f8d3SArmin Le Grand                         aClips.back(),
481*4665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
482*4665f8d3SArmin Le Grand                     {
483*4665f8d3SArmin Le Grand                         // when not inside, do not add original
484*4665f8d3SArmin Le Grand                         bDone = true;
485*4665f8d3SArmin Le Grand                     }
486*4665f8d3SArmin Le Grand                     break;
487*4665f8d3SArmin Le Grand                 }
488*4665f8d3SArmin Le Grand 
489*4665f8d3SArmin Le Grand                 //
490*4665f8d3SArmin Le Grand                 // geometry actions
491*4665f8d3SArmin Le Grand                 //
492*4665f8d3SArmin Le Grand                 case META_LINE_ACTION :
493*4665f8d3SArmin Le Grand                 {
494*4665f8d3SArmin Le Grand                     const MetaLineAction* pA = static_cast< const MetaLineAction* >(pAction);
495*4665f8d3SArmin Le Grand                     const Point& rStart(pA->GetStartPoint());
496*4665f8d3SArmin Le Grand                     const Point& rEnd(pA->GetEndPoint());
497*4665f8d3SArmin Le Grand                     basegfx::B2DPolygon aLine;
498*4665f8d3SArmin Le Grand 
499*4665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
500*4665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
501*4665f8d3SArmin Le Grand 
502*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
503*4665f8d3SArmin Le Grand                         aClips.back(),
504*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(aLine),
505*4665f8d3SArmin Le Grand                         aTarget,
506*4665f8d3SArmin Le Grand                         true); // stroke
507*4665f8d3SArmin Le Grand                     break;
508*4665f8d3SArmin Le Grand                 }
509*4665f8d3SArmin Le Grand 
510*4665f8d3SArmin Le Grand                 case META_RECT_ACTION :
511*4665f8d3SArmin Le Grand                 {
512*4665f8d3SArmin Le Grand                     const MetaRectAction* pA = static_cast< const MetaRectAction* >(pAction);
513*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
514*4665f8d3SArmin Le Grand 
515*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
516*4665f8d3SArmin Le Grand                     {
517*4665f8d3SArmin Le Grand                         bDone = true;
518*4665f8d3SArmin Le Grand                     }
519*4665f8d3SArmin Le Grand                     else
520*4665f8d3SArmin Le Grand                     {
521*4665f8d3SArmin Le Grand 
522*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
523*4665f8d3SArmin Le Grand                             aClips.back(),
524*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
525*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
526*4665f8d3SArmin Le Grand                                     basegfx::B2DRange(
527*4665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
528*4665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
529*4665f8d3SArmin Le Grand                             aTarget,
530*4665f8d3SArmin Le Grand                             false); // stroke
531*4665f8d3SArmin Le Grand                     }
532*4665f8d3SArmin Le Grand                     break;
533*4665f8d3SArmin Le Grand                 }
534*4665f8d3SArmin Le Grand 
535*4665f8d3SArmin Le Grand                 case META_ROUNDRECT_ACTION :
536*4665f8d3SArmin Le Grand                 {
537*4665f8d3SArmin Le Grand                     const MetaRoundRectAction* pA = static_cast< const MetaRoundRectAction* >(pAction);
538*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
539*4665f8d3SArmin Le Grand 
540*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
541*4665f8d3SArmin Le Grand                     {
542*4665f8d3SArmin Le Grand                         bDone = true;
543*4665f8d3SArmin Le Grand                     }
544*4665f8d3SArmin Le Grand                     else
545*4665f8d3SArmin Le Grand                     {
546*4665f8d3SArmin Le Grand                         const sal_uInt32 nHor(pA->GetHorzRound());
547*4665f8d3SArmin Le Grand                         const sal_uInt32 nVer(pA->GetVertRound());
548*4665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
549*4665f8d3SArmin Le Grand                         basegfx::B2DPolygon aOutline;
550*4665f8d3SArmin Le Grand 
551*4665f8d3SArmin Le Grand                         if(nHor || nVer)
552*4665f8d3SArmin Le Grand                         {
553*4665f8d3SArmin Le Grand                             double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
554*4665f8d3SArmin Le Grand                             double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
555*4665f8d3SArmin Le Grand                             fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
556*4665f8d3SArmin Le Grand                             fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
557*4665f8d3SArmin Le Grand 
558*4665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
559*4665f8d3SArmin Le Grand                         }
560*4665f8d3SArmin Le Grand                         else
561*4665f8d3SArmin Le Grand                         {
562*4665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange);
563*4665f8d3SArmin Le Grand                         }
564*4665f8d3SArmin Le Grand 
565*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
566*4665f8d3SArmin Le Grand                             aClips.back(),
567*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aOutline),
568*4665f8d3SArmin Le Grand                             aTarget,
569*4665f8d3SArmin Le Grand                             false); // stroke
570*4665f8d3SArmin Le Grand                     }
571*4665f8d3SArmin Le Grand                     break;
572*4665f8d3SArmin Le Grand                 }
573*4665f8d3SArmin Le Grand 
574*4665f8d3SArmin Le Grand                 case META_ELLIPSE_ACTION :
575*4665f8d3SArmin Le Grand                 {
576*4665f8d3SArmin Le Grand                     const MetaEllipseAction* pA = static_cast< const MetaEllipseAction* >(pAction);
577*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
578*4665f8d3SArmin Le Grand 
579*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
580*4665f8d3SArmin Le Grand                     {
581*4665f8d3SArmin Le Grand                         bDone = true;
582*4665f8d3SArmin Le Grand                     }
583*4665f8d3SArmin Le Grand                     else
584*4665f8d3SArmin Le Grand                     {
585*4665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
586*4665f8d3SArmin Le Grand 
587*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
588*4665f8d3SArmin Le Grand                             aClips.back(),
589*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
590*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromEllipse(
591*4665f8d3SArmin Le Grand                                     aRange.getCenter(),
592*4665f8d3SArmin Le Grand                                     aRange.getWidth() * 0.5,
593*4665f8d3SArmin Le Grand                                     aRange.getHeight() * 0.5)),
594*4665f8d3SArmin Le Grand                             aTarget,
595*4665f8d3SArmin Le Grand                             false); // stroke
596*4665f8d3SArmin Le Grand                     }
597*4665f8d3SArmin Le Grand                     break;
598*4665f8d3SArmin Le Grand                 }
599*4665f8d3SArmin Le Grand 
600*4665f8d3SArmin Le Grand                 case META_ARC_ACTION :
601*4665f8d3SArmin Le Grand                 {
602*4665f8d3SArmin Le Grand                     const MetaArcAction* pA = static_cast< const MetaArcAction* >(pAction);
603*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
604*4665f8d3SArmin Le Grand 
605*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
606*4665f8d3SArmin Le Grand                     {
607*4665f8d3SArmin Le Grand                         bDone = true;
608*4665f8d3SArmin Le Grand                     }
609*4665f8d3SArmin Le Grand                     else
610*4665f8d3SArmin Le Grand                     {
611*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
612*4665f8d3SArmin Le Grand                             rRect,
613*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
614*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
615*4665f8d3SArmin Le Grand                             POLY_ARC);
616*4665f8d3SArmin Le Grand 
617*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
618*4665f8d3SArmin Le Grand                             aClips.back(),
619*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
620*4665f8d3SArmin Le Grand                             aTarget,
621*4665f8d3SArmin Le Grand                             true); // stroke
622*4665f8d3SArmin Le Grand                     }
623*4665f8d3SArmin Le Grand                     break;
624*4665f8d3SArmin Le Grand                 }
625*4665f8d3SArmin Le Grand 
626*4665f8d3SArmin Le Grand                 case META_PIE_ACTION :
627*4665f8d3SArmin Le Grand                 {
628*4665f8d3SArmin Le Grand                     const MetaPieAction* pA = static_cast< const MetaPieAction* >(pAction);
629*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
630*4665f8d3SArmin Le Grand 
631*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
632*4665f8d3SArmin Le Grand                     {
633*4665f8d3SArmin Le Grand                         bDone = true;
634*4665f8d3SArmin Le Grand                     }
635*4665f8d3SArmin Le Grand                     else
636*4665f8d3SArmin Le Grand                     {
637*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
638*4665f8d3SArmin Le Grand                             rRect,
639*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
640*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
641*4665f8d3SArmin Le Grand                             POLY_PIE);
642*4665f8d3SArmin Le Grand 
643*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
644*4665f8d3SArmin Le Grand                             aClips.back(),
645*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
646*4665f8d3SArmin Le Grand                             aTarget,
647*4665f8d3SArmin Le Grand                             false); // stroke
648*4665f8d3SArmin Le Grand                     }
649*4665f8d3SArmin Le Grand                     break;
650*4665f8d3SArmin Le Grand                 }
651*4665f8d3SArmin Le Grand 
652*4665f8d3SArmin Le Grand                 case META_CHORD_ACTION :
653*4665f8d3SArmin Le Grand                 {
654*4665f8d3SArmin Le Grand                     const MetaChordAction* pA = static_cast< const MetaChordAction* >(pAction);
655*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
656*4665f8d3SArmin Le Grand 
657*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
658*4665f8d3SArmin Le Grand                     {
659*4665f8d3SArmin Le Grand                         bDone = true;
660*4665f8d3SArmin Le Grand                     }
661*4665f8d3SArmin Le Grand                     else
662*4665f8d3SArmin Le Grand                     {
663*4665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
664*4665f8d3SArmin Le Grand                             rRect,
665*4665f8d3SArmin Le Grand                             pA->GetStartPoint(),
666*4665f8d3SArmin Le Grand                             pA->GetEndPoint(),
667*4665f8d3SArmin Le Grand                             POLY_CHORD);
668*4665f8d3SArmin Le Grand 
669*4665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
670*4665f8d3SArmin Le Grand                             aClips.back(),
671*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
672*4665f8d3SArmin Le Grand                             aTarget,
673*4665f8d3SArmin Le Grand                             false); // stroke
674*4665f8d3SArmin Le Grand                     }
675*4665f8d3SArmin Le Grand                     break;
676*4665f8d3SArmin Le Grand                 }
677*4665f8d3SArmin Le Grand 
678*4665f8d3SArmin Le Grand                 case META_POLYLINE_ACTION :
679*4665f8d3SArmin Le Grand                 {
680*4665f8d3SArmin Le Grand                     const MetaPolyLineAction* pA = static_cast< const MetaPolyLineAction* >(pAction);
681*4665f8d3SArmin Le Grand 
682*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
683*4665f8d3SArmin Le Grand                         aClips.back(),
684*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
685*4665f8d3SArmin Le Grand                         aTarget,
686*4665f8d3SArmin Le Grand                         true); // stroke
687*4665f8d3SArmin Le Grand                     break;
688*4665f8d3SArmin Le Grand                 }
689*4665f8d3SArmin Le Grand 
690*4665f8d3SArmin Le Grand                 case META_POLYGON_ACTION :
691*4665f8d3SArmin Le Grand                 {
692*4665f8d3SArmin Le Grand                     const MetaPolygonAction* pA = static_cast< const MetaPolygonAction* >(pAction);
693*4665f8d3SArmin Le Grand 
694*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
695*4665f8d3SArmin Le Grand                         aClips.back(),
696*4665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
697*4665f8d3SArmin Le Grand                         aTarget,
698*4665f8d3SArmin Le Grand                         false); // stroke
699*4665f8d3SArmin Le Grand                     break;
700*4665f8d3SArmin Le Grand                 }
701*4665f8d3SArmin Le Grand 
702*4665f8d3SArmin Le Grand                 case META_POLYPOLYGON_ACTION :
703*4665f8d3SArmin Le Grand                 {
704*4665f8d3SArmin Le Grand                     const MetaPolyPolygonAction* pA = static_cast< const MetaPolyPolygonAction* >(pAction);
705*4665f8d3SArmin Le Grand                     const PolyPolygon& rPoly = pA->GetPolyPolygon();
706*4665f8d3SArmin Le Grand 
707*4665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
708*4665f8d3SArmin Le Grand                         aClips.back(),
709*4665f8d3SArmin Le Grand                         rPoly.getB2DPolyPolygon(),
710*4665f8d3SArmin Le Grand                         aTarget,
711*4665f8d3SArmin Le Grand                         false); // stroke
712*4665f8d3SArmin Le Grand                     break;
713*4665f8d3SArmin Le Grand                 }
714*4665f8d3SArmin Le Grand 
715*4665f8d3SArmin Le Grand                 //
716*4665f8d3SArmin Le Grand                 // bitmap actions, create BitmapEx with alpha channel derived
717*4665f8d3SArmin Le Grand                 // from clipping
718*4665f8d3SArmin Le Grand                 //
719*4665f8d3SArmin Le Grand                 case META_BMPEX_ACTION :
720*4665f8d3SArmin Le Grand                 {
721*4665f8d3SArmin Le Grand                     const MetaBmpExAction* pA = static_cast< const MetaBmpExAction* >(pAction);
722*4665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
723*4665f8d3SArmin Le Grand 
724*4665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
725*4665f8d3SArmin Le Grand                     // combination with the current MapMode
726*4665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmapEx.GetPrefSize());
727*4665f8d3SArmin Le Grand 
728*4665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmapEx.GetPrefMapMode().GetMapUnit())
729*4665f8d3SArmin Le Grand                     {
730*4665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
731*4665f8d3SArmin Le Grand                     }
732*4665f8d3SArmin Le Grand                     else
733*4665f8d3SArmin Le Grand                     {
734*4665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmapEx.GetPrefMapMode(), aMapModes.back().GetMapUnit());
735*4665f8d3SArmin Le Grand                     }
736*4665f8d3SArmin Le Grand 
737*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
738*4665f8d3SArmin Le Grand                         aClips.back(),
739*4665f8d3SArmin Le Grand                         pA->GetPoint(),
740*4665f8d3SArmin Le Grand                         aLogicalSize,
741*4665f8d3SArmin Le Grand                         rBitmapEx,
742*4665f8d3SArmin Le Grand                         aTarget);
743*4665f8d3SArmin Le Grand                     break;
744*4665f8d3SArmin Le Grand                 }
745*4665f8d3SArmin Le Grand 
746*4665f8d3SArmin Le Grand                 case META_BMP_ACTION :
747*4665f8d3SArmin Le Grand                 {
748*4665f8d3SArmin Le Grand                     const MetaBmpAction* pA = static_cast< const MetaBmpAction* >(pAction);
749*4665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
750*4665f8d3SArmin Le Grand 
751*4665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
752*4665f8d3SArmin Le Grand                     // combination with the current MapMode
753*4665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmap.GetPrefSize());
754*4665f8d3SArmin Le Grand 
755*4665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmap.GetPrefMapMode().GetMapUnit())
756*4665f8d3SArmin Le Grand                     {
757*4665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
758*4665f8d3SArmin Le Grand                     }
759*4665f8d3SArmin Le Grand                     else
760*4665f8d3SArmin Le Grand                     {
761*4665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmap.GetPrefMapMode(), aMapModes.back().GetMapUnit());
762*4665f8d3SArmin Le Grand                     }
763*4665f8d3SArmin Le Grand 
764*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
765*4665f8d3SArmin Le Grand                         aClips.back(),
766*4665f8d3SArmin Le Grand                         pA->GetPoint(),
767*4665f8d3SArmin Le Grand                         aLogicalSize,
768*4665f8d3SArmin Le Grand                         BitmapEx(rBitmap),
769*4665f8d3SArmin Le Grand                         aTarget);
770*4665f8d3SArmin Le Grand                     break;
771*4665f8d3SArmin Le Grand                 }
772*4665f8d3SArmin Le Grand 
773*4665f8d3SArmin Le Grand                 case META_BMPEXSCALE_ACTION :
774*4665f8d3SArmin Le Grand                 {
775*4665f8d3SArmin Le Grand                     const MetaBmpExScaleAction* pA = static_cast< const MetaBmpExScaleAction* >(pAction);
776*4665f8d3SArmin Le Grand 
777*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
778*4665f8d3SArmin Le Grand                         aClips.back(),
779*4665f8d3SArmin Le Grand                         pA->GetPoint(),
780*4665f8d3SArmin Le Grand                         pA->GetSize(),
781*4665f8d3SArmin Le Grand                         pA->GetBitmapEx(),
782*4665f8d3SArmin Le Grand                         aTarget);
783*4665f8d3SArmin Le Grand                     break;
784*4665f8d3SArmin Le Grand                 }
785*4665f8d3SArmin Le Grand 
786*4665f8d3SArmin Le Grand                 case META_BMPSCALE_ACTION :
787*4665f8d3SArmin Le Grand                 {
788*4665f8d3SArmin Le Grand                     const MetaBmpScaleAction* pA = static_cast< const MetaBmpScaleAction* >(pAction);
789*4665f8d3SArmin Le Grand 
790*4665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
791*4665f8d3SArmin Le Grand                         aClips.back(),
792*4665f8d3SArmin Le Grand                         pA->GetPoint(),
793*4665f8d3SArmin Le Grand                         pA->GetSize(),
794*4665f8d3SArmin Le Grand                         BitmapEx(pA->GetBitmap()),
795*4665f8d3SArmin Le Grand                         aTarget);
796*4665f8d3SArmin Le Grand                     break;
797*4665f8d3SArmin Le Grand                 }
798*4665f8d3SArmin Le Grand 
799*4665f8d3SArmin Le Grand                 case META_BMPEXSCALEPART_ACTION :
800*4665f8d3SArmin Le Grand                 {
801*4665f8d3SArmin Le Grand                     const MetaBmpExScalePartAction* pA = static_cast< const MetaBmpExScalePartAction* >(pAction);
802*4665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
803*4665f8d3SArmin Le Grand 
804*4665f8d3SArmin Le Grand                     if(rBitmapEx.IsEmpty())
805*4665f8d3SArmin Le Grand                     {
806*4665f8d3SArmin Le Grand                         // empty content
807*4665f8d3SArmin Le Grand                         bDone = true;
808*4665f8d3SArmin Le Grand                     }
809*4665f8d3SArmin Le Grand                     else
810*4665f8d3SArmin Le Grand                     {
811*4665f8d3SArmin Le Grand                         BitmapEx aCroppedBitmapEx(rBitmapEx);
812*4665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
813*4665f8d3SArmin Le Grand 
814*4665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
815*4665f8d3SArmin Le Grand                         {
816*4665f8d3SArmin Le Grand                             // empty content
817*4665f8d3SArmin Le Grand                             bDone = true;
818*4665f8d3SArmin Le Grand                         }
819*4665f8d3SArmin Le Grand                         else
820*4665f8d3SArmin Le Grand                         {
821*4665f8d3SArmin Le Grand                             aCroppedBitmapEx.Crop(aCropRectangle);
822*4665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
823*4665f8d3SArmin Le Grand                                 aClips.back(),
824*4665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
825*4665f8d3SArmin Le Grand                                 pA->GetDestSize(),
826*4665f8d3SArmin Le Grand                                 aCroppedBitmapEx,
827*4665f8d3SArmin Le Grand                                 aTarget);
828*4665f8d3SArmin Le Grand                         }
829*4665f8d3SArmin Le Grand                     }
830*4665f8d3SArmin Le Grand                     break;
831*4665f8d3SArmin Le Grand                 }
832*4665f8d3SArmin Le Grand 
833*4665f8d3SArmin Le Grand                 case META_BMPSCALEPART_ACTION :
834*4665f8d3SArmin Le Grand                 {
835*4665f8d3SArmin Le Grand                     const MetaBmpScalePartAction* pA = static_cast< const MetaBmpScalePartAction* >(pAction);
836*4665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
837*4665f8d3SArmin Le Grand 
838*4665f8d3SArmin Le Grand                     if(rBitmap.IsEmpty())
839*4665f8d3SArmin Le Grand                     {
840*4665f8d3SArmin Le Grand                         // empty content
841*4665f8d3SArmin Le Grand                         bDone = true;
842*4665f8d3SArmin Le Grand                     }
843*4665f8d3SArmin Le Grand                     else
844*4665f8d3SArmin Le Grand                     {
845*4665f8d3SArmin Le Grand                         Bitmap aCroppedBitmap(rBitmap);
846*4665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
847*4665f8d3SArmin Le Grand 
848*4665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
849*4665f8d3SArmin Le Grand                         {
850*4665f8d3SArmin Le Grand                             // empty content
851*4665f8d3SArmin Le Grand                             bDone = true;
852*4665f8d3SArmin Le Grand                         }
853*4665f8d3SArmin Le Grand                         else
854*4665f8d3SArmin Le Grand                         {
855*4665f8d3SArmin Le Grand                             aCroppedBitmap.Crop(aCropRectangle);
856*4665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
857*4665f8d3SArmin Le Grand                                 aClips.back(),
858*4665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
859*4665f8d3SArmin Le Grand                                 pA->GetDestSize(),
860*4665f8d3SArmin Le Grand                                 BitmapEx(aCroppedBitmap),
861*4665f8d3SArmin Le Grand                                 aTarget);
862*4665f8d3SArmin Le Grand                         }
863*4665f8d3SArmin Le Grand                     }
864*4665f8d3SArmin Le Grand                     break;
865*4665f8d3SArmin Le Grand                 }
866*4665f8d3SArmin Le Grand 
867*4665f8d3SArmin Le Grand                 //
868*4665f8d3SArmin Le Grand                 // need to handle all those 'hacks' which hide data in comments
869*4665f8d3SArmin Le Grand                 //
870*4665f8d3SArmin Le Grand                 case META_COMMENT_ACTION :
871*4665f8d3SArmin Le Grand                 {
872*4665f8d3SArmin Le Grand                     const MetaCommentAction* pA = static_cast< const MetaCommentAction* >(pAction);
873*4665f8d3SArmin Le Grand                     const ByteString& rComment = pA->GetComment();
874*4665f8d3SArmin Le Grand 
875*4665f8d3SArmin Le Grand                     if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XGRAD_SEQ_BEGIN"))
876*4665f8d3SArmin Le Grand                     {
877*4665f8d3SArmin Le Grand                         // nothing to do; this just means that between here and XGRAD_SEQ_END
878*4665f8d3SArmin Le Grand                         // exists a META_GRADIENTEX_ACTION mixed with Xor-tricked painiting
879*4665f8d3SArmin Le Grand                         // commands. This comment is used to scan over these and filter for
880*4665f8d3SArmin Le Grand                         // the gradient action. It is needed to support META_GRADIENTEX_ACTION
881*4665f8d3SArmin Le Grand                         // in this processor to solve usages.
882*4665f8d3SArmin Le Grand                     }
883*4665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHFILL_SEQ_BEGIN"))
884*4665f8d3SArmin Le Grand                     {
885*4665f8d3SArmin Le Grand                         SvtGraphicFill aFilling;
886*4665f8d3SArmin Le Grand                         PolyPolygon aPath;
887*4665f8d3SArmin Le Grand 
888*4665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
889*4665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
890*4665f8d3SArmin Le Grand                             aMemStm >> aFilling;
891*4665f8d3SArmin Le Grand                         }
892*4665f8d3SArmin Le Grand 
893*4665f8d3SArmin Le Grand                         aFilling.getPath(aPath);
894*4665f8d3SArmin Le Grand 
895*4665f8d3SArmin Le Grand                         if(aPath.Count())
896*4665f8d3SArmin Le Grand                         {
897*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aSource(aPath.getB2DPolyPolygon());
898*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
899*4665f8d3SArmin Le Grand                                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
900*4665f8d3SArmin Le Grand                                     aSource,
901*4665f8d3SArmin Le Grand                                     aClips.back(),
902*4665f8d3SArmin Le Grand                                     true, // inside
903*4665f8d3SArmin Le Grand                                     false)); // stroke
904*4665f8d3SArmin Le Grand 
905*4665f8d3SArmin Le Grand                             if(aResult.count())
906*4665f8d3SArmin Le Grand                             {
907*4665f8d3SArmin Le Grand                                 if(aResult != aSource)
908*4665f8d3SArmin Le Grand                                 {
909*4665f8d3SArmin Le Grand                                     // add clipped geometry
910*4665f8d3SArmin Le Grand                                     aFilling.setPath(PolyPolygon(aResult));
911*4665f8d3SArmin Le Grand                                     addSvtGraphicFill(aFilling, aTarget);
912*4665f8d3SArmin Le Grand                                     bDone = true;
913*4665f8d3SArmin Le Grand                                 }
914*4665f8d3SArmin Le Grand                             }
915*4665f8d3SArmin Le Grand                             else
916*4665f8d3SArmin Le Grand                             {
917*4665f8d3SArmin Le Grand                                 // exchange with empty polygon
918*4665f8d3SArmin Le Grand                                 aFilling.setPath(PolyPolygon());
919*4665f8d3SArmin Le Grand                                 addSvtGraphicFill(aFilling, aTarget);
920*4665f8d3SArmin Le Grand                                 bDone = true;
921*4665f8d3SArmin Le Grand                             }
922*4665f8d3SArmin Le Grand                         }
923*4665f8d3SArmin Le Grand                     }
924*4665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHSTROKE_SEQ_BEGIN"))
925*4665f8d3SArmin Le Grand                     {
926*4665f8d3SArmin Le Grand                         SvtGraphicStroke aStroke;
927*4665f8d3SArmin Le Grand                         Polygon aPath;
928*4665f8d3SArmin Le Grand 
929*4665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
930*4665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
931*4665f8d3SArmin Le Grand                             aMemStm >> aStroke;
932*4665f8d3SArmin Le Grand                         }
933*4665f8d3SArmin Le Grand 
934*4665f8d3SArmin Le Grand                         aStroke.getPath(aPath);
935*4665f8d3SArmin Le Grand 
936*4665f8d3SArmin Le Grand                         if(aPath.GetSize())
937*4665f8d3SArmin Le Grand                         {
938*4665f8d3SArmin Le Grand                             const basegfx::B2DPolygon aSource(aPath.getB2DPolygon());
939*4665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
940*4665f8d3SArmin Le Grand                                 basegfx::tools::clipPolygonOnPolyPolygon(
941*4665f8d3SArmin Le Grand                                     aSource,
942*4665f8d3SArmin Le Grand                                     aClips.back(),
943*4665f8d3SArmin Le Grand                                     true, // inside
944*4665f8d3SArmin Le Grand                                     true)); // stroke
945*4665f8d3SArmin Le Grand 
946*4665f8d3SArmin Le Grand                             if(aResult.count())
947*4665f8d3SArmin Le Grand                             {
948*4665f8d3SArmin Le Grand                                 if(aResult.count() > 1 || aResult.getB2DPolygon(0) != aSource)
949*4665f8d3SArmin Le Grand                                 {
950*4665f8d3SArmin Le Grand                                     // add clipped geometry
951*4665f8d3SArmin Le Grand                                     for(sal_uInt32 a(0); a < aResult.count(); a++)
952*4665f8d3SArmin Le Grand                                     {
953*4665f8d3SArmin Le Grand                                         aStroke.setPath(Polygon(aResult.getB2DPolygon(a)));
954*4665f8d3SArmin Le Grand                                         addSvtGraphicStroke(aStroke, aTarget);
955*4665f8d3SArmin Le Grand                                     }
956*4665f8d3SArmin Le Grand 
957*4665f8d3SArmin Le Grand                                     bDone = true;
958*4665f8d3SArmin Le Grand                                 }
959*4665f8d3SArmin Le Grand                             }
960*4665f8d3SArmin Le Grand                             else
961*4665f8d3SArmin Le Grand                             {
962*4665f8d3SArmin Le Grand                                 // exchange with empty polygon
963*4665f8d3SArmin Le Grand                                 aStroke.setPath(Polygon());
964*4665f8d3SArmin Le Grand                                 addSvtGraphicStroke(aStroke, aTarget);
965*4665f8d3SArmin Le Grand                                 bDone = true;
966*4665f8d3SArmin Le Grand                             }
967*4665f8d3SArmin Le Grand 
968*4665f8d3SArmin Le Grand                         }
969*4665f8d3SArmin Le Grand                     }
970*4665f8d3SArmin Le Grand                     break;
971*4665f8d3SArmin Le Grand                 }
972*4665f8d3SArmin Le Grand 
973*4665f8d3SArmin Le Grand                 //
974*4665f8d3SArmin Le Grand                 // need to handle gradient fills (hopefully only unroated ones)
975*4665f8d3SArmin Le Grand                 //
976*4665f8d3SArmin Le Grand 
977*4665f8d3SArmin Le Grand                 case META_GRADIENT_ACTION :
978*4665f8d3SArmin Le Grand                 {
979*4665f8d3SArmin Le Grand                     const MetaGradientAction* pA = static_cast< const MetaGradientAction* >(pAction);
980*4665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
981*4665f8d3SArmin Le Grand 
982*4665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
983*4665f8d3SArmin Le Grand                     {
984*4665f8d3SArmin Le Grand                         bDone = true;
985*4665f8d3SArmin Le Grand                     }
986*4665f8d3SArmin Le Grand                     else
987*4665f8d3SArmin Le Grand                     {
988*4665f8d3SArmin Le Grand                         bDone = handleGradientContent(
989*4665f8d3SArmin Le Grand                             aClips.back(),
990*4665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
991*4665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
992*4665f8d3SArmin Le Grand                                     basegfx::B2DRange(
993*4665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
994*4665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
995*4665f8d3SArmin Le Grand                             pA->GetGradient(),
996*4665f8d3SArmin Le Grand                             aTarget);
997*4665f8d3SArmin Le Grand                     }
998*4665f8d3SArmin Le Grand 
999*4665f8d3SArmin Le Grand 
1000*4665f8d3SArmin Le Grand                     break;
1001*4665f8d3SArmin Le Grand                 }
1002*4665f8d3SArmin Le Grand 
1003*4665f8d3SArmin Le Grand                 case META_GRADIENTEX_ACTION :
1004*4665f8d3SArmin Le Grand                 {
1005*4665f8d3SArmin Le Grand                     const MetaGradientExAction* pA = static_cast< const MetaGradientExAction* >(pAction);
1006*4665f8d3SArmin Le Grand                     const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
1007*4665f8d3SArmin Le Grand 
1008*4665f8d3SArmin Le Grand                     bDone = handleGradientContent(
1009*4665f8d3SArmin Le Grand                         aClips.back(),
1010*4665f8d3SArmin Le Grand                         rPolyPoly.getB2DPolyPolygon(),
1011*4665f8d3SArmin Le Grand                         pA->GetGradient(),
1012*4665f8d3SArmin Le Grand                         aTarget);
1013*4665f8d3SArmin Le Grand                     break;
1014*4665f8d3SArmin Le Grand                 }
1015*4665f8d3SArmin Le Grand 
1016*4665f8d3SArmin Le Grand                 // not (yet) supported actions
1017*4665f8d3SArmin Le Grand                 //
1018*4665f8d3SArmin Le Grand                 // META_NULL_ACTION
1019*4665f8d3SArmin Le Grand                 // META_TEXT_ACTION
1020*4665f8d3SArmin Le Grand                 // META_TEXTARRAY_ACTION
1021*4665f8d3SArmin Le Grand                 // META_STRETCHTEXT_ACTION
1022*4665f8d3SArmin Le Grand                 // META_TEXTRECT_ACTION
1023*4665f8d3SArmin Le Grand                 // META_MASK_ACTION
1024*4665f8d3SArmin Le Grand                 // META_MASKSCALE_ACTION
1025*4665f8d3SArmin Le Grand                 // META_MASKSCALEPART_ACTION
1026*4665f8d3SArmin Le Grand                 // META_HATCH_ACTION
1027*4665f8d3SArmin Le Grand                 // META_WALLPAPER_ACTION
1028*4665f8d3SArmin Le Grand                 // META_FILLCOLOR_ACTION
1029*4665f8d3SArmin Le Grand                 // META_TEXTCOLOR_ACTION
1030*4665f8d3SArmin Le Grand                 // META_TEXTFILLCOLOR_ACTION
1031*4665f8d3SArmin Le Grand                 // META_TEXTALIGN_ACTION
1032*4665f8d3SArmin Le Grand                 // META_MAPMODE_ACTION
1033*4665f8d3SArmin Le Grand                 // META_FONT_ACTION
1034*4665f8d3SArmin Le Grand                 // META_TRANSPARENT_ACTION
1035*4665f8d3SArmin Le Grand                 // META_EPS_ACTION
1036*4665f8d3SArmin Le Grand                 // META_REFPOINT_ACTION
1037*4665f8d3SArmin Le Grand                 // META_TEXTLINECOLOR_ACTION
1038*4665f8d3SArmin Le Grand                 // META_TEXTLINE_ACTION
1039*4665f8d3SArmin Le Grand                 // META_FLOATTRANSPARENT_ACTION
1040*4665f8d3SArmin Le Grand                 // META_LAYOUTMODE_ACTION
1041*4665f8d3SArmin Le Grand                 // META_TEXTLANGUAGE_ACTION
1042*4665f8d3SArmin Le Grand                 // META_OVERLINECOLOR_ACTION
1043*4665f8d3SArmin Le Grand 
1044*4665f8d3SArmin Le Grand                 // if an action is not handled at all, it will simply get copied to the
1045*4665f8d3SArmin Le Grand                 // target (see below). This is the default for all non-implemented actions
1046*4665f8d3SArmin Le Grand                 default:
1047*4665f8d3SArmin Le Grand                 {
1048*4665f8d3SArmin Le Grand                     break;
1049*4665f8d3SArmin Le Grand                 }
1050*4665f8d3SArmin Le Grand             }
1051*4665f8d3SArmin Le Grand         }
1052*4665f8d3SArmin Le Grand 
1053*4665f8d3SArmin Le Grand         if(bDone)
1054*4665f8d3SArmin Le Grand         {
1055*4665f8d3SArmin Le Grand             bChanged = true;
1056*4665f8d3SArmin Le Grand         }
1057*4665f8d3SArmin Le Grand         else
1058*4665f8d3SArmin Le Grand         {
1059*4665f8d3SArmin Le Grand             const_cast< MetaAction* >(pAction)->Duplicate();
1060*4665f8d3SArmin Le Grand             aTarget.AddAction(const_cast< MetaAction* >(pAction));
1061*4665f8d3SArmin Le Grand         }
1062*4665f8d3SArmin Le Grand     }
1063*4665f8d3SArmin Le Grand 
1064*4665f8d3SArmin Le Grand     if(bChanged)
1065*4665f8d3SArmin Le Grand     {
1066*4665f8d3SArmin Le Grand         // when changed, copy back and do not forget to set MapMode
1067*4665f8d3SArmin Le Grand         // and PrefSize
1068*4665f8d3SArmin Le Grand         aTarget.SetPrefMapMode(rSource.GetPrefMapMode());
1069*4665f8d3SArmin Le Grand         aTarget.SetPrefSize(rSource.GetPrefSize());
1070*4665f8d3SArmin Le Grand         rSource = aTarget;
1071*4665f8d3SArmin Le Grand     }
1072*4665f8d3SArmin Le Grand }
1073*4665f8d3SArmin Le Grand 
1074*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1075*4665f8d3SArmin Le Grand 
1076*4665f8d3SArmin Le Grand bool VCL_DLLPUBLIC usesClipActions(const GDIMetaFile& rSource)
1077*4665f8d3SArmin Le Grand {
1078*4665f8d3SArmin Le Grand     const sal_uLong nObjCount(rSource.GetActionCount());
1079*4665f8d3SArmin Le Grand 
1080*4665f8d3SArmin Le Grand     for(sal_uLong i(0); i < nObjCount; ++i)
1081*4665f8d3SArmin Le Grand     {
1082*4665f8d3SArmin Le Grand         const MetaAction* pAction(rSource.GetAction(i));
1083*4665f8d3SArmin Le Grand         const sal_uInt16 nType(pAction->GetType());
1084*4665f8d3SArmin Le Grand 
1085*4665f8d3SArmin Le Grand         switch(nType)
1086*4665f8d3SArmin Le Grand         {
1087*4665f8d3SArmin Le Grand             case META_CLIPREGION_ACTION :
1088*4665f8d3SArmin Le Grand             case META_ISECTRECTCLIPREGION_ACTION :
1089*4665f8d3SArmin Le Grand             case META_ISECTREGIONCLIPREGION_ACTION :
1090*4665f8d3SArmin Le Grand             case META_MOVECLIPREGION_ACTION :
1091*4665f8d3SArmin Le Grand             {
1092*4665f8d3SArmin Le Grand                 return true;
1093*4665f8d3SArmin Le Grand                 break;
1094*4665f8d3SArmin Le Grand             }
1095*4665f8d3SArmin Le Grand 
1096*4665f8d3SArmin Le Grand             default: break;
1097*4665f8d3SArmin Le Grand         }
1098*4665f8d3SArmin Le Grand     }
1099*4665f8d3SArmin Le Grand 
1100*4665f8d3SArmin Le Grand     return false;
1101*4665f8d3SArmin Le Grand }
1102*4665f8d3SArmin Le Grand 
1103*4665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1104*4665f8d3SArmin Le Grand // eof
1105