/src/libreoffice/drawinglayer/source/texture/texture3d.cxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <algorithm> |
23 | | |
24 | | #include <texture/texture3d.hxx> |
25 | | #include <vcl/BitmapReadAccess.hxx> |
26 | | #include <vcl/BitmapTools.hxx> |
27 | | #include <primitive3d/hatchtextureprimitive3d.hxx> |
28 | | #include <sal/log.hxx> |
29 | | #include <osl/diagnose.h> |
30 | | |
31 | | namespace drawinglayer::texture |
32 | | { |
33 | | GeoTexSvxMono::GeoTexSvxMono( |
34 | | const basegfx::BColor& rSingleColor, |
35 | | double fOpacity) |
36 | 0 | : maSingleColor(rSingleColor), |
37 | 0 | mfOpacity(fOpacity) |
38 | 0 | { |
39 | 0 | } |
40 | | |
41 | | bool GeoTexSvxMono::operator==(const GeoTexSvx& rGeoTexSvx) const |
42 | 0 | { |
43 | 0 | const GeoTexSvxMono* pCompare = dynamic_cast< const GeoTexSvxMono* >(&rGeoTexSvx); |
44 | |
|
45 | 0 | return (pCompare |
46 | 0 | && maSingleColor == pCompare->maSingleColor |
47 | 0 | && mfOpacity == pCompare->mfOpacity); |
48 | 0 | } |
49 | | |
50 | | void GeoTexSvxMono::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const |
51 | 0 | { |
52 | 0 | rBColor = maSingleColor; |
53 | 0 | } |
54 | | |
55 | | void GeoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& /*rUV*/, double& rfOpacity) const |
56 | 0 | { |
57 | 0 | rfOpacity = mfOpacity; |
58 | 0 | } |
59 | | |
60 | | |
61 | | GeoTexSvxBitmapEx::GeoTexSvxBitmapEx( |
62 | | const BitmapEx& rBitmapEx, |
63 | | const basegfx::B2DRange& rRange) |
64 | 0 | : maBitmapEx(rBitmapEx), |
65 | 0 | maTopLeft(rRange.getMinimum()), |
66 | 0 | maSize(rRange.getRange()), |
67 | 0 | mfMulX(0.0), |
68 | 0 | mfMulY(0.0) |
69 | 0 | { |
70 | 0 | bool bIsAlpha(maBitmapEx.IsAlpha()); |
71 | 0 | if(vcl::bitmap::convertBitmap32To24Plus8(maBitmapEx,maBitmapEx)) |
72 | 0 | bIsAlpha = maBitmapEx.IsAlpha(); |
73 | | // #121194# Todo: use alpha channel, too (for 3d) |
74 | 0 | maBitmap = maBitmapEx.GetBitmap(); |
75 | |
|
76 | 0 | if (bIsAlpha) |
77 | 0 | { |
78 | 0 | maTransparence = rBitmapEx.GetAlphaMask().GetBitmap(); |
79 | 0 | mpReadTransparence = maTransparence; |
80 | 0 | OSL_ENSURE(mpReadTransparence, "OOps, transparence type Bitmap, but no read access created in the constructor (?)"); |
81 | 0 | } |
82 | |
|
83 | 0 | if (!maBitmap.IsEmpty()) |
84 | 0 | mpReadBitmap = maBitmap; |
85 | 0 | SAL_WARN_IF(!mpReadBitmap, "drawinglayer", "GeoTexSvxBitmapEx: Got no read access to Bitmap"); |
86 | 0 | if (mpReadBitmap) |
87 | 0 | { |
88 | 0 | mfMulX = static_cast<double>(mpReadBitmap->Width()) / maSize.getX(); |
89 | 0 | mfMulY = static_cast<double>(mpReadBitmap->Height()) / maSize.getY(); |
90 | 0 | } |
91 | |
|
92 | 0 | if(maSize.getX() <= 1.0) |
93 | 0 | { |
94 | 0 | maSize.setX(1.0); |
95 | 0 | } |
96 | |
|
97 | 0 | if(maSize.getY() <= 1.0) |
98 | 0 | { |
99 | 0 | maSize.setY(1.0); |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | GeoTexSvxBitmapEx::~GeoTexSvxBitmapEx() |
104 | 0 | { |
105 | 0 | } |
106 | | |
107 | | //static |
108 | | sal_uInt8 GeoTexSvxBitmapEx::impGetAlpha(const BitmapReadAccess& readTransparence, sal_Int32 rX, sal_Int32 rY) |
109 | 0 | { |
110 | 0 | const BitmapColor aBitmapColor(readTransparence.GetPixel(rY, rX)); |
111 | 0 | return aBitmapColor.GetIndex(); |
112 | 0 | } |
113 | | |
114 | | bool GeoTexSvxBitmapEx::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const |
115 | 0 | { |
116 | 0 | if(mpReadBitmap) |
117 | 0 | { |
118 | 0 | rX = static_cast<sal_Int32>((rUV.getX() - maTopLeft.getX()) * mfMulX); |
119 | |
|
120 | 0 | if(rX >= 0 && rX < mpReadBitmap->Width()) |
121 | 0 | { |
122 | 0 | rY = static_cast<sal_Int32>((rUV.getY() - maTopLeft.getY()) * mfMulY); |
123 | |
|
124 | 0 | return (rY >= 0 && rY < mpReadBitmap->Height()); |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | 0 | return false; |
129 | 0 | } |
130 | | |
131 | | void GeoTexSvxBitmapEx::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const |
132 | 0 | { |
133 | 0 | sal_Int32 nX, nY; |
134 | |
|
135 | 0 | if(impIsValid(rUV, nX, nY)) |
136 | 0 | { |
137 | 0 | const double fConvertColor(1.0 / 255.0); |
138 | 0 | const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX)); |
139 | 0 | const basegfx::BColor aBSource( |
140 | 0 | static_cast<double>(aBMCol.GetRed()) * fConvertColor, |
141 | 0 | static_cast<double>(aBMCol.GetGreen()) * fConvertColor, |
142 | 0 | static_cast<double>(aBMCol.GetBlue()) * fConvertColor); |
143 | |
|
144 | 0 | rBColor = aBSource; |
145 | |
|
146 | 0 | if (mpReadTransparence) |
147 | 0 | { |
148 | | // when we have alpha, make use of it |
149 | 0 | const sal_uInt8 aAlpha(impGetAlpha(*mpReadTransparence, nX, nY)); |
150 | |
|
151 | 0 | rfOpacity = (static_cast<double>(aAlpha) * (1.0 / 255.0)); |
152 | 0 | } |
153 | 0 | else |
154 | 0 | { |
155 | 0 | rfOpacity = 1.0; |
156 | 0 | } |
157 | 0 | } |
158 | 0 | else |
159 | 0 | { |
160 | 0 | rfOpacity = 0.0; |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | void GeoTexSvxBitmapEx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const |
165 | 0 | { |
166 | 0 | sal_Int32 nX, nY; |
167 | |
|
168 | 0 | if(impIsValid(rUV, nX, nY)) |
169 | 0 | { |
170 | 0 | if (mpReadTransparence) |
171 | 0 | { |
172 | | // this texture has an alpha part, use it |
173 | 0 | const sal_uInt8 aAlpha(impGetAlpha(*mpReadTransparence, nX, nY)); |
174 | 0 | const double fNewOpacity(static_cast<double>(aAlpha) * (1.0 / 255.0)); |
175 | |
|
176 | 0 | rfOpacity = 1.0 - ((1.0 - fNewOpacity) * (1.0 - rfOpacity)); |
177 | 0 | } |
178 | 0 | else |
179 | 0 | { |
180 | | // this texture is a color bitmap used as transparence map |
181 | 0 | const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX)); |
182 | 0 | const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue()); |
183 | |
|
184 | 0 | rfOpacity = (static_cast<double>(0xff - aColor.GetLuminance()) * (1.0 / 255.0)); |
185 | 0 | } |
186 | 0 | } |
187 | 0 | else |
188 | 0 | { |
189 | 0 | rfOpacity = 0.0; |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | |
194 | | basegfx::B2DPoint GeoTexSvxBitmapExTiled::impGetCorrected(const basegfx::B2DPoint& rUV) const |
195 | 0 | { |
196 | 0 | double fX(rUV.getX() - maTopLeft.getX()); |
197 | 0 | double fY(rUV.getY() - maTopLeft.getY()); |
198 | |
|
199 | 0 | if(mbUseOffsetX) |
200 | 0 | { |
201 | 0 | const sal_Int32 nCol(static_cast< sal_Int32 >((fY < 0.0 ? maSize.getY() -fY : fY) / maSize.getY())); |
202 | |
|
203 | 0 | if(nCol % 2) |
204 | 0 | { |
205 | 0 | fX += mfOffsetX * maSize.getX(); |
206 | 0 | } |
207 | 0 | } |
208 | 0 | else if(mbUseOffsetY) |
209 | 0 | { |
210 | 0 | const sal_Int32 nRow(static_cast< sal_Int32 >((fX < 0.0 ? maSize.getX() -fX : fX) / maSize.getX())); |
211 | |
|
212 | 0 | if(nRow % 2) |
213 | 0 | { |
214 | 0 | fY += mfOffsetY * maSize.getY(); |
215 | 0 | } |
216 | 0 | } |
217 | |
|
218 | 0 | fX = fmod(fX, maSize.getX()); |
219 | 0 | fY = fmod(fY, maSize.getY()); |
220 | |
|
221 | 0 | if(fX < 0.0) |
222 | 0 | { |
223 | 0 | fX += maSize.getX(); |
224 | 0 | } |
225 | |
|
226 | 0 | if(fY < 0.0) |
227 | 0 | { |
228 | 0 | fY += maSize.getY(); |
229 | 0 | } |
230 | |
|
231 | 0 | return basegfx::B2DPoint(fX + maTopLeft.getX(), fY + maTopLeft.getY()); |
232 | 0 | } |
233 | | |
234 | | GeoTexSvxBitmapExTiled::GeoTexSvxBitmapExTiled( |
235 | | const BitmapEx& rBitmapEx, |
236 | | const basegfx::B2DRange& rRange, |
237 | | double fOffsetX, |
238 | | double fOffsetY) |
239 | 0 | : GeoTexSvxBitmapEx(rBitmapEx, rRange), |
240 | 0 | mfOffsetX(std::clamp(fOffsetX, 0.0, 1.0)), |
241 | 0 | mfOffsetY(std::clamp(fOffsetY, 0.0, 1.0)), |
242 | 0 | mbUseOffsetX(!basegfx::fTools::equalZero(mfOffsetX)), |
243 | 0 | mbUseOffsetY(!mbUseOffsetX && !basegfx::fTools::equalZero(mfOffsetY)) |
244 | 0 | { |
245 | 0 | } |
246 | | |
247 | | void GeoTexSvxBitmapExTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const |
248 | 0 | { |
249 | 0 | if(mpReadBitmap) |
250 | 0 | { |
251 | 0 | GeoTexSvxBitmapEx::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity); |
252 | 0 | } |
253 | 0 | } |
254 | | |
255 | | void GeoTexSvxBitmapExTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const |
256 | 0 | { |
257 | 0 | if(mpReadBitmap) |
258 | 0 | { |
259 | 0 | GeoTexSvxBitmapEx::modifyOpacity(impGetCorrected(rUV), rfOpacity); |
260 | 0 | } |
261 | 0 | } |
262 | | |
263 | | |
264 | | GeoTexSvxMultiHatch::GeoTexSvxMultiHatch( |
265 | | const primitive3d::HatchTexturePrimitive3D& rPrimitive, |
266 | | double fLogicPixelSize) |
267 | 0 | : mfLogicPixelSize(fLogicPixelSize) |
268 | 0 | { |
269 | 0 | const attribute::FillHatchAttribute& rHatch(rPrimitive.getHatch()); |
270 | 0 | const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY()); |
271 | 0 | const double fAngleA(rHatch.getAngle()); |
272 | 0 | maColor = rHatch.getColor(); |
273 | 0 | mbFillBackground = rHatch.isFillBackground(); |
274 | 0 | mp0.reset( new GeoTexSvxHatch( |
275 | 0 | aOutlineRange, |
276 | 0 | aOutlineRange, |
277 | 0 | rHatch.getDistance(), |
278 | 0 | fAngleA) ); |
279 | |
|
280 | 0 | if(attribute::HatchStyle::Double == rHatch.getStyle() || attribute::HatchStyle::Triple == rHatch.getStyle()) |
281 | 0 | { |
282 | 0 | mp1.reset( new GeoTexSvxHatch( |
283 | 0 | aOutlineRange, |
284 | 0 | aOutlineRange, |
285 | 0 | rHatch.getDistance(), |
286 | 0 | fAngleA + M_PI_2) ); |
287 | 0 | } |
288 | |
|
289 | 0 | if(attribute::HatchStyle::Triple == rHatch.getStyle()) |
290 | 0 | { |
291 | 0 | mp2.reset( new GeoTexSvxHatch( |
292 | 0 | aOutlineRange, |
293 | 0 | aOutlineRange, |
294 | 0 | rHatch.getDistance(), |
295 | 0 | fAngleA + M_PI_4) ); |
296 | 0 | } |
297 | 0 | } |
298 | | |
299 | | GeoTexSvxMultiHatch::~GeoTexSvxMultiHatch() |
300 | 0 | { |
301 | 0 | } |
302 | | |
303 | | bool GeoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const |
304 | 0 | { |
305 | 0 | if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize) |
306 | 0 | { |
307 | 0 | return true; |
308 | 0 | } |
309 | | |
310 | 0 | if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize) |
311 | 0 | { |
312 | 0 | return true; |
313 | 0 | } |
314 | | |
315 | 0 | if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize) |
316 | 0 | { |
317 | 0 | return true; |
318 | 0 | } |
319 | | |
320 | 0 | return false; |
321 | 0 | } |
322 | | |
323 | | void GeoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const |
324 | 0 | { |
325 | 0 | if(impIsOnHatch(rUV)) |
326 | 0 | { |
327 | 0 | rBColor = maColor; |
328 | 0 | } |
329 | 0 | else if(!mbFillBackground) |
330 | 0 | { |
331 | 0 | rfOpacity = 0.0; |
332 | 0 | } |
333 | 0 | } |
334 | | |
335 | | void GeoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const |
336 | 0 | { |
337 | 0 | if(mbFillBackground || impIsOnHatch(rUV)) |
338 | 0 | { |
339 | 0 | rfOpacity = 1.0; |
340 | 0 | } |
341 | 0 | else |
342 | 0 | { |
343 | 0 | rfOpacity = 0.0; |
344 | 0 | } |
345 | 0 | } |
346 | | |
347 | | } // end of namespace |
348 | | |
349 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |