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