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_drawinglayer.hxx"
26 
27 #include <drawinglayer/texture/texture3d.hxx>
28 #include <vcl/bmpacc.hxx>
29 #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
30 
31 //////////////////////////////////////////////////////////////////////////////
32 
33 namespace drawinglayer
34 {
35     namespace texture
36     {
GeoTexSvxMono(const basegfx::BColor & rSingleColor,double fOpacity)37         GeoTexSvxMono::GeoTexSvxMono(
38             const basegfx::BColor& rSingleColor,
39             double fOpacity)
40         :	maSingleColor(rSingleColor),
41             mfOpacity(fOpacity)
42         {
43         }
44 
operator ==(const GeoTexSvx & rGeoTexSvx) const45         bool GeoTexSvxMono::operator==(const GeoTexSvx& rGeoTexSvx) const
46         {
47             const GeoTexSvxMono* pCompare = dynamic_cast< const GeoTexSvxMono* >(&rGeoTexSvx);
48 
49             return (pCompare
50                 && maSingleColor == pCompare->maSingleColor
51                 && mfOpacity == pCompare->mfOpacity);
52         }
53 
modifyBColor(const basegfx::B2DPoint &,basegfx::BColor & rBColor,double &) const54         void GeoTexSvxMono::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
55         {
56             rBColor = maSingleColor;
57         }
58 
modifyOpacity(const basegfx::B2DPoint &,double & rfOpacity) const59         void GeoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& /*rUV*/, double& rfOpacity) const
60         {
61             rfOpacity = mfOpacity;
62         }
63     } // end of namespace texture
64 } // end of namespace drawinglayer
65 
66 //////////////////////////////////////////////////////////////////////////////
67 
68 namespace drawinglayer
69 {
70     namespace texture
71     {
GeoTexSvxBitmapEx(const BitmapEx & rBitmapEx,const basegfx::B2DRange & rRange)72         GeoTexSvxBitmapEx::GeoTexSvxBitmapEx(
73             const BitmapEx& rBitmapEx,
74             const basegfx::B2DRange& rRange)
75         :	maBitmapEx(rBitmapEx),
76             mpReadBitmap(0),
77             maTransparence(),
78             mpReadTransparence(0),
79             maTopLeft(rRange.getMinimum()),
80             maSize(rRange.getRange()),
81             mfMulX(0.0),
82             mfMulY(0.0),
83             mbIsAlpha(false),
84             mbIsTransparent(maBitmapEx.IsTransparent())
85         {
86             // #121194# Todo: use alpha channel, too (for 3d)
87             mpReadBitmap = maBitmapEx.GetBitmap().AcquireReadAccess();
88             OSL_ENSURE(mpReadBitmap, "GeoTexSvxBitmapEx: Got no read access to Bitmap (!)");
89 
90             if(mbIsTransparent)
91             {
92                 if(maBitmapEx.IsAlpha())
93                 {
94                     mbIsAlpha = true;
95                     maTransparence = rBitmapEx.GetAlpha().GetBitmap();
96                 }
97                 else
98                 {
99                     maTransparence = rBitmapEx.GetMask();
100                 }
101 
102                 mpReadTransparence = maTransparence.AcquireReadAccess();
103             }
104 
105             mfMulX = (double)mpReadBitmap->Width() / maSize.getX();
106             mfMulY = (double)mpReadBitmap->Height() / maSize.getY();
107 
108             if(maSize.getX() <= 1.0)
109             {
110                 maSize.setX(1.0);
111             }
112 
113             if(maSize.getY() <= 1.0)
114             {
115                 maSize.setY(1.0);
116             }
117         }
118 
~GeoTexSvxBitmapEx()119         GeoTexSvxBitmapEx::~GeoTexSvxBitmapEx()
120         {
121             delete mpReadTransparence;
122             delete mpReadBitmap;
123         }
124 
impGetTransparence(sal_Int32 & rX,sal_Int32 & rY) const125         sal_uInt8 GeoTexSvxBitmapEx::impGetTransparence(sal_Int32& rX, sal_Int32& rY) const
126         {
127             switch(maBitmapEx.GetTransparentType())
128             {
129                 case TRANSPARENT_NONE:
130                 {
131                     break;
132                 }
133                 case TRANSPARENT_COLOR:
134                 {
135                     const BitmapColor aBitmapColor(mpReadBitmap->GetColor(rY, rX));
136 
137                     if(maBitmapEx.GetTransparentColor() == aBitmapColor.operator Color())
138                     {
139                         return 255;
140                     }
141 
142                     break;
143                 }
144                 case TRANSPARENT_BITMAP:
145                 {
146                     OSL_ENSURE(mpReadTransparence, "OOps, transparence type Bitmap, but no read access created in the constructor (?)");
147                     const BitmapColor aBitmapColor(mpReadTransparence->GetPixel(rY, rX));
148 
149                     if(mbIsAlpha)
150                     {
151                         return aBitmapColor.GetIndex();
152                     }
153                     else
154                     {
155                         if(0x00 != aBitmapColor.GetIndex())
156                         {
157                             return 255;
158                         }
159                     }
160                     break;
161                 }
162             }
163 
164             return 0;
165         }
166 
impIsValid(const basegfx::B2DPoint & rUV,sal_Int32 & rX,sal_Int32 & rY) const167         bool GeoTexSvxBitmapEx::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const
168         {
169             if(mpReadBitmap)
170             {
171                 rX = (sal_Int32)((rUV.getX() - maTopLeft.getX()) * mfMulX);
172 
173                 if(rX >= 0L && rX < mpReadBitmap->Width())
174                 {
175                     rY = (sal_Int32)((rUV.getY() - maTopLeft.getY()) * mfMulY);
176 
177                     return (rY >= 0L && rY < mpReadBitmap->Height());
178                 }
179             }
180 
181             return false;
182         }
183 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double & rfOpacity) const184         void GeoTexSvxBitmapEx::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
185         {
186             sal_Int32 nX, nY;
187 
188             if(impIsValid(rUV, nX, nY))
189             {
190                 const double fConvertColor(1.0 / 255.0);
191                 const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
192                 const basegfx::BColor aBSource(
193                     (double)aBMCol.GetRed() * fConvertColor,
194                     (double)aBMCol.GetGreen() * fConvertColor,
195                     (double)aBMCol.GetBlue() * fConvertColor);
196 
197                 rBColor = aBSource;
198 
199                 if(mbIsTransparent)
200                 {
201                     // when we have a transparence, make use of it
202                     const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
203 
204                     rfOpacity = ((double)(0xff - aLuminance) * (1.0 / 255.0));
205                 }
206                 else
207                 {
208                     rfOpacity = 1.0;
209                 }
210             }
211             else
212             {
213                 rfOpacity = 0.0;
214             }
215         }
216 
modifyOpacity(const basegfx::B2DPoint & rUV,double & rfOpacity) const217         void GeoTexSvxBitmapEx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
218         {
219             sal_Int32 nX, nY;
220 
221             if(impIsValid(rUV, nX, nY))
222             {
223                 if(mbIsTransparent)
224                 {
225                     // this texture has an alpha part, use it
226                     const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
227                     const double fNewOpacity((double)(0xff - aLuminance) * (1.0 / 255.0));
228 
229                     rfOpacity = 1.0 - ((1.0 - fNewOpacity) * (1.0 - rfOpacity));
230                 }
231                 else
232                 {
233                     // this texture is a color bitmap used as transparence map
234                     const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
235                     const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue());
236 
237                     rfOpacity = ((double)(0xff - aColor.GetLuminance()) * (1.0 / 255.0));
238                 }
239             }
240             else
241             {
242                 rfOpacity = 0.0;
243             }
244         }
245     } // end of namespace texture
246 } // end of namespace drawinglayer
247 
248 //////////////////////////////////////////////////////////////////////////////
249 
250 namespace drawinglayer
251 {
252     namespace texture
253     {
impGetCorrected(const basegfx::B2DPoint & rUV) const254         basegfx::B2DPoint GeoTexSvxBitmapExTiled::impGetCorrected(const basegfx::B2DPoint& rUV) const
255         {
256             double fX(rUV.getX() - maTopLeft.getX());
257             double fY(rUV.getY() - maTopLeft.getY());
258 
259             if(mbUseOffsetX)
260             {
261                 const sal_Int32 nCol(static_cast< sal_Int32 >((fY < 0.0 ? maSize.getY() -fY : fY) / maSize.getY()));
262 
263                 if(nCol % 2)
264                 {
265                     fX += mfOffsetX * maSize.getX();
266                 }
267             }
268             else if(mbUseOffsetY)
269             {
270                 const sal_Int32 nRow(static_cast< sal_Int32 >((fX < 0.0 ? maSize.getX() -fX : fX) / maSize.getX()));
271 
272                 if(nRow % 2)
273                 {
274                     fY += mfOffsetY * maSize.getY();
275                 }
276             }
277 
278             fX = fmod(fX, maSize.getX());
279             fY = fmod(fY, maSize.getY());
280 
281             if(fX < 0.0)
282             {
283                 fX += maSize.getX();
284             }
285 
286             if(fY < 0.0)
287             {
288                 fY += maSize.getY();
289             }
290 
291             return basegfx::B2DPoint(fX + maTopLeft.getX(), fY + maTopLeft.getY());
292         }
293 
GeoTexSvxBitmapExTiled(const BitmapEx & rBitmapEx,const basegfx::B2DRange & rRange,double fOffsetX,double fOffsetY)294         GeoTexSvxBitmapExTiled::GeoTexSvxBitmapExTiled(
295             const BitmapEx& rBitmapEx,
296             const basegfx::B2DRange& rRange,
297             double fOffsetX,
298             double fOffsetY)
299         :	GeoTexSvxBitmapEx(rBitmapEx, rRange),
300             mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)),
301             mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0)),
302             mbUseOffsetX(!basegfx::fTools::equalZero(mfOffsetX)),
303             mbUseOffsetY(!mbUseOffsetX && !basegfx::fTools::equalZero(mfOffsetY))
304         {
305         }
306 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double & rfOpacity) const307         void GeoTexSvxBitmapExTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
308         {
309             if(mpReadBitmap)
310             {
311                 GeoTexSvxBitmapEx::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity);
312             }
313         }
314 
modifyOpacity(const basegfx::B2DPoint & rUV,double & rfOpacity) const315         void GeoTexSvxBitmapExTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
316         {
317             if(mpReadBitmap)
318             {
319                 GeoTexSvxBitmapEx::modifyOpacity(impGetCorrected(rUV), rfOpacity);
320             }
321         }
322     } // end of namespace texture
323 } // end of namespace drawinglayer
324 
325 //////////////////////////////////////////////////////////////////////////////
326 
327 namespace drawinglayer
328 {
329     namespace texture
330     {
GeoTexSvxMultiHatch(const primitive3d::HatchTexturePrimitive3D & rPrimitive,double fLogicPixelSize)331         GeoTexSvxMultiHatch::GeoTexSvxMultiHatch(
332             const primitive3d::HatchTexturePrimitive3D& rPrimitive,
333             double fLogicPixelSize)
334         :	mfLogicPixelSize(fLogicPixelSize),
335             mp0(0L),
336             mp1(0L),
337             mp2(0L)
338         {
339             const attribute::FillHatchAttribute& rHatch(rPrimitive.getHatch());
340             const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
341             const double fAngleA(rHatch.getAngle());
342             maColor = rHatch.getColor();
343             mbFillBackground = rHatch.isFillBackground();
344             mp0 = new GeoTexSvxHatch(
345                 aOutlineRange,
346                 aOutlineRange,
347                 rHatch.getDistance(),
348                 fAngleA);
349 
350             if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
351             {
352                 mp1 = new GeoTexSvxHatch(
353                     aOutlineRange,
354                     aOutlineRange,
355                     rHatch.getDistance(),
356                     fAngleA + F_PI2);
357             }
358 
359             if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
360             {
361                 mp2 = new GeoTexSvxHatch(
362                     aOutlineRange,
363                     aOutlineRange,
364                     rHatch.getDistance(),
365                     fAngleA + F_PI4);
366             }
367         }
368 
~GeoTexSvxMultiHatch()369         GeoTexSvxMultiHatch::~GeoTexSvxMultiHatch()
370         {
371             delete mp0;
372             delete mp1;
373             delete mp2;
374         }
375 
impIsOnHatch(const basegfx::B2DPoint & rUV) const376         bool GeoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const
377         {
378             if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize)
379             {
380                 return true;
381             }
382 
383             if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize)
384             {
385                 return true;
386             }
387 
388             if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize)
389             {
390                 return true;
391             }
392 
393             return false;
394         }
395 
modifyBColor(const basegfx::B2DPoint & rUV,basegfx::BColor & rBColor,double & rfOpacity) const396         void GeoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
397         {
398             if(impIsOnHatch(rUV))
399             {
400                 rBColor = maColor;
401             }
402             else if(!mbFillBackground)
403             {
404                 rfOpacity = 0.0;
405             }
406         }
407 
modifyOpacity(const basegfx::B2DPoint & rUV,double & rfOpacity) const408         void GeoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
409         {
410             if(mbFillBackground || impIsOnHatch(rUV))
411             {
412                 rfOpacity = 1.0;
413             }
414             else
415             {
416                 rfOpacity = 0.0;
417             }
418         }
419     } // end of namespace texture
420 } // end of namespace drawinglayer
421 
422 //////////////////////////////////////////////////////////////////////////////
423 // eof
424