diff options
author | David Robillard <d@drobilla.net> | 2019-07-28 18:53:31 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-07-29 22:43:19 +0200 |
commit | b0a92df939138ba3fb92d0d5b3cafcc822df4fec (patch) | |
tree | 7a3c330f97cf98a21ae6d7ea6dd42ec08941f184 /pugl/detail/mac_cairo.m | |
parent | 074538bae86584b962b9cd41304fed235f8731b1 (diff) | |
download | pugl-b0a92df939138ba3fb92d0d5b3cafcc822df4fec.tar.gz pugl-b0a92df939138ba3fb92d0d5b3cafcc822df4fec.tar.bz2 pugl-b0a92df939138ba3fb92d0d5b3cafcc822df4fec.zip |
Mac: Separate backends from platform implementation
Diffstat (limited to 'pugl/detail/mac_cairo.m')
-rw-r--r-- | pugl/detail/mac_cairo.m | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/pugl/detail/mac_cairo.m b/pugl/detail/mac_cairo.m new file mode 100644 index 0000000..b0a8db5 --- /dev/null +++ b/pugl/detail/mac_cairo.m @@ -0,0 +1,166 @@ +/* + Copyright 2019 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file mac_cairo.m Cairo graphics backend for MacOS. +*/ + +#include "pugl/detail/implementation.h" +#include "pugl/detail/mac.h" +#include "pugl/pugl_cairo_backend.h" + +#include <cairo-quartz.h> + +#import <Cocoa/Cocoa.h> + +#include <assert.h> + +@interface PuglCairoView : NSView +{ +@public + PuglView* puglview; + cairo_surface_t* surface; + cairo_t* cr; +} + +@end + +@implementation PuglCairoView + +- (id) initWithFrame:(NSRect)frame +{ + return (self = [super initWithFrame:frame]); +} + +- (void) resizeWithOldSuperviewSize:(NSSize)oldSize +{ + PuglWrapperView* wrapper = (PuglWrapperView*)[self superview]; + + [super resizeWithOldSuperviewSize:oldSize]; + [wrapper dispatchConfigure:[self bounds]]; +} + +@end + +static int +puglMacCairoConfigure(PuglView* PUGL_UNUSED(view)) +{ + return 0; +} + +static int +puglMacCairoCreate(PuglView* view) +{ + PuglInternals* impl = view->impl; + PuglCairoView* drawView = [PuglCairoView alloc]; + + drawView->puglview = view; + [drawView initWithFrame:NSMakeRect(0, 0, view->width, view->height)]; + if (view->hints.resizable) { + [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + } else { + [drawView setAutoresizingMask:NSViewNotSizable]; + } + + impl->drawView = drawView; + return 0; +} + +static int +puglMacCairoDestroy(PuglView* view) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + + [drawView removeFromSuperview]; + [drawView release]; + + view->impl->drawView = nil; + return 0; +} + +static int +puglMacCairoEnter(PuglView* view, bool drawing) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + if (!drawing) { + return 0; + } + + assert(!drawView->surface); + assert(!drawView->cr); + + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + + drawView->surface = cairo_quartz_surface_create_for_cg_context( + context, view->width, view->height); + + drawView->cr = cairo_create(drawView->surface); + + return 0; +} + +static int +puglMacCairoLeave(PuglView* view, bool drawing) +{ + PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView; + if (!drawing) { + return 0; + } + + assert(drawView->surface); + assert(drawView->cr); + + CGContextRef context = cairo_quartz_surface_get_cg_context(drawView->surface); + + cairo_destroy(drawView->cr); + cairo_surface_destroy(drawView->surface); + drawView->cr = NULL; + drawView->surface = NULL; + + CGContextFlush(context); + + return 0; +} + +static int +puglMacCairoResize(PuglView* PUGL_UNUSED(view), + int PUGL_UNUSED(width), + int PUGL_UNUSED(height)) +{ + // No need to resize, the surface is created for the drawing context + return 0; +} + +static void* +puglMacCairoGetContext(PuglView* view) +{ + return ((PuglCairoView*)view->impl->drawView)->cr; +} + +const PuglBackend* puglCairoBackend(void) +{ + static const PuglBackend backend = { + puglMacCairoConfigure, + puglMacCairoCreate, + puglMacCairoDestroy, + puglMacCairoEnter, + puglMacCairoLeave, + puglMacCairoResize, + puglMacCairoGetContext + }; + + return &backend; +} |