1// Aseprite
2// Copyright (C) 2021 Igara Studio S.A.
3//
4// This program is distributed under the terms of
5// the End-User License Agreement for Aseprite.
6
7#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
11#include "app/tools/symmetry.h"
12
13 #include "app/tools/point_shape.h"
14 #include "app/tools/tool_loop.h"
15
16namespace app {
17namespace tools {
18
19void Symmetry::generateStrokes(const Stroke& stroke, Strokes& strokes,
20 ToolLoop* loop)
21{
22 Stroke stroke2;
23 strokes.push_back(stroke);
24 gen::SymmetryMode symmetryMode = loop->getSymmetry()->mode();
25 switch (symmetryMode) {
26 case gen::SymmetryMode::NONE:
27 ASSERT(false);
28 break;
29
30 case gen::SymmetryMode::HORIZONTAL:
31 case gen::SymmetryMode::VERTICAL:
32 calculateSymmetricalStroke(stroke, stroke2, loop, symmetryMode);
33 strokes.push_back(stroke2);
34 break;
35
36 case gen::SymmetryMode::BOTH: {
37 calculateSymmetricalStroke(stroke, stroke2, loop, gen::SymmetryMode::HORIZONTAL);
38 strokes.push_back(stroke2);
39
40 Stroke stroke3;
41 calculateSymmetricalStroke(stroke, stroke3, loop, gen::SymmetryMode::VERTICAL);
42 strokes.push_back(stroke3);
43
44 Stroke stroke4;
45 calculateSymmetricalStroke(stroke3, stroke4, loop, gen::SymmetryMode::BOTH);
46 strokes.push_back(stroke4);
47 break;
48 }
49 }
50}
51
52void Symmetry::calculateSymmetricalStroke(const Stroke& refStroke, Stroke& stroke,
53 ToolLoop* loop, gen::SymmetryMode symmetryMode)
54{
55 int brushSize, brushCenter;
56 if (loop->getPointShape()->isFloodFill()) {
57 brushSize = 1;
58 brushCenter = 0;
59 }
60 else {
61 // TODO we should flip the brush center+image+bitmap or just do
62 // the symmetry of all pixels
63 auto brush = loop->getBrush();
64 if (symmetryMode == gen::SymmetryMode::HORIZONTAL || symmetryMode == gen::SymmetryMode::BOTH) {
65 brushSize = brush->bounds().w;
66 brushCenter = brush->center().x;
67 }
68 else {
69 brushSize = brush->bounds().h;
70 brushCenter = brush->center().y;
71 }
72 }
73
74 const bool isDynamic = loop->getDynamics().isDynamic();
75 for (const auto& pt : refStroke) {
76 if (isDynamic) {
77 brushSize = pt.size;
78 brushCenter = (brushSize - brushSize % 2) / 2;
79 }
80 Stroke::Pt pt2 = pt;
81 pt2.symmetry = symmetryMode;
82 if (symmetryMode == gen::SymmetryMode::HORIZONTAL || symmetryMode == gen::SymmetryMode::BOTH)
83 pt2.x = 2 * (m_x + brushCenter) - pt2.x - brushSize;
84 else
85 pt2.y = 2 * (m_y + brushCenter) - pt2.y - brushSize;
86 stroke.addPoint(pt2);
87 }
88}
89
90} // namespace tools
91} // namespace app
92