/[zanavi_public1]/navit/navit/graphics/sdl/graphics_sdl.c
ZANavi

Contents of /navit/navit/graphics/sdl/graphics_sdl.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 62969 byte(s)
import files
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

   
Visit the ZANavi Wiki