1// Aseprite UI Library
2// Copyright (C) 2018-2022 Igara Studio S.A.
3// Copyright (C) 2001-2016 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/overlay.h"
13
14#include "os/surface.h"
15#include "os/system.h"
16#include "ui/display.h"
17
18namespace ui {
19
20Overlay::Overlay(Display* display,
21 const os::SurfaceRef& overlaySurface,
22 const gfx::Point& pos,
23 ZOrder zorder)
24 : m_display(display)
25 , m_surface(overlaySurface)
26 , m_overlap(nullptr)
27 , m_captured(nullptr)
28 , m_pos(pos)
29 , m_zorder(zorder)
30{
31}
32
33Overlay::~Overlay()
34{
35 ASSERT(!m_captured);
36
37 if (m_surface) {
38 if (m_display)
39 m_display->invalidateRect(bounds());
40 m_surface.reset();
41 }
42
43 if (m_overlap)
44 m_overlap.reset();
45}
46
47os::SurfaceRef Overlay::setSurface(const os::SurfaceRef& newSurface)
48{
49 os::SurfaceRef oldSurface = m_surface;
50 m_surface = newSurface;
51 return oldSurface;
52}
53
54gfx::Rect Overlay::bounds() const
55{
56 if (m_surface)
57 return gfx::Rect(m_pos.x, m_pos.y, m_surface->width(), m_surface->height());
58 else
59 return gfx::Rect(0, 0, 0, 0);
60}
61
62void Overlay::drawOverlay()
63{
64 if (!m_surface ||
65 !m_captured)
66 return;
67
68 os::SurfaceLock lock(m_surface.get());
69 m_captured->drawRgbaSurface(m_surface.get(), m_pos.x, m_pos.y);
70
71 m_display->dirtyRect(
72 gfx::Rect(m_pos.x, m_pos.y,
73 m_surface->width(),
74 m_surface->height()));
75}
76
77void Overlay::moveOverlay(const gfx::Point& newPos)
78{
79 if (m_captured)
80 restoreOverlappedArea(gfx::Rect());
81
82 m_pos = newPos;
83}
84
85void Overlay::captureOverlappedArea()
86{
87 if (!m_surface ||
88 m_captured)
89 return;
90
91 os::Surface* displaySurface = m_display->surface();
92 os::SurfaceLock lockDisplaySurface(displaySurface);
93
94 if (!m_overlap) {
95 // Use the same color space for the overlay as in the screen
96 m_overlap = os::instance()->makeSurface(m_surface->width(),
97 m_surface->height(),
98 displaySurface->colorSpace());
99 }
100
101 os::SurfaceLock lock(m_overlap.get());
102 displaySurface->blitTo(m_overlap.get(), m_pos.x, m_pos.y, 0, 0,
103 m_overlap->width(), m_overlap->height());
104 // TODO uncomment and test this when GPU support is added
105 //m_overlap->setImmutable();
106
107 m_captured = base::AddRef(displaySurface);
108}
109
110void Overlay::restoreOverlappedArea(const gfx::Rect& restoreBounds)
111{
112 if (!m_surface ||
113 !m_overlap ||
114 !m_captured)
115 return;
116
117 if (!restoreBounds.isEmpty() &&
118 !restoreBounds.intersects(bounds()))
119 return;
120
121 os::SurfaceLock lock(m_overlap.get());
122 m_overlap->blitTo(m_captured.get(), 0, 0, m_pos.x, m_pos.y,
123 m_overlap->width(), m_overlap->height());
124
125 m_display->dirtyRect(bounds());
126 m_captured = nullptr;
127}
128
129}
130