1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_svx.hxx"
26*b1cdbd2cSJim Jagielski #include <svx/sdr/overlay/overlayselection.hxx>
27*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygontools.hxx>
28*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygon.hxx>
29*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
30*b1cdbd2cSJim Jagielski #include <svtools/optionsdrawinglayer.hxx>
31*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
32*b1cdbd2cSJim Jagielski #include <vcl/outdev.hxx>
33*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/invertprimitive2d.hxx>
34*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
35*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
36*b1cdbd2cSJim Jagielski #include <svx/sdr/overlay/overlaymanager.hxx>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski namespace sdr
41*b1cdbd2cSJim Jagielski {
42*b1cdbd2cSJim Jagielski 	namespace overlay
43*b1cdbd2cSJim Jagielski 	{
44*b1cdbd2cSJim Jagielski         // combine rages geometrically to a single, ORed polygon
impCombineRangesToPolyPolygon(const std::vector<basegfx::B2DRange> & rRanges)45*b1cdbd2cSJim Jagielski 		basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRanges)
46*b1cdbd2cSJim Jagielski 		{
47*b1cdbd2cSJim Jagielski             const sal_uInt32 nCount(rRanges.size());
48*b1cdbd2cSJim Jagielski 			basegfx::B2DPolyPolygon aRetval;
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski 			for(sal_uInt32 a(0); a < nCount; a++)
51*b1cdbd2cSJim Jagielski             {
52*b1cdbd2cSJim Jagielski 				const basegfx::B2DPolygon aDiscretePolygon(basegfx::tools::createPolygonFromRect(rRanges[a]));
53*b1cdbd2cSJim Jagielski 
54*b1cdbd2cSJim Jagielski 				if(0 == a)
55*b1cdbd2cSJim Jagielski 				{
56*b1cdbd2cSJim Jagielski 					aRetval.append(aDiscretePolygon);
57*b1cdbd2cSJim Jagielski 				}
58*b1cdbd2cSJim Jagielski 				else
59*b1cdbd2cSJim Jagielski 				{
60*b1cdbd2cSJim Jagielski 					aRetval = basegfx::tools::solvePolygonOperationOr(aRetval, basegfx::B2DPolyPolygon(aDiscretePolygon));
61*b1cdbd2cSJim Jagielski 				}
62*b1cdbd2cSJim Jagielski 			}
63*b1cdbd2cSJim Jagielski 
64*b1cdbd2cSJim Jagielski 			return aRetval;
65*b1cdbd2cSJim Jagielski 		}
66*b1cdbd2cSJim Jagielski 
67*b1cdbd2cSJim Jagielski 		// check if wanted type OVERLAY_TRANSPARENT or OVERLAY_SOLID
68*b1cdbd2cSJim Jagielski 		// is possible. If not, fallback to invert mode (classic mode)
impCheckPossibleOverlayType(OverlayType aOverlayType)69*b1cdbd2cSJim Jagielski     	OverlayType impCheckPossibleOverlayType(OverlayType aOverlayType)
70*b1cdbd2cSJim Jagielski         {
71*b1cdbd2cSJim Jagielski 			if(OVERLAY_INVERT != aOverlayType)
72*b1cdbd2cSJim Jagielski 			{
73*b1cdbd2cSJim Jagielski 				const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
74*b1cdbd2cSJim Jagielski 
75*b1cdbd2cSJim Jagielski 				if(!aSvtOptionsDrawinglayer.IsTransparentSelection())
76*b1cdbd2cSJim Jagielski 				{
77*b1cdbd2cSJim Jagielski 					// not possible when switched off by user
78*b1cdbd2cSJim Jagielski 					return OVERLAY_INVERT;
79*b1cdbd2cSJim Jagielski 				}
80*b1cdbd2cSJim Jagielski 				else
81*b1cdbd2cSJim Jagielski 				{
82*b1cdbd2cSJim Jagielski 					const OutputDevice *pOut = Application::GetDefaultDevice();
83*b1cdbd2cSJim Jagielski 
84*b1cdbd2cSJim Jagielski 					if(pOut->GetSettings().GetStyleSettings().GetHighContrastMode())
85*b1cdbd2cSJim Jagielski 					{
86*b1cdbd2cSJim Jagielski 						// not possible when in high contrast mode
87*b1cdbd2cSJim Jagielski 						return  OVERLAY_INVERT;
88*b1cdbd2cSJim Jagielski 					}
89*b1cdbd2cSJim Jagielski 
90*b1cdbd2cSJim Jagielski 					if(!pOut->supportsOperation(OutDevSupport_TransparentRect))
91*b1cdbd2cSJim Jagielski 					{
92*b1cdbd2cSJim Jagielski 						// not possible when no fast transparence paint is supported on the system
93*b1cdbd2cSJim Jagielski 						return OVERLAY_INVERT;
94*b1cdbd2cSJim Jagielski 					}
95*b1cdbd2cSJim Jagielski 				}
96*b1cdbd2cSJim Jagielski 			}
97*b1cdbd2cSJim Jagielski 
98*b1cdbd2cSJim Jagielski             return aOverlayType;
99*b1cdbd2cSJim Jagielski         }
100*b1cdbd2cSJim Jagielski 
createOverlayObjectPrimitive2DSequence()101*b1cdbd2cSJim Jagielski         drawinglayer::primitive2d::Primitive2DSequence OverlaySelection::createOverlayObjectPrimitive2DSequence()
102*b1cdbd2cSJim Jagielski 		{
103*b1cdbd2cSJim Jagielski 			drawinglayer::primitive2d::Primitive2DSequence aRetval;
104*b1cdbd2cSJim Jagielski 			const sal_uInt32 nCount(getRanges().size());
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski 			if(nCount)
107*b1cdbd2cSJim Jagielski 			{
108*b1cdbd2cSJim Jagielski 				// create range primitives
109*b1cdbd2cSJim Jagielski                 const bool bInvert(OVERLAY_INVERT == maLastOverlayType);
110*b1cdbd2cSJim Jagielski 			    basegfx::BColor aRGBColor(getBaseColor().getBColor());
111*b1cdbd2cSJim Jagielski                 aRetval.realloc(nCount);
112*b1cdbd2cSJim Jagielski 
113*b1cdbd2cSJim Jagielski                 if(bInvert)
114*b1cdbd2cSJim Jagielski                 {
115*b1cdbd2cSJim Jagielski                     // force color to white for invert to get a full invert
116*b1cdbd2cSJim Jagielski                     aRGBColor = basegfx::BColor(1.0, 1.0, 1.0);
117*b1cdbd2cSJim Jagielski                 }
118*b1cdbd2cSJim Jagielski 
119*b1cdbd2cSJim Jagielski 				for(sal_uInt32 a(0);a < nCount; a++)
120*b1cdbd2cSJim Jagielski 				{
121*b1cdbd2cSJim Jagielski 					const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(maRanges[a]));
122*b1cdbd2cSJim Jagielski 					aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(
123*b1cdbd2cSJim Jagielski 						new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
124*b1cdbd2cSJim Jagielski 							basegfx::B2DPolyPolygon(aPolygon),
125*b1cdbd2cSJim Jagielski 							aRGBColor));
126*b1cdbd2cSJim Jagielski 				}
127*b1cdbd2cSJim Jagielski 
128*b1cdbd2cSJim Jagielski 				if(bInvert)
129*b1cdbd2cSJim Jagielski 				{
130*b1cdbd2cSJim Jagielski 					// embed all in invert primitive
131*b1cdbd2cSJim Jagielski 					const drawinglayer::primitive2d::Primitive2DReference aInvert(
132*b1cdbd2cSJim Jagielski 						new drawinglayer::primitive2d::InvertPrimitive2D(
133*b1cdbd2cSJim Jagielski 							aRetval));
134*b1cdbd2cSJim Jagielski 					aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aInvert, 1);
135*b1cdbd2cSJim Jagielski 				}
136*b1cdbd2cSJim Jagielski                 else if(OVERLAY_TRANSPARENT == maLastOverlayType)
137*b1cdbd2cSJim Jagielski                 {
138*b1cdbd2cSJim Jagielski 			        // embed all rectangles in transparent paint
139*b1cdbd2cSJim Jagielski 					const double fTransparence(mnLastTransparence / 100.0);
140*b1cdbd2cSJim Jagielski 					const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence(
141*b1cdbd2cSJim Jagielski 				        new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
142*b1cdbd2cSJim Jagielski 					        aRetval,
143*b1cdbd2cSJim Jagielski 					        fTransparence));
144*b1cdbd2cSJim Jagielski 
145*b1cdbd2cSJim Jagielski                     if(getBorder())
146*b1cdbd2cSJim Jagielski                     {
147*b1cdbd2cSJim Jagielski 					    const basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges()));
148*b1cdbd2cSJim Jagielski 			            const drawinglayer::primitive2d::Primitive2DReference aSelectionOutline(
149*b1cdbd2cSJim Jagielski 				            new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D(
150*b1cdbd2cSJim Jagielski 					            aPolyPolygon,
151*b1cdbd2cSJim Jagielski 					            aRGBColor));
152*b1cdbd2cSJim Jagielski 
153*b1cdbd2cSJim Jagielski                         // add both to result
154*b1cdbd2cSJim Jagielski                         aRetval.realloc(2);
155*b1cdbd2cSJim Jagielski                         aRetval[0] = aUnifiedTransparence;
156*b1cdbd2cSJim Jagielski                         aRetval[1] = aSelectionOutline;
157*b1cdbd2cSJim Jagielski                     }
158*b1cdbd2cSJim Jagielski                     else
159*b1cdbd2cSJim Jagielski                     {
160*b1cdbd2cSJim Jagielski                         // just add transparent part
161*b1cdbd2cSJim Jagielski     					aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparence, 1);
162*b1cdbd2cSJim Jagielski                     }
163*b1cdbd2cSJim Jagielski                 }
164*b1cdbd2cSJim Jagielski 			}
165*b1cdbd2cSJim Jagielski 
166*b1cdbd2cSJim Jagielski 			return aRetval;
167*b1cdbd2cSJim Jagielski 		}
168*b1cdbd2cSJim Jagielski 
OverlaySelection(OverlayType eType,const Color & rColor,const std::vector<basegfx::B2DRange> & rRanges,bool bBorder)169*b1cdbd2cSJim Jagielski 		OverlaySelection::OverlaySelection(
170*b1cdbd2cSJim Jagielski 			OverlayType eType,
171*b1cdbd2cSJim Jagielski 			const Color& rColor,
172*b1cdbd2cSJim Jagielski 			const std::vector< basegfx::B2DRange >& rRanges,
173*b1cdbd2cSJim Jagielski             bool bBorder)
174*b1cdbd2cSJim Jagielski 		:	OverlayObject(rColor),
175*b1cdbd2cSJim Jagielski             meOverlayType(eType),
176*b1cdbd2cSJim Jagielski             maRanges(rRanges),
177*b1cdbd2cSJim Jagielski             maLastOverlayType(eType),
178*b1cdbd2cSJim Jagielski             mnLastTransparence(0),
179*b1cdbd2cSJim Jagielski             mbBorder(bBorder)
180*b1cdbd2cSJim Jagielski 		{
181*b1cdbd2cSJim Jagielski             // no AA for selection overlays
182*b1cdbd2cSJim Jagielski             allowAntiAliase(false);
183*b1cdbd2cSJim Jagielski 		}
184*b1cdbd2cSJim Jagielski 
~OverlaySelection()185*b1cdbd2cSJim Jagielski 		OverlaySelection::~OverlaySelection()
186*b1cdbd2cSJim Jagielski 		{
187*b1cdbd2cSJim Jagielski 			if(getOverlayManager())
188*b1cdbd2cSJim Jagielski 			{
189*b1cdbd2cSJim Jagielski 				getOverlayManager()->remove(*this);
190*b1cdbd2cSJim Jagielski 			}
191*b1cdbd2cSJim Jagielski 		}
192*b1cdbd2cSJim Jagielski 
getOverlayObjectPrimitive2DSequence() const193*b1cdbd2cSJim Jagielski 		drawinglayer::primitive2d::Primitive2DSequence OverlaySelection::getOverlayObjectPrimitive2DSequence() const
194*b1cdbd2cSJim Jagielski         {
195*b1cdbd2cSJim Jagielski             // get current values
196*b1cdbd2cSJim Jagielski            	const OverlayType aNewOverlayType(impCheckPossibleOverlayType(meOverlayType));
197*b1cdbd2cSJim Jagielski 			const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
198*b1cdbd2cSJim Jagielski 			const sal_uInt16 nNewTransparence(aSvtOptionsDrawinglayer.GetTransparentSelectionPercent());
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski 			if(getPrimitive2DSequence().hasElements())
201*b1cdbd2cSJim Jagielski 			{
202*b1cdbd2cSJim Jagielski                 if(aNewOverlayType != maLastOverlayType
203*b1cdbd2cSJim Jagielski                     || nNewTransparence != mnLastTransparence)
204*b1cdbd2cSJim Jagielski                 {
205*b1cdbd2cSJim Jagielski                     // conditions of last local decomposition have changed, delete
206*b1cdbd2cSJim Jagielski 				    const_cast< OverlaySelection* >(this)->setPrimitive2DSequence(drawinglayer::primitive2d::Primitive2DSequence());
207*b1cdbd2cSJim Jagielski                 }
208*b1cdbd2cSJim Jagielski 			}
209*b1cdbd2cSJim Jagielski 
210*b1cdbd2cSJim Jagielski 			if(!getPrimitive2DSequence().hasElements())
211*b1cdbd2cSJim Jagielski 			{
212*b1cdbd2cSJim Jagielski 				// remember new values
213*b1cdbd2cSJim Jagielski 				const_cast< OverlaySelection* >(this)->maLastOverlayType = aNewOverlayType;
214*b1cdbd2cSJim Jagielski 				const_cast< OverlaySelection* >(this)->mnLastTransparence = nNewTransparence;
215*b1cdbd2cSJim Jagielski 			}
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski 			// call base implementation
218*b1cdbd2cSJim Jagielski 			return OverlayObject::getOverlayObjectPrimitive2DSequence();
219*b1cdbd2cSJim Jagielski         }
220*b1cdbd2cSJim Jagielski 
setRanges(const std::vector<basegfx::B2DRange> & rNew)221*b1cdbd2cSJim Jagielski 		void OverlaySelection::setRanges(const std::vector< basegfx::B2DRange >& rNew)
222*b1cdbd2cSJim Jagielski 		{
223*b1cdbd2cSJim Jagielski 			if(rNew != maRanges)
224*b1cdbd2cSJim Jagielski 			{
225*b1cdbd2cSJim Jagielski 				maRanges = rNew;
226*b1cdbd2cSJim Jagielski 				objectChange();
227*b1cdbd2cSJim Jagielski 			}
228*b1cdbd2cSJim Jagielski 		}
229*b1cdbd2cSJim Jagielski 	} // end of namespace overlay
230*b1cdbd2cSJim Jagielski } // end of namespace sdr
231*b1cdbd2cSJim Jagielski 
232*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
233*b1cdbd2cSJim Jagielski // eof
234