Mercurial > sdl-ios-xcode
annotate src/video/SDL_cursor.c @ 1057:e9d23bb80140
Date: Mon, 02 May 2005 04:23:16 -0500
From: Jonathan Atkins
Subject: Re: [PATCH] *CRITICAL* 8bit direct RGB palette not being created
I think that SDL_AllocFormat should create the palette for all 8bit
surfaces. And when the RGBAmasks match the normal 3:3:2:0 we need to
apply the old behavior. If the mask doesn't match that, then we need
to make the right palette assuming the masks are valid (I don't think
we validate any masks for high color surfaces...so we wouldn't here)
Then there's always a palette available for the 8bit surfaces.
This restores the normal behavior and allows for masks to create
palettes automatically for odd masks even, which would be a neato
thing to have in there, as SDL never did this before.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 16 May 2005 05:34:58 +0000 |
parents | b8d311d90021 |
children | af8b0f9ac2f4 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
595
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
113
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* General cursor handling code for SDL */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 | |
34 #include "SDL_mutex.h" | |
35 #include "SDL_error.h" | |
36 #include "SDL_video.h" | |
37 #include "SDL_mouse.h" | |
38 #include "SDL_blit.h" | |
39 #include "SDL_events_c.h" | |
40 #include "SDL_sysvideo.h" | |
41 #include "SDL_sysevents.h" | |
42 #include "SDL_cursor_c.h" | |
43 #include "SDL_pixels_c.h" | |
44 #include "default_cursor.h" | |
45 | |
46 /* These are static for our cursor handling code */ | |
47 volatile int SDL_cursorstate = CURSOR_VISIBLE; | |
48 SDL_Cursor *SDL_cursor = NULL; | |
49 static SDL_Cursor *SDL_defcursor = NULL; | |
50 SDL_mutex *SDL_cursorlock = NULL; | |
51 | |
52 /* Public functions */ | |
53 void SDL_CursorQuit(void) | |
54 { | |
55 if ( SDL_cursor != NULL ) { | |
56 SDL_Cursor *cursor; | |
57 | |
58 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
59 if ( SDL_cursor != SDL_defcursor ) { | |
60 SDL_FreeCursor(SDL_cursor); | |
61 } | |
62 SDL_cursor = NULL; | |
63 if ( SDL_defcursor != NULL ) { | |
64 cursor = SDL_defcursor; | |
65 SDL_defcursor = NULL; | |
66 SDL_FreeCursor(cursor); | |
67 } | |
68 } | |
69 if ( SDL_cursorlock != NULL ) { | |
70 SDL_DestroyMutex(SDL_cursorlock); | |
71 SDL_cursorlock = NULL; | |
72 } | |
73 } | |
74 int SDL_CursorInit(Uint32 multithreaded) | |
75 { | |
76 /* We don't have mouse focus, and the cursor isn't drawn yet */ | |
77 SDL_cursorstate = CURSOR_VISIBLE; | |
78 | |
79 /* Create the default cursor */ | |
80 if ( SDL_defcursor == NULL ) { | |
81 SDL_defcursor = SDL_CreateCursor(default_cdata, default_cmask, | |
82 DEFAULT_CWIDTH, DEFAULT_CHEIGHT, | |
83 DEFAULT_CHOTX, DEFAULT_CHOTY); | |
84 SDL_SetCursor(SDL_defcursor); | |
85 } | |
86 | |
87 /* Create a lock if necessary */ | |
88 if ( multithreaded ) { | |
89 SDL_cursorlock = SDL_CreateMutex(); | |
90 } | |
91 | |
92 /* That's it! */ | |
93 return(0); | |
94 } | |
95 | |
96 /* Multi-thread support for cursors */ | |
97 #ifndef SDL_LockCursor | |
98 void SDL_LockCursor(void) | |
99 { | |
100 if ( SDL_cursorlock ) { | |
101 SDL_mutexP(SDL_cursorlock); | |
102 } | |
103 } | |
104 #endif | |
105 #ifndef SDL_UnlockCursor | |
106 void SDL_UnlockCursor(void) | |
107 { | |
108 if ( SDL_cursorlock ) { | |
109 SDL_mutexV(SDL_cursorlock); | |
110 } | |
111 } | |
112 #endif | |
113 | |
114 /* Software cursor drawing support */ | |
115 SDL_Cursor * SDL_CreateCursor (Uint8 *data, Uint8 *mask, | |
116 int w, int h, int hot_x, int hot_y) | |
117 { | |
118 SDL_VideoDevice *video = current_video; | |
119 int savelen; | |
120 int i; | |
121 SDL_Cursor *cursor; | |
122 | |
123 /* Make sure the width is a multiple of 8 */ | |
124 w = ((w+7)&~7); | |
125 | |
126 /* Sanity check the hot spot */ | |
127 if ( (hot_x < 0) || (hot_y < 0) || (hot_x >= w) || (hot_y >= h) ) { | |
128 SDL_SetError("Cursor hot spot doesn't lie within cursor"); | |
129 return(NULL); | |
130 } | |
131 | |
132 /* Allocate memory for the cursor */ | |
133 cursor = (SDL_Cursor *)malloc(sizeof *cursor); | |
134 if ( cursor == NULL ) { | |
135 SDL_OutOfMemory(); | |
136 return(NULL); | |
137 } | |
138 savelen = (w*4)*h; | |
139 cursor->area.x = 0; | |
140 cursor->area.y = 0; | |
141 cursor->area.w = w; | |
142 cursor->area.h = h; | |
143 cursor->hot_x = hot_x; | |
144 cursor->hot_y = hot_y; | |
145 cursor->data = (Uint8 *)malloc((w/8)*h*2); | |
146 cursor->mask = cursor->data+((w/8)*h); | |
147 cursor->save[0] = (Uint8 *)malloc(savelen*2); | |
148 cursor->save[1] = cursor->save[0] + savelen; | |
149 cursor->wm_cursor = NULL; | |
150 if ( ! cursor->data || ! cursor->save[0] ) { | |
151 SDL_FreeCursor(cursor); | |
152 SDL_OutOfMemory(); | |
153 return(NULL); | |
154 } | |
155 for ( i=((w/8)*h)-1; i>=0; --i ) { | |
156 cursor->data[i] = data[i]; | |
157 cursor->mask[i] = mask[i] | data[i]; | |
158 } | |
159 memset(cursor->save[0], 0, savelen*2); | |
160 | |
161 /* If the window manager gives us a good cursor, we're done! */ | |
162 if ( video->CreateWMCursor ) { | |
163 cursor->wm_cursor = video->CreateWMCursor(video, data, mask, | |
164 w, h, hot_x, hot_y); | |
165 } else { | |
166 cursor->wm_cursor = NULL; | |
167 } | |
168 return(cursor); | |
169 } | |
170 | |
171 /* SDL_SetCursor(NULL) can be used to force the cursor redraw, | |
172 if this is desired for any reason. This is used when setting | |
173 the video mode and when the SDL window gains the mouse focus. | |
174 */ | |
175 void SDL_SetCursor (SDL_Cursor *cursor) | |
176 { | |
177 SDL_VideoDevice *video = current_video; | |
178 SDL_VideoDevice *this = current_video; | |
179 | |
180 /* Make sure that the video subsystem has been initialized */ | |
181 if ( ! video ) { | |
182 return; | |
183 } | |
184 | |
185 /* Prevent the event thread from moving the mouse */ | |
186 SDL_LockCursor(); | |
187 | |
188 /* Set the new cursor */ | |
189 if ( cursor && (cursor != SDL_cursor) ) { | |
190 /* Erase the current mouse position */ | |
191 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
192 SDL_EraseCursor(SDL_VideoSurface); | |
193 } else if ( video->MoveWMCursor ) { | |
194 /* If the video driver is moving the cursor directly, | |
195 it needs to hide the old cursor before (possibly) | |
196 showing the new one. (But don't erase NULL cursor) | |
197 */ | |
198 if ( SDL_cursor ) { | |
199 video->ShowWMCursor(this, NULL); | |
200 } | |
201 } | |
202 SDL_cursor = cursor; | |
203 } | |
204 | |
205 /* Draw the new mouse cursor */ | |
206 if ( SDL_cursor && (SDL_cursorstate&CURSOR_VISIBLE) ) { | |
207 /* Use window manager cursor if possible */ | |
208 if ( SDL_cursor->wm_cursor && | |
209 video->ShowWMCursor(this, SDL_cursor->wm_cursor) ) | |
210 SDL_cursorstate &= ~CURSOR_USINGSW; | |
211 else { | |
212 SDL_cursorstate |= CURSOR_USINGSW; | |
213 if ( video->ShowWMCursor ) { | |
214 video->ShowWMCursor(this, NULL); | |
215 } | |
216 { int x, y; | |
217 SDL_GetMouseState(&x, &y); | |
218 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
219 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
220 } | |
221 SDL_DrawCursor(SDL_VideoSurface); | |
222 } | |
223 } else { | |
224 /* Erase window manager mouse (cursor not visible) */ | |
225 if ( SDL_cursor && (SDL_cursorstate & CURSOR_USINGSW) ) { | |
226 SDL_EraseCursor(SDL_VideoSurface); | |
227 } else { | |
228 if ( video ) { | |
229 video->ShowWMCursor(this, NULL); | |
230 } | |
231 } | |
232 } | |
233 SDL_UnlockCursor(); | |
234 } | |
235 | |
236 SDL_Cursor * SDL_GetCursor (void) | |
237 { | |
238 return(SDL_cursor); | |
239 } | |
240 | |
241 void SDL_FreeCursor (SDL_Cursor *cursor) | |
242 { | |
243 if ( cursor ) { | |
244 if ( cursor == SDL_cursor ) { | |
245 SDL_SetCursor(SDL_defcursor); | |
246 } | |
247 if ( cursor != SDL_defcursor ) { | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
248 SDL_VideoDevice *video = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
249 SDL_VideoDevice *this = current_video; |
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
250 |
0 | 251 if ( cursor->data ) { |
252 free(cursor->data); | |
253 } | |
254 if ( cursor->save[0] ) { | |
255 free(cursor->save[0]); | |
256 } | |
77
1e7e61b9b0f9
Don't crash if freeing a cursor after quit...
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
257 if ( video && cursor->wm_cursor ) { |
0 | 258 video->FreeWMCursor(this, cursor->wm_cursor); |
259 } | |
260 free(cursor); | |
261 } | |
262 } | |
263 } | |
264 | |
265 int SDL_ShowCursor (int toggle) | |
266 { | |
267 int showing; | |
268 | |
269 showing = (SDL_cursorstate & CURSOR_VISIBLE); | |
270 if ( toggle >= 0 ) { | |
271 SDL_LockCursor(); | |
272 if ( toggle ) { | |
273 SDL_cursorstate |= CURSOR_VISIBLE; | |
274 } else { | |
275 SDL_cursorstate &= ~CURSOR_VISIBLE; | |
276 } | |
277 SDL_UnlockCursor(); | |
278 if ( (SDL_cursorstate & CURSOR_VISIBLE) != showing ) { | |
279 SDL_VideoDevice *video = current_video; | |
280 SDL_VideoDevice *this = current_video; | |
281 | |
282 SDL_SetCursor(NULL); | |
283 if ( video && video->CheckMouseMode ) { | |
284 video->CheckMouseMode(this); | |
285 } | |
286 } | |
287 } else { | |
288 /* Query current state */ ; | |
289 } | |
290 return(showing ? 1 : 0); | |
291 } | |
292 | |
293 void SDL_WarpMouse (Uint16 x, Uint16 y) | |
294 { | |
295 SDL_VideoDevice *video = current_video; | |
296 SDL_VideoDevice *this = current_video; | |
297 | |
595
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
298 if ( !video || !SDL_PublicSurface ) { |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
299 SDL_SetError("A video mode must be set before warping mouse"); |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
300 return; |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
301 } |
591b438ab94a
Don't warp the mouse when a video mode hasn't been set
Sam Lantinga <slouken@libsdl.org>
parents:
527
diff
changeset
|
302 |
527
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
303 /* If we have an offset video mode, offset the mouse coordinates */ |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
304 x += (this->screen->offset % this->screen->pitch) / |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
305 this->screen->format->BytesPerPixel; |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
306 y += (this->screen->offset / this->screen->pitch); |
5c74ac147358
Fixed mouse warp position bug with offset video modes
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
307 |
0 | 308 /* This generates a mouse motion event */ |
309 if ( video->WarpWMCursor ) { | |
310 video->WarpWMCursor(this, x, y); | |
311 } else { | |
312 SDL_PrivateMouseMotion(0, 0, x, y); | |
313 } | |
314 } | |
315 | |
316 void SDL_MoveCursor(int x, int y) | |
317 { | |
318 SDL_VideoDevice *video = current_video; | |
319 | |
320 /* Erase and update the current mouse position */ | |
321 if ( SHOULD_DRAWCURSOR(SDL_cursorstate) ) { | |
322 /* Erase and redraw mouse cursor in new position */ | |
323 SDL_LockCursor(); | |
324 SDL_EraseCursor(SDL_VideoSurface); | |
325 SDL_cursor->area.x = (x - SDL_cursor->hot_x); | |
326 SDL_cursor->area.y = (y - SDL_cursor->hot_y); | |
327 SDL_DrawCursor(SDL_VideoSurface); | |
328 SDL_UnlockCursor(); | |
329 } else if ( video->MoveWMCursor ) { | |
330 video->MoveWMCursor(video, x, y); | |
331 } | |
332 } | |
333 | |
334 /* Keep track of the current cursor colors */ | |
335 static int palette_changed = 1; | |
336 static Uint32 pixels8[2]; | |
337 | |
338 void SDL_CursorPaletteChanged(void) | |
339 { | |
340 palette_changed = 1; | |
341 } | |
342 | |
343 void SDL_MouseRect(SDL_Rect *area) | |
344 { | |
345 int clip_diff; | |
346 | |
347 *area = SDL_cursor->area; | |
348 if ( area->x < 0 ) { | |
349 area->w += area->x; | |
350 area->x = 0; | |
351 } | |
352 if ( area->y < 0 ) { | |
353 area->h += area->y; | |
354 area->y = 0; | |
355 } | |
356 clip_diff = (area->x+area->w)-SDL_VideoSurface->w; | |
357 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
358 area->w = area->w < clip_diff ? 0 : area->w-clip_diff; |
0 | 359 } |
360 clip_diff = (area->y+area->h)-SDL_VideoSurface->h; | |
361 if ( clip_diff > 0 ) { | |
113
e21ac1dd30f1
Fixed crash if mouse is outside of the screen bounds for some reason
Sam Lantinga <slouken@lokigames.com>
parents:
77
diff
changeset
|
362 area->h = area->h < clip_diff ? 0 : area->h-clip_diff; |
0 | 363 } |
364 } | |
365 | |
366 static void SDL_DrawCursorFast(SDL_Surface *screen, SDL_Rect *area) | |
367 { | |
368 const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 }; | |
369 int i, w, h; | |
370 Uint8 *data, datab; | |
371 Uint8 *mask, maskb; | |
372 | |
373 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
374 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
375 switch (screen->format->BytesPerPixel) { | |
376 | |
377 case 1: { | |
378 Uint8 *dst; | |
379 int dstskip; | |
380 | |
381 if ( palette_changed ) { | |
382 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255); | |
383 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0); | |
384 palette_changed = 0; | |
385 } | |
386 dst = (Uint8 *)screen->pixels + | |
387 (SDL_cursor->area.y+area->y)*screen->pitch + | |
388 SDL_cursor->area.x; | |
389 dstskip = screen->pitch-area->w; | |
390 | |
391 for ( h=area->h; h; h-- ) { | |
392 for ( w=area->w/8; w; w-- ) { | |
393 maskb = *mask++; | |
394 datab = *data++; | |
395 for ( i=0; i<8; ++i ) { | |
396 if ( maskb & 0x80 ) { | |
397 *dst = pixels8[datab>>7]; | |
398 } | |
399 maskb <<= 1; | |
400 datab <<= 1; | |
401 dst++; | |
402 } | |
403 } | |
404 dst += dstskip; | |
405 } | |
406 } | |
407 break; | |
408 | |
409 case 2: { | |
410 Uint16 *dst; | |
411 int dstskip; | |
412 | |
413 dst = (Uint16 *)screen->pixels + | |
414 (SDL_cursor->area.y+area->y)*screen->pitch/2 + | |
415 SDL_cursor->area.x; | |
416 dstskip = (screen->pitch/2)-area->w; | |
417 | |
418 for ( h=area->h; h; h-- ) { | |
419 for ( w=area->w/8; w; w-- ) { | |
420 maskb = *mask++; | |
421 datab = *data++; | |
422 for ( i=0; i<8; ++i ) { | |
423 if ( maskb & 0x80 ) { | |
424 *dst = pixels[datab>>7]; | |
425 } | |
426 maskb <<= 1; | |
427 datab <<= 1; | |
428 dst++; | |
429 } | |
430 } | |
431 dst += dstskip; | |
432 } | |
433 } | |
434 break; | |
435 | |
436 case 3: { | |
437 Uint8 *dst; | |
438 int dstskip; | |
439 | |
440 dst = (Uint8 *)screen->pixels + | |
441 (SDL_cursor->area.y+area->y)*screen->pitch + | |
442 SDL_cursor->area.x*3; | |
443 dstskip = screen->pitch-area->w*3; | |
444 | |
445 for ( h=area->h; h; h-- ) { | |
446 for ( w=area->w/8; w; w-- ) { | |
447 maskb = *mask++; | |
448 datab = *data++; | |
449 for ( i=0; i<8; ++i ) { | |
450 if ( maskb & 0x80 ) { | |
451 memset(dst,pixels[datab>>7],3); | |
452 } | |
453 maskb <<= 1; | |
454 datab <<= 1; | |
455 dst += 3; | |
456 } | |
457 } | |
458 dst += dstskip; | |
459 } | |
460 } | |
461 break; | |
462 | |
463 case 4: { | |
464 Uint32 *dst; | |
465 int dstskip; | |
466 | |
467 dst = (Uint32 *)screen->pixels + | |
468 (SDL_cursor->area.y+area->y)*screen->pitch/4 + | |
469 SDL_cursor->area.x; | |
470 dstskip = (screen->pitch/4)-area->w; | |
471 | |
472 for ( h=area->h; h; h-- ) { | |
473 for ( w=area->w/8; w; w-- ) { | |
474 maskb = *mask++; | |
475 datab = *data++; | |
476 for ( i=0; i<8; ++i ) { | |
477 if ( maskb & 0x80 ) { | |
478 *dst = pixels[datab>>7]; | |
479 } | |
480 maskb <<= 1; | |
481 datab <<= 1; | |
482 dst++; | |
483 } | |
484 } | |
485 dst += dstskip; | |
486 } | |
487 } | |
488 break; | |
489 } | |
490 } | |
491 | |
492 static void SDL_DrawCursorSlow(SDL_Surface *screen, SDL_Rect *area) | |
493 { | |
494 const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 }; | |
495 int h; | |
496 int x, minx, maxx; | |
497 Uint8 *data, datab = 0; | |
498 Uint8 *mask, maskb = 0; | |
499 Uint8 *dst; | |
500 int dstbpp, dstskip; | |
501 | |
502 data = SDL_cursor->data + area->y * SDL_cursor->area.w/8; | |
503 mask = SDL_cursor->mask + area->y * SDL_cursor->area.w/8; | |
504 dstbpp = screen->format->BytesPerPixel; | |
505 dst = (Uint8 *)screen->pixels + | |
506 (SDL_cursor->area.y+area->y)*screen->pitch + | |
507 SDL_cursor->area.x*dstbpp; | |
508 dstskip = screen->pitch-SDL_cursor->area.w*dstbpp; | |
509 | |
510 minx = area->x; | |
511 maxx = area->x+area->w; | |
512 if ( screen->format->BytesPerPixel == 1 ) { | |
513 if ( palette_changed ) { | |
514 pixels8[0] = SDL_MapRGB(screen->format, 255, 255, 255); | |
515 pixels8[1] = SDL_MapRGB(screen->format, 0, 0, 0); | |
516 palette_changed = 0; | |
517 } | |
518 for ( h=area->h; h; h-- ) { | |
519 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
520 if ( (x%8) == 0 ) { | |
521 maskb = *mask++; | |
522 datab = *data++; | |
523 } | |
524 if ( (x >= minx) && (x < maxx) ) { | |
525 if ( maskb & 0x80 ) { | |
526 memset(dst, pixels8[datab>>7], dstbpp); | |
527 } | |
528 } | |
529 maskb <<= 1; | |
530 datab <<= 1; | |
531 dst += dstbpp; | |
532 } | |
533 dst += dstskip; | |
534 } | |
535 } else { | |
536 for ( h=area->h; h; h-- ) { | |
537 for ( x=0; x<SDL_cursor->area.w; ++x ) { | |
538 if ( (x%8) == 0 ) { | |
539 maskb = *mask++; | |
540 datab = *data++; | |
541 } | |
542 if ( (x >= minx) && (x < maxx) ) { | |
543 if ( maskb & 0x80 ) { | |
544 memset(dst, pixels[datab>>7], dstbpp); | |
545 } | |
546 } | |
547 maskb <<= 1; | |
548 datab <<= 1; | |
549 dst += dstbpp; | |
550 } | |
551 dst += dstskip; | |
552 } | |
553 } | |
554 } | |
555 | |
556 /* This handles the ugly work of converting the saved cursor background from | |
557 the pixel format of the shadow surface to that of the video surface. | |
558 This is only necessary when blitting from a shadow surface of a different | |
559 pixel format than the video surface, and using a software rendered cursor. | |
560 */ | |
561 static void SDL_ConvertCursorSave(SDL_Surface *screen, int w, int h) | |
562 { | |
563 SDL_BlitInfo info; | |
564 SDL_loblit RunBlit; | |
565 | |
566 /* Make sure we can steal the blit mapping */ | |
567 if ( screen->map->dst != SDL_VideoSurface ) { | |
568 return; | |
569 } | |
570 | |
571 /* Set up the blit information */ | |
572 info.s_pixels = SDL_cursor->save[1]; | |
573 info.s_width = w; | |
574 info.s_height = h; | |
575 info.s_skip = 0; | |
576 info.d_pixels = SDL_cursor->save[0]; | |
577 info.d_width = w; | |
578 info.d_height = h; | |
579 info.d_skip = 0; | |
580 info.aux_data = screen->map->sw_data->aux_data; | |
581 info.src = screen->format; | |
582 info.table = screen->map->table; | |
583 info.dst = SDL_VideoSurface->format; | |
584 RunBlit = screen->map->sw_data->blit; | |
585 | |
586 /* Run the actual software blit */ | |
587 RunBlit(&info); | |
588 } | |
589 | |
590 void SDL_DrawCursorNoLock(SDL_Surface *screen) | |
591 { | |
592 SDL_Rect area; | |
593 | |
594 /* Get the mouse rectangle, clipped to the screen */ | |
595 SDL_MouseRect(&area); | |
596 if ( (area.w == 0) || (area.h == 0) ) { | |
597 return; | |
598 } | |
599 | |
600 /* Copy mouse background */ | |
601 { int w, h, screenbpp; | |
602 Uint8 *src, *dst; | |
603 | |
604 /* Set up the copy pointers */ | |
605 screenbpp = screen->format->BytesPerPixel; | |
606 if ( (screen == SDL_VideoSurface) || | |
607 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
608 dst = SDL_cursor->save[0]; | |
609 } else { | |
610 dst = SDL_cursor->save[1]; | |
611 } | |
612 src = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
613 area.x * screenbpp; | |
614 | |
615 /* Perform the copy */ | |
616 w = area.w*screenbpp; | |
617 h = area.h; | |
618 while ( h-- ) { | |
619 memcpy(dst, src, w); | |
620 dst += w; | |
621 src += screen->pitch; | |
622 } | |
623 } | |
624 | |
625 /* Draw the mouse cursor */ | |
626 area.x -= SDL_cursor->area.x; | |
627 area.y -= SDL_cursor->area.y; | |
628 if ( (area.x == 0) && (area.w == SDL_cursor->area.w) ) { | |
629 SDL_DrawCursorFast(screen, &area); | |
630 } else { | |
631 SDL_DrawCursorSlow(screen, &area); | |
632 } | |
633 } | |
634 | |
635 void SDL_DrawCursor(SDL_Surface *screen) | |
636 { | |
637 /* Lock the screen if necessary */ | |
638 if ( screen == NULL ) { | |
639 return; | |
640 } | |
641 if ( SDL_MUSTLOCK(screen) ) { | |
642 if ( SDL_LockSurface(screen) < 0 ) { | |
643 return; | |
644 } | |
645 } | |
646 | |
647 SDL_DrawCursorNoLock(screen); | |
648 | |
649 /* Unlock the screen and update if necessary */ | |
650 if ( SDL_MUSTLOCK(screen) ) { | |
651 SDL_UnlockSurface(screen); | |
652 } | |
653 if ( (screen == SDL_VideoSurface) && | |
654 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
655 SDL_VideoDevice *video = current_video; | |
656 SDL_VideoDevice *this = current_video; | |
657 SDL_Rect area; | |
658 | |
659 SDL_MouseRect(&area); | |
660 | |
661 /* This can be called before a video mode is set */ | |
662 if ( video->UpdateRects ) { | |
663 video->UpdateRects(this, 1, &area); | |
664 } | |
665 } | |
666 } | |
667 | |
668 void SDL_EraseCursorNoLock(SDL_Surface *screen) | |
669 { | |
670 SDL_Rect area; | |
671 | |
672 /* Get the mouse rectangle, clipped to the screen */ | |
673 SDL_MouseRect(&area); | |
674 if ( (area.w == 0) || (area.h == 0) ) { | |
675 return; | |
676 } | |
677 | |
678 /* Copy mouse background */ | |
679 { int w, h, screenbpp; | |
680 Uint8 *src, *dst; | |
681 | |
682 /* Set up the copy pointers */ | |
683 screenbpp = screen->format->BytesPerPixel; | |
684 if ( (screen == SDL_VideoSurface) || | |
685 FORMAT_EQUAL(screen->format, SDL_VideoSurface->format) ) { | |
686 src = SDL_cursor->save[0]; | |
687 } else { | |
688 src = SDL_cursor->save[1]; | |
689 } | |
690 dst = (Uint8 *)screen->pixels + area.y * screen->pitch + | |
691 area.x * screenbpp; | |
692 | |
693 /* Perform the copy */ | |
694 w = area.w*screenbpp; | |
695 h = area.h; | |
696 while ( h-- ) { | |
697 memcpy(dst, src, w); | |
698 src += w; | |
699 dst += screen->pitch; | |
700 } | |
701 | |
702 /* Perform pixel conversion on cursor background */ | |
703 if ( src > SDL_cursor->save[1] ) { | |
704 SDL_ConvertCursorSave(screen, area.w, area.h); | |
705 } | |
706 } | |
707 } | |
708 | |
709 void SDL_EraseCursor(SDL_Surface *screen) | |
710 { | |
711 /* Lock the screen if necessary */ | |
712 if ( screen == NULL ) { | |
713 return; | |
714 } | |
715 if ( SDL_MUSTLOCK(screen) ) { | |
716 if ( SDL_LockSurface(screen) < 0 ) { | |
717 return; | |
718 } | |
719 } | |
720 | |
721 SDL_EraseCursorNoLock(screen); | |
722 | |
723 /* Unlock the screen and update if necessary */ | |
724 if ( SDL_MUSTLOCK(screen) ) { | |
725 SDL_UnlockSurface(screen); | |
726 } | |
727 if ( (screen == SDL_VideoSurface) && | |
728 ((screen->flags & SDL_HWSURFACE) != SDL_HWSURFACE) ) { | |
729 SDL_VideoDevice *video = current_video; | |
730 SDL_VideoDevice *this = current_video; | |
731 SDL_Rect area; | |
732 | |
733 SDL_MouseRect(&area); | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
734 if ( video->UpdateRects ) { |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
735 video->UpdateRects(this, 1, &area); |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
736 } |
0 | 737 } |
738 } | |
739 | |
740 /* Reset the cursor on video mode change | |
741 FIXME: Keep track of all cursors, and reset them all. | |
742 */ | |
743 void SDL_ResetCursor(void) | |
744 { | |
745 int savelen; | |
746 | |
747 if ( SDL_cursor ) { | |
748 savelen = SDL_cursor->area.w*4*SDL_cursor->area.h; | |
749 SDL_cursor->area.x = 0; | |
750 SDL_cursor->area.y = 0; | |
751 memset(SDL_cursor->save[0], 0, savelen); | |
752 } | |
753 } |