blob: c15382daf9e23e2fd4008214afaeb02f0fa131b9 [file] [log] [blame]
/*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 2007-2016 The R Core Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, a copy is available at
* https://www.R-project.org/Licenses/
*
*---------------------------------------------------------------------
* This header file constitutes the (unofficial) API to the Quartz
* device. Being unofficial, the API may change at any point without
* warning.
*
* Quartz is a general device-independent way of drawing in macOS,
* therefore the Quartz device modularizes the actual drawing target
* implementation into separate modules (e.g. Carbon and Cocoa for
* on-screen display and PDF, Bitmap for off-screen drawing). The API
* below is used by the modules to talk to the Quartz device without
* having to know anything about R graphics device API.
*
* Key functions are listed here:
* QuartzDevice_Create - creates a Quartz device
* QuartzDevice_ResetContext - should be called after the target
* context has been created to initialize it.
* QuartzDevice_Kill - closes the Quartz device (e.g. on window close)
* QuartzDevice_SetScaledSize - resize device (does not include
* re-painting, it should be followed by a call to
* QuartzDevice_ReplayDisplayList)
* QuartzDevice_ReplayDisplayList - replays all plot commands
*
* Key concepts
* - all Quartz modules are expected to provide a device context
* (CGContextRef) for drawing. A device can temporarily return NULL
* (e.g. if the context is not available immediately) and replay
* the display list later to catch up.
*
* - interactive devices can use QuartzDevice_SetScaledSize to resize
* the device (no context is necessary), then prepare the context
* (call QuartzDevice_ResetContext if a new context was created)
* and finally re-draw using QuartzDevice_ReplayDisplayList.
*
* - snapshots can be created either off the current display list
* (last=0) or off the last known one (last=1). NewPage callback
* can only use last=1 as there is no display list during that
* call. Restored snapshots become the current display list and
* thus can be extended by further painting (yet the original saved
* copy is not influenced). Also note that all snapshots are SEXPs
* (the declaration doesn't use SEXP as to not depend on
* Rinternals.h) therefore must be protected or preserved immediately
* (i.e. the Quartz device does NOT protect them - except in the
* call to RestoreSnapshot).
*
* - dirty flag: the dirty flag is not used internally by the Quartz
* device, but can be useful for the modules to determine whether
* the current graphics is a restored copy or in-progress
* drawing. The Quartz device manages the flag as follows: a)
* display list replay does NOT change the flag, b) snapshot
* restoration resets the flag, c) all other paint operations
* (i.e. outside of restore/replay) set the flag. Most common use
* is to determine whether restored snapshots have been
* subsequently modified.
*
* - history: currently the history management is not used by any
* modules and as such is untested and strictly experimental. It
* may be removed in the future as it is not clear whether it makes
* sense to be part of the device. See Cocoa module for a
* module-internal implementation of the display history.
*
* Quartz device creation path:
* quartz() function -> SEXP Quartz(args) ->
* setup QuartzParameters_t, call backend constructor
* [e.g. QuartzCocoa_DeviceCreate(dd, fn, QuartzParameters_t *pars)] ->
* create backend definition (QuartzBackend_t backend) ->
* fn->Create(dd, &backend), return the result
*/
/* Unix-only header */
#ifndef R_EXT_QUARTZDEVICE_H_
#define R_EXT_QUARTZDEVICE_H_
/* FIXME: this is installed, but can it really work without config.h? */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if HAVE_AQUA
#include <ApplicationServices/ApplicationServices.h>
#else
typedef void* CGContextRef;
#endif
/* flags passed to the newPage callback */
#define QNPF_REDRAW 0x0001 /* is set when NewPage really means re-draw of an existing page */
/* flags passed to QuartzDevice_Create (as fs parameter) */
#define QDFLAG_DISPLAY_LIST 0x0001
#define QDFLAG_INTERACTIVE 0x0002
#define QDFLAG_RASTERIZED 0x0004 /* rasterized media - may imply disabling AA paritally for rects etc. */
/* parameter flags (they should not conflict with QDFLAGS to allow chaining) */
#define QPFLAG_ANTIALIAS 0x0100
typedef void* QuartzDesc_t;
typedef struct QuartzBackend_s {
int size; /* structure size */
double width, height;
double scalex, scaley, pointsize;
int bg, canvas;
int flags;
void* userInfo;
CGContextRef (*getCGContext)(QuartzDesc_t dev, void*userInfo); /* Get the context for this device */
int (*locatePoint)(QuartzDesc_t dev, void*userInfo, double*x, double*y);
void (*close)(QuartzDesc_t dev, void*userInfo);
void (*newPage)(QuartzDesc_t dev, void*userInfo, int flags);
void (*state)(QuartzDesc_t dev, void*userInfo, int state);
void* (*par)(QuartzDesc_t dev, void*userInfo, int set, const char *key, void *value);
void (*sync)(QuartzDesc_t dev, void*userInfo);
void* (*cap)(QuartzDesc_t dev, void*userInfo);
} QuartzBackend_t;
/* parameters that are passed to functions that create backends */
typedef struct QuartzParameters_s {
int size; /* structure size */
const char *type, *file, *title;
double x, y, width, height, pointsize;
const char *family;
int flags;
int connection;
int bg, canvas;
double *dpi;
/* the following parameters can be used to pass custom parameters when desired */
double pard1, pard2;
int pari1, pari2;
const char *pars1, *pars2;
void *parv;
} QuartzParameters_t;
/* all device implementations have to call this general Quartz device constructor at some point */
QuartzDesc_t QuartzDevice_Create(void *dd, QuartzBackend_t* def);
typedef struct QuartzFunctons_s {
void* (*Create)(void *, QuartzBackend_t *); /* create a new device */
int (*DevNumber)(QuartzDesc_t desc); /* returns device number */
void (*Kill)(QuartzDesc_t desc); /* call to close the device */
void (*ResetContext)(QuartzDesc_t desc); /* notifies Q back-end that the implementation has created a new context */
double (*GetWidth)(QuartzDesc_t desc); /* get device width (in inches) */
double (*GetHeight)(QuartzDesc_t desc); /* get device height (in inches) */
void (*SetSize)(QuartzDesc_t desc, double width, double height); /* set device size (in inches) */
double (*GetScaledWidth)(QuartzDesc_t desc); /* get device width (in pixels) */
double (*GetScaledHeight)(QuartzDesc_t desc); /* get device height (in pixels) */
void (*SetScaledSize)(QuartzDesc_t desc, double width, double height); /* set device size (in pixels) */
double (*GetXScale)(QuartzDesc_t desc); /* get x scale factor (px/pt ratio) */
double (*GetYScale)(QuartzDesc_t desc); /* get y scale factor (px/pt ratio) */
void (*SetScale)(QuartzDesc_t desc,double scalex, double scaley); /* sets both scale factors (px/pt ratio) */
void (*SetTextScale)(QuartzDesc_t desc,double scale); /* sets text scale factor */
double (*GetTextScale)(QuartzDesc_t desc); /* sets text scale factor */
void (*SetPointSize)(QuartzDesc_t desc,double ps); /* sets point size */
double (*GetPointSize)(QuartzDesc_t desc); /* gets point size */
int (*GetDirty)(QuartzDesc_t desc); /* sets dirty flag */
void (*SetDirty)(QuartzDesc_t desc,int dirty); /* gets dirty flag */
void (*ReplayDisplayList)(QuartzDesc_t desc); /* replay display list
Note: it inhibits sync calls during repaint,
the caller is responsible for calling sync if needed.
Dirty flag is kept unmodified */
void* (*GetSnapshot)(QuartzDesc_t desc, int last);
/* create a (replayable) snapshot of the device contents.
when 'last' is set then the last stored display list is used,
otherwise a new snapshot is created */
void (*RestoreSnapshot)(QuartzDesc_t desc,void* snapshot);
/* restore a snapshot. also clears the dirty flag */
int (*GetAntialias)(QuartzDesc_t desc); /* get anti-alias flag */
void (*SetAntialias)(QuartzDesc_t desc, int aa); /* set anti-alias flag */
int (*GetBackground)(QuartzDesc_t desc); /* get background color */
void (*Activate)(QuartzDesc_t desc); /* activate/select the device */
/* get/set Quartz-specific parameters. desc can be NULL for global parameters */
void* (*SetParameter)(QuartzDesc_t desc, const char *key, void *value);
void* (*GetParameter)(QuartzDesc_t desc, const char *key);
} QuartzFunctions_t;
#define QuartzParam_EmbeddingFlags "embeddeding flags" /* value: int[1] */
#define QP_Flags_CFLoop 0x0001 /* drives application event loop */
#define QP_Flags_Cocoa 0x0002 /* Cocoa is fully initialized */
#define QP_Flags_Front 0x0004 /* is front application */
/* FIXME: no longer used, remove in due course */
/* from unix/aqua.c - loads grDevices if necessary and returns NULL on failure */
QuartzFunctions_t *getQuartzFunctions();
/* type of a Quartz contructor */
typedef QuartzDesc_t (*quartz_create_fn_t)(void *dd, QuartzFunctions_t *fn, QuartzParameters_t *par);
/* grDevices currently supply following constructors:
QuartzCocoa_DeviceCreate, QuartzCarbon_DeviceCreate,
QuartzBitmap_DeviceCreate, QuartzPDF_DeviceCreate */
/* embedded Quartz support hook (defined in unix/aqua.c):
dd = should be passed-through to QuartzDevice_Create
fn = Quartz API functions
par = parameters (see above) */
#ifndef IN_AQUA_C
extern
#endif
QuartzDesc_t (*ptr_QuartzBackend)(void *dd, QuartzFunctions_t *fn, QuartzParameters_t *par);
/* C version of the Quartz call (experimental)
returns 0 on success, error code on failure */
QuartzDesc_t Quartz_C(QuartzParameters_t *par, quartz_create_fn_t q_create, int *errorCode);
#ifdef __cplusplus
}
#endif
#endif