1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2004-12-09
7  * Description : image selection widget used by ratio crop tool.
8  *
9  * Copyright (C) 2007      by Jaromir Malenko <malenko at email.cz>
10  * Copyright (C) 2008      by Roberto Castagnola <roberto dot castagnola at gmail dot com>
11  * Copyright (C) 2004-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12  *
13  * This program is free software; you can redistribute it
14  * and/or modify it under the terms of the GNU General
15  * Public License as published by the Free Software Foundation;
16  * either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * ============================================================ */
25 
26 #ifndef DIGIKAM_EDITOR_RATIO_CROP_WIDGET_H
27 #define DIGIKAM_EDITOR_RATIO_CROP_WIDGET_H
28 
29 // Qt includes
30 
31 #include <QWidget>
32 #include <QRect>
33 #include <QColor>
34 
35 // Local includes
36 
37 #include "imageiface.h"
38 
39 using namespace Digikam;
40 
41 namespace DigikamEditorRatioCropToolPlugin
42 {
43 
44 class RatioCropWidget : public QWidget
45 {
46     Q_OBJECT
47 
48 public:
49 
50     enum RatioAspect               ///< Constrained Aspect Ratio list. See RatioCropWidget::setSelectionAspectRatioType() method for crop-value implementations.
51     {
52         RATIOCUSTOM = 0,           ///< Custom aspect ratio.
53         RATIO01X01,                ///< 1:1
54         RATIO02x01,                ///< 2:1
55         RATIO02x03,                ///< 2:3
56         RATIO03X01,                ///< 3:1
57         RATIO03X04,                ///< 3:4
58         RATIO04X01,                ///< 4:1
59         RATIO04X05,                ///< 4:5
60         RATIO05x07,                ///< 5:7
61         RATIO07x10,                ///< 7:10
62         RATIO08x05,                ///< 8:5
63         RATIO16x09,                ///< 19:9
64         RATIODINA0,                ///< DIN A
65         RATIOGOLDEN,               ///< Golden ratio : 1:1.618
66         RATIOCURRENT,              ///< Current loaded image aspect ratio
67         RATIONONE                  ///< No aspect ratio.
68     };
69 
70     enum Orient
71     {
72         Landscape = 0,
73         Portrait
74     };
75 
76     enum CenterType
77     {
78         CenterWidth = 0,           ///< Center selection to the center of image width.
79         CenterHeight,              ///< Center selection to the center of image height.
80         CenterImage                ///< Center selection to the center of image.
81     };
82 
83     // Proportion : Golden Ratio and Rule of Thirds. More information at this url:
84     // photoinf.com/General/Robert_Berdan/Composition_and_the_Elements_of_Visual_Design.htm
85 
86     enum GuideLineType
87     {
88         RulesOfThirds = 0,         ///< Line guides position to 1/3 width and height.
89         DiagonalMethod,            ///< Diagonal Method to improve composition.
90         HarmoniousTriangles,       ///< Harmonious Triangle to improve composition.
91         GoldenMean,                ///< Guides tools using Phi ratio (1.618).
92         GuideNone                  ///< No guide line.
93     };
94 
95 public:
96 
97     RatioCropWidget(int width, int height, QWidget* const parent = nullptr);
98     RatioCropWidget(int width, int height, bool initDrawing, QWidget* const parent = nullptr);
99     ~RatioCropWidget() override;
100 
101     void  setBackgroundColor(const QColor& bg);
102     void  setCenterSelection(int centerType=CenterImage);
103     void  setSelectionX(int x);
104     void  setSelectionY(int y);
105     void  setSelectionWidth(int w);
106     void  setSelectionHeight(int h);
107     void  setSelectionOrientation(int orient);
108     void  setIsDrawingSelection(bool draw);
109     void  setPreciseCrop(bool precise);
110     void  setAutoOrientation(bool orientation);
111     void  setSelectionAspectRatioType(int aspectRatioType);
112     void  setSelectionAspectRatioValue(int widthRatioValue, int heightRatioValue);
113     void  setGoldenGuideTypes(bool drawGoldenSection,  bool drawGoldenSpiralSection,
114                               bool drawGoldenSpiral,   bool drawGoldenTriangle,
115                               bool flipHorGoldenGuide, bool flipVerGoldenGuide);
116 
117     int   getOriginalImageWidth()   const;
118     int   getOriginalImageHeight()  const;
119     QRect getRegionSelection()      const;
120 
121     int   getMinWidthRange()        const;
122     int   getMinHeightRange()       const;
123     int   getMaxWidthRange()        const;
124     int   getMaxHeightRange()       const;
125     int   getWidthStep()            const;
126     int   getHeightStep()           const;
127 
128     bool  preciseCropAvailable()    const;
129 
130     void  resetSelection();
131     void  maxAspectSelection();
132 
133     ImageIface* imageIface()        const;
134 
135 public Q_SLOTS:
136 
137     void slotGuideLines(int guideLinesType);
138     void slotChangeGuideColor(const QColor& color);
139     void slotChangeGuideSize(int size);
140 
141 Q_SIGNALS:
142 
143     void signalSelectionMoved(const QRect& rect);
144     void signalSelectionChanged(const QRect& rect);
145     void signalSelectionOrientationChanged(int newOrientation);
146 
147 protected:
148 
149     void paintEvent(QPaintEvent*)           override;
150     void mousePressEvent(QMouseEvent*)      override;
151     void mouseReleaseEvent(QMouseEvent*)    override;
152     void mouseMoveEvent(QMouseEvent*)       override;
153     void resizeEvent(QResizeEvent*)         override;
154 
155 private:
156 
157     // Recalculate the target selection position and emit 'signalSelectionMoved'.
158     void   regionSelectionMoved();
159     void   regionSelectionChanged();
160 
161     QPoint convertPoint(const QPoint& pm, bool localToReal=true) const;
162     QPoint convertPoint(int x, int y, bool localToReal=true)     const;
163     QPoint opposite()                                            const;
164 
165     void   normalizeRegion();
166     void   reverseRatioValues();
167     void   applyAspectRatio(bool useHeight, bool repaintWidget=true);
168     void   updatePixmap();
169     void   placeSelection(const QPoint& pm, bool symmetric, const QPoint& center);
170     void   setCursorResizing();
171 
172     float  distance(const QPoint& a, const QPoint& b) const;
173     int    computePreciseSize(int size, int step)     const;
174 
175     // drawing functions for the various guide types
176     void   drawRulesOfThirds(QPainter& p, const int& xThird, const int& yThird);
177     void   drawDiagonalMethod(QPainter& p, const int& w, const int& h);
178     void   drawHarmoniousTriangles(QPainter& p, const int& dst);
179     void   drawGoldenMean(QPainter& p, const QRect& R1, const QRect& R2,
180                           const QRect& R3, const QRect& R4, const QRect& R5,
181                           const QRect& R6, const QRect& R7);
182 
183     void setup(int width, int height,
184                int widthRatioValue = 1, int heightRatioValue = 1,
185                int aspectRatio = RATIO01X01, int orient = Landscape,
186                int guideLinesType = GuideNone);
187 
188 private:
189 
190     class Private;
191     Private* const d;
192 };
193 
194 } // namespace DigikamEditorRatioCropToolPlugin
195 
196 #endif // DIGIKAM_EDITOR_RATIO_CROP_WIDGET_H
197