1// Aseprite
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2001-2015 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/tools/point_shape.h"
13
14#include "app/tools/ink.h"
15#include "app/tools/tool_loop.h"
16#include "app/util/wrap_value.h"
17#include "doc/brush.h"
18#include "doc/image.h"
19#include "doc/sprite.h"
20
21#include <algorithm>
22
23namespace app {
24namespace tools {
25
26using namespace doc;
27using namespace filters;
28
29void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
30{
31 Ink* ink = loop->getInk();
32 TiledMode tiledMode = loop->getTiledMode();
33 const int dstw = loop->getDstImage()->width();
34 const int dsth = loop->getDstImage()->height();
35 int x, w, size; // width or height
36
37 // In case the ink needs original cel coordinates, we have to
38 // translate the x1/y/x2 coordinate.
39 if (loop->needsCelCoordinates()) {
40 gfx::Point origin = loop->getCelOrigin();
41 x1 -= origin.x;
42 x2 -= origin.x;
43 y -= origin.y;
44 }
45
46 // Tiled in Y axis
47 if (int(tiledMode) & int(TiledMode::Y_AXIS)) {
48 size = dsth; // size = image height
49 y = wrap_value(y, size);
50 }
51 else if (y < 0 || y >= dsth) {
52 return;
53 }
54
55 // Tiled in X axis
56 if (int(tiledMode) & int(TiledMode::X_AXIS)) {
57 if (x1 > x2)
58 return;
59
60 size = dstw; // size = image width
61 w = x2-x1+1;
62 if (w >= size)
63 ink->inkHline(0, y, size-1, loop);
64 else {
65 x = wrap_value(x1, dstw);
66 if (x+w <= dstw) {
67 // Here we asure that tile limit line does not bisect the current
68 // scanline, i.e. the scanline is enterely contained inside the tile.
69 ink->prepareUForPointShapeWholeScanline(loop, x1);
70 ink->inkHline(x, y, x+w-1, loop);
71 }
72 else {
73 // Here the tile limit line bisect the current scanline.
74 // So we need to execute TWO times the inkHline function, each one with a different m_u.
75 ink->prepareUForPointShapeSlicedScanline(loop, true, x1);// true = left slice
76 ink->inkHline(x, y, size-1, loop);
77
78 ink->prepareUForPointShapeSlicedScanline(loop, false, x1);// false = right slice
79 ink->inkHline(0, y, w-(size-x)-1, loop);
80 }
81 }
82 }
83 // Clipped in X axis
84 else {
85 if (x2 < 0 || x1 >= dstw || x2-x1+1 < 1)
86 return;
87
88 x1 = std::clamp(x1, 0, dstw-1);
89 x2 = std::clamp(x2, 0, dstw-1);
90 ink->inkHline(x1, y, x2, loop);
91 }
92}
93
94} // namespace tools
95} // namespace app
96