15 #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
22 #import <UIKit/UIKit.h>
24 #define NSMakeRect CGRectMake
29 return UIGraphicsGetCurrentContext();
33 #import <Cocoa/Cocoa.h>
35 #define UIViewController NSViewController
36 #define UIApplicationDelegate NSApplicationDelegate
37 #define UIWindow NSWindow
38 #define UIApplication NSApplication
39 #define UIApplicationMain(a,b,c,d) NSApplicationMain(a,b)
40 #define UIScreen NSScreen
41 #define UIEvent NSEvent
42 #define applicationFrame frame
47 return [[NSGraphicsContext currentContext] graphicsPort];
53 @interface NavitView : UIView {
56 CGContextRef layer_context;
57 struct graphics_priv *graphics;
62 static struct graphics_priv {
65 struct callback_list *cbl;
68 } *global_graphics_cocoa;
70 iconv_t utf8_macosroman;
72 struct graphics_gc_priv {
77 struct graphics_font_priv {
84 @implementation NavitView
86 - (void)drawRect:(NSRect)rect
89 NSLog(@"NavitView:drawRect...");
92 CGContextRef X = current_context();
94 CGContextDrawLayerAtPoint(X, CGPointZero, layer);
98 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
100 NSArray *arr=touches.allObjects;
101 UITouch *touch=[arr objectAtIndex: 0];
102 struct CGPoint pc=[touch locationInView: self];
106 dbg(0,"Enter count=%d %d %d\n",touches.count,p.x,p.y);
107 callback_list_call_attr_3(graphics->cbl, attr_button, GINT_TO_POINTER(1), GINT_TO_POINTER(1), (void *)&p);
111 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
113 NSArray *arr=touches.allObjects;
114 UITouch *touch=[arr objectAtIndex: 0];
115 struct CGPoint pc=[touch locationInView: self];
119 dbg(0,"Enter count=%d %d %d\n",touches.count,p.x,p.y);
120 callback_list_call_attr_3(graphics->cbl, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(1), (void *)&p);
123 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
125 NSArray *arr=touches.allObjects;
126 UITouch *touch=[arr objectAtIndex: 0];
127 struct CGPoint pc=[touch locationInView: self];
131 dbg(0,"Enter count=%d %d %d\n",touches.count,p.x,p.y);
132 callback_list_call_attr_3(graphics->cbl, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(1), (void *)&p);
135 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
137 NSArray *arr=touches.allObjects;
138 UITouch *touch=[arr objectAtIndex: 0];
139 struct CGPoint pc=[touch locationInView: self];
143 dbg(0,"Enter count=%d %d %d\n",touches.count,p.x,p.y);
144 callback_list_call_attr_1(graphics->cbl, attr_motion, (void *)&p);
148 - (void)mouseDown:(UIEvent *)theEvent
151 p.x=theEvent.locationInWindow.x;
152 p.y=graphics->h-theEvent.locationInWindow.y;
154 dbg(0,"Enter %d %d\n",p.x,p.y);
155 callback_list_call_attr_3(graphics->cbl, attr_button, GINT_TO_POINTER(1), GINT_TO_POINTER(1), (void *)&p);
158 - (void)mouseUp:(UIEvent *)theEvent
161 p.x=theEvent.locationInWindow.x;
162 p.y=graphics->h-theEvent.locationInWindow.y;
164 dbg(0,"Enter %d %d\n",p.x,p.y);
165 callback_list_call_attr_3(graphics->cbl, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(1), (void *)&p);
168 - (void)mouseDragged:(UIEvent *)theEvent
171 p.x=theEvent.locationInWindow.x;
172 p.y=graphics->h-theEvent.locationInWindow.y;
174 dbg(0,"Enter %d %d\n",p.x,p.y);
175 callback_list_call_attr_1(graphics->cbl, attr_motion, (void *)&p);
186 @interface NavitViewController : UIViewController
192 @property (nonatomic) NSRect frame;
194 - (id) init_withFrame : (NSRect) _frame;
200 @implementation NavitViewController
204 - (id) init_withFrame : (NSRect) _frame
206 NSLog(@"init with frame\n");
214 NavitView* myV = [NavitView alloc];
216 if (global_graphics_cocoa) {
217 global_graphics_cocoa->view=myV;
218 global_graphics_cocoa->w=frame.size.width;
219 global_graphics_cocoa->h=frame.size.height;
220 myV->graphics=global_graphics_cocoa;
223 CGContextRef X = current_context();
224 CGRect lr=CGRectMake(0, 0, frame.size.width, frame.size.height);
225 myV->layer=CGLayerCreateWithContext(X, lr.size, NULL);
226 myV->layer_context=CGLayerGetContext(myV->layer);
228 CGContextScaleCTM(myV->layer_context, 1, -1);
229 CGContextTranslateCTM(myV->layer_context, 0, -frame.size.height);
231 CGContextSetRGBFillColor(myV->layer_context, 1, 1, 1, 1);
232 CGContextSetRGBStrokeColor(myV->layer_context, 1, 1, 1, 1);
233 CGContextFillRect(myV->layer_context, lr);
235 [myV initWithFrame: frame];
242 - (void)didReceiveMemoryWarning {
243 // Releases the view if it doesn't have a superview.
244 [super didReceiveMemoryWarning];
246 // Release any cached data, images, etc that aren't in use.
249 - (void)viewDidUnload {
250 // Release any retained subviews of the main view.
251 // e.g. self.myOutlet = nil;
261 @class NavitViewController;
263 @interface NavitAppDelegate : NSObject <UIApplicationDelegate> {
265 NavitViewController *viewController;
268 @property (nonatomic, retain) /*IBOutlet*/ UIWindow *window;
269 @property (nonatomic, retain) /*IBOutlet*/ NavitViewController *viewController;
274 @implementation NavitAppDelegate
277 @synthesize viewController;
281 - (BOOL)application:(UIApplication *)application
282 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
285 applicationDidFinishLaunching:(NSNotification *)aNotification
288 NSLog(@"DidFinishLaunching\n");
290 [[UIApplication sharedApplication] setStatusBarHidden:NO];
293 NSRect appFrame = [UIScreen mainScreen].applicationFrame;
295 self.viewController = [[[NavitViewController alloc] init_withFrame : appFrame] autorelease];
297 NSRect windowRect = NSMakeRect(0, 0, appFrame.size.width, appFrame.size.height);
300 self.window = [[[UIWindow alloc] initWithFrame:windowRect] autorelease];
302 self.window = [[[UIWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO] autorelease];
304 utf8_macosroman=iconv_open("MACROMAN","UTF-8");
307 [window addSubview:viewController.view];
308 [window makeKeyAndVisible];
310 NSWindowController * controller = [[NSWindowController alloc] initWithWindow : window];
311 NSLog(@"Setting view\n");
312 [viewController loadView];
313 [window setContentView : viewController.view];
314 [controller setWindow : window];
315 [controller showWindow : nil];
319 if (global_graphics_cocoa) {
320 callback_list_call_attr_2(global_graphics_cocoa->cbl, attr_resize, (int)appFrame.size.width, (int)appFrame.size.height);
331 [viewController release];
341 draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
343 if (mode == draw_mode_end) {
346 [gr->view setNeedsDisplay];
354 draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
356 CGPoint points[count];
358 for (i = 0 ; i < count ; i++) {
362 CGContextSetStrokeColor(gr->view->layer_context, gc->rgba);
363 CGContextSetLineWidth(gr->view->layer_context, gc->w);
364 CGContextSetLineCap(gr->view->layer_context, kCGLineCapRound);
365 CGContextBeginPath(gr->view->layer_context);
366 CGContextAddLines(gr->view->layer_context, points, count);
367 CGContextStrokePath(gr->view->layer_context);
372 draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
374 CGPoint points[count];
376 for (i = 0 ; i < count ; i++) {
380 CGContextSetFillColor(gr->view->layer_context, gc->rgba);
381 CGContextBeginPath(gr->view->layer_context);
382 CGContextAddLines(gr->view->layer_context, points, count);
383 CGContextFillPath(gr->view->layer_context);
387 draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
389 CGRect lr=CGRectMake(p->x, p->y, w, h);
390 CGContextSetFillColor(gr->view->layer_context, gc->rgba);
391 CGContextFillRect(gr->view->layer_context, lr);
395 draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
397 size_t len,inlen=strlen(text)+1,outlen=strlen(text)+1;
399 char *inp=text,*outp=outb;
401 len=iconv (utf8_macosroman, &inp, &inlen, &outp, &outlen);
403 CGContextSetFillColor(gr->view->layer_context, fg->rgba);
405 CGContextSelectFont(gr->view->layer_context, font->name, font->size/16.0, kCGEncodingMacRoman);
406 CGContextSetTextDrawingMode(gr->view->layer_context, kCGTextFill);
407 CGAffineTransform xform = CGAffineTransformMake(dx/65536.0, dy/65536.0, dy/65536.0, -dx/65536.0, 0.0f, 0.0f);
408 CGContextSetTextMatrix(gr->view->layer_context, xform);
409 CGContextShowTextAtPoint(gr->view->layer_context, p->x, p->y, outb, strlen(outb));
413 draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
415 CGImageRef imgc=(CGImageRef) img;
416 int w=CGImageGetWidth(imgc);
417 int h=CGImageGetHeight(imgc);
418 CGRect rect=CGRectMake(0, 0, w, h);
419 CGContextSaveGState(gr->view->layer_context);
420 CGContextTranslateCTM(gr->view->layer_context, p->x, p->y+h);
421 CGContextScaleCTM(gr->view->layer_context, 1.0, -1.0);
422 CGContextDrawImage(gr->view->layer_context, rect, imgc);
423 CGContextRestoreGState(gr->view->layer_context);
426 static void font_destroy(struct graphics_font_priv *font)
431 static struct graphics_font_methods font_methods = {
435 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *font, int size, int flags)
437 struct graphics_font_priv *ret=g_new0(struct graphics_font_priv, 1);
441 ret->name="Helvetica";
446 gc_destroy(struct graphics_gc_priv *gc)
452 gc_set_linewidth(struct graphics_gc_priv *gc, int w)
458 gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
463 gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
465 gc->rgba[0]=c->r/65535.0;
466 gc->rgba[1]=c->g/65535.0;
467 gc->rgba[2]=c->b/65535.0;
468 gc->rgba[3]=c->a/65535.0;
472 gc_set_background(struct graphics_gc_priv *gc, struct color *c)
477 gc_set_stipple(struct graphics_gc_priv *gc, struct graphics_image_priv *img)
481 static struct graphics_gc_methods gc_methods = {
490 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
492 struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
501 background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
506 static struct graphics_image_priv *
507 image_new(struct graphics_priv *gra, struct graphics_image_methods *meth, char *path, int *w, int *h, struct point *hot, int rotation)
509 NSString *s=[[NSString alloc]initWithCString:path encoding:NSMacOSRomanStringEncoding];
510 CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData((CFDataRef)[NSData dataWithContentsOfFile:s]);
513 if (!imgDataProvider)
516 CGImageRef image = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
517 CGDataProviderRelease(imgDataProvider);
518 dbg(0,"size %dx%d\n",CGImageGetWidth(image),CGImageGetHeight(image));
520 *w=CGImageGetWidth(image);
522 *h=CGImageGetHeight(image);
524 hot->x=CGImageGetWidth(image)/2;
525 hot->y=CGImageGetHeight(image)/2;
531 get_data(struct graphics_priv *this, const char *type)
534 if (strcmp(type,"window"))
540 image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
542 CGImageRelease(priv);
546 get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
548 int len = g_utf8_strlen(text, -1);
551 int yMax = 13*font->size/256;
552 int xMax = 9*font->size*len/256;
564 static struct graphics_methods graphics_methods = {
565 NULL, /* graphics_destroy, */
570 NULL, /* draw_circle, */
573 NULL, /* draw_image_warp, */
574 NULL, /* draw_restore, */
575 NULL, /* draw_drag, */
579 NULL, /* overlay_new, */
584 NULL, /* overlay_disable, */
585 NULL, /* overlay_resize, */
586 NULL, /* set_attr, */
591 struct graphics_priv *
592 graphics_cocoa_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
594 struct graphics_priv *ret;
595 *meth=graphics_methods;
597 if(!event_request_system("cocoa","graphics_cocoa"))
599 ret=g_new0(struct graphics_priv, 1);
601 global_graphics_cocoa=ret;
606 event_cocoa_main_loop_run(void)
611 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
612 NSString *documentsDirectory = [paths objectAtIndex:0];
613 NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
614 freopen("/tmp/log.txt","a+",stderr);
617 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
619 dbg(0,"calling main\n");
620 int retval = UIApplicationMain(main_argc, main_argv, nil, @"NavitAppDelegate");
621 dbg(0,"retval=%d\n",retval);
623 NavitAppDelegate * delegate = [[NavitAppDelegate alloc] init];
624 NSApplication * application = [NSApplication sharedApplication];
625 [application setDelegate:delegate];
635 @interface NavitTimer : NSObject{
640 - (void)onTimer:(NSTimer*)theTimer;
644 @implementation NavitTimer
646 - (void)onTimer:(NSTimer*)theTimer
660 event_cocoa_add_timeout(int timeout, int multi, struct callback *cb)
662 NavitTimer *ret=[[NavitTimer alloc]init];
664 ret->timer=[NSTimer scheduledTimerWithTimeInterval:(timeout/1000.0) target:ret selector:@selector(onTimer:) userInfo:nil repeats:multi?YES:NO];
665 dbg(0,"timer=%p\n",ret->timer);
671 event_cocoa_remove_timeout(struct event_timeout *ev)
673 NavitTimer *t=(NavitTimer *)ev;
675 [t->timer invalidate];
680 static struct event_idle *
681 event_cocoa_add_idle(int priority, struct callback *cb)
683 NavitTimer *ret=[[NavitTimer alloc]init];
685 ret->timer=[NSTimer scheduledTimerWithTimeInterval:(0.0) target:ret selector:@selector(onTimer:) userInfo:nil repeats:YES];
687 dbg(0,"timer=%p\n",ret->timer);
692 event_cocoa_remove_idle(struct event_idle *ev)
694 NavitTimer *t=(NavitTimer *)ev;
696 [t->timer invalidate];
700 static struct event_methods event_cocoa_methods = {
701 event_cocoa_main_loop_run,
702 NULL, /* event_cocoa_main_loop_quit, */
703 NULL, /* event_cocoa_add_watch, */
704 NULL, /* event_cocoa_remove_watch, */
705 event_cocoa_add_timeout,
706 event_cocoa_remove_timeout,
707 event_cocoa_add_idle,
708 event_cocoa_remove_idle,
709 NULL, /* event_cocoa_call_callback, */
713 static struct event_priv *
714 event_cocoa_new(struct event_methods *meth)
717 *meth=event_cocoa_methods;
726 plugin_register_graphics_type("cocoa", graphics_cocoa_new);
727 plugin_register_event_type("cocoa", event_cocoa_new);