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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svx.hxx"
24 
25 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
26 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
27 #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include <basegfx/polygon/b2dpolygon.hxx>
31 #include <drawinglayer/attribute/fillhatchattribute.hxx>
32 #include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
33 #include <svx/xfillit0.hxx>
34 #include <vcl/graph.hxx>
35 
36 //////////////////////////////////////////////////////////////////////////////
37 
38 namespace drawinglayer
39 {
40     namespace attribute
41     {
42         void SdrAllFillAttributesHelper::createPrimitive2DSequence(
43             const basegfx::B2DRange& rPaintRange,
44             const basegfx::B2DRange& rDefineRange)
45         {
46             // reset and remember new target range for object geometry
47             maLastPaintRange = rPaintRange;
48             maLastDefineRange = rDefineRange;
49 
50             if(isUsed())
51             {
52                 maPrimitives.realloc(1);
53                 maPrimitives[0] = drawinglayer::primitive2d::createPolyPolygonFillPrimitive(
54                     basegfx::B2DPolyPolygon(
55                         basegfx::tools::createPolygonFromRect(
56                             maLastPaintRange)),
57                         maLastDefineRange,
58                     maFillAttribute.get() ? *maFillAttribute.get() : drawinglayer::attribute::SdrFillAttribute(),
59                     maFillGradientAttribute.get() ? *maFillGradientAttribute.get() : drawinglayer::attribute::FillGradientAttribute());
60             }
61         }
62 
63         SdrAllFillAttributesHelper::SdrAllFillAttributesHelper()
64         :   maLastPaintRange(),
65             maLastDefineRange(),
66             maFillAttribute(),
67             maFillGradientAttribute(),
68             maPrimitives()
69         {
70         }
71 
72         SdrAllFillAttributesHelper::SdrAllFillAttributesHelper(const Color& rColor)
73         :   maLastPaintRange(),
74             maLastDefineRange(),
75             maFillAttribute(),
76             maFillGradientAttribute(),
77             maPrimitives()
78         {
79             maFillAttribute.reset(
80                 new drawinglayer::attribute::SdrFillAttribute(
81                     0.0,
82                     Color(rColor.GetRGBColor()).getBColor(),
83                     drawinglayer::attribute::FillGradientAttribute(),
84                     drawinglayer::attribute::FillHatchAttribute(),
85                     drawinglayer::attribute::SdrFillGraphicAttribute()));
86         }
87 
88         SdrAllFillAttributesHelper::SdrAllFillAttributesHelper(const SfxItemSet& rSet)
89         :   maLastPaintRange(),
90             maLastDefineRange(),
91             maFillAttribute(
92                 new drawinglayer::attribute::SdrFillAttribute(
93                     drawinglayer::primitive2d::createNewSdrFillAttribute(rSet))),
94             maFillGradientAttribute(
95                 new drawinglayer::attribute::FillGradientAttribute(
96                     drawinglayer::primitive2d::createNewTransparenceGradientAttribute(rSet))),
97             maPrimitives()
98         {
99         }
100 
101         SdrAllFillAttributesHelper::~SdrAllFillAttributesHelper()
102         {
103         }
104 
105         bool SdrAllFillAttributesHelper::isUsed() const
106         {
107             // only depends on fill, FillGradientAttribute alone defines no fill
108             return maFillAttribute.get() && !maFillAttribute->isDefault();
109         }
110 
111         bool SdrAllFillAttributesHelper::isTransparent() const
112         {
113             if(hasSdrFillAttribute() && 0.0 != maFillAttribute->getTransparence())
114             {
115                 return true;
116             }
117 
118             if(hasFillGradientAttribute() && !maFillGradientAttribute->isDefault())
119             {
120                 return true;
121             }
122 
123             if(hasSdrFillAttribute())
124             {
125                 const Graphic& rGraphic = getFillAttribute().getFillGraphic().getFillGraphic();
126 
127                 return rGraphic.IsSupportedGraphic() && rGraphic.IsTransparent();
128             }
129 
130             return false;
131         }
132 
133         const drawinglayer::attribute::SdrFillAttribute& SdrAllFillAttributesHelper::getFillAttribute() const
134         {
135             if(!maFillAttribute.get())
136             {
137                 const_cast< SdrAllFillAttributesHelper* >(this)->maFillAttribute.reset(new drawinglayer::attribute::SdrFillAttribute());
138             }
139 
140             return *maFillAttribute.get();
141         }
142 
143         const drawinglayer::attribute::FillGradientAttribute& SdrAllFillAttributesHelper::getFillGradientAttribute() const
144         {
145             if(!maFillGradientAttribute.get())
146             {
147                 const_cast< SdrAllFillAttributesHelper* >(this)->maFillGradientAttribute.reset(new drawinglayer::attribute::FillGradientAttribute());
148             }
149 
150             return *maFillGradientAttribute.get();
151         }
152 
153         const drawinglayer::primitive2d::Primitive2DSequence& SdrAllFillAttributesHelper::getPrimitive2DSequence(
154             const basegfx::B2DRange& rPaintRange,
155             const basegfx::B2DRange& rDefineRange) const
156         {
157             if(maPrimitives.getLength() && (maLastPaintRange != rPaintRange || maLastDefineRange != rDefineRange))
158             {
159                 const_cast< SdrAllFillAttributesHelper* >(this)->maPrimitives.realloc(0);
160             }
161 
162             if(!maPrimitives.getLength())
163             {
164                 const_cast< SdrAllFillAttributesHelper* >(this)->createPrimitive2DSequence(rPaintRange, rDefineRange);
165             }
166 
167             return maPrimitives;
168         }
169 
170         basegfx::BColor SdrAllFillAttributesHelper::getAverageColor(const basegfx::BColor& rFallback) const
171         {
172             basegfx::BColor aRetval(rFallback);
173 
174             if(maFillAttribute.get() && !maFillAttribute->isDefault())
175             {
176                 const drawinglayer::attribute::FillGradientAttribute& rFillGradientAttribute = maFillAttribute->getGradient();
177                 const drawinglayer::attribute::FillHatchAttribute& rFillHatchAttribute = maFillAttribute->getHatch();
178                 const drawinglayer::attribute::SdrFillGraphicAttribute& rSdrFillGraphicAttribute = maFillAttribute->getFillGraphic();
179                 const drawinglayer::attribute::FillGradientAttribute& rFillTransparenceGradientAttribute = getFillGradientAttribute();
180                 double fTransparence(maFillAttribute->getTransparence());
181 
182                 if(!rFillTransparenceGradientAttribute.isDefault())
183                 {
184                     const double fTransA = rFillTransparenceGradientAttribute.getStartColor().luminance();
185                     const double fTransB = rFillTransparenceGradientAttribute.getEndColor().luminance();
186 
187                     fTransparence = (fTransA + fTransB) * 0.5;
188                 }
189 
190                 if(!rFillGradientAttribute.isDefault())
191                 {
192                     // gradient fill
193                     const basegfx::BColor& rStart = rFillGradientAttribute.getStartColor();
194                     const basegfx::BColor& rEnd = rFillGradientAttribute.getEndColor();
195 
196                     aRetval = basegfx::interpolate(rStart, rEnd, 0.5);
197                 }
198                 else if(!rFillHatchAttribute.isDefault())
199                 {
200                     // hatch fill
201                     const basegfx::BColor& rColor = rFillHatchAttribute.getColor();
202 
203                     if(rFillHatchAttribute.isFillBackground())
204                     {
205                         const basegfx::BColor& rBackgroundColor = maFillAttribute->getColor();
206 
207                         // mix colors 50%/50%
208                         aRetval = basegfx::interpolate(rColor, rBackgroundColor, 0.5);
209                     }
210                     else
211                     {
212                         // mix color with fallback color
213                         aRetval = basegfx::interpolate(rColor, rFallback, 0.5);
214                     }
215                 }
216                 else if(!rSdrFillGraphicAttribute.isDefault())
217                 {
218                     // graphic fill
219 
220                     // not used yet by purpose (see SwPageFrm::GetDrawBackgrdColor()),
221                     // use fallback (already set)
222                 }
223                 else
224                 {
225                     // color fill
226                     aRetval = maFillAttribute->getColor();
227                 }
228 
229                 if(!basegfx::fTools::equalZero(fTransparence))
230                 {
231                     // blend into transparency
232                     aRetval = basegfx::interpolate(aRetval, rFallback, fTransparence);
233                 }
234             }
235 
236             return aRetval.clamp();
237         }
238 
239         bool SdrAllFillAttributesHelper::needCompleteRepaint() const
240         {
241             if(!isUsed() || !hasSdrFillAttribute())
242             {
243                 // not used or no fill
244                 return false;
245             }
246 
247             const drawinglayer::attribute::SdrFillAttribute& rSdrFillAttribute = getFillAttribute();
248 
249             if(!rSdrFillAttribute.getHatch().isDefault())
250             {
251                 // hatch is always top-left aligned, needs no full refreshes
252                 return false;
253             }
254 
255             if(!rSdrFillAttribute.getGradient().isDefault())
256             {
257                 // gradients always scale with the object
258                 return true;
259             }
260 
261             if(!rSdrFillAttribute.getFillGraphic().isDefault())
262             {
263                 // some graphic constellations may not need this, but since most do
264                 // (stretch to fill, all but top-left aligned, ...) claim to do by default
265                 return true;
266             }
267 
268             // color fill
269             return false;
270         }
271     } // end of namespace attribute
272 } // end of namespace drawinglayer
273 
274 //////////////////////////////////////////////////////////////////////////////
275 // eof
276