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