| /* |
| * R : A Computer Language for Statistical Data Analysis |
| * Copyright (C) 2001-3 Paul Murrell |
| * 2003-2019 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/ |
| */ |
| |
| #include <R.h> |
| #include <Rconfig.h> |
| #include <Rinternals.h> |
| #include <Rmath.h> |
| |
| #include <R_ext/Constants.h> |
| #include <R_ext/GraphicsEngine.h> |
| |
| #include <Rinternals.h> |
| #ifdef ENABLE_NLS |
| #include <libintl.h> |
| #define _(String) dgettext ("grid", String) |
| #else |
| #define _(String) (String) |
| #endif |
| |
| /* All grid type names are prefixed with an "L" |
| * All grid global variable names are prefixed with an "L_" |
| */ |
| |
| /* This information is stored with R's graphics engine so that |
| * grid can have state information per device and grid output can |
| * be maintained on multiple devices. |
| */ |
| |
| #define GSS_DEVSIZE 0 |
| #define GSS_CURRLOC 1 |
| #define GSS_DL 2 |
| #define GSS_DLINDEX 3 |
| #define GSS_DLON 4 |
| #define GSS_GPAR 5 |
| #define GSS_GPSAVED 6 |
| #define GSS_VP 7 |
| #define GSS_GLOBALINDEX 8 |
| #define GSS_GRIDDEVICE 9 |
| #define GSS_PREVLOC 10 |
| #define GSS_ENGINEDLON 11 |
| #define GSS_CURRGROB 12 |
| #define GSS_ENGINERECORDING 13 |
| /* #define GSS_ASK 14 unused in R >= 2.7.0 */ |
| #define GSS_SCALE 15 |
| |
| /* |
| * Structure of a viewport |
| */ |
| #define VP_X 0 |
| #define VP_Y 1 |
| #define VP_WIDTH 2 |
| #define VP_HEIGHT 3 |
| #define VP_JUST 4 |
| #define VP_GP 5 |
| #define VP_CLIP 6 |
| #define VP_XSCALE 7 |
| #define VP_YSCALE 8 |
| #define VP_ANGLE 9 |
| #define VP_LAYOUT 10 |
| #define VP_LPOSROW 11 |
| #define VP_LPOSCOL 12 |
| #define VP_VALIDJUST 13 |
| #define VP_VALIDLPOSROW 14 |
| #define VP_VALIDLPOSCOL 15 |
| #define VP_NAME 16 |
| /* |
| * Additional structure of a pushedvp |
| */ |
| #define PVP_PARENTGPAR 17 |
| #define PVP_GPAR 18 |
| #define PVP_TRANS 19 |
| #define PVP_WIDTHS 20 |
| #define PVP_HEIGHTS 21 |
| #define PVP_WIDTHCM 22 |
| #define PVP_HEIGHTCM 23 |
| #define PVP_ROTATION 24 |
| #define PVP_CLIPRECT 25 |
| #define PVP_PARENT 26 |
| #define PVP_CHILDREN 27 |
| #define PVP_DEVWIDTHCM 28 |
| #define PVP_DEVHEIGHTCM 29 |
| |
| /* |
| * Structure of a layout |
| */ |
| #define LAYOUT_NROW 0 |
| #define LAYOUT_NCOL 1 |
| #define LAYOUT_WIDTHS 2 |
| #define LAYOUT_HEIGHTS 3 |
| #define LAYOUT_RESPECT 4 |
| #define LAYOUT_VRESPECT 5 |
| #define LAYOUT_MRESPECT 6 |
| #define LAYOUT_JUST 7 |
| #define LAYOUT_VJUST 8 |
| |
| #define GP_FILL 0 |
| #define GP_COL 1 |
| #define GP_GAMMA 2 |
| #define GP_LTY 3 |
| #define GP_LWD 4 |
| #define GP_CEX 5 |
| #define GP_FONTSIZE 6 |
| #define GP_LINEHEIGHT 7 |
| #define GP_FONT 8 |
| #define GP_FONTFAMILY 9 |
| #define GP_ALPHA 10 |
| #define GP_LINEEND 11 |
| #define GP_LINEJOIN 12 |
| #define GP_LINEMITRE 13 |
| #define GP_LEX 14 |
| /* |
| * Keep fontface at the end because it is never used in C code |
| */ |
| #define GP_FONTFACE 15 |
| |
| /* |
| * Structure of an arrow description |
| */ |
| #define GRID_ARROWANGLE 0 |
| #define GRID_ARROWLENGTH 1 |
| #define GRID_ARROWENDS 2 |
| #define GRID_ARROWTYPE 3 |
| |
| typedef double LTransform[3][3]; |
| |
| typedef double LLocation[3]; |
| |
| typedef enum { |
| L_adding = 1, |
| L_subtracting = 2, |
| L_summing = 3, |
| L_plain = 4, |
| L_maximising = 5, |
| L_minimising = 6, |
| L_multiplying = 7 |
| } LNullArithmeticMode; |
| |
| /* NOTE: The order of the enums here must match the order of the |
| * strings in unit.R |
| */ |
| typedef enum { |
| L_NPC = 0, |
| L_CM = 1, |
| L_INCHES = 2, |
| L_LINES = 3, |
| L_NATIVE = 4, |
| L_NULL = 5, /* only used in layout specifications (?) */ |
| L_SNPC = 6, |
| L_MM = 7, |
| /* Some units based on TeX's definition thereof |
| */ |
| L_POINTS = 8, /* 72.27 pt = 1 in */ |
| L_PICAS = 9, /* 1 pc = 12 pt */ |
| L_BIGPOINTS = 10, /* 72 bp = 1 in */ |
| L_DIDA = 11, /* 1157 dd = 1238 pt */ |
| L_CICERO = 12, /* 1 cc = 12 dd */ |
| L_SCALEDPOINTS = 13, /* 65536 sp = 1pt */ |
| /* Some units which require an object to query for a value. |
| */ |
| L_STRINGWIDTH = 14, |
| L_STRINGHEIGHT = 15, |
| L_STRINGASCENT = 16, |
| L_STRINGDESCENT = 17, |
| /* L_LINES now means multiples of the line height. |
| * This is multiples of the font size. |
| */ |
| L_CHAR = 18, |
| L_GROBX = 19, |
| L_GROBY = 20, |
| L_GROBWIDTH = 21, |
| L_GROBHEIGHT = 22, |
| L_GROBASCENT = 23, |
| L_GROBDESCENT = 24, |
| /* |
| * No longer used |
| */ |
| L_MYLINES = 103, |
| L_MYCHAR = 104, |
| L_MYSTRINGWIDTH = 105, |
| L_MYSTRINGHEIGHT = 106 |
| } LUnit; |
| |
| typedef enum { |
| L_LEFT = 0, |
| L_RIGHT = 1, |
| L_BOTTOM = 2, |
| L_TOP = 3, |
| L_CENTRE = 4, |
| L_CENTER = 5 |
| } LJustification; |
| |
| /* An arbitrarily-oriented rectangle. |
| * The vertices are assumed to be in order going anticlockwise |
| * around the rectangle. |
| */ |
| typedef struct { |
| double x1; |
| double x2; |
| double x3; |
| double x4; |
| double y1; |
| double y2; |
| double y3; |
| double y4; |
| } LRect; |
| |
| /* A description of the location of a viewport */ |
| typedef struct { |
| SEXP x; |
| SEXP y; |
| SEXP width; |
| SEXP height; |
| double hjust; |
| double vjust; |
| } LViewportLocation; |
| |
| /* Components of a viewport which provide coordinate information |
| * for children of the viewport |
| */ |
| typedef struct { |
| double xscalemin; |
| double xscalemax; |
| double yscalemin; |
| double yscalemax; |
| } LViewportContext; |
| |
| /* Evaluation environment */ |
| #ifndef GRID_MAIN |
| extern SEXP R_gridEvalEnv; |
| #else |
| SEXP R_gridEvalEnv; |
| #endif |
| |
| |
| /* Functions called by R code |
| * (from all over the place) |
| */ |
| SEXP L_initGrid(SEXP GridEvalEnv); |
| SEXP L_killGrid(); |
| SEXP L_gridDirty(); |
| SEXP L_currentViewport(); |
| SEXP L_setviewport(SEXP vp, SEXP hasParent); |
| SEXP L_downviewport(SEXP vp, SEXP strict); |
| SEXP L_downvppath(SEXP path, SEXP name, SEXP strict); |
| SEXP L_unsetviewport(SEXP last); |
| SEXP L_upviewport(SEXP last); |
| SEXP L_getDisplayList(); |
| SEXP L_setDisplayList(SEXP dl); |
| SEXP L_getDLelt(SEXP index); |
| SEXP L_setDLelt(SEXP value); |
| SEXP L_getDLindex(); |
| SEXP L_setDLindex(SEXP index); |
| SEXP L_getDLon(); |
| SEXP L_setDLon(SEXP value); |
| SEXP L_getEngineDLon(); |
| SEXP L_setEngineDLon(SEXP value); |
| SEXP L_getCurrentGrob(); |
| SEXP L_setCurrentGrob(SEXP value); |
| SEXP L_getEngineRecording(); |
| SEXP L_setEngineRecording(SEXP value); |
| SEXP L_currentGPar(); |
| SEXP L_newpagerecording(); |
| SEXP L_newpage(); |
| SEXP L_initGPar(); |
| SEXP L_initViewportStack(); |
| SEXP L_initDisplayList(); |
| SEXP L_convertToNative(SEXP x, SEXP what); |
| SEXP L_moveTo(SEXP x, SEXP y); |
| SEXP L_lineTo(SEXP x, SEXP y, SEXP arrow); |
| SEXP L_lines(SEXP x, SEXP y, SEXP index, SEXP arrow); |
| SEXP L_segments(SEXP x0, SEXP y0, SEXP x1, SEXP y1, SEXP arrow); |
| SEXP L_arrows(SEXP x1, SEXP x2, SEXP xnm1, SEXP xn, |
| SEXP y1, SEXP y2, SEXP ynm1, SEXP yn, |
| SEXP angle, SEXP length, SEXP ends, SEXP type); |
| SEXP L_path(SEXP x, SEXP y, SEXP index, SEXP rule); |
| SEXP L_polygon(SEXP x, SEXP y, SEXP index); |
| SEXP L_xspline(SEXP x, SEXP y, SEXP s, SEXP o, SEXP a, SEXP rep, SEXP index); |
| SEXP L_circle(SEXP x, SEXP y, SEXP r); |
| SEXP L_rect(SEXP x, SEXP y, SEXP w, SEXP h, SEXP hjust, SEXP vjust); |
| SEXP L_raster(SEXP raster, SEXP x, SEXP y, SEXP w, SEXP h, |
| SEXP hjust, SEXP vjust, SEXP interpolate); |
| SEXP L_cap(); |
| SEXP L_text(SEXP label, SEXP x, SEXP y, SEXP hjust, SEXP vjust, |
| SEXP rot, SEXP checkOverlap); |
| SEXP L_points(SEXP x, SEXP y, SEXP pch, SEXP size); |
| SEXP L_clip(SEXP x, SEXP y, SEXP w, SEXP h, SEXP hjust, SEXP vjust); |
| SEXP L_pretty(SEXP scale); |
| SEXP L_locator(); |
| SEXP L_convert(SEXP x, SEXP whatfrom, |
| SEXP whatto, SEXP unitto); |
| SEXP L_devLoc(SEXP x, SEXP y); |
| SEXP L_devDim(SEXP x, SEXP y); |
| SEXP L_layoutRegion(SEXP layoutPosRow, SEXP layoutPosCol); |
| |
| SEXP L_stringMetric(SEXP label); |
| |
| /* From matrix.c */ |
| double locationX(LLocation l); |
| |
| double locationY(LLocation l); |
| |
| void copyTransform(LTransform t1, LTransform t2); |
| |
| void invTransform(LTransform t, LTransform invt); |
| |
| void identity(LTransform m); |
| |
| void translation(double tx, double ty, LTransform m); |
| |
| void scaling(double sx, double sy, LTransform m); |
| |
| void rotation(double theta, LTransform m); |
| |
| void multiply(LTransform m1, LTransform m2, LTransform m); |
| |
| void location(double x, double y, LLocation v); |
| |
| void trans(LLocation vin, LTransform m, LLocation vout); |
| |
| /* From unit.c */ |
| int isUnitArithmetic(SEXP ua); |
| |
| int isUnitList(SEXP ul); |
| |
| SEXP unit(double value, int unit); |
| |
| double unitValue(SEXP unit, int index); |
| |
| int unitUnit(SEXP unit, int index); |
| |
| SEXP unitData(SEXP unit, int index); |
| |
| int unitLength(SEXP u); |
| |
| extern int L_nullLayoutMode; |
| |
| double pureNullUnitValue(SEXP unit, int index); |
| |
| int pureNullUnit(SEXP unit, int index, pGEDevDesc dd); |
| |
| double transformX(SEXP x, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| int nullLMode, int nullAMode, |
| pGEDevDesc dd); |
| |
| double transformY(SEXP y, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| int nullLMode, int nullAMode, |
| pGEDevDesc dd); |
| |
| double transformWidth(SEXP width, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| int nullLMode, int nullAMode, |
| pGEDevDesc dd); |
| |
| double transformHeight(SEXP height, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| int nullLMode, int nullAMode, |
| pGEDevDesc dd); |
| |
| double transformXtoINCHES(SEXP x, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd); |
| |
| double transformYtoINCHES(SEXP y, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd); |
| |
| void transformLocn(SEXP x, SEXP y, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd, |
| LTransform t, |
| double *xx, double *yy); |
| |
| double transformWidthtoINCHES(SEXP w, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd); |
| |
| double transformHeighttoINCHES(SEXP h, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd); |
| |
| void transformDimn(SEXP w, SEXP h, int index, LViewportContext vpc, |
| const pGEcontext gc, |
| double widthCM, double heightCM, |
| pGEDevDesc dd, |
| double rotationAngle, |
| double *ww, double *hh); |
| |
| double transformXYFromINCHES(double location, int unit, |
| double scalemin, double scalemax, |
| const pGEcontext gc, |
| double thisCM, double otherCM, |
| pGEDevDesc dd); |
| |
| double transformWidthHeightFromINCHES(double value, int unit, |
| double scalemin, double scalemax, |
| const pGEcontext gc, |
| double thisCM, double otherCM, |
| pGEDevDesc dd); |
| |
| double transformXYtoNPC(double x, int from, double min, double max); |
| |
| double transformWHtoNPC(double x, int from, double min, double max); |
| |
| double transformXYfromNPC(double x, int to, double min, double max); |
| |
| double transformWHfromNPC(double x, int to, double min, double max); |
| |
| /* From just.c */ |
| double justifyX(double x, double width, double hjust); |
| |
| double justifyY(double y, double height, double vjust); |
| |
| double convertJust(int vjust); |
| |
| void justification(double width, double height, double hjust, double vjust, |
| double *hadj, double *vadj); |
| |
| /* From util.c */ |
| SEXP getListElement(SEXP list, char *str); |
| |
| void setListElement(SEXP list, char *str, SEXP value); |
| |
| SEXP getSymbolValue(char *symbolName); |
| |
| void setSymbolValue(char *symbolName, SEXP value); |
| |
| double numeric(SEXP x, int index); |
| |
| void rect(double x1, double x2, double x3, double x4, |
| double y1, double y2, double y3, double y4, |
| LRect *r); |
| |
| void copyRect(LRect r1, LRect *r); |
| |
| int intersect(LRect r1, LRect r2); |
| |
| void textRect(double x, double y, SEXP text, int i, |
| const pGEcontext gc, |
| double xadj, double yadj, |
| double rot, pGEDevDesc dd, LRect *r); |
| |
| /* From gpar.c */ |
| double gpFontSize(SEXP gp, int i); |
| |
| double gpLineHeight(SEXP gp, int i); |
| |
| int gpCol(SEXP gp, int i); |
| |
| SEXP gpFillSXP(SEXP gp); |
| |
| int gpFill(SEXP gp, int i); |
| |
| double gpGamma(SEXP gp, int i); |
| |
| int gpLineType(SEXP gp, int i); |
| |
| double gpLineWidth(SEXP gp, int i); |
| |
| double gpCex(SEXP gp, int i); |
| |
| int gpFont(SEXP gp, int i); |
| |
| const char* gpFontFamily(SEXP gp, int i); |
| |
| SEXP gpFontSXP(SEXP gp); |
| |
| SEXP gpFontFamilySXP(SEXP gp); |
| |
| SEXP gpFontSizeSXP(SEXP gp); |
| |
| SEXP gpLineHeightSXP(SEXP gp); |
| |
| void gcontextFromgpar(SEXP gp, int i, const pGEcontext gc, pGEDevDesc dd); |
| void initGContext(SEXP gp, const pGEcontext gc, pGEDevDesc dd, int* gpIsScalar, |
| const pGEcontext gcCache); |
| void updateGContext(SEXP gp, int i, const pGEcontext gc, pGEDevDesc dd, |
| int* gpIsScalar, const pGEcontext gcCache); |
| |
| void initGPar(pGEDevDesc dd); |
| |
| /* From viewport.c */ |
| SEXP viewportX(SEXP vp); |
| |
| SEXP viewportY(SEXP vp); |
| |
| SEXP viewportWidth(SEXP vp); |
| |
| SEXP viewportHeight(SEXP vp); |
| |
| SEXP viewportgpar(SEXP vp); |
| |
| const char* viewportFontFamily(SEXP vp); |
| |
| int viewportFont(SEXP vp); |
| |
| double viewportFontSize(SEXP vp); |
| |
| double viewportLineHeight(SEXP vp); |
| |
| Rboolean viewportClip(SEXP vp); |
| |
| SEXP viewportClipRect(SEXP vp); |
| |
| double viewportXScaleMin(SEXP vp); |
| |
| double viewportXScaleMax(SEXP vp); |
| |
| double viewportYScaleMin(SEXP vp); |
| |
| double viewportYScaleMax(SEXP vp); |
| |
| double viewportHJust(SEXP v); |
| |
| double viewportVJust(SEXP vp); |
| |
| SEXP viewportLayoutPosRow(SEXP vp); |
| |
| SEXP viewportLayoutPosCol(SEXP vp); |
| |
| SEXP viewportLayout(SEXP vp); |
| |
| SEXP viewportParent(SEXP vp); |
| |
| SEXP viewportTransform(SEXP vp); |
| |
| SEXP viewportLayoutWidths(SEXP vp); |
| |
| SEXP viewportLayoutHeights(SEXP vp); |
| |
| SEXP viewportWidthCM(SEXP vp); |
| |
| SEXP viewportHeightCM(SEXP vp); |
| |
| SEXP viewportRotation(SEXP vp); |
| |
| SEXP viewportParent(SEXP vp); |
| |
| SEXP viewportChildren(SEXP vp); |
| |
| SEXP viewportDevWidthCM(SEXP vp); |
| |
| SEXP viewportDevHeightCM(SEXP vp); |
| |
| void fillViewportContextFromViewport(SEXP vp, LViewportContext *vpc); |
| |
| void copyViewportContext(LViewportContext vpc1, LViewportContext *vpc2); |
| |
| void gcontextFromViewport(SEXP vp, const pGEcontext gc, pGEDevDesc dd); |
| |
| void calcViewportTransform(SEXP vp, SEXP parent, Rboolean incremental, |
| pGEDevDesc dd); |
| |
| void initVP(pGEDevDesc dd); |
| |
| /* From layout.c */ |
| Rboolean checkPosRowPosCol(SEXP viewport, SEXP parent); |
| |
| void calcViewportLayout(SEXP viewport, |
| double parentWidthCM, |
| double parentHeightCM, |
| LViewportContext parentContext, |
| const pGEcontext parentgc, |
| pGEDevDesc dd); |
| |
| void calcViewportLocationFromLayout(SEXP layoutPosRow, |
| SEXP layoutPosCol, |
| SEXP parent, |
| LViewportLocation *vpl); |
| |
| /* From state.c */ |
| void initDL(pGEDevDesc dd); |
| |
| SEXP gridStateElement(pGEDevDesc dd, int elementIndex); |
| |
| void setGridStateElement(pGEDevDesc dd, int elementIndex, SEXP value); |
| |
| SEXP gridCallback(GEevent task, pGEDevDesc dd, SEXP data); |
| |
| extern int gridRegisterIndex; |
| |
| |
| /* From grid.c */ |
| SEXP doSetViewport(SEXP vp, |
| Rboolean topLevelVP, |
| Rboolean pushing, |
| pGEDevDesc dd); |
| |
| void getDeviceSize(pGEDevDesc dd, double *devWidthCM, double *devHeightCM); |
| |
| /* This is, confusingly, a wrapper for GEcurrentDevice */ |
| pGEDevDesc getDevice(); |
| |
| void dirtyGridDevice(pGEDevDesc dd); |
| |
| void getViewportTransform(SEXP currentvp, |
| pGEDevDesc dd, |
| double *vpWidthCM, double *vpHeightCM, |
| LTransform transform, double *rotationAngle); |
| |
| SEXP L_circleBounds(SEXP x, SEXP y, SEXP r, SEXP theta); |
| SEXP L_locnBounds(SEXP x, SEXP y, SEXP theta); |
| SEXP L_rectBounds(SEXP x, SEXP y, SEXP w, SEXP h, SEXP hjust, SEXP vjust, |
| SEXP theta); |
| SEXP L_textBounds(SEXP label, SEXP x, SEXP y, |
| SEXP hjust, SEXP vjust, SEXP rot, SEXP theta); |
| SEXP L_xsplineBounds(SEXP x, SEXP y, SEXP s, SEXP o, SEXP a, SEXP rep, |
| SEXP index, SEXP theta); |
| SEXP L_xsplinePoints(SEXP x, SEXP y, SEXP s, SEXP o, SEXP a, SEXP rep, |
| SEXP index, SEXP theta); |
| |
| /* From unit.c */ |
| SEXP validUnits(SEXP units); |
| |
| /* From gpar.c */ |
| SEXP L_getGPar(void); |
| SEXP L_setGPar(SEXP gpars); |
| |