Commit 510f039c authored by L. E. Segovia's avatar L. E. Segovia

Merge branch 'krita/4.3' into amyspark/T13097-gsoc2020-seexpr

parents 246d9db1 c4d0924a
......@@ -18,8 +18,12 @@
#ifndef KISCPPQUIRKS_H
#define KISCPPQUIRKS_H
#include <type_traits>
namespace std {
// from C++14
#if __cplusplus < 201402L
template <typename Cont>
......@@ -38,6 +42,18 @@ inline reverse_iterator<BidirectionalIterator> make_reverse_iterator(Bidirection
return reverse_iterator<BidirectionalIterator>(x);
}
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
#endif
// from C++17
#if __cplusplus < 201703L
template<typename...>
using void_t = void;
#endif
}
......
......@@ -495,7 +495,8 @@ inline bool KisPainter::Private::tryReduceSourceRect(const KisPaintDevice *srcDe
* We should also crop the blitted area by the selected region,
* because we cannot paint outside the selection.
*/
*srcRect &= selection->selectedRect();
*srcRect &= selection->selectedRect().translated(*srcX - *dstX,
*srcY - *dstY);
if (srcRect->isEmpty()) return true;
needsReadjustParams = true;
......@@ -543,12 +544,10 @@ void KisPainter::bitBltWithFixedSelection(qint32 dstX, qint32 dstY,
Q_ASSERT(selection->colorSpace() == KoColorSpaceRegistry::instance()->alpha8());
QRect srcRect = QRect(srcX, srcY, srcWidth, srcHeight);
QRect selRect = QRect(selX, selY, srcWidth, srcHeight);
/* Trying to read outside a KisFixedPaintDevice is inherently wrong and shouldn't be done,
so crash if someone attempts to do this. Don't resize YET as it would obfuscate the mistake. */
Q_ASSERT(selection->bounds().contains(selRect));
Q_UNUSED(selRect); // only used by the above Q_ASSERT
// save selection offset in case tryReduceSourceRect() will change rects
const int xSelectionOffset = selX - srcX;
const int ySelectionOffset = selY - srcY;
/**
* An optimization, which crops the source rect by the bounds of
......@@ -559,6 +558,16 @@ void KisPainter::bitBltWithFixedSelection(qint32 dstX, qint32 dstY,
&srcWidth, &srcHeight,
&dstX, &dstY)) return;
const QRect selRect = QRect(srcX + xSelectionOffset,
srcY + ySelectionOffset,
srcWidth, srcHeight);
/* Trying to read outside a KisFixedPaintDevice is inherently wrong and shouldn't be done,
so crash if someone attempts to do this. Don't resize YET as it would obfuscate the mistake. */
KIS_SAFE_ASSERT_RECOVER_RETURN(selection->bounds().contains(selRect));
Q_UNUSED(selRect); // only used by the above Q_ASSERT
/* Create an intermediate byte array to hold information before it is written
to the current paint device (d->device) */
quint8* dstBytes = 0;
......@@ -582,9 +591,9 @@ void KisPainter::bitBltWithFixedSelection(qint32 dstX, qint32 dstY,
srcDev->readBytes(srcBytes, srcX, srcY, srcWidth, srcHeight);
QRect selBounds = selection->bounds();
const QRect selBounds = selection->bounds();
const quint8 *selRowStart = selection->data() +
(selBounds.width() * (selY - selBounds.top()) + (selX - selBounds.left())) * selection->pixelSize();
(selBounds.width() * (selRect.y() - selBounds.top()) + (selRect.x() - selBounds.left())) * selection->pixelSize();
/*
* This checks whether there is nothing selected.
......
......@@ -23,6 +23,23 @@
#include "KoMixColorsOp.h"
#include <type_traits>
#include <KisCppQuirks.h>
template <typename T>
static inline T safeDivideWithRound(T dividend,
std::enable_if_t<std::is_floating_point<T>::value, T> divisor) {
return dividend / divisor;
}
template <typename T>
static inline T safeDivideWithRound(T dividend,
std::enable_if_t<std::is_integral<T>::value, T> divisor) {
return (dividend + divisor / 2) / divisor;
}
template<class _CSTrait>
class KoMixColorsOpImpl : public KoMixColorsOp
{
......@@ -168,7 +185,7 @@ private:
}
// set totalAlpha to the minimum between its value and the unit value of the channels
const int sumOfWeights = weightsWrapper.normalizeFactor();
const typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype sumOfWeights = weightsWrapper.normalizeFactor();
if (totalAlpha > KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue * sumOfWeights) {
totalAlpha = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue * sumOfWeights;
......@@ -186,10 +203,7 @@ private:
for (int i = 0; i < (int)_CSTrait::channels_nb; i++) {
if (i != _CSTrait::alpha_pos) {
typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype v = (totals[i] + totalAlpha / 2) / totalAlpha;
if (KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue == 1.0) {
v = totals[i] / totalAlpha;
}
typename KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::compositetype v = safeDivideWithRound(totals[i], totalAlpha);
if (v > KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::max) {
v = KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::max;
......@@ -202,11 +216,7 @@ private:
}
if (_CSTrait::alpha_pos != -1) {
if (KoColorSpaceMathsTraits<typename _CSTrait::channels_type>::unitValue == 1.0) {
dstColor[ _CSTrait::alpha_pos ] = totalAlpha / sumOfWeights;
} else {
dstColor[ _CSTrait::alpha_pos ] = (totalAlpha + sumOfWeights / 2) / sumOfWeights;
}
dstColor[ _CSTrait::alpha_pos ] = safeDivideWithRound(totalAlpha, sumOfWeights);
}
} else {
memset(dst, 0, sizeof(typename _CSTrait::channels_type) * _CSTrait::channels_nb);
......
......@@ -22,41 +22,32 @@
#include <brushengine/kis_paintop_factory.h>
#include <brushengine/kis_paintop_settings.h>
#include <kis_icon.h>
#include <KisCppQuirks.h>
#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
namespace detail {
template <typename T>
struct __impl_has_typedef_needs_preinitialization {
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::needs_preinitialization*);
template< class, class = std::void_t<> >
struct has_preinitialize_statically : std::false_type { };
template <typename>
static no& test(...);
template< class T >
struct has_preinitialize_statically<T, std::void_t<decltype(std::declval<T>().preinitializeOpStatically(KisPaintOpSettingsSP()))>> : std::true_type { };
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template <typename T>
struct has_typedef_needs_preinitialization
: public boost::integral_constant <bool, __impl_has_typedef_needs_preinitialization<T>::value>
{};
template <typename T>
void preinitializeOpStatically(const KisPaintOpSettingsSP settings, typename boost::enable_if<has_typedef_needs_preinitialization<T> >::type * = 0)
void preinitializeOpStatically(const KisPaintOpSettingsSP settings, typename std::enable_if_t<has_preinitialize_statically<T>::value> * = 0)
{
T::preinitializeOpStatically(settings);
}
template <typename T>
void preinitializeOpStatically(const KisPaintOpSettingsSP settings, typename boost::disable_if<has_typedef_needs_preinitialization<T> >::type * = 0)
void preinitializeOpStatically(const KisPaintOpSettingsSP settings, typename std::enable_if_t<!has_preinitialize_statically<T>::value> * = 0)
{
Q_UNUSED(settings);
// noop
}
}
#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
......@@ -86,7 +77,7 @@ public:
#ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND
void preinitializePaintOpIfNeeded(const KisPaintOpSettingsSP settings) override {
preinitializeOpStatically<Op>(settings);
detail::preinitializeOpStatically<Op>(settings);
}
#endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment