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 .
20 #include <vclhelpergradient.hxx>
21 #include <basegfx/range/b2drange.hxx>
22 #include <vcl/outdev.hxx>
23 #include <basegfx/polygon/b2dpolygon.hxx>
24 #include <basegfx/polygon/b2dpolypolygontools.hxx>
25 #include <basegfx/polygon/b2dpolygontools.hxx>
26 #include <drawinglayer/texture/texture.hxx>
28 //////////////////////////////////////////////////////////////////////////////
29 // support methods for vcl direct gradient renderering
31 namespace drawinglayer
35 sal_uInt32
impCalcGradientSteps(OutputDevice
& rOutDev
, sal_uInt32 nSteps
, const basegfx::B2DRange
& rRange
, sal_uInt32 nMaxDist
)
39 const Size
aSize(rOutDev
.LogicToPixel(Size(basegfx::fround(rRange
.getWidth()), basegfx::fround(rRange
.getHeight()))));
40 nSteps
= (aSize
.getWidth() + aSize
.getHeight()) >> 3L;
56 void impDrawGradientToOutDevSimple(
57 OutputDevice
& rOutDev
,
58 const basegfx::B2DPolyPolygon
& rTargetForm
,
59 const ::std::vector
< basegfx::B2DHomMatrix
>& rMatrices
,
60 const ::std::vector
< basegfx::BColor
>& rColors
,
61 const basegfx::B2DPolygon
& rUnitPolygon
)
63 rOutDev
.SetLineColor();
65 for(sal_uInt32
a(0L); a
< rColors
.size(); a
++)
68 const basegfx::BColor
aFillColor(rColors
[a
]);
69 rOutDev
.SetFillColor(Color(aFillColor
));
73 if(a
- 1L < static_cast< sal_uInt32
>(rMatrices
.size()))
75 basegfx::B2DPolygon
aNewPoly(rUnitPolygon
);
76 aNewPoly
.transform(rMatrices
[a
- 1L]);
77 rOutDev
.DrawPolygon(aNewPoly
);
82 rOutDev
.DrawPolyPolygon(rTargetForm
);
87 void impDrawGradientToOutDevComplex(
88 OutputDevice
& rOutDev
,
89 const basegfx::B2DPolyPolygon
& rTargetForm
,
90 const ::std::vector
< basegfx::B2DHomMatrix
>& rMatrices
,
91 const ::std::vector
< basegfx::BColor
>& rColors
,
92 const basegfx::B2DPolygon
& rUnitPolygon
)
94 PolyPolygon
aVclTargetForm(rTargetForm
);
95 ::std::vector
< Polygon
> aVclPolygons
;
98 // remember and set to XOR
99 rOutDev
.SetLineColor();
100 rOutDev
.Push(PUSH_RASTEROP
);
101 rOutDev
.SetRasterOp(ROP_XOR
);
103 // draw gradient PolyPolygons
104 for(a
= 0L; a
< rMatrices
.size(); a
++)
106 // create polygon and remember
107 basegfx::B2DPolygon
aNewPoly(rUnitPolygon
);
108 aNewPoly
.transform(rMatrices
[a
]);
109 aVclPolygons
.push_back(Polygon(aNewPoly
));
112 if(rColors
.size() > a
)
114 const basegfx::BColor
aFillColor(rColors
[a
]);
115 rOutDev
.SetFillColor(Color(aFillColor
));
118 // create vcl PolyPolygon and draw it
121 PolyPolygon
aVclPolyPoly(aVclPolygons
[a
- 1L]);
122 aVclPolyPoly
.Insert(aVclPolygons
[a
]);
123 rOutDev
.DrawPolyPolygon(aVclPolyPoly
);
127 PolyPolygon
aVclPolyPoly(aVclTargetForm
);
128 aVclPolyPoly
.Insert(aVclPolygons
[0L]);
129 rOutDev
.DrawPolyPolygon(aVclPolyPoly
);
133 // draw last poly in last color
136 const basegfx::BColor
aFillColor(rColors
[rColors
.size() - 1L]);
137 rOutDev
.SetFillColor(Color(aFillColor
));
138 rOutDev
.DrawPolygon(aVclPolygons
[aVclPolygons
.size() - 1L]);
141 // draw object form in black and go back to XOR
142 rOutDev
.SetFillColor(COL_BLACK
);
143 rOutDev
.SetRasterOp(ROP_0
);
144 rOutDev
.DrawPolyPolygon(aVclTargetForm
);
145 rOutDev
.SetRasterOp(ROP_XOR
);
147 // draw gradient PolyPolygons again
148 for(a
= 0L; a
< rMatrices
.size(); a
++)
151 if(rColors
.size() > a
)
153 const basegfx::BColor
aFillColor(rColors
[a
]);
154 rOutDev
.SetFillColor(Color(aFillColor
));
157 // create vcl PolyPolygon and draw it
160 PolyPolygon
aVclPolyPoly(aVclPolygons
[a
- 1L]);
161 aVclPolyPoly
.Insert(aVclPolygons
[a
]);
162 rOutDev
.DrawPolyPolygon(aVclPolyPoly
);
166 PolyPolygon
aVclPolyPoly(aVclTargetForm
);
167 aVclPolyPoly
.Insert(aVclPolygons
[0L]);
168 rOutDev
.DrawPolyPolygon(aVclPolyPoly
);
172 // draw last poly in last color
175 const basegfx::BColor
aFillColor(rColors
[rColors
.size() - 1L]);
176 rOutDev
.SetFillColor(Color(aFillColor
));
177 rOutDev
.DrawPolygon(aVclPolygons
[aVclPolygons
.size() - 1L]);
183 } // end of anonymous namespace
184 } // end of namespace drawinglayer
186 namespace drawinglayer
188 void impDrawGradientToOutDev(
189 OutputDevice
& rOutDev
,
190 const basegfx::B2DPolyPolygon
& rTargetForm
,
191 attribute::GradientStyle eGradientStyle
,
193 const basegfx::BColor
& rStart
,
194 const basegfx::BColor
& rEnd
,
195 double fBorder
, double fAngle
, double fOffsetX
, double fOffsetY
, bool bSimple
)
197 const basegfx::B2DRange
aOutlineRange(basegfx::tools::getRange(rTargetForm
));
198 ::std::vector
< basegfx::B2DHomMatrix
> aMatrices
;
199 ::std::vector
< basegfx::BColor
> aColors
;
200 basegfx::B2DPolygon aUnitPolygon
;
202 // make sure steps is not too high/low
203 nSteps
= impCalcGradientSteps(rOutDev
, nSteps
, aOutlineRange
, sal_uInt32((rStart
.getMaximumDistance(rEnd
) * 127.5) + 0.5));
206 switch(eGradientStyle
)
208 case attribute::GRADIENTSTYLE_LINEAR
:
210 texture::GeoTexSvxGradientLinear
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fAngle
);
211 aGradient
.appendTransformations(aMatrices
);
212 aGradient
.appendColors(aColors
);
213 aUnitPolygon
= basegfx::tools::createUnitPolygon();
216 case attribute::GRADIENTSTYLE_AXIAL
:
218 texture::GeoTexSvxGradientAxial
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fAngle
);
219 aGradient
.appendTransformations(aMatrices
);
220 aGradient
.appendColors(aColors
);
221 aUnitPolygon
= basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
224 case attribute::GRADIENTSTYLE_RADIAL
:
226 texture::GeoTexSvxGradientRadial
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fOffsetX
, fOffsetY
);
227 aGradient
.appendTransformations(aMatrices
);
228 aGradient
.appendColors(aColors
);
229 aUnitPolygon
= basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0,0), 1);
232 case attribute::GRADIENTSTYLE_ELLIPTICAL
:
234 texture::GeoTexSvxGradientElliptical
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fOffsetX
, fOffsetX
, fAngle
);
235 aGradient
.appendTransformations(aMatrices
);
236 aGradient
.appendColors(aColors
);
237 aUnitPolygon
= basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0,0), 1);
240 case attribute::GRADIENTSTYLE_SQUARE
:
242 texture::GeoTexSvxGradientSquare
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fOffsetX
, fOffsetX
, fAngle
);
243 aGradient
.appendTransformations(aMatrices
);
244 aGradient
.appendColors(aColors
);
245 aUnitPolygon
= basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
248 case attribute::GRADIENTSTYLE_RECT
:
250 texture::GeoTexSvxGradientRect
aGradient(aOutlineRange
, rStart
, rEnd
, nSteps
, fBorder
, fOffsetX
, fOffsetX
, fAngle
);
251 aGradient
.appendTransformations(aMatrices
);
252 aGradient
.appendColors(aColors
);
253 aUnitPolygon
= basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1, -1, 1, 1));
258 // paint them with mask using the XOR method
259 if(!aMatrices
.empty())
263 impDrawGradientToOutDevSimple(rOutDev
, rTargetForm
, aMatrices
, aColors
, aUnitPolygon
);
267 impDrawGradientToOutDevComplex(rOutDev
, rTargetForm
, aMatrices
, aColors
, aUnitPolygon
);
271 } // end of namespace drawinglayer
273 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */