Recreate the navit git/gerrit project that vanished
[profile/ivi/navit.git] / navit / graphics / android / graphics_android.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <unistd.h>
21 #include <glib.h>
22 #include <poll.h>
23 #include "config.h"
24 #include "window.h"
25 #include "point.h"
26 #include "graphics.h"
27 #include "color.h"
28 #include "plugin.h"
29 #include "event.h"
30 #include "debug.h"
31 #include "callback.h"
32 #include "android.h"
33
34 int dummy;
35
36 struct graphics_priv {
37         jclass NavitGraphicsClass;
38         jmethodID NavitGraphics_draw_polyline, NavitGraphics_draw_polygon, NavitGraphics_draw_rectangle, NavitGraphics_draw_circle, NavitGraphics_draw_text, NavitGraphics_draw_image, NavitGraphics_draw_mode, NavitGraphics_draw_drag, NavitGraphics_overlay_disable, NavitGraphics_overlay_resize, NavitGraphics_SetCamera;
39
40         jclass PaintClass;
41         jmethodID Paint_init,Paint_setStrokeWidth,Paint_setARGB;
42
43         jobject NavitGraphics;
44         jobject Paint;
45         
46         jclass BitmapFactoryClass;      
47         jmethodID BitmapFactory_decodeFile, BitmapFactory_decodeResource;
48
49         jclass BitmapClass;
50         jmethodID Bitmap_getHeight, Bitmap_getWidth;
51
52         jclass ContextClass;
53         jmethodID Context_getResources;
54
55         jclass ResourcesClass;
56         jobject Resources;
57         jmethodID Resources_getIdentifier;
58
59         jobject packageName;
60
61         struct callback_list *cbl;
62         struct window win;
63 };
64
65 struct graphics_font_priv {
66         int size;
67 };
68
69 struct graphics_gc_priv {
70         struct graphics_priv *gra;
71         int linewidth;
72         enum draw_mode_num mode;
73         int a,r,g,b;
74 };
75
76 struct graphics_image_priv {
77         jobject Bitmap;
78         int width;
79         int height;
80         struct point hot;
81 };
82
83 static GHashTable *image_cache_hash = NULL;
84
85 static int
86 find_class_global(char *name, jclass *ret)
87 {
88         *ret=(*jnienv)->FindClass(jnienv, name);
89         if (! *ret) {
90                 dbg(0,"Failed to get Class %s\n",name);
91                 return 0;
92         }
93         (*jnienv)->NewGlobalRef(jnienv, *ret);
94         return 1;
95 }
96
97 static int
98 find_method(jclass class, char *name, char *args, jmethodID *ret)
99 {
100         *ret = (*jnienv)->GetMethodID(jnienv, class, name, args);
101         if (*ret == NULL) {
102                 dbg(0,"Failed to get Method %s with signature %s\n",name,args);
103                 return 0;
104         }
105         return 1;
106 }
107
108 static int
109 find_static_method(jclass class, char *name, char *args, jmethodID *ret)
110 {
111         *ret = (*jnienv)->GetStaticMethodID(jnienv, class, name, args);
112         if (*ret == NULL) {
113                 dbg(0,"Failed to get static Method %s with signature %s\n",name,args);
114                 return 0;
115         }
116         return 1;
117 }
118
119 static void
120 graphics_destroy(struct graphics_priv *gr)
121 {
122 }
123
124 static void font_destroy(struct graphics_font_priv *font)
125 {
126         g_free(font);
127 }
128
129 static struct graphics_font_methods font_methods = {
130         font_destroy
131 };
132
133 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *font,  int size, int flags)
134 {
135         struct graphics_font_priv *ret=g_new0(struct graphics_font_priv, 1);
136         *meth=font_methods;
137
138         ret->size=size;
139         return ret;
140 }
141
142 static void
143 gc_destroy(struct graphics_gc_priv *gc)
144 {
145         g_free(gc);
146 }
147
148 static void
149 gc_set_linewidth(struct graphics_gc_priv *gc, int w)
150 {
151     gc->linewidth = w;
152 }
153
154 static void
155 gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
156 {
157 }
158
159 static void
160 gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
161 {
162     gc->r = c->r >> 8;
163     gc->g = c->g >> 8;
164     gc->b = c->b >> 8;
165     gc->a = c->a >> 8;
166 }
167
168 static void
169 gc_set_background(struct graphics_gc_priv *gc, struct color *c)
170 {
171 }
172
173 static struct graphics_gc_methods gc_methods = {
174         gc_destroy,
175         gc_set_linewidth,
176         gc_set_dashes,  
177         gc_set_foreground,      
178         gc_set_background       
179 };
180
181 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
182 {
183         struct graphics_gc_priv *ret=g_new0(struct graphics_gc_priv, 1);
184         *meth=gc_methods;
185
186         ret->gra = gr;
187         ret->a = ret->r = ret->g = ret->b = 255;
188         ret->linewidth=1;
189         return ret;
190 }
191
192 static void image_destroy(struct graphics_image_priv *img)
193 {
194     // unused?
195 }
196
197 static struct graphics_image_methods image_methods = {
198         image_destroy
199 };
200
201
202 static struct graphics_image_priv *
203 image_new(struct graphics_priv *gra, struct graphics_image_methods *meth, char *path, int *w, int *h, struct point *hot, int rotation)
204 {
205         struct graphics_image_priv* ret = NULL;
206         
207         if ( !g_hash_table_lookup_extended( image_cache_hash, path, NULL, (gpointer)&ret) )
208         {
209                 ret=g_new0(struct graphics_image_priv, 1);
210                 jstring string;
211                 int id;
212
213                 dbg(1,"enter %s\n",path);
214                 if (!strncmp(path,"res/drawable/",13)) {
215                         jstring a=(*jnienv)->NewStringUTF(jnienv, "drawable");
216                         char *path_noext=g_strdup(path+13);
217                         char *pos=strrchr(path_noext, '.');
218                         if (pos) 
219                                 *pos='\0';
220                         dbg(1,"path_noext=%s\n",path_noext);
221                         string = (*jnienv)->NewStringUTF(jnienv, path_noext);
222                         g_free(path_noext);
223                         id=(*jnienv)->CallIntMethod(jnienv, gra->Resources, gra->Resources_getIdentifier, string, a, gra->packageName);
224                         dbg(1,"id=%d\n",id);
225                         if (id)
226                                 ret->Bitmap=(*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeResource, gra->Resources, id);
227                         (*jnienv)->DeleteLocalRef(jnienv, a);
228                 } else {
229                         string = (*jnienv)->NewStringUTF(jnienv, path);
230                         ret->Bitmap=(*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeFile, string);
231                 }
232                 dbg(1,"result=%p\n",ret->Bitmap);
233                 if (ret->Bitmap) {
234                         (*jnienv)->NewGlobalRef(jnienv, ret->Bitmap);
235                         (*jnienv)->DeleteLocalRef(jnienv, ret->Bitmap);
236                         ret->width=(*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getWidth);
237                         ret->height=(*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getHeight);
238                         dbg(1,"w=%d h=%d for %s\n",ret->width,ret->height,path);
239                         ret->hot.x=ret->width/2;
240                         ret->hot.y=ret->height/2;
241                 } else {
242                         g_free(ret);
243                         ret=NULL;
244                         dbg(0,"Failed to open %s\n",path);
245                 }
246                 (*jnienv)->DeleteLocalRef(jnienv, string);
247                 g_hash_table_insert(image_cache_hash, g_strdup( path ),  (gpointer)ret );
248         }
249         if (ret) {
250                 *w=ret->width;
251                 *h=ret->height;
252                 if (hot)
253                         *hot=ret->hot;
254         }
255
256         return ret;
257 }
258
259 static void initPaint(struct graphics_priv *gra, struct graphics_gc_priv *gc)
260 {
261     float wf = gc->linewidth;
262     (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setStrokeWidth, wf);
263     (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setARGB, gc->a, gc->r, gc->g, gc->b);
264 }
265
266 static void
267 draw_lines(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
268 {
269         jint pc[count*2];
270         int i;
271         jintArray points;
272         if (count <= 0)
273                 return;
274         points = (*jnienv)->NewIntArray(jnienv,count*2);
275         for (i = 0 ; i < count ; i++) {
276                 pc[i*2]=p[i].x;
277                 pc[i*2+1]=p[i].y;
278         }
279         initPaint(gra, gc);
280         (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count*2, pc);
281         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline, gc->gra->Paint, points);
282         (*jnienv)->DeleteLocalRef(jnienv, points);
283 }
284
285 static void
286 draw_polygon(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
287 {
288         jint pc[count*2];
289         int i;
290         jintArray points;
291         if (count <= 0)
292                 return;
293         points = (*jnienv)->NewIntArray(jnienv,count*2);
294         for (i = 0 ; i < count ; i++) {
295                 pc[i*2]=p[i].x;
296                 pc[i*2+1]=p[i].y;
297         }
298         initPaint(gra, gc);
299         (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count*2, pc);
300         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polygon, gc->gra->Paint, points);
301         (*jnienv)->DeleteLocalRef(jnienv, points);
302 }
303
304 static void
305 draw_rectangle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int w, int h)
306 {
307         initPaint(gra, gc);
308         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_rectangle, gc->gra->Paint, p->x, p->y, w, h);
309 }
310
311 static void
312 draw_circle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int r)
313 {
314         initPaint(gra, gc);
315         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_circle, gc->gra->Paint, p->x, p->y, r);
316 }
317
318
319 static void
320 draw_text(struct graphics_priv *gra, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
321 {
322         dbg(1,"enter %s\n", text);
323         initPaint(gra, fg);
324         jstring string = (*jnienv)->NewStringUTF(jnienv, text);
325         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_text, fg->gra->Paint, p->x, p->y, string, font->size, dx, dy);
326         (*jnienv)->DeleteLocalRef(jnienv, string);
327 }
328
329 static void
330 draw_image(struct graphics_priv *gra, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
331 {
332         dbg(1,"enter %p\n",img);
333         initPaint(gra, fg);
334         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_image, fg->gra->Paint, p->x, p->y, img->Bitmap);
335         
336 }
337
338 static void
339 draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
340 {
341 }
342
343 static void
344 draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
345 {
346 }
347
348 static void draw_drag(struct graphics_priv *gra, struct point *p)
349 {
350         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_drag, p ? p->x : 0, p ? p->y : 0);
351 }
352
353 static void
354 background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
355 {
356 }
357
358 static void
359 draw_mode(struct graphics_priv *gra, enum draw_mode_num mode)
360 {
361         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_mode, (int)mode);
362 }
363
364 static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound);
365
366 static void *
367 get_data(struct graphics_priv *this, const char *type)
368 {
369         if (strcmp(type,"window"))
370                 return NULL;
371         return &this->win;
372 }
373
374 static void image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
375 {
376 }
377
378 static void get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
379 {
380         int len = g_utf8_strlen(text, -1);
381         int xMin = 0;
382         int yMin = 0;
383         int yMax = 13*font->size/256;
384         int xMax = 9*font->size*len/256;
385
386         ret[0].x = xMin;
387         ret[0].y = -yMin;
388         ret[1].x = xMin;
389         ret[1].y = -yMax;
390         ret[2].x = xMax;
391         ret[2].y = -yMax;
392         ret[3].x = xMax;
393         ret[3].y = -yMin;
394 }
395
396 static void overlay_disable(struct graphics_priv *gra, int disable)
397 {
398         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_disable, disable);
399 }
400
401 static void overlay_resize(struct graphics_priv *gra, struct point *pnt, int w, int h, int alpha, int wraparound)
402 {
403         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_resize, pnt ? pnt->x:0 , pnt ? pnt->y:0, w, h, alpha, wraparound);
404 }
405
406 static int
407 set_attr(struct graphics_priv *gra, struct attr *attr)
408 {
409         switch (attr->type) {
410         case attr_use_camera:
411                 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_SetCamera, attr->u.num);
412                 return 1;
413         default:
414                 return 0;
415         }
416 }
417
418 static struct graphics_methods graphics_methods = {
419         graphics_destroy,
420         draw_mode,
421         draw_lines,
422         draw_polygon,
423         draw_rectangle,
424         draw_circle,
425         draw_text,
426         draw_image,
427         draw_image_warp,
428         draw_restore,
429         draw_drag,
430         font_new,
431         gc_new,
432         background_gc,
433         overlay_new,
434         image_new,
435         get_data,
436         image_free,
437         get_text_bbox,
438         overlay_disable,
439         overlay_resize,
440         set_attr,
441 };
442
443 static void
444 resize_callback(struct graphics_priv *gra, int w, int h)
445 {
446         dbg(0,"w=%d h=%d ok\n",w,h);
447          callback_list_call_attr_2(gra->cbl, attr_resize, (void *)w, (void *)h);
448 }
449
450 static void
451 motion_callback(struct graphics_priv *gra, int x, int y)
452 {
453         struct point p;
454         p.x=x;
455         p.y=y;
456         callback_list_call_attr_1(gra->cbl, attr_motion, (void *)&p);
457 }
458
459 static void
460 keypress_callback(struct graphics_priv *gra, char *s)
461 {
462         dbg(0,"enter %s\n",s);
463         callback_list_call_attr_1(gra->cbl, attr_keypress, s);
464 }
465
466 static void
467 button_callback(struct graphics_priv *gra, int pressed, int button, int x, int y)
468 {
469         struct point p;
470         p.x=x;
471         p.y=y;
472         callback_list_call_attr_3(gra->cbl, attr_button, (void *)pressed, (void *)button, (void *)&p);
473 }
474
475
476 static int
477 set_activity(jobject graphics)
478 {
479         jclass ActivityClass;
480         jmethodID cid;
481
482         ActivityClass = (*jnienv)->GetObjectClass(jnienv, android_activity);
483         dbg(0,"at 5\n");
484         if (ActivityClass == NULL) {
485                 dbg(0,"no activity class found\n");
486                 return 0;
487         }
488         dbg(0,"at 6\n");
489         cid = (*jnienv)->GetMethodID(jnienv, ActivityClass, "setContentView", "(Landroid/view/View;)V");
490         if (cid == NULL) {
491                 dbg(0,"no setContentView method found\n");
492                 return 0;
493         }
494         dbg(0,"at 7\n");
495         (*jnienv)->CallVoidMethod(jnienv, android_activity, cid, graphics);
496         dbg(0,"at 8\n");
497         return 1;
498 }
499
500 static int
501 graphics_android_init(struct graphics_priv *ret, struct graphics_priv *parent, struct point *pnt, int w, int h, int alpha, int wraparound, int use_camera)
502 {
503         struct callback *cb;
504         jmethodID cid, Context_getPackageName;
505
506         dbg(0,"at 2 jnienv=%p\n",jnienv);
507         if (!find_class_global("android/graphics/Paint", &ret->PaintClass))
508                 return 0;
509         if (!find_method(ret->PaintClass, "<init>", "(I)V", &ret->Paint_init))
510                 return 0;
511         if (!find_method(ret->PaintClass, "setARGB", "(IIII)V", &ret->Paint_setARGB))
512                 return 0;
513         if (!find_method(ret->PaintClass, "setStrokeWidth", "(F)V", &ret->Paint_setStrokeWidth))
514                 return 0;
515
516         if (!find_class_global("android/graphics/BitmapFactory", &ret->BitmapFactoryClass))
517                 return 0;
518         if (!find_static_method(ret->BitmapFactoryClass, "decodeFile", "(Ljava/lang/String;)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeFile))
519                 return 0;
520         if (!find_static_method(ret->BitmapFactoryClass, "decodeResource", "(Landroid/content/res/Resources;I)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeResource))
521                 return 0;
522
523         if (!find_class_global("android/graphics/Bitmap", &ret->BitmapClass))
524                 return 0;
525         if (!find_method(ret->BitmapClass, "getHeight", "()I", &ret->Bitmap_getHeight))
526                 return 0;
527         if (!find_method(ret->BitmapClass, "getWidth", "()I", &ret->Bitmap_getWidth))
528                 return 0;
529
530         if (!find_class_global("android/content/Context", &ret->ContextClass))
531                 return 0;
532         if (!find_method(ret->ContextClass, "getResources", "()Landroid/content/res/Resources;", &ret->Context_getResources))
533                 return 0;
534         
535
536         ret->Resources=(*jnienv)->CallObjectMethod(jnienv, android_activity, ret->Context_getResources);
537         if (ret->Resources)
538                 (*jnienv)->NewGlobalRef(jnienv, ret->Resources);
539         if (!find_class_global("android/content/res/Resources", &ret->ResourcesClass))
540                 return 0;
541         if (!find_method(ret->ResourcesClass, "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", &ret->Resources_getIdentifier))
542                 return 0;
543
544         if (!find_method(ret->ContextClass, "getPackageName", "()Ljava/lang/String;", &Context_getPackageName))
545                 return 0;
546         ret->packageName=(*jnienv)->CallObjectMethod(jnienv, android_activity, Context_getPackageName);
547         (*jnienv)->NewGlobalRef(jnienv, ret->packageName);
548
549         if (!find_class_global("org/navitproject/navit/NavitGraphics", &ret->NavitGraphicsClass))
550                 return 0;
551         dbg(0,"at 3\n");
552         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "<init>", "(Landroid/app/Activity;Lorg/navitproject/navit/NavitGraphics;IIIIIII)V");
553         if (cid == NULL) {
554                 dbg(0,"no method found\n");
555                 return 0; /* exception thrown */
556         }
557         dbg(0,"at 4 android_activity=%p\n",android_activity);
558         ret->NavitGraphics=(*jnienv)->NewObject(jnienv, ret->NavitGraphicsClass, cid, android_activity, parent ? parent->NavitGraphics : NULL, pnt ? pnt->x:0 , pnt ? pnt->y:0, w, h, alpha, wraparound, use_camera);
559         dbg(0,"result=%p\n",ret->NavitGraphics);
560         if (ret->NavitGraphics)
561                 (*jnienv)->NewGlobalRef(jnienv, ret->NavitGraphics);
562         
563
564         /* Create a single global Paint, otherwise android will quickly run out
565          * of global refs.*/
566         /* 0x101 = text kerning (default), antialiasing */
567         ret->Paint=(*jnienv)->NewObject(jnienv, ret->PaintClass, ret->Paint_init, 0x101);
568
569         dbg(0,"result=%p\n",ret->Paint);
570         if (ret->Paint)
571                 (*jnienv)->NewGlobalRef(jnienv, ret->Paint);
572
573         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setSizeChangedCallback", "(I)V");
574         if (cid == NULL) {
575                 dbg(0,"no SetResizeCallback method found\n");
576                 return 0; /* exception thrown */
577         }
578         cb=callback_new_1(callback_cast(resize_callback), ret);
579         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
580
581         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setButtonCallback", "(I)V");
582         if (cid == NULL) {
583                 dbg(0,"no SetButtonCallback method found\n");
584                 return 0; /* exception thrown */
585         }
586         cb=callback_new_1(callback_cast(button_callback), ret);
587         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
588
589         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setMotionCallback", "(I)V");
590         if (cid == NULL) {
591                 dbg(0,"no SetMotionCallback method found\n");
592                 return 0; /* exception thrown */
593         }
594         cb=callback_new_1(callback_cast(motion_callback), ret);
595         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
596
597         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setKeypressCallback", "(I)V");
598         if (cid == NULL) {
599                 dbg(0,"no SetKeypressCallback method found\n");
600                 return 0; /* exception thrown */
601         }
602         cb=callback_new_1(callback_cast(keypress_callback), ret);
603         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
604
605         if (!find_method(ret->NavitGraphicsClass, "draw_polyline", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polyline))
606                 return 0;
607         if (!find_method(ret->NavitGraphicsClass, "draw_polygon", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polygon))
608                 return 0;
609         if (!find_method(ret->NavitGraphicsClass, "draw_rectangle", "(Landroid/graphics/Paint;IIII)V", &ret->NavitGraphics_draw_rectangle))
610                 return 0;
611         if (!find_method(ret->NavitGraphicsClass, "draw_circle", "(Landroid/graphics/Paint;III)V", &ret->NavitGraphics_draw_circle))
612                 return 0;
613         if (!find_method(ret->NavitGraphicsClass, "draw_text", "(Landroid/graphics/Paint;IILjava/lang/String;III)V", &ret->NavitGraphics_draw_text))
614                 return 0;
615         if (!find_method(ret->NavitGraphicsClass, "draw_image", "(Landroid/graphics/Paint;IILandroid/graphics/Bitmap;)V", &ret->NavitGraphics_draw_image))
616                 return 0;
617         if (!find_method(ret->NavitGraphicsClass, "draw_mode", "(I)V", &ret->NavitGraphics_draw_mode))
618                 return 0;
619         if (!find_method(ret->NavitGraphicsClass, "draw_drag", "(II)V", &ret->NavitGraphics_draw_drag))
620                 return 0;
621         if (!find_method(ret->NavitGraphicsClass, "overlay_disable", "(I)V", &ret->NavitGraphics_overlay_disable))
622                 return 0;
623         if (!find_method(ret->NavitGraphicsClass, "overlay_resize", "(IIIIII)V", &ret->NavitGraphics_overlay_resize))
624                 return 0;
625         if (!find_method(ret->NavitGraphicsClass, "SetCamera", "(I)V", &ret->NavitGraphics_SetCamera))
626                 return 0;
627 #if 0
628         set_activity(ret->NavitGraphics);
629 #endif
630         return 1;
631 }
632
633 static int
634 graphics_android_fullscreen(struct window *win, int on)
635 {
636         return 1;
637 }
638
639 static jclass NavitClass;
640 static jmethodID Navit_disableSuspend, Navit_exit;
641
642 static void
643 graphics_android_disable_suspend(struct window *win)
644 {
645         dbg(1,"enter\n");
646         (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_disableSuspend);
647 }
648
649
650
651 static struct graphics_priv *
652 graphics_android_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
653 {
654         struct graphics_priv *ret;
655         struct attr *attr;
656         int use_camera=0;
657         if (!event_request_system("android","graphics_android"))
658                 return NULL;
659         ret=g_new0(struct graphics_priv, 1);
660
661         ret->cbl=cbl;
662         *meth=graphics_methods;
663         ret->win.priv=ret;
664         ret->win.fullscreen=graphics_android_fullscreen;
665         ret->win.disable_suspend=graphics_android_disable_suspend;
666         if ((attr=attr_search(attrs, NULL, attr_use_camera))) {
667                 use_camera=attr->u.num;
668         }
669         image_cache_hash = g_hash_table_new(g_str_hash, g_str_equal);
670         if (graphics_android_init(ret, NULL, NULL, 0, 0, 0, 0, use_camera)) {
671                 dbg(0,"returning %p\n",ret);
672                 return ret;
673         } else {
674                 g_free(ret);
675                 return NULL;
676         }
677 }
678
679 static struct graphics_priv *
680 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
681 {
682         struct graphics_priv *ret=g_new0(struct graphics_priv, 1);
683         *meth=graphics_methods;
684         if (graphics_android_init(ret, gr, p, w, h, alpha, wraparound, 0)) {
685                 dbg(0,"returning %p\n",ret);
686                 return ret;
687         } else {
688                 g_free(ret);
689                 return NULL;
690         }
691 }
692
693
694 static void
695 event_android_main_loop_run(void)
696 {
697         dbg(0,"enter\n");
698 }
699
700 static void event_android_main_loop_quit(void)
701 {
702         dbg(0,"enter\n");
703         (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_exit);
704 }
705
706
707 static jclass NavitTimeoutClass;
708 static jmethodID NavitTimeout_init;
709 static jmethodID NavitTimeout_remove;
710
711 static jclass NavitIdleClass;
712 static jmethodID NavitIdle_init;
713 static jmethodID NavitIdle_remove;
714
715 static jclass NavitWatchClass;
716 static jmethodID NavitWatch_init;
717 static jmethodID NavitWatch_remove;
718
719
720 static void do_poll(JNIEnv *env, int fd, int cond)
721 {
722         struct pollfd pfd;
723         pfd.fd=fd;
724         dbg(1,"%p poll called for %d %d\n", fd, cond);
725         switch ((enum event_watch_cond)cond) {
726         case event_watch_cond_read:
727                 pfd.events=POLLIN;
728                 break;
729         case event_watch_cond_write:
730                 pfd.events=POLLOUT;
731                 break;
732         case event_watch_cond_except:
733                 pfd.events=POLLERR;
734                 break;
735         default:
736                 pfd.events=0;
737         }
738         pfd.revents=0;
739         poll(&pfd, 1, -1);
740 }
741
742 static struct event_watch *
743 event_android_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
744 {
745         jobject ret;
746         ret=(*jnienv)->NewObject(jnienv, NavitWatchClass, NavitWatch_init, (int)do_poll, (int) h, (int) cond, (int)cb);
747         dbg(0,"result for %p,%d,%p=%p\n",h,cond,cb,ret);
748         if (ret)
749                 (*jnienv)->NewGlobalRef(jnienv, ret);
750         return (struct event_watch *)ret;
751 }
752
753 static void
754 event_android_remove_watch(struct event_watch *ev)
755 {
756         dbg(0,"enter %p\n",ev);
757         if (ev) {
758                 jobject obj=(jobject )ev;
759                 (*jnienv)->CallVoidMethod(jnienv, obj, NavitWatch_remove);
760                 (*jnienv)->DeleteGlobalRef(jnienv, obj);
761         }
762 }
763
764 static struct event_timeout *
765 event_android_add_timeout(int timeout, int multi, struct callback *cb)
766 {
767         jobject ret;
768         ret=(*jnienv)->NewObject(jnienv, NavitTimeoutClass, NavitTimeout_init, timeout, multi, (int)cb);
769         dbg(1,"result for %d,%d,%p=%p\n",timeout,multi,cb,ret);
770         if (ret)
771                 (*jnienv)->NewGlobalRef(jnienv, ret);
772         return (struct event_timeout *)ret;
773 }
774
775 static void
776 event_android_remove_timeout(struct event_timeout *to)
777 {
778         dbg(1,"enter %p\n",to);
779         if (to) {
780                 jobject obj=(jobject )to;
781                 (*jnienv)->CallVoidMethod(jnienv, obj, NavitTimeout_remove);
782                 (*jnienv)->DeleteGlobalRef(jnienv, obj);
783         }
784 }
785
786
787 static struct event_idle *
788 event_android_add_idle(int priority, struct callback *cb)
789 {
790 #if 0
791         jobject ret;
792         dbg(1,"enter\n");
793         ret=(*jnienv)->NewObject(jnienv, NavitIdleClass, NavitIdle_init, (int)cb);
794         dbg(1,"result for %p=%p\n",cb,ret);
795         if (ret)
796                 (*jnienv)->NewGlobalRef(jnienv, ret);
797         return (struct event_idle *)ret;
798 #endif
799         return (struct event_idle *)event_android_add_timeout(1, 1, cb);
800 }
801
802 static void
803 event_android_remove_idle(struct event_idle *ev)
804 {
805 #if 0
806         dbg(1,"enter %p\n",ev);
807         if (ev) {
808                 jobject obj=(jobject )ev;
809                 (*jnienv)->CallVoidMethod(jnienv, obj, NavitIdle_remove);
810                 (*jnienv)->DeleteGlobalRef(jnienv, obj);
811         }
812 #endif
813         event_android_remove_timeout((struct event_timeout *)ev);
814 }
815
816 static void
817 event_android_call_callback(struct callback_list *cb)
818 {
819         dbg(0,"enter\n");
820 }
821
822 static struct event_methods event_android_methods = {
823         event_android_main_loop_run,
824         event_android_main_loop_quit,
825         event_android_add_watch,
826         event_android_remove_watch,
827         event_android_add_timeout,
828         event_android_remove_timeout,
829         event_android_add_idle,
830         event_android_remove_idle,
831         event_android_call_callback,
832 };
833
834 static struct event_priv *
835 event_android_new(struct event_methods *meth)
836 {
837         dbg(0,"enter\n");
838         if (!find_class_global("org/navitproject/navit/NavitTimeout", &NavitTimeoutClass))
839                 return NULL;
840         NavitTimeout_init = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "<init>", "(IZI)V");
841         if (NavitTimeout_init == NULL) 
842                 return NULL;
843         NavitTimeout_remove = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "remove", "()V");
844         if (NavitTimeout_remove == NULL) 
845                 return NULL;
846 #if 0
847         if (!find_class_global("org/navitproject/navit/NavitIdle", &NavitIdleClass))
848                 return NULL;
849         NavitIdle_init = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "<init>", "(I)V");
850         if (NavitIdle_init == NULL) 
851                 return NULL;
852         NavitIdle_remove = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "remove", "()V");
853         if (NavitIdle_remove == NULL) 
854                 return NULL;
855 #endif
856
857         if (!find_class_global("org/navitproject/navit/NavitWatch", &NavitWatchClass))
858                 return NULL;
859         NavitWatch_init = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "<init>", "(IIII)V");
860         if (NavitWatch_init == NULL) 
861                 return NULL;
862         NavitWatch_remove = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "remove", "()V");
863         if (NavitWatch_remove == NULL) 
864                 return NULL;
865
866         if (!find_class_global("org/navitproject/navit/Navit", &NavitClass))
867                 return NULL;
868         Navit_disableSuspend = (*jnienv)->GetMethodID(jnienv, NavitClass, "disableSuspend", "()V");
869         if (Navit_disableSuspend == NULL) 
870                 return NULL;
871         Navit_exit = (*jnienv)->GetMethodID(jnienv, NavitClass, "exit", "()V");
872         if (Navit_exit == NULL) 
873                 return NULL;
874         dbg(0,"ok\n");
875         *meth=event_android_methods;
876         return NULL;
877 }
878
879
880 void
881 plugin_init(void)
882 {
883         dbg(0,"enter\n");
884         plugin_register_graphics_type("android", graphics_android_new);
885         plugin_register_event_type("android", event_android_new);
886 }