File indexing completed on 2024-05-05 04:21:08

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #ifndef KP_PAINTER_H
0030 #define KP_PAINTER_H
0031 
0032 
0033 #include "kpColor.h"
0034 #include "kpImage.h"
0035 
0036 
0037 
0038 
0039 //
0040 // Stateless painter with sane semantics that works on kpImage's i.e. it
0041 // works on document - not view - data.  If you find that you need state,
0042 // you should probably move it into kpPainter to avoid the overhead of
0043 // passing around this state (e.g. color, line width) and for reuse.
0044 //
0045 // kpPainter is to kpImage as QPainter is to QPixmap.
0046 //
0047 // This encapsulates the set of functionality used by all of KolourPaint's
0048 // document drawing functions and nothing more, permitting rewriting of
0049 // the image library.  Currently uses QPainter/kpPixmapFX as the image library.
0050 //
0051 
0052 struct kpPainterPrivate;
0053 
0054 class kpPainter
0055 {
0056 public:
0057     // helper to make a correct QRect out of 2 QPoints regardless of their relative position
0058     // to each other
0059     static QRect normalizedRect(const QPoint& p1, const QPoint& p2)
0060     {
0061       return QRect(qMin(p1.x(), p2.x()), qMin(p1.y(), p2.y()),
0062                    qAbs(p2.x() - p1.x()) + 1, qAbs(p2.y() - p1.y()) + 1);
0063     }
0064 
0065     // Returns whether the given points are cardinally adjacent (i.e. one point
0066     // is exactly 1 pixel north, east, south or west of the other).  Equal
0067     // points are not cardinally adjacent.
0068     static bool pointsAreCardinallyAdjacent (const QPoint &p, const QPoint &q);
0069 
0070     // Returns a list of points representing a straight line from <startPoint>
0071     // to <endPoint> inclusive, using Bresenham's line algorithm.  Each point
0072     // is created only with the specified <probability>.
0073     //
0074     // If <cardinalAdjacency> is set, a modified Bresenham's algorithm will add
0075     // an extra point between every pair of originally strictly-diagonally-adjacent
0076     // points, such that these points become cardinally adjacent.  However, these
0077     // extra points are also created only with the specified <probability>.
0078     //
0079     // For instance, <cardinalAdjacency> must be set if a diagonal line is to
0080     // drawn at each of the returned points, otherwise things won't look right:
0081     //
0082     //     .\.....
0083     //     \.\....
0084     //     .\.B...
0085     //     ..Ac\..
0086     //     ...\.\.
0087     //     ....\..
0088     //
0089     // 'A' is the previous Bresenham point.  'B' is the new point.  See how if
0090     // diagonal lines are drawn at A and B, there is a gap between the lines.
0091     // Setting <cardinalAdjacency> will solve this problem, since it will add
0092     // a point at 'c'.
0093     //
0094     // ASSUMPTION: <probability> is between 0.0 and 1.0 inclusive.
0095     static QList <QPoint> interpolatePoints (const QPoint &startPoint,
0096         const QPoint &endPoint,
0097         bool cardinalAdjacency = false,
0098         double probability = 1.0);
0099 
0100     static void fillRect (kpImage *image,
0101         int x, int y, int width, int height,
0102         const kpColor &color);
0103 
0104     // Replaces all pixels of <colorToReplace> on the line
0105     // from (x1,y1) to (x2,y2) of <image>, with a pen of <color> with
0106     // dimensions <penWidth>x<penHeight>.
0107     //
0108     // The corners are centred at those coordinates so if <penWidth> > 1 or
0109     // <penHeight> > 1, the line is likely to extend past a rectangle with
0110     // those corners.
0111     //
0112     // Returns the dirty rectangle.
0113     static QRect washLine (kpImage *image,
0114         int x1, int y1, int x2, int y2,
0115         const kpColor &color, int penWidth, int penHeight,
0116         const kpColor &colorToReplace,
0117         int processedColorSimilarity);
0118 
0119     static QRect washRect (kpImage *image,
0120         int x, int y, int width, int height,
0121         const kpColor &color,
0122         const kpColor &colorToReplace,
0123         int processedColorSimilarity);
0124 
0125     // For each point in <points>, sprays a random pattern of 10 dots of <color>,
0126     // each within a circle of diameter <spraycanSize>, onto <image>.
0127     //
0128     // ASSUMPTION: spraycanSize > 0.
0129     // TODO: I think this diameter is 1 or 2 off.
0130     static void sprayPoints (kpImage *image,
0131         const QList <QPoint> &points,
0132         const kpColor &color,
0133         int spraycanSize);
0134 };
0135 
0136 
0137 #endif  // KP_PAINTER_H