merged tag ooo/DEV300_m102
[LibreOffice.git] / vcl / win / source / gdi / salgdi_gdiplus.cxx
blob88efbb29d30a9a5d268a0b8693fc43cfeb028aaa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <stdio.h>
32 #include <string.h>
33 #include <tools/svwin.h>
34 #include <wincomp.hxx>
35 #include <saldata.hxx>
36 #include <salgdi.h>
37 #include <tools/debug.hxx>
39 #ifndef min
40 #define min(a,b) (((a) < (b)) ? (a) : (b))
41 #endif
42 #ifndef max
43 #define max(a,b) (((a) > (b)) ? (a) : (b))
44 #endif
46 #if defined _MSC_VER
47 #pragma warning(push, 1)
48 #endif
50 #include <GdiPlus.h>
51 #include <GdiPlusEnums.h>
52 #include <GdiPlusColor.h>
54 #if defined _MSC_VER
55 #pragma warning(pop)
56 #endif
58 #include <basegfx/polygon/b2dpolygon.hxx>
60 // -----------------------------------------------------------------------
62 void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
64 sal_uInt32 nCount(rPolygon.count());
66 if(nCount)
68 const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1);
69 const bool bControls(rPolygon.areControlPointsUsed());
70 basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
71 Gdiplus::PointF aFCurr(Gdiplus::REAL(aCurr.getX()), Gdiplus::REAL(aCurr.getY()));
73 for(sal_uInt32 a(0); a < nEdgeCount; a++)
75 const sal_uInt32 nNextIndex((a + 1) % nCount);
76 const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
77 const Gdiplus::PointF aFNext(Gdiplus::REAL(aNext.getX()), Gdiplus::REAL(aNext.getY()));
79 if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex)))
81 const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
82 const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
84 rPath.AddBezier(
85 aFCurr,
86 Gdiplus::PointF(Gdiplus::REAL(aCa.getX()), Gdiplus::REAL(aCa.getY())),
87 Gdiplus::PointF(Gdiplus::REAL(aCb.getX()), Gdiplus::REAL(aCb.getY())),
88 aFNext);
90 else
92 rPath.AddLine(aFCurr, aFNext);
95 if(a + 1 < nEdgeCount)
97 aFCurr = aFNext;
99 if(bNoLineJoin)
101 rPath.StartFigure();
108 void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
110 sal_uInt32 nCount(rPolygon.count());
112 if(nCount)
114 const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1);
115 const bool bControls(rPolygon.areControlPointsUsed());
116 basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
117 Gdiplus::Point aICurr(INT(aCurr.getX()), INT(aCurr.getY()));
119 for(sal_uInt32 a(0); a < nEdgeCount; a++)
121 const sal_uInt32 nNextIndex((a + 1) % nCount);
122 const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
123 const Gdiplus::Point aINext(INT(aNext.getX()), INT(aNext.getY()));
125 if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex)))
127 const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
128 const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
130 rPath.AddBezier(
131 aICurr,
132 Gdiplus::Point(INT(aCa.getX()), INT(aCa.getY())),
133 Gdiplus::Point(INT(aCb.getX()), INT(aCb.getY())),
134 aINext);
136 else
138 rPath.AddLine(aICurr, aINext);
141 if(a + 1 < nEdgeCount)
143 aICurr = aINext;
145 if(bNoLineJoin)
147 rPath.StartFigure();
154 bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
156 const sal_uInt32 nCount(rPolyPolygon.count());
158 if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0))
160 Gdiplus::Graphics aGraphics(mhDC);
161 const sal_uInt8 aTrans((sal_uInt8)255 - (sal_uInt8)basegfx::fround(fTransparency * 255.0));
162 Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maFillColor), SALCOLOR_GREEN(maFillColor), SALCOLOR_BLUE(maFillColor));
163 Gdiplus::SolidBrush aTestBrush(aTestColor);
164 Gdiplus::GraphicsPath aPath;
166 for(sal_uInt32 a(0); a < nCount; a++)
168 if(0 != a)
170 aPath.StartFigure(); // #i101491# not needed for first run
173 impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolyPolygon.getB2DPolygon(a), false);
174 aPath.CloseFigure();
177 if(getAntiAliasB2DDraw())
179 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
181 else
183 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
186 aGraphics.FillPath(&aTestBrush, &aPath);
189 return true;
192 bool WinSalGraphics::drawPolyLine( const basegfx::B2DPolygon& rPolygon, double fTransparency, const basegfx::B2DVector& rLineWidths, basegfx::B2DLineJoin eLineJoin )
194 const sal_uInt32 nCount(rPolygon.count());
196 if(mbPen && nCount)
198 Gdiplus::Graphics aGraphics(mhDC);
199 const sal_uInt8 aTrans = (sal_uInt8)basegfx::fround( 255 * (1.0 - fTransparency) );
200 Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor));
201 Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX()));
202 Gdiplus::GraphicsPath aPath;
203 bool bNoLineJoin(false);
205 switch(eLineJoin)
207 default : // basegfx::B2DLINEJOIN_NONE :
209 if(basegfx::fTools::more(rLineWidths.getX(), 0.0))
211 bNoLineJoin = true;
213 break;
215 case basegfx::B2DLINEJOIN_BEVEL :
217 aTestPen.SetLineJoin(Gdiplus::LineJoinBevel);
218 break;
220 case basegfx::B2DLINEJOIN_MIDDLE :
221 case basegfx::B2DLINEJOIN_MITER :
223 const Gdiplus::REAL aMiterLimit(15.0);
224 aTestPen.SetMiterLimit(aMiterLimit);
225 aTestPen.SetLineJoin(Gdiplus::LineJoinMiter);
226 break;
228 case basegfx::B2DLINEJOIN_ROUND :
230 aTestPen.SetLineJoin(Gdiplus::LineJoinRound);
231 break;
235 if(nCount > 250 && basegfx::fTools::more(rLineWidths.getX(), 1.5))
237 impAddB2DPolygonToGDIPlusGraphicsPathInteger(aPath, rPolygon, bNoLineJoin);
239 else
241 impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolygon, bNoLineJoin);
244 if(rPolygon.isClosed() && !bNoLineJoin)
246 // #i101491# needed to create the correct line joins
247 aPath.CloseFigure();
250 if(getAntiAliasB2DDraw())
252 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
254 else
256 aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
259 aGraphics.DrawPath(&aTestPen, &aPath);
262 return true;
265 // -----------------------------------------------------------------------