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