Commit 48f7e12a authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Add APIDOX

parent ba5373bb
......@@ -618,7 +618,13 @@ void KisBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst,
}
namespace {
/**
* Some brush engines may need the gray brush image to be normalized,
* that is, to have average lightness value of 127. That is important
* for the lightness mode of the colorsmudge paintop, because the dab
* adds color inside a feedback loop. So non-neutral average lightness
* may lead to a rapid color drift to either black or white.
*/
void normalalizeRGBADab(QImage &image)
{
qint64 lightnessSum = 0;
......
......@@ -11,21 +11,94 @@
#include <QVector>
#include "kritaglobal_export.h"
/**
* @brief A utility class to maintain a sparse grid of loaded/unloaded rects
*
* KisRectsGrid manages the presence of the rectangular cells in the grid
* covering some specific area. The main usecase of the class is to maintain
* an overlay device over some other paint device.
*
* When you need to ensure that the overlay has some particular `rect` loaded,
* you just call `grid->addRect(rect)` and get a list of rects that should
* still be loaded into the overlay. The returned list may be empty if all the
* grid cells intersecting `rect` has already been loaded (added to the grid).
*
* The size of the cell is defined at the construction stage and must be
* power of 2.
*/
class KRITAGLOBAL_EXPORT KisRectsGrid
{
public:
/**
* Create a grid with cell size set to \p gridSize
*/
KisRectsGrid(int gridSize = 64);
/**
* Grow rectangle \p rc until it becomes aligned to
* the grid cell borders.
*/
QRect alignRect(const QRect &rc) const;
/**
* Add an arbitrary (non-aligned) rect to the grid
*
* The grid will form a list of cells that intersect \p rc and are still
* not loaded, mark them as loaded and return the list to the caller.
*
* \param rc the rect to be added, not necessary aligned to the grid
* \return the list of cells that has actually been changed
*/
QVector<QRect> addRect(const QRect &rc);
/**
* Remove an arbitrary (non-aligned) rect from the grid
*
* The grid will form a list of loaded cells that are fully contained in \p
* rc, mark them as unloaded and return the list to the caller.
*
* TODO: please note that removing two neighbouring non-aligned rectangles
* may still leave some cells marked as loaded. Perhaps we should change
* the meaning of this function to remove "all intersecting rectangles"
* instead of "all contained rectangles".
*
* \param rc the rect to be removed, not necessary aligned to the grid
* \return the list of cells that has actually been changed
*/
QVector<QRect> removeRect(const QRect &rc);
/**
* Add an aligned rect to the grid
*
* The grid will form a list of cells that intersect \p rc and are still
* not loaded, mark them as loaded and return the list to the caller.
*
* \param rc the rect to be added, the rect must be aligned
* \return the list of cells that has actually been changed
*/
QVector<QRect> addAlignedRect(const QRect &rc);
/**
* Remove an aligned rect from the grid
*
* The grid will form a list of loaded cells that are fully contained in \p
* rc, mark them as unloaded and return the list to the caller.
*
* \param rc the rect to be removed, not necessary aligned to the grid
* \return the list of cells that has actually been changed
*/
QVector<QRect> removeAlignedRect(const QRect &rc);
/**
* Return is \p rc is fully covered by the loaded cells of the grid
*/
bool contains(const QRect &rc) const;
/**
* Return the bounding box of the loaded cells of the grid
*/
QRect boundingRect() const;
private:
......
......@@ -147,12 +147,12 @@ inline PointType snapToClosestAxis(PointType P) {
}
template<typename T>
inline const T pow2(const T& x) {
inline T pow2(const T& x) {
return x * x;
}
template<typename T>
inline const T pow3(const T& x) {
inline T pow3(const T& x) {
return x * x * x;
}
......
......@@ -15,7 +15,19 @@
class KUndo2Command;
class KoColorSpace;
/**
* A special base class for storing temporary data inside a paint
* device between brush strokes. That might be used by the brushes to
* store data that needs to be passes between different strokes of the
* same brush, e.g. paint drying drying or heightmap information.
*
* The data is stored inside device->interstrokeData() and added
* via passing a factory to the transaction.
*
* The data is automatically removed when some incompatible change
* happens to a device, e.g. colorspace change or painting with
* incompatible brush.
*/
class KRITAIMAGE_EXPORT KisInterstrokeData
{
public:
......
......@@ -12,6 +12,15 @@
class KisInterstrokeData;
/**
* A factory class for creation KisInterstrokeData by paint tools
*
* The main purpose for the factory is to check if the currently
* attached interstroke data is compatible with the current tool
* and replace it with the new one if needed.
*
* \see KisInterstrokeData
*/
class KRITAIMAGE_EXPORT KisInterstrokeDataFactory
{
public:
......
......@@ -12,6 +12,15 @@
class KisInterstrokeDataFactory;
/**
* A factory object to extend the behavior of a normal transaction and
* handle management of interstroke data. It will create a new interstorke
* data using passed passed `KisInterstrokeDataFactory` or reset it if the
* current transaction is incompatible with it.
*
* \see KisTransactionWrapperFactory
* \see KisInterstrokeDataFactory
*/
class KRITAIMAGE_EXPORT KisInterstrokeDataTransactionWrapperFactory : public KisTransactionWrapperFactory
{
public:
......
......@@ -12,6 +12,15 @@
class KUndo2Command;
/**
* A simple factory that allows to wrap a paint device transaction
* with two commands. One command will be executed before the own
* transaction's code, and the other one after the transaction has
* been exected.
*
* The only use of this class now is to change/reset interstroke data of
* a paint device alongside executing the transaction.
*/
class KRITAIMAGE_EXPORT KisTransactionWrapperFactory
{
public:
......
......@@ -861,18 +861,15 @@ void KoColorSpace::fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, c
this->fromRgbA16(rgbBuffer.data(), dst, nPixels);
}
void KoColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const
void KoColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const
{
/// Fallback implementation. All RGB color spaces have their own
/// implementation without any conversions.
const int rgbPixelSize = sizeof(KoBgrU16Traits::Pixel);
QScopedArrayPointer<quint8> srcBuffer(new quint8[nPixels * rgbPixelSize]);
QScopedArrayPointer<quint8> dstBuffer(new quint8[nPixels * rgbPixelSize]);
// NOTE: src may be equal to dst!!!
this->toRgbA16(dst, dstBuffer.data(), nPixels);
modulateLightnessByGrayBrushRGB<KoBgrU16Traits>(dstBuffer.data(), brush, srcBuffer.data(), strength, nPixels);
modulateLightnessByGrayBrushRGB<KoBgrU16Traits>(dstBuffer.data(), brush, strength, nPixels);
this->fromRgbA16(dstBuffer.data(), dst, nPixels);
}
......@@ -525,9 +525,10 @@ public:
* see KoColorSpacePreserveLightnessUtils.h
*/
virtual void fillGrayBrushWithColorAndLightnessOverlay(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const;
//Same as above, but with contrast adjusted by strength. Strength == 1 -> full contrast. Allows softer lightness adjustments.
// Same as above, but with contrast adjusted by strength. Strength == 1 -> full contrast. Allows softer lightness adjustments.
virtual void fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, const QRgb* brush, quint8* brushColor, qreal strength, qint32 nPixels) const;
virtual void modulateLightnessByGrayBrush(quint8* dst, const QRgb *brush, quint8* src, qreal strength, qint32 nPixels) const;
// Same as above, but applies lightness adjustment to \p dst in-place
virtual void modulateLightnessByGrayBrush(quint8* dst, const QRgb *brush, qreal strength, qint32 nPixels) const;
/**
* Create an adjustment object for adjusting the brightness and contrast
......
......@@ -67,7 +67,7 @@ inline static void fillGrayBrushWithColorPreserveLightnessRGB(quint8 *pixels, co
}
template<typename CSTraits>
inline static void modulateLightnessByGrayBrushRGB(quint8 *pixels, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) {
inline static void modulateLightnessByGrayBrushRGB(quint8 *pixels, const QRgb *brush, qreal strength, qint32 nPixels) {
using RGBPixel = typename CSTraits::Pixel;
using channels_type = typename CSTraits::channels_type;
static const quint32 pixelSize = CSTraits::pixelSize;
......
......@@ -17,13 +17,38 @@
class KoMixColorsOp
{
public:
/**
* An accumulator-like object for mixing color without copying and allocations
*/
class Mixer
{
public:
virtual ~Mixer() {}
/**
* Add \p nPixels pixels pointed by \p data to the mixing sum. The
* passed pixels are weighted by coefficients in \p weights.
*/
virtual void accumulate(const quint8 *data, const qint16 *weights, int weightSum, int nPixels) = 0;
/**
* Add \p nPixels pixels pointed by \p data to the mixing sum. The
* passed pixels are weighted uniformly, that is, each pixel has
* implicit weight of 1.
*/
virtual void accumulateAverage(const quint8 *data, int nPixels) = 0;
/**
* Calculate the final mixed color. This function may be called
* as many times as needed on any stage of the mixing.
*/
virtual void computeMixedColor(quint8 *data) = 0;
/**
* Return the current sum of the weights of the averaging
* algorithm. That might be needed to make a decision whether
* we had a meaningful amount of data passed.
*/
virtual qint64 currentWeightsSum() const = 0;
};
......
......@@ -10,7 +10,42 @@
#include <QtGlobal>
#include "kritapigment_export.h"
/**
* @brief Converts an RGB-like color space between U8 and U16 formats
*
* In some places we need to extend precision of the color space
* in a very efficient way. It is specifically needed in the
* colorsmudge engine, because it operates at an extremely low
* levels of opacity. The conversion should also happen very
* efficiently, because colorsmudge requests it on the fly right
* when the user is painting on the canvas.
*
* The actual implementation is placed in class
* `KoOptimizedRgbPixelDataScalerU8ToU16`.
*
* To create a scaler, just call a factory. It will create a version
* of the scaler optimized for your CPU architecture.
*
* \code{.cpp}
* QScopedPointer<KoOptimizedRgbPixelDataScalerU8ToU16Base> scaler(
* KoOptimizedRgbPixelDataScalerU8ToU16Factory::create());
*
* // ...
*
* // convert the data from U8 to U16
* scaler->convertU8ToU16(src, srcRowStride,
* dst, dstRowStride,
* numRows, numColumns);
*
* // ...
*
* // convert the data back from U16 to U8
* scaler->convertU16ToU8(src, srcRowStride,
* dst, dstRowStride,
* numRows, numColumns);
*
* \endcode
*/
class KRITAPIGMENT_EXPORT KoOptimizedRgbPixelDataScalerU8ToU16Base
{
public:
......
......@@ -9,6 +9,9 @@
#include "KoOptimizedRgbPixelDataScalerU8ToU16Base.h"
/**
* \see KoOptimizedRgbPixelDataScalerU8ToU16Base
*/
class KRITAPIGMENT_EXPORT KoOptimizedRgbPixelDataScalerU8ToU16Factory
{
public:
......
......@@ -99,7 +99,7 @@ void KoRgbU16ColorSpace::fillGrayBrushWithColorAndLightnessWithStrength(quint8*
fillGrayBrushWithColorPreserveLightnessRGB<KoBgrU16Traits>(dst, brush, brushColor, strength, nPixels);
}
void KoRgbU16ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const
void KoRgbU16ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const
{
modulateLightnessByGrayBrushRGB<KoBgrU16Traits>(dst, brush, src, strength, nPixels);
modulateLightnessByGrayBrushRGB<KoBgrU16Traits>(dst, brush, strength, nPixels);
}
......@@ -42,7 +42,7 @@ public:
void fillGrayBrushWithColorAndLightnessOverlay(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const override;
void fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, const QRgb* brush, quint8* brushColor, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const override;
};
......
......@@ -110,7 +110,7 @@ void KoRgbU8ColorSpace::fillGrayBrushWithColorAndLightnessWithStrength(quint8* d
fillGrayBrushWithColorPreserveLightnessRGB<KoBgrU8Traits>(dst, brush, brushColor, strength, nPixels);
}
void KoRgbU8ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const
void KoRgbU8ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const
{
modulateLightnessByGrayBrushRGB<KoBgrU8Traits>(dst, brush, src, strength, nPixels);
modulateLightnessByGrayBrushRGB<KoBgrU8Traits>(dst, brush, strength, nPixels);
}
......@@ -43,7 +43,7 @@ public:
void fillGrayBrushWithColorAndLightnessOverlay(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const override;
void fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, const QRgb* brush, quint8* brushColor, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const override;
};
class KoRgbU8ColorSpaceFactory : public KoSimpleColorSpaceFactory
......
......@@ -111,7 +111,7 @@ void RgbF16ColorSpace::fillGrayBrushWithColorAndLightnessWithStrength(quint8* ds
fillGrayBrushWithColorPreserveLightnessRGB<KoRgbF16Traits>(dst, brush, brushColor, strength, nPixels);
}
void RgbF16ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const
void RgbF16ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const
{
modulateLightnessByGrayBrushRGB<KoRgbF16Traits>(dst, brush, src, strength, nPixels);
modulateLightnessByGrayBrushRGB<KoRgbF16Traits>(dst, brush, strength, nPixels);
}
......@@ -51,7 +51,7 @@ public:
void fillGrayBrushWithColorAndLightnessOverlay(quint8 *dst, const QRgb *brush, quint8 *brushColor, qint32 nPixels) const override;
void fillGrayBrushWithColorAndLightnessWithStrength(quint8* dst, const QRgb* brush, quint8* brushColor, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const override;
void modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const override;
};
class RgbF16ColorSpaceFactory : public LcmsColorSpaceFactory
......
......@@ -115,8 +115,8 @@ void RgbF32ColorSpace::fillGrayBrushWithColorAndLightnessWithStrength(quint8* ds
fillGrayBrushWithColorPreserveLightnessRGB<KoRgbF32Traits>(dst, brush, brushColor, strength, nPixels);
}
void RgbF32ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, quint8 *src, qreal strength, qint32 nPixels) const
void RgbF32ColorSpace::modulateLightnessByGrayBrush(quint8 *dst, const QRgb *brush, qreal strength, qint32 nPixels) const
{
modulateLightnessByGrayBrushRGB<KoRgbF32Traits>(dst, brush, src, strength, nPixels);
modulateLightnessByGrayBrushRGB<KoRgbF32Traits>(dst, brush, strength, nPixels);
}
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