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_vcl.hxx" 26 27 #include <stdio.h> 28 #include <string.h> 29 30 #include <tools/svwin.h> 31 #include <tools/debug.hxx> 32 33 #include <win/wincomp.hxx> 34 #include <win/saldata.hxx> 35 #include <win/salgdi.h> 36 37 #ifndef min 38 #define min(a,b) (((a) < (b)) ? (a) : (b)) 39 #endif 40 #ifndef max 41 #define max(a,b) (((a) > (b)) ? (a) : (b)) 42 #endif 43 44 #if defined _MSC_VER 45 #pragma warning(push, 1) 46 #endif 47 48 #include <GdiPlus.h> 49 #include <GdiPlusEnums.h> 50 #include <GdiPlusColor.h> 51 52 #if defined _MSC_VER 53 #pragma warning(pop) 54 #endif 55 56 #include <basegfx/polygon/b2dpolygon.hxx> 57 58 // ----------------------------------------------------------------------- 59 60 void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin) 61 { 62 sal_uInt32 nCount(rPolygon.count()); 63 64 if(nCount) 65 { 66 const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1); 67 const bool bControls(rPolygon.areControlPointsUsed()); 68 basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0)); 69 Gdiplus::PointF aFCurr(Gdiplus::REAL(aCurr.getX()), Gdiplus::REAL(aCurr.getY())); 70 71 for(sal_uInt32 a(0); a < nEdgeCount; a++) 72 { 73 const sal_uInt32 nNextIndex((a + 1) % nCount); 74 const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex)); 75 const Gdiplus::PointF aFNext(Gdiplus::REAL(aNext.getX()), Gdiplus::REAL(aNext.getY())); 76 77 if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex))) 78 { 79 const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a)); 80 const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex)); 81 82 rPath.AddBezier( 83 aFCurr, 84 Gdiplus::PointF(Gdiplus::REAL(aCa.getX()), Gdiplus::REAL(aCa.getY())), 85 Gdiplus::PointF(Gdiplus::REAL(aCb.getX()), Gdiplus::REAL(aCb.getY())), 86 aFNext); 87 } 88 else 89 { 90 rPath.AddLine(aFCurr, aFNext); 91 } 92 93 if(a + 1 < nEdgeCount) 94 { 95 aFCurr = aFNext; 96 97 if(bNoLineJoin) 98 { 99 rPath.StartFigure(); 100 } 101 } 102 } 103 } 104 } 105 106 void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin) 107 { 108 sal_uInt32 nCount(rPolygon.count()); 109 110 if(nCount) 111 { 112 const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1); 113 const bool bControls(rPolygon.areControlPointsUsed()); 114 basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0)); 115 Gdiplus::Point aICurr(INT(aCurr.getX()), INT(aCurr.getY())); 116 117 for(sal_uInt32 a(0); a < nEdgeCount; a++) 118 { 119 const sal_uInt32 nNextIndex((a + 1) % nCount); 120 const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex)); 121 const Gdiplus::Point aINext(INT(aNext.getX()), INT(aNext.getY())); 122 123 if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex))) 124 { 125 const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a)); 126 const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex)); 127 128 rPath.AddBezier( 129 aICurr, 130 Gdiplus::Point(INT(aCa.getX()), INT(aCa.getY())), 131 Gdiplus::Point(INT(aCb.getX()), INT(aCb.getY())), 132 aINext); 133 } 134 else 135 { 136 rPath.AddLine(aICurr, aINext); 137 } 138 139 if(a + 1 < nEdgeCount) 140 { 141 aICurr = aINext; 142 143 if(bNoLineJoin) 144 { 145 rPath.StartFigure(); 146 } 147 } 148 } 149 } 150 } 151 152 bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency) 153 { 154 const sal_uInt32 nCount(rPolyPolygon.count()); 155 156 if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0)) 157 { 158 Gdiplus::Graphics aGraphics(mhDC); 159 const sal_uInt8 aTrans((sal_uInt8)255 - (sal_uInt8)basegfx::fround(fTransparency * 255.0)); 160 Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maFillColor), SALCOLOR_GREEN(maFillColor), SALCOLOR_BLUE(maFillColor)); 161 Gdiplus::SolidBrush aTestBrush(aTestColor); 162 Gdiplus::GraphicsPath aPath; 163 164 for(sal_uInt32 a(0); a < nCount; a++) 165 { 166 if(0 != a) 167 { 168 aPath.StartFigure(); // #i101491# not needed for first run 169 } 170 171 impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolyPolygon.getB2DPolygon(a), false); 172 aPath.CloseFigure(); 173 } 174 175 if(getAntiAliasB2DDraw()) 176 { 177 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); 178 } 179 else 180 { 181 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); 182 } 183 184 aGraphics.FillPath(&aTestBrush, &aPath); 185 } 186 187 return true; 188 } 189 190 bool WinSalGraphics::drawPolyLine( 191 const basegfx::B2DPolygon& rPolygon, 192 double fTransparency, 193 const basegfx::B2DVector& rLineWidths, 194 basegfx::B2DLineJoin eLineJoin, 195 com::sun::star::drawing::LineCap eLineCap) 196 { 197 const sal_uInt32 nCount(rPolygon.count()); 198 199 if(mbPen && nCount) 200 { 201 Gdiplus::Graphics aGraphics(mhDC); 202 const sal_uInt8 aTrans = (sal_uInt8)basegfx::fround( 255 * (1.0 - fTransparency) ); 203 Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor)); 204 Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX())); 205 Gdiplus::GraphicsPath aPath; 206 bool bNoLineJoin(false); 207 208 switch(eLineJoin) 209 { 210 default : // basegfx::B2DLINEJOIN_NONE : 211 { 212 if(basegfx::fTools::more(rLineWidths.getX(), 0.0)) 213 { 214 bNoLineJoin = true; 215 } 216 break; 217 } 218 case basegfx::B2DLINEJOIN_BEVEL : 219 { 220 aTestPen.SetLineJoin(Gdiplus::LineJoinBevel); 221 break; 222 } 223 case basegfx::B2DLINEJOIN_MIDDLE : 224 case basegfx::B2DLINEJOIN_MITER : 225 { 226 const Gdiplus::REAL aMiterLimit(15.0); 227 aTestPen.SetMiterLimit(aMiterLimit); 228 aTestPen.SetLineJoin(Gdiplus::LineJoinMiter); 229 break; 230 } 231 case basegfx::B2DLINEJOIN_ROUND : 232 { 233 aTestPen.SetLineJoin(Gdiplus::LineJoinRound); 234 break; 235 } 236 } 237 238 switch(eLineCap) 239 { 240 default: /*com::sun::star::drawing::LineCap_BUTT*/ 241 { 242 // nothing to do 243 break; 244 } 245 case com::sun::star::drawing::LineCap_ROUND: 246 { 247 aTestPen.SetStartCap(Gdiplus::LineCapRound); 248 aTestPen.SetEndCap(Gdiplus::LineCapRound); 249 break; 250 } 251 case com::sun::star::drawing::LineCap_SQUARE: 252 { 253 aTestPen.SetStartCap(Gdiplus::LineCapSquare); 254 aTestPen.SetEndCap(Gdiplus::LineCapSquare); 255 break; 256 } 257 } 258 259 if(nCount > 250 && basegfx::fTools::more(rLineWidths.getX(), 1.5)) 260 { 261 impAddB2DPolygonToGDIPlusGraphicsPathInteger(aPath, rPolygon, bNoLineJoin); 262 } 263 else 264 { 265 impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolygon, bNoLineJoin); 266 } 267 268 if(rPolygon.isClosed() && !bNoLineJoin) 269 { 270 // #i101491# needed to create the correct line joins 271 aPath.CloseFigure(); 272 } 273 274 if(getAntiAliasB2DDraw()) 275 { 276 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); 277 } 278 else 279 { 280 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone); 281 } 282 283 aGraphics.DrawPath(&aTestPen, &aPath); 284 } 285 286 return true; 287 } 288 289 // ----------------------------------------------------------------------- 290