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 <sal/config.h>
23 #include <basegfx/color/bcolormodifier.hxx>
24 #include <comphelper/random.hxx>
28 BColorModifier::~BColorModifier()
32 BColorModifier_gray::~BColorModifier_gray()
36 ::basegfx::BColor
BColorModifier_gray::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
38 const double fLuminance(aSourceColor
.luminance());
40 return ::basegfx::BColor(fLuminance
, fLuminance
, fLuminance
);
43 OUString
BColorModifier_gray::getModifierName() const
48 BColorModifier_invert::~BColorModifier_invert()
52 ::basegfx::BColor
BColorModifier_invert::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
54 return ::basegfx::BColor(1.0 - aSourceColor
.getRed(), 1.0 - aSourceColor
.getGreen(), 1.0 - aSourceColor
.getBlue());
57 OUString
BColorModifier_invert::getModifierName() const
59 return u
"invert"_ustr
;
62 BColorModifier_luminance_to_alpha::~BColorModifier_luminance_to_alpha()
66 ::basegfx::BColor
BColorModifier_luminance_to_alpha::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
68 const double fAlpha(1.0 - ((aSourceColor
.getRed() * 0.2125) + (aSourceColor
.getGreen() * 0.7154) + (aSourceColor
.getBlue() * 0.0721)));
70 return ::basegfx::BColor(fAlpha
, fAlpha
, fAlpha
);
73 OUString
BColorModifier_luminance_to_alpha::getModifierName() const
75 return u
"luminance_to_alpha"_ustr
;
78 BColorModifier_replace::~BColorModifier_replace()
82 bool BColorModifier_replace::operator==(const BColorModifier
& rCompare
) const
84 if (!BColorModifier::operator==(rCompare
))
87 const BColorModifier_replace
* pCompare(static_cast< const BColorModifier_replace
* >(&rCompare
));
88 return getBColor() == pCompare
->getBColor();
91 ::basegfx::BColor
BColorModifier_replace::getModifiedColor(const ::basegfx::BColor
& /*aSourceColor*/) const
96 OUString
BColorModifier_replace::getModifierName() const
98 return u
"replace"_ustr
;
101 BColorModifier_interpolate::~BColorModifier_interpolate()
105 bool BColorModifier_interpolate::operator==(const BColorModifier
& rCompare
) const
107 if (!BColorModifier::operator==(rCompare
))
110 const BColorModifier_interpolate
* pCompare(static_cast< const BColorModifier_interpolate
* >(&rCompare
));
111 return maBColor
== pCompare
->maBColor
&& mfValue
== pCompare
->mfValue
;
114 ::basegfx::BColor
BColorModifier_interpolate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
116 return interpolate(maBColor
, aSourceColor
, mfValue
);
119 OUString
BColorModifier_interpolate::getModifierName() const
121 return u
"interpolate"_ustr
;
124 BColorModifier_matrix::~BColorModifier_matrix()
128 bool BColorModifier_matrix::operator==(const BColorModifier
& rCompare
) const
130 if (!BColorModifier::operator==(rCompare
))
133 const BColorModifier_matrix
* pCompare(static_cast< const BColorModifier_matrix
* >(&rCompare
));
134 return maVector
== pCompare
->maVector
;
137 ::basegfx::BColor
BColorModifier_matrix::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
139 if (maVector
.size() != 20)
142 const double aRed
= maVector
[0] * aSourceColor
.getRed()
143 + maVector
[1] * aSourceColor
.getGreen()
144 + maVector
[2] * aSourceColor
.getBlue()
147 const double aGreen
= maVector
[5] * aSourceColor
.getRed()
148 + maVector
[6] * aSourceColor
.getGreen()
149 + maVector
[7] * aSourceColor
.getBlue()
152 const double aBlue
= maVector
[10] * aSourceColor
.getRed()
153 + maVector
[11] * aSourceColor
.getGreen()
154 + maVector
[12] * aSourceColor
.getBlue()
157 /*TODO: add support for alpha
158 const double aAlpha = maVector[15] * aSourceColor.getRed()
159 + maVector[16] * aSourceColor.getGreen()
160 + maVector[17] * aSourceColor.getBlue()
165 return ::basegfx::BColor(
166 std::clamp(aRed
, 0.0, 1.0),
167 std::clamp(aGreen
, 0.0, 1.0),
168 std::clamp(aBlue
, 0.0, 1.0));
171 OUString
BColorModifier_matrix::getModifierName() const
173 return u
"matrix"_ustr
;
176 BColorModifier_saturate::BColorModifier_saturate(double fValue
)
177 : BColorModifier(basegfx::BColorModifierType::BCMType_saturate
)
179 maSatMatrix
.set(0, 0, 0.213 + 0.787 * fValue
);
180 maSatMatrix
.set(0, 1, 0.715 - 0.715 * fValue
);
181 maSatMatrix
.set(0, 2, 0.072 - 0.072 * fValue
);
182 maSatMatrix
.set(1, 0, 0.213 - 0.213 * fValue
);
183 maSatMatrix
.set(1, 1, 0.715 + 0.285 * fValue
);
184 maSatMatrix
.set(1, 2, 0.072 - 0.072 * fValue
);
185 maSatMatrix
.set(2, 0, 0.213 - 0.213 * fValue
);
186 maSatMatrix
.set(2, 1, 0.715 - 0.715 * fValue
);
187 maSatMatrix
.set(2, 2, 0.072 + 0.928 * fValue
);
190 BColorModifier_saturate::~BColorModifier_saturate()
194 bool BColorModifier_saturate::operator==(const BColorModifier
& rCompare
) const
196 if (!BColorModifier::operator==(rCompare
))
199 const BColorModifier_saturate
* pCompare(static_cast< const BColorModifier_saturate
* >(&rCompare
));
200 return maSatMatrix
== pCompare
->maSatMatrix
;
203 ::basegfx::BColor
BColorModifier_saturate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
205 basegfx::B3DHomMatrix aColorMatrix
;
206 aColorMatrix
.set(0, 0, aSourceColor
.getRed());
207 aColorMatrix
.set(1, 0, aSourceColor
.getGreen());
208 aColorMatrix
.set(2, 0, aSourceColor
.getBlue());
210 aColorMatrix
= maSatMatrix
* aColorMatrix
;
211 return ::basegfx::BColor(aColorMatrix
.get(0, 0), aColorMatrix
.get(1, 0), aColorMatrix
.get(2, 0));
214 OUString
BColorModifier_saturate::getModifierName() const
216 return u
"saturate"_ustr
;
219 BColorModifier_hueRotate::BColorModifier_hueRotate(double fRad
)
220 : BColorModifier(basegfx::BColorModifierType::BCMType_hueRotate
)
222 const double fCos
= cos(fRad
);
223 const double fSin
= sin(fRad
);
225 maHueMatrix
.set(0, 0, 0.213 + fCos
* 0.787 - fSin
* 0.213);
226 maHueMatrix
.set(0, 1, 0.715 - fCos
* 0.715 - fSin
* 0.715);
227 maHueMatrix
.set(0, 2, 0.072 - fCos
* 0.072 + fSin
* 0.928);
228 maHueMatrix
.set(1, 0, 0.213 - fCos
* 0.213 + fSin
* 0.143);
229 maHueMatrix
.set(1, 1, 0.715 + fCos
* 0.285 + fSin
* 0.140);
230 maHueMatrix
.set(1, 2, 0.072 - fCos
* 0.072 - fSin
* 0.283);
231 maHueMatrix
.set(2, 0, 0.213 - fCos
* 0.213 - fSin
* 0.787);
232 maHueMatrix
.set(2, 1, 0.715 - fCos
* 0.715 + fSin
* 0.715);
233 maHueMatrix
.set(2, 2, 0.072 + fCos
* 0.928 + fSin
* 0.072);
236 BColorModifier_hueRotate::~BColorModifier_hueRotate()
240 bool BColorModifier_hueRotate::operator==(const BColorModifier
& rCompare
) const
242 if (!BColorModifier::operator==(rCompare
))
245 const BColorModifier_hueRotate
* pCompare(static_cast< const BColorModifier_hueRotate
* >(&rCompare
));
246 return maHueMatrix
== pCompare
->maHueMatrix
;
249 ::basegfx::BColor
BColorModifier_hueRotate::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
251 basegfx::B3DHomMatrix aColorMatrix
;
252 aColorMatrix
.set(0, 0, aSourceColor
.getRed());
253 aColorMatrix
.set(1, 0, aSourceColor
.getGreen());
254 aColorMatrix
.set(2, 0, aSourceColor
.getBlue());
256 aColorMatrix
= maHueMatrix
* aColorMatrix
;
257 return ::basegfx::BColor(
258 std::clamp(aColorMatrix
.get(0, 0), 0.0, 1.0),
259 std::clamp(aColorMatrix
.get(1, 0), 0.0, 1.0),
260 std::clamp(aColorMatrix
.get(2, 0), 0.0, 1.0));
263 OUString
BColorModifier_hueRotate::getModifierName() const
265 return u
"hueRotate"_ustr
;
268 BColorModifier_black_and_white::~BColorModifier_black_and_white()
272 bool BColorModifier_black_and_white::operator==(const BColorModifier
& rCompare
) const
274 if (!BColorModifier::operator==(rCompare
))
277 const BColorModifier_black_and_white
* pCompare(static_cast< const BColorModifier_black_and_white
* >(&rCompare
));
278 return mfValue
== pCompare
->mfValue
;
281 ::basegfx::BColor
BColorModifier_black_and_white::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
283 const double fLuminance(aSourceColor
.luminance());
285 if(fLuminance
< mfValue
)
287 return ::basegfx::BColor::getEmptyBColor();
291 return ::basegfx::BColor(1.0, 1.0, 1.0);
295 OUString
BColorModifier_black_and_white::getModifierName() const
297 return u
"black_and_white"_ustr
;
300 BColorModifier_gamma::BColorModifier_gamma(double fValue
)
301 : BColorModifier(basegfx::BColorModifierType::BCMType_gamma
)
304 , mbUseIt(!basegfx::fTools::equal(fValue
, 1.0) && fValue
> 0.0 && basegfx::fTools::lessOrEqual(fValue
, 10.0))
308 mfInvValue
= 1.0 / mfValue
;
312 BColorModifier_gamma::~BColorModifier_gamma()
316 bool BColorModifier_gamma::operator==(const BColorModifier
& rCompare
) const
318 if (!BColorModifier::operator==(rCompare
))
321 const BColorModifier_gamma
* pCompare(static_cast< const BColorModifier_gamma
* >(&rCompare
));
323 // mfValue is sufficient, mfInvValue and mbUseIt are only helper values
324 return mfValue
== pCompare
->mfValue
;
327 ::basegfx::BColor
BColorModifier_gamma::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
331 ::basegfx::BColor
aRetval(
332 pow(aSourceColor
.getRed(), mfInvValue
),
333 pow(aSourceColor
.getGreen(), mfInvValue
),
334 pow(aSourceColor
.getBlue(), mfInvValue
));
345 OUString
BColorModifier_gamma::getModifierName() const
347 return u
"gamma"_ustr
;
350 BColorModifier_RGBLuminanceContrast::BColorModifier_RGBLuminanceContrast(double fRed
, double fGreen
, double fBlue
, double fLuminance
, double fContrast
)
351 : BColorModifier(basegfx::BColorModifierType::BCMType_RGBLuminanceContrast
)
352 , mfRed(std::clamp(fRed
, -1.0, 1.0))
353 , mfGreen(std::clamp(fGreen
, -1.0, 1.0))
354 , mfBlue(std::clamp(fBlue
, -1.0, 1.0))
355 , mfLuminance(std::clamp(fLuminance
, -1.0, 1.0))
356 , mfContrast(std::clamp(fContrast
, -1.0, 1.0))
363 if(basegfx::fTools::equalZero(mfRed
)
364 && basegfx::fTools::equalZero(mfGreen
)
365 && basegfx::fTools::equalZero(mfBlue
)
366 && basegfx::fTools::equalZero(mfLuminance
)
367 && basegfx::fTools::equalZero(mfContrast
))
371 if(mfContrast
>= 0.0)
373 mfContrastOff
= 128.0 / (128.0 - (mfContrast
* 127.0));
377 mfContrastOff
= ( 128.0 + (mfContrast
* 127.0)) / 128.0;
380 // calculate unified contrast offset
381 const double fPreparedContrastOff((128.0 - mfContrastOff
* 128.0) / 255.0);
382 const double fCombinedOffset(mfLuminance
+ fPreparedContrastOff
);
385 mfRedOff
= mfRed
+ fCombinedOffset
;
386 mfGreenOff
= mfGreen
+ fCombinedOffset
;
387 mfBlueOff
= mfBlue
+ fCombinedOffset
;
392 BColorModifier_RGBLuminanceContrast::~BColorModifier_RGBLuminanceContrast()
396 bool BColorModifier_RGBLuminanceContrast::operator==(const BColorModifier
& rCompare
) const
398 if (!BColorModifier::operator==(rCompare
))
401 const BColorModifier_RGBLuminanceContrast
* pCompare(static_cast< const BColorModifier_RGBLuminanceContrast
* >(&rCompare
));
403 // no need to compare other values, these are just helpers
404 return mfRed
== pCompare
->mfRed
405 && mfGreen
== pCompare
->mfGreen
406 && mfBlue
== pCompare
->mfBlue
407 && mfLuminance
== pCompare
->mfLuminance
408 && mfContrast
== pCompare
->mfContrast
;
411 ::basegfx::BColor
BColorModifier_RGBLuminanceContrast::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
415 return basegfx::BColor(
416 std::clamp(aSourceColor
.getRed() * mfContrastOff
+ mfRedOff
, 0.0, 1.0),
417 std::clamp(aSourceColor
.getGreen() * mfContrastOff
+ mfGreenOff
, 0.0, 1.0),
418 std::clamp(aSourceColor
.getBlue() * mfContrastOff
+ mfBlueOff
, 0.0, 1.0));
426 OUString
BColorModifier_RGBLuminanceContrast::getModifierName() const
428 return u
"RGBLuminanceContrast"_ustr
;
431 BColorModifier_randomize::BColorModifier_randomize(double fRandomPart
)
432 : BColorModifier(basegfx::BColorModifierType::BCMType_randomize
)
433 , mfRandomPart(fRandomPart
)
437 BColorModifier_randomize::~BColorModifier_randomize()
442 bool BColorModifier_randomize::operator==(const BColorModifier
& rCompare
) const
444 if (!BColorModifier::operator==(rCompare
))
447 const BColorModifier_randomize
* pCompare(static_cast< const BColorModifier_randomize
* >(&rCompare
));
448 return mfRandomPart
== pCompare
->mfRandomPart
;
451 // compute modified color
452 ::basegfx::BColor
BColorModifier_randomize::getModifiedColor(const ::basegfx::BColor
& aSourceColor
) const
454 if(0.0 >= mfRandomPart
)
456 // no randomizing, use orig color
460 if(1.0 <= mfRandomPart
)
462 // full randomized color
463 return basegfx::BColor(
464 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)),
465 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)),
466 comphelper::rng::uniform_real_distribution(0.0, nextafter(1.0, DBL_MAX
)));
470 const double fMulA(1.0 - mfRandomPart
);
471 return basegfx::BColor(
472 aSourceColor
.getRed() * fMulA
+
473 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)),
474 aSourceColor
.getGreen() * fMulA
+
475 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)),
476 aSourceColor
.getBlue() * fMulA
+
477 comphelper::rng::uniform_real_distribution(0.0, nextafter(mfRandomPart
, DBL_MAX
)));
480 OUString
BColorModifier_randomize::getModifierName() const
482 return u
"randomize"_ustr
;
485 ::basegfx::BColor
BColorModifierStack::getModifiedColor(const ::basegfx::BColor
& rSource
) const
487 if(maBColorModifiers
.empty())
492 ::basegfx::BColor
aRetval(rSource
);
494 for(sal_uInt32
a(maBColorModifiers
.size()); a
;)
497 aRetval
= maBColorModifiers
[a
]->getModifiedColor(aRetval
);
503 bool BColorModifierStack::operator==(const BColorModifierStack
& rComp
) const
505 if (count() != rComp
.count())
511 for (sal_uInt32
a(0); a
< count(); a
++)
513 // nullptrs are not allowed/expected
514 assert(maBColorModifiers
[a
] != nullptr);
515 assert(rComp
.maBColorModifiers
[a
] != nullptr);
517 if (!(*maBColorModifiers
[a
] == *rComp
.maBColorModifiers
[a
]))
523 } // end of namespace basegfx
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */