1 |
/* graphics_sdl.c -- barebones sdl graphics layer
|
2 |
|
3 |
copyright (c) 2008 bryan rittmeyer <bryanr@bryanr.org>
|
4 |
license: GPLv2
|
5 |
|
6 |
TODO:
|
7 |
- dashed lines
|
8 |
- ifdef DEBUG -> dbg()
|
9 |
- proper image transparency (libsdl-image xpm does not work)
|
10 |
- valgrind
|
11 |
|
12 |
revision history:
|
13 |
2008-06-01 initial
|
14 |
2008-06-15 SDL_DOUBLEBUF+SDL_Flip for linux fb. fix FT leaks.
|
15 |
2008-06-18 defer initial resize_callback
|
16 |
2008-06-21 linux touchscreen
|
17 |
2008-07-04 custom rastering
|
18 |
*/
|
19 |
|
20 |
#include <glib.h>
|
21 |
#include <pthread.h>
|
22 |
#include <poll.h>
|
23 |
#include <signal.h>
|
24 |
#include "config.h"
|
25 |
#include "debug.h"
|
26 |
#include "point.h"
|
27 |
#include "graphics.h"
|
28 |
#include "color.h"
|
29 |
#include "plugin.h"
|
30 |
#include "window.h"
|
31 |
#include "navit.h"
|
32 |
#include "keys.h"
|
33 |
#include "item.h"
|
34 |
#include "attr.h"
|
35 |
#include "callback.h"
|
36 |
#include "font/freetype/font_freetype.h"
|
37 |
|
38 |
#include <SDL/SDL.h>
|
39 |
#include <math.h>
|
40 |
|
41 |
#ifdef USE_WEBOS
|
42 |
# include "vehicle.h"
|
43 |
# include <PDL.h>
|
44 |
# define USE_WEBOS_ACCELEROMETER
|
45 |
#endif
|
46 |
|
47 |
#define RASTER
|
48 |
#undef SDL_SGE
|
49 |
#undef SDL_GFX
|
50 |
#undef ALPHA
|
51 |
|
52 |
#undef SDL_TTF
|
53 |
#define SDL_IMAGE
|
54 |
#undef LINUX_TOUCHSCREEN
|
55 |
|
56 |
#ifdef USE_WEBOS
|
57 |
#define DISPLAY_W 0
|
58 |
#define DISPLAY_H 0
|
59 |
#else
|
60 |
#define DISPLAY_W 800
|
61 |
#define DISPLAY_H 600
|
62 |
#endif
|
63 |
|
64 |
|
65 |
#undef DEBUG
|
66 |
#undef PROFILE
|
67 |
|
68 |
#define OVERLAY_MAX 32
|
69 |
|
70 |
#ifdef RASTER
|
71 |
#include "raster.h"
|
72 |
#endif
|
73 |
|
74 |
#ifdef SDL_SGE
|
75 |
#include <SDL/sge.h>
|
76 |
#endif
|
77 |
|
78 |
#ifdef SDL_GFX
|
79 |
#include <SDL/SDL_gfxPrimitives.h>
|
80 |
#endif
|
81 |
|
82 |
#ifdef SDL_TTF
|
83 |
#include <SDL/SDL_ttf.h>
|
84 |
#else
|
85 |
#include <ft2build.h>
|
86 |
#include FT_FREETYPE_H
|
87 |
#include <freetype/ftglyph.h>
|
88 |
#endif
|
89 |
#include <event.h>
|
90 |
|
91 |
#ifdef SDL_IMAGE
|
92 |
#include <SDL/SDL_image.h>
|
93 |
#endif
|
94 |
|
95 |
#ifdef LINUX_TOUCHSCREEN
|
96 |
/* we use Linux evdev directly for the touchscreen. */
|
97 |
#include <sys/types.h>
|
98 |
#include <sys/stat.h>
|
99 |
#include <fcntl.h>
|
100 |
#include <linux/input.h>
|
101 |
#endif
|
102 |
|
103 |
#include <alloca.h>
|
104 |
|
105 |
#ifdef PROFILE
|
106 |
#include <sys/time.h>
|
107 |
#include <time.h>
|
108 |
#endif
|
109 |
|
110 |
|
111 |
/* TODO: union overlay + non-overlay to reduce size */
|
112 |
struct graphics_priv;
|
113 |
struct graphics_priv {
|
114 |
SDL_Surface *screen;
|
115 |
int aa;
|
116 |
/* video modes */
|
117 |
uint32_t video_flags;
|
118 |
int video_bpp;
|
119 |
|
120 |
/* <overlay> */
|
121 |
int overlay_mode;
|
122 |
int overlay_x;
|
123 |
int overlay_y;
|
124 |
struct graphics_priv *overlay_parent;
|
125 |
int overlay_idx;
|
126 |
/* </overlay> */
|
127 |
|
128 |
/* <main> */
|
129 |
struct graphics_priv *overlay_array[OVERLAY_MAX];
|
130 |
int overlay_enable;
|
131 |
enum draw_mode_num draw_mode;
|
132 |
|
133 |
int resize_callback_initial;
|
134 |
|
135 |
struct navit *nav;
|
136 |
struct callback_list *cbl;
|
137 |
|
138 |
#ifdef USE_WEBOS_ACCELEROMETER
|
139 |
SDL_Joystick *accelerometer;
|
140 |
char orientation;
|
141 |
int real_w, real_h;
|
142 |
#endif
|
143 |
|
144 |
#ifdef LINUX_TOUCHSCREEN
|
145 |
int ts_fd;
|
146 |
int32_t ts_hit;
|
147 |
uint32_t ts_x;
|
148 |
uint32_t ts_y;
|
149 |
#endif
|
150 |
|
151 |
#ifndef SDL_TTF
|
152 |
FT_Library library;
|
153 |
#endif
|
154 |
|
155 |
#ifdef PROFILE
|
156 |
struct timeval draw_begin_tv;
|
157 |
unsigned long draw_time_peak;
|
158 |
#endif
|
159 |
struct font_freetype_methods freetype_methods;
|
160 |
/* </main> */
|
161 |
};
|
162 |
|
163 |
static int dummy;
|
164 |
|
165 |
#ifdef USE_WEBOS
|
166 |
# define WEBOS_KEY_SHIFT 0x130
|
167 |
# define WEBOS_KEY_SYM 0x131
|
168 |
# define WEBOS_KEY_ORANGE 0x133
|
169 |
|
170 |
# define WEBOS_KEY_MOD_SHIFT 0x1
|
171 |
# define WEBOS_KEY_MOD_ORANGE 0x2
|
172 |
# define WEBOS_KEY_MOD_SYM 0x4
|
173 |
|
174 |
# define WEBOS_KEY_MOD_SHIFT_STICKY 0x11
|
175 |
# define WEBOS_KEY_MOD_ORANGE_STICKY 0x22
|
176 |
# define WEBOS_KEY_MOD_SYM_STICKY 0x44
|
177 |
|
178 |
# ifdef USE_WEBOS_ACCELEROMETER
|
179 |
# define WEBOS_ORIENTATION_PORTRAIT 0x0
|
180 |
# define WEBOS_ORIENTATION_LANDSCAPE 0x1
|
181 |
# endif
|
182 |
|
183 |
# define SDL_USEREVENT_CODE_TIMER 0x1
|
184 |
# define SDL_USEREVENT_CODE_CALL_CALLBACK 0x2
|
185 |
# define SDL_USEREVENT_CODE_IDLE_EVENT 0x4
|
186 |
# define SDL_USEREVENT_CODE_WATCH 0x8
|
187 |
# ifdef USE_WEBOS_ACCELEROMETER
|
188 |
# define SDL_USEREVENT_CODE_ROTATE 0xA
|
189 |
# endif
|
190 |
|
191 |
struct event_timeout {
|
192 |
SDL_TimerID id;
|
193 |
int multi;
|
194 |
struct callback *cb;
|
195 |
};
|
196 |
|
197 |
struct idle_task {
|
198 |
int priority;
|
199 |
struct callback *cb;
|
200 |
};
|
201 |
|
202 |
struct event_watch {
|
203 |
struct pollfd *pfd;
|
204 |
struct callback *cb;
|
205 |
};
|
206 |
|
207 |
static struct graphics_priv* the_graphics = NULL;
|
208 |
static int quit_event_loop = 0; // quit the main event loop
|
209 |
static int the_graphics_count = 0; // count how many graphics objects are created
|
210 |
static GPtrArray *idle_tasks = NULL;
|
211 |
static pthread_t sdl_watch_thread = 0;
|
212 |
static GPtrArray *sdl_watch_list = NULL;
|
213 |
|
214 |
static void event_sdl_watch_thread (GPtrArray *);
|
215 |
static void event_sdl_watch_startthread(GPtrArray *watch_list);
|
216 |
static void event_sdl_watch_stopthread(void);
|
217 |
static struct event_watch *event_sdl_add_watch(void *, enum event_watch_cond, struct callback *);
|
218 |
static void event_sdl_remove_watch(struct event_watch *);
|
219 |
static struct event_timeout *event_sdl_add_timeout(int, int, struct callback *);
|
220 |
static void event_sdl_remove_timeout(struct event_timeout *);
|
221 |
static struct event_idle *event_sdl_add_idle(int, struct callback *);
|
222 |
static void event_sdl_remove_idle(struct event_idle *);
|
223 |
static void event_sdl_call_callback(struct callback_list *);
|
224 |
# ifdef USE_WEBOS_ACCELEROMETER
|
225 |
static unsigned int sdl_orientation_count = 2^16;
|
226 |
static char sdl_next_orientation = WEBOS_ORIENTATION_PORTRAIT;
|
227 |
# endif
|
228 |
#endif
|
229 |
unsigned char * ft_buffer = NULL;
|
230 |
unsigned int ft_buffer_size = 0;
|
231 |
|
232 |
struct graphics_font_priv {
|
233 |
#ifdef SDL_TTF
|
234 |
TTF_Font *font;
|
235 |
#else
|
236 |
FT_Face face;
|
237 |
#endif
|
238 |
};
|
239 |
|
240 |
struct graphics_gc_priv {
|
241 |
struct graphics_priv *gr;
|
242 |
Uint8 fore_r;
|
243 |
Uint8 fore_g;
|
244 |
Uint8 fore_b;
|
245 |
Uint8 fore_a;
|
246 |
Uint8 back_r;
|
247 |
Uint8 back_g;
|
248 |
Uint8 back_b;
|
249 |
Uint8 back_a;
|
250 |
int linewidth;
|
251 |
};
|
252 |
|
253 |
struct graphics_image_priv {
|
254 |
SDL_Surface *img;
|
255 |
};
|
256 |
|
257 |
|
258 |
#ifdef LINUX_TOUCHSCREEN
|
259 |
static int input_ts_exit(struct graphics_priv *gr);
|
260 |
#endif
|
261 |
|
262 |
static void
|
263 |
graphics_destroy(struct graphics_priv *gr)
|
264 |
{
|
265 |
dbg(1, "graphics_destroy %p %u\n", gr, gr->overlay_mode);
|
266 |
|
267 |
if(gr->overlay_mode)
|
268 |
{
|
269 |
SDL_FreeSurface(gr->screen);
|
270 |
gr->overlay_parent->overlay_array[gr->overlay_idx] = NULL;
|
271 |
}
|
272 |
else
|
273 |
{
|
274 |
g_free (ft_buffer);
|
275 |
#ifdef SDL_TTF
|
276 |
TTF_Quit();
|
277 |
#else
|
278 |
FT_Done_FreeType(gr->library);
|
279 |
#endif
|
280 |
#ifdef LINUX_TOUCHSCREEN
|
281 |
input_ts_exit(gr);
|
282 |
#endif
|
283 |
#ifdef USE_WEBOS_ACCELEROMETER
|
284 |
SDL_JoystickClose(gr->accelerometer);
|
285 |
#endif
|
286 |
#ifdef USE_WEBOS
|
287 |
PDL_Quit();
|
288 |
#endif
|
289 |
SDL_Quit();
|
290 |
}
|
291 |
|
292 |
g_free(gr);
|
293 |
}
|
294 |
|
295 |
/* graphics_gc */
|
296 |
|
297 |
static void
|
298 |
gc_destroy(struct graphics_gc_priv *gc)
|
299 |
{
|
300 |
g_free(gc);
|
301 |
}
|
302 |
|
303 |
static void
|
304 |
gc_set_linewidth(struct graphics_gc_priv *gc, int w)
|
305 |
{
|
306 |
#ifdef DEBUG
|
307 |
printf("gc_set_linewidth %p %d\n", gc, w);
|
308 |
#endif
|
309 |
gc->linewidth = w;
|
310 |
}
|
311 |
|
312 |
static void
|
313 |
gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
|
314 |
{
|
315 |
/* TODO */
|
316 |
}
|
317 |
|
318 |
static void
|
319 |
gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
|
320 |
{
|
321 |
#ifdef DEBUG
|
322 |
printf("gc_set_foreground: %p %d %d %d %d\n", gc, c->a, c->r, c->g, c->b);
|
323 |
#endif
|
324 |
gc->fore_r = c->r/256;
|
325 |
gc->fore_g = c->g/256;
|
326 |
gc->fore_b = c->b/256;
|
327 |
gc->fore_a = c->a/256;
|
328 |
}
|
329 |
|
330 |
static void
|
331 |
gc_set_background(struct graphics_gc_priv *gc, struct color *c)
|
332 |
{
|
333 |
#ifdef DEBUG
|
334 |
printf("gc_set_background: %p %d %d %d %d\n", gc, c->a, c->r, c->g, c->b);
|
335 |
#endif
|
336 |
gc->back_r = c->r/256;
|
337 |
gc->back_g = c->g/256;
|
338 |
gc->back_b = c->b/256;
|
339 |
gc->back_a = c->a/256;
|
340 |
}
|
341 |
|
342 |
static struct graphics_gc_methods gc_methods = {
|
343 |
gc_destroy,
|
344 |
gc_set_linewidth,
|
345 |
gc_set_dashes,
|
346 |
gc_set_foreground,
|
347 |
gc_set_background
|
348 |
};
|
349 |
|
350 |
static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
|
351 |
{
|
352 |
struct graphics_gc_priv *gc=g_new0(struct graphics_gc_priv, 1);
|
353 |
*meth=gc_methods;
|
354 |
gc->gr=gr;
|
355 |
gc->linewidth=1; /* upper layer should override anyway? */
|
356 |
return gc;
|
357 |
}
|
358 |
|
359 |
|
360 |
#if 0 /* unused by core? */
|
361 |
static void image_destroy(struct graphics_image_priv *gi)
|
362 |
{
|
363 |
#ifdef SDL_IMAGE
|
364 |
SDL_FreeSurface(gi->img);
|
365 |
g_free(gi);
|
366 |
#endif
|
367 |
}
|
368 |
|
369 |
static struct graphics_image_methods gi_methods =
|
370 |
{
|
371 |
image_destroy
|
372 |
};
|
373 |
#endif
|
374 |
|
375 |
static struct graphics_image_priv *
|
376 |
image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h,
|
377 |
struct point *hot, int rotation)
|
378 |
{
|
379 |
#ifdef SDL_IMAGE
|
380 |
struct graphics_image_priv *gi;
|
381 |
|
382 |
/* FIXME: meth is not used yet.. so gi leaks. at least xpm is small */
|
383 |
|
384 |
gi = g_new0(struct graphics_image_priv, 1);
|
385 |
gi->img = IMG_Load(name);
|
386 |
if(gi->img)
|
387 |
{
|
388 |
/* TBD: improves blit performance? */
|
389 |
#if !SDL_VERSION_ATLEAST(1,3,0)
|
390 |
SDL_SetColorKey(gi->img, SDL_RLEACCEL, gi->img->format->colorkey);
|
391 |
#endif
|
392 |
*w=gi->img->w;
|
393 |
*h=gi->img->h;
|
394 |
hot->x=*w/2;
|
395 |
hot->y=*h/2;
|
396 |
}
|
397 |
else
|
398 |
{
|
399 |
/* TODO: debug "colour parse errors" on xpm */
|
400 |
printf("graphics_sdl: image_new on '%s' failed: %s\n", name, IMG_GetError());
|
401 |
g_free(gi);
|
402 |
gi = NULL;
|
403 |
}
|
404 |
|
405 |
return gi;
|
406 |
#else
|
407 |
return NULL;
|
408 |
#endif
|
409 |
}
|
410 |
|
411 |
static void
|
412 |
image_free(struct graphics_priv *gr, struct graphics_image_priv * gi)
|
413 |
{
|
414 |
#ifdef SDL_IMAGE
|
415 |
SDL_FreeSurface(gi->img);
|
416 |
g_free(gi);
|
417 |
#endif
|
418 |
}
|
419 |
|
420 |
static void
|
421 |
get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
|
422 |
{
|
423 |
char *p=text;
|
424 |
FT_BBox bbox;
|
425 |
FT_UInt glyph_index;
|
426 |
FT_GlyphSlot slot = font->face->glyph; // a small shortcut
|
427 |
FT_Glyph glyph;
|
428 |
FT_Matrix matrix;
|
429 |
FT_Vector pen;
|
430 |
pen.x = 0 * 64;
|
431 |
pen.y = 0 * 64;
|
432 |
matrix.xx = dx;
|
433 |
matrix.xy = dy;
|
434 |
matrix.yx = -dy;
|
435 |
matrix.yy = dx;
|
436 |
int n,len,x=0,y=0;
|
437 |
|
438 |
bbox.xMin = bbox.yMin = 32000;
|
439 |
bbox.xMax = bbox.yMax = -32000;
|
440 |
FT_Set_Transform( font->face, &matrix, &pen );
|
441 |
len=g_utf8_strlen(text, -1);
|
442 |
for ( n = 0; n < len; n++ ) {
|
443 |
FT_BBox glyph_bbox;
|
444 |
glyph_index = FT_Get_Char_Index(font->face, g_utf8_get_char(p));
|
445 |
p=g_utf8_next_char(p);
|
446 |
FT_Load_Glyph(font->face, glyph_index, FT_LOAD_DEFAULT );
|
447 |
FT_Get_Glyph(font->face->glyph, &glyph);
|
448 |
FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox );
|
449 |
FT_Done_Glyph(glyph);
|
450 |
glyph_bbox.xMin += x >> 6;
|
451 |
glyph_bbox.xMax += x >> 6;
|
452 |
glyph_bbox.yMin += y >> 6;
|
453 |
glyph_bbox.yMax += y >> 6;
|
454 |
x += slot->advance.x;
|
455 |
y -= slot->advance.y;
|
456 |
if ( glyph_bbox.xMin < bbox.xMin )
|
457 |
bbox.xMin = glyph_bbox.xMin;
|
458 |
if ( glyph_bbox.yMin < bbox.yMin )
|
459 |
bbox.yMin = glyph_bbox.yMin;
|
460 |
if ( glyph_bbox.xMax > bbox.xMax )
|
461 |
bbox.xMax = glyph_bbox.xMax;
|
462 |
if ( glyph_bbox.yMax > bbox.yMax )
|
463 |
bbox.yMax = glyph_bbox.yMax;
|
464 |
}
|
465 |
if ( bbox.xMin > bbox.xMax ) {
|
466 |
bbox.xMin = 0;
|
467 |
bbox.yMin = 0;
|
468 |
bbox.xMax = 0;
|
469 |
bbox.yMax = 0;
|
470 |
}
|
471 |
ret[0].x=bbox.xMin;
|
472 |
ret[0].y=-bbox.yMin;
|
473 |
ret[1].x=bbox.xMin;
|
474 |
ret[1].y=-bbox.yMax;
|
475 |
ret[2].x=bbox.xMax;
|
476 |
ret[2].y=-bbox.yMax;
|
477 |
ret[3].x=bbox.xMax;
|
478 |
ret[3].y=-bbox.yMin;
|
479 |
}
|
480 |
|
481 |
static void
|
482 |
draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
|
483 |
{
|
484 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
|
485 |
{
|
486 |
return;
|
487 |
}
|
488 |
|
489 |
Sint16 *vx, *vy;
|
490 |
Sint16 x, y;
|
491 |
int i;
|
492 |
|
493 |
vx = alloca(count * sizeof(Sint16));
|
494 |
vy = alloca(count * sizeof(Sint16));
|
495 |
|
496 |
for(i = 0; i < count; i++)
|
497 |
{
|
498 |
x = (Sint16)p[i].x;
|
499 |
y = (Sint16)p[i].y;
|
500 |
|
501 |
#if 0
|
502 |
if(x < 0)
|
503 |
{
|
504 |
x = 0;
|
505 |
}
|
506 |
if(y < 0)
|
507 |
{
|
508 |
y = 0;
|
509 |
}
|
510 |
#endif
|
511 |
|
512 |
vx[i] = x;
|
513 |
vy[i] = y;
|
514 |
|
515 |
#ifdef DEBUG
|
516 |
printf("draw_polygon: %p %i %d,%d\n", gc, i, p[i].x, p[i].y);
|
517 |
#endif
|
518 |
}
|
519 |
|
520 |
#ifdef RASTER
|
521 |
if(gr->aa)
|
522 |
{
|
523 |
raster_aapolygon(gr->screen, count, vx, vy,
|
524 |
SDL_MapRGBA(gr->screen->format,
|
525 |
gc->fore_r,
|
526 |
gc->fore_g,
|
527 |
gc->fore_b,
|
528 |
gc->fore_a));
|
529 |
}
|
530 |
else
|
531 |
{
|
532 |
raster_polygon(gr->screen, count, vx, vy,
|
533 |
SDL_MapRGBA(gr->screen->format,
|
534 |
gc->fore_r,
|
535 |
gc->fore_g,
|
536 |
gc->fore_b,
|
537 |
gc->fore_a));
|
538 |
}
|
539 |
#else
|
540 |
# ifdef SDL_SGE
|
541 |
# ifdef ALPHA
|
542 |
sge_FilledPolygonAlpha(gr->screen, count, vx, vy,
|
543 |
SDL_MapRGB(gr->screen->format,
|
544 |
gc->fore_r,
|
545 |
gc->fore_g,
|
546 |
gc->fore_b),
|
547 |
gc->fore_a);
|
548 |
# else
|
549 |
# ifdef ANTI_ALIAS
|
550 |
sge_AAFilledPolygon(gr->screen, count, vx, vy,
|
551 |
SDL_MapRGB(gr->screen->format,
|
552 |
gc->fore_r,
|
553 |
gc->fore_g,
|
554 |
gc->fore_b));
|
555 |
# else
|
556 |
sge_FilledPolygon(gr->screen, count, vx, vy,
|
557 |
SDL_MapRGB(gr->screen->format,
|
558 |
gc->fore_r,
|
559 |
gc->fore_g,
|
560 |
gc->fore_b));
|
561 |
# endif
|
562 |
# endif
|
563 |
# else
|
564 |
filledPolygonRGBA(gr->screen, vx, vy, count,
|
565 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
566 |
# endif
|
567 |
#endif
|
568 |
}
|
569 |
|
570 |
|
571 |
|
572 |
static void
|
573 |
draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
|
574 |
{
|
575 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
|
576 |
{
|
577 |
return;
|
578 |
}
|
579 |
|
580 |
#ifdef DEBUG
|
581 |
printf("draw_rectangle: %d %d %d %d r=%d g=%d b=%d a=%d\n", p->x, p->y, w, h,
|
582 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
583 |
#endif
|
584 |
if(w > gr->screen->w)
|
585 |
{
|
586 |
w = gr->screen->w;
|
587 |
}
|
588 |
if(h > gr->screen->h)
|
589 |
{
|
590 |
h = gr->screen->h;
|
591 |
}
|
592 |
|
593 |
#ifdef RASTER
|
594 |
raster_rect(gr->screen, p->x, p->y, w, h,
|
595 |
SDL_MapRGBA(gr->screen->format,
|
596 |
gc->fore_r,
|
597 |
gc->fore_g,
|
598 |
gc->fore_b,
|
599 |
gc->fore_a));
|
600 |
#else
|
601 |
# ifdef SDL_SGE
|
602 |
# ifdef ALPHA
|
603 |
sge_FilledRectAlpha(gr->screen, p->x, p->y, p->x + w, p->y + h,
|
604 |
SDL_MapRGB(gr->screen->format,
|
605 |
gc->fore_r,
|
606 |
gc->fore_g,
|
607 |
gc->fore_b),
|
608 |
gc->fore_a);
|
609 |
# else
|
610 |
/* no AA -- should use poly instead for that */
|
611 |
sge_FilledRect(gr->screen, p->x, p->y, p->x + w, p->y + h,
|
612 |
SDL_MapRGB(gr->screen->format,
|
613 |
gc->fore_r,
|
614 |
gc->fore_g,
|
615 |
gc->fore_b));
|
616 |
# endif
|
617 |
# else
|
618 |
boxRGBA(gr->screen, p->x, p->y, p->x + w, p->y + h,
|
619 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
620 |
# endif
|
621 |
#endif
|
622 |
|
623 |
}
|
624 |
|
625 |
static void
|
626 |
draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
|
627 |
{
|
628 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
|
629 |
{
|
630 |
return;
|
631 |
}
|
632 |
|
633 |
#if 0
|
634 |
if(gc->fore_a != 0xff)
|
635 |
{
|
636 |
dbg(0, "%d %d %d %u %u:%u:%u:%u\n", p->x, p->y, r, gc->linewidth,
|
637 |
gc->fore_a, gc->fore_r, gc->fore_g, gc->fore_b);
|
638 |
}
|
639 |
#endif
|
640 |
|
641 |
/* FIXME: does not quite match gtk */
|
642 |
|
643 |
/* hack for osd compass.. why is this needed!? */
|
644 |
if(gr->overlay_mode)
|
645 |
{
|
646 |
r = r / 2;
|
647 |
}
|
648 |
|
649 |
#ifdef RASTER
|
650 |
if(gr->aa)
|
651 |
{
|
652 |
raster_aacircle(gr->screen, p->x, p->y, r,
|
653 |
SDL_MapRGBA(gr->screen->format,
|
654 |
gc->fore_r,
|
655 |
gc->fore_g,
|
656 |
gc->fore_b,
|
657 |
gc->fore_a));
|
658 |
}
|
659 |
else
|
660 |
{
|
661 |
raster_circle(gr->screen, p->x, p->y, r,
|
662 |
SDL_MapRGBA(gr->screen->format,
|
663 |
gc->fore_r,
|
664 |
gc->fore_g,
|
665 |
gc->fore_b,
|
666 |
gc->fore_a));
|
667 |
}
|
668 |
#else
|
669 |
# ifdef SDL_SGE
|
670 |
# ifdef ALPHA
|
671 |
sge_FilledCircleAlpha(gr->screen, p->x, p->y, r,
|
672 |
SDL_MapRGB(gr->screen->format,
|
673 |
gc->fore_r, gc->fore_g, gc->fore_b),
|
674 |
gc->fore_a);
|
675 |
# else
|
676 |
# ifdef ANTI_ALIAS
|
677 |
sge_AAFilledCircle(gr->screen, p->x, p->y, r,
|
678 |
SDL_MapRGB(gr->screen->format,
|
679 |
gc->fore_r, gc->fore_g, gc->fore_b));
|
680 |
# else
|
681 |
sge_FilledCircle(gr->screen, p->x, p->y, r,
|
682 |
SDL_MapRGB(gr->screen->format,
|
683 |
gc->fore_r, gc->fore_g, gc->fore_b));
|
684 |
# endif
|
685 |
# endif
|
686 |
# else
|
687 |
# ifdef ANTI_ALIAS
|
688 |
aacircleRGBA(gr->screen, p->x, p->y, r,
|
689 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
690 |
# else
|
691 |
filledCircleRGBA(gr->screen, p->x, p->y, r,
|
692 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
693 |
# endif
|
694 |
# endif
|
695 |
#endif
|
696 |
}
|
697 |
|
698 |
|
699 |
static void
|
700 |
draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
|
701 |
{
|
702 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
|
703 |
{
|
704 |
return;
|
705 |
}
|
706 |
|
707 |
/* you might expect lines to be simpler than the other shapes.
|
708 |
but, that would be wrong. 1 line can generate 1 polygon + 2 circles
|
709 |
and even worse, we have to calculate their parameters!
|
710 |
go dust off your trigonometry hat.
|
711 |
*/
|
712 |
#if 0
|
713 |
int i, l, x_inc, y_inc, lw;
|
714 |
|
715 |
lw = gc->linewidth;
|
716 |
|
717 |
for(i = 0; i < count-1; i++)
|
718 |
{
|
719 |
#ifdef DEBUG
|
720 |
printf("draw_lines: %p %d %d,%d->%d,%d %d\n", gc, i, p[i].x, p[i].y, p[i+1].x, p[i+1].y, gc->linewidth);
|
721 |
#endif
|
722 |
for(l = 0; l < lw; l++)
|
723 |
{
|
724 |
/* FIXME: center? */
|
725 |
#if 1
|
726 |
if(p[i].x != p[i+1].x)
|
727 |
{
|
728 |
x_inc = l - (lw/2);
|
729 |
}
|
730 |
else
|
731 |
{
|
732 |
x_inc = 0;
|
733 |
}
|
734 |
|
735 |
if(p[i].y != p[i+1].y)
|
736 |
{
|
737 |
y_inc = l - (lw/2);
|
738 |
}
|
739 |
else
|
740 |
{
|
741 |
y_inc = 0;
|
742 |
}
|
743 |
#else
|
744 |
x_inc = 0;
|
745 |
y_inc = 0;
|
746 |
#endif
|
747 |
|
748 |
#ifdef ANTI_ALIAS
|
749 |
aalineRGBA(gr->screen, p[i].x + x_inc, p[i].y + y_inc, p[i+1].x + x_inc, p[i+1].y + y_inc,
|
750 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
751 |
#else
|
752 |
lineRGBA(gr->screen, p[i].x + x_inc, p[i].y + y_inc, p[i+1].x + x_inc, p[i+1].y + y_inc,
|
753 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
754 |
#endif
|
755 |
}
|
756 |
}
|
757 |
#else
|
758 |
/* sort of based on graphics_opengl.c::draw_lines */
|
759 |
/* FIXME: should honor ./configure flag for no fp.
|
760 |
this could be 100% integer code pretty easily,
|
761 |
except that i am lazy
|
762 |
*/
|
763 |
struct point vert[4];
|
764 |
int lw = gc->linewidth;
|
765 |
//int lw = 1;
|
766 |
int i;
|
767 |
|
768 |
for(i = 0; i < count-1; i++)
|
769 |
{
|
770 |
float dx=p[i+1].x-p[i].x;
|
771 |
float dy=p[i+1].y-p[i].y;
|
772 |
|
773 |
#if 0
|
774 |
float cx=(p[i+1].x+p[i].x)/2;
|
775 |
float cy=(p[i+1].y+p[i].y)/2;
|
776 |
#endif
|
777 |
|
778 |
float angle;
|
779 |
|
780 |
int x_lw_adj, y_lw_adj;
|
781 |
|
782 |
if(lw == 1)
|
783 |
{
|
784 |
#ifdef RASTER
|
785 |
if(gr->aa)
|
786 |
{
|
787 |
raster_aaline(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
788 |
SDL_MapRGBA(gr->screen->format,
|
789 |
gc->fore_r,
|
790 |
gc->fore_g,
|
791 |
gc->fore_b,
|
792 |
gc->fore_a));
|
793 |
}
|
794 |
else
|
795 |
{
|
796 |
raster_line(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
797 |
SDL_MapRGBA(gr->screen->format,
|
798 |
gc->fore_r,
|
799 |
gc->fore_g,
|
800 |
gc->fore_b,
|
801 |
gc->fore_a));
|
802 |
}
|
803 |
#else
|
804 |
# ifdef SDL_SGE
|
805 |
# ifdef ALPHA
|
806 |
sge_LineAlpha(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
807 |
SDL_MapRGB(gr->screen->format,
|
808 |
gc->fore_r, gc->fore_g, gc->fore_b),
|
809 |
gc->fore_a);
|
810 |
# else
|
811 |
# ifdef ANTI_ALIAS
|
812 |
sge_AALine(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
813 |
SDL_MapRGB(gr->screen->format,
|
814 |
gc->fore_r, gc->fore_g, gc->fore_b));
|
815 |
# else
|
816 |
sge_Line(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
817 |
SDL_MapRGB(gr->screen->format,
|
818 |
gc->fore_r, gc->fore_g, gc->fore_b));
|
819 |
# endif
|
820 |
# endif
|
821 |
# else
|
822 |
# ifdef ANTI_ALIAS
|
823 |
aalineRGBA(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
824 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
825 |
# else
|
826 |
lineRGBA(gr->screen, p[i].x, p[i].y, p[i+1].x, p[i+1].y,
|
827 |
gc->fore_r, gc->fore_g, gc->fore_b, gc->fore_a);
|
828 |
# endif
|
829 |
# endif
|
830 |
#endif
|
831 |
}
|
832 |
else
|
833 |
{
|
834 |
/* there is probably a much simpler way but this works ok */
|
835 |
|
836 |
/* FIXME: float + double mixture */
|
837 |
/* FIXME: lrint(round())? */
|
838 |
if(dy == 0.0)
|
839 |
{
|
840 |
angle = 0.0;
|
841 |
x_lw_adj = 0;
|
842 |
y_lw_adj = round((float)lw/2.0);
|
843 |
}
|
844 |
else if(dx == 0.0)
|
845 |
{
|
846 |
angle = 0.0;
|
847 |
x_lw_adj = round((float)lw/2.0);
|
848 |
y_lw_adj = 0;
|
849 |
}
|
850 |
else
|
851 |
{
|
852 |
angle = (M_PI/2.0) - atan(abs(dx)/abs(dy));
|
853 |
x_lw_adj = round(sin(angle)*(float)lw/2.0);
|
854 |
y_lw_adj = round(cos(angle)*(float)lw/2.0);
|
855 |
if((x_lw_adj < 0) || (y_lw_adj < 0))
|
856 |
{
|
857 |
printf("i=%d\n", i);
|
858 |
printf(" %d,%d->%d,%d\n", p[i].x, p[i].y, p[i+1].x, p[i+1].y);
|
859 |
printf(" lw=%d angle=%f\n", lw, 180.0 * angle / M_PI);
|
860 |
printf(" x_lw_adj=%d y_lw_adj=%d\n", x_lw_adj, y_lw_adj);
|
861 |
}
|
862 |
}
|
863 |
|
864 |
if(p[i+1].x > p[i].x)
|
865 |
{
|
866 |
x_lw_adj = -x_lw_adj;
|
867 |
}
|
868 |
if(p[i+1].y > p[i].y)
|
869 |
{
|
870 |
y_lw_adj = -y_lw_adj;
|
871 |
}
|
872 |
|
873 |
#if 0
|
874 |
if(((y_lw_adj*y_lw_adj)+(x_lw_adj*x_lw_adj)) != (lw/2)*(lw/2))
|
875 |
{
|
876 |
printf("i=%d\n", i);
|
877 |
printf(" %d,%d->%d,%d\n", p[i].x, p[i].y, p[i+1].x, p[i+1].y);
|
878 |
printf(" lw=%d angle=%f\n", lw, 180.0 * angle / M_PI);
|
879 |
printf(" x_lw_adj=%d y_lw_adj=%d\n", x_lw_adj, y_lw_adj);
|
880 |
}
|
881 |
#endif
|
882 |
|
883 |
/* FIXME: draw a circle/square if p[i]==p[i+1]? */
|
884 |
/* FIXME: clipping, check for neg values. hoping sdl-gfx does this */
|
885 |
vert[0].x = p[i].x + x_lw_adj;
|
886 |
vert[0].y = p[i].y - y_lw_adj;
|
887 |
vert[1].x = p[i].x - x_lw_adj;
|
888 |
vert[1].y = p[i].y + y_lw_adj;
|
889 |
vert[2].x = p[i+1].x - x_lw_adj;
|
890 |
vert[2].y = p[i+1].y + y_lw_adj;
|
891 |
vert[3].x = p[i+1].x + x_lw_adj;
|
892 |
vert[3].y = p[i+1].y - y_lw_adj;
|
893 |
|
894 |
draw_polygon(gr, gc, vert, 4);
|
895 |
|
896 |
/* draw small circles at the ends. this looks better than nothing, and slightly
|
897 |
* better than the triangle used by graphics_opengl, but is more expensive.
|
898 |
* should have an ifdef/xml attr?
|
899 |
*/
|
900 |
|
901 |
/* FIXME: should just draw a half circle */
|
902 |
|
903 |
/* now some circular endcaps, if the width is over 2 */
|
904 |
if(lw > 2)
|
905 |
{
|
906 |
if(i == 0)
|
907 |
{
|
908 |
draw_circle(gr, gc, &p[i], lw/2);
|
909 |
}
|
910 |
/* we truncate on the divide on purpose, so we don't go outside the line */
|
911 |
draw_circle(gr, gc, &p[i+1], lw/2);
|
912 |
}
|
913 |
}
|
914 |
}
|
915 |
#endif
|
916 |
}
|
917 |
|
918 |
|
919 |
static void
|
920 |
set_pixel(SDL_Surface *surface, int x, int y, Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2)
|
921 |
{
|
922 |
if(x<0 || y<0 || x>=surface->w || y>=surface->h) {
|
923 |
return;
|
924 |
}
|
925 |
|
926 |
void *target_pixel = ((Uint8*)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel);
|
927 |
|
928 |
Uint8 r1,g1,b1,a1;
|
929 |
|
930 |
switch(surface->format->BytesPerPixel) {
|
931 |
case 2:
|
932 |
{
|
933 |
SDL_GetRGBA(*(Uint16 *)target_pixel, surface->format, &r1, &g1, &b1, &a1);
|
934 |
*(Uint16 *)target_pixel = SDL_MapRGBA(surface->format,
|
935 |
(r1*(0xff-a2)/0xff) + (r2*a2/0xff),
|
936 |
(g1*(0xff-a2)/0xff) + (g2*a2/0xff),
|
937 |
(b1*(0xff-a2)/0xff) + (b2*a2/0xff),
|
938 |
a2 + a1*(0xff-a2)/0xff );
|
939 |
break;
|
940 |
}
|
941 |
case 4:
|
942 |
{
|
943 |
SDL_GetRGBA(*(Uint32 *)target_pixel, surface->format, &r1, &g1, &b1, &a1);
|
944 |
*(Uint32 *)target_pixel = SDL_MapRGBA(surface->format,
|
945 |
(r1*(0xff-a2)/0xff) + (r2*a2/0xff),
|
946 |
(g1*(0xff-a2)/0xff) + (g2*a2/0xff),
|
947 |
(b1*(0xff-a2)/0xff) + (b2*a2/0xff),
|
948 |
a2 + a1*(0xff-a2)/0xff );
|
949 |
break;
|
950 |
}
|
951 |
}
|
952 |
}
|
953 |
|
954 |
|
955 |
static void
|
956 |
resize_ft_buffer (unsigned int new_size)
|
957 |
{
|
958 |
if (new_size > ft_buffer_size) {
|
959 |
g_free (ft_buffer);
|
960 |
ft_buffer = g_malloc (new_size);
|
961 |
dbg(1, "old_size(%i) new_size(%i) ft_buffer(%i)\n", ft_buffer_size, new_size, ft_buffer);
|
962 |
ft_buffer_size = new_size;
|
963 |
}
|
964 |
}
|
965 |
|
966 |
static void
|
967 |
display_text_draw(struct font_freetype_text *text,
|
968 |
struct graphics_priv *gr, struct graphics_gc_priv *fg,
|
969 |
struct graphics_gc_priv *bg, int color, struct point *p)
|
970 |
{
|
971 |
int i, x, y, stride;
|
972 |
struct font_freetype_glyph *g, **gp;
|
973 |
struct color transparent = { 0x0000, 0x0000, 0x0000, 0x0000 };
|
974 |
struct color black = { fg->fore_r * 255, fg->fore_g * 255,
|
975 |
fg->fore_b * 255, fg->fore_a * 255 };
|
976 |
struct color white = { 0xffff, 0xffff, 0xffff, 0xffff };
|
977 |
|
978 |
if (bg) {
|
979 |
if (COLOR_IS_WHITE(black) && COLOR_IS_BLACK(white)) {
|
980 |
black.r = 65535;
|
981 |
black.g = 65535;
|
982 |
black.b = 65535;
|
983 |
black.a = 65535;
|
984 |
|
985 |
white.r = 0;
|
986 |
white.g = 0;
|
987 |
white.b = 0;
|
988 |
white.a = 65535;
|
989 |
} else if (COLOR_IS_BLACK(black) && COLOR_IS_WHITE(white)) {
|
990 |
white.r = 65535;
|
991 |
white.g = 65535;
|
992 |
white.b = 65535;
|
993 |
white.a = 65535;
|
994 |
|
995 |
black.r = 0;
|
996 |
black.g = 0;
|
997 |
black.b = 0;
|
998 |
black.a = 65535;
|
999 |
} else {
|
1000 |
white.r = bg->fore_r * 255;
|
1001 |
white.g = bg->fore_g * 255;
|
1002 |
white.b = bg->fore_b * 255;
|
1003 |
white.a = bg->fore_a * 255;
|
1004 |
}
|
1005 |
} else {
|
1006 |
white.r = 0;
|
1007 |
white.g = 0;
|
1008 |
white.b = 0;
|
1009 |
white.a = 0;
|
1010 |
}
|
1011 |
|
1012 |
|
1013 |
gp = text->glyph;
|
1014 |
i = text->glyph_count;
|
1015 |
x = p->x << 6;
|
1016 |
y = p->y << 6;
|
1017 |
while (i-- > 0) {
|
1018 |
g = *gp++;
|
1019 |
if (g->w && g->h && bg) {
|
1020 |
stride = (g->w + 2) * 4;
|
1021 |
if (color) {
|
1022 |
resize_ft_buffer(stride * (g->h + 2));
|
1023 |
gr->freetype_methods.get_shadow(g, ft_buffer, 32, stride, &white, &transparent);
|
1024 |
|
1025 |
SDL_Surface *glyph_surface =
|
1026 |
SDL_CreateRGBSurfaceFrom(ft_buffer, g->w + 2, g->h + 2,
|
1027 |
32,
|
1028 |
stride,
|
1029 |
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
|
1030 |
if (glyph_surface) {
|
1031 |
SDL_Rect r;
|
1032 |
r.x = (x + g->x) >> 6;
|
1033 |
r.y = (y + g->y) >> 6;
|
1034 |
r.w = g->w + 2;
|
1035 |
r.h = g->h + 2;
|
1036 |
|
1037 |
SDL_BlitSurface(glyph_surface, NULL, gr->screen, &r);
|
1038 |
SDL_FreeSurface(glyph_surface);
|
1039 |
}
|
1040 |
}
|
1041 |
}
|
1042 |
x += g->dx;
|
1043 |
y += g->dy;
|
1044 |
}
|
1045 |
|
1046 |
gp = text->glyph;
|
1047 |
i = text->glyph_count;
|
1048 |
x = p->x << 6;
|
1049 |
y = p->y << 6;
|
1050 |
while (i-- > 0) {
|
1051 |
g = *gp++;
|
1052 |
if (g->w && g->h) {
|
1053 |
if (color) {
|
1054 |
stride = g->w;
|
1055 |
if (bg) {
|
1056 |
resize_ft_buffer(stride * g->h * 4);
|
1057 |
gr->freetype_methods.get_glyph(g, ft_buffer, 32,
|
1058 |
stride * 4, &black,
|
1059 |
&white, &transparent);
|
1060 |
SDL_Surface *glyph_surface =
|
1061 |
SDL_CreateRGBSurfaceFrom(ft_buffer, g->w, g->h, 32,
|
1062 |
stride * 4,
|
1063 |
0x000000ff,0x0000ff00, 0x00ff0000,0xff000000);
|
1064 |
if (glyph_surface) {
|
1065 |
SDL_Rect r;
|
1066 |
r.x = (x + g->x) >> 6;
|
1067 |
r.y = (y + g->y) >> 6;
|
1068 |
r.w = g->w;
|
1069 |
r.h = g->h;
|
1070 |
|
1071 |
SDL_BlitSurface(glyph_surface, NULL, gr->screen,&r);
|
1072 |
SDL_FreeSurface(glyph_surface);
|
1073 |
}
|
1074 |
}
|
1075 |
stride *= 4;
|
1076 |
resize_ft_buffer(stride * g->h);
|
1077 |
gr->freetype_methods.get_glyph(g, ft_buffer, 32, stride,
|
1078 |
&black, &white,
|
1079 |
&transparent);
|
1080 |
int ii, jj;
|
1081 |
unsigned char* pGlyph = ft_buffer;
|
1082 |
for (jj = 0; jj < g->h; ++jj) {
|
1083 |
for (ii = 0; ii < g->w; ++ii) {
|
1084 |
if(*(pGlyph+3) > 0) {
|
1085 |
set_pixel(gr->screen,
|
1086 |
ii+((x + g->x) >> 6),
|
1087 |
jj+((y + g->y) >> 6),
|
1088 |
*(pGlyph+2), // Pixels are in BGRA format
|
1089 |
*(pGlyph+1),
|
1090 |
*(pGlyph+0),
|
1091 |
*(pGlyph+3)
|
1092 |
);
|
1093 |
}
|
1094 |
pGlyph += 4;
|
1095 |
}
|
1096 |
}
|
1097 |
}
|
1098 |
}
|
1099 |
x += g->dx;
|
1100 |
y += g->dy;
|
1101 |
}
|
1102 |
}
|
1103 |
|
1104 |
static void
|
1105 |
draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg,
|
1106 |
struct graphics_gc_priv *bg, struct graphics_font_priv *font,
|
1107 |
char *text, struct point *p, int dx, int dy)
|
1108 |
{
|
1109 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable)
|
1110 |
|| (gr->overlay_parent && gr->overlay_parent->overlay_enable
|
1111 |
&& !gr->overlay_enable)) {
|
1112 |
return;
|
1113 |
}
|
1114 |
|
1115 |
struct font_freetype_text *t;
|
1116 |
int color = 1;
|
1117 |
|
1118 |
if (!font) {
|
1119 |
dbg(0, "no font, returning\n");
|
1120 |
return;
|
1121 |
}
|
1122 |
t = gr->freetype_methods.text_new(text,
|
1123 |
(struct font_freetype_font *) font,
|
1124 |
dx, dy);
|
1125 |
|
1126 |
struct point p_eff;
|
1127 |
p_eff.x = p->x;
|
1128 |
p_eff.y = p->y;
|
1129 |
|
1130 |
display_text_draw(t, gr, fg, bg, color, &p_eff);
|
1131 |
gr->freetype_methods.text_destroy(t);
|
1132 |
}
|
1133 |
|
1134 |
static void
|
1135 |
draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
|
1136 |
{
|
1137 |
if ((gr->overlay_parent && !gr->overlay_parent->overlay_enable) || (gr->overlay_parent && gr->overlay_parent->overlay_enable && !gr->overlay_enable) )
|
1138 |
{
|
1139 |
return;
|
1140 |
}
|
1141 |
|
1142 |
#ifdef SDL_IMAGE
|
1143 |
SDL_Rect r;
|
1144 |
|
1145 |
r.x = p->x;
|
1146 |
r.y = p->y;
|
1147 |
r.w = img->img->w;
|
1148 |
r.h = img->img->h;
|
1149 |
|
1150 |
SDL_BlitSurface(img->img, NULL, gr->screen, &r);
|
1151 |
#endif
|
1152 |
}
|
1153 |
|
1154 |
static void
|
1155 |
draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
|
1156 |
{
|
1157 |
/* TODO */
|
1158 |
}
|
1159 |
|
1160 |
static void
|
1161 |
draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
|
1162 |
{
|
1163 |
#ifdef DEBUG
|
1164 |
printf("draw_restore\n");
|
1165 |
#endif
|
1166 |
}
|
1167 |
|
1168 |
static void
|
1169 |
background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
|
1170 |
{
|
1171 |
#ifdef DEBUG
|
1172 |
printf("background_gc\n");
|
1173 |
#endif
|
1174 |
}
|
1175 |
|
1176 |
|
1177 |
static void
|
1178 |
draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
|
1179 |
{
|
1180 |
#ifdef PROFILE
|
1181 |
struct timeval now;
|
1182 |
unsigned long elapsed;
|
1183 |
#endif
|
1184 |
struct graphics_priv *ov;
|
1185 |
SDL_Rect rect;
|
1186 |
int i;
|
1187 |
|
1188 |
if(gr->overlay_mode)
|
1189 |
{
|
1190 |
/* will be drawn below */
|
1191 |
}
|
1192 |
else
|
1193 |
{
|
1194 |
#ifdef DEBUG
|
1195 |
printf("draw_mode: %d\n", mode);
|
1196 |
#endif
|
1197 |
|
1198 |
#ifdef PROFILE
|
1199 |
if(mode == draw_mode_begin)
|
1200 |
{
|
1201 |
gettimeofday(&gr->draw_begin_tv, NULL);
|
1202 |
}
|
1203 |
#endif
|
1204 |
|
1205 |
if(mode == draw_mode_end)
|
1206 |
{
|
1207 |
if((gr->draw_mode == draw_mode_begin) && gr->overlay_enable)
|
1208 |
{
|
1209 |
for(i = 0; i < OVERLAY_MAX; i++)
|
1210 |
{
|
1211 |
ov = gr->overlay_array[i];
|
1212 |
if(ov && ov->overlay_enable)
|
1213 |
{
|
1214 |
rect.x = ov->overlay_x;
|
1215 |
if(rect.x<0) rect.x += gr->screen->w;
|
1216 |
rect.y = ov->overlay_y;
|
1217 |
if(rect.y<0) rect.y += gr->screen->h;
|
1218 |
rect.w = ov->screen->w;
|
1219 |
rect.h = ov->screen->h;
|
1220 |
SDL_BlitSurface(ov->screen, NULL,
|
1221 |
gr->screen, &rect);
|
1222 |
}
|
1223 |
}
|
1224 |
}
|
1225 |
|
1226 |
SDL_Flip(gr->screen);
|
1227 |
|
1228 |
#ifdef PROFILE
|
1229 |
gettimeofday(&now, NULL);
|
1230 |
elapsed = 1000000 * (now.tv_sec - gr->draw_begin_tv.tv_sec);
|
1231 |
elapsed += (now.tv_usec - gr->draw_begin_tv.tv_usec);
|
1232 |
if(elapsed >= gr->draw_time_peak)
|
1233 |
{
|
1234 |
dbg(0, "draw elapsed %u usec\n", elapsed);
|
1235 |
gr->draw_time_peak = elapsed;
|
1236 |
}
|
1237 |
#endif
|
1238 |
}
|
1239 |
|
1240 |
gr->draw_mode = mode;
|
1241 |
}
|
1242 |
}
|
1243 |
|
1244 |
static void overlay_disable(struct graphics_priv *gr, int disable)
|
1245 |
{
|
1246 |
gr->overlay_enable = !disable;
|
1247 |
struct graphics_priv *curr_gr = gr;
|
1248 |
if(gr->overlay_parent) {
|
1249 |
curr_gr = gr->overlay_parent;
|
1250 |
}
|
1251 |
draw_mode(curr_gr,draw_mode_end);
|
1252 |
}
|
1253 |
|
1254 |
static struct graphics_priv *
|
1255 |
overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound);
|
1256 |
|
1257 |
static int window_fullscreen(struct window *win, int on)
|
1258 |
{
|
1259 |
struct graphics_priv *gr=(struct graphics_priv *)win->priv;
|
1260 |
|
1261 |
/* Update video flags */
|
1262 |
if(on) {
|
1263 |
gr->video_flags |= SDL_FULLSCREEN;
|
1264 |
} else {
|
1265 |
gr->video_flags &= ~SDL_FULLSCREEN;
|
1266 |
}
|
1267 |
|
1268 |
/* Update video mode */
|
1269 |
gr->screen = SDL_SetVideoMode(gr->screen->w, gr->screen->h, gr->video_bpp, gr->video_flags);
|
1270 |
if(gr->screen == NULL) {
|
1271 |
navit_destroy(gr->nav);
|
1272 |
}
|
1273 |
else {
|
1274 |
callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
|
1275 |
}
|
1276 |
return 1;
|
1277 |
}
|
1278 |
|
1279 |
static void *
|
1280 |
get_data(struct graphics_priv *this, char const *type)
|
1281 |
{
|
1282 |
if(strcmp(type, "window") == 0) {
|
1283 |
struct window *win;
|
1284 |
win=g_new(struct window, 1);
|
1285 |
win->priv=this;
|
1286 |
win->fullscreen=window_fullscreen;
|
1287 |
win->disable_suspend=NULL;
|
1288 |
return win;
|
1289 |
} else {
|
1290 |
return &dummy;
|
1291 |
}
|
1292 |
}
|
1293 |
|
1294 |
static void draw_drag(struct graphics_priv *gr, struct point *p)
|
1295 |
{
|
1296 |
if(p) {
|
1297 |
gr->overlay_x = p->x;
|
1298 |
gr->overlay_y = p->y;
|
1299 |
}
|
1300 |
}
|
1301 |
|
1302 |
static struct graphics_methods graphics_methods = {
|
1303 |
graphics_destroy,
|
1304 |
draw_mode,
|
1305 |
draw_lines,
|
1306 |
draw_polygon,
|
1307 |
draw_rectangle,
|
1308 |
NULL /*draw_circle*/,
|
1309 |
draw_text,
|
1310 |
draw_image,
|
1311 |
draw_image_warp,
|
1312 |
draw_restore,
|
1313 |
draw_drag,
|
1314 |
NULL,
|
1315 |
gc_new,
|
1316 |
background_gc,
|
1317 |
overlay_new,
|
1318 |
image_new,
|
1319 |
get_data,
|
1320 |
image_free,
|
1321 |
get_text_bbox,
|
1322 |
overlay_disable,
|
1323 |
};
|
1324 |
|
1325 |
static struct graphics_priv *
|
1326 |
overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h,int alpha, int wraparound)
|
1327 |
{
|
1328 |
struct graphics_priv *ov;
|
1329 |
Uint32 rmask, gmask, bmask, amask;
|
1330 |
int i;
|
1331 |
|
1332 |
for(i = 0; i < OVERLAY_MAX; i++)
|
1333 |
{
|
1334 |
if(gr->overlay_array[i] == NULL)
|
1335 |
{
|
1336 |
break;
|
1337 |
}
|
1338 |
}
|
1339 |
if(i == OVERLAY_MAX)
|
1340 |
{
|
1341 |
dbg(0, "too many overlays! increase OVERLAY_MAX\n");
|
1342 |
return NULL;
|
1343 |
}
|
1344 |
|
1345 |
dbg(1, "overlay_new %d %d %d %u %u (%x, %x, %x ,%x, %d)\n", i,
|
1346 |
p->x,
|
1347 |
p->y,
|
1348 |
w,
|
1349 |
h,
|
1350 |
gr->screen->format->Rmask,
|
1351 |
gr->screen->format->Gmask,
|
1352 |
gr->screen->format->Bmask,
|
1353 |
gr->screen->format->Amask,
|
1354 |
gr->screen->format->BitsPerPixel
|
1355 |
);
|
1356 |
|
1357 |
ov = g_new0(struct graphics_priv, 1);
|
1358 |
|
1359 |
switch(gr->screen->format->BitsPerPixel) {
|
1360 |
case 8:
|
1361 |
rmask = 0xc0;
|
1362 |
gmask = 0x30;
|
1363 |
bmask = 0x0c;
|
1364 |
amask = 0x03;
|
1365 |
break;
|
1366 |
case 16:
|
1367 |
rmask = 0xf000;
|
1368 |
gmask = 0x0f00;
|
1369 |
bmask = 0x00f0;
|
1370 |
amask = 0x000f;
|
1371 |
break;
|
1372 |
case 32:
|
1373 |
rmask = 0xff000000;
|
1374 |
gmask = 0x00ff0000;
|
1375 |
bmask = 0x0000ff00;
|
1376 |
amask = 0x000000ff;
|
1377 |
break;
|
1378 |
default:
|
1379 |
rmask = gr->screen->format->Rmask;
|
1380 |
gmask = gr->screen->format->Gmask;
|
1381 |
bmask = gr->screen->format->Bmask;
|
1382 |
amask = gr->screen->format->Amask;
|
1383 |
}
|
1384 |
|
1385 |
ov->screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
1386 |
w, h,
|
1387 |
gr->screen->format->BitsPerPixel,
|
1388 |
rmask, gmask, bmask, amask);
|
1389 |
|
1390 |
ov->overlay_mode = 1;
|
1391 |
ov->overlay_enable = 1;
|
1392 |
ov->overlay_x = p->x;
|
1393 |
ov->overlay_y = p->y;
|
1394 |
ov->overlay_parent = gr;
|
1395 |
ov->overlay_idx = i;
|
1396 |
gr->overlay_array[i] = ov;
|
1397 |
|
1398 |
|
1399 |
struct font_priv *(*font_freetype_new) (void *meth);
|
1400 |
font_freetype_new = plugin_get_font_type ("freetype");
|
1401 |
|
1402 |
if (!font_freetype_new)
|
1403 |
{
|
1404 |
return NULL;
|
1405 |
}
|
1406 |
|
1407 |
|
1408 |
font_freetype_new (&ov->freetype_methods);
|
1409 |
|
1410 |
*meth=graphics_methods;
|
1411 |
|
1412 |
meth->font_new =
|
1413 |
(struct graphics_font_priv *
|
1414 |
(*)(struct graphics_priv *, struct graphics_font_methods *, char *, int,
|
1415 |
int)) ov->freetype_methods.font_new;
|
1416 |
meth->get_text_bbox = (void *)ov->freetype_methods.get_text_bbox;
|
1417 |
|
1418 |
|
1419 |
|
1420 |
|
1421 |
return ov;
|
1422 |
}
|
1423 |
|
1424 |
|
1425 |
#ifdef LINUX_TOUCHSCREEN
|
1426 |
|
1427 |
#define EVFN "/dev/input/eventX"
|
1428 |
|
1429 |
static int input_ts_init(struct graphics_priv *gr)
|
1430 |
{
|
1431 |
struct input_id ii;
|
1432 |
char fn[32];
|
1433 |
#if 0
|
1434 |
char name[64];
|
1435 |
#endif
|
1436 |
int n, fd, ret;
|
1437 |
|
1438 |
gr->ts_fd = -1;
|
1439 |
gr->ts_hit = -1;
|
1440 |
gr->ts_x = 0;
|
1441 |
gr->ts_y = 0;
|
1442 |
|
1443 |
strcpy(fn, EVFN);
|
1444 |
n = 0;
|
1445 |
while(1)
|
1446 |
{
|
1447 |
fn[sizeof(EVFN)-2] = '0' + n;
|
1448 |
|
1449 |
fd = open(fn, O_RDONLY);
|
1450 |
if(fd >= 0)
|
1451 |
{
|
1452 |
#if 0
|
1453 |
ret = ioctl(fd, EVIOCGNAME(64), (void *)name);
|
1454 |
if(ret > 0)
|
1455 |
{
|
1456 |
printf("input_ts: %s\n", name);
|
1457 |
}
|
1458 |
#endif
|
1459 |
|
1460 |
ret = ioctl(fd, EVIOCGID, (void *)&ii);
|
1461 |
if(ret == 0)
|
1462 |
{
|
1463 |
#if 1
|
1464 |
printf("bustype %04x vendor %04x product %04x version %04x\n",
|
1465 |
ii.bustype,
|
1466 |
ii.vendor,
|
1467 |
ii.product,
|
1468 |
ii.version);
|
1469 |
#endif
|
1470 |
|
1471 |
if((ii.bustype == BUS_USB) &&
|
1472 |
(ii.vendor == 0x0eef) &&
|
1473 |
(ii.product == 0x0001))
|
1474 |
{
|
1475 |
ret = fcntl(fd, F_SETFL, O_NONBLOCK);
|
1476 |
if(ret == 0)
|
1477 |
{
|
1478 |
gr->ts_fd = fd;
|
1479 |
}
|
1480 |
else
|
1481 |
{
|
1482 |
close(fd);
|
1483 |
}
|
1484 |
|
1485 |
break;
|
1486 |
}
|
1487 |
}
|
1488 |
|
1489 |
close(fd);
|
1490 |
}
|
1491 |
|
1492 |
n = n + 1;
|
1493 |
|
1494 |
/* FIXME: should check all 32 minors */
|
1495 |
if(n == 10)
|
1496 |
{
|
1497 |
/* not found */
|
1498 |
ret = -1;
|
1499 |
break;
|
1500 |
}
|
1501 |
}
|
1502 |
|
1503 |
return ret;
|
1504 |
}
|
1505 |
|
1506 |
|
1507 |
/* returns 0-based display coordinate for the given ts coord */
|
1508 |
static void input_ts_map(int *disp_x, int *disp_y,
|
1509 |
uint32_t ts_x, uint32_t ts_y)
|
1510 |
{
|
1511 |
/* Dynamix 7" (eGalax TS)
|
1512 |
top left = 1986,103
|
1513 |
top right = 61,114
|
1514 |
bot left = 1986,1897
|
1515 |
bot right = 63,1872
|
1516 |
|
1517 |
calibrate your TS using input_event_dump
|
1518 |
and touching all four corners. use the most extreme values.
|
1519 |
*/
|
1520 |
|
1521 |
#define INPUT_TS_LEFT 1978
|
1522 |
#define INPUT_TS_RIGHT 48
|
1523 |
#define INPUT_TS_TOP 115
|
1524 |
#define INPUT_TS_BOT 1870
|
1525 |
|
1526 |
/* clamp first */
|
1527 |
if(ts_x > INPUT_TS_LEFT)
|
1528 |
{
|
1529 |
ts_x = INPUT_TS_LEFT;
|
1530 |
}
|
1531 |
if(ts_x < INPUT_TS_RIGHT)
|
1532 |
{
|
1533 |
ts_x = INPUT_TS_RIGHT;
|
1534 |
}
|
1535 |
|
1536 |
ts_x = ts_x - INPUT_TS_RIGHT;
|
1537 |
|
1538 |
*disp_x = ((DISPLAY_W-1) * ts_x) / (INPUT_TS_LEFT - INPUT_TS_RIGHT);
|
1539 |
*disp_x = (DISPLAY_W-1) - *disp_x;
|
1540 |
|
1541 |
|
1542 |
if(ts_y > INPUT_TS_BOT)
|
1543 |
{
|
1544 |
ts_y = INPUT_TS_BOT;
|
1545 |
}
|
1546 |
if(ts_y < INPUT_TS_TOP)
|
1547 |
{
|
1548 |
ts_y = INPUT_TS_TOP;
|
1549 |
}
|
1550 |
|
1551 |
ts_y = ts_y - INPUT_TS_TOP;
|
1552 |
|
1553 |
*disp_y = ((DISPLAY_H-1) * ts_y) / (INPUT_TS_BOT - INPUT_TS_TOP);
|
1554 |
/* *disp_y = (DISPLAY_H-1) - *disp_y; */
|
1555 |
}
|
1556 |
|
1557 |
#if 0
|
1558 |
static void input_event_dump(struct input_event *ie)
|
1559 |
{
|
1560 |
printf("input_event:\n"
|
1561 |
"\ttv_sec\t%u\n"
|
1562 |
"\ttv_usec\t%lu\n"
|
1563 |
"\ttype\t%u\n"
|
1564 |
"\tcode\t%u\n"
|
1565 |
"\tvalue\t%d\n",
|
1566 |
(unsigned int)ie->time.tv_sec,
|
1567 |
ie->time.tv_usec,
|
1568 |
ie->type,
|
1569 |
ie->code,
|
1570 |
ie->value);
|
1571 |
}
|
1572 |
#endif
|
1573 |
|
1574 |
static int input_ts_exit(struct graphics_priv *gr)
|
1575 |
{
|
1576 |
close(gr->ts_fd);
|
1577 |
gr->ts_fd = -1;
|
1578 |
|
1579 |
return 0;
|
1580 |
}
|
1581 |
#endif
|
1582 |
|
1583 |
#ifdef USE_WEBOS_ACCELEROMETER
|
1584 |
static void
|
1585 |
sdl_accelerometer_handler(void* param)
|
1586 |
{
|
1587 |
struct graphics_priv *gr = (struct graphics_priv *)param;
|
1588 |
int xAxis = SDL_JoystickGetAxis(gr->accelerometer, 0);
|
1589 |
int yAxis = SDL_JoystickGetAxis(gr->accelerometer, 1);
|
1590 |
int zAxis = SDL_JoystickGetAxis(gr->accelerometer, 2);
|
1591 |
unsigned char new_orientation;
|
1592 |
|
1593 |
dbg(2,"x(%d) y(%d) z(%d) c(%d)\n",xAxis, yAxis, zAxis, sdl_orientation_count);
|
1594 |
|
1595 |
if (zAxis > -30000) {
|
1596 |
if (xAxis < -15000 && yAxis > -5000 && yAxis < 5000)
|
1597 |
new_orientation = WEBOS_ORIENTATION_LANDSCAPE;
|
1598 |
else if (yAxis > 15000 && xAxis > -5000 && xAxis < 5000)
|
1599 |
new_orientation = WEBOS_ORIENTATION_PORTRAIT;
|
1600 |
else
|
1601 |
return;
|
1602 |
}
|
1603 |
else
|
1604 |
return;
|
1605 |
|
1606 |
if (new_orientation == sdl_next_orientation) {
|
1607 |
if (sdl_orientation_count < 3) sdl_orientation_count++;
|
1608 |
}
|
1609 |
else {
|
1610 |
sdl_orientation_count = 0;
|
1611 |
sdl_next_orientation = new_orientation;
|
1612 |
return;
|
1613 |
}
|
1614 |
|
1615 |
|
1616 |
if (sdl_orientation_count == 3)
|
1617 |
{
|
1618 |
sdl_orientation_count++;
|
1619 |
|
1620 |
if (new_orientation != gr->orientation) {
|
1621 |
dbg(1,"x(%d) y(%d) z(%d) o(%d)\n",xAxis, yAxis, zAxis, new_orientation);
|
1622 |
gr->orientation = new_orientation;
|
1623 |
|
1624 |
SDL_Event event;
|
1625 |
SDL_UserEvent userevent;
|
1626 |
|
1627 |
userevent.type = SDL_USEREVENT;
|
1628 |
userevent.code = SDL_USEREVENT_CODE_ROTATE;
|
1629 |
userevent.data1 = NULL;
|
1630 |
userevent.data2 = NULL;
|
1631 |
|
1632 |
event.type = SDL_USEREVENT;
|
1633 |
event.user = userevent;
|
1634 |
|
1635 |
SDL_PushEvent (&event);
|
1636 |
}
|
1637 |
}
|
1638 |
}
|
1639 |
#endif
|
1640 |
|
1641 |
static gboolean graphics_sdl_idle(void *data)
|
1642 |
{
|
1643 |
struct graphics_priv *gr = (struct graphics_priv *)data;
|
1644 |
struct point p;
|
1645 |
SDL_Event ev;
|
1646 |
#ifdef LINUX_TOUCHSCREEN
|
1647 |
struct input_event ie;
|
1648 |
ssize_t ss;
|
1649 |
#endif
|
1650 |
int ret;
|
1651 |
char key_mod = 0;
|
1652 |
char keybuf[8];
|
1653 |
|
1654 |
#ifdef USE_WEBOS
|
1655 |
if(data==NULL) {
|
1656 |
if(the_graphics!=NULL) {
|
1657 |
gr = the_graphics;
|
1658 |
}
|
1659 |
else {
|
1660 |
dbg(0,"graphics_idle: graphics not set!\n");
|
1661 |
return FALSE;
|
1662 |
}
|
1663 |
}
|
1664 |
#endif
|
1665 |
|
1666 |
/* generate the initial resize callback, so the gui knows W/H
|
1667 |
|
1668 |
its unsafe to do this directly inside register_resize_callback;
|
1669 |
graphics_gtk does it during Configure, but SDL does not have
|
1670 |
an equivalent event, so we use our own flag
|
1671 |
*/
|
1672 |
if(gr->resize_callback_initial != 0)
|
1673 |
{
|
1674 |
callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
|
1675 |
gr->resize_callback_initial = 0;
|
1676 |
}
|
1677 |
|
1678 |
#ifdef LINUX_TOUCHSCREEN
|
1679 |
if(gr->ts_fd >= 0)
|
1680 |
{
|
1681 |
ss = read(gr->ts_fd, (void *)&ie, sizeof(ie));
|
1682 |
if(ss == sizeof(ie))
|
1683 |
{
|
1684 |
/* we (usually) get three events on a touchscreen hit:
|
1685 |
1: type =EV_KEY
|
1686 |
code =330 [BTN_TOUCH]
|
1687 |
value=1
|
1688 |
|
1689 |
2: type =EV_ABS
|
1690 |
code =0 [X]
|
1691 |
value=X pos
|
1692 |
|
1693 |
3: type =EV_ABS
|
1694 |
code =1 [Y]
|
1695 |
value=Y pos
|
1696 |
|
1697 |
4: type =EV_SYN
|
1698 |
|
1699 |
once hit, if the contact point changes, we'll get more
|
1700 |
EV_ABS (for 1 or both axes), followed by an EV_SYN.
|
1701 |
|
1702 |
and, on a lift:
|
1703 |
|
1704 |
5: type =EV_KEY
|
1705 |
code =330 [BTN_TOUCH]
|
1706 |
value=0
|
1707 |
|
1708 |
6: type =EV_SYN
|
1709 |
*/
|
1710 |
switch(ie.type)
|
1711 |
{
|
1712 |
case EV_KEY:
|
1713 |
{
|
1714 |
if(ie.code == BTN_TOUCH)
|
1715 |
{
|
1716 |
gr->ts_hit = ie.value;
|
1717 |
}
|
1718 |
|
1719 |
break;
|
1720 |
}
|
1721 |
|
1722 |
case EV_ABS:
|
1723 |
{
|
1724 |
if(ie.code == 0)
|
1725 |
{
|
1726 |
gr->ts_x = ie.value;
|
1727 |
}
|
1728 |
else if(ie.code == 1)
|
1729 |
{
|
1730 |
gr->ts_y = ie.value;
|
1731 |
}
|
1732 |
|
1733 |
break;
|
1734 |
}
|
1735 |
|
1736 |
case EV_SYN:
|
1737 |
{
|
1738 |
input_ts_map(&p.x, &p.y, gr->ts_x, gr->ts_y);
|
1739 |
|
1740 |
/* always send MOUSE_MOTION (first) */
|
1741 |
callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p);
|
1742 |
if(gr->ts_hit > 0)
|
1743 |
{
|
1744 |
callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)SDL_BUTTON_LEFT, (void *)&p);
|
1745 |
}
|
1746 |
else if(gr->ts_hit == 0)
|
1747 |
{
|
1748 |
callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)SDL_BUTTON_LEFT, (void *)&p);
|
1749 |
}
|
1750 |
|
1751 |
/* reset ts_hit */
|
1752 |
gr->ts_hit = -1;
|
1753 |
|
1754 |
break;
|
1755 |
}
|
1756 |
|
1757 |
default:
|
1758 |
{
|
1759 |
break;
|
1760 |
}
|
1761 |
}
|
1762 |
}
|
1763 |
}
|
1764 |
#endif
|
1765 |
|
1766 |
#ifdef USE_WEBOS_ACCELEROMETER
|
1767 |
struct callback* accel_cb = NULL;
|
1768 |
struct event_timeout* accel_to = NULL;
|
1769 |
if (PDL_GetPDKVersion() > 100) {
|
1770 |
accel_cb = callback_new_1(callback_cast(sdl_accelerometer_handler), gr);
|
1771 |
accel_to = event_add_timeout(200, 1, accel_cb);
|
1772 |
}
|
1773 |
#endif
|
1774 |
#ifdef USE_WEBOS
|
1775 |
unsigned int idle_tasks_idx=0;
|
1776 |
unsigned int idle_tasks_cur_priority=0;
|
1777 |
struct idle_task *task;
|
1778 |
|
1779 |
while(!quit_event_loop)
|
1780 |
#else
|
1781 |
while(1)
|
1782 |
#endif
|
1783 |
{
|
1784 |
#ifdef USE_WEBOS
|
1785 |
ret = 0;
|
1786 |
if(idle_tasks->len > 0)
|
1787 |
{
|
1788 |
while (!(ret = SDL_PollEvent(&ev)) && idle_tasks->len > 0)
|
1789 |
{
|
1790 |
if (idle_tasks_idx >= idle_tasks->len)
|
1791 |
idle_tasks_idx = 0;
|
1792 |
|
1793 |
dbg(3,"idle_tasks_idx(%d)\n",idle_tasks_idx);
|
1794 |
task = (struct idle_task *)g_ptr_array_index(idle_tasks,idle_tasks_idx);
|
1795 |
|
1796 |
if (idle_tasks_idx == 0) // only execute tasks with lowest priority value
|
1797 |
idle_tasks_cur_priority = task->priority;
|
1798 |
if (task->priority > idle_tasks_cur_priority)
|
1799 |
idle_tasks_idx = 0;
|
1800 |
else
|
1801 |
{
|
1802 |
callback_call_0(task->cb);
|
1803 |
idle_tasks_idx++;
|
1804 |
}
|
1805 |
}
|
1806 |
}
|
1807 |
if (!ret) // If we get here there are no idle_tasks and we have no events pending
|
1808 |
ret = SDL_WaitEvent(&ev);
|
1809 |
#else
|
1810 |
ret = SDL_PollEvent(&ev);
|
1811 |
#endif
|
1812 |
if(ret == 0)
|
1813 |
{
|
1814 |
break;
|
1815 |
}
|
1816 |
|
1817 |
#ifdef USE_WEBOS
|
1818 |
dbg(1,"SDL_Event %d\n", ev.type);
|
1819 |
#endif
|
1820 |
switch(ev.type)
|
1821 |
{
|
1822 |
case SDL_MOUSEMOTION:
|
1823 |
{
|
1824 |
p.x = ev.motion.x;
|
1825 |
p.y = ev.motion.y;
|
1826 |
callback_list_call_attr_1(gr->cbl, attr_motion, (void *)&p);
|
1827 |
break;
|
1828 |
}
|
1829 |
|
1830 |
case SDL_KEYDOWN:
|
1831 |
{
|
1832 |
memset(keybuf, 0, sizeof(keybuf));
|
1833 |
switch(ev.key.keysym.sym)
|
1834 |
{
|
1835 |
case SDLK_LEFT:
|
1836 |
{
|
1837 |
keybuf[0] = NAVIT_KEY_LEFT;
|
1838 |
break;
|
1839 |
}
|
1840 |
case SDLK_RIGHT:
|
1841 |
{
|
1842 |
keybuf[0] = NAVIT_KEY_RIGHT;
|
1843 |
break;
|
1844 |
}
|
1845 |
case SDLK_BACKSPACE:
|
1846 |
{
|
1847 |
keybuf[0] = NAVIT_KEY_BACKSPACE;
|
1848 |
break;
|
1849 |
}
|
1850 |
case SDLK_RETURN:
|
1851 |
{
|
1852 |
keybuf[0] = NAVIT_KEY_RETURN;
|
1853 |
break;
|
1854 |
}
|
1855 |
case SDLK_DOWN:
|
1856 |
{
|
1857 |
keybuf[0] = NAVIT_KEY_DOWN;
|
1858 |
break;
|
1859 |
}
|
1860 |
case SDLK_PAGEUP:
|
1861 |
{
|
1862 |
keybuf[0] = NAVIT_KEY_ZOOM_OUT;
|
1863 |
break;
|
1864 |
}
|
1865 |
case SDLK_UP:
|
1866 |
{
|
1867 |
keybuf[0] = NAVIT_KEY_UP;
|
1868 |
break;
|
1869 |
}
|
1870 |
case SDLK_PAGEDOWN:
|
1871 |
{
|
1872 |
keybuf[0] = NAVIT_KEY_ZOOM_IN;
|
1873 |
break;
|
1874 |
}
|
1875 |
#ifdef USE_WEBOS
|
1876 |
case WEBOS_KEY_SHIFT:
|
1877 |
{
|
1878 |
if ((key_mod & WEBOS_KEY_MOD_SHIFT_STICKY) == WEBOS_KEY_MOD_SHIFT_STICKY)
|
1879 |
key_mod &= ~(WEBOS_KEY_MOD_SHIFT_STICKY);
|
1880 |
else if ((key_mod & WEBOS_KEY_MOD_SHIFT) == WEBOS_KEY_MOD_SHIFT)
|
1881 |
key_mod |= WEBOS_KEY_MOD_SHIFT_STICKY;
|
1882 |
else
|
1883 |
key_mod |= WEBOS_KEY_MOD_SHIFT;
|
1884 |
break;
|
1885 |
}
|
1886 |
case WEBOS_KEY_ORANGE:
|
1887 |
{
|
1888 |
if ((key_mod & WEBOS_KEY_MOD_ORANGE_STICKY) == WEBOS_KEY_MOD_ORANGE_STICKY)
|
1889 |
key_mod &= ~(WEBOS_KEY_MOD_ORANGE_STICKY);
|
1890 |
else if ((key_mod & WEBOS_KEY_MOD_ORANGE) == WEBOS_KEY_MOD_ORANGE)
|
1891 |
key_mod |= WEBOS_KEY_MOD_ORANGE_STICKY;
|
1892 |
else
|
1893 |
key_mod |= WEBOS_KEY_MOD_ORANGE;
|
1894 |
break;
|
1895 |
}
|
1896 |
case WEBOS_KEY_SYM:
|
1897 |
{
|
1898 |
/* Toggle the on-screen keyboard */
|
1899 |
//callback_list_call_attr_1(gr->cbl, attr_keyboard_toggle); // Not implemented yet
|
1900 |
break;
|
1901 |
}
|
1902 |
case PDLK_GESTURE_BACK:
|
1903 |
{
|
1904 |
keybuf[0] = NAVIT_KEY_BACK;
|
1905 |
break;
|
1906 |
}
|
1907 |
case PDLK_GESTURE_FORWARD:
|
1908 |
case PDLK_GESTURE_AREA:
|
1909 |
{
|
1910 |
break;
|
1911 |
}
|
1912 |
#endif
|
1913 |
default:
|
1914 |
{
|
1915 |
#ifdef USE_WEBOS
|
1916 |
if (ev.key.keysym.unicode < 0x80 && ev.key.keysym.unicode > 0) {
|
1917 |
keybuf[0] = (char)ev.key.keysym.unicode;
|
1918 |
if ((key_mod & WEBOS_KEY_MOD_ORANGE) == WEBOS_KEY_MOD_ORANGE) {
|
1919 |
switch(keybuf[0]) {
|
1920 |
case 'e': keybuf[0] = '1'; break;
|
1921 |
case 'r': keybuf[0] = '2'; break;
|
1922 |
case 't': keybuf[0] = '3'; break;
|
1923 |
case 'd': keybuf[0] = '4'; break;
|
1924 |
case 'f': keybuf[0] = '5'; break;
|
1925 |
case 'g': keybuf[0] = '6'; break;
|
1926 |
case 'x': keybuf[0] = '7'; break;
|
1927 |
case 'c': keybuf[0] = '8'; break;
|
1928 |
case 'v': keybuf[0] = '9'; break;
|
1929 |
case '@': keybuf[0] = '0'; break;
|
1930 |
case ',': keybuf[0] = '-'; break;
|
1931 |
case 'u': strncpy(keybuf, "ü", sizeof(keybuf)); break;
|
1932 |
case 'a': strncpy(keybuf, "ä", sizeof(keybuf)); break;
|
1933 |
case 'o': strncpy(keybuf, "ö", sizeof(keybuf)); break;
|
1934 |
case 's': strncpy(keybuf, "ß", sizeof(keybuf)); break;
|
1935 |
}
|
1936 |
}
|
1937 |
if ((key_mod & WEBOS_KEY_MOD_SHIFT_STICKY) != WEBOS_KEY_MOD_SHIFT_STICKY)
|
1938 |
key_mod &= ~(WEBOS_KEY_MOD_SHIFT_STICKY);
|
1939 |
if ((key_mod & WEBOS_KEY_MOD_ORANGE_STICKY) != WEBOS_KEY_MOD_ORANGE_STICKY)
|
1940 |
key_mod &= ~(WEBOS_KEY_MOD_ORANGE_STICKY);
|
1941 |
}
|
1942 |
else {
|
1943 |
dbg(0,"Unknown key sym: %x\n", ev.key.keysym.sym);
|
1944 |
}
|
1945 |
#else
|
1946 |
/* return unicode chars when they can be converted to ascii */
|
1947 |
keybuf[0] = ev.key.keysym.unicode<=127 ? ev.key.keysym.unicode : 0;
|
1948 |
#endif
|
1949 |
break;
|
1950 |
}
|
1951 |
}
|
1952 |
|
1953 |
dbg(2,"key mod: 0x%x\n", key_mod);
|
1954 |
|
1955 |
if (keybuf[0]) {
|
1956 |
dbg(2,"key: %s 0x%x\n", keybuf, keybuf);
|
1957 |
callback_list_call_attr_1(gr->cbl, attr_keypress, (void *)keybuf);
|
1958 |
}
|
1959 |
break;
|
1960 |
}
|
1961 |
|
1962 |
case SDL_KEYUP:
|
1963 |
{
|
1964 |
break;
|
1965 |
}
|
1966 |
|
1967 |
case SDL_MOUSEBUTTONDOWN:
|
1968 |
{
|
1969 |
#ifdef DEBUG
|
1970 |
printf("SDL_MOUSEBUTTONDOWN %d %d %d %d %d\n",
|
1971 |
ev.button.which,
|
1972 |
ev.button.button,
|
1973 |
ev.button.state,
|
1974 |
ev.button.x,
|
1975 |
ev.button.y);
|
1976 |
#endif
|
1977 |
|
1978 |
p.x = ev.button.x;
|
1979 |
p.y = ev.button.y;
|
1980 |
callback_list_call_attr_3(gr->cbl, attr_button, (void *)1, (void *)(int)ev.button.button, (void *)&p);
|
1981 |
break;
|
1982 |
}
|
1983 |
|
1984 |
case SDL_MOUSEBUTTONUP:
|
1985 |
{
|
1986 |
#ifdef DEBUG
|
1987 |
printf("SDL_MOUSEBUTTONUP %d %d %d %d %d\n",
|
1988 |
ev.button.which,
|
1989 |
ev.button.button,
|
1990 |
ev.button.state,
|
1991 |
ev.button.x,
|
1992 |
ev.button.y);
|
1993 |
#endif
|
1994 |
|
1995 |
p.x = ev.button.x;
|
1996 |
p.y = ev.button.y;
|
1997 |
callback_list_call_attr_3(gr->cbl, attr_button, (void *)0, (void *)(int)ev.button.button, (void *)&p);
|
1998 |
break;
|
1999 |
}
|
2000 |
|
2001 |
case SDL_QUIT:
|
2002 |
{
|
2003 |
#ifdef USE_WEBOS
|
2004 |
quit_event_loop = 1;
|
2005 |
navit_destroy(gr->nav);
|
2006 |
#endif
|
2007 |
break;
|
2008 |
}
|
2009 |
|
2010 |
case SDL_VIDEORESIZE:
|
2011 |
{
|
2012 |
|
2013 |
gr->screen = SDL_SetVideoMode(ev.resize.w, ev.resize.h, gr->video_bpp, gr->video_flags);
|
2014 |
if(gr->screen == NULL)
|
2015 |
{
|
2016 |
navit_destroy(gr->nav);
|
2017 |
}
|
2018 |
else
|
2019 |
{
|
2020 |
callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
|
2021 |
}
|
2022 |
|
2023 |
break;
|
2024 |
}
|
2025 |
|
2026 |
#ifdef USE_WEBOS
|
2027 |
case SDL_USEREVENT:
|
2028 |
{
|
2029 |
SDL_UserEvent userevent = ev.user;
|
2030 |
dbg(9,"received SDL_USEREVENT type(%x) code(%x)\n",userevent.type,userevent.code);
|
2031 |
if (userevent.type != SDL_USEREVENT)
|
2032 |
break;
|
2033 |
|
2034 |
if (userevent.code == PDL_GPS_UPDATE)
|
2035 |
{
|
2036 |
struct attr vehicle_attr;
|
2037 |
struct vehicle *v;
|
2038 |
navit_get_attr(gr->nav, attr_vehicle, &vehicle_attr, NULL);
|
2039 |
v = vehicle_attr.u.vehicle;
|
2040 |
if (v) {
|
2041 |
struct attr attr;
|
2042 |
attr.type = attr_pdl_gps_update;
|
2043 |
attr.u.data = userevent.data1;
|
2044 |
vehicle_set_attr(v, &attr);
|
2045 |
}
|
2046 |
}
|
2047 |
else if(userevent.code == SDL_USEREVENT_CODE_TIMER)
|
2048 |
{
|
2049 |
struct callback *cb = (struct callback *)userevent.data1;
|
2050 |
dbg(1, "SDL_USEREVENT timer received cb(%p)\n", cb);
|
2051 |
callback_call_0(cb);
|
2052 |
}
|
2053 |
else if(userevent.code == SDL_USEREVENT_CODE_WATCH)
|
2054 |
{
|
2055 |
struct callback *cb = (struct callback *)userevent.data1;
|
2056 |
dbg(1, "SDL_USEREVENT watch received cb(%p)\n", cb);
|
2057 |
callback_call_0(cb);
|
2058 |
}
|
2059 |
else if(userevent.code == SDL_USEREVENT_CODE_CALL_CALLBACK)
|
2060 |
{
|
2061 |
struct callback_list *cbl = (struct callback_list *)userevent.data1;
|
2062 |
dbg(1, "SDL_USEREVENT call_callback received cbl(%p)\n", cbl);
|
2063 |
callback_list_call_0(cbl);
|
2064 |
}
|
2065 |
else if(userevent.code == SDL_USEREVENT_CODE_IDLE_EVENT) {
|
2066 |
dbg(1, "SDL_USEREVENT idle_event received\n");
|
2067 |
}
|
2068 |
#ifdef USE_WEBOS_ACCELEROMETER
|
2069 |
else if(userevent.code == SDL_USEREVENT_CODE_ROTATE)
|
2070 |
{
|
2071 |
dbg(1, "SDL_USEREVENT rotate received\n");
|
2072 |
switch(gr->orientation)
|
2073 |
{
|
2074 |
case WEBOS_ORIENTATION_PORTRAIT:
|
2075 |
gr->screen = SDL_SetVideoMode(gr->real_w, gr->real_h, gr->video_bpp, gr->video_flags);
|
2076 |
PDL_SetOrientation(PDL_ORIENTATION_0);
|
2077 |
break;
|
2078 |
case WEBOS_ORIENTATION_LANDSCAPE:
|
2079 |
gr->screen = SDL_SetVideoMode(gr->real_h, gr->real_w, gr->video_bpp, gr->video_flags);
|
2080 |
PDL_SetOrientation(PDL_ORIENTATION_270);
|
2081 |
break;
|
2082 |
}
|
2083 |
if(gr->screen == NULL)
|
2084 |
{
|
2085 |
navit_destroy(gr->nav);
|
2086 |
}
|
2087 |
else
|
2088 |
{
|
2089 |
callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->screen->w, (void *)gr->screen->h);
|
2090 |
}
|
2091 |
}
|
2092 |
#endif
|
2093 |
else
|
2094 |
dbg(1, "unknown SDL_USEREVENT\n");
|
2095 |
|
2096 |
break;
|
2097 |
}
|
2098 |
#endif
|
2099 |
default:
|
2100 |
{
|
2101 |
#ifdef DEBUG
|
2102 |
printf("SDL_Event %d\n", ev.type);
|
2103 |
#endif
|
2104 |
break;
|
2105 |
}
|
2106 |
}
|
2107 |
}
|
2108 |
|
2109 |
#ifdef USE_WEBOS
|
2110 |
event_sdl_watch_stopthread();
|
2111 |
#endif
|
2112 |
|
2113 |
#ifdef USE_WEBOS_ACCELEROMETER
|
2114 |
if (PDL_GetPDKVersion() > 100) {
|
2115 |
event_remove_timeout(accel_to);
|
2116 |
callback_destroy(accel_cb);
|
2117 |
}
|
2118 |
#endif
|
2119 |
|
2120 |
return TRUE;
|
2121 |
}
|
2122 |
|
2123 |
|
2124 |
static struct graphics_priv *
|
2125 |
graphics_sdl_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
|
2126 |
{
|
2127 |
struct graphics_priv *this=g_new0(struct graphics_priv, 1);
|
2128 |
struct attr *attr;
|
2129 |
int ret;
|
2130 |
int w=DISPLAY_W,h=DISPLAY_H;
|
2131 |
|
2132 |
struct font_priv *(*font_freetype_new) (void *meth);
|
2133 |
font_freetype_new = plugin_get_font_type ("freetype");
|
2134 |
|
2135 |
if (!font_freetype_new)
|
2136 |
{
|
2137 |
return NULL;
|
2138 |
}
|
2139 |
|
2140 |
font_freetype_new (&this->freetype_methods);
|
2141 |
|
2142 |
this->nav = nav;
|
2143 |
this->cbl = cbl;
|
2144 |
|
2145 |
dbg(1,"Calling SDL_Init\n");
|
2146 |
#ifdef USE_WEBOS
|
2147 |
# ifdef USE_WEBOS_ACCELEROMETER
|
2148 |
ret = SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_JOYSTICK);
|
2149 |
# else
|
2150 |
ret = SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
|
2151 |
# endif
|
2152 |
#else
|
2153 |
ret = SDL_Init(SDL_INIT_VIDEO);
|
2154 |
#endif
|
2155 |
if(ret < 0)
|
2156 |
{
|
2157 |
dbg(0,"SDL_Init failed %d\n", ret);
|
2158 |
g_free(this);
|
2159 |
return NULL;
|
2160 |
}
|
2161 |
|
2162 |
#ifdef USE_WEBOS
|
2163 |
dbg(1,"Calling PDL_Init(0)\n");
|
2164 |
ret = PDL_Init(0);
|
2165 |
if(ret < 0)
|
2166 |
{
|
2167 |
dbg(0,"PDL_Init failed %d\n", ret);
|
2168 |
g_free(this);
|
2169 |
return NULL;
|
2170 |
}
|
2171 |
|
2172 |
if (! event_request_system("sdl","graphics_sdl_new")) {
|
2173 |
#else
|
2174 |
if (! event_request_system("glib","graphics_sdl_new")) {
|
2175 |
#endif
|
2176 |
dbg(0,"event_request_system failed");
|
2177 |
return NULL;
|
2178 |
}
|
2179 |
|
2180 |
#ifdef USE_WEBOS
|
2181 |
this->video_bpp = 0;
|
2182 |
this->video_flags = SDL_SWSURFACE | SDL_ANYFORMAT | SDL_RESIZABLE;
|
2183 |
#else
|
2184 |
this->video_bpp = 16;
|
2185 |
this->video_flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE;
|
2186 |
#endif
|
2187 |
|
2188 |
if ((attr=attr_search(attrs, NULL, attr_w)))
|
2189 |
w=attr->u.num;
|
2190 |
if ((attr=attr_search(attrs, NULL, attr_h)))
|
2191 |
h=attr->u.num;
|
2192 |
if ((attr=attr_search(attrs, NULL, attr_bpp)))
|
2193 |
this->video_bpp=attr->u.num;
|
2194 |
if ((attr=attr_search(attrs, NULL, attr_flags))) {
|
2195 |
if (attr->u.num & 1)
|
2196 |
this->video_flags = SDL_SWSURFACE;
|
2197 |
}
|
2198 |
if ((attr=attr_search(attrs, NULL, attr_frame))) {
|
2199 |
if(!attr->u.num)
|
2200 |
this->video_flags |= SDL_NOFRAME;
|
2201 |
}
|
2202 |
|
2203 |
this->screen = SDL_SetVideoMode(w, h, this->video_bpp, this->video_flags);
|
2204 |
|
2205 |
if(this->screen == NULL)
|
2206 |
{
|
2207 |
dbg(0,"SDL_SetVideoMode failed\n");
|
2208 |
g_free(this);
|
2209 |
#ifdef USE_WEBOS
|
2210 |
PDL_Quit();
|
2211 |
#endif
|
2212 |
SDL_Quit();
|
2213 |
return NULL;
|
2214 |
}
|
2215 |
|
2216 |
/* Use screen size instead of requested */
|
2217 |
w = this->screen->w;
|
2218 |
h = this->screen->h;
|
2219 |
|
2220 |
dbg(0, "using screen %ix%i@%i\n",
|
2221 |
this->screen->w, this->screen->h,
|
2222 |
this->screen->format->BytesPerPixel * 8);
|
2223 |
#ifdef USE_WEBOS_ACCELEROMETER
|
2224 |
this->real_w = w;
|
2225 |
this->real_h = h;
|
2226 |
this->accelerometer = SDL_JoystickOpen(0);
|
2227 |
#endif
|
2228 |
|
2229 |
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
2230 |
#ifdef USE_WEBOS
|
2231 |
PDL_SetOrientation(PDL_ORIENTATION_0);
|
2232 |
#endif
|
2233 |
|
2234 |
SDL_EnableUNICODE(1);
|
2235 |
SDL_WM_SetCaption("navit", NULL);
|
2236 |
|
2237 |
#ifdef LINUX_TOUCHSCREEN
|
2238 |
input_ts_init(this);
|
2239 |
if(this->ts_fd >= 0)
|
2240 |
{
|
2241 |
/* mouse cursor does not always display correctly in Linux FB.
|
2242 |
anyway, it is unnecessary w/ a touch screen
|
2243 |
*/
|
2244 |
SDL_ShowCursor(0);
|
2245 |
}
|
2246 |
#endif
|
2247 |
|
2248 |
#ifdef SDL_SGE
|
2249 |
sge_Update_OFF();
|
2250 |
sge_Lock_ON();
|
2251 |
#endif
|
2252 |
|
2253 |
*meth=graphics_methods;
|
2254 |
|
2255 |
|
2256 |
meth->font_new =
|
2257 |
(struct graphics_font_priv *
|
2258 |
(*)(struct graphics_priv *, struct graphics_font_methods *, char *, int,
|
2259 |
int)) this->freetype_methods.font_new;
|
2260 |
meth->get_text_bbox = (void*) this->freetype_methods.get_text_bbox;
|
2261 |
|
2262 |
|
2263 |
|
2264 |
#ifdef USE_WEBOS
|
2265 |
if(the_graphics!=NULL) {
|
2266 |
dbg(0,"graphics_sdl_new: graphics struct already set: %d!\n", the_graphics_count);
|
2267 |
}
|
2268 |
the_graphics = this;
|
2269 |
the_graphics_count++;
|
2270 |
#else
|
2271 |
g_timeout_add(G_PRIORITY_DEFAULT+10, graphics_sdl_idle, this);
|
2272 |
#endif
|
2273 |
|
2274 |
this->overlay_enable = 1;
|
2275 |
|
2276 |
this->aa = 1;
|
2277 |
if((attr=attr_search(attrs, NULL, attr_antialias)))
|
2278 |
this->aa = attr->u.num;
|
2279 |
|
2280 |
this->resize_callback_initial=1;
|
2281 |
return this;
|
2282 |
}
|
2283 |
|
2284 |
#ifdef USE_WEBOS
|
2285 |
/* ---------- SDL Eventhandling ---------- */
|
2286 |
|
2287 |
static Uint32
|
2288 |
sdl_timer_callback(Uint32 interval, void* param)
|
2289 |
{
|
2290 |
struct event_timeout *timeout=(struct event_timeout*)param;
|
2291 |
|
2292 |
dbg(1,"timer(%p) multi(%d) interval(%d) fired\n", param, timeout->multi, interval);
|
2293 |
|
2294 |
SDL_Event event;
|
2295 |
SDL_UserEvent userevent;
|
2296 |
|
2297 |
userevent.type = SDL_USEREVENT;
|
2298 |
userevent.code = SDL_USEREVENT_CODE_TIMER;
|
2299 |
userevent.data1 = timeout->cb;
|
2300 |
userevent.data2 = NULL;
|
2301 |
|
2302 |
event.type = SDL_USEREVENT;
|
2303 |
event.user = userevent;
|
2304 |
|
2305 |
SDL_PushEvent (&event);
|
2306 |
|
2307 |
if (timeout->multi==0) {
|
2308 |
g_free(timeout);
|
2309 |
timeout = NULL;
|
2310 |
return 0; // cancel timer
|
2311 |
}
|
2312 |
return interval; // reactivate timer
|
2313 |
}
|
2314 |
|
2315 |
/* SDL Mainloop */
|
2316 |
|
2317 |
static void
|
2318 |
event_sdl_main_loop_run(void)
|
2319 |
{
|
2320 |
PDL_ScreenTimeoutEnable(PDL_FALSE);
|
2321 |
graphics_sdl_idle(NULL);
|
2322 |
PDL_ScreenTimeoutEnable(PDL_TRUE);
|
2323 |
}
|
2324 |
|
2325 |
static void
|
2326 |
event_sdl_main_loop_quit(void)
|
2327 |
{
|
2328 |
quit_event_loop = 1;
|
2329 |
}
|
2330 |
|
2331 |
/* Watch */
|
2332 |
|
2333 |
static void
|
2334 |
event_sdl_watch_thread (GPtrArray *watch_list)
|
2335 |
{
|
2336 |
struct pollfd *pfds = g_new0 (struct pollfd, watch_list->len);
|
2337 |
struct event_watch *ew;
|
2338 |
int ret;
|
2339 |
int idx;
|
2340 |
|
2341 |
for (idx = 0; idx < watch_list->len; idx++ ) {
|
2342 |
ew = g_ptr_array_index (watch_list, idx);
|
2343 |
g_memmove (&pfds[idx], ew->pfd, sizeof(struct pollfd));
|
2344 |
}
|
2345 |
|
2346 |
while ((ret = ppoll(pfds, watch_list->len, NULL, NULL)) > 0) {
|
2347 |
for (idx = 0; idx < watch_list->len; idx++ ) {
|
2348 |
if (pfds[idx].revents == pfds[idx].events) { /* The requested event happened, notify mainloop! */
|
2349 |
ew = g_ptr_array_index (watch_list, idx);
|
2350 |
dbg(1,"watch(%p) event(%d) encountered\n", ew, pfds[idx].revents);
|
2351 |
|
2352 |
SDL_Event event;
|
2353 |
SDL_UserEvent userevent;
|
2354 |
|
2355 |
userevent.type = SDL_USEREVENT;
|
2356 |
userevent.code = SDL_USEREVENT_CODE_WATCH;
|
2357 |
userevent.data1 = ew->cb;
|
2358 |
userevent.data2 = NULL;
|
2359 |
|
2360 |
event.type = SDL_USEREVENT;
|
2361 |
event.user = userevent;
|
2362 |
|
2363 |
SDL_PushEvent (&event);
|
2364 |
}
|
2365 |
}
|
2366 |
}
|
2367 |
|
2368 |
g_free(pfds);
|
2369 |
|
2370 |
pthread_exit(0);
|
2371 |
}
|
2372 |
|
2373 |
static void
|
2374 |
event_sdl_watch_startthread(GPtrArray *watch_list)
|
2375 |
{
|
2376 |
dbg(1,"enter\n");
|
2377 |
if (sdl_watch_thread)
|
2378 |
event_sdl_watch_stopthread();
|
2379 |
|
2380 |
int ret;
|
2381 |
ret = pthread_create (&sdl_watch_thread, NULL, (void *)event_sdl_watch_thread, (void *)watch_list);
|
2382 |
|
2383 |
dbg_assert (ret == 0);
|
2384 |
}
|
2385 |
|
2386 |
static void
|
2387 |
event_sdl_watch_stopthread()
|
2388 |
{
|
2389 |
dbg(1,"enter\n");
|
2390 |
if (sdl_watch_thread) {
|
2391 |
/* Notify the watch thread that the list of FDs will change */
|
2392 |
pthread_kill(sdl_watch_thread, SIGUSR1);
|
2393 |
pthread_join(sdl_watch_thread, NULL);
|
2394 |
sdl_watch_thread = 0;
|
2395 |
}
|
2396 |
}
|
2397 |
|
2398 |
static struct event_watch *
|
2399 |
event_sdl_add_watch(void *fd, enum event_watch_cond cond, struct callback *cb)
|
2400 |
{
|
2401 |
dbg(1,"fd(%d) cond(%x) cb(%x)\n", fd, cond, cb);
|
2402 |
|
2403 |
event_sdl_watch_stopthread();
|
2404 |
|
2405 |
if (!sdl_watch_list)
|
2406 |
sdl_watch_list = g_ptr_array_new();
|
2407 |
|
2408 |
struct event_watch *new_ew = g_new0 (struct event_watch, 1);
|
2409 |
struct pollfd *pfd = g_new0 (struct pollfd, 1);
|
2410 |
|
2411 |
pfd->fd = (int) fd;
|
2412 |
|
2413 |
/* Modify watchlist here */
|
2414 |
switch (cond) {
|
2415 |
case event_watch_cond_read:
|
2416 |
pfd->events = POLLIN;
|
2417 |
break;
|
2418 |
case event_watch_cond_write:
|
2419 |
pfd->events = POLLOUT;
|
2420 |
break;
|
2421 |
case event_watch_cond_except:
|
2422 |
pfd->events = POLLERR|POLLHUP;
|
2423 |
break;
|
2424 |
}
|
2425 |
|
2426 |
new_ew->pfd = (struct pollfd*) pfd;
|
2427 |
new_ew->cb = cb;
|
2428 |
|
2429 |
g_ptr_array_add (sdl_watch_list, (gpointer)new_ew);
|
2430 |
|
2431 |
event_sdl_watch_startthread(sdl_watch_list);
|
2432 |
|
2433 |
return new_ew;
|
2434 |
}
|
2435 |
|
2436 |
static void
|
2437 |
event_sdl_remove_watch(struct event_watch *ew)
|
2438 |
{
|
2439 |
dbg(1,"enter %p\n",ew);
|
2440 |
|
2441 |
event_sdl_watch_stopthread();
|
2442 |
|
2443 |
g_ptr_array_remove (sdl_watch_list, ew);
|
2444 |
g_free (ew->pfd);
|
2445 |
g_free (ew);
|
2446 |
|
2447 |
if (sdl_watch_list->len > 0)
|
2448 |
event_sdl_watch_startthread(sdl_watch_list);
|
2449 |
}
|
2450 |
|
2451 |
/* Timeout */
|
2452 |
|
2453 |
static struct event_timeout *
|
2454 |
event_sdl_add_timeout(int timeout, int multi, struct callback *cb)
|
2455 |
{
|
2456 |
struct event_timeout * ret = g_new0(struct event_timeout, 1);
|
2457 |
if(!ret)
|
2458 |
return ret;
|
2459 |
dbg(1,"timer(%p) multi(%d) interval(%d) cb(%p) added\n",ret, multi, timeout, cb);
|
2460 |
ret->multi = multi;
|
2461 |
ret->cb = cb;
|
2462 |
ret->id = SDL_AddTimer(timeout, sdl_timer_callback, ret);
|
2463 |
|
2464 |
return ret;
|
2465 |
}
|
2466 |
|
2467 |
static void
|
2468 |
event_sdl_remove_timeout(struct event_timeout *to)
|
2469 |
{
|
2470 |
dbg(2,"enter %p\n", to);
|
2471 |
if(to!=NULL)
|
2472 |
{
|
2473 |
int ret = to->id ? SDL_RemoveTimer(to->id) : SDL_TRUE;
|
2474 |
if (ret == SDL_FALSE) {
|
2475 |
dbg(0,"SDL_RemoveTimer (%p) failed\n", to->id);
|
2476 |
}
|
2477 |
else {
|
2478 |
g_free(to);
|
2479 |
dbg(1,"timer(%p) removed\n", to);
|
2480 |
}
|
2481 |
}
|
2482 |
}
|
2483 |
|
2484 |
/* Idle */
|
2485 |
|
2486 |
/* sort ptr_array by priority, increasing order */
|
2487 |
static gint
|
2488 |
sdl_sort_idle_tasks(gconstpointer parama, gconstpointer paramb)
|
2489 |
{
|
2490 |
struct idle_task *a = (struct idle_task *)parama;
|
2491 |
struct idle_task *b = (struct idle_task *)paramb;
|
2492 |
if (a->priority < b->priority)
|
2493 |
return -1;
|
2494 |
if (a->priority > b->priority)
|
2495 |
return 1;
|
2496 |
return 0;
|
2497 |
}
|
2498 |
|
2499 |
static struct event_idle *
|
2500 |
event_sdl_add_idle(int priority, struct callback *cb)
|
2501 |
{
|
2502 |
dbg(1,"add idle priority(%d) cb(%p)\n", priority, cb);
|
2503 |
|
2504 |
struct idle_task *task = g_new0(struct idle_task, 1);
|
2505 |
task->priority = priority;
|
2506 |
task->cb = cb;
|
2507 |
|
2508 |
g_ptr_array_add(idle_tasks, (gpointer)task);
|
2509 |
|
2510 |
if (idle_tasks->len < 2)
|
2511 |
{
|
2512 |
SDL_Event event;
|
2513 |
SDL_UserEvent userevent;
|
2514 |
|
2515 |
dbg(1,"poking eventloop because of new idle_events\n");
|
2516 |
|
2517 |
userevent.type = SDL_USEREVENT;
|
2518 |
userevent.code = SDL_USEREVENT_CODE_IDLE_EVENT;
|
2519 |
userevent.data1 = NULL;
|
2520 |
userevent.data2 = NULL;
|
2521 |
|
2522 |
event.type = SDL_USEREVENT;
|
2523 |
event.user = userevent;
|
2524 |
|
2525 |
SDL_PushEvent (&event);
|
2526 |
}
|
2527 |
else // more than one entry => sort the list
|
2528 |
g_ptr_array_sort(idle_tasks, sdl_sort_idle_tasks);
|
2529 |
|
2530 |
return (struct event_idle *)task;
|
2531 |
}
|
2532 |
|
2533 |
static void
|
2534 |
event_sdl_remove_idle(struct event_idle *task)
|
2535 |
{
|
2536 |
dbg(1,"remove task(%p)\n", task);
|
2537 |
g_ptr_array_remove(idle_tasks, (gpointer)task);
|
2538 |
}
|
2539 |
|
2540 |
/* callback */
|
2541 |
|
2542 |
static void
|
2543 |
event_sdl_call_callback(struct callback_list *cbl)
|
2544 |
{
|
2545 |
dbg(1,"call_callback cbl(%p)\n",cbl);
|
2546 |
SDL_Event event;
|
2547 |
SDL_UserEvent userevent;
|
2548 |
|
2549 |
userevent.type = SDL_USEREVENT;
|
2550 |
userevent.code = SDL_USEREVENT_CODE_CALL_CALLBACK;
|
2551 |
userevent.data1 = cbl;
|
2552 |
userevent.data2 = NULL;
|
2553 |
|
2554 |
event.type = SDL_USEREVENT;
|
2555 |
event.user = userevent;
|
2556 |
|
2557 |
SDL_PushEvent (&event);
|
2558 |
}
|
2559 |
|
2560 |
static struct event_methods event_sdl_methods = {
|
2561 |
event_sdl_main_loop_run,
|
2562 |
event_sdl_main_loop_quit,
|
2563 |
event_sdl_add_watch,
|
2564 |
event_sdl_remove_watch,
|
2565 |
event_sdl_add_timeout,
|
2566 |
event_sdl_remove_timeout,
|
2567 |
event_sdl_add_idle,
|
2568 |
event_sdl_remove_idle,
|
2569 |
event_sdl_call_callback,
|
2570 |
};
|
2571 |
|
2572 |
static struct event_priv *
|
2573 |
event_sdl_new(struct event_methods* methods)
|
2574 |
{
|
2575 |
idle_tasks = g_ptr_array_new();
|
2576 |
*methods = event_sdl_methods;
|
2577 |
return NULL;
|
2578 |
}
|
2579 |
|
2580 |
/* ---------- SDL Eventhandling ---------- */
|
2581 |
#endif
|
2582 |
|
2583 |
void
|
2584 |
plugin_init(void)
|
2585 |
{
|
2586 |
#ifdef USE_WEBOS
|
2587 |
plugin_register_event_type("sdl", event_sdl_new);
|
2588 |
#endif
|
2589 |
plugin_register_graphics_type("sdl", graphics_sdl_new);
|
2590 |
}
|
2591 |
|
2592 |
// vim: sw=4 ts=8
|