1 // Aseprite
2 // Copyright (C) 2001-2016  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifndef APP_UI_EDITOR_BRUSH_PREVIEW_H_INCLUDED
8 #define APP_UI_EDITOR_BRUSH_PREVIEW_H_INCLUDED
9 #pragma once
10 
11 #include "app/extra_cel.h"
12 #include "base/shared_ptr.h"
13 #include "doc/brush.h"
14 #include "doc/color.h"
15 #include "doc/frame.h"
16 #include "doc/mask_boundaries.h"
17 #include "gfx/color.h"
18 #include "gfx/point.h"
19 #include "gfx/rect.h"
20 #include "gfx/region.h"
21 
22 #include <vector>
23 
24 namespace doc {
25   class Layer;
26   class Sprite;
27 }
28 
29 namespace ui {
30   class Graphics;
31 }
32 
33 namespace app {
34   class Editor;
35 
36   class BrushPreview {
37   public:
38     // Brush type
39     enum {
40       CROSSHAIR           = 1,
41       SELECTION_CROSSHAIR = 2,
42       BRUSH_BOUNDARIES    = 4,
43       NATIVE_CROSSHAIR    = 8,
44     };
45 
46     BrushPreview(Editor* editor);
47     ~BrushPreview();
48 
onScreen()49     bool onScreen() const { return m_onScreen; }
screenPosition()50     const gfx::Point& screenPosition() const { return m_screenPosition; }
51 
52     void show(const gfx::Point& screenPos);
53     void hide();
54     void redraw();
55     void discardBrushPreview();
56 
57     void invalidateRegion(const gfx::Region& region);
58 
59   private:
60     typedef void (BrushPreview::*PixelDelegate)(ui::Graphics*, const gfx::Point&, gfx::Color);
61 
62     doc::BrushRef getCurrentBrush();
63     static doc::color_t getBrushColor(doc::Sprite* sprite, doc::Layer* layer);
64 
65     void generateBoundaries();
66     void forEachBrushPixel(
67       ui::Graphics* g,
68       const gfx::Point& screenPos,
69       const gfx::Point& spritePos,
70       gfx::Color color,
71       PixelDelegate pixelDelegate);
72 
73     void traceCrossPixels(ui::Graphics* g, const gfx::Point& pt, gfx::Color color, PixelDelegate pixel);
74     void traceSelectionCrossPixels(ui::Graphics* g, const gfx::Point& pt, gfx::Color color, int thickness, PixelDelegate pixel);
75     void traceBrushBoundaries(ui::Graphics* g, gfx::Point pos, gfx::Color color, PixelDelegate pixel);
76 
77     void savePixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
78     void drawPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
79     void clearPixelDelegate(ui::Graphics* g, const gfx::Point& pt, gfx::Color color);
80 
81     Editor* m_editor;
82     int m_type;
83 
84     // The brush preview shows the cross or brush boundaries as black
85     // & white negative.
86     bool m_blackAndWhiteNegative;
87 
88     // The brush preview is on the screen.
89     bool m_onScreen;
90     bool m_withModifiedPixels;
91     bool m_withRealPreview;
92     gfx::Point m_screenPosition; // Position in the screen (view)
93     gfx::Point m_editorPosition; // Position in the editor (model)
94 
95     // Information about current brush
96     base::SharedPtr<doc::MaskBoundaries> m_brushBoundaries;
97     int m_brushGen;
98     int m_brushWidth;
99     int m_brushHeight;
100 
101     std::vector<gfx::Color> m_savedPixels;
102     int m_savedPixelsIterator;
103     int m_savedPixelsLimit;
104 
105     gfx::Region m_clippingRegion;
106     gfx::Region m_oldClippingRegion;
107 
108     // Information stored in show() and used in hide() to clear the
109     // brush preview in the exact same place.
110     gfx::Rect m_lastBounds;
111     doc::frame_t m_lastFrame;
112 
113     ExtraCelRef m_extraCel;
114   };
115 
116   class HideBrushPreview {
117   public:
HideBrushPreview(BrushPreview & brushPreview)118     HideBrushPreview(BrushPreview& brushPreview)
119       : m_brushPreview(brushPreview)
120       , m_oldScreenPosition(brushPreview.screenPosition())
121       , m_onScreen(brushPreview.onScreen()) {
122       if (m_onScreen)
123         m_brushPreview.hide();
124     }
125 
~HideBrushPreview()126     ~HideBrushPreview() {
127       if (m_onScreen)
128         m_brushPreview.show(m_oldScreenPosition);
129     }
130 
131   private:
132     BrushPreview& m_brushPreview;
133     gfx::Point m_oldScreenPosition;
134     bool m_onScreen;
135   };
136 
137 } // namespace app
138 
139 #endif
140