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