File indexing completed on 2024-05-12 15:58:35

0001 /*
0002  *  SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2004 Clarence Dang <dang@kde.org>
0004  *  SPDX-FileCopyrightText: 2008-2010 Lukáš Tvrdý <lukast.dev@gmail.com>
0005  *  SPDX-FileCopyrightText: 2010 José Luis Vergara Toloza <pentalis@gmail.com>
0006  *
0007  *  SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #ifndef KIS_PAINTER_H_
0011 #define KIS_PAINTER_H_
0012 
0013 #include <math.h>
0014 
0015 #include <QVector>
0016 
0017 #include <KoColorSpaceConstants.h>
0018 #include <KoColorConversionTransformation.h>
0019 #include <KoPattern.h>
0020 #include <KoAbstractGradient.h>
0021 
0022 #include "kundo2magicstring.h"
0023 #include "kis_types.h"
0024 #include <kis_filter_configuration.h>
0025 #include <kritaimage_export.h>
0026 
0027 
0028 class QPen;
0029 class KUndo2Command;
0030 class QRect;
0031 class QRectF;
0032 class QBitArray;
0033 class QPainterPath;
0034 
0035 class KoUpdater;
0036 class KoColor;
0037 class KoCompositeOp;
0038 
0039 class KisUndoAdapter;
0040 class KisPostExecutionUndoAdapter;
0041 class KisTransaction;
0042 class KisPaintInformation;
0043 class KisPaintOp;
0044 class KisDistanceInformation;
0045 struct KisRenderedDab;
0046 class KisRunnableStrokeJobsInterface;
0047 
0048 /**
0049  * KisPainter contains the graphics primitives necessary to draw on a
0050  * KisPaintDevice. This is the same kind of abstraction as used in Qt
0051  * itself, where you have QPainter and QPaintDevice.
0052  *
0053  * However, KisPainter works on a tiled image and supports different
0054  * color models, and that's a lot more complicated.
0055  *
0056  * KisPainter supports transactions that can group various paint operations
0057  * in one undoable step.
0058  *
0059  * For more complex operations, you might want to have a look at the subclasses
0060  * of KisPainter: KisConvolutionPainter, KisFillPainter and KisGradientPainter
0061  *
0062  * KisPainter sets a number of default values, like COMPOSITE_OVER for compositeop,
0063  * OPACITY_OPAQUE for opacity and no selection for selection.
0064  */
0065 class KRITAIMAGE_EXPORT KisPainter
0066 {
0067 
0068 
0069 public:
0070     /// Construct painter without a device
0071     KisPainter();
0072 
0073     /// Construct a painter, and begin painting on the device
0074     KisPainter(KisPaintDeviceSP device);
0075 
0076     /// Construct a painter, and begin painting on the device. All actions will be masked by the given selection.
0077     KisPainter(KisPaintDeviceSP device, KisSelectionSP selection);
0078     virtual ~KisPainter();
0079 
0080 public:
0081     static void copyAreaOptimized(const QPoint &dstPt,
0082                                   KisPaintDeviceSP src,
0083                                   KisPaintDeviceSP dst,
0084                                   const QRect &originalSrcRect);
0085 
0086     static void copyAreaOptimizedOldData(const QPoint &dstPt,
0087                                          KisPaintDeviceSP src,
0088                                          KisPaintDeviceSP dst,
0089                                          const QRect &originalSrcRect);
0090 
0091     static void copyAreaOptimized(const QPoint &dstPt,
0092                                   KisPaintDeviceSP src,
0093                                   KisPaintDeviceSP dst,
0094                                   const QRect &originalSrcRect,
0095                                   KisSelectionSP selection);
0096 
0097     static KisPaintDeviceSP convertToAlphaAsAlpha(KisPaintDeviceSP src);
0098     static KisPaintDeviceSP convertToAlphaAsGray(KisPaintDeviceSP src);
0099 
0100     /**
0101      * creates a paint device with only alpha values from src
0102      */
0103     static KisPaintDeviceSP convertToAlphaAsPureAlpha(KisPaintDeviceSP src);
0104 
0105     static bool checkDeviceHasTransparency(KisPaintDeviceSP dev);
0106 
0107     /**
0108      * Start painting on the specified device. Not undoable.
0109      */
0110     void begin(KisPaintDeviceSP device);
0111 
0112     /**
0113      * Start painting on the specified paint device. All actions will be masked by the given selection.
0114      */
0115     void begin(KisPaintDeviceSP device, KisSelectionSP selection);
0116 
0117     /**
0118      * Finish painting on the current device
0119      */
0120     void end();
0121 
0122     /**
0123      * If set, the painter action is cancelable, if the action supports that.
0124      */
0125     void setProgress(KoUpdater * progressUpdater);
0126 
0127     /// Begin an undoable paint operation
0128     void beginTransaction(const KUndo2MagicString& transactionName = KUndo2MagicString(),int timedID = -1);
0129 
0130     /// Cancel all the changes made by the painter
0131     void revertTransaction();
0132 
0133     /// Finish the undoable paint operation
0134     void endTransaction(KisUndoAdapter *undoAdapter);
0135 
0136     /**
0137      * Finish transaction and load it to a special adapter for strokes
0138      */
0139     void endTransaction(KisPostExecutionUndoAdapter *undoAdapter);
0140 
0141     /**
0142      * Finishes a transaction and returns a pointer to its undo command
0143      */
0144     KUndo2Command* endAndTakeTransaction();
0145 
0146     /**
0147      * Finish the transaction and delete it's undo information.
0148      * NOTE: Be careful, because all the previous transactions
0149      * will become non-undoable after execution of this method.
0150      */
0151     void deleteTransaction();
0152 
0153     /// continue a transaction started somewhere else
0154     void putTransaction(KisTransaction* transaction);
0155 
0156     /// take transaction out of the reach of KisPainter
0157     KisTransaction* takeTransaction();
0158 
0159     /// Returns the current paint device.
0160     const KisPaintDeviceSP device() const;
0161     KisPaintDeviceSP device();
0162 
0163 
0164 
0165     /**
0166      * Blast a region of srcWidth @param srcWidth and srcHeight @param srcHeight from @param
0167      * srcDev onto the current paint device. @param srcX and @param srcY set the x and y
0168      * positions of the origin top-left corner, @param dstX and @param dstY those of
0169      * the destination.
0170      * Any pixel read outside the limits of @param srcDev will return the
0171      * default pixel, this is a property of \ref KisPaintDevice.
0172      *
0173      * @param dstX the destination x-coordinate
0174      * @param dstY the destination y-coordinate
0175      * @param srcDev the source device
0176      * @param srcX the source x-coordinate
0177      * @param srcY the source y-coordinate
0178      * @param srcWidth the width of the region to be manipulated
0179      * @param srcHeight the height of the region to be manipulated
0180      */
0181     void bitBlt(qint32 dstX, qint32 dstY,
0182                 const KisPaintDeviceSP srcDev,
0183                 qint32 srcX, qint32 srcY,
0184                 qint32 srcWidth, qint32 srcHeight);
0185 
0186     /**
0187      * Convenience method that uses QPoint and QRect.
0188      *
0189      * @param pos the destination coordinate, it replaces @p dstX and @p dstY.
0190      * @param srcDev the source device.
0191      * @param srcRect the rectangle describing the area to blast from @p srcDev into the current paint device.
0192      * @p srcRect replaces @p srcX, @p srcY, @p srcWidth and @p srcHeight.
0193      *
0194      */
0195     void bitBlt(const QPoint & pos, const KisPaintDeviceSP srcDev, const QRect & srcRect);
0196 
0197     /**
0198      * The same as @ref bitBlt() but reads data from oldData() part of the device
0199      *
0200      * @param dstX the destination x-coordinate
0201      * @param dstY the destination y-coordinate
0202      * @param srcDev the source device
0203      * @param srcX the source x-coordinate
0204      * @param srcY the source y-coordinate
0205      * @param srcWidth the width of the region to be manipulated
0206      * @param srcHeight the height of the region to be manipulated
0207      */
0208     void bitBltOldData(qint32 dstX, qint32 dstY,
0209                        const KisPaintDeviceSP srcDev,
0210                        qint32 srcX, qint32 srcY,
0211                        qint32 srcWidth, qint32 srcHeight);
0212 
0213     /**
0214      * Convenience method that uses QPoint and QRect.
0215      *
0216      * @param pos the destination coordinate, it replaces @p dstX and @p dstY.
0217      * @param srcDev the source device.
0218      * @param srcRect the rectangle describing the area to blast from @param srcDev into the current paint device.
0219      * @p srcRect replaces @p srcX, @p srcY, @p srcWidth and @p srcHeight.
0220      *
0221      */
0222     void bitBltOldData(const QPoint & pos, const KisPaintDeviceSP srcDev, const QRect & srcRect);
0223 
0224     /**
0225      * Blasts a @param selection of srcWidth @param srcWidth and srcHeight @param srcHeight
0226      * of @param srcDev on the current paint device. There is parameters
0227      * to control where the area begins in each distinct device, explained below.
0228      * @param selection can be used as a mask to shape @param srcDev to
0229      * something interesting in the same step it is rendered to the current
0230      * paint device. @param selection 's colorspace must be alpha8 (the
0231      * colorspace for selections/transparency), the rectangle formed by
0232      * @param selX, @param selY, @param srcWidth and @param srcHeight must not go
0233      * beyond its limits, and they must be different from zero.
0234      * @param selection and KisPainter's selection (the user selection) are
0235      * fused together through the composite operation COMPOSITE_MULT.
0236      * Any pixel read outside the limits of @param srcDev will return the
0237      * default pixel, this is a property of \ref KisPaintDevice.
0238      *
0239      * @param dstX the destination x-coordinate
0240      * @param dstY the destination y-coordinate
0241      * @param srcDev the source device
0242      * @param selection the custom selection to apply on the source device
0243      * @param selX the selection x-coordinate
0244      * @param selY the selection y-coordinate
0245      * @param srcX the source x-coordinate
0246      * @param srcY the source y-coordinate
0247      * @param srcWidth the width of the region to be manipulated
0248      * @param srcHeight the height of the region to be manipulated
0249      *
0250      */
0251     void bitBltWithFixedSelection(qint32 dstX, qint32 dstY,
0252                                   const KisPaintDeviceSP srcDev,
0253                                   const KisFixedPaintDeviceSP selection,
0254                                   qint32 selX, qint32 selY,
0255                                   qint32 srcX, qint32 srcY,
0256                                   qint32 srcWidth, qint32 srcHeight);
0257 
0258     /**
0259      * Convenience method that assumes @p selX, @p selY, @p srcX and @p srcY are
0260      * equal to 0. Best used when @p selection and the desired area of @p srcDev have exactly
0261      * the same dimensions and are specially made for each other.
0262      *
0263      * @param dstX the destination x-coordinate
0264      * @param dstY the destination y-coordinate
0265      * @param srcDev the source device
0266      * @param selection the custom selection to apply on the source device
0267      * @param srcWidth the width of the region to be manipulated
0268      * @param srcHeight the height of the region to be manipulated
0269      */
0270     void bitBltWithFixedSelection(qint32 dstX, qint32 dstY,
0271                                   const KisPaintDeviceSP srcDev,
0272                                   const KisFixedPaintDeviceSP selection,
0273                                   qint32 srcWidth, qint32 srcHeight);
0274 
0275     /**
0276      * Blast a region of srcWidth @p srcWidth and srcHeight @p srcHeight from @p srcDev onto the current
0277      * paint device. @p srcX and @p srcY set the x and y positions of the
0278      * origin top-left corner, @p dstX and @p dstY those of the destination.
0279      * @p srcDev is a @ref KisFixedPaintDevice : this means that @p srcDev must have the same
0280      * colorspace as the destination device.
0281      *
0282      * @param dstX the destination x-coordinate
0283      * @param dstY the destination y-coordinate
0284      * @param srcDev the source device
0285      * @param srcX the source x-coordinate
0286      * @param srcY the source y-coordinate
0287      * @param srcWidth the width of the region to be manipulated
0288      * @param srcHeight the height of the region to be manipulated
0289      */
0290     void bltFixed(qint32 dstX, qint32 dstY,
0291                   const KisFixedPaintDeviceSP srcDev,
0292                   qint32 srcX, qint32 srcY,
0293                   qint32 srcWidth, qint32 srcHeight);
0294 
0295 
0296     /**
0297      * Render the area \p rc from \p srcDevices on the destination device.
0298      * If \p rc doesn't cross the device's rect, then the device is not
0299      * rendered at all.
0300      */
0301     void bltFixed(const QRect &rc, const QList<KisRenderedDab> allSrcDevices);
0302 
0303     /**
0304      * Convenience method that uses QPoint and QRect.
0305      *
0306      * @param pos the destination coordinate, it replaces @p dstX and @p dstY.
0307      * @param srcDev the source device.
0308      * @param srcRect the rectangle describing the area to blast from @p srcDev into the current paint device.
0309      * @param srcRect replaces @p srcX, @p srcY, @p srcWidth and @p srcHeight.
0310      *
0311      */
0312     void bltFixed(const QPoint & pos, const KisFixedPaintDeviceSP srcDev, const QRect & srcRect);
0313 
0314     /**
0315      * Blasts a @p selection of srcWidth @p srcWidth and srcHeight @p srcHeight
0316      * of @p srcDev on the current paint device. There is parameters to control
0317      * the top-left corner of the area in each respective paint device (@p dstX,
0318      * @p dstY, @p srcX, @p srcY).
0319      * @p selection can be used as a mask to shape @p srcDev to something
0320      * interesting in the same step it is rendered to the current paint device.
0321      * @p srcDev is a @ref KisFixedPaintDevice : this means that @p srcDev
0322      * must have the same colorspace as the destination device.
0323      * @p selection 's colorspace must be alpha8 (the colorspace for
0324      * selections/transparency).
0325      * The rectangle formed by the respective top-left coordinates of each device
0326      * and @p srcWidth and @p srcHeight must not go beyond their limits, and
0327      * they must be different from zero.
0328      * @p selection and KisPainter's selection (the user selection) are
0329      * fused together through the composite operation COMPOSITE_MULT.
0330      *
0331      * @param dstX the destination x-coordinate
0332      * @param dstY the destination y-coordinate
0333      * @param srcDev the source device
0334      * @param selection the selection stored in fixed device
0335      * @param selX the selection x-coordinate
0336      * @param selY the selection y-coordinate
0337      * @param srcX the source x-coordinate
0338      * @param srcY the source y-coordinate
0339      * @param srcWidth the width of the region to be manipulated
0340      * @param srcHeight the height of the region to be manipulated
0341      */
0342     void bltFixedWithFixedSelection(qint32 dstX, qint32 dstY,
0343                                     const KisFixedPaintDeviceSP srcDev,
0344                                     const KisFixedPaintDeviceSP selection,
0345                                     qint32 selX, qint32 selY,
0346                                     qint32 srcX, qint32 srcY,
0347                                     quint32 srcWidth, quint32 srcHeight);
0348 
0349     /**
0350      * Convenience method that assumes @p selX, @p selY, @p srcX and @p srcY are
0351      * equal to 0. Best used when @p selection and @p srcDev have exactly the same
0352      * dimensions and are specially made for each other.
0353      *
0354      * @param dstX the destination x-coordinate
0355      * @param dstY the destination y-coordinate
0356      * @param srcDev the source device
0357      * @param selection the custom selection to apply on the source device
0358      * @param srcWidth the width of the region to be manipulated
0359      * @param srcHeight the height of the region to be manipulated
0360      */
0361     void bltFixedWithFixedSelection(qint32 dstX, qint32 dstY,
0362                                     const KisFixedPaintDeviceSP srcDev,
0363                                     const KisFixedPaintDeviceSP selection,
0364                                     quint32 srcWidth, quint32 srcHeight);
0365 
0366     /**
0367      * fills a region of width @p width and height @p height of the current
0368      * paint device with the color @p color. @p x and @p y set the x and y positions of the
0369      * origin top-left corner.
0370      *
0371      * @param x the destination x-coordinate
0372      * @param y the destination y-coordinate
0373      * @param width the width of the region to be manipulated
0374      * @param height the height of the region to be manipulated
0375      * @param color the color the area is filled with
0376      */
0377     void fill(qint32 x, qint32 y, qint32 width, qint32 height, const KoColor& color);
0378 
0379     /**
0380      * First you need to setup the painter with setMirrorInformation,
0381      * then these set of methods provide way to render the devices mirrored
0382      * according the axesCenter vertically or horizontally or both.
0383      *
0384      * @param rc rectangle area covered by dab
0385      * @param dab this device will be mirrored in-place, it means that it will be changed
0386      */
0387     void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab);
0388     void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab, KisFixedPaintDeviceSP mask);
0389     void renderMirrorMask(QRect rc, KisPaintDeviceSP dab);
0390     void renderMirrorMask(QRect rc, KisPaintDeviceSP dab, int sx, int sy, KisFixedPaintDeviceSP mask);
0391 
0392     /**
0393      * Convenience method for renderMirrorMask(), allows to choose whether
0394      * we need to preserve out dab or do the transformations in-place.
0395      *
0396      * @param rc rectangle area covered by dab
0397      * @param dab the device to render
0398      * @param mask mask to use for rendering
0399      * @param preserveDab states whether a temporary device should be
0400      *                    created to do the transformations
0401      */
0402     void renderMirrorMaskSafe(QRect rc, KisFixedPaintDeviceSP dab, bool preserveDab);
0403     void renderMirrorMaskSafe(QRect rc, KisFixedPaintDeviceSP dab, KisFixedPaintDeviceSP mask, bool preserveDab);
0404 
0405     /**
0406      * Convenience method for renderMirrorMask(), allows to choose whether
0407      * we need to preserve our fixed mask or do the transformations in-place.
0408      *
0409      * @param rc rectangular area covered by dab
0410      * @param dab the device to render
0411      * @param sx x coordinate of the top left corner of the area
0412      * @param sy y coordinate of the top left corner of the area
0413      * @param mask mask to use for rendering
0414      * @param preserveMask states whether a temporary device should be
0415      *                    created to do the transformations
0416      */
0417     void renderMirrorMaskSafe(QRect rc, KisPaintDeviceSP dab, int sx, int sy, KisFixedPaintDeviceSP mask, bool preserveMask);
0418 
0419     /**
0420      * A complex method that re-renders a dab on an \p rc area.
0421      * The \p rc  area and all the dedicated mirroring areas are cleared
0422      * before the painting, so this method should be used by paintops
0423      * which do not update the canvas incrementally, but instead
0424      * regenerate some internal cache \p dab with the COMPOSITE_COPY op.
0425      *
0426      * \see KisExperimentPaintOp
0427      */
0428     void renderDabWithMirroringNonIncremental(QRect rc, KisPaintDeviceSP dab);
0429 
0430     /**
0431      * @return true if the painter has some rects marked as dirty
0432      * @see takeDirtyRegion(), addDirtyRect()
0433      */
0434     bool hasDirtyRegion() const;
0435 
0436     /**
0437       * The methods in this class do not tell the paintdevice to update, but they calculate the
0438       * dirty area. This method returns this dirty area and resets it.
0439       */
0440     QVector<QRect> takeDirtyRegion();
0441 
0442     /**
0443      * Paint a line that connects the dots in points
0444      */
0445     void paintPolyline(const QVector <QPointF> &points,
0446                        int index = 0, int numPoints = -1);
0447 
0448     /**
0449      * Draw a line between pos1 and pos2 using the currently set brush and color.
0450      * If savedDist is less than zero, the brush is painted at pos1 before being
0451      * painted along the line using the spacing setting.
0452      * @return the drag distance, that is the remains of the distance between p1 and p2 not covered
0453      * because the currently set brush has a spacing greater than that distance.
0454      */
0455     void paintLine(const KisPaintInformation &pi1,
0456                    const KisPaintInformation &pi2,
0457                    KisDistanceInformation *currentDistance);
0458 
0459     /**
0460      * Draw a Bezier curve between @p pi1 and @p pi2 using control points @p control1 and @p control2.
0461      * If savedDist is less than zero, the brush is painted at pos1 before being
0462      * painted along the curve using the spacing setting.
0463      * @return the drag distance, that is the remains of the distance between @p pi1 and @p pi2 not covered
0464      * because the currently set brush has a spacing greater than that distance.
0465      */
0466     void paintBezierCurve(const KisPaintInformation &pi1,
0467                           const QPointF &control1,
0468                           const QPointF &control2,
0469                           const KisPaintInformation &pi2,
0470                           KisDistanceInformation *currentDistance);
0471     /**
0472      * Fill the given vector points with the points needed to draw the Bezier curve between
0473      * @p pos1 and @p pos2 using control points @p control1 and @p control2, excluding the final pos2.
0474      */
0475     void getBezierCurvePoints(const QPointF &pos1,
0476                               const QPointF &control1,
0477                               const QPointF &control2,
0478                               const QPointF &pos2,
0479                               vQPointF& points) const;
0480 
0481     /**
0482      * Paint a rectangle.
0483      * @param rect the rectangle to paint.
0484      */
0485     void paintRect(const QRectF &rect);
0486 
0487     /**
0488      * Paint a rectangle.
0489      *
0490      * @param x x coordinate of the top-left corner
0491      * @param y y coordinate of the top-left corner
0492      * @param w the rectangle width
0493      * @param h the rectangle height
0494      */
0495     void paintRect(const qreal x,
0496                    const qreal y,
0497                    const qreal w,
0498                    const qreal h);
0499 
0500     /**
0501      * Paint the ellipse that fills the given rectangle.
0502      *
0503      * @param rect the rectangle containing the ellipse to paint.
0504      */
0505     void paintEllipse(const QRectF &rect);
0506 
0507     /**
0508      * Paint the ellipse that fills the given rectangle.
0509      *
0510      * @param x x coordinate of the top-left corner
0511      * @param y y coordinate of the top-left corner
0512      * @param w the rectangle width
0513      * @param h the rectangle height
0514      */
0515     void paintEllipse(const qreal x,
0516                       const qreal y,
0517                       const qreal w,
0518                       const qreal h);
0519 
0520     /**
0521      * Paint the polygon with the points given in points. It automatically closes the polygon
0522      * by drawing the line from the last point to the first.
0523      */
0524     void paintPolygon(const vQPointF& points);
0525 
0526     /** Draw a spot at pos using the currently set paint op, brush and color */
0527     void paintAt(const KisPaintInformation &pos,
0528                  KisDistanceInformation *savedDist);
0529 
0530     /**
0531      * Stroke the given QPainterPath.
0532      */
0533     void paintPainterPath(const QPainterPath& path);
0534 
0535     /**
0536      * Fills the area enclosed by the given QPainterPath
0537      * Convenience method for fillPainterPath(path, rect)
0538      */
0539     void fillPainterPath(const QPainterPath& path);
0540 
0541     /**
0542      * Fills the portion of an area enclosed by the given QPainterPath
0543      *
0544      * \param path the portion of the path to fill
0545      * \param requestedRect the rectangle containing the area
0546      */
0547     void fillPainterPath(const QPainterPath& path, const QRect &requestedRect);
0548 
0549     /**
0550      * Draw the path using the Pen
0551      *
0552      * if \p requestedRect is null, the entire path is painted
0553      */
0554     void drawPainterPath(const QPainterPath& path, const QPen& pen, const QRect &requestedRect);
0555 
0556     // convenience overload
0557     void drawPainterPath(const QPainterPath& path, const QPen& pen);
0558 
0559     /**
0560      * paint an unstroked one-pixel wide line from specified start position to the
0561      * specified end position.
0562      *
0563      */
0564     void drawLine(const QPointF & start, const QPointF & end);
0565 
0566     /**
0567      * paint an unstroked line with thickness from specified start position to the
0568      * specified end position. Scanline algorithm is used.
0569      */
0570     void drawLine(const QPointF &start, const QPointF &end, qreal width, bool antialias);
0571 
0572 
0573     /**
0574      * paints an unstroked, aliased one-pixel line using the DDA algorithm from specified start position to the
0575      * specified end position.
0576      *
0577      */
0578     void drawDDALine(const QPointF & start, const QPointF & end);
0579 
0580     /**
0581      * Paint an unstroked, wobbly one-pixel wide line from the specified start to the specified
0582      * end position.
0583      *
0584      */
0585     void drawWobblyLine(const QPointF & start, const QPointF & end);
0586 
0587     /**
0588      * Paint an unstroked, anti-aliased one-pixel wide line from the specified start to the specified
0589      * end position using the Wu algorithm
0590      */
0591     void drawWuLine(const QPointF & start, const QPointF & end);
0592 
0593     /**
0594      * Paint an unstroked wide line from the specified start to the specified
0595      * end position with width varying from @p start at the start to @p end at
0596      * the end.
0597      *
0598      * XXX: the width should be set in doubles, not integers.
0599      */
0600     void drawThickLine(const QPointF & start, const QPointF & end, int startWidth, int endWidth);
0601 
0602     /**
0603      * Set the channelflags: a bit array where true means that the
0604      * channel corresponding in position with the bit will be read
0605      * by the operation, and false means that it will not be affected.
0606      *
0607      * An empty channelFlags parameter means that all channels are
0608      * affected.
0609      *
0610      * @param channelFlags the bit array that masks the source channels; only
0611      * the channels where the corresponding bit is true will will be
0612      * composited onto the destination device.
0613      */
0614     void setChannelFlags(QBitArray channelFlags);
0615 
0616     /// @return the channel flags
0617     QBitArray channelFlags();
0618 
0619     /**
0620      * Set the paintop preset to use. If @p image is given,
0621      * the paintop will be created using this image as parameter.
0622      * Some paintops really want to know about the image they work
0623      * for, e.g. the clone paintop.
0624      */
0625     void setPaintOpPreset(KisPaintOpPresetSP preset, KisNodeSP node, KisImageSP image);
0626 
0627     /// Return the paintop preset
0628     KisPaintOpPresetSP preset() const;
0629 
0630     /**
0631      * Return the active paintop (which is created based on the specified preset and
0632      * will be deleted as soon as the KisPainter instance dies).
0633      */
0634     KisPaintOp* paintOp() const;
0635 
0636     void setMirrorInformation(const QPointF &axesCenter, bool mirrorHorizontally, bool mirrorVertically);
0637 
0638     void copyMirrorInformationFrom(const KisPainter *other);
0639 
0640     /**
0641      * Returns whether the mirroring methods will do any
0642      * work when called
0643      */
0644     bool hasMirroring() const;
0645 
0646     /**
0647      * Indicates if horizontal mirroring mode is activated
0648      */
0649     bool hasHorizontalMirroring() const;
0650 
0651     /**
0652      * Indicates if vertical mirroring mode is activated
0653      */
0654     bool hasVerticalMirroring() const;
0655 
0656     /**
0657      * Mirror \p rc in the requested \p direction around the center point defined
0658      * in the painter.
0659      */
0660     void mirrorRect(Qt::Orientation direction, QRect *rc) const;
0661 
0662     /**
0663      * Mirror \p dab in the requested direction around the center point defined
0664      * in the painter. The dab's offset is adjusted automatically.
0665      */
0666     void mirrorDab(Qt::Orientation direction, KisRenderedDab *dab, bool skipMirrorPixels = false) const;
0667 
0668     /**
0669      * Calculate the list of the mirrored rects that will be painted on the
0670      * the canvas when calling renderMirrorMask() at al
0671      */
0672     const QVector<QRect> calculateAllMirroredRects(const QRect &rc);
0673 
0674     /**
0675      * Calculate the list of the mirrored points according to the current
0676      * mirroring configuration.
0677      */
0678     const QVector<QPointF> calculateAllMirroredPoints(const QPointF &pos);
0679 
0680     /**
0681      * Calculate the list of the mirrored point pairs according to the current
0682      * mirroring configuration.
0683      */
0684     const QVector<QPair<QPointF, QPointF>> calculateAllMirroredPoints(const QPair<QPointF, QPointF> &pair);
0685 
0686     /// Set the current pattern
0687     void setPattern(const KoPatternSP pattern);
0688 
0689     /// Returns the currently set pattern
0690     const KoPatternSP pattern() const;
0691 
0692     /**
0693      * Set the color that will be used to paint with, and convert it
0694      * to the color space of the current paint device.
0695      */
0696     void setPaintColor(const KoColor& color);
0697 
0698     /// Returns the color that will be used to paint with
0699     const KoColor &paintColor() const;
0700 
0701     /**
0702      * Set the current background color, and convert it
0703      * to the color space of the current paint device.
0704      */
0705     void setBackgroundColor(const KoColor& color);
0706 
0707     /// Returns the current background color
0708     const KoColor &backgroundColor() const;
0709 
0710     /// Set the current generator (a generator can be used to fill an area
0711     void setGenerator(KisFilterConfigurationSP generator);
0712 
0713     /// @return the current generator configuration
0714     const KisFilterConfigurationSP  generator() const;
0715 
0716     /// This enum contains the styles with which we can fill things like polygons and ellipses
0717     enum FillStyle {
0718         FillStyleNone,
0719         FillStyleForegroundColor,
0720         FillStyleBackgroundColor,
0721         FillStylePattern,
0722         FillStyleGenerator
0723     };
0724 
0725     /// Set the current style with which to fill
0726     void setFillStyle(FillStyle fillStyle);
0727 
0728     /// Returns the current fill style
0729     FillStyle fillStyle() const;
0730 
0731     /// Set the transform on the pattern.
0732     void setPatternTransform(QTransform transform);
0733 
0734     /// get the current transform on the pattern.
0735     QTransform patternTransform();
0736 
0737     /// Set whether a polygon's filled area should be anti-aliased or not. The default is true.
0738     void setAntiAliasPolygonFill(bool antiAliasPolygonFill);
0739 
0740     /// Return whether a polygon's filled area should be anti-aliased or not
0741     bool antiAliasPolygonFill();
0742 
0743     /// The style of the brush stroke around polygons and so
0744     enum StrokeStyle {
0745         StrokeStyleNone,
0746         StrokeStyleBrush
0747     };
0748 
0749     /// Set the current brush stroke style
0750     void setStrokeStyle(StrokeStyle strokeStyle);
0751 
0752     /// Returns the current brush stroke style
0753     StrokeStyle strokeStyle() const;
0754 
0755     void setFlow(quint8 flow);
0756 
0757     quint8 flow() const;
0758 
0759     /**
0760      * Sets the opacity of the painting and recalculates the
0761      * mean opacity of the stroke. This mean value is used to
0762      * make ALPHA_DARKEN painting look correct
0763      */
0764     void setOpacityUpdateAverage(quint8 opacity);
0765 
0766     /**
0767      * Sets average opacity, that is used to make ALPHA_DARKEN painting look correct
0768      */
0769     void setAverageOpacity(qreal averageOpacity);
0770 
0771     /**
0772      * Calculate average opacity value after painting a single dab with \p opacity
0773      */
0774     static qreal blendAverageOpacity(qreal opacity, qreal averageOpacity);
0775 
0776     /// Set the opacity which is used in painting (like filling polygons)
0777     void setOpacity(quint8 opacity);
0778 
0779     /// Returns the opacity that is used in painting
0780     quint8 opacity() const;
0781 
0782     /**
0783      * Set the composite op ID for this painter
0784      * Only kept for convenience, it will just call ::setCompositeOpId(QString) with op->Id().
0785      */
0786     void setCompositeOpId(const KoCompositeOp * op);
0787 
0788     /// Returns the current composite op Id
0789     QString compositeOpId();
0790 
0791     /// Set the composite op for this painter by string.
0792     void setCompositeOpId(const QString& op);
0793 
0794     /**
0795      * Add \p r to the current set of dirty rects
0796      */
0797     void addDirtyRect(const QRect &r);
0798 
0799     /**
0800      * Add \p rects to the current set of dirty rects
0801      */
0802     void addDirtyRects(const QVector<QRect> &rects);
0803 
0804     /**
0805      * Reset the selection to the given selection. All painter actions will be
0806      * masked by the specified selection.
0807      */
0808     void setSelection(KisSelectionSP selection);
0809 
0810     /**
0811      * @return the selection set on this painter.
0812      */
0813     KisSelectionSP selection();
0814 
0815     void setGradient(const KoAbstractGradientSP gradient);
0816     const KoAbstractGradientSP gradient() const;
0817 
0818     /**
0819     * Set the size of the tile in fillPainterPath, useful when optimizing the use of fillPainterPath
0820     * e.g. Spray paintop uses more small tiles, although selections uses bigger tiles. QImage::fill
0821     * is quite expensive so with smaller images you can save instructions
0822     * Default and maximum size is 256x256 image
0823     */
0824     void setMaskImageSize(qint32 width, qint32 height);
0825 
0826 //    /**
0827 //     * If the alpha channel is locked, the alpha values of the paint device we are painting on
0828 //     * will not change.
0829 //     */
0830 //    void setLockAlpha(bool protect);
0831 //    bool alphaLocked() const;
0832 
0833     /**
0834      * set the rendering intent in case pixels need to be converted before painting
0835      */
0836     void setRenderingIntent(KoColorConversionTransformation::Intent intent);
0837 
0838     /**
0839      * set the conversion flags in case pixels need to be converted before painting
0840      */
0841     void setColorConversionFlags(KoColorConversionTransformation::ConversionFlags conversionFlags);
0842 
0843     /**
0844      * Set interface for running asynchronous jobs by paintops.
0845      *
0846      * NOTE: the painter does *not* own the interface device. It is the responsibility
0847      *       of the caller to ensure that the interface object is alive during the lifetime
0848      *       of the painter.
0849      */
0850     void setRunnableStrokeJobsInterface(KisRunnableStrokeJobsInterface *interface);
0851 
0852     /**
0853      * Get the interface for running asynchronous jobs. It is used by paintops mostly.
0854      */
0855     KisRunnableStrokeJobsInterface* runnableStrokeJobsInterface() const;
0856 
0857 protected:
0858     /// Initialize, set everything to '0' or defaults
0859     void init();
0860 
0861     /// Fill the polygon defined by points with the fillStyle
0862     void fillPolygon(const vQPointF& points, FillStyle fillStyle);
0863 
0864 private:
0865 
0866     KisPainter(const KisPainter&);
0867     KisPainter& operator=(const KisPainter&);
0868 
0869     float frac(float value) {
0870         float tmp = 0;
0871         return modff(value , &tmp);
0872     }
0873 
0874     float invertFrac(float value) {
0875         float tmp = 0;
0876         return 1.0f - modff(value , &tmp);
0877     }
0878 
0879 protected:
0880     KoUpdater * progressUpdater();
0881 
0882 private:
0883     template <bool useOldSrcData>
0884         void bitBltImpl(qint32 dstX, qint32 dstY,
0885                         const KisPaintDeviceSP srcDev,
0886                         qint32 srcX, qint32 srcY,
0887                         qint32 srcWidth, qint32 srcHeight);
0888 
0889     inline void compositeOnePixel(quint8 *dst, const KoColor &color);
0890 
0891 private:
0892 
0893     struct Private;
0894     Private* const d;
0895 };
0896 
0897 
0898 #endif // KIS_PAINTER_H_
0899