1// Aseprite UI Library
2// Copyright (C) 2018-2021 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "ui/manager.h"
13
14#include "os/surface.h"
15#include "os/system.h"
16#include "os/window.h"
17#include "ui/overlay_manager.h"
18
19#include <vector>
20
21namespace ui {
22
23using namespace gfx;
24
25void move_region(Display* display, const Region& region, int dx, int dy)
26{
27 ASSERT(display);
28 if (!display)
29 return;
30
31 os::Window* window = display->nativeWindow();
32 ASSERT(window);
33 if (!window)
34 return;
35
36 auto overlays = ui::OverlayManager::instance();
37 gfx::Rect bounds = region.bounds();
38 bounds |= gfx::Rect(bounds).offset(dx, dy);
39 overlays->restoreOverlappedAreas(bounds);
40
41 os::Surface* surface = window->surface();
42 os::SurfaceLock lock(surface);
43
44 // Fast path, move one rectangle.
45 if (region.isRect()) {
46 gfx::Rect rc = region.bounds();
47 surface->scrollTo(rc, dx, dy);
48
49 rc.offset(dx, dy);
50 display->dirtyRect(rc);
51 }
52 // As rectangles in the region internals are separated by bands
53 // through the y-axis, we can sort the rectangles by y-axis and then
54 // by x-axis to move rectangle by rectangle depending on the dx/dy
55 // direction so we don't overlap each rectangle.
56 else if (region.isComplex()) {
57 std::size_t nrects = region.size();
58 std::vector<gfx::Rect> rcs(nrects);
59 std::copy(region.begin(), region.end(), rcs.begin());
60
61 std::sort(
62 rcs.begin(), rcs.end(),
63 [dx, dy](const gfx::Rect& a, const gfx::Rect& b){
64 if (dy < 0) {
65 if (a.y < b.y)
66 return true;
67 else if (a.y == b.y) {
68 if (dx < 0)
69 return a.x < b.x;
70 else
71 return a.x > b.x;
72 }
73 else
74 return false;
75 }
76 else {
77 if (a.y > b.y)
78 return true;
79 else if (a.y == b.y) {
80 if (dx < 0)
81 return a.x < b.x;
82 else
83 return a.x > b.x;
84 }
85 else
86 return false;
87 }
88 });
89
90 for (gfx::Rect& rc : rcs) {
91 surface->scrollTo(rc, dx, dy);
92
93 rc.offset(dx, dy);
94 display->dirtyRect(rc);
95 }
96 }
97
98 overlays->drawOverlays();
99}
100
101} // namespace ui
102