1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "graphics/cursorman.h"
24
25 #include "common/system.h"
26 #include "common/stack.h"
27
28 namespace Common {
29 DECLARE_SINGLETON(Graphics::CursorManager);
30 }
31
32 namespace Graphics {
33
~CursorManager()34 CursorManager::~CursorManager() {
35 for (Common::Stack<Cursor *>::size_type i = 0; i < _cursorStack.size(); ++i)
36 delete _cursorStack[i];
37 _cursorStack.clear();
38 for (Common::Stack<Palette *>::size_type i = 0; i < _cursorPaletteStack.size(); ++i)
39 delete _cursorPaletteStack[i];
40 _cursorPaletteStack.clear();
41 }
42
isVisible()43 bool CursorManager::isVisible() {
44 if (_cursorStack.empty())
45 return false;
46 return _cursorStack.top()->_visible;
47 }
48
showMouse(bool visible)49 bool CursorManager::showMouse(bool visible) {
50 if (_cursorStack.empty())
51 return false;
52 if (_locked) {
53 return false;
54 }
55
56 _cursorStack.top()->_visible = visible;
57
58 // Should work, even if there's just a dummy cursor on the stack.
59 return g_system->showMouse(visible);
60 }
61
pushCursor(const void * buf,uint w,uint h,int hotspotX,int hotspotY,uint32 keycolor,bool dontScale,const Graphics::PixelFormat * format)62 void CursorManager::pushCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
63 Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, dontScale, format);
64
65 cur->_visible = isVisible();
66 _cursorStack.push(cur);
67
68 if (buf) {
69 g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format);
70 }
71 }
72
popCursor()73 void CursorManager::popCursor() {
74 if (_cursorStack.empty())
75 return;
76
77 Cursor *cur = _cursorStack.pop();
78 delete cur;
79
80 if (!_cursorStack.empty()) {
81 cur = _cursorStack.top();
82 g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_dontScale, &cur->_format);
83 }
84
85 g_system->showMouse(isVisible());
86 }
87
88
popAllCursors()89 void CursorManager::popAllCursors() {
90 while (!_cursorStack.empty()) {
91 Cursor *cur = _cursorStack.pop();
92 delete cur;
93 }
94
95 if (g_system->hasFeature(OSystem::kFeatureCursorPalette)) {
96 while (!_cursorPaletteStack.empty()) {
97 Palette *pal = _cursorPaletteStack.pop();
98 delete pal;
99 }
100 }
101
102 g_system->showMouse(isVisible());
103 }
104
replaceCursor(const void * buf,uint w,uint h,int hotspotX,int hotspotY,uint32 keycolor,bool dontScale,const Graphics::PixelFormat * format)105 void CursorManager::replaceCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
106
107 if (_cursorStack.empty()) {
108 pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, dontScale, format);
109 return;
110 }
111
112 Cursor *cur = _cursorStack.top();
113
114 #ifdef USE_RGB_COLOR
115 uint size;
116 if (!format)
117 size = w * h;
118 else
119 size = w * h * format->bytesPerPixel;
120 #else
121 uint size = w * h;
122 #endif
123
124 if (cur->_size < size) {
125 delete[] cur->_data;
126 cur->_data = new byte[size];
127 cur->_size = size;
128 }
129
130 if (buf && cur->_data)
131 memcpy(cur->_data, buf, size);
132
133 cur->_width = w;
134 cur->_height = h;
135 cur->_hotspotX = hotspotX;
136 cur->_hotspotY = hotspotY;
137 cur->_keycolor = keycolor;
138 cur->_dontScale = dontScale;
139 #ifdef USE_RGB_COLOR
140 if (format)
141 cur->_format = *format;
142 else
143 cur->_format = Graphics::PixelFormat::createFormatCLUT8();
144 #endif
145
146 g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format);
147 }
148
supportsCursorPalettes()149 bool CursorManager::supportsCursorPalettes() {
150 return g_system->hasFeature(OSystem::kFeatureCursorPalette);
151 }
152
disableCursorPalette(bool disable)153 void CursorManager::disableCursorPalette(bool disable) {
154 if (!g_system->hasFeature(OSystem::kFeatureCursorPalette))
155 return;
156
157 if (_cursorPaletteStack.empty())
158 return;
159
160 Palette *pal = _cursorPaletteStack.top();
161 pal->_disabled = disable;
162
163 g_system->setFeatureState(OSystem::kFeatureCursorPalette, !disable);
164 }
165
pushCursorPalette(const byte * colors,uint start,uint num)166 void CursorManager::pushCursorPalette(const byte *colors, uint start, uint num) {
167 if (!g_system->hasFeature(OSystem::kFeatureCursorPalette))
168 return;
169
170 Palette *pal = new Palette(colors, start, num);
171 _cursorPaletteStack.push(pal);
172
173 if (num)
174 g_system->setCursorPalette(colors, start, num);
175 else
176 g_system->setFeatureState(OSystem::kFeatureCursorPalette, false);
177 }
178
popCursorPalette()179 void CursorManager::popCursorPalette() {
180 if (!g_system->hasFeature(OSystem::kFeatureCursorPalette))
181 return;
182
183 if (_cursorPaletteStack.empty())
184 return;
185
186 Palette *pal = _cursorPaletteStack.pop();
187 delete pal;
188
189 if (_cursorPaletteStack.empty()) {
190 g_system->setFeatureState(OSystem::kFeatureCursorPalette, false);
191 return;
192 }
193
194 pal = _cursorPaletteStack.top();
195
196 if (pal->_num && !pal->_disabled)
197 g_system->setCursorPalette(pal->_data, pal->_start, pal->_num);
198 else
199 g_system->setFeatureState(OSystem::kFeatureCursorPalette, false);
200 }
201
replaceCursorPalette(const byte * colors,uint start,uint num)202 void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint num) {
203 if (!g_system->hasFeature(OSystem::kFeatureCursorPalette))
204 return;
205
206 if (_cursorPaletteStack.empty()) {
207 pushCursorPalette(colors, start, num);
208 return;
209 }
210
211 Palette *pal = _cursorPaletteStack.top();
212 uint size = 3 * num;
213
214 if (pal->_size < size) {
215 // Could not re-use the old buffer. Create a new one.
216 delete[] pal->_data;
217 pal->_data = new byte[size];
218 pal->_size = size;
219 }
220
221 pal->_start = start;
222 pal->_num = num;
223
224 if (num) {
225 memcpy(pal->_data, colors, size);
226 g_system->setCursorPalette(pal->_data, pal->_start, pal->_num);
227 } else {
228 g_system->setFeatureState(OSystem::kFeatureCursorPalette, false);
229 }
230 }
231
lock(bool locked)232 void CursorManager::lock(bool locked) {
233 _locked = locked;
234 }
235
Cursor(const void * data,uint w,uint h,int hotspotX,int hotspotY,uint32 keycolor,bool dontScale,const Graphics::PixelFormat * format)236 CursorManager::Cursor::Cursor(const void *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
237 #ifdef USE_RGB_COLOR
238 if (!format)
239 _format = Graphics::PixelFormat::createFormatCLUT8();
240 else
241 _format = *format;
242 _size = w * h * _format.bytesPerPixel;
243 _keycolor = keycolor & ((1 << (_format.bytesPerPixel << 3)) - 1);
244 #else
245 _format = Graphics::PixelFormat::createFormatCLUT8();
246 _size = w * h;
247 _keycolor = keycolor & 0xFF;
248 #endif
249 _data = new byte[_size];
250 if (data && _data)
251 memcpy(_data, data, _size);
252 _width = w;
253 _height = h;
254 _hotspotX = hotspotX;
255 _hotspotY = hotspotY;
256 _dontScale = dontScale;
257 _visible = false;
258 }
259
~Cursor()260 CursorManager::Cursor::~Cursor() {
261 delete[] _data;
262 }
263
Palette(const byte * colors,uint start,uint num)264 CursorManager::Palette::Palette(const byte *colors, uint start, uint num) {
265 _start = start;
266 _num = num;
267 _size = 3 * num;
268
269 if (num) {
270 _data = new byte[_size];
271 memcpy(_data, colors, _size);
272 } else {
273 _data = NULL;
274 }
275
276 _disabled = false;
277 }
278
~Palette()279 CursorManager::Palette::~Palette() {
280 delete[] _data;
281 }
282
283 } // End of namespace Graphics
284