2015-02-15 20:48:38 +08:00
|
|
|
// Aseprite
|
2020-02-11 23:43:29 +08:00
|
|
|
// Copyright (C) 2019-2020 Igara Studio S.A.
|
2016-03-19 22:33:05 +08:00
|
|
|
// Copyright (C) 2001-2016 David Capello
|
2015-02-15 20:48:38 +08:00
|
|
|
//
|
2016-08-27 04:02:58 +08:00
|
|
|
// This program is distributed under the terms of
|
|
|
|
|
// the End-User License Agreement for Aseprite.
|
2015-02-15 20:48:38 +08:00
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "app/snap_to_grid.h"
|
|
|
|
|
|
|
|
|
|
#include "gfx/point.h"
|
|
|
|
|
#include "gfx/rect.h"
|
|
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
|
|
namespace app {
|
|
|
|
|
|
2016-03-19 22:33:05 +08:00
|
|
|
gfx::Point snap_to_grid(const gfx::Rect& grid,
|
|
|
|
|
const gfx::Point& point,
|
|
|
|
|
const PreferSnapTo prefer)
|
2015-02-15 20:48:38 +08:00
|
|
|
{
|
2019-05-18 05:11:14 +08:00
|
|
|
if (grid.isEmpty())
|
|
|
|
|
return point;
|
|
|
|
|
|
2015-02-15 20:48:38 +08:00
|
|
|
div_t d, dx, dy;
|
|
|
|
|
dx = std::div(grid.x, grid.w);
|
|
|
|
|
dy = std::div(grid.y, grid.h);
|
|
|
|
|
|
2020-02-11 23:43:29 +08:00
|
|
|
gfx::Point newPoint(point.x-dx.rem,
|
|
|
|
|
point.y-dy.rem);
|
|
|
|
|
if (prefer != PreferSnapTo::ClosestGridVertex) {
|
|
|
|
|
if (newPoint.x < 0) newPoint.x -= grid.w;
|
|
|
|
|
if (newPoint.y < 0) newPoint.y -= grid.h;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-19 22:33:05 +08:00
|
|
|
switch (prefer) {
|
2015-02-15 20:48:38 +08:00
|
|
|
|
2016-03-19 22:33:05 +08:00
|
|
|
case PreferSnapTo::ClosestGridVertex:
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.x, grid.w);
|
2016-03-19 22:33:05 +08:00
|
|
|
newPoint.x = dx.rem + d.quot*grid.w + ((d.rem > grid.w/2)? grid.w: 0);
|
|
|
|
|
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.y, grid.h);
|
2016-03-19 22:33:05 +08:00
|
|
|
newPoint.y = dy.rem + d.quot*grid.h + ((d.rem > grid.h/2)? grid.h: 0);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PreferSnapTo::BoxOrigin:
|
2019-02-08 01:03:11 +08:00
|
|
|
case PreferSnapTo::FloorGrid:
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.x, grid.w);
|
2016-03-19 22:33:05 +08:00
|
|
|
newPoint.x = dx.rem + d.quot*grid.w;
|
|
|
|
|
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.y, grid.h);
|
2016-03-19 22:33:05 +08:00
|
|
|
newPoint.y = dy.rem + d.quot*grid.h;
|
|
|
|
|
break;
|
2019-02-08 01:03:11 +08:00
|
|
|
|
|
|
|
|
case PreferSnapTo::CeilGrid:
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.x, grid.w);
|
|
|
|
|
newPoint.x = d.rem ? dx.rem + (d.quot+1)*grid.w: newPoint.x;
|
2019-02-08 01:03:11 +08:00
|
|
|
|
2020-02-11 23:43:29 +08:00
|
|
|
d = std::div(newPoint.y, grid.h);
|
|
|
|
|
newPoint.y = d.rem ? dy.rem + (d.quot+1)*grid.h: newPoint.y;
|
2019-02-08 01:03:11 +08:00
|
|
|
break;
|
2020-02-16 23:42:29 +08:00
|
|
|
|
|
|
|
|
case PreferSnapTo::BoxEnd:
|
|
|
|
|
d = std::div(newPoint.x, grid.w);
|
|
|
|
|
newPoint.x = dx.rem + (d.quot+1)*grid.w;
|
|
|
|
|
|
|
|
|
|
d = std::div(newPoint.y, grid.h);
|
|
|
|
|
newPoint.y = dy.rem + (d.quot+1)*grid.h;
|
|
|
|
|
break;
|
2016-03-19 22:33:05 +08:00
|
|
|
}
|
2015-02-15 20:48:38 +08:00
|
|
|
|
|
|
|
|
return newPoint;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace app
|