1/*
2    PPFillTool.m
3
4    Copyright 2013-2018 Josh Freeman
5    http://www.twilightedge.com
6
7    This file is part of PikoPixel for Mac OS X and GNUstep.
8    PikoPixel is a graphical application for drawing & editing pixel-art images.
9
10    PikoPixel is free software: you can redistribute it and/or modify it under
11    the terms of the GNU Affero General Public License as published by the
12    Free Software Foundation, either version 3 of the License, or (at your
13    option) any later version approved for PikoPixel by its copyright holder (or
14    an authorized proxy).
15
16    PikoPixel is distributed in the hope that it will be useful, but WITHOUT ANY
17    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18    FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19    details.
20
21    You should have received a copy of the GNU Affero General Public License
22    along with this program. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#import "PPFillTool.h"
26
27#import "PPDocument.h"
28#import "PPCanvasView.h"
29#import "PPGeometry.h"
30#import "PPToolUtilities.h"
31#import "NSCursor_PPUtilities.h"
32
33
34#define kFillToolAttributesMask                                                     \
35            (kPPToolAttributeMask_RequiresPointsInViewCoordinates                   \
36            | kPPToolAttributeMask_DisableAutoscrolling                             \
37            | kPPToolAttributeMask_MatchCanvasDisplayModeToOperationTarget)
38
39
40@implementation PPFillTool
41
42- (void) mouseDownForDocument: (PPDocument *) ppDocument
43            withCanvasView: (PPCanvasView *) canvasView
44            currentPoint: (NSPoint) currentPoint
45            modifierKeyFlags: (unsigned) modifierKeyFlags
46{
47    unsigned colorMatchTolerance;
48    PPPixelMatchingMode pixelMatchingMode;
49    NSBitmapImageRep *matchMask;
50    NSRect matchMaskBounds;
51
52    // tool receives points in view coordinates, must convert to get image coordinates
53    _mouseDownLocationInImage = [canvasView imagePointFromViewPoint: currentPoint
54                                                clippedToCanvasBounds: YES];
55
56    colorMatchTolerance = 0;
57    pixelMatchingMode = PPToolUtils_PixelMatchingModeForModifierKeyFlags(modifierKeyFlags);
58
59    [ppDocument beginDrawingWithPenMode: kPPPenMode_Fill];
60
61    [ppDocument fillPixelsMatchingColorAtPoint: _mouseDownLocationInImage
62                    colorMatchTolerance: colorMatchTolerance
63                    pixelMatchingMode: pixelMatchingMode
64                    returnedMatchMask: &matchMask
65                    returnedMatchMaskBounds: &matchMaskBounds];
66
67    [canvasView beginFillToolOverlayForOperationTarget: [ppDocument layerOperationTarget]
68                    fillColor: [ppDocument fillColor]];
69
70    [canvasView setFillToolOverlayToMask: matchMask maskBounds: matchMaskBounds];
71
72    [canvasView showMatchToolToleranceIndicatorAtViewPoint: currentPoint];
73
74    _lastColorMatchTolerance = colorMatchTolerance;
75    _lastPixelMatchingMode = pixelMatchingMode;
76}
77
78- (void) mouseDraggedOrModifierKeysChangedForDocument: (PPDocument *) ppDocument
79            withCanvasView: (PPCanvasView *) canvasView
80            currentPoint: (NSPoint) currentPoint
81            lastPoint: (NSPoint) lastPoint
82            mouseDownPoint: (NSPoint) mouseDownPoint
83            modifierKeyFlags: (unsigned) modifierKeyFlags
84{
85    unsigned mouseDistance, colorMatchTolerance;
86    PPPixelMatchingMode pixelMatchingMode;
87    NSBitmapImageRep *matchMask;
88    NSRect matchMaskBounds;
89
90    mouseDistance = PPGeometry_IntegerDistanceBetweenPoints(mouseDownPoint, currentPoint);
91    colorMatchTolerance = PPToolUtils_ColorMatchToleranceForMouseDistance(mouseDistance);
92
93    pixelMatchingMode = PPToolUtils_PixelMatchingModeForModifierKeyFlags(modifierKeyFlags);
94
95    if ((colorMatchTolerance != _lastColorMatchTolerance)
96        || (pixelMatchingMode != _lastPixelMatchingMode))
97    {
98        [ppDocument undoCurrentDrawingAtNextDraw];
99
100        [ppDocument fillPixelsMatchingColorAtPoint: _mouseDownLocationInImage
101                        colorMatchTolerance: colorMatchTolerance
102                        pixelMatchingMode: pixelMatchingMode
103                        returnedMatchMask: &matchMask
104                        returnedMatchMaskBounds: &matchMaskBounds];
105
106        [canvasView setFillToolOverlayToMask: matchMask maskBounds: matchMaskBounds];
107
108        _lastColorMatchTolerance = colorMatchTolerance;
109        _lastPixelMatchingMode = pixelMatchingMode;
110    }
111
112    [canvasView setMatchToolToleranceIndicatorRadius: mouseDistance];
113}
114
115- (void) mouseUpForDocument: (PPDocument *) ppDocument
116            withCanvasView: (PPCanvasView *) canvasView
117            currentPoint: (NSPoint) currentPoint
118            mouseDownPoint: (NSPoint) mouseDownPoint
119            modifierKeyFlags: (unsigned) modifierKeyFlags
120{
121    [canvasView hideMatchToolToleranceIndicator];
122    [canvasView endFillToolOverlay];
123
124    [ppDocument finishDrawing];
125}
126
127- (NSCursor *) cursor
128{
129    return [NSCursor ppFillToolCursor];
130}
131
132- (unsigned) toolAttributeFlags
133{
134    return kFillToolAttributesMask;
135}
136
137@end
138