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