1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/gdimetafiletools.hxx>
21 #include <vcl/metaact.hxx>
22 #include <vcl/canvastools.hxx>
23 #include <basegfx/polygon/b2dpolygonclipper.hxx>
24 #include <basegfx/matrix/b2dhommatrixtools.hxx>
25 #include <basegfx/polygon/b2dpolypolygontools.hxx>
26 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <vcl/virdev.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/graphictools.hxx>
30 #include <osl/diagnose.h>
31 #include <tools/stream.hxx>
37 bool handleGeometricContent(
38 const basegfx::B2DPolyPolygon
& rClip
,
39 const basegfx::B2DPolyPolygon
& rSource
,
43 if(rSource
.count() && rClip
.count())
45 const basegfx::B2DPolyPolygon
aResult(
46 basegfx::utils::clipPolyPolygonOnPolyPolygon(
54 if(aResult
== rSource
)
56 // not clipped, but inside. Add original
61 // add clipped geometry
64 for(auto const& rB2DPolygon
: aResult
)
67 new MetaPolyLineAction(
68 tools::Polygon(rB2DPolygon
)));
74 new MetaPolyPolygonAction(
75 tools::PolyPolygon(aResult
)));
84 bool handleGradientContent(
85 const basegfx::B2DPolyPolygon
& rClip
,
86 const basegfx::B2DPolyPolygon
& rSource
,
87 const Gradient
& rGradient
,
90 if(rSource
.count() && rClip
.count())
92 const basegfx::B2DPolyPolygon
aResult(
93 basegfx::utils::clipPolyPolygonOnPolyPolygon(
101 if(aResult
== rSource
)
103 // not clipped, but inside. Add original
108 // add clipped geometry
110 new MetaGradientExAction(
111 tools::PolyPolygon(aResult
),
120 bool handleBitmapContent(
121 const basegfx::B2DPolyPolygon
& rClip
,
124 const BitmapEx
& rBitmapEx
,
125 GDIMetaFile
& rTarget
)
127 if(!rSize
.Width() || !rSize
.Height() || rBitmapEx
.IsEmpty())
129 // bitmap or size is empty
133 const basegfx::B2DRange
aLogicBitmapRange(
134 rPoint
.X(), rPoint
.Y(),
135 rPoint
.X() + rSize
.Width(), rPoint
.Y() + rSize
.Height());
136 const basegfx::B2DPolyPolygon
aClipOfBitmap(
137 basegfx::utils::clipPolyPolygonOnRange(
143 if(!aClipOfBitmap
.count())
145 // outside clip region
149 // inside or overlapping. Use area to find out if it is completely
150 // covering (inside) or overlapping
151 const double fClipArea(basegfx::utils::getArea(aClipOfBitmap
));
152 const double fBitmapArea(
153 aLogicBitmapRange
.getWidth() * aLogicBitmapRange
.getWidth() +
154 aLogicBitmapRange
.getHeight() * aLogicBitmapRange
.getHeight());
155 const double fFactor(fClipArea
/ fBitmapArea
);
157 if(basegfx::fTools::more(fFactor
, 1.0 - 0.001))
159 // completely covering (with 0.1% tolerance)
163 // needs clipping (with 0.1% tolerance). Prepare VirtualDevice
164 // in pixel mode for alpha channel painting (black is transparent,
165 // white to paint 100% opacity)
166 const Size
aSizePixel(rBitmapEx
.GetSizePixel());
167 ScopedVclPtrInstance
< VirtualDevice
> aVDev
;
169 aVDev
->SetOutputSizePixel(aSizePixel
);
170 aVDev
->EnableMapMode(false);
171 aVDev
->SetFillColor( COL_WHITE
);
172 aVDev
->SetLineColor();
174 if(rBitmapEx
.IsTransparent())
176 // use given alpha channel
177 aVDev
->DrawBitmap(Point(0, 0), rBitmapEx
.GetAlpha().GetBitmap());
181 // reset alpha channel
182 aVDev
->SetBackground(Wallpaper(COL_BLACK
));
186 // transform polygon from clipping to pixel coordinates
187 basegfx::B2DPolyPolygon
aPixelPoly(aClipOfBitmap
);
188 basegfx::B2DHomMatrix aTransform
;
190 aTransform
.translate(-aLogicBitmapRange
.getMinX(), -aLogicBitmapRange
.getMinY());
192 static_cast< double >(aSizePixel
.Width()) / aLogicBitmapRange
.getWidth(),
193 static_cast< double >(aSizePixel
.Height()) / aLogicBitmapRange
.getHeight());
194 aPixelPoly
.transform(aTransform
);
196 // to fill the non-covered parts, use the Xor fill rule of
197 // tools::PolyPolygon painting. Start with an all-covering polygon and
198 // add the clip polygon one
199 basegfx::B2DPolyPolygon aInvertPixelPoly
;
201 aInvertPixelPoly
.append(
202 basegfx::utils::createPolygonFromRect(
205 aSizePixel
.Width(), aSizePixel
.Height())));
206 aInvertPixelPoly
.append(aPixelPoly
);
209 aVDev
->DrawPolyPolygon(aInvertPixelPoly
);
211 // get created alpha mask and set defaults
217 aAlpha
.SetPrefSize(rBitmapEx
.GetPrefSize());
218 aAlpha
.SetPrefMapMode(rBitmapEx
.GetPrefMapMode());
220 // add new action replacing the old one
222 new MetaBmpExScaleAction(
224 basegfx::fround(aLogicBitmapRange
.getMinX()),
225 basegfx::fround(aLogicBitmapRange
.getMinY())),
227 basegfx::fround(aLogicBitmapRange
.getWidth()),
228 basegfx::fround(aLogicBitmapRange
.getHeight())),
229 BitmapEx(rBitmapEx
.GetBitmap(), aAlpha
)));
234 void addSvtGraphicStroke(const SvtGraphicStroke
& rStroke
, GDIMetaFile
& rTarget
)
236 // write SvtGraphicFill
237 SvMemoryStream aMemStm
;
238 WriteSvtGraphicStroke( aMemStm
, rStroke
);
240 new MetaCommentAction(
241 "XPATHSTROKE_SEQ_BEGIN",
243 static_cast< const sal_uInt8
* >(aMemStm
.GetData()),
247 void addSvtGraphicFill(const SvtGraphicFill
&rFilling
, GDIMetaFile
& rTarget
)
249 // write SvtGraphicFill
250 SvMemoryStream aMemStm
;
251 WriteSvtGraphicFill( aMemStm
, rFilling
);
253 new MetaCommentAction(
254 "XPATHFILL_SEQ_BEGIN",
256 static_cast< const sal_uInt8
* >(aMemStm
.GetData()),
259 } // end of anonymous namespace
261 // #i121267# Tooling to internally clip geometry against internal clip regions
263 void clipMetafileContentAgainstOwnRegions(GDIMetaFile
& rSource
)
265 const sal_uLong
nObjCount(rSource
.GetActionSize());
272 // prepare target data container and push/pop stack data
274 bool bChanged(false);
275 std::vector
< basegfx::B2DPolyPolygon
> aClips
;
276 std::vector
< PushFlags
> aPushFlags
;
277 std::vector
< MapMode
> aMapModes
;
279 // start with empty region
280 aClips
.emplace_back();
282 // start with default MapMode (MapUnit::MapPixel)
283 aMapModes
.emplace_back();
285 for(sal_uLong
i(0); i
< nObjCount
; ++i
)
287 const MetaAction
* pAction(rSource
.GetAction(i
));
288 const MetaActionType
nType(pAction
->GetType());
291 // basic operation takes care of clipregion actions (four) and push/pop of these
292 // to steer the currently set clip region. There *is* an active
293 // clip region when (aClips.size() && aClips.back().count()), see
297 case MetaActionType::CLIPREGION
:
299 const MetaClipRegionAction
* pA
= static_cast< const MetaClipRegionAction
* >(pAction
);
303 const vcl::Region
& rRegion
= pA
->GetRegion();
304 const basegfx::B2DPolyPolygon
aNewClip(rRegion
.GetAsB2DPolyPolygon());
306 aClips
.back() = aNewClip
;
310 aClips
.back() = basegfx::B2DPolyPolygon();
316 case MetaActionType::ISECTRECTCLIPREGION
:
318 const MetaISectRectClipRegionAction
* pA
= static_cast< const MetaISectRectClipRegionAction
* >(pAction
);
319 const tools::Rectangle
& rRect
= pA
->GetRect();
321 if(!rRect
.IsEmpty() && !aClips
.empty() && aClips
.back().count())
323 const basegfx::B2DRange
aClipRange(vcl::unotools::b2DRectangleFromRectangle(rRect
));
325 aClips
.back() = basegfx::utils::clipPolyPolygonOnRange(
334 case MetaActionType::ISECTREGIONCLIPREGION
:
336 const MetaISectRegionClipRegionAction
* pA
= static_cast< const MetaISectRegionClipRegionAction
* >(pAction
);
337 const vcl::Region
& rRegion
= pA
->GetRegion();
339 if(!rRegion
.IsEmpty() && !aClips
.empty() && aClips
.back().count())
341 const basegfx::B2DPolyPolygon
aNewClip(rRegion
.GetAsB2DPolyPolygon());
343 aClips
.back() = basegfx::utils::clipPolyPolygonOnPolyPolygon(
352 case MetaActionType::MOVECLIPREGION
:
354 const MetaMoveClipRegionAction
* pA
= static_cast< const MetaMoveClipRegionAction
* >(pAction
);
355 const long aHorMove(pA
->GetHorzMove());
356 const long aVerMove(pA
->GetVertMove());
358 if((aHorMove
|| aVerMove
) && !aClips
.empty() && aClips
.back().count())
360 aClips
.back().transform(
361 basegfx::utils::createTranslateB2DHomMatrix(
368 case MetaActionType::PUSH
:
370 const MetaPushAction
* pA
= static_cast< const MetaPushAction
* >(pAction
);
371 const PushFlags
nFlags(pA
->GetFlags());
373 aPushFlags
.push_back(nFlags
);
375 if(nFlags
& PushFlags::CLIPREGION
)
377 aClips
.push_back(aClips
.back());
380 if(nFlags
& PushFlags::MAPMODE
)
382 aMapModes
.push_back(aMapModes
.back());
387 case MetaActionType::POP
:
390 if(!aPushFlags
.empty())
392 const PushFlags
nFlags(aPushFlags
.back());
393 aPushFlags
.pop_back();
395 if(nFlags
& PushFlags::CLIPREGION
)
397 if(aClips
.size() > 1)
403 OSL_ENSURE(false, "Wrong POP() in ClipRegions (!)");
407 if(nFlags
& PushFlags::MAPMODE
)
409 if(aMapModes
.size() > 1)
411 aMapModes
.pop_back();
415 OSL_ENSURE(false, "Wrong POP() in MapModes (!)");
421 OSL_ENSURE(false, "Invalid pop() without push() (!)");
427 case MetaActionType::MAPMODE
:
429 const MetaMapModeAction
* pA
= static_cast< const MetaMapModeAction
* >(pAction
);
431 aMapModes
.back() = pA
->GetMapMode();
441 // this area contains all actions which could potentially be clipped. Since
442 // this tooling is only a fallback (see comments in header), only the needed
443 // actions will be implemented. Extend using the pattern for the already
444 // implemented actions.
445 if(!aClips
.empty() && aClips
.back().count())
450 // pixel actions, just check on inside
452 case MetaActionType::PIXEL
:
454 const MetaPixelAction
* pA
= static_cast< const MetaPixelAction
* >(pAction
);
455 const Point
& rPoint
= pA
->GetPoint();
457 if(!basegfx::utils::isInside(
459 basegfx::B2DPoint(rPoint
.X(), rPoint
.Y())))
461 // when not inside, do not add original
467 case MetaActionType::POINT
:
469 const MetaPointAction
* pA
= static_cast< const MetaPointAction
* >(pAction
);
470 const Point
& rPoint
= pA
->GetPoint();
472 if(!basegfx::utils::isInside(
474 basegfx::B2DPoint(rPoint
.X(), rPoint
.Y())))
476 // when not inside, do not add original
484 case MetaActionType::LINE
:
486 const MetaLineAction
* pA
= static_cast< const MetaLineAction
* >(pAction
);
487 const Point
& rStart(pA
->GetStartPoint());
488 const Point
& rEnd(pA
->GetEndPoint());
489 basegfx::B2DPolygon aLine
;
491 aLine
.append(basegfx::B2DPoint(rStart
.X(), rStart
.Y()));
492 aLine
.append(basegfx::B2DPoint(rEnd
.X(), rEnd
.Y()));
494 bDone
= handleGeometricContent(
496 basegfx::B2DPolyPolygon(aLine
),
502 case MetaActionType::RECT
:
504 const MetaRectAction
* pA
= static_cast< const MetaRectAction
* >(pAction
);
505 const tools::Rectangle
& rRect
= pA
->GetRect();
514 bDone
= handleGeometricContent(
516 basegfx::B2DPolyPolygon(
517 basegfx::utils::createPolygonFromRect(
518 vcl::unotools::b2DRectangleFromRectangle(rRect
))),
525 case MetaActionType::ROUNDRECT
:
527 const MetaRoundRectAction
* pA
= static_cast< const MetaRoundRectAction
* >(pAction
);
528 const tools::Rectangle
& rRect
= pA
->GetRect();
536 const sal_uInt32
nHor(pA
->GetHorzRound());
537 const sal_uInt32
nVer(pA
->GetVertRound());
538 const basegfx::B2DRange
aRange(vcl::unotools::b2DRectangleFromRectangle(rRect
));
539 basegfx::B2DPolygon aOutline
;
543 double fRadiusX((nHor
* 2.0) / (aRange
.getWidth() > 0.0 ? aRange
.getWidth() : 1.0));
544 double fRadiusY((nVer
* 2.0) / (aRange
.getHeight() > 0.0 ? aRange
.getHeight() : 1.0));
545 fRadiusX
= std::max(0.0, std::min(1.0, fRadiusX
));
546 fRadiusY
= std::max(0.0, std::min(1.0, fRadiusY
));
548 aOutline
= basegfx::utils::createPolygonFromRect(aRange
, fRadiusX
, fRadiusY
);
552 aOutline
= basegfx::utils::createPolygonFromRect(aRange
);
555 bDone
= handleGeometricContent(
557 basegfx::B2DPolyPolygon(aOutline
),
564 case MetaActionType::ELLIPSE
:
566 const MetaEllipseAction
* pA
= static_cast< const MetaEllipseAction
* >(pAction
);
567 const tools::Rectangle
& rRect
= pA
->GetRect();
575 const basegfx::B2DRange
aRange(vcl::unotools::b2DRectangleFromRectangle(rRect
));
577 bDone
= handleGeometricContent(
579 basegfx::B2DPolyPolygon(
580 basegfx::utils::createPolygonFromEllipse(
582 aRange
.getWidth() * 0.5,
583 aRange
.getHeight() * 0.5)),
590 case MetaActionType::ARC
:
592 const MetaArcAction
* pA
= static_cast< const MetaArcAction
* >(pAction
);
593 const tools::Rectangle
& rRect
= pA
->GetRect();
601 const tools::Polygon
aToolsPoly(
607 bDone
= handleGeometricContent(
609 basegfx::B2DPolyPolygon(aToolsPoly
.getB2DPolygon()),
616 case MetaActionType::PIE
:
618 const MetaPieAction
* pA
= static_cast< const MetaPieAction
* >(pAction
);
619 const tools::Rectangle
& rRect
= pA
->GetRect();
627 const tools::Polygon
aToolsPoly(
633 bDone
= handleGeometricContent(
635 basegfx::B2DPolyPolygon(aToolsPoly
.getB2DPolygon()),
642 case MetaActionType::CHORD
:
644 const MetaChordAction
* pA
= static_cast< const MetaChordAction
* >(pAction
);
645 const tools::Rectangle
& rRect
= pA
->GetRect();
653 const tools::Polygon
aToolsPoly(
659 bDone
= handleGeometricContent(
661 basegfx::B2DPolyPolygon(aToolsPoly
.getB2DPolygon()),
668 case MetaActionType::POLYLINE
:
670 const MetaPolyLineAction
* pA
= static_cast< const MetaPolyLineAction
* >(pAction
);
672 bDone
= handleGeometricContent(
674 basegfx::B2DPolyPolygon(pA
->GetPolygon().getB2DPolygon()),
680 case MetaActionType::POLYGON
:
682 const MetaPolygonAction
* pA
= static_cast< const MetaPolygonAction
* >(pAction
);
684 bDone
= handleGeometricContent(
686 basegfx::B2DPolyPolygon(pA
->GetPolygon().getB2DPolygon()),
692 case MetaActionType::POLYPOLYGON
:
694 const MetaPolyPolygonAction
* pA
= static_cast< const MetaPolyPolygonAction
* >(pAction
);
695 const tools::PolyPolygon
& rPoly
= pA
->GetPolyPolygon();
697 bDone
= handleGeometricContent(
699 rPoly
.getB2DPolyPolygon(),
705 // bitmap actions, create BitmapEx with alpha channel derived
708 case MetaActionType::BMPEX
:
710 const MetaBmpExAction
* pA
= static_cast< const MetaBmpExAction
* >(pAction
);
711 const BitmapEx
& rBitmapEx
= pA
->GetBitmapEx();
713 // the logical size depends on the PrefSize of the given bitmap in
714 // combination with the current MapMode
715 Size
aLogicalSize(rBitmapEx
.GetPrefSize());
717 if(MapUnit::MapPixel
== rBitmapEx
.GetPrefMapMode().GetMapUnit())
719 aLogicalSize
= Application::GetDefaultDevice()->PixelToLogic(aLogicalSize
, aMapModes
.back());
723 aLogicalSize
= OutputDevice::LogicToLogic(aLogicalSize
, rBitmapEx
.GetPrefMapMode(), aMapModes
.back());
726 bDone
= handleBitmapContent(
735 case MetaActionType::BMP
:
737 const MetaBmpAction
* pA
= static_cast< const MetaBmpAction
* >(pAction
);
738 const Bitmap
& rBitmap
= pA
->GetBitmap();
740 // the logical size depends on the PrefSize of the given bitmap in
741 // combination with the current MapMode
742 Size
aLogicalSize(rBitmap
.GetPrefSize());
744 if(MapUnit::MapPixel
== rBitmap
.GetPrefMapMode().GetMapUnit())
746 aLogicalSize
= Application::GetDefaultDevice()->PixelToLogic(aLogicalSize
, aMapModes
.back());
750 aLogicalSize
= OutputDevice::LogicToLogic(aLogicalSize
, rBitmap
.GetPrefMapMode(), aMapModes
.back());
753 bDone
= handleBitmapContent(
762 case MetaActionType::BMPEXSCALE
:
764 const MetaBmpExScaleAction
* pA
= static_cast< const MetaBmpExScaleAction
* >(pAction
);
766 bDone
= handleBitmapContent(
775 case MetaActionType::BMPSCALE
:
777 const MetaBmpScaleAction
* pA
= static_cast< const MetaBmpScaleAction
* >(pAction
);
779 bDone
= handleBitmapContent(
783 BitmapEx(pA
->GetBitmap()),
788 case MetaActionType::BMPEXSCALEPART
:
790 const MetaBmpExScalePartAction
* pA
= static_cast< const MetaBmpExScalePartAction
* >(pAction
);
791 const BitmapEx
& rBitmapEx
= pA
->GetBitmapEx();
793 if(rBitmapEx
.IsEmpty())
800 BitmapEx
aCroppedBitmapEx(rBitmapEx
);
801 const tools::Rectangle
aCropRectangle(pA
->GetSrcPoint(), pA
->GetSrcSize());
803 if(aCropRectangle
.IsEmpty())
810 aCroppedBitmapEx
.Crop(aCropRectangle
);
811 bDone
= handleBitmapContent(
822 case MetaActionType::BMPSCALEPART
:
824 const MetaBmpScalePartAction
* pA
= static_cast< const MetaBmpScalePartAction
* >(pAction
);
825 const Bitmap
& rBitmap
= pA
->GetBitmap();
827 if(rBitmap
.IsEmpty())
834 Bitmap
aCroppedBitmap(rBitmap
);
835 const tools::Rectangle
aCropRectangle(pA
->GetSrcPoint(), pA
->GetSrcSize());
837 if(aCropRectangle
.IsEmpty())
844 aCroppedBitmap
.Crop(aCropRectangle
);
845 bDone
= handleBitmapContent(
849 BitmapEx(aCroppedBitmap
),
856 // need to handle all those 'hacks' which hide data in comments
858 case MetaActionType::COMMENT
:
860 const MetaCommentAction
* pA
= static_cast< const MetaCommentAction
* >(pAction
);
861 const OString
& rComment
= pA
->GetComment();
863 if(rComment
.equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
865 // nothing to do; this just means that between here and XGRAD_SEQ_END
866 // exists a MetaActionType::GRADIENTEX mixed with Xor-tricked painting
867 // commands. This comment is used to scan over these and filter for
868 // the gradient action. It is needed to support MetaActionType::GRADIENTEX
869 // in this processor to solve usages.
871 else if(rComment
.equalsIgnoreAsciiCase("XPATHFILL_SEQ_BEGIN"))
873 SvtGraphicFill aFilling
;
874 tools::PolyPolygon aPath
;
876 { // read SvtGraphicFill
877 SvMemoryStream
aMemStm(const_cast<sal_uInt8
*>(pA
->GetData()), pA
->GetDataSize(),StreamMode::READ
);
878 ReadSvtGraphicFill( aMemStm
, aFilling
);
881 aFilling
.getPath(aPath
);
885 const basegfx::B2DPolyPolygon
aSource(aPath
.getB2DPolyPolygon());
886 const basegfx::B2DPolyPolygon
aResult(
887 basegfx::utils::clipPolyPolygonOnPolyPolygon(
895 if(aResult
!= aSource
)
897 // add clipped geometry
898 aFilling
.setPath(tools::PolyPolygon(aResult
));
899 addSvtGraphicFill(aFilling
, aTarget
);
905 // exchange with empty polygon
906 aFilling
.setPath(tools::PolyPolygon());
907 addSvtGraphicFill(aFilling
, aTarget
);
912 else if(rComment
.equalsIgnoreAsciiCase("XPATHSTROKE_SEQ_BEGIN"))
914 SvtGraphicStroke aStroke
;
915 tools::Polygon aPath
;
917 { // read SvtGraphicFill
918 SvMemoryStream
aMemStm(const_cast<sal_uInt8
*>(pA
->GetData()), pA
->GetDataSize(),StreamMode::READ
);
919 ReadSvtGraphicStroke( aMemStm
, aStroke
);
922 aStroke
.getPath(aPath
);
926 const basegfx::B2DPolygon
aSource(aPath
.getB2DPolygon());
927 const basegfx::B2DPolyPolygon
aResult(
928 basegfx::utils::clipPolygonOnPolyPolygon(
936 if(aResult
.count() > 1 || aResult
.getB2DPolygon(0) != aSource
)
938 // add clipped geometry
939 for(auto const& rB2DPolygon
: aResult
)
941 aStroke
.setPath(tools::Polygon(rB2DPolygon
));
942 addSvtGraphicStroke(aStroke
, aTarget
);
950 // exchange with empty polygon
951 aStroke
.setPath(tools::Polygon());
952 addSvtGraphicStroke(aStroke
, aTarget
);
961 // need to handle gradient fills (hopefully only unrotated ones)
963 case MetaActionType::GRADIENT
:
965 const MetaGradientAction
* pA
= static_cast< const MetaGradientAction
* >(pAction
);
966 const tools::Rectangle
& rRect
= pA
->GetRect();
974 bDone
= handleGradientContent(
976 basegfx::B2DPolyPolygon(
977 basegfx::utils::createPolygonFromRect(
978 vcl::unotools::b2DRectangleFromRectangle(rRect
))),
986 case MetaActionType::GRADIENTEX
:
988 const MetaGradientExAction
* pA
= static_cast< const MetaGradientExAction
* >(pAction
);
989 const tools::PolyPolygon
& rPolyPoly
= pA
->GetPolyPolygon();
991 bDone
= handleGradientContent(
993 rPolyPoly
.getB2DPolyPolygon(),
999 // not (yet) supported actions
1001 // MetaActionType::NONE
1002 // MetaActionType::TEXT
1003 // MetaActionType::TEXTARRAY
1004 // MetaActionType::STRETCHTEXT
1005 // MetaActionType::TEXTRECT
1006 // MetaActionType::MASK
1007 // MetaActionType::MASKSCALE
1008 // MetaActionType::MASKSCALEPART
1009 // MetaActionType::HATCH
1010 // MetaActionType::WALLPAPER
1011 // MetaActionType::FILLCOLOR
1012 // MetaActionType::TEXTCOLOR
1013 // MetaActionType::TEXTFILLCOLOR
1014 // MetaActionType::TEXTALIGN
1015 // MetaActionType::MAPMODE
1016 // MetaActionType::FONT
1017 // MetaActionType::Transparent
1018 // MetaActionType::EPS
1019 // MetaActionType::REFPOINT
1020 // MetaActionType::TEXTLINECOLOR
1021 // MetaActionType::TEXTLINE
1022 // MetaActionType::FLOATTRANSPARENT
1023 // MetaActionType::LAYOUTMODE
1024 // MetaActionType::TEXTLANGUAGE
1025 // MetaActionType::OVERLINECOLOR
1027 // if an action is not handled at all, it will simply get copied to the
1028 // target (see below). This is the default for all non-implemented actions
1042 aTarget
.AddAction(const_cast< MetaAction
* >(pAction
));
1048 // when changed, copy back and do not forget to set MapMode
1050 aTarget
.SetPrefMapMode(rSource
.GetPrefMapMode());
1051 aTarget
.SetPrefSize(rSource
.GetPrefSize());
1056 bool usesClipActions(const GDIMetaFile
& rSource
)
1058 const sal_uLong
nObjCount(rSource
.GetActionSize());
1060 for(sal_uLong
i(0); i
< nObjCount
; ++i
)
1062 const MetaAction
* pAction(rSource
.GetAction(i
));
1063 const MetaActionType
nType(pAction
->GetType());
1067 case MetaActionType::CLIPREGION
:
1068 case MetaActionType::ISECTRECTCLIPREGION
:
1069 case MetaActionType::ISECTREGIONCLIPREGION
:
1070 case MetaActionType::MOVECLIPREGION
:
1082 MetafileAccessor::~MetafileAccessor()
1086 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */