1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 #include <win/wincomp.hxx>
26 #include <win/saldata.hxx>
27 #include <win/salgdi.h>
31 #define min(a,b) (((a) < (b)) ? (a) : (b))
34 #define max(a,b) (((a) > (b)) ? (a) : (b))
39 #pragma warning(push, 1)
43 #include <gdiplusenums.h>
44 #include <gdipluscolor.h>
50 #include <basegfx/polygon/b2dpolygon.hxx>
52 // -----------------------------------------------------------------------
54 void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GpPath
*pPath
, const basegfx::B2DPolygon
& rPolygon
, bool bNoLineJoin
)
56 sal_uInt32
nCount(rPolygon
.count());
60 const sal_uInt32
nEdgeCount(rPolygon
.isClosed() ? nCount
: nCount
- 1);
61 const bool bControls(rPolygon
.areControlPointsUsed());
62 basegfx::B2DPoint
aCurr(rPolygon
.getB2DPoint(0));
64 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
66 const sal_uInt32
nNextIndex((a
+ 1) % nCount
);
67 const basegfx::B2DPoint
aNext(rPolygon
.getB2DPoint(nNextIndex
));
69 if(bControls
&& (rPolygon
.isNextControlPointUsed(a
) || rPolygon
.isPrevControlPointUsed(nNextIndex
)))
71 const basegfx::B2DPoint
aCa(rPolygon
.getNextControlPoint(a
));
72 const basegfx::B2DPoint
aCb(rPolygon
.getPrevControlPoint(nNextIndex
));
74 Gdiplus::DllExports::GdipAddPathBezier(pPath
,
75 aCurr
.getX(), aCurr
.getY(),
76 aCa
.getX(), aCa
.getY(),
77 aCb
.getX(), aCb
.getY(),
78 aNext
.getX(), aNext
.getY());
82 Gdiplus::DllExports::GdipAddPathLine(pPath
, aCurr
.getX(), aCurr
.getY(), aNext
.getX(), aNext
.getY());
85 if(a
+ 1 < nEdgeCount
)
91 Gdiplus::DllExports::GdipStartPathFigure(pPath
);
98 void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GpPath
*pPath
, const basegfx::B2DPolygon
& rPolygon
, bool bNoLineJoin
)
100 sal_uInt32
nCount(rPolygon
.count());
104 const sal_uInt32
nEdgeCount(rPolygon
.isClosed() ? nCount
: nCount
- 1);
105 const bool bControls(rPolygon
.areControlPointsUsed());
106 basegfx::B2DPoint
aCurr(rPolygon
.getB2DPoint(0));
108 for(sal_uInt32
a(0); a
< nEdgeCount
; a
++)
110 const sal_uInt32
nNextIndex((a
+ 1) % nCount
);
111 const basegfx::B2DPoint
aNext(rPolygon
.getB2DPoint(nNextIndex
));
113 if(bControls
&& (rPolygon
.isNextControlPointUsed(a
) || rPolygon
.isPrevControlPointUsed(nNextIndex
)))
115 const basegfx::B2DPoint
aCa(rPolygon
.getNextControlPoint(a
));
116 const basegfx::B2DPoint
aCb(rPolygon
.getPrevControlPoint(nNextIndex
));
118 Gdiplus::DllExports::GdipAddPathBezier(
120 aCurr
.getX(), aCurr
.getY(),
121 aCa
.getX(), aCa
.getY(),
122 aCb
.getX(), aCb
.getY(),
123 aNext
.getX(), aNext
.getY());
127 Gdiplus::DllExports::GdipAddPathLine(pPath
, aCurr
.getX(), aCurr
.getY(), aNext
.getX(), aNext
.getY());
130 if(a
+ 1 < nEdgeCount
)
136 Gdiplus::DllExports::GdipStartPathFigure(pPath
);
143 bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon
& rPolyPolygon
, double fTransparency
)
145 const sal_uInt32
nCount(rPolyPolygon
.count());
147 if(mbBrush
&& nCount
&& (fTransparency
>= 0.0 && fTransparency
< 1.0))
149 Gdiplus::GpGraphics
*pGraphics
= NULL
;
150 Gdiplus::DllExports::GdipCreateFromHDC(mhDC
, &pGraphics
);
151 const sal_uInt8
aTrans((sal_uInt8
)255 - (sal_uInt8
)basegfx::fround(fTransparency
* 255.0));
152 Gdiplus::Color
aTestColor(aTrans
, SALCOLOR_RED(maFillColor
), SALCOLOR_GREEN(maFillColor
), SALCOLOR_BLUE(maFillColor
));
153 Gdiplus::GpSolidFill
*pTestBrush
;
154 Gdiplus::DllExports::GdipCreateSolidFill(aTestColor
.GetValue(), &pTestBrush
);
155 Gdiplus::GpPath
*pPath
= NULL
;
156 Gdiplus::DllExports::GdipCreatePath(Gdiplus::FillModeAlternate
, &pPath
);
158 for(sal_uInt32
a(0); a
< nCount
; a
++)
162 Gdiplus::DllExports::GdipStartPathFigure(pPath
); // #i101491# not needed for first run
165 impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath
, rPolyPolygon
.getB2DPolygon(a
), false);
166 Gdiplus::DllExports::GdipClosePathFigure(pPath
);
169 if(getAntiAliasB2DDraw())
171 Gdiplus::DllExports::GdipSetSmoothingMode(pGraphics
, Gdiplus::SmoothingModeAntiAlias
);
175 Gdiplus::DllExports::GdipSetSmoothingMode(pGraphics
, Gdiplus::SmoothingModeNone
);
178 Gdiplus::DllExports::GdipFillPath(pGraphics
, pTestBrush
, pPath
);
180 Gdiplus::DllExports::GdipDeletePath(pPath
);
181 Gdiplus::DllExports::GdipDeleteGraphics(pGraphics
);
187 bool WinSalGraphics::drawPolyLine(
188 const basegfx::B2DPolygon
& rPolygon
,
189 double fTransparency
,
190 const basegfx::B2DVector
& rLineWidths
,
191 basegfx::B2DLineJoin eLineJoin
,
192 com::sun::star::drawing::LineCap eLineCap
)
194 const sal_uInt32
nCount(rPolygon
.count());
198 Gdiplus::GpGraphics
*pGraphics
= NULL
;
199 Gdiplus::DllExports::GdipCreateFromHDC(mhDC
, &pGraphics
);
200 const sal_uInt8 aTrans
= (sal_uInt8
)basegfx::fround( 255 * (1.0 - fTransparency
) );
201 Gdiplus::Color
aTestColor(aTrans
, SALCOLOR_RED(maLineColor
), SALCOLOR_GREEN(maLineColor
), SALCOLOR_BLUE(maLineColor
));
202 Gdiplus::GpPen
*pTestPen
= NULL
;
203 Gdiplus::DllExports::GdipCreatePen1(aTestColor
.GetValue(), Gdiplus::REAL(rLineWidths
.getX()), Gdiplus::UnitWorld
, &pTestPen
);
204 Gdiplus::GpPath
*pPath
;
205 Gdiplus::DllExports::GdipCreatePath(Gdiplus::FillModeAlternate
, &pPath
);
206 bool bNoLineJoin(false);
210 default : // basegfx::B2DLINEJOIN_NONE :
212 if(basegfx::fTools::more(rLineWidths
.getX(), 0.0))
218 case basegfx::B2DLINEJOIN_BEVEL
:
220 Gdiplus::DllExports::GdipSetPenLineJoin(pTestPen
, Gdiplus::LineJoinBevel
);
223 case basegfx::B2DLINEJOIN_MIDDLE
:
224 case basegfx::B2DLINEJOIN_MITER
:
226 const Gdiplus::REAL
aMiterLimit(15.0);
227 Gdiplus::DllExports::GdipSetPenMiterLimit(pTestPen
, aMiterLimit
);
228 Gdiplus::DllExports::GdipSetPenLineJoin(pTestPen
, Gdiplus::LineJoinMiter
);
231 case basegfx::B2DLINEJOIN_ROUND
:
233 Gdiplus::DllExports::GdipSetPenLineJoin(pTestPen
, Gdiplus::LineJoinRound
);
240 default: /*com::sun::star::drawing::LineCap_BUTT*/
245 case com::sun::star::drawing::LineCap_ROUND
:
247 Gdiplus::DllExports::GdipSetPenStartCap(pTestPen
, Gdiplus::LineCapRound
);
248 Gdiplus::DllExports::GdipSetPenEndCap(pTestPen
, Gdiplus::LineCapRound
);
251 case com::sun::star::drawing::LineCap_SQUARE
:
253 Gdiplus::DllExports::GdipSetPenStartCap(pTestPen
, Gdiplus::LineCapSquare
);
254 Gdiplus::DllExports::GdipSetPenEndCap(pTestPen
, Gdiplus::LineCapSquare
);
259 if(nCount
> 250 && basegfx::fTools::more(rLineWidths
.getX(), 1.5))
261 impAddB2DPolygonToGDIPlusGraphicsPathInteger(pPath
, rPolygon
, bNoLineJoin
);
265 impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath
, rPolygon
, bNoLineJoin
);
268 if(rPolygon
.isClosed() && !bNoLineJoin
)
270 // #i101491# needed to create the correct line joins
271 Gdiplus::DllExports::GdipClosePathFigure(pPath
);
274 if(getAntiAliasB2DDraw())
276 Gdiplus::DllExports::GdipSetSmoothingMode(pGraphics
, Gdiplus::SmoothingModeAntiAlias
);
280 Gdiplus::DllExports::GdipSetSmoothingMode(pGraphics
, Gdiplus::SmoothingModeNone
);
283 Gdiplus::DllExports::GdipDrawPath(pGraphics
, pTestPen
, pPath
);
285 Gdiplus::DllExports::GdipDeletePath(pPath
);
286 Gdiplus::DllExports::GdipDeletePen(pTestPen
);
287 Gdiplus::DllExports::GdipDeleteGraphics(pGraphics
);
293 // -----------------------------------------------------------------------
295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */