xref: /trunk/main/vcl/source/gdi/gdimetafiletools.cxx (revision 515f4036a64467de788f5756d8ebf472d92f9466)
14665f8d3SArmin Le Grand /**************************************************************
24665f8d3SArmin Le Grand  *
34665f8d3SArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
44665f8d3SArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
54665f8d3SArmin Le Grand  * distributed with this work for additional information
64665f8d3SArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
74665f8d3SArmin Le Grand  * to you under the Apache License, Version 2.0 (the
84665f8d3SArmin Le Grand  * "License"); you may not use this file except in compliance
94665f8d3SArmin Le Grand  * with the License.  You may obtain a copy of the License at
104665f8d3SArmin Le Grand  *
114665f8d3SArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
124665f8d3SArmin Le Grand  *
134665f8d3SArmin Le Grand  * Unless required by applicable law or agreed to in writing,
144665f8d3SArmin Le Grand  * software distributed under the License is distributed on an
154665f8d3SArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
164665f8d3SArmin Le Grand  * KIND, either express or implied.  See the License for the
174665f8d3SArmin Le Grand  * specific language governing permissions and limitations
184665f8d3SArmin Le Grand  * under the License.
194665f8d3SArmin Le Grand  *
204665f8d3SArmin Le Grand  *************************************************************/
214665f8d3SArmin Le Grand 
224665f8d3SArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
234665f8d3SArmin Le Grand #include "precompiled_vcl.hxx"
244665f8d3SArmin Le Grand 
254665f8d3SArmin Le Grand #include <vcl/gdimetafiletools.hxx>
264665f8d3SArmin Le Grand #include <vcl/metaact.hxx>
274665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolygonclipper.hxx>
284665f8d3SArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
294665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolypolygontools.hxx>
304665f8d3SArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx>
314665f8d3SArmin Le Grand #include <vcl/virdev.hxx>
324665f8d3SArmin Le Grand #include <vcl/svapp.hxx>
334665f8d3SArmin Le Grand #include <vcl/graphictools.hxx>
344665f8d3SArmin Le Grand 
354665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
364665f8d3SArmin Le Grand // helpers
374665f8d3SArmin Le Grand 
384665f8d3SArmin Le Grand namespace
394665f8d3SArmin Le Grand {
handleGeometricContent(const basegfx::B2DPolyPolygon & rClip,const basegfx::B2DPolyPolygon & rSource,GDIMetaFile & rTarget,bool bStroke)404665f8d3SArmin Le Grand     bool handleGeometricContent(
414665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
424665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rSource,
434665f8d3SArmin Le Grand         GDIMetaFile& rTarget,
444665f8d3SArmin Le Grand         bool bStroke)
454665f8d3SArmin Le Grand     {
464665f8d3SArmin Le Grand         if(rSource.count() && rClip.count())
474665f8d3SArmin Le Grand         {
484665f8d3SArmin Le Grand             const basegfx::B2DPolyPolygon aResult(
494665f8d3SArmin Le Grand                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
504665f8d3SArmin Le Grand                     rSource,
514665f8d3SArmin Le Grand                     rClip,
524665f8d3SArmin Le Grand                     true, // inside
534665f8d3SArmin Le Grand                     bStroke));
544665f8d3SArmin Le Grand 
554665f8d3SArmin Le Grand             if(aResult.count())
564665f8d3SArmin Le Grand             {
574665f8d3SArmin Le Grand                 if(aResult == rSource)
584665f8d3SArmin Le Grand                 {
594665f8d3SArmin Le Grand                     // not clipped, but inside. Add original
604665f8d3SArmin Le Grand                     return false;
614665f8d3SArmin Le Grand                 }
624665f8d3SArmin Le Grand                 else
634665f8d3SArmin Le Grand                 {
644665f8d3SArmin Le Grand                     // add clipped geometry
654665f8d3SArmin Le Grand                     if(bStroke)
664665f8d3SArmin Le Grand                     {
674665f8d3SArmin Le Grand                         for(sal_uInt32 a(0); a < aResult.count(); a++)
684665f8d3SArmin Le Grand                         {
694665f8d3SArmin Le Grand                             rTarget.AddAction(
704665f8d3SArmin Le Grand                                 new MetaPolyLineAction(
714665f8d3SArmin Le Grand                                     Polygon(aResult.getB2DPolygon(a))));
724665f8d3SArmin Le Grand                         }
734665f8d3SArmin Le Grand                     }
744665f8d3SArmin Le Grand                     else
754665f8d3SArmin Le Grand                     {
764665f8d3SArmin Le Grand                         rTarget.AddAction(
774665f8d3SArmin Le Grand                             new MetaPolyPolygonAction(
784665f8d3SArmin Le Grand                                 PolyPolygon(aResult)));
794665f8d3SArmin Le Grand                     }
804665f8d3SArmin Le Grand                 }
814665f8d3SArmin Le Grand             }
824665f8d3SArmin Le Grand         }
834665f8d3SArmin Le Grand 
844665f8d3SArmin Le Grand         return true;
854665f8d3SArmin Le Grand     }
864665f8d3SArmin Le Grand 
handleGradientContent(const basegfx::B2DPolyPolygon & rClip,const basegfx::B2DPolyPolygon & rSource,const Gradient & rGradient,GDIMetaFile & rTarget)874665f8d3SArmin Le Grand     bool handleGradientContent(
884665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
894665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rSource,
904665f8d3SArmin Le Grand         const Gradient& rGradient,
914665f8d3SArmin Le Grand         GDIMetaFile& rTarget)
924665f8d3SArmin Le Grand     {
934665f8d3SArmin Le Grand         if(rSource.count() && rClip.count())
944665f8d3SArmin Le Grand         {
954665f8d3SArmin Le Grand             const basegfx::B2DPolyPolygon aResult(
964665f8d3SArmin Le Grand                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
974665f8d3SArmin Le Grand                     rSource,
984665f8d3SArmin Le Grand                     rClip,
994665f8d3SArmin Le Grand                     true, // inside
1004665f8d3SArmin Le Grand                     false)); // stroke
1014665f8d3SArmin Le Grand 
1024665f8d3SArmin Le Grand             if(aResult.count())
1034665f8d3SArmin Le Grand             {
1044665f8d3SArmin Le Grand                 if(aResult == rSource)
1054665f8d3SArmin Le Grand                 {
1064665f8d3SArmin Le Grand                     // not clipped, but inside. Add original
1074665f8d3SArmin Le Grand                     return false;
1084665f8d3SArmin Le Grand                 }
1094665f8d3SArmin Le Grand                 else
1104665f8d3SArmin Le Grand                 {
1114665f8d3SArmin Le Grand                     // add clipped geometry
1124665f8d3SArmin Le Grand                     rTarget.AddAction(
1134665f8d3SArmin Le Grand                         new MetaGradientExAction(
1144665f8d3SArmin Le Grand                             PolyPolygon(aResult),
1154665f8d3SArmin Le Grand                             rGradient));
1164665f8d3SArmin Le Grand                 }
1174665f8d3SArmin Le Grand             }
1184665f8d3SArmin Le Grand         }
1194665f8d3SArmin Le Grand 
1204665f8d3SArmin Le Grand         return true;
1214665f8d3SArmin Le Grand     }
1224665f8d3SArmin Le Grand 
handleBitmapContent(const basegfx::B2DPolyPolygon & rClip,const Point & rPoint,const Size & rSize,const BitmapEx & rBitmapEx,GDIMetaFile & rTarget)1234665f8d3SArmin Le Grand     bool handleBitmapContent(
1244665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon& rClip,
1254665f8d3SArmin Le Grand         const Point& rPoint,
1264665f8d3SArmin Le Grand         const Size& rSize,
1274665f8d3SArmin Le Grand         const BitmapEx& rBitmapEx,
1284665f8d3SArmin Le Grand         GDIMetaFile& rTarget)
1294665f8d3SArmin Le Grand     {
1304665f8d3SArmin Le Grand         if(!rSize.Width() || !rSize.Height() || rBitmapEx.IsEmpty())
1314665f8d3SArmin Le Grand         {
1324665f8d3SArmin Le Grand             // bitmap or size is empty
1334665f8d3SArmin Le Grand             return true;
1344665f8d3SArmin Le Grand         }
1354665f8d3SArmin Le Grand 
1364665f8d3SArmin Le Grand         const basegfx::B2DRange aLogicBitmapRange(
1374665f8d3SArmin Le Grand             rPoint.X(), rPoint.Y(),
1384665f8d3SArmin Le Grand             rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height());
1394665f8d3SArmin Le Grand         const basegfx::B2DPolyPolygon aClipOfBitmap(
1404665f8d3SArmin Le Grand             basegfx::tools::clipPolyPolygonOnRange(
1414665f8d3SArmin Le Grand                 rClip,
1424665f8d3SArmin Le Grand                 aLogicBitmapRange,
1434665f8d3SArmin Le Grand                 true,
1444665f8d3SArmin Le Grand                 false)); // stroke
1454665f8d3SArmin Le Grand 
1464665f8d3SArmin Le Grand         if(!aClipOfBitmap.count())
1474665f8d3SArmin Le Grand         {
1484665f8d3SArmin Le Grand             // outside clip region
1494665f8d3SArmin Le Grand             return true;
1504665f8d3SArmin Le Grand         }
1514665f8d3SArmin Le Grand 
1524665f8d3SArmin Le Grand         // inside or overlapping. Use area to find out if it is completely
1534665f8d3SArmin Le Grand         // covering (inside) or overlapping
1544665f8d3SArmin Le Grand         const double fClipArea(basegfx::tools::getArea(aClipOfBitmap));
1554665f8d3SArmin Le Grand         const double fBitmapArea(
1564665f8d3SArmin Le Grand             aLogicBitmapRange.getWidth() * aLogicBitmapRange.getWidth() +
1574665f8d3SArmin Le Grand             aLogicBitmapRange.getHeight() * aLogicBitmapRange.getHeight());
1584665f8d3SArmin Le Grand         const double fFactor(fClipArea / fBitmapArea);
1594665f8d3SArmin Le Grand 
1604665f8d3SArmin Le Grand         if(basegfx::fTools::more(fFactor, 1.0 - 0.001))
1614665f8d3SArmin Le Grand         {
1624665f8d3SArmin Le Grand             // completely covering (with 0.1% tolerance)
1634665f8d3SArmin Le Grand             return false;
1644665f8d3SArmin Le Grand         }
1654665f8d3SArmin Le Grand 
1664665f8d3SArmin Le Grand         // needs clipping (with 0.1% tolerance). Prepare VirtualDevice
1674665f8d3SArmin Le Grand         // in pixel mode for alpha channel painting (black is transparent,
1684665f8d3SArmin Le Grand         // white to paint 100% opacity)
1694665f8d3SArmin Le Grand         const Size aSizePixel(rBitmapEx.GetSizePixel());
1704665f8d3SArmin Le Grand         VirtualDevice aVDev;
1714665f8d3SArmin Le Grand 
1724665f8d3SArmin Le Grand         aVDev.SetOutputSizePixel(aSizePixel);
1734665f8d3SArmin Le Grand         aVDev.EnableMapMode(false);
1744665f8d3SArmin Le Grand         aVDev.SetFillColor(COL_WHITE);
1754665f8d3SArmin Le Grand         aVDev.SetLineColor();
1764665f8d3SArmin Le Grand 
1774665f8d3SArmin Le Grand         if(rBitmapEx.IsTransparent())
1784665f8d3SArmin Le Grand         {
1794665f8d3SArmin Le Grand             // use given alpha channel
1804665f8d3SArmin Le Grand             aVDev.DrawBitmap(Point(0, 0), rBitmapEx.GetAlpha().GetBitmap());
1814665f8d3SArmin Le Grand         }
1824665f8d3SArmin Le Grand         else
1834665f8d3SArmin Le Grand         {
1844665f8d3SArmin Le Grand             // reset alpha channel
1854665f8d3SArmin Le Grand             aVDev.SetBackground(Wallpaper(Color(COL_BLACK)));
1864665f8d3SArmin Le Grand             aVDev.Erase();
1874665f8d3SArmin Le Grand         }
1884665f8d3SArmin Le Grand 
1894665f8d3SArmin Le Grand         // transform polygon from clipping to pixel coordinates
1904665f8d3SArmin Le Grand         basegfx::B2DPolyPolygon aPixelPoly(aClipOfBitmap);
1914665f8d3SArmin Le Grand         basegfx::B2DHomMatrix aTransform;
1924665f8d3SArmin Le Grand 
1934665f8d3SArmin Le Grand         aTransform.translate(-aLogicBitmapRange.getMinX(), -aLogicBitmapRange.getMinY());
1944665f8d3SArmin Le Grand         aTransform.scale(
1954665f8d3SArmin Le Grand             static_cast< double >(aSizePixel.Width()) / aLogicBitmapRange.getWidth(),
1964665f8d3SArmin Le Grand             static_cast< double >(aSizePixel.Height()) / aLogicBitmapRange.getHeight());
1974665f8d3SArmin Le Grand         aPixelPoly.transform(aTransform);
1984665f8d3SArmin Le Grand 
1994665f8d3SArmin Le Grand         // to fill the non-covered parts, use the Xor fill rule of
2004665f8d3SArmin Le Grand         // PolyPolygon painting. Start with a all-covering polygon and
2014665f8d3SArmin Le Grand         // add the clip polygon one
2024665f8d3SArmin Le Grand         basegfx::B2DPolyPolygon aInvertPixelPoly;
2034665f8d3SArmin Le Grand 
2044665f8d3SArmin Le Grand         aInvertPixelPoly.append(
2054665f8d3SArmin Le Grand             basegfx::tools::createPolygonFromRect(
2064665f8d3SArmin Le Grand                 basegfx::B2DRange(
2074665f8d3SArmin Le Grand                     0.0, 0.0,
2084665f8d3SArmin Le Grand                     aSizePixel.Width(), aSizePixel.Height())));
2094665f8d3SArmin Le Grand         aInvertPixelPoly.append(aPixelPoly);
2104665f8d3SArmin Le Grand 
2114665f8d3SArmin Le Grand         // paint as alpha
2124665f8d3SArmin Le Grand         aVDev.DrawPolyPolygon(aInvertPixelPoly);
2134665f8d3SArmin Le Grand 
2144665f8d3SArmin Le Grand         // get created alpha mask and set defaults
2154665f8d3SArmin Le Grand         AlphaMask aAlpha(
2164665f8d3SArmin Le Grand             aVDev.GetBitmap(
2174665f8d3SArmin Le Grand                 Point(0, 0),
2184665f8d3SArmin Le Grand                 aSizePixel));
2194665f8d3SArmin Le Grand 
2204665f8d3SArmin Le Grand         aAlpha.SetPrefSize(rBitmapEx.GetPrefSize());
2214665f8d3SArmin Le Grand         aAlpha.SetPrefMapMode(rBitmapEx.GetPrefMapMode());
2224665f8d3SArmin Le Grand 
2234665f8d3SArmin Le Grand         // add new action replacing the old one
2244665f8d3SArmin Le Grand         rTarget.AddAction(
2254665f8d3SArmin Le Grand             new MetaBmpExScaleAction(
2264665f8d3SArmin Le Grand                 Point(
2274665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getMinX()),
2284665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getMinY())),
2294665f8d3SArmin Le Grand                 Size(
2304665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getWidth()),
2314665f8d3SArmin Le Grand                     basegfx::fround(aLogicBitmapRange.getHeight())),
2324665f8d3SArmin Le Grand                 BitmapEx(rBitmapEx.GetBitmap(), aAlpha)));
2334665f8d3SArmin Le Grand 
2344665f8d3SArmin Le Grand         return true;
2354665f8d3SArmin Le Grand     }
2364665f8d3SArmin Le Grand 
addSvtGraphicStroke(const SvtGraphicStroke & rStroke,GDIMetaFile & rTarget)2374665f8d3SArmin Le Grand     void addSvtGraphicStroke(const SvtGraphicStroke& rStroke, GDIMetaFile& rTarget)
2384665f8d3SArmin Le Grand     {
2394665f8d3SArmin Le Grand         // write SvtGraphicFill
2404665f8d3SArmin Le Grand         SvMemoryStream aMemStm;
2414665f8d3SArmin Le Grand         aMemStm << rStroke;
2424665f8d3SArmin Le Grand         rTarget.AddAction(
2434665f8d3SArmin Le Grand             new MetaCommentAction(
2444665f8d3SArmin Le Grand                 "XPATHSTROKE_SEQ_BEGIN",
2454665f8d3SArmin Le Grand                 0,
2464665f8d3SArmin Le Grand                 static_cast< const sal_uInt8* >(aMemStm.GetData()),
2474665f8d3SArmin Le Grand                 aMemStm.Seek(STREAM_SEEK_TO_END)));
2484665f8d3SArmin Le Grand     }
2494665f8d3SArmin Le Grand 
addSvtGraphicFill(const SvtGraphicFill & rFilling,GDIMetaFile & rTarget)2504665f8d3SArmin Le Grand     void addSvtGraphicFill(const SvtGraphicFill &rFilling, GDIMetaFile& rTarget)
2514665f8d3SArmin Le Grand     {
2524665f8d3SArmin Le Grand         // write SvtGraphicFill
2534665f8d3SArmin Le Grand         SvMemoryStream aMemStm;
2544665f8d3SArmin Le Grand         aMemStm << rFilling;
2554665f8d3SArmin Le Grand         rTarget.AddAction(
2564665f8d3SArmin Le Grand             new MetaCommentAction(
2574665f8d3SArmin Le Grand                 "XPATHFILL_SEQ_BEGIN",
2584665f8d3SArmin Le Grand                 0,
2594665f8d3SArmin Le Grand                 static_cast< const sal_uInt8* >(aMemStm.GetData()),
2604665f8d3SArmin Le Grand                 aMemStm.Seek(STREAM_SEEK_TO_END)));
2614665f8d3SArmin Le Grand     }
2624665f8d3SArmin Le Grand } // end of anonymous namespace
2634665f8d3SArmin Le Grand 
2644665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
2654665f8d3SArmin Le Grand // #121267# Tooling to internally clip geometry against internal clip regions
2664665f8d3SArmin Le Grand 
clipMetafileContentAgainstOwnRegions(GDIMetaFile & rSource)2674665f8d3SArmin Le Grand void clipMetafileContentAgainstOwnRegions(GDIMetaFile& rSource)
2684665f8d3SArmin Le Grand {
2694665f8d3SArmin Le Grand     const sal_uLong nObjCount(rSource.GetActionCount());
2704665f8d3SArmin Le Grand 
2714665f8d3SArmin Le Grand     if(!nObjCount)
2724665f8d3SArmin Le Grand     {
2734665f8d3SArmin Le Grand         return;
2744665f8d3SArmin Le Grand     }
2754665f8d3SArmin Le Grand 
2764665f8d3SArmin Le Grand     // prepare target data container and push/pop stack data
2774665f8d3SArmin Le Grand     GDIMetaFile aTarget;
2784665f8d3SArmin Le Grand     bool bChanged(false);
2794665f8d3SArmin Le Grand     std::vector< basegfx::B2DPolyPolygon > aClips;
2804665f8d3SArmin Le Grand     std::vector< sal_uInt16 > aPushFlags;
2814665f8d3SArmin Le Grand     std::vector< MapMode > aMapModes;
2824665f8d3SArmin Le Grand 
2834665f8d3SArmin Le Grand     // start with empty region
2844665f8d3SArmin Le Grand     aClips.push_back(basegfx::B2DPolyPolygon());
2854665f8d3SArmin Le Grand 
2864665f8d3SArmin Le Grand     // start with default MapMode (MAP_PIXEL)
2874665f8d3SArmin Le Grand     aMapModes.push_back(MapMode());
2884665f8d3SArmin Le Grand 
2894665f8d3SArmin Le Grand     for(sal_uLong i(0); i < nObjCount; ++i)
2904665f8d3SArmin Le Grand     {
2914665f8d3SArmin Le Grand         const MetaAction* pAction(rSource.GetAction(i));
2924665f8d3SArmin Le Grand         const sal_uInt16 nType(pAction->GetType());
2934665f8d3SArmin Le Grand         bool bDone(false);
2944665f8d3SArmin Le Grand 
2954665f8d3SArmin Le Grand         // basic operation takes care of clipregion actions (four) and push/pop of these
2964665f8d3SArmin Le Grand         // to steer the currently set clip region. There *is* an active
2974665f8d3SArmin Le Grand         // clip region when (aClips.size() && aClips.back().count()), see
2984665f8d3SArmin Le Grand         // below
2994665f8d3SArmin Le Grand         switch(nType)
3004665f8d3SArmin Le Grand         {
3014665f8d3SArmin Le Grand             case META_CLIPREGION_ACTION :
3024665f8d3SArmin Le Grand             {
3034665f8d3SArmin Le Grand                 const MetaClipRegionAction* pA = static_cast< const MetaClipRegionAction* >(pAction);
3044665f8d3SArmin Le Grand 
3054665f8d3SArmin Le Grand                 if(pA->IsClipping())
3064665f8d3SArmin Le Grand                 {
3074665f8d3SArmin Le Grand                     const Region& rRegion = pA->GetRegion();
3084665f8d3SArmin Le Grand                     const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
3094665f8d3SArmin Le Grand 
3104665f8d3SArmin Le Grand                     aClips.back() = aNewClip;
3114665f8d3SArmin Le Grand                 }
3124665f8d3SArmin Le Grand                 else
3134665f8d3SArmin Le Grand                 {
3144665f8d3SArmin Le Grand                     aClips.back() = basegfx::B2DPolyPolygon();
3154665f8d3SArmin Le Grand                 }
3164665f8d3SArmin Le Grand 
3174665f8d3SArmin Le Grand                 break;
3184665f8d3SArmin Le Grand             }
3194665f8d3SArmin Le Grand 
3204665f8d3SArmin Le Grand             case META_ISECTRECTCLIPREGION_ACTION :
3214665f8d3SArmin Le Grand             {
3224665f8d3SArmin Le Grand                 const MetaISectRectClipRegionAction* pA = static_cast< const MetaISectRectClipRegionAction* >(pAction);
3234665f8d3SArmin Le Grand                 const Rectangle& rRect = pA->GetRect();
3244665f8d3SArmin Le Grand 
3254665f8d3SArmin Le Grand                 if(!rRect.IsEmpty() && aClips.size() && aClips.back().count())
3264665f8d3SArmin Le Grand                 {
3274665f8d3SArmin Le Grand                     const basegfx::B2DRange aClipRange(
3284665f8d3SArmin Le Grand                         rRect.Left(), rRect.Top(),
3294665f8d3SArmin Le Grand                         rRect.Right(), rRect.Bottom());
3304665f8d3SArmin Le Grand 
3314665f8d3SArmin Le Grand                     aClips.back() = basegfx::tools::clipPolyPolygonOnRange(
3324665f8d3SArmin Le Grand                         aClips.back(),
3334665f8d3SArmin Le Grand                         aClipRange,
3344665f8d3SArmin Le Grand                         true, // inside
3354665f8d3SArmin Le Grand                         false); // stroke
3364665f8d3SArmin Le Grand                 }
3374665f8d3SArmin Le Grand                 break;
3384665f8d3SArmin Le Grand             }
3394665f8d3SArmin Le Grand 
3404665f8d3SArmin Le Grand             case META_ISECTREGIONCLIPREGION_ACTION :
3414665f8d3SArmin Le Grand             {
3424665f8d3SArmin Le Grand                 const MetaISectRegionClipRegionAction* pA = static_cast< const MetaISectRegionClipRegionAction* >(pAction);
3434665f8d3SArmin Le Grand                 const Region& rRegion = pA->GetRegion();
3444665f8d3SArmin Le Grand 
3454665f8d3SArmin Le Grand                 if(!rRegion.IsEmpty() && aClips.size() && aClips.back().count())
3464665f8d3SArmin Le Grand                 {
3474665f8d3SArmin Le Grand                     const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
3484665f8d3SArmin Le Grand 
3494665f8d3SArmin Le Grand                     aClips.back() = basegfx::tools::clipPolyPolygonOnPolyPolygon(
3504665f8d3SArmin Le Grand                         aClips.back(),
3514665f8d3SArmin Le Grand                         aNewClip,
3524665f8d3SArmin Le Grand                         true,  // inside
3534665f8d3SArmin Le Grand                         false); // stroke
3544665f8d3SArmin Le Grand                 }
3554665f8d3SArmin Le Grand                 break;
3564665f8d3SArmin Le Grand             }
3574665f8d3SArmin Le Grand 
3584665f8d3SArmin Le Grand             case META_MOVECLIPREGION_ACTION :
3594665f8d3SArmin Le Grand             {
3604665f8d3SArmin Le Grand                 const MetaMoveClipRegionAction* pA = static_cast< const MetaMoveClipRegionAction* >(pAction);
3614665f8d3SArmin Le Grand                 const long aHorMove(pA->GetHorzMove());
3624665f8d3SArmin Le Grand                 const long aVerMove(pA->GetVertMove());
3634665f8d3SArmin Le Grand 
3644665f8d3SArmin Le Grand                 if((aHorMove || aVerMove) && aClips.size() && aClips.back().count())
3654665f8d3SArmin Le Grand                 {
3664665f8d3SArmin Le Grand                     aClips.back().transform(
3674665f8d3SArmin Le Grand                         basegfx::tools::createTranslateB2DHomMatrix(
3684665f8d3SArmin Le Grand                             aHorMove,
3694665f8d3SArmin Le Grand                             aVerMove));
3704665f8d3SArmin Le Grand                 }
3714665f8d3SArmin Le Grand                 break;
3724665f8d3SArmin Le Grand             }
3734665f8d3SArmin Le Grand 
3744665f8d3SArmin Le Grand             case META_PUSH_ACTION :
3754665f8d3SArmin Le Grand             {
3764665f8d3SArmin Le Grand                 const MetaPushAction* pA = static_cast< const MetaPushAction* >(pAction);
3774665f8d3SArmin Le Grand                 const sal_uInt16 nFlags(pA->GetFlags());
3784665f8d3SArmin Le Grand 
3794665f8d3SArmin Le Grand                 aPushFlags.push_back(nFlags);
3804665f8d3SArmin Le Grand 
3814665f8d3SArmin Le Grand                 if(nFlags & PUSH_CLIPREGION)
3824665f8d3SArmin Le Grand                 {
3834665f8d3SArmin Le Grand                     aClips.push_back(aClips.back());
3844665f8d3SArmin Le Grand                 }
3854665f8d3SArmin Le Grand 
3864665f8d3SArmin Le Grand                 if(nFlags & PUSH_MAPMODE)
3874665f8d3SArmin Le Grand                 {
3884665f8d3SArmin Le Grand                     aMapModes.push_back(aMapModes.back());
3894665f8d3SArmin Le Grand                 }
3904665f8d3SArmin Le Grand                 break;
3914665f8d3SArmin Le Grand             }
3924665f8d3SArmin Le Grand 
3934665f8d3SArmin Le Grand             case META_POP_ACTION :
3944665f8d3SArmin Le Grand             {
3954665f8d3SArmin Le Grand 
3964665f8d3SArmin Le Grand                 if(aPushFlags.size())
3974665f8d3SArmin Le Grand                 {
3984665f8d3SArmin Le Grand                     const sal_uInt16 nFlags(aPushFlags.back());
3994665f8d3SArmin Le Grand                     aPushFlags.pop_back();
4004665f8d3SArmin Le Grand 
4014665f8d3SArmin Le Grand                     if(nFlags & PUSH_CLIPREGION)
4024665f8d3SArmin Le Grand                     {
4034665f8d3SArmin Le Grand                         if(aClips.size() > 1)
4044665f8d3SArmin Le Grand                         {
4054665f8d3SArmin Le Grand                             aClips.pop_back();
4064665f8d3SArmin Le Grand                         }
4074665f8d3SArmin Le Grand                         else
4084665f8d3SArmin Le Grand                         {
4094665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in ClipRegions (!)");
4104665f8d3SArmin Le Grand                         }
4114665f8d3SArmin Le Grand                     }
4124665f8d3SArmin Le Grand 
4134665f8d3SArmin Le Grand                     if(nFlags & PUSH_MAPMODE)
4144665f8d3SArmin Le Grand                     {
4154665f8d3SArmin Le Grand                         if(aMapModes.size() > 1)
4164665f8d3SArmin Le Grand                         {
4174665f8d3SArmin Le Grand                             aMapModes.pop_back();
4184665f8d3SArmin Le Grand                         }
4194665f8d3SArmin Le Grand                         else
4204665f8d3SArmin Le Grand                         {
4214665f8d3SArmin Le Grand                             OSL_ENSURE(false, "Wrong POP() in MapModes (!)");
4224665f8d3SArmin Le Grand                         }
4234665f8d3SArmin Le Grand                     }
4244665f8d3SArmin Le Grand                 }
4254665f8d3SArmin Le Grand                 else
4264665f8d3SArmin Le Grand                 {
4274665f8d3SArmin Le Grand                     OSL_ENSURE(false, "Invalid pop() without push() (!)");
4284665f8d3SArmin Le Grand                 }
4294665f8d3SArmin Le Grand 
4304665f8d3SArmin Le Grand                 break;
4314665f8d3SArmin Le Grand             }
4324665f8d3SArmin Le Grand 
4334665f8d3SArmin Le Grand             case META_MAPMODE_ACTION :
4344665f8d3SArmin Le Grand             {
4354665f8d3SArmin Le Grand                 const MetaMapModeAction* pA = static_cast< const MetaMapModeAction* >(pAction);
4364665f8d3SArmin Le Grand 
4374665f8d3SArmin Le Grand                 aMapModes.back() = pA->GetMapMode();
4384665f8d3SArmin Le Grand                 break;
4394665f8d3SArmin Le Grand             }
4404665f8d3SArmin Le Grand 
4414665f8d3SArmin Le Grand             default:
4424665f8d3SArmin Le Grand             {
4434665f8d3SArmin Le Grand                 break;
4444665f8d3SArmin Le Grand             }
4454665f8d3SArmin Le Grand         }
4464665f8d3SArmin Le Grand 
4474665f8d3SArmin Le Grand         // this area contains all actions which could potentially be clipped. Since
4484665f8d3SArmin Le Grand         // this tooling is only a fallback (see comments in header), only the needed
4494665f8d3SArmin Le Grand         // actions will be implemented. Extend using the pattern for the already
4504665f8d3SArmin Le Grand         // implemented actions.
4514665f8d3SArmin Le Grand         if(aClips.size() && aClips.back().count())
4524665f8d3SArmin Le Grand         {
4534665f8d3SArmin Le Grand             switch(nType)
4544665f8d3SArmin Le Grand             {
4554665f8d3SArmin Le Grand                 //
4564665f8d3SArmin Le Grand                 // pixel actions, just check on inside
4574665f8d3SArmin Le Grand                 //
4584665f8d3SArmin Le Grand                 case META_PIXEL_ACTION :
4594665f8d3SArmin Le Grand                 {
4604665f8d3SArmin Le Grand                     const MetaPixelAction* pA = static_cast< const MetaPixelAction* >(pAction);
4614665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
4624665f8d3SArmin Le Grand 
4634665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
4644665f8d3SArmin Le Grand                         aClips.back(),
4654665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
4664665f8d3SArmin Le Grand                     {
4674665f8d3SArmin Le Grand                         // when not inside, do not add original
4684665f8d3SArmin Le Grand                         bDone = true;
4694665f8d3SArmin Le Grand                     }
4704665f8d3SArmin Le Grand                     break;
4714665f8d3SArmin Le Grand                 }
4724665f8d3SArmin Le Grand 
4734665f8d3SArmin Le Grand                 case META_POINT_ACTION :
4744665f8d3SArmin Le Grand                 {
4754665f8d3SArmin Le Grand                     const MetaPointAction* pA = static_cast< const MetaPointAction* >(pAction);
4764665f8d3SArmin Le Grand                     const Point& rPoint = pA->GetPoint();
4774665f8d3SArmin Le Grand 
4784665f8d3SArmin Le Grand                     if(!basegfx::tools::isInside(
4794665f8d3SArmin Le Grand                         aClips.back(),
4804665f8d3SArmin Le Grand                         basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
4814665f8d3SArmin Le Grand                     {
4824665f8d3SArmin Le Grand                         // when not inside, do not add original
4834665f8d3SArmin Le Grand                         bDone = true;
4844665f8d3SArmin Le Grand                     }
4854665f8d3SArmin Le Grand                     break;
4864665f8d3SArmin Le Grand                 }
4874665f8d3SArmin Le Grand 
4884665f8d3SArmin Le Grand                 //
4894665f8d3SArmin Le Grand                 // geometry actions
4904665f8d3SArmin Le Grand                 //
4914665f8d3SArmin Le Grand                 case META_LINE_ACTION :
4924665f8d3SArmin Le Grand                 {
4934665f8d3SArmin Le Grand                     const MetaLineAction* pA = static_cast< const MetaLineAction* >(pAction);
4944665f8d3SArmin Le Grand                     const Point& rStart(pA->GetStartPoint());
4954665f8d3SArmin Le Grand                     const Point& rEnd(pA->GetEndPoint());
4964665f8d3SArmin Le Grand                     basegfx::B2DPolygon aLine;
4974665f8d3SArmin Le Grand 
4984665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
4994665f8d3SArmin Le Grand                     aLine.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
5004665f8d3SArmin Le Grand 
5014665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
5024665f8d3SArmin Le Grand                         aClips.back(),
5034665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(aLine),
5044665f8d3SArmin Le Grand                         aTarget,
5054665f8d3SArmin Le Grand                         true); // stroke
5064665f8d3SArmin Le Grand                     break;
5074665f8d3SArmin Le Grand                 }
5084665f8d3SArmin Le Grand 
5094665f8d3SArmin Le Grand                 case META_RECT_ACTION :
5104665f8d3SArmin Le Grand                 {
5114665f8d3SArmin Le Grand                     const MetaRectAction* pA = static_cast< const MetaRectAction* >(pAction);
5124665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
5134665f8d3SArmin Le Grand 
5144665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
5154665f8d3SArmin Le Grand                     {
5164665f8d3SArmin Le Grand                         bDone = true;
5174665f8d3SArmin Le Grand                     }
5184665f8d3SArmin Le Grand                     else
5194665f8d3SArmin Le Grand                     {
5204665f8d3SArmin Le Grand 
5214665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
5224665f8d3SArmin Le Grand                             aClips.back(),
5234665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
5244665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
5254665f8d3SArmin Le Grand                                     basegfx::B2DRange(
5264665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
5274665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
5284665f8d3SArmin Le Grand                             aTarget,
5294665f8d3SArmin Le Grand                             false); // stroke
5304665f8d3SArmin Le Grand                     }
5314665f8d3SArmin Le Grand                     break;
5324665f8d3SArmin Le Grand                 }
5334665f8d3SArmin Le Grand 
5344665f8d3SArmin Le Grand                 case META_ROUNDRECT_ACTION :
5354665f8d3SArmin Le Grand                 {
5364665f8d3SArmin Le Grand                     const MetaRoundRectAction* pA = static_cast< const MetaRoundRectAction* >(pAction);
5374665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
5384665f8d3SArmin Le Grand 
5394665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
5404665f8d3SArmin Le Grand                     {
5414665f8d3SArmin Le Grand                         bDone = true;
5424665f8d3SArmin Le Grand                     }
5434665f8d3SArmin Le Grand                     else
5444665f8d3SArmin Le Grand                     {
5454665f8d3SArmin Le Grand                         const sal_uInt32 nHor(pA->GetHorzRound());
5464665f8d3SArmin Le Grand                         const sal_uInt32 nVer(pA->GetVertRound());
5474665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
5484665f8d3SArmin Le Grand                         basegfx::B2DPolygon aOutline;
5494665f8d3SArmin Le Grand 
5504665f8d3SArmin Le Grand                         if(nHor || nVer)
5514665f8d3SArmin Le Grand                         {
5524665f8d3SArmin Le Grand                             double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
5534665f8d3SArmin Le Grand                             double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
5544665f8d3SArmin Le Grand                             fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
5554665f8d3SArmin Le Grand                             fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
5564665f8d3SArmin Le Grand 
5574665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
5584665f8d3SArmin Le Grand                         }
5594665f8d3SArmin Le Grand                         else
5604665f8d3SArmin Le Grand                         {
5614665f8d3SArmin Le Grand                             aOutline = basegfx::tools::createPolygonFromRect(aRange);
5624665f8d3SArmin Le Grand                         }
5634665f8d3SArmin Le Grand 
5644665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
5654665f8d3SArmin Le Grand                             aClips.back(),
5664665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aOutline),
5674665f8d3SArmin Le Grand                             aTarget,
5684665f8d3SArmin Le Grand                             false); // stroke
5694665f8d3SArmin Le Grand                     }
5704665f8d3SArmin Le Grand                     break;
5714665f8d3SArmin Le Grand                 }
5724665f8d3SArmin Le Grand 
5734665f8d3SArmin Le Grand                 case META_ELLIPSE_ACTION :
5744665f8d3SArmin Le Grand                 {
5754665f8d3SArmin Le Grand                     const MetaEllipseAction* pA = static_cast< const MetaEllipseAction* >(pAction);
5764665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
5774665f8d3SArmin Le Grand 
5784665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
5794665f8d3SArmin Le Grand                     {
5804665f8d3SArmin Le Grand                         bDone = true;
5814665f8d3SArmin Le Grand                     }
5824665f8d3SArmin Le Grand                     else
5834665f8d3SArmin Le Grand                     {
5844665f8d3SArmin Le Grand                         const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
5854665f8d3SArmin Le Grand 
5864665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
5874665f8d3SArmin Le Grand                             aClips.back(),
5884665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
5894665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromEllipse(
5904665f8d3SArmin Le Grand                                     aRange.getCenter(),
5914665f8d3SArmin Le Grand                                     aRange.getWidth() * 0.5,
5924665f8d3SArmin Le Grand                                     aRange.getHeight() * 0.5)),
5934665f8d3SArmin Le Grand                             aTarget,
5944665f8d3SArmin Le Grand                             false); // stroke
5954665f8d3SArmin Le Grand                     }
5964665f8d3SArmin Le Grand                     break;
5974665f8d3SArmin Le Grand                 }
5984665f8d3SArmin Le Grand 
5994665f8d3SArmin Le Grand                 case META_ARC_ACTION :
6004665f8d3SArmin Le Grand                 {
6014665f8d3SArmin Le Grand                     const MetaArcAction* pA = static_cast< const MetaArcAction* >(pAction);
6024665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
6034665f8d3SArmin Le Grand 
6044665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
6054665f8d3SArmin Le Grand                     {
6064665f8d3SArmin Le Grand                         bDone = true;
6074665f8d3SArmin Le Grand                     }
6084665f8d3SArmin Le Grand                     else
6094665f8d3SArmin Le Grand                     {
6104665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
6114665f8d3SArmin Le Grand                             rRect,
6124665f8d3SArmin Le Grand                             pA->GetStartPoint(),
6134665f8d3SArmin Le Grand                             pA->GetEndPoint(),
6144665f8d3SArmin Le Grand                             POLY_ARC);
6154665f8d3SArmin Le Grand 
6164665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
6174665f8d3SArmin Le Grand                             aClips.back(),
6184665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
6194665f8d3SArmin Le Grand                             aTarget,
6204665f8d3SArmin Le Grand                             true); // stroke
6214665f8d3SArmin Le Grand                     }
6224665f8d3SArmin Le Grand                     break;
6234665f8d3SArmin Le Grand                 }
6244665f8d3SArmin Le Grand 
6254665f8d3SArmin Le Grand                 case META_PIE_ACTION :
6264665f8d3SArmin Le Grand                 {
6274665f8d3SArmin Le Grand                     const MetaPieAction* pA = static_cast< const MetaPieAction* >(pAction);
6284665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
6294665f8d3SArmin Le Grand 
6304665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
6314665f8d3SArmin Le Grand                     {
6324665f8d3SArmin Le Grand                         bDone = true;
6334665f8d3SArmin Le Grand                     }
6344665f8d3SArmin Le Grand                     else
6354665f8d3SArmin Le Grand                     {
6364665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
6374665f8d3SArmin Le Grand                             rRect,
6384665f8d3SArmin Le Grand                             pA->GetStartPoint(),
6394665f8d3SArmin Le Grand                             pA->GetEndPoint(),
6404665f8d3SArmin Le Grand                             POLY_PIE);
6414665f8d3SArmin Le Grand 
6424665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
6434665f8d3SArmin Le Grand                             aClips.back(),
6444665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
6454665f8d3SArmin Le Grand                             aTarget,
6464665f8d3SArmin Le Grand                             false); // stroke
6474665f8d3SArmin Le Grand                     }
6484665f8d3SArmin Le Grand                     break;
6494665f8d3SArmin Le Grand                 }
6504665f8d3SArmin Le Grand 
6514665f8d3SArmin Le Grand                 case META_CHORD_ACTION :
6524665f8d3SArmin Le Grand                 {
6534665f8d3SArmin Le Grand                     const MetaChordAction* pA = static_cast< const MetaChordAction* >(pAction);
6544665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
6554665f8d3SArmin Le Grand 
6564665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
6574665f8d3SArmin Le Grand                     {
6584665f8d3SArmin Le Grand                         bDone = true;
6594665f8d3SArmin Le Grand                     }
6604665f8d3SArmin Le Grand                     else
6614665f8d3SArmin Le Grand                     {
6624665f8d3SArmin Le Grand                         const Polygon aToolsPoly(
6634665f8d3SArmin Le Grand                             rRect,
6644665f8d3SArmin Le Grand                             pA->GetStartPoint(),
6654665f8d3SArmin Le Grand                             pA->GetEndPoint(),
6664665f8d3SArmin Le Grand                             POLY_CHORD);
6674665f8d3SArmin Le Grand 
6684665f8d3SArmin Le Grand                         bDone = handleGeometricContent(
6694665f8d3SArmin Le Grand                             aClips.back(),
6704665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
6714665f8d3SArmin Le Grand                             aTarget,
6724665f8d3SArmin Le Grand                             false); // stroke
6734665f8d3SArmin Le Grand                     }
6744665f8d3SArmin Le Grand                     break;
6754665f8d3SArmin Le Grand                 }
6764665f8d3SArmin Le Grand 
6774665f8d3SArmin Le Grand                 case META_POLYLINE_ACTION :
6784665f8d3SArmin Le Grand                 {
6794665f8d3SArmin Le Grand                     const MetaPolyLineAction* pA = static_cast< const MetaPolyLineAction* >(pAction);
6804665f8d3SArmin Le Grand 
6814665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
6824665f8d3SArmin Le Grand                         aClips.back(),
6834665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
6844665f8d3SArmin Le Grand                         aTarget,
6854665f8d3SArmin Le Grand                         true); // stroke
6864665f8d3SArmin Le Grand                     break;
6874665f8d3SArmin Le Grand                 }
6884665f8d3SArmin Le Grand 
6894665f8d3SArmin Le Grand                 case META_POLYGON_ACTION :
6904665f8d3SArmin Le Grand                 {
6914665f8d3SArmin Le Grand                     const MetaPolygonAction* pA = static_cast< const MetaPolygonAction* >(pAction);
6924665f8d3SArmin Le Grand 
6934665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
6944665f8d3SArmin Le Grand                         aClips.back(),
6954665f8d3SArmin Le Grand                         basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
6964665f8d3SArmin Le Grand                         aTarget,
6974665f8d3SArmin Le Grand                         false); // stroke
6984665f8d3SArmin Le Grand                     break;
6994665f8d3SArmin Le Grand                 }
7004665f8d3SArmin Le Grand 
7014665f8d3SArmin Le Grand                 case META_POLYPOLYGON_ACTION :
7024665f8d3SArmin Le Grand                 {
7034665f8d3SArmin Le Grand                     const MetaPolyPolygonAction* pA = static_cast< const MetaPolyPolygonAction* >(pAction);
7044665f8d3SArmin Le Grand                     const PolyPolygon& rPoly = pA->GetPolyPolygon();
7054665f8d3SArmin Le Grand 
7064665f8d3SArmin Le Grand                     bDone = handleGeometricContent(
7074665f8d3SArmin Le Grand                         aClips.back(),
7084665f8d3SArmin Le Grand                         rPoly.getB2DPolyPolygon(),
7094665f8d3SArmin Le Grand                         aTarget,
7104665f8d3SArmin Le Grand                         false); // stroke
7114665f8d3SArmin Le Grand                     break;
7124665f8d3SArmin Le Grand                 }
7134665f8d3SArmin Le Grand 
7144665f8d3SArmin Le Grand                 //
7154665f8d3SArmin Le Grand                 // bitmap actions, create BitmapEx with alpha channel derived
7164665f8d3SArmin Le Grand                 // from clipping
7174665f8d3SArmin Le Grand                 //
7184665f8d3SArmin Le Grand                 case META_BMPEX_ACTION :
7194665f8d3SArmin Le Grand                 {
7204665f8d3SArmin Le Grand                     const MetaBmpExAction* pA = static_cast< const MetaBmpExAction* >(pAction);
7214665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
7224665f8d3SArmin Le Grand 
7234665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
7244665f8d3SArmin Le Grand                     // combination with the current MapMode
7254665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmapEx.GetPrefSize());
7264665f8d3SArmin Le Grand 
7274665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmapEx.GetPrefMapMode().GetMapUnit())
7284665f8d3SArmin Le Grand                     {
7294665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
7304665f8d3SArmin Le Grand                     }
7314665f8d3SArmin Le Grand                     else
7324665f8d3SArmin Le Grand                     {
7334665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmapEx.GetPrefMapMode(), aMapModes.back().GetMapUnit());
7344665f8d3SArmin Le Grand                     }
7354665f8d3SArmin Le Grand 
7364665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
7374665f8d3SArmin Le Grand                         aClips.back(),
7384665f8d3SArmin Le Grand                         pA->GetPoint(),
7394665f8d3SArmin Le Grand                         aLogicalSize,
7404665f8d3SArmin Le Grand                         rBitmapEx,
7414665f8d3SArmin Le Grand                         aTarget);
7424665f8d3SArmin Le Grand                     break;
7434665f8d3SArmin Le Grand                 }
7444665f8d3SArmin Le Grand 
7454665f8d3SArmin Le Grand                 case META_BMP_ACTION :
7464665f8d3SArmin Le Grand                 {
7474665f8d3SArmin Le Grand                     const MetaBmpAction* pA = static_cast< const MetaBmpAction* >(pAction);
7484665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
7494665f8d3SArmin Le Grand 
7504665f8d3SArmin Le Grand                     // the logical size depends on the PrefSize of the given bitmap in
7514665f8d3SArmin Le Grand                     // combination with the current MapMode
7524665f8d3SArmin Le Grand                     Size aLogicalSize(rBitmap.GetPrefSize());
7534665f8d3SArmin Le Grand 
7544665f8d3SArmin Le Grand                     if(MAP_PIXEL == rBitmap.GetPrefMapMode().GetMapUnit())
7554665f8d3SArmin Le Grand                     {
7564665f8d3SArmin Le Grand                         aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit());
7574665f8d3SArmin Le Grand                     }
7584665f8d3SArmin Le Grand                     else
7594665f8d3SArmin Le Grand                     {
7604665f8d3SArmin Le Grand                         aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmap.GetPrefMapMode(), aMapModes.back().GetMapUnit());
7614665f8d3SArmin Le Grand                     }
7624665f8d3SArmin Le Grand 
7634665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
7644665f8d3SArmin Le Grand                         aClips.back(),
7654665f8d3SArmin Le Grand                         pA->GetPoint(),
7664665f8d3SArmin Le Grand                         aLogicalSize,
7674665f8d3SArmin Le Grand                         BitmapEx(rBitmap),
7684665f8d3SArmin Le Grand                         aTarget);
7694665f8d3SArmin Le Grand                     break;
7704665f8d3SArmin Le Grand                 }
7714665f8d3SArmin Le Grand 
7724665f8d3SArmin Le Grand                 case META_BMPEXSCALE_ACTION :
7734665f8d3SArmin Le Grand                 {
7744665f8d3SArmin Le Grand                     const MetaBmpExScaleAction* pA = static_cast< const MetaBmpExScaleAction* >(pAction);
7754665f8d3SArmin Le Grand 
7764665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
7774665f8d3SArmin Le Grand                         aClips.back(),
7784665f8d3SArmin Le Grand                         pA->GetPoint(),
7794665f8d3SArmin Le Grand                         pA->GetSize(),
7804665f8d3SArmin Le Grand                         pA->GetBitmapEx(),
7814665f8d3SArmin Le Grand                         aTarget);
7824665f8d3SArmin Le Grand                     break;
7834665f8d3SArmin Le Grand                 }
7844665f8d3SArmin Le Grand 
7854665f8d3SArmin Le Grand                 case META_BMPSCALE_ACTION :
7864665f8d3SArmin Le Grand                 {
7874665f8d3SArmin Le Grand                     const MetaBmpScaleAction* pA = static_cast< const MetaBmpScaleAction* >(pAction);
7884665f8d3SArmin Le Grand 
7894665f8d3SArmin Le Grand                     bDone = handleBitmapContent(
7904665f8d3SArmin Le Grand                         aClips.back(),
7914665f8d3SArmin Le Grand                         pA->GetPoint(),
7924665f8d3SArmin Le Grand                         pA->GetSize(),
7934665f8d3SArmin Le Grand                         BitmapEx(pA->GetBitmap()),
7944665f8d3SArmin Le Grand                         aTarget);
7954665f8d3SArmin Le Grand                     break;
7964665f8d3SArmin Le Grand                 }
7974665f8d3SArmin Le Grand 
7984665f8d3SArmin Le Grand                 case META_BMPEXSCALEPART_ACTION :
7994665f8d3SArmin Le Grand                 {
8004665f8d3SArmin Le Grand                     const MetaBmpExScalePartAction* pA = static_cast< const MetaBmpExScalePartAction* >(pAction);
8014665f8d3SArmin Le Grand                     const BitmapEx& rBitmapEx = pA->GetBitmapEx();
8024665f8d3SArmin Le Grand 
8034665f8d3SArmin Le Grand                     if(rBitmapEx.IsEmpty())
8044665f8d3SArmin Le Grand                     {
8054665f8d3SArmin Le Grand                         // empty content
8064665f8d3SArmin Le Grand                         bDone = true;
8074665f8d3SArmin Le Grand                     }
8084665f8d3SArmin Le Grand                     else
8094665f8d3SArmin Le Grand                     {
8104665f8d3SArmin Le Grand                         BitmapEx aCroppedBitmapEx(rBitmapEx);
8114665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
8124665f8d3SArmin Le Grand 
8134665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
8144665f8d3SArmin Le Grand                         {
8154665f8d3SArmin Le Grand                             // empty content
8164665f8d3SArmin Le Grand                             bDone = true;
8174665f8d3SArmin Le Grand                         }
8184665f8d3SArmin Le Grand                         else
8194665f8d3SArmin Le Grand                         {
8204665f8d3SArmin Le Grand                             aCroppedBitmapEx.Crop(aCropRectangle);
8214665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
8224665f8d3SArmin Le Grand                                 aClips.back(),
8234665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
8244665f8d3SArmin Le Grand                                 pA->GetDestSize(),
8254665f8d3SArmin Le Grand                                 aCroppedBitmapEx,
8264665f8d3SArmin Le Grand                                 aTarget);
8274665f8d3SArmin Le Grand                         }
8284665f8d3SArmin Le Grand                     }
8294665f8d3SArmin Le Grand                     break;
8304665f8d3SArmin Le Grand                 }
8314665f8d3SArmin Le Grand 
8324665f8d3SArmin Le Grand                 case META_BMPSCALEPART_ACTION :
8334665f8d3SArmin Le Grand                 {
8344665f8d3SArmin Le Grand                     const MetaBmpScalePartAction* pA = static_cast< const MetaBmpScalePartAction* >(pAction);
8354665f8d3SArmin Le Grand                     const Bitmap& rBitmap = pA->GetBitmap();
8364665f8d3SArmin Le Grand 
8374665f8d3SArmin Le Grand                     if(rBitmap.IsEmpty())
8384665f8d3SArmin Le Grand                     {
8394665f8d3SArmin Le Grand                         // empty content
8404665f8d3SArmin Le Grand                         bDone = true;
8414665f8d3SArmin Le Grand                     }
8424665f8d3SArmin Le Grand                     else
8434665f8d3SArmin Le Grand                     {
8444665f8d3SArmin Le Grand                         Bitmap aCroppedBitmap(rBitmap);
8454665f8d3SArmin Le Grand                         const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
8464665f8d3SArmin Le Grand 
8474665f8d3SArmin Le Grand                         if(aCropRectangle.IsEmpty())
8484665f8d3SArmin Le Grand                         {
8494665f8d3SArmin Le Grand                             // empty content
8504665f8d3SArmin Le Grand                             bDone = true;
8514665f8d3SArmin Le Grand                         }
8524665f8d3SArmin Le Grand                         else
8534665f8d3SArmin Le Grand                         {
8544665f8d3SArmin Le Grand                             aCroppedBitmap.Crop(aCropRectangle);
8554665f8d3SArmin Le Grand                             bDone = handleBitmapContent(
8564665f8d3SArmin Le Grand                                 aClips.back(),
8574665f8d3SArmin Le Grand                                 pA->GetDestPoint(),
8584665f8d3SArmin Le Grand                                 pA->GetDestSize(),
8594665f8d3SArmin Le Grand                                 BitmapEx(aCroppedBitmap),
8604665f8d3SArmin Le Grand                                 aTarget);
8614665f8d3SArmin Le Grand                         }
8624665f8d3SArmin Le Grand                     }
8634665f8d3SArmin Le Grand                     break;
8644665f8d3SArmin Le Grand                 }
8654665f8d3SArmin Le Grand 
8664665f8d3SArmin Le Grand                 //
8674665f8d3SArmin Le Grand                 // need to handle all those 'hacks' which hide data in comments
8684665f8d3SArmin Le Grand                 //
8694665f8d3SArmin Le Grand                 case META_COMMENT_ACTION :
8704665f8d3SArmin Le Grand                 {
8714665f8d3SArmin Le Grand                     const MetaCommentAction* pA = static_cast< const MetaCommentAction* >(pAction);
8724665f8d3SArmin Le Grand                     const ByteString& rComment = pA->GetComment();
8734665f8d3SArmin Le Grand 
8744665f8d3SArmin Le Grand                     if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XGRAD_SEQ_BEGIN"))
8754665f8d3SArmin Le Grand                     {
8764665f8d3SArmin Le Grand                         // nothing to do; this just means that between here and XGRAD_SEQ_END
877*515f4036SJohn Bampton                         // exists a META_GRADIENTEX_ACTION mixed with Xor-tricked painting
8784665f8d3SArmin Le Grand                         // commands. This comment is used to scan over these and filter for
8794665f8d3SArmin Le Grand                         // the gradient action. It is needed to support META_GRADIENTEX_ACTION
8804665f8d3SArmin Le Grand                         // in this processor to solve usages.
8814665f8d3SArmin Le Grand                     }
8824665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHFILL_SEQ_BEGIN"))
8834665f8d3SArmin Le Grand                     {
8844665f8d3SArmin Le Grand                         SvtGraphicFill aFilling;
8854665f8d3SArmin Le Grand                         PolyPolygon aPath;
8864665f8d3SArmin Le Grand 
8874665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
8884665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
8894665f8d3SArmin Le Grand                             aMemStm >> aFilling;
8904665f8d3SArmin Le Grand                         }
8914665f8d3SArmin Le Grand 
8924665f8d3SArmin Le Grand                         aFilling.getPath(aPath);
8934665f8d3SArmin Le Grand 
8944665f8d3SArmin Le Grand                         if(aPath.Count())
8954665f8d3SArmin Le Grand                         {
8964665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aSource(aPath.getB2DPolyPolygon());
8974665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
8984665f8d3SArmin Le Grand                                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
8994665f8d3SArmin Le Grand                                     aSource,
9004665f8d3SArmin Le Grand                                     aClips.back(),
9014665f8d3SArmin Le Grand                                     true, // inside
9024665f8d3SArmin Le Grand                                     false)); // stroke
9034665f8d3SArmin Le Grand 
9044665f8d3SArmin Le Grand                             if(aResult.count())
9054665f8d3SArmin Le Grand                             {
9064665f8d3SArmin Le Grand                                 if(aResult != aSource)
9074665f8d3SArmin Le Grand                                 {
9084665f8d3SArmin Le Grand                                     // add clipped geometry
9094665f8d3SArmin Le Grand                                     aFilling.setPath(PolyPolygon(aResult));
9104665f8d3SArmin Le Grand                                     addSvtGraphicFill(aFilling, aTarget);
9114665f8d3SArmin Le Grand                                     bDone = true;
9124665f8d3SArmin Le Grand                                 }
9134665f8d3SArmin Le Grand                             }
9144665f8d3SArmin Le Grand                             else
9154665f8d3SArmin Le Grand                             {
9164665f8d3SArmin Le Grand                                 // exchange with empty polygon
9174665f8d3SArmin Le Grand                                 aFilling.setPath(PolyPolygon());
9184665f8d3SArmin Le Grand                                 addSvtGraphicFill(aFilling, aTarget);
9194665f8d3SArmin Le Grand                                 bDone = true;
9204665f8d3SArmin Le Grand                             }
9214665f8d3SArmin Le Grand                         }
9224665f8d3SArmin Le Grand                     }
9234665f8d3SArmin Le Grand                     else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHSTROKE_SEQ_BEGIN"))
9244665f8d3SArmin Le Grand                     {
9254665f8d3SArmin Le Grand                         SvtGraphicStroke aStroke;
9264665f8d3SArmin Le Grand                         Polygon aPath;
9274665f8d3SArmin Le Grand 
9284665f8d3SArmin Le Grand                         {   // read SvtGraphicFill
9294665f8d3SArmin Le Grand                             SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
9304665f8d3SArmin Le Grand                             aMemStm >> aStroke;
9314665f8d3SArmin Le Grand                         }
9324665f8d3SArmin Le Grand 
9334665f8d3SArmin Le Grand                         aStroke.getPath(aPath);
9344665f8d3SArmin Le Grand 
9354665f8d3SArmin Le Grand                         if(aPath.GetSize())
9364665f8d3SArmin Le Grand                         {
9374665f8d3SArmin Le Grand                             const basegfx::B2DPolygon aSource(aPath.getB2DPolygon());
9384665f8d3SArmin Le Grand                             const basegfx::B2DPolyPolygon aResult(
9394665f8d3SArmin Le Grand                                 basegfx::tools::clipPolygonOnPolyPolygon(
9404665f8d3SArmin Le Grand                                     aSource,
9414665f8d3SArmin Le Grand                                     aClips.back(),
9424665f8d3SArmin Le Grand                                     true, // inside
9434665f8d3SArmin Le Grand                                     true)); // stroke
9444665f8d3SArmin Le Grand 
9454665f8d3SArmin Le Grand                             if(aResult.count())
9464665f8d3SArmin Le Grand                             {
9474665f8d3SArmin Le Grand                                 if(aResult.count() > 1 || aResult.getB2DPolygon(0) != aSource)
9484665f8d3SArmin Le Grand                                 {
9494665f8d3SArmin Le Grand                                     // add clipped geometry
9504665f8d3SArmin Le Grand                                     for(sal_uInt32 a(0); a < aResult.count(); a++)
9514665f8d3SArmin Le Grand                                     {
9524665f8d3SArmin Le Grand                                         aStroke.setPath(Polygon(aResult.getB2DPolygon(a)));
9534665f8d3SArmin Le Grand                                         addSvtGraphicStroke(aStroke, aTarget);
9544665f8d3SArmin Le Grand                                     }
9554665f8d3SArmin Le Grand 
9564665f8d3SArmin Le Grand                                     bDone = true;
9574665f8d3SArmin Le Grand                                 }
9584665f8d3SArmin Le Grand                             }
9594665f8d3SArmin Le Grand                             else
9604665f8d3SArmin Le Grand                             {
9614665f8d3SArmin Le Grand                                 // exchange with empty polygon
9624665f8d3SArmin Le Grand                                 aStroke.setPath(Polygon());
9634665f8d3SArmin Le Grand                                 addSvtGraphicStroke(aStroke, aTarget);
9644665f8d3SArmin Le Grand                                 bDone = true;
9654665f8d3SArmin Le Grand                             }
9664665f8d3SArmin Le Grand 
9674665f8d3SArmin Le Grand                         }
9684665f8d3SArmin Le Grand                     }
9694665f8d3SArmin Le Grand                     break;
9704665f8d3SArmin Le Grand                 }
9714665f8d3SArmin Le Grand 
9724665f8d3SArmin Le Grand                 //
9734665f8d3SArmin Le Grand                 // need to handle gradient fills (hopefully only unroated ones)
9744665f8d3SArmin Le Grand                 //
9754665f8d3SArmin Le Grand 
9764665f8d3SArmin Le Grand                 case META_GRADIENT_ACTION :
9774665f8d3SArmin Le Grand                 {
9784665f8d3SArmin Le Grand                     const MetaGradientAction* pA = static_cast< const MetaGradientAction* >(pAction);
9794665f8d3SArmin Le Grand                     const Rectangle& rRect = pA->GetRect();
9804665f8d3SArmin Le Grand 
9814665f8d3SArmin Le Grand                     if(rRect.IsEmpty())
9824665f8d3SArmin Le Grand                     {
9834665f8d3SArmin Le Grand                         bDone = true;
9844665f8d3SArmin Le Grand                     }
9854665f8d3SArmin Le Grand                     else
9864665f8d3SArmin Le Grand                     {
9874665f8d3SArmin Le Grand                         bDone = handleGradientContent(
9884665f8d3SArmin Le Grand                             aClips.back(),
9894665f8d3SArmin Le Grand                             basegfx::B2DPolyPolygon(
9904665f8d3SArmin Le Grand                                 basegfx::tools::createPolygonFromRect(
9914665f8d3SArmin Le Grand                                     basegfx::B2DRange(
9924665f8d3SArmin Le Grand                                         rRect.Left(), rRect.Top(),
9934665f8d3SArmin Le Grand                                         rRect.Right(), rRect.Bottom()))),
9944665f8d3SArmin Le Grand                             pA->GetGradient(),
9954665f8d3SArmin Le Grand                             aTarget);
9964665f8d3SArmin Le Grand                     }
9974665f8d3SArmin Le Grand 
9984665f8d3SArmin Le Grand 
9994665f8d3SArmin Le Grand                     break;
10004665f8d3SArmin Le Grand                 }
10014665f8d3SArmin Le Grand 
10024665f8d3SArmin Le Grand                 case META_GRADIENTEX_ACTION :
10034665f8d3SArmin Le Grand                 {
10044665f8d3SArmin Le Grand                     const MetaGradientExAction* pA = static_cast< const MetaGradientExAction* >(pAction);
10054665f8d3SArmin Le Grand                     const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
10064665f8d3SArmin Le Grand 
10074665f8d3SArmin Le Grand                     bDone = handleGradientContent(
10084665f8d3SArmin Le Grand                         aClips.back(),
10094665f8d3SArmin Le Grand                         rPolyPoly.getB2DPolyPolygon(),
10104665f8d3SArmin Le Grand                         pA->GetGradient(),
10114665f8d3SArmin Le Grand                         aTarget);
10124665f8d3SArmin Le Grand                     break;
10134665f8d3SArmin Le Grand                 }
10144665f8d3SArmin Le Grand 
10154665f8d3SArmin Le Grand                 // not (yet) supported actions
10164665f8d3SArmin Le Grand                 //
10174665f8d3SArmin Le Grand                 // META_NULL_ACTION
10184665f8d3SArmin Le Grand                 // META_TEXT_ACTION
10194665f8d3SArmin Le Grand                 // META_TEXTARRAY_ACTION
10204665f8d3SArmin Le Grand                 // META_STRETCHTEXT_ACTION
10214665f8d3SArmin Le Grand                 // META_TEXTRECT_ACTION
10224665f8d3SArmin Le Grand                 // META_MASK_ACTION
10234665f8d3SArmin Le Grand                 // META_MASKSCALE_ACTION
10244665f8d3SArmin Le Grand                 // META_MASKSCALEPART_ACTION
10254665f8d3SArmin Le Grand                 // META_HATCH_ACTION
10264665f8d3SArmin Le Grand                 // META_WALLPAPER_ACTION
10274665f8d3SArmin Le Grand                 // META_FILLCOLOR_ACTION
10284665f8d3SArmin Le Grand                 // META_TEXTCOLOR_ACTION
10294665f8d3SArmin Le Grand                 // META_TEXTFILLCOLOR_ACTION
10304665f8d3SArmin Le Grand                 // META_TEXTALIGN_ACTION
10314665f8d3SArmin Le Grand                 // META_MAPMODE_ACTION
10324665f8d3SArmin Le Grand                 // META_FONT_ACTION
10334665f8d3SArmin Le Grand                 // META_TRANSPARENT_ACTION
10344665f8d3SArmin Le Grand                 // META_EPS_ACTION
10354665f8d3SArmin Le Grand                 // META_REFPOINT_ACTION
10364665f8d3SArmin Le Grand                 // META_TEXTLINECOLOR_ACTION
10374665f8d3SArmin Le Grand                 // META_TEXTLINE_ACTION
10384665f8d3SArmin Le Grand                 // META_FLOATTRANSPARENT_ACTION
10394665f8d3SArmin Le Grand                 // META_LAYOUTMODE_ACTION
10404665f8d3SArmin Le Grand                 // META_TEXTLANGUAGE_ACTION
10414665f8d3SArmin Le Grand                 // META_OVERLINECOLOR_ACTION
10424665f8d3SArmin Le Grand 
10434665f8d3SArmin Le Grand                 // if an action is not handled at all, it will simply get copied to the
10444665f8d3SArmin Le Grand                 // target (see below). This is the default for all non-implemented actions
10454665f8d3SArmin Le Grand                 default:
10464665f8d3SArmin Le Grand                 {
10474665f8d3SArmin Le Grand                     break;
10484665f8d3SArmin Le Grand                 }
10494665f8d3SArmin Le Grand             }
10504665f8d3SArmin Le Grand         }
10514665f8d3SArmin Le Grand 
10524665f8d3SArmin Le Grand         if(bDone)
10534665f8d3SArmin Le Grand         {
10544665f8d3SArmin Le Grand             bChanged = true;
10554665f8d3SArmin Le Grand         }
10564665f8d3SArmin Le Grand         else
10574665f8d3SArmin Le Grand         {
10584665f8d3SArmin Le Grand             const_cast< MetaAction* >(pAction)->Duplicate();
10594665f8d3SArmin Le Grand             aTarget.AddAction(const_cast< MetaAction* >(pAction));
10604665f8d3SArmin Le Grand         }
10614665f8d3SArmin Le Grand     }
10624665f8d3SArmin Le Grand 
10634665f8d3SArmin Le Grand     if(bChanged)
10644665f8d3SArmin Le Grand     {
10654665f8d3SArmin Le Grand         // when changed, copy back and do not forget to set MapMode
10664665f8d3SArmin Le Grand         // and PrefSize
10674665f8d3SArmin Le Grand         aTarget.SetPrefMapMode(rSource.GetPrefMapMode());
10684665f8d3SArmin Le Grand         aTarget.SetPrefSize(rSource.GetPrefSize());
10694665f8d3SArmin Le Grand         rSource = aTarget;
10704665f8d3SArmin Le Grand     }
10714665f8d3SArmin Le Grand }
10724665f8d3SArmin Le Grand 
10734665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
10744665f8d3SArmin Le Grand 
usesClipActions(const GDIMetaFile & rSource)10754665f8d3SArmin Le Grand bool VCL_DLLPUBLIC usesClipActions(const GDIMetaFile& rSource)
10764665f8d3SArmin Le Grand {
10774665f8d3SArmin Le Grand     const sal_uLong nObjCount(rSource.GetActionCount());
10784665f8d3SArmin Le Grand 
10794665f8d3SArmin Le Grand     for(sal_uLong i(0); i < nObjCount; ++i)
10804665f8d3SArmin Le Grand     {
10814665f8d3SArmin Le Grand         const MetaAction* pAction(rSource.GetAction(i));
10824665f8d3SArmin Le Grand         const sal_uInt16 nType(pAction->GetType());
10834665f8d3SArmin Le Grand 
10844665f8d3SArmin Le Grand         switch(nType)
10854665f8d3SArmin Le Grand         {
10864665f8d3SArmin Le Grand             case META_CLIPREGION_ACTION :
10874665f8d3SArmin Le Grand             case META_ISECTRECTCLIPREGION_ACTION :
10884665f8d3SArmin Le Grand             case META_ISECTREGIONCLIPREGION_ACTION :
10894665f8d3SArmin Le Grand             case META_MOVECLIPREGION_ACTION :
10904665f8d3SArmin Le Grand             {
10914665f8d3SArmin Le Grand                 return true;
10924665f8d3SArmin Le Grand                 break;
10934665f8d3SArmin Le Grand             }
10944665f8d3SArmin Le Grand 
10954665f8d3SArmin Le Grand             default: break;
10964665f8d3SArmin Le Grand         }
10974665f8d3SArmin Le Grand     }
10984665f8d3SArmin Le Grand 
10994665f8d3SArmin Le Grand     return false;
11004665f8d3SArmin Le Grand }
11014665f8d3SArmin Le Grand 
11024665f8d3SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
11034665f8d3SArmin Le Grand // eof
1104