/[zanavi_public1]/navit/navit/graphics/android/graphics_android.c
ZANavi

Contents of /navit/navit/graphics/android/graphics_android.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show annotations) (download)
Mon Apr 9 21:27:36 2012 UTC (12 years ago) by zoff99
File MIME type: text/plain
File size: 35220 byte(s)
lots of new stuff, tranlsations, bug fixes ...
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
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 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <unistd.h>
40 #include <glib.h>
41 #include "config.h"
42 #include "window.h"
43 #include "point.h"
44 #include "graphics.h"
45 #include "color.h"
46 #include "plugin.h"
47 #include "event.h"
48 #include "debug.h"
49 #include "callback.h"
50 #include "android.h"
51
52 int dummy;
53
54 struct graphics_priv
55 {
56 jclass NavitGraphicsClass;
57 jmethodID NavitGraphics_draw_polyline, NavitGraphics_draw_polyline2, NavitGraphics_draw_polyline3, NavitGraphics_draw_polyline4, NavitGraphics_draw_polyline_dashed, NavitGraphics_set_dashes, NavitGraphics_draw_polygon, NavitGraphics_draw_polygon2, NavitGraphics_draw_rectangle, NavitGraphics_draw_circle, NavitGraphics_draw_text, NavitGraphics_draw_image,
58 NavitGraphics_draw_bigmap, NavitGraphics_send_osd_values, NavitGraphics_draw_mode, NavitGraphics_draw_drag, NavitGraphics_overlay_disable, NavitGraphics_overlay_resize, NavitGraphics_SetCamera, NavitGraphicsClass_rotate_and_scale_bitmap;
59
60 jclass PaintClass;
61 jmethodID Paint_init, Paint_setStrokeWidth, Paint_setARGB;
62
63 jobject NavitGraphics;
64 jobject Paint;
65
66 jclass BitmapFactoryClass;
67 jmethodID BitmapFactory_decodeFile, BitmapFactory_decodeResource;
68
69 jclass BitmapClass;
70 jmethodID Bitmap_getHeight, Bitmap_getWidth;
71
72 jclass ContextClass;
73 jmethodID Context_getResources;
74
75 jclass ResourcesClass;
76 jobject Resources;
77 jmethodID Resources_getIdentifier;
78
79 struct callback_list *cbl;
80 struct window win;
81 };
82
83 struct graphics_font_priv
84 {
85 int size;
86 };
87
88 struct graphics_gc_priv
89 {
90 struct graphics_priv *gra;
91 int linewidth;
92 enum draw_mode_num mode;
93 int a, r, g, b;
94 };
95
96 struct graphics_image_priv
97 {
98 jobject Bitmap;
99 int width;
100 int height;
101 struct point hot;
102 };
103
104 static GHashTable *image_cache_hash = NULL;
105
106 static int find_class_global(char *name, jclass *ret)
107 {
108 //DBG dbg(0,"EEnter\n");
109 *ret = (*jnienv)->FindClass(jnienv, name);
110 if (!*ret)
111 {
112 //DBG dbg(0, "Failed to get Class %s\n", name);
113 return 0;
114 }
115 *ret = (*jnienv)->NewGlobalRef(jnienv, *ret);
116 return 1;
117 }
118
119 static int find_method(jclass class, char *name, char *args, jmethodID *ret)
120 {
121 //DBG dbg(0,"EEnter\n");
122 *ret = (*jnienv)->GetMethodID(jnienv, class, name, args);
123 if (*ret == NULL)
124 {
125 //DBG dbg(0, "Failed to get Method %s with signature %s\n", name, args);
126 return 0;
127 }
128 return 1;
129 }
130
131 static int find_static_method(jclass class, char *name, char *args, jmethodID *ret)
132 {
133 //DBG dbg(0,"EEnter\n");
134 *ret = (*jnienv)->GetStaticMethodID(jnienv, class, name, args);
135 if (*ret == NULL)
136 {
137 //DBG dbg(0, "Failed to get static Method %s with signature %s\n", name, args);
138 return 0;
139 }
140 return 1;
141 }
142
143 static void graphics_destroy(struct graphics_priv *gr)
144 {
145 }
146
147 static void font_destroy(struct graphics_font_priv *font)
148 {
149 g_free(font);
150 }
151
152 static struct graphics_font_methods font_methods =
153 { font_destroy };
154
155 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *font, int size, int flags)
156 {
157 struct graphics_font_priv *ret=g_new0(struct graphics_font_priv, 1);
158 *meth = font_methods;
159
160 ret->size = size;
161 return ret;
162 }
163
164 static void gc_destroy(struct graphics_gc_priv *gc)
165 {
166 //DBG dbg(0,"EEnter\n");
167
168 g_free(gc);
169 }
170
171 static void gc_set_linewidth(struct graphics_gc_priv *gc, int w)
172 {
173 gc->linewidth = w;
174 }
175
176 static void gc_set_dashes(struct graphics_priv *gra, struct graphics_gc_priv *gc, int w, int offset, int dash_list[], int order)
177 {
178 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_set_dashes, gc->gra->Paint, dash_list[0], order);
179 }
180
181 static void gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
182 {
183 gc->r = c->r >> 8;
184 gc->g = c->g >> 8;
185 gc->b = c->b >> 8;
186 gc->a = c->a >> 8;
187 }
188
189 static void gc_set_background(struct graphics_gc_priv *gc, struct color *c)
190 {
191 }
192
193 static struct graphics_gc_methods gc_methods =
194 { gc_destroy, gc_set_linewidth, gc_set_dashes, gc_set_foreground, gc_set_background };
195
196 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
197 {
198 ////DBG dbg(0,"EEnter\n");
199
200 struct graphics_gc_priv *ret=g_new0(struct graphics_gc_priv, 1);
201 *meth = gc_methods;
202
203 ret->gra = gr;
204 ret->a = ret->r = ret->g = ret->b = 255;
205 ret->linewidth = 1;
206 return ret;
207 }
208
209 static void image_destroy(struct graphics_image_priv *img)
210 {
211 // unused?
212 }
213
214 static struct graphics_image_methods image_methods =
215 { image_destroy };
216
217 static struct graphics_image_priv *
218 image_new(struct graphics_priv *gra, struct graphics_image_methods *meth, char *path, int *w, int *h, struct point *hot, int rotation)
219 {
220 //DBG dbg(0,"EEnter\n");
221
222 struct graphics_image_priv* ret = NULL;
223
224 if (!g_hash_table_lookup_extended(image_cache_hash, path, NULL, (gpointer) & ret))
225 {
226 ret=g_new0(struct graphics_image_priv, 1);
227 jstring string;
228 int id;
229
230 // // dbg(1, "enter %s\n", path);
231 if (!strncmp(path, "res/drawable/", 13))
232 {
233 jstring a = (*jnienv)->NewStringUTF(jnienv, "drawable");
234 jstring b = (*jnienv)->NewStringUTF(jnienv, "com.zoffcc.applications.zanavi");
235 char *path_noext = g_strdup(path + 13);
236 char *pos = strrchr(path_noext, '.');
237 if (pos)
238 *pos = '\0';
239 //DBG dbg(0, "path_noext=%s\n", path_noext);
240 string = (*jnienv)->NewStringUTF(jnienv, path_noext);
241 g_free(path_noext);
242 id = (*jnienv)->CallIntMethod(jnienv, gra->Resources, gra->Resources_getIdentifier, string, a, b);
243 //DBG dbg(0, "id=%d\n", id);
244 //DBG dbg(0,"JNI\n");
245 if (id)
246 {
247 ret->Bitmap = (*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeResource, gra->Resources, id);
248 }
249 (*jnienv)->DeleteLocalRef(jnienv, b);
250 (*jnienv)->DeleteLocalRef(jnienv, a);
251 }
252 else
253 {
254 string = (*jnienv)->NewStringUTF(jnienv, path);
255 //DBG dbg(0,"JNI\n");
256 ret->Bitmap = (*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeFile, string);
257 // there should be a check here, if we really want any rotation/scaling
258 // otherwise the call is overkill
259 //DBG dbg(0,"JNI\n");
260 ret->Bitmap = (*jnienv)->CallStaticObjectMethod(jnienv, gra->NavitGraphicsClass, gra->NavitGraphicsClass_rotate_and_scale_bitmap, ret->Bitmap, *w, *h, rotation);
261 }
262 //// dbg(1, "result=%p\n", ret->Bitmap);
263 if (ret->Bitmap)
264 {
265 //DBG dbg(0,"JNI\n");
266 ret->Bitmap = (*jnienv)->NewGlobalRef(jnienv, ret->Bitmap);
267 // ICS (*jnienv)->DeleteLocalRef(jnienv, ret->Bitmap);
268 //DBG dbg(0,"JNI\n");
269 ret->width = (*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getWidth);
270 //DBG dbg(0,"JNI\n");
271 ret->height = (*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getHeight);
272 //// dbg(1, "w=%d h=%d for %s\n", ret->width, ret->height, path);
273 ret->hot.x = ret->width / 2;
274 ret->hot.y = ret->height / 2;
275 }
276 else
277 {
278 g_free(ret);
279 ret = NULL;
280 //DBG dbg(0, "Failed to open %s\n", path);
281 }
282 //DBG dbg(0,"JNI\n");
283 (*jnienv)->DeleteLocalRef(jnienv, string);
284 //DBG dbg(0,"JNI\n");
285 g_hash_table_insert(image_cache_hash, g_strdup(path), (gpointer) ret);
286 }
287 if (ret)
288 {
289 *w = ret->width;
290 *h = ret->height;
291 if (hot)
292 {
293 *hot = ret->hot;
294 }
295 }
296
297 return ret;
298 }
299
300 static void initPaint(struct graphics_priv *gra, struct graphics_gc_priv *gc)
301 {
302 //DBG dbg(0,"EEnter\n");
303
304 float wf = gc->linewidth;
305 (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setStrokeWidth, wf);
306 (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setARGB, gc->a, gc->r, gc->g, gc->b);
307 }
308
309 static void draw_lines(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
310 {
311 //DBG dbg(0,"EEnter\n");
312 jint pc[count * 2];
313 int i;
314 jintArray points;
315 if (count <= 0)
316 return;
317 points = (*jnienv)->NewIntArray(jnienv, count * 2);
318 for (i = 0; i < count; i++)
319 {
320 pc[i * 2] = p[i].x;
321 pc[i * 2 + 1] = p[i].y;
322 }
323 initPaint(gra, gc);
324 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
325 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline, gc->gra->Paint, points);
326 (*jnienv)->DeleteLocalRef(jnienv, points);
327 }
328
329 static void draw_lines3(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count, int order, int width)
330 {
331 //DBG dbg(0,"EEnter\n");
332 jint pc[count * 2];
333 int i;
334 jintArray points;
335 if (count <= 0)
336 return;
337 points = (*jnienv)->NewIntArray(jnienv, count * 2);
338 for (i = 0; i < count; i++)
339 {
340 pc[i * 2] = p[i].x;
341 pc[i * 2 + 1] = p[i].y;
342 }
343 initPaint(gra, gc);
344 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
345 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline3, gc->gra->Paint, points, order, width);
346 (*jnienv)->DeleteLocalRef(jnienv, points);
347 }
348
349 static void draw_lines4(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count, int order, int width, int type)
350 {
351 //DBG dbg(0,"EEnter\n");
352
353 // draw tunnel-street or bridge-street
354 // type:1 -> tunnel
355 // type:2 -> bridge
356
357 jint pc[count * 2];
358 int i;
359 jintArray points;
360 if (count <= 0)
361 {
362 return;
363 }
364 points = (*jnienv)->NewIntArray(jnienv, count * 2);
365 for (i = 0; i < count; i++)
366 {
367 pc[i * 2] = p[i].x;
368 pc[i * 2 + 1] = p[i].y;
369 }
370 initPaint(gra, gc);
371 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
372 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline4, gc->gra->Paint, points, order, width, type);
373 (*jnienv)->DeleteLocalRef(jnienv, points);
374 }
375
376 static void draw_lines2(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count, int order, int oneway)
377 {
378 //DBG dbg(0,"EEnter\n");
379 jint pc[count * 2];
380 int i;
381 jintArray points;
382 if (count <= 0)
383 return;
384 points = (*jnienv)->NewIntArray(jnienv, count * 2);
385 for (i = 0; i < count; i++)
386 {
387 pc[i * 2] = p[i].x;
388 pc[i * 2 + 1] = p[i].y;
389 }
390 initPaint(gra, gc);
391 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
392 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline2, gc->gra->Paint, points, order, oneway);
393 (*jnienv)->DeleteLocalRef(jnienv, points);
394 }
395
396 static void draw_lines_dashed(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count, int order, int oneway)
397 {
398 jint pc[count * 2];
399 int i;
400 jintArray points;
401 if (count <= 0)
402 return;
403 points = (*jnienv)->NewIntArray(jnienv, count * 2);
404 for (i = 0; i < count; i++)
405 {
406 pc[i * 2] = p[i].x;
407 pc[i * 2 + 1] = p[i].y;
408 }
409 initPaint(gra, gc);
410 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
411 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline_dashed, gc->gra->Paint, points, order, oneway);
412 (*jnienv)->DeleteLocalRef(jnienv, points);
413 }
414
415 static void draw_polygon(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
416 {
417 jint pc[count * 2];
418 int i;
419 jintArray points;
420 if (count <= 0)
421 return;
422 points = (*jnienv)->NewIntArray(jnienv, count * 2);
423 for (i = 0; i < count; i++)
424 {
425 pc[i * 2] = p[i].x;
426 pc[i * 2 + 1] = p[i].y;
427 }
428 initPaint(gra, gc);
429 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
430 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polygon, gc->gra->Paint, points);
431 (*jnienv)->DeleteLocalRef(jnienv, points);
432 }
433
434 static void draw_polygon2(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count, int order, int oneway)
435 {
436 jint pc[count * 2];
437 int i;
438 jintArray points;
439 if (count <= 0)
440 return;
441 points = (*jnienv)->NewIntArray(jnienv, count * 2);
442 for (i = 0; i < count; i++)
443 {
444 pc[i * 2] = p[i].x;
445 pc[i * 2 + 1] = p[i].y;
446 }
447 initPaint(gra, gc);
448 (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count * 2, pc);
449 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polygon2, gc->gra->Paint, points, order, oneway);
450 (*jnienv)->DeleteLocalRef(jnienv, points);
451 }
452
453 static void draw_rectangle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int w, int h)
454 {
455 initPaint(gra, gc);
456 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_rectangle, gc->gra->Paint, p->x, p->y, w, h);
457 }
458
459 static void draw_circle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int r)
460 {
461 initPaint(gra, gc);
462 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_circle, gc->gra->Paint, p->x, p->y, r);
463 }
464
465 static void 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)
466 {
467 //// dbg(1, "enter %s\n", text);
468 initPaint(gra, fg);
469 jstring string = (*jnienv)->NewStringUTF(jnienv, text);
470 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_text, fg->gra->Paint, p->x, p->y, string, font->size, dx, dy);
471 (*jnienv)->DeleteLocalRef(jnienv, string);
472 }
473
474 static void draw_image(struct graphics_priv *gra, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
475 {
476 //DBG dbg(0,"EEnter\n");
477
478 //// dbg(1, "enter %p\n", img);
479 initPaint(gra, fg);
480 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_image, fg->gra->Paint, p->x, p->y, img->Bitmap);
481
482 }
483
484 static void draw_bigmap(struct graphics_priv *gra, struct graphics_gc_priv *fg, int yaw, int order, float clat, float clng, int x, int y, int scx, int scy, int px, int py, int valid)
485 {
486 //DBG dbg(0,"EEnter\n");
487
488 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_bigmap, yaw, order, clat, clng, x, y, scx, scy, px, py, valid);
489
490 //DBG dbg(0,"leave\n");
491 }
492
493 static void send_osd_values(struct graphics_priv *gra, struct graphics_gc_priv *fg, char *id, char *text1, char *text2, char *text3, int i1, int i2, int i3, int i4, float f1, float f2, float f3)
494 {
495 //DBG dbg(0,"EEnter\n");
496
497 jstring string1 = (*jnienv)->NewStringUTF(jnienv, id);
498 jstring string2 = (*jnienv)->NewStringUTF(jnienv, text1);
499 jstring string3 = (*jnienv)->NewStringUTF(jnienv, text2);
500 jstring string4 = (*jnienv)->NewStringUTF(jnienv, text3);
501 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_send_osd_values, string1, string2, string3, string4, i1, i2, i3, i4, f1, f2, f3);
502 (*jnienv)->DeleteLocalRef(jnienv, string1);
503 (*jnienv)->DeleteLocalRef(jnienv, string2);
504 (*jnienv)->DeleteLocalRef(jnienv, string3);
505 (*jnienv)->DeleteLocalRef(jnienv, string4);
506 }
507
508 static void draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
509 {
510 }
511
512 static void draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
513 {
514 }
515
516 static void draw_drag(struct graphics_priv *gra, struct point *p)
517 {
518 //DBG dbg(0,"EEnter\n");
519
520 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_drag, p ? p->x : 0, p ? p->y : 0);
521 }
522
523 static void background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
524 {
525 }
526
527 static void draw_mode(struct graphics_priv *gra, enum draw_mode_num mode)
528 {
529 //DBG dbg(0,"EEnter\n");
530
531 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_mode, (int) mode);
532 }
533
534 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);
535
536 static void *
537 get_data(struct graphics_priv *this, const char *type)
538 {
539 //DBG dbg(0,"EEnter\n");
540
541 if (strcmp(type, "window"))
542 return NULL;
543 return &this->win;
544 }
545
546 static void image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
547 {
548 }
549
550 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)
551 {
552 ////DBG dbg(0,"EEnter\n");
553
554 int len = g_utf8_strlen(text, -1);
555 int xMin = 0;
556 int yMin = 0;
557 int yMax = 13 * font->size / 256;
558 int xMax = 9 * font->size * len / 256;
559
560 ret[0].x = xMin;
561 ret[0].y = -yMin;
562 ret[1].x = xMin;
563 ret[1].y = -yMax;
564 ret[2].x = xMax;
565 ret[2].y = -yMax;
566 ret[3].x = xMax;
567 ret[3].y = -yMin;
568 }
569
570 static void overlay_disable(struct graphics_priv *gra, int disable)
571 {
572 //DBG dbg(0,"EEnter\n");
573 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_disable, disable);
574 }
575
576 static void overlay_resize(struct graphics_priv *gra, struct point *pnt, int w, int h, int alpha, int wraparound)
577 {
578 //DBG dbg(0,"EEnter\n");
579 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_resize, pnt ? pnt->x : 0, pnt ? pnt->y : 0, w, h, alpha, wraparound);
580 }
581
582 static int set_attr(struct graphics_priv *gra, struct attr *attr)
583 {
584 //DBG dbg(0,"EEnter\n");
585 switch (attr->type)
586 {
587 case attr_use_camera:
588 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_SetCamera, attr->u.num);
589 return 1;
590 default:
591 return 0;
592 }
593 }
594
595 static struct graphics_methods graphics_methods =
596 { graphics_destroy, draw_mode, draw_lines, draw_lines2, draw_lines3, draw_lines4, draw_lines_dashed, draw_polygon, draw_polygon2, draw_rectangle, draw_circle, draw_text, draw_image, draw_bigmap, send_osd_values, draw_image_warp, draw_restore, draw_drag, font_new, gc_new, background_gc, overlay_new, image_new, get_data,
597 image_free, get_text_bbox, overlay_disable, overlay_resize, set_attr, };
598
599 static void resize_callback(struct graphics_priv *gra, int w, int h)
600 {
601 //DBG dbg(0,"EEnter\n");
602 // //DBG dbg(0,"w=%d h=%d ok\n",w,h);
603 callback_list_call_attr_2(gra->cbl, attr_resize, (void *) w, (void *) h);
604 }
605
606 static void motion_callback(struct graphics_priv *gra, int x, int y)
607 {
608 //DBG dbg(0,"EEnter\n");
609
610 struct point p;
611 p.x = x;
612 p.y = y;
613 callback_list_call_attr_1(gra->cbl, attr_motion, (void *) &p);
614 }
615
616 static void keypress_callback(struct graphics_priv *gra, char *s)
617 {
618 //DBG dbg(0,"EEnter\n");
619 callback_list_call_attr_1(gra->cbl, attr_keypress, s);
620 }
621
622 static void button_callback(struct graphics_priv *gra, int pressed, int button, int x, int y)
623 {
624 //DBG dbg(0,"EEnter\n");
625
626 struct point p;
627 p.x = x;
628 p.y = y;
629 // //DBG dbg(0,"XXXXXXXYYYYYYYYY\n");
630 callback_list_call_attr_3(gra->cbl, attr_button, (void *) pressed, (void *) button, (void *) &p);
631 }
632
633 static int set_activity(jobject graphics)
634 {
635 //DBG dbg(0,"EEnter\n");
636
637 jclass ActivityClass;
638 jmethodID cid;
639
640 ActivityClass = (*jnienv)->GetObjectClass(jnienv, android_activity);
641 // //DBG dbg(0,"at 5\n");
642 if (ActivityClass == NULL)
643 {
644 //DBG dbg(0, "no activity class found\n");
645 return 0;
646 }
647 // //DBG dbg(0,"at 6\n");
648 cid = (*jnienv)->GetMethodID(jnienv, ActivityClass, "setContentView", "(Landroid/view/View;)V");
649 if (cid == NULL)
650 {
651 //DBG dbg(0, "no setContentView method found\n");
652 return 0;
653 }
654 //DBG dbg(0,"at 7\n");
655 (*jnienv)->CallVoidMethod(jnienv, android_activity, cid, graphics);
656 //DBG dbg(0,"at 8\n");
657 return 1;
658 }
659
660 static int 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)
661 {
662 struct callback *cb;
663 jmethodID cid;
664
665 //DBG dbg(0, "at 2 jnienv=%p\n", jnienv);
666 //DBG dbg(0,"a1\n");
667 if (!find_class_global("android/graphics/Paint", &ret->PaintClass))
668 return 0;
669 //DBG dbg(0,"a2\n");
670 if (!find_method(ret->PaintClass, "<init>", "(I)V", &ret->Paint_init))
671 return 0;
672 //DBG dbg(0,"a3\n");
673 if (!find_method(ret->PaintClass, "setARGB", "(IIII)V", &ret->Paint_setARGB))
674 return 0;
675 //DBG dbg(0,"a4\n");
676 if (!find_method(ret->PaintClass, "setStrokeWidth", "(F)V", &ret->Paint_setStrokeWidth))
677 return 0;
678
679 //DBG dbg(0,"a4.1\n");
680 if (!find_class_global("android/graphics/BitmapFactory", &ret->BitmapFactoryClass))
681 return 0;
682 //DBG dbg(0,"a4.2\n");
683 if (!find_static_method(ret->BitmapFactoryClass, "decodeFile", "(Ljava/lang/String;)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeFile))
684 return 0;
685 //DBG dbg(0,"a4.3\n");
686 if (!find_static_method(ret->BitmapFactoryClass, "decodeResource", "(Landroid/content/res/Resources;I)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeResource))
687 return 0;
688
689 //DBG dbg(0,"a4.4\n");
690 if (!find_class_global("android/graphics/Bitmap", &ret->BitmapClass))
691 return 0;
692 //DBG dbg(0,"a4.5\n");
693 if (!find_method(ret->BitmapClass, "getHeight", "()I", &ret->Bitmap_getHeight))
694 return 0;
695 //DBG dbg(0,"a4.6\n");
696 if (!find_method(ret->BitmapClass, "getWidth", "()I", &ret->Bitmap_getWidth))
697 return 0;
698 //DBG dbg(0,"a4.7\n");
699 if (!find_class_global("android/content/Context", &ret->ContextClass))
700 return 0;
701 //DBG dbg(0,"a4.8\n");
702 if (!find_method(ret->ContextClass, "getResources", "()Landroid/content/res/Resources;", &ret->Context_getResources))
703 return 0;
704 //DBG dbg(0,"a5\n");
705 ret->Resources = (*jnienv)->CallObjectMethod(jnienv, android_activity, ret->Context_getResources);
706 //DBG dbg(0,"a6\n");
707 if (ret->Resources)
708 {
709 ret->Resources = (*jnienv)->NewGlobalRef(jnienv, ret->Resources);
710 }
711 //DBG dbg(0,"a7\n");
712 if (!find_class_global("android/content/res/Resources", &ret->ResourcesClass))
713 return 0;
714 //DBG dbg(0,"a8\n");
715 if (!find_method(ret->ResourcesClass, "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", &ret->Resources_getIdentifier))
716 return 0;
717 //DBG dbg(0,"a9\n");
718 if (!find_class_global("com/zoffcc/applications/zanavi/NavitGraphics", &ret->NavitGraphicsClass))
719 return 0;
720 //DBG dbg(0, "at 3\n");
721 cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "<init>", "(Landroid/app/Activity;Lcom/zoffcc/applications/zanavi/NavitGraphics;IIIIIII)V");
722 if (cid == NULL)
723 {
724 //DBG dbg(0, "no method found\n");
725 return 0; /* exception thrown */
726 }
727 //DBG dbg(0, "at 4 android_activity=%p\n", android_activity);
728 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);
729 //DBG dbg(0, "result=%p\n", ret->NavitGraphics);
730 if (ret->NavitGraphics)
731 {
732 ret->NavitGraphics = (*jnienv)->NewGlobalRef(jnienv, ret->NavitGraphics);
733 }
734
735 /* Create a single global Paint, otherwise android will quickly run out
736 * of global refs.*/
737 /* 0x101 = text kerning (default), antialiasing */
738 ret->Paint = (*jnienv)->NewObject(jnienv, ret->PaintClass, ret->Paint_init, 0x101);
739
740 //DBG dbg(0, "l result=%p\n", ret->Paint);
741 if (ret->Paint)
742 {
743 ret->Paint = (*jnienv)->NewGlobalRef(jnienv, ret->Paint);
744 }
745 //DBG dbg(0, "g result=%p\n", ret->Paint);
746
747 cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setSizeChangedCallback", "(I)V");
748 if (cid == NULL)
749 {
750 //DBG dbg(0, "no SetResizeCallback method found\n");
751 return 0; /* exception thrown */
752 }
753 cb = callback_new_1(callback_cast(resize_callback), ret);
754 (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int) cb);
755
756 cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setButtonCallback", "(I)V");
757 if (cid == NULL)
758 {
759 //DBG dbg(0, "no SetButtonCallback method found\n");
760 return 0; /* exception thrown */
761 }
762 cb = callback_new_1(callback_cast(button_callback), ret);
763 (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int) cb);
764
765 cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setMotionCallback", "(I)V");
766 if (cid == NULL)
767 {
768 //DBG dbg(0, "no SetMotionCallback method found\n");
769 return 0; /* exception thrown */
770 }
771 cb = callback_new_1(callback_cast(motion_callback), ret);
772 (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int) cb);
773
774 // public Bitmap rotate_and_scale_bitmap(Bitmap in, int w, int h, int angle)
775
776 if (!find_static_method(ret->NavitGraphicsClass, "rotate_and_scale_bitmap", "(Landroid/graphics/Bitmap;III)Landroid/graphics/Bitmap;", &ret->NavitGraphicsClass_rotate_and_scale_bitmap))
777 return 0;
778
779 //
780 //cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "rotate_and_scale_bitmap", "(Landroid/graphics/Bitmap;III)Landroid/graphics/Bitmap;");
781 //if (cid == NULL) {
782 // //DBG dbg(0,"no rotate_and_scale_bitmap method found\n");
783 // return 0; /* exception thrown */
784 //}
785
786 cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setKeypressCallback", "(I)V");
787 if (cid == NULL)
788 {
789 //DBG dbg(0, "no SetKeypressCallback method found\n");
790 return 0; /* exception thrown */
791 }
792 cb = callback_new_1(callback_cast(keypress_callback), ret);
793 (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int) cb);
794
795 if (!find_method(ret->NavitGraphicsClass, "draw_polyline", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polyline))
796 return 0;
797 if (!find_method(ret->NavitGraphicsClass, "draw_polyline2", "(Landroid/graphics/Paint;[III)V", &ret->NavitGraphics_draw_polyline2))
798 return 0;
799 if (!find_method(ret->NavitGraphicsClass, "draw_polyline3", "(Landroid/graphics/Paint;[III)V", &ret->NavitGraphics_draw_polyline3))
800 return 0;
801 if (!find_method(ret->NavitGraphicsClass, "draw_polyline4", "(Landroid/graphics/Paint;[IIII)V", &ret->NavitGraphics_draw_polyline4))
802 return 0;
803 if (!find_method(ret->NavitGraphicsClass, "draw_polyline_dashed", "(Landroid/graphics/Paint;[III)V", &ret->NavitGraphics_draw_polyline_dashed))
804 return 0;
805 if (!find_method(ret->NavitGraphicsClass, "set_dashes", "(Landroid/graphics/Paint;II)V", &ret->NavitGraphics_set_dashes))
806 return 0;
807 if (!find_method(ret->NavitGraphicsClass, "draw_polygon", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polygon))
808 return 0;
809 if (!find_method(ret->NavitGraphicsClass, "draw_polygon2", "(Landroid/graphics/Paint;[III)V", &ret->NavitGraphics_draw_polygon2))
810 return 0;
811 if (!find_method(ret->NavitGraphicsClass, "draw_rectangle", "(Landroid/graphics/Paint;IIII)V", &ret->NavitGraphics_draw_rectangle))
812 return 0;
813 if (!find_method(ret->NavitGraphicsClass, "draw_circle", "(Landroid/graphics/Paint;III)V", &ret->NavitGraphics_draw_circle))
814 return 0;
815 if (!find_method(ret->NavitGraphicsClass, "draw_text", "(Landroid/graphics/Paint;IILjava/lang/String;III)V", &ret->NavitGraphics_draw_text))
816 return 0;
817 if (!find_method(ret->NavitGraphicsClass, "draw_image", "(Landroid/graphics/Paint;IILandroid/graphics/Bitmap;)V", &ret->NavitGraphics_draw_image))
818 return 0;
819 if (!find_method(ret->NavitGraphicsClass, "draw_bigmap", "(IIFFIIIIIII)V", &ret->NavitGraphics_draw_bigmap))
820 return 0;
821 if (!find_method(ret->NavitGraphicsClass, "send_osd_values", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIFFF)V", &ret->NavitGraphics_send_osd_values))
822 return 0;
823 if (!find_method(ret->NavitGraphicsClass, "draw_mode", "(I)V", &ret->NavitGraphics_draw_mode))
824 return 0;
825 if (!find_method(ret->NavitGraphicsClass, "draw_drag", "(II)V", &ret->NavitGraphics_draw_drag))
826 return 0;
827 if (!find_method(ret->NavitGraphicsClass, "overlay_disable", "(I)V", &ret->NavitGraphics_overlay_disable))
828 return 0;
829 if (!find_method(ret->NavitGraphicsClass, "overlay_resize", "(IIIIII)V", &ret->NavitGraphics_overlay_resize))
830 return 0;
831 if (!find_method(ret->NavitGraphicsClass, "SetCamera", "(I)V", &ret->NavitGraphics_SetCamera))
832 return 0;
833
834 //DBG dbg(0,"99\n");
835 #if 0
836 set_activity(ret->NavitGraphics);
837 #endif
838 return 1;
839 }
840
841 static int graphics_android_fullscreen(struct window *win, int on)
842 {
843 return 1;
844 }
845
846 static jclass NavitClass;
847 static jmethodID Navit_disableSuspend, Navit_exit;
848
849 static void graphics_android_disable_suspend(struct window *win)
850 {
851 //DBG dbg(0,"enter\n");
852 (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_disableSuspend);
853 }
854
855 static struct graphics_priv *
856 graphics_android_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
857 {
858 //DBG dbg(0,"EEnter\n");
859
860 struct graphics_priv *ret;
861 struct attr *attr;
862 int use_camera = 0;
863 if (!event_request_system("android", "graphics_android"))
864 return NULL;ret=g_new0(struct graphics_priv, 1);
865
866 ret->cbl = cbl;
867 *meth = graphics_methods;
868 ret->win.priv = ret;
869 ret->win.fullscreen = graphics_android_fullscreen;
870 ret->win.disable_suspend = graphics_android_disable_suspend;
871 if ((attr = attr_search(attrs, NULL, attr_use_camera)))
872 {
873 use_camera = attr->u.num;
874 }
875 image_cache_hash = g_hash_table_new(g_str_hash, g_str_equal);
876 if (graphics_android_init(ret, NULL, NULL, 0, 0, 0, 0, use_camera))
877 {
878 ////DBG dbg(0,"returning %p\n",ret);
879 return ret;
880 }
881 else
882 {
883 g_free(ret);
884 return NULL;
885 }
886 }
887
888 static struct graphics_priv *
889 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
890 {
891 //DBG dbg(0,"EEnter\n");
892
893 struct graphics_priv *ret=g_new0(struct graphics_priv, 1);
894 *meth = graphics_methods;
895 if (graphics_android_init(ret, gr, p, w, h, alpha, wraparound, 0))
896 {
897 //DBG dbg(0, "returning %p\n", ret);
898 return ret;
899 }
900 else
901 {
902 g_free(ret);
903 return NULL;
904 }
905 }
906
907 static void event_android_main_loop_run(void)
908 {
909 //DBG dbg(0, "enter\n");
910 }
911
912 static void event_android_main_loop_quit(void)
913 {
914 //DBG dbg(0, "enter\n");
915 // ******* exit(0);
916 (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_exit);
917 }
918
919 static jclass NavitTimeoutClass;
920 static jmethodID NavitTimeout_init;
921 static jmethodID NavitTimeout_remove;
922
923 static jclass NavitIdleClass;
924 static jmethodID NavitIdle_init;
925 static jmethodID NavitIdle_remove;
926
927 static jclass NavitWatchClass;
928 static jmethodID NavitWatch_init;
929 static jmethodID NavitWatch_remove;
930
931 static struct event_watch *
932 event_android_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
933 {
934 //DBG dbg(0,"enter\n");
935 jobject ret;
936 ret = (*jnienv)->NewObject(jnienv, NavitWatchClass, NavitWatch_init, (int) h, (int) cond, (int) cb);
937 // //DBG dbg(0,"result for %p,%d,%p=%p\n",h,cond,cb,ret);
938 if (ret)
939 {
940 //DBG dbg(0,"result for %p,%p\n",h,ret);
941 ret = (*jnienv)->NewGlobalRef(jnienv, ret);
942 //DBG dbg(0,"g ret %p\n",ret);
943 }
944 return (struct event_watch *) ret;
945 }
946
947 static void event_android_remove_watch(struct event_watch *ev)
948 {
949 //DBG dbg(0,"enter\n");
950 if (ev)
951 {
952 //DBG dbg(0,"enter %p\n",ev);
953 jobject obj = (jobject) ev;
954 // maybe need this ? ICS obj = (*jnienv)->NewGlobalRef(jnienv, obj);
955 (*jnienv)->CallVoidMethod(jnienv, obj, NavitWatch_remove);
956 // ICS (*jnienv)->DeleteGlobalRef(jnienv, obj);
957 }
958 }
959
960 static struct event_timeout *
961 event_android_add_timeout(int timeout, int multi, struct callback *cb)
962 {
963 //DBG dbg(0,"EEnter\n");
964
965 jobject ret;
966 ret = (*jnienv)->NewObject(jnienv, NavitTimeoutClass, NavitTimeout_init, timeout, multi, (int) cb);
967 ////DBG dbg(0, "result for %d,%d,%p\n", timeout, multi, cb);
968
969 if (ret)
970 {
971 //DBG dbg(0,"l ret=%p\n",ret);
972 ret = (*jnienv)->NewGlobalRef(jnienv, ret);
973 //DBG dbg(0,"g ret=%p\n",ret);
974 }
975 //DBG dbg(0,"leave\n");
976 return (struct event_timeout *) ret;
977 }
978
979 static void event_android_remove_timeout(struct event_timeout *to)
980 {
981 //DBG dbg(0,"EEnter\n");
982
983 if (to)
984 {
985 // //DBG dbg(0, "remove %p\n", to);
986 //DBG dbg(0, "remove\n");
987 jobject obj = (jobject) to;
988 (*jnienv)->CallVoidMethod(jnienv, obj, NavitTimeout_remove);
989 // ICS (*jnienv)->DeleteGlobalRef(jnienv, obj);
990 }
991 }
992
993 static struct event_idle *
994 event_android_add_idle(int priority, struct callback *cb)
995 {
996 //DBG dbg(0,"EEnter\n");
997
998 #if 0
999 jobject ret;
1000 // dbg(1,"enter\n");
1001 ret=(*jnienv)->NewObject(jnienv, NavitIdleClass, NavitIdle_init, (int)cb);
1002 // dbg(1,"result for %p=%p\n",cb,ret);
1003 if (ret)
1004 (*jnienv)->NewGlobalRef(jnienv, ret);
1005 return (struct event_idle *)ret;
1006 #endif
1007 return (struct event_idle *) event_android_add_timeout(1, 1, cb);
1008 }
1009
1010 static void event_android_remove_idle(struct event_idle *ev)
1011 {
1012 //DBG dbg(0,"EEnter\n");
1013
1014 #if 0
1015 // dbg(1,"enter %p\n",ev);
1016 if (ev)
1017 {
1018 jobject obj=(jobject )ev;
1019 (*jnienv)->CallVoidMethod(jnienv, obj, NavitIdle_remove);
1020 (*jnienv)->DeleteGlobalRef(jnienv, obj);
1021 }
1022 #endif
1023 event_android_remove_timeout((struct event_timeout *) ev);
1024 }
1025
1026 static void event_android_call_callback(struct callback_list *cb)
1027 {
1028 //DBG dbg(0,"enter\n");
1029 }
1030
1031 static struct event_methods event_android_methods =
1032 { event_android_main_loop_run, event_android_main_loop_quit, event_android_add_watch, event_android_remove_watch, event_android_add_timeout, event_android_remove_timeout, event_android_add_idle, event_android_remove_idle, event_android_call_callback, };
1033
1034 static struct event_priv *
1035 event_android_new(struct event_methods *meth)
1036 {
1037 //DBG dbg(0,"enter\n");
1038 if (!find_class_global("com/zoffcc/applications/zanavi/NavitTimeout", &NavitTimeoutClass))
1039 return NULL;
1040 NavitTimeout_init = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "<init>", "(IZI)V");
1041 if (NavitTimeout_init == NULL)
1042 return NULL;
1043 NavitTimeout_remove = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "remove", "()V");
1044 if (NavitTimeout_remove == NULL)
1045 return NULL;
1046 #if 0
1047 if (!find_class_global("com/zoffcc/applications/zanavi/NavitIdle", &NavitIdleClass))
1048 return NULL;
1049 NavitIdle_init = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "<init>", "(I)V");
1050 if (NavitIdle_init == NULL)
1051 return NULL;
1052 NavitIdle_remove = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "remove", "()V");
1053 if (NavitIdle_remove == NULL)
1054 return NULL;
1055 #endif
1056
1057 if (!find_class_global("com/zoffcc/applications/zanavi/NavitWatch", &NavitWatchClass))
1058 return NULL;
1059 NavitWatch_init = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "<init>", "(III)V");
1060 if (NavitWatch_init == NULL)
1061 return NULL;
1062 NavitWatch_remove = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "remove", "()V");
1063 if (NavitWatch_remove == NULL)
1064 return NULL;
1065
1066 if (!find_class_global("com/zoffcc/applications/zanavi/Navit", &NavitClass))
1067 return NULL;
1068 Navit_disableSuspend = (*jnienv)->GetMethodID(jnienv, NavitClass, "disableSuspend", "()V");
1069 if (Navit_disableSuspend == NULL)
1070 return NULL;
1071 Navit_exit = (*jnienv)->GetMethodID(jnienv, NavitClass, "exit", "()V");
1072 if (Navit_exit == NULL)
1073 return NULL;
1074 //DBG dbg(0,"ok\n");
1075 *meth = event_android_methods;
1076 return NULL;
1077 }
1078
1079 void plugin_init(void)
1080 {
1081 //DBG dbg(0,"enter\n");
1082 plugin_register_graphics_type("android", graphics_android_new);
1083 plugin_register_event_type("android", event_android_new);
1084 }
1085

   
Visit the ZANavi Wiki