Copyright (C) Kevin Larke 2009-2020

This file is part of libcm.

libcm 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 3 of the License, or (at your option) any later version.

libcm 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.

See the GNU General Public License distributed with the libcm package or look here: .


cmGr : Low level device independent API for descibing interactive graphics objects.
enum 
{
  kAliceBlueGrId            = 0xf0f8ff,
  kAntiqueWhiteGrId         = 0xfaebd7,
  kAquaGrId                 = 0x00ffff,
  kAquamarineGrId           = 0x7fffd4,
  kAzureGrId                = 0xf0ffff,
  kBeigeGrId                = 0xf5f5dc,
  kBisqueGrId               = 0xffe4c4,
  kBlackGrId                = 0x000000,
  kBlanchedAlmondGrId       = 0xffebcd,
  kBlueGrId                 = 0x0000ff,
  kBlueVioletGrId           = 0x8a2be2,
  kBrownGrId                = 0xa52a2a,
  kBurlyWoodGrId            = 0xdeb887,
  kCadetBlueGrId            = 0x5f9ea0,
  kChartreuseGrId           = 0x7fff00,
  kChocolateGrId            = 0xd2691e,
  kCoralGrId                = 0xff7f50,
  kCornflowerBlueGrId       = 0x6495ed,
  kCornsilkGrId             = 0xfff8dc,
  kCrimsonGrId              = 0xdc143c,
  kCyanGrId                 = 0x00ffff,
  kDarkBlueGrId             = 0x00008b,
  kDarkCyanGrId             = 0x008b8b,
  kDarkGoldenRodGrId        = 0xb8860b,
  kDarkGrayGrId             = 0xa9a9a9,
  kDarkGreyGrId             = 0xa9a9a9,
  kDarkGreenGrId            = 0x006400,
  kDarkKhakiGrId            = 0xbdb76b,
  kDarkMagentaGrId          = 0x8b008b,
  kDarkOliveGreenGrId       = 0x556b2f,
  kDarkorangeGrId           = 0xff8c00,
  kDarkOrchidGrId           = 0x9932cc,
  kDarkRedGrId              = 0x8b0000,
  kDarkSalmonGrId           = 0xe9967a,
  kDarkSeaGreenGrId         = 0x8fbc8f,
  kDarkSlateBlueGrId        = 0x483d8b,
  kDarkSlateGrayGrId        = 0x2f4f4f,
  kDarkSlateGreyGrId        = 0x2f4f4f,
  kDarkTurquoiseGrId        = 0x00ced1,
  kDarkVioletGrId           = 0x9400d3,
  kDeepPinkGrId             = 0xff1493,
  kDeepSkyBlueGrId          = 0x00bfff,
  kDimGrayGrId              = 0x696969,
  kDimGreyGrId              = 0x696969,
  kDodgerBlueGrId           = 0x1e90ff,
  kFireBrickGrId            = 0xb22222,
  kFloralWhiteGrId          = 0xfffaf0,
  kForestGreenGrId          = 0x228b22,
  kFuchsiaGrId              = 0xff00ff,
  kGainsboroGrId            = 0xdcdcdc,
  kGhostWhiteGrId           = 0xf8f8ff,
  kGoldGrId                 = 0xffd700,
  kGoldenRodGrId            = 0xdaa520,
  kGrayGrId                 = 0x808080,
  kGreyGrId                 = 0x808080,
  kGreenGrId                = 0x008000,
  kGreenYellowGrId          = 0xadff2f,
  kHoneyDewGrId             = 0xf0fff0,
  kHotPinkGrId              = 0xff69b4,
  kIndianRedGrId            = 0xcd5c5c,
  kIndigoGrId               = 0x4b0082,
  kIvoryGrId                = 0xfffff0,
  kKhakiGrId                = 0xf0e68c,
  kLavenderGrId             = 0xe6e6fa,
  kLavenderBlushGrId        = 0xfff0f5,
  kLawnGreenGrId            = 0x7cfc00,
  kLemonChiffonGrId         = 0xfffacd,
  kLightBlueGrId            = 0xadd8e6,
  kLightCoralGrId           = 0xf08080,
  kLightCyanGrId            = 0xe0ffff,
  kLightGoldenRodYellowGrId = 0xfafad2,
  kLightGrayGrId            = 0xd3d3d3,
  kLightGreyGrId            = 0xd3d3d3,
  kLightGreenGrId           = 0x90ee90,
  kLightPinkGrId            = 0xffb6c1,
  kLightSalmonGrId          = 0xffa07a,
  kLightSeaGreenGrId        = 0x20b2aa,
  kLightSkyBlueGrId         = 0x87cefa,
  kLightSlateGrayGrId       = 0x778899,
  kLightSlateGreyGrId       = 0x778899,
  kLightSteelBlueGrId       = 0xb0c4de,
  kLightYellowGrId          = 0xffffe0,
  kLimeGrId                 = 0x00ff00,
  kLimeGreenGrId            = 0x32cd32,
  kLinenGrId                = 0xfaf0e6,
  kMagentaGrId              = 0xff00ff,
  kMaroonGrId               = 0x800000,
  kMediumAquaMarineGrId     = 0x66cdaa,
  kMediumBlueGrId           = 0x0000cd,
  kMediumOrchidGrId         = 0xba55d3,
  kMediumPurpleGrId         = 0x9370d8,
  kMediumSeaGreenGrId       = 0x3cb371,
  kMediumSlateBlueGrId      = 0x7b68ee,
  kMediumSpringGreenGrId    = 0x00fa9a,
  kMediumTurquoiseGrId      = 0x48d1cc,
  kMediumVioletRedGrId      = 0xc71585,
  kMidnightBlueGrId         = 0x191970,
  kMintCreamGrId            = 0xf5fffa,
  kMistyRoseGrId            = 0xffe4e1,
  kMoccasinGrId             = 0xffe4b5,
  kNavajoWhiteGrId          = 0xffdead,
  kNavyGrId                 = 0x000080,
  kOldLaceGrId              = 0xfdf5e6,
  kOliveGrId                = 0x808000,
  kOliveDrabGrId            = 0x6b8e23,
  kOrangeGrId               = 0xffa500,
  kOrangeRedGrId            = 0xff4500,
  kOrchidGrId               = 0xda70d6,
  kPaleGoldenRodGrId        = 0xeee8aa,
  kPaleGreenGrId            = 0x98fb98,
  kPaleTurquoiseGrId        = 0xafeeee,
  kPaleVioletRedGrId        = 0xd87093,
  kPapayaWhipGrId           = 0xffefd5,
  kPeachPuffGrId            = 0xffdab9,
  kPeruGrId                 = 0xcd853f,
  kPinkGrId                 = 0xffc0cb,
  kPlumGrId                 = 0xdda0dd,
  kPowderBlueGrId           = 0xb0e0e6,
  kPurpleGrId               = 0x800080,
  kRedGrId                  = 0xff0000,
  kRosyBrownGrId            = 0xbc8f8f,
  kRoyalBlueGrId            = 0x4169e1,
  kSaddleBrownGrId          = 0x8b4513,
  kSalmonGrId               = 0xfa8072,
  kSandyBrownGrId           = 0xf4a460,
  kSeaGreenGrId             = 0x2e8b57,
  kSeaShellGrId             = 0xfff5ee,
  kSiennaGrId               = 0xa0522d,
  kSilverGrId               = 0xc0c0c0,
  kSkyBlueGrId              = 0x87ceeb,
  kSlateBlueGrId            = 0x6a5acd,
  kSlateGrayGrId            = 0x708090,
  kSlateGreyGrId            = 0x708090,
  kSnowGrId                 = 0xfffafa,
  kSpringGreenGrId          = 0x00ff7f,
  kSteelBlueGrId            = 0x4682b4,
  kTanGrId                  = 0xd2b48c,
  kTealGrId                 = 0x008080,
  kThistleGrId              = 0xd8bfd8,
  kTomatoGrId               = 0xff6347,
  kTurquoiseGrId            = 0x40e0d0,
  kVioletGrId               = 0xee82ee,
  kWheatGrId                = 0xf5deb3,
  kWhiteGrId                = 0xffffff,
  kWhiteSmokeGrId           = 0xf5f5f5,
  kYellowGrId               = 0xffff00,
  kYellowGreenGrId          = 0x9acd32
};


typedef enum
{
  kHomeGrId = 5,        // 5
  kPageUpGrId,          // 6
  kEndGrId,             // 7
  kBackSpaceGrId = 8,   // 8
  kTabGrId       = 9,   // 9 
  kPageDownGrId,        // 10
  kLeftGrId,            // 11
  kUpGrId,              // 12
  kEnterGrId  = 13,     // 13
  kRightGrId,           // 14
  kDownGrId,            // 15
  kInsertGrId,          // 16
  kPrintGrId,           // 17
  kScrollLockGrId,      // 18
  kPauseGrId,           // 19
  kMenuGrId,            // 20
  kLShiftGrId,          // 21
  kRShiftGrId,          // 22
  kLCtrlGrId,           // 23
  kRCtrlGrId,           // 24
  kLAltGrId,            // 25
  kRAltGrId,            // 26
  kEscapeGrId = 27,     // 27
  kLSuperGrId,          // 28
  kRSuperGrId,          // 29
  kNumLockGrId,         // 30
  kCapsLockGrId,        // 31
  kSpaceGrId     = 32,  // 32 Min. printable ASCII
  kExclMarkGrId,        // 33
  kDQuoteGrId,          // 34
  kPoundGrId,           // 35
  kDollarGrId,          // 36
  kPercentGrId,         // 37
  kAmpersandGrId,       // 38
  kApostropheGrId,      // 39
  kLParenGrId,          // 40
  kRParenGrId,          // 41
  kAsteriskGrId,        // 42 
  kPlusGrId,            // 43
  kCommaGrId,           // 44
  kHyphenGrId,          // 45
  kPeriodGrId,          // 46
  kForwardSlashGrId,    // 47
  k0GrId,               // 48
  k1GrId,               // 49
  k2GrId,               // 50
  k3GrId,               // 51
  k4GrId,               // 52
  k5GrId,               // 53 
  k6GrId,               // 54
  k7GrId,               // 55
  k8GrId,               // 56
  k9GrId,               // 57
  kColonGrId,           // 58 
  kSemiColonGrId,       // 59
  kLesserGrId,          // 60
  kEqualGrId,           // 61
  kGreaterGrId,         // 62
  kQMarkGrId,           // 63
  kAtGrId,              // 64
  kA_GrId,              // 65
  kB_GrId,              // 66
  kC_GrId,              // 67
  kD_GrId,              // 68
  kE_GrId,              // 69
  kF_GrId,              // 70
  kG_GrId,              // 71
  kH_GrId,              // 72
  kI_GrId,              // 73
  kJ_GrId,              // 74
  kK_GrId,              // 75
  kL_GrId,              // 76
  kM_GrId,              // 77
  kN_GrId,              // 78
  kO_GrId,              // 79
  kP_GrId,              // 80
  kQ_GrId,              // 81
  kR_GrId,              // 82
  kS_GrId,              // 83
  kT_GrId,              // 84
  kU_GrId,              // 85
  kV_GrId,              // 86
  kW_GrId,              // 87
  kX_GrId,              // 88
  kY_GrId,              // 89
  kZ_GrId,              // 90
  kLBracketGrId,        // 91
  kBackSlashGrId,       // 92
  kRBracketGrId,        // 93
  kCaretGrId,           // 94
  kUnderScoreGrId,      // 95
  kAccentGrId,          // 96
  ka_GrId,              // 97
  kb_GrId,              // 98 
  kc_GrId,              // 99 
  kd_GrId,              // 100
  ke_GrId,              // 101
  kf_GrId,              // 102
  kg_GrId,              // 103
  kh_GrId,              // 104
  ki_GrId,              // 105
  kj_GrId,              // 106
  kk_GrId,              // 107
  kl_GrId,              // 108
  km_GrId,              // 109
  kn_GrId,              // 110
  ko_GrId,              // 111
  kp_GrId,              // 112
  kq_GrId,              // 113
  kr_GrId,              // 114
  ks_GrId,              // 115
  kt_GrId,              // 116
  ku_GrId,              // 117
  kv_GrId,              // 118
  kw_GrId,              // 119
  kx_GrId,              // 120
  ky_GrId,              // 121
  kz_GrId,              // 122
  kLBraceGrId,          // 123
  kPipeGrId,            // 124
  kRBraceGrId,          // 125
  kTildeGrId,           // 126
  kDeleteGrId,          // 127
  kNP_MultGrId,         // 128
  kNP_PlusGrId,         // 129
  kNP_MinusGrId,        // 130
  kNP_DecPtGrId,        // 131
  kNP_DivGrId,          // 132
  kNP_0GrId,            // 133
  kNP_1GrId,            // 134
  kNP_2GrId,            // 135
  kNP_3GrId,            // 136
  kNP_4GrId,            // 137
  kNP_5GrId,            // 138
  kNP_6GrId,            // 139
  kNP_7GrId,            // 140
  kNP_8GrId,            // 141
  kNP_9GrId,            // 142
  kNP_EqualGrId,        // 143
  kNP_EnterGrId,        // 144
  kFunc_1GrId,          // 145
  kFunc_2GrId,          // 146
  kFunc_3GrId,          // 147
  kFunc_4GrId,          // 148 
  kFunc_5GrId,          // 149
  kFunc_6GrId,          // 150
  kFunc_7GrId,          // 151
  kFunc_8GrId,          // 152
  kFunc_9GrId,          // 153
  kFunc_10GrId,         // 154
  kFunc_11GrId,         // 155
  kFunc_12GrId,         // 156
  kBrightUpGrId,        // 157
  kBrightDnGrId,        // 158
  kAudio_PrevGrId,      // 159
  kAudio_PlayGrId,      // 160
  kAudio_NextGrId,      // 161
  kAudio_MuteGrId,      // 162
  kAudio_UpGrId,        // 163
  kAudio_DnGrId,        // 164
  kEjectGrId,           // 165
  kInvalidKeyCodeGrId
} cmGrKeyCodeId_t;

enum
{
  kMinAsciiGrId = kSpaceGrId,
  kMaxAsciiGrId = kDeleteGrId
};

enum
{
  kOkGrRC,
  kLHeapFailGrRC,
  kAppErrGrRC,
  kRootObjCreateFailGrRC,
  kInvalidCoordsGrRC,
  kExtsErrGrRC
};

enum
{
  kLeftGrFl   = 0x01,
  kTopGrFl    = 0x02,
  kRightGrFl  = 0x04,
  kBottomGrFl = 0x08,
};

typedef enum
{
  kLeftGrIdx   = 0,    // min-x
  kTopGrIdx    = 1,    // max-y
  kRightGrIdx  = 2,    // max-x
  kBottomGrIdx = 3,    // min-y
  kAxisGrCnt   = 4
} cmGrAxisIdx_t;


typedef cmHandle_t cmGrH_t;
typedef cmHandle_t cmGrObjH_t;
typedef cmHandle_t cmGrDcH_t;
typedef unsigned   cmGrRC_t;

extern cmGrH_t     cmGrNullHandle;
extern cmGrObjH_t  cmGrObjNullHandle;

typedef cmReal_t cmGrV_t;


// Calculate the width and height between two pixels. // This implies that the first and last pixel are inside the valid range. #define cmGrXtoW(x0,x1) (abs((x1)-(x0))+1) #define cmGrWtoX(x0,w) (((x0)+(w))-1) #define cmGrYtoH(y0,y1) (abs((y1)-(y0))+1) #define cmGrHtoY(y0,h) (((y0)+(h))-1) #define cmGrPIsXInRange(x,x0,w) ((x0)<=(x)&&(x)<=cmGrWtoX((x0),(w))) #define cmGrPIsYInRange(y,y0,h) ((y0)<=(y)&&(y)<=cmGrHtoY((y0),(h))) #define cmGrVIsXInRange(x,x0,w) ((x0)<=(x)&&(x)<=((x0)+(w))) #define cmGrVIsYInRange(y,y0,h) ((y0)<=(y)&&(y)<=((y0)+(h))) typedef struct { int x; int y; } cmGrPPt_t; #define cmGrPPtSet( p, xx, yy ) do{ (p)->x=(xx); (p)->y=(yy); }while(0) #define cmGrPPtIsEqual(p0,p1) ((p0)->x==(p1)->x && (p0)->y==(p1)->y) #define cmGrPPtPrint(lbl,p) printf("%s x=%i y=%i\n",(lbl),(p)->x,(p)->y)
typedef struct { int w; int h; } cmGrPSz_t; #define cmGrPSzSet( s, ww, hh ) do{ (s)->w=(ww); (s)->h=(hh);}while(0) #define cmGrPSzSetD( s, x0, y0, x1, y1 ) cmGrPSzSet(cmGrXtoW(x0,x1),cmGrYtoH(y0,y1)) #define cmGrPSzSetEmpty( s ) ((s)->w = (s)->h = 0) #define cmGrPSzSetNull( s ) ((s)->w = (s)->h = -1) #define cmGrPSzIsEmpty( s ) ((s)->w== 0 && (s)->h== 0) #define cmGrPSzIsNull( s ) ((s)->w==-1 && (s)->h==-1) #define cmGrPSzIsEqual(s0,s1) ((s0)->w==(s1)->w && (s0)->h==(s1)->h) #define cmGrPSzPrint(lbl,s) printf("%s w=%i h=%i\n",(lbl),(s)->w,(s)->h)
typedef struct { cmGrPPt_t loc; cmGrPSz_t sz; } cmGrPExt_t; #define cmGrPExtSet( e, x, y, w, h ) do{ cmGrPPtSet(&(e)->loc,(x),(y)); cmGrPSzSet(&(e)->sz,(w),(h)); }while(0) #define cmGrPExtSetD(e, x0, y0, x1, y1) cmGrPExtSet(e,cmMin(x0,x1),cmMin(y0,y1),cmGrXtoW(x0,x1),cmGrYtoH(y0,y1)) #define cmGrPExtL(e) ((e)->loc.x) #define cmGrPExtT(e) ((e)->loc.y) #define cmGrPExtR(e) (cmGrWtoX((e)->loc.x,(e)->sz.w)) #define cmGrPExtB(e) (cmGrHtoY((e)->loc.y,(e)->sz.h)) #define cmGrPExtW(e) ((e)->sz.w) #define cmGrPExtH(e) ((e)->sz.h) #define cmGrPExtSetL(e,v) ((e)->loc.x = (v)) #define cmGrPExtSetT(e,v) ((e)->loc.y = (v)) #define cmGrPExtSetR(e,v) cmGrPExtSetW(e,cmGrXtoW((e)->loc.x,(v))) #define cmGrPExtSetB(e,v) cmGrPExtSetH(e,cmGrYtoH((e)->loc.y,(v))) #define cmGrPExtSetW(e,v) ((e)->sz.w = (v)) #define cmGrPExtSetH(e,v) ((e)->sz.h = (v)) #define cmGrPExtCtrX(e) ((e)->loc.x + (e)->sz.w / 2) #define cmGrPExtCtrY(e) ((e)->loc.y + (e)->sz.h / 2) #define cmGrPExtCtr(e,pt) do{ (pt)->x=cmGrPExtCtrX(e); (pt)->y=cmGrPExtCtrY(e); }while(0) #define cmGrPExtSetEmpty( e ) do{ cmGrPSzSetEmpty(&(e)->sz); cmGrPPtSet(&(e)->loc,0,0); }while(0) #define cmGrPExtSetNull( e ) do{ cmGrPSzSetNull( &(e)->sz); cmGrPPtSet(&(e)->loc,0,0); }while(0) #define cmGrPExtIsEmpty( e ) cmGrPSzIsEmpty( &(e)->sz ) #define cmGrPExtIsNull( e ) cmGrPSzIsNull( &(e)->sz ) #define cmGrPExtIsNullOrEmpty(e) (cmGrPExtIsNull(e)||cmGrPExtIsEmpty(e)) #define cmGrPExtIsNotEmpty(e) (!cmGrPExtIsEmpty(e)) #define cmGrPExtIsNotNull(e) (!cmGrPExtIsNull(e)) #define cmGrPExtIsNotNullOrEmpty(e) (cmGrPExtIsNotNull(e)&&cmGrPExtIsNotEmpty(e)) #define cmGrPExtIsEqual( e0, e1 ) (cmGrPPtIsEqual(&(e0)->loc,&(e1)->loc) && cmGrPSzIsEqual(&(e0)->sz, &(e1)->sz)) #define cmGrPExtIsXyInside( e, xx, yy) (cmGrPIsXInRange((xx),(e)->loc.x,(e)->sz.w) && cmGrPIsYInRange((yy), (e)->loc.y, (e)->sz.h) ) #define cmGrPExtIsPtInside( e, pt ) (cmGrPExtIsXyInside((e),(pt)->x,(pt)->y)) #define cmGrPExtIsExtInside(e0, e1) (cmGrPExtIsPtInside((e0),&((e1)->loc)) && cmGrPExtIsXyInside((e0), cmGrWtoX((e1)->loc.x,(e1)->sz.w), cmGrHtoY((e1)->loc.y,(e1)->sz.h))) #define cmGrPExtExpand(e,l,t,r,b) do{(e)->loc.x+=(l); (e)->loc.y+=(t); (e)->sz.w+=(abs(l)+abs(r)); (e)->sz.h+=(abs(t)+abs(b));}while(0) #define cmGrPExtRpt(e,rpt) cmRptPrintf(rpt,"x:%i y:%i w:%i h:%i",(e)->loc.x,(e)->loc.y,(e)->sz.w,(e)->sz.h) #define cmGrPExtPrint(lbl,e) printf("%s %i %i %i %i\n",lbl,(e)->loc.x,(e)->loc.y,(e)->sz.w,(e)->sz.h) void cmGrPExtIntersect( cmGrPExt_t* r, const cmGrPExt_t* e0, const cmGrPExt_t* e1 );
typedef struct { cmGrV_t x; cmGrV_t y; } cmGrVPt_t; #define cmGrVPtSet( p, xx, yy ) do{ (p)->x=(xx); (p)->y=(yy); }while(0) #define cmGrVPtIsEqual(p0,p1) ((p0)->x==(p1)->x && (p0)->y==(p1)->y) #define cmGrVPtIsNotEqual(p0,p1) (!cmGrVPtIsEqual(p0,p1))
typedef struct { cmGrV_t w; cmGrV_t h; } cmGrVSz_t; #define cmGrVSzSet( s, ww, hh ) do{ (s)->w=(ww); (s)->h=(hh);}while(0) #define cmGrVSzSetD( s, x0, y0, x1, y1 ) cmGrVSzSet((x1)-(x0),(y1)-(y0)) #define cmGrVSzSetEmpty( s ) ((s)->w = (s)->h = 0) #define cmGrVSzSetNull( s ) ((s)->w = (s)->h = -1) #define cmGrVSzIsEmpty( s ) ((s)->w== 0 && (s)->h== 0) #define cmGrVSzIsNull( s ) ((s)->w==-1 || (s)->h==-1) #define cmGrVSzIsEqual(s0,s1) ((s0)->w==(s1)->w && (s0)->h==(s1)->h)
typedef struct { cmGrVPt_t loc; cmGrVSz_t sz; } cmGrVExt_t; #define cmGrVExtIsNorm( e ) ((e)->sz.w>=0 && (e)->sz.h>=0) #define cmGrVExtNorm( e ) do{ if( cmGrVExtIsNotNull(e) ){ if((e)->sz.w<0){(e)->loc.x += (e)->sz.w; (e)->sz.w*=-1;} if((e)->sz.h<0){(e)->loc.y += (e)->sz.h; (e)->sz.h*=-1;}} }while(0) #define cmGrVExtSet( e, x, y, w, h ) do{ cmGrVPtSet(&(e)->loc,(x),(y)); cmGrVSzSet(&(e)->sz,(w),(h)); cmGrVExtNorm(e); }while(0) #define cmGrVExtSetD(e, x0, y0, x1, y1) cmGrVExtSet((e),(x0),(y0),(x1)-(x0),(y1)-(y0)) // // l,t minx,maxy // r,b maxx,miny // #define cmGrVExtMinX(e) ((e)->loc.x) #define cmGrVExtMinY(e) ((e)->loc.y) #define cmGrVExtMaxX(e) ((e)->loc.x + (e)->sz.w) #define cmGrVExtMaxY(e) ((e)->loc.y + (e)->sz.h) #define cmGrVExtW(e) ((e)->sz.w) #define cmGrVExtH(e) ((e)->sz.h) #define cmGrVExtSetMinX(e,v) ((e)->loc.x = (v)) #define cmGrVExtSetMinY(e,v) ((e)->loc.y = (v)) // Beware: setting maxx and maxy depends on the current value of minx and miny. // If both minx and maxx are being changed then be sure to set minx first. // If both miny and maxy are being changed then be sure to set miny first. #define cmGrVExtSetMaxX(e,v) ((e)->sz.w = (v) - cmGrVExtMinX(e)) #define cmGrVExtSetMaxY(e,v) ((e)->sz.h = (v) - cmGrVExtMinY(e)) #define cmGrVExtSetW(e,v) ((e)->sz.w = (v)) #define cmGrVExtSetH(e,v) ((e)->sz.h = (v)) #define cmGrVExtSetEmpty( e ) do{ cmGrVSzSetEmpty(&(e)->sz); cmGrVPtSet(&(e)->loc,0,0); }while(0) #define cmGrVExtSetNull( e ) do{ cmGrVSzSetNull(&(e)->sz); cmGrVPtSet(&(e)->loc,0,0); }while(0) #define cmGrVExtIsEmpty( e ) cmGrVSzIsEmpty(&(e)->sz) #define cmGrVExtIsNull( e ) cmGrVSzIsNull( &(e)->sz) #define cmGrVExtIsNullOrEmpty(e) (cmGrVExtIsNull(e)||cmGrVExtIsEmpty(e)) #define cmGrVExtIsNotEmpty(e) (!cmGrVExtIsEmpty(e)) #define cmGrVExtIsNotNull(e) (!cmGrVExtIsNull(e)) #define cmGrVExtIsNotNullOrEmpty(e) (cmGrVExtIsNotNull(e)&&cmGrVExtIsNotEmpty(e)) #define cmGrVExtIsEqual( e0, e1 ) (cmGrVPtIsEqual(&(e0)->loc,&(e1)->loc) && cmGrVSzIsEqual(&(e0)->sz, &(e1)->sz)) #define cmGrVExtIsXyInside( e, xx, yy) (cmGrVIsXInRange((xx),(e)->loc.x,(e)->sz.w) && cmGrVIsYInRange((yy),(e)->loc.y,(e)->sz.h)) #define cmGrVExtIsPtInside( e, pt ) (cmGrVExtIsXyInside((e),(pt)->x,(pt)->y)) // e1 is inside e0 #define cmGrVExtIsExtInside(e0, e1) (cmGrVExtIsXyInside((e0),cmGrVExtMinX(e1),cmGrVExtMinY(e1)) && cmGrVExtIsXyInside((e0), cmGrVExtMaxX(e1), cmGrVExtMaxY(e1))) #define cmGrVExtRpt(e,rpt) cmRptPrintf(rpt,"x:%f y:%f w:%f h:%f",(e)->loc.x,(e)->loc.y,(e)->sz.w,(e)->sz.h) #define cmGrVExtPrint(lbl,e) printf("%s %f %f %f %f\n",lbl,(e)->loc.x,(e)->loc.y,(e)->sz.w,(e)->sz.h) // Shift and expand e0 to contain e1. Return true if e0 actually changes. bool cmGrVExtExpandToContain( cmGrVExt_t* e0, const cmGrVExt_t* e1 ); // Force e1 to be contained by e0 by shifting e1's location. This function // will never change the width or height of e1. Return true if e1 is changed. bool cmGrVExtContain( const cmGrVExt_t* e0, cmGrVExt_t* e1 ); // Return the intersection of 'e0' with 'e1' in 'r'. void cmGrVExtIntersect( cmGrVExt_t* r, const cmGrVExt_t* e0, const cmGrVExt_t* e1 );
#define cmGrRgbToColor( r, g, b ) (((r) << 16) + ((g) << 8) + (b)) #define cmGrColorToR( c ) (((c) >> 16) & 0x000000ff) #define cmGrColorToG( c ) (((c) >> 8) & 0x000000ff) #define cmGrColorToB( c ) (((c) ) & 0x000000ff) typedef unsigned cmGrColor_t; enum { kGrDefaultColorMapIdx = 0, kGrDefaultColorMapId=0 }; unsigned cmGrColorMapCount( cmGrH_t grH ); unsigned cmGrColorMapId( cmGrH_t grH, unsigned mapIdx ); const cmChar_t* cmGrColorMapLabel( cmGrH_t grH, unsigned id ); unsigned cmGrColorMapRegister( cmGrH_t grH, cmChar_t* label, const cmGrColor_t* array, unsigned cnt ); cmGrColor_t* cmGrColorMap( cmGrH_t grH, unsigned mapId ); unsigned cmGrColorMapEleCount( cmGrH_t grH, unsigned mapId );
typedef struct { cmCtx_t* ctx; // application context cmGrH_t grH; // graphics system handle to which this graphic object belongs cmGrObjH_t objH; // this graphics object handle void* cbArg; // user callback arg cmGrPPt_t msDnPPt; // mouse down phys point cmGrVPt_t msDnVPt; // mouse down virt point inside op-&gtparent-&gtwext cmGrVSz_t msDnVOffs; // virtual offset from mouse down point to msDnObj-&gtvext cmGrObjH_t msDnObjH; // handle of object which recv'd mouse down cmGrVPt_t msVPt; // cur ms virtual point } cmGrObjFuncArgs_t; typedef cmGrRC_t (*cmGrCreateObjCb_t)( cmGrObjFuncArgs_t* args ); typedef void (*cmGrDestroyObjCb_t)( cmGrObjFuncArgs_t* args ); typedef bool (*cmGrRenderObjCb_t)( cmGrObjFuncArgs_t* args, cmGrDcH_t dcH ); typedef int (*cmGrDistanceObjCb_t)( cmGrObjFuncArgs_t* args, int x, int y ); typedef bool (*cmGrEventObjCb_t)( cmGrObjFuncArgs_t* args, unsigned flags, unsigned key, int px, int py ); typedef void (*cmGrVExtObjCb_t)( cmGrObjFuncArgs_t* args, cmGrVExt_t* vext ); typedef bool (*cmGrIsInsideObjCb_t)( cmGrObjFuncArgs_t* args, unsigned evtFlags, int px, int py, cmGrV_t vx, cmGrV_t vy ); typedef struct cmGrObjFunc_str { // User defined constructor. cmGrCreateObjCb_t createCbFunc; void* createCbArg; // User defined destructor. cmGrDestroyObjCb_t destroyCbFunc; void* destroyCbArg; // Draw the object by calling back to the cmGrDrawXXX() functions cmGrRenderObjCb_t renderCbFunc; void* renderCbArg; // Return the physical distance from a physical view location to the object. // (NOT USED) cmGrDistanceObjCb_t distanceCbFunc; void* distanceCbArg; // Handle an event. gx,gy are in the same coord's as args.objH.vext (they are inside args.objH.parent.wext). // Return true if the event objects dirty flag should be set. cmGrEventObjCb_t eventCbFunc; void* eventCbArg; // Return the objects location and size inside op-&gtparent-&gtwext cmGrVExtObjCb_t vextCbFunc; void* vextCbArg; // Called to determine which object is under the mouse and whether the event can // handle the event as described by the 'evtFlags' args. // Return true if the point is inside this obj. vx,vy is in the the same coord's // as op-&gtvext (i.e. vx,vy is inside op-&gtparent-&gtwext) and the object will accept // the event implied by the 'evtFlags' argument. // The simple answer to this call is cmGrVExtIsXyInside( *vext, vx, vy ). cmGrIsInsideObjCb_t isInsideCbFunc; void* isInsideCbArg; } cmGrObjFunc_t; // Create a graphic object. This function calls the user defined (*create)() function. // ('flags' is not used) cmGrRC_t cmGrObjCreate( cmGrH_t h, cmGrObjH_t* hp, cmGrObjH_t parentH, cmGrObjFunc_t* f, unsigned id, unsigned flags, const cmGrVExt_t* wext ); // Destroy a graphic object and all of it's children. // This function calls the user defined (*destroy)() function. cmGrRC_t cmGrObjDestroy( cmGrH_t h, cmGrObjH_t* hp ); // Return true if 'oh' is a valid handle. cmGrRC_t cmGrObjIsValid( cmGrH_t h, cmGrObjH_t oh ); // Return the user id associated with this object. unsigned cmGrObjId( cmGrObjH_t oh ); void cmGrObjSetId( cmGrObjH_t oh, unsigned id ); // Return the handle to the parent object. cmGrObjH_t cmGrObjParent( cmGrObjH_t oh ); // An object world coord's are used to place child objects. cmGrRC_t cmGrObjSetWorldExt( cmGrH_t h, cmGrObjH_t oh, const cmGrVExt_t* vext ); void cmGrObjWorldExt( cmGrObjH_t oh, cmGrVExt_t* vext ); cmGrRC_t cmGrObjSetWorldLimitExt( cmGrH_t h, cmGrObjH_t oh, const cmGrVExt_t* vext, unsigned limitFlags ); void cmGrObjWorldLimitExt( cmGrObjH_t oh, cmGrVExt_t* vext, unsigned* limitFlags ); void cmGrObjSetCreateCb( cmGrObjH_t oh, cmGrCreateObjCb_t cbFunc, void* cbArg ); void cmGrObjSetDestroyCb( cmGrObjH_t oh, cmGrDestroyObjCb_t cbFunc, void* cbArg ); void cmGrObjSetRenderCb( cmGrObjH_t oh, cmGrRenderObjCb_t cbFunc, void* cbArg ); void cmGrObjSetDistanceCb( cmGrObjH_t oh, cmGrDistanceObjCb_t cbFunc, void* cbArg ); void cmGrObjSetEventCb( cmGrObjH_t oh, cmGrEventObjCb_t cbFunc, void* cbArg ); void cmGrObjSetVExtCb( cmGrObjH_t oh, cmGrVExtObjCb_t cbFunc, void* cbArg ); void cmGrObjSetIsInsideCb( cmGrObjH_t oh, cmGrIsInsideObjCb_t cbFunc, void* cbArg ); cmGrCreateObjCb_t cmGrObjCreateCbFunc( cmGrObjH_t oh ); cmGrDestroyObjCb_t cmGrObjDestroyCbFunc( cmGrObjH_t oh ); cmGrRenderObjCb_t cmGrObjRenderCbFunc( cmGrObjH_t oh ); cmGrDistanceObjCb_t cmGrObjDistanceCbFunc( cmGrObjH_t oh ); cmGrEventObjCb_t cmGrObjEventCbFunc( cmGrObjH_t oh ); cmGrVExtObjCb_t cmGrObjVExtCbFunc( cmGrObjH_t oh ); cmGrIsInsideObjCb_t cmGrObjIsInsideCbFunc( cmGrObjH_t oh ); void* cmGrObjCreateCbArg( cmGrObjH_t oh ); void* cmGrObjDestroyCbArg( cmGrObjH_t oh ); void* cmGrObjRenderCbArg( cmGrObjH_t oh ); void* cmGrObjDistanceCbArg( cmGrObjH_t oh ); void* cmGrObjEventCbArg( cmGrObjH_t oh ); void* cmGrObjVExtCbArg( cmGrObjH_t oh ); void* cmGrObjIsInsideCbArg( cmGrObjH_t oh ); // Same as call to user defined (*vect)(). void cmGrObjLocalVExt( cmGrH_t h, cmGrObjH_t oh, cmGrVExt_t* vext ); // Given an objects id return it's handle. cmGrObjH_t cmGrObjIdToHandle( cmGrH_t h, unsigned id ); // Move 'aoH' such that it is drawn above 'boH' in the z-order. // This means that 'boH' will be drawn before 'aoH'. void cmGrObjDrawAbove( cmGrObjH_t boH, cmGrObjH_t aoH ); void cmGrObjReport( cmGrH_t h, cmGrObjH_t oh, cmRpt_t* rpt ); void cmGrObjReportR( cmGrH_t h, cmGrObjH_t oh, cmRpt_t* rpt ); // print children
// Drawing Functions - called by objects to draw themselves
int cmGrX_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t y ); int cmGrY_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t x ); void cmGrXY_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrPPt_t* rp ); void cmGrXYWH_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrV_t w, cmGrV_t h, cmGrPExt_t* pext ); void cmGrVExt_VtoP( cmGrH_t hh, cmGrObjH_t oh, const cmGrVExt_t* vext, cmGrPExt_t* pext ); void cmGrXY_PtoV( cmGrH_t hh, cmGrObjH_t oh, int x, int y, cmGrVPt_t* rp ); void cmGrXYWH_PtoV( cmGrH_t hh, cmGrObjH_t oh, int x, int y, int w, int h, cmGrVExt_t* vext ); void cmGrPExt_PtoV( cmGrH_t hh, cmGrObjH_t oh, const cmGrPExt_t* pext, cmGrVExt_t* vext ); void cmGrDrawVLine( cmGrH_t hh, cmGrDcH_t dcH, cmGrObjH_t oh, cmGrV_t x0, cmGrV_t y0, cmGrV_t x1, cmGrV_t y1 ); void cmGrDrawVRect( cmGrH_t hh, cmGrDcH_t dcH, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrV_t w, cmGrV_t h );
// Callback identifiers typedef enum { kCreateCbGrId, kDestroyCbGrId, kLocalPtCbGrId, kGlobalPtCbGrId, kPhysExtCbGrId, kViewExtCbGrId, kSelectExtCbGrId, kFocusCbGrId, kKeyUpCbGrId, kKeyDnCbGrId } cmGrCbId_t; // Callback function associated with this canvas. typedef void (*cmGrCbFunc_t)( void* arg, cmGrH_t grH, cmGrCbId_t id, unsigned evtFlags, cmGrKeyCodeId_t keycode ); // Configuration Flags enum { kExpandViewGrFl = 0x01, // expand the view to show new objects kSelectHorzGrFl = 0x02, // select along x-axis only kSelectVertGrFl = 0x04 // select along y-axis only }; // 'wext' is optional. // 'id' is an arbitrary user definable identifier - although it is used // as the view index by cmGrPage(). cmGrRC_t cmGrCreate( cmCtx_t* ctx, cmGrH_t* hp, unsigned id, unsigned cfgFlags, cmGrCbFunc_t cbFunc, void* cbArg, const cmGrVExt_t* wext ); // Optional internal world extents for this object // Destroy this canvas. cmGrRC_t cmGrDestroy( cmGrH_t* hp ); // Remove all objects from the root object and restore the canvas to it's default state. cmGrRC_t cmGrClear( cmGrH_t h ); // Get the root object handle cmGrObjH_t cmGrRootObjH( cmGrH_t h ); // Get and set the configuration flags (e.g. kExpandViewGrFl | kSelectHorzGrFl | kSelectVertHorzGrFl ) unsigned cmGrCfgFlags( cmGrH_t h ); void cmGrSetCfgFlags( cmGrH_t h, unsigned cfgFlags ); // Draw the objects on the canvas. cmGrRC_t cmGrDraw( cmGrH_t h, cmGrDcH_t dcH ); // event flags enum { kMsDownGrFl = 0x0001, kMsUpGrFl = 0x0002, kMsMoveGrFl = 0x0004, kMsWheelGrFl= 0x0008, kMsDragGrFl = 0x0010, kMsClickGrFl= 0x0020, kKeyDnGrFl = 0x0040, kKeyUpGrFl = 0x0080, kMsEvtMask = 0x02f, kEvtMask = 0x00ff, kMsLBtnGrFl = 0x0100, kMsCBtnGrFl = 0x0200, kMsRBtnGrFl = 0x0400, kShiftKeyGrFl = 0x0800, kAltKeyGrFl = 0x1000, kCtlKeyGrFl = 0x2000, }; // Receive a UI event. bool cmGrEvent( cmGrH_t h, unsigned flags, cmGrKeyCodeId_t key, int x, int y ); // Return true if 'h' is valid. bool cmGrIsValid( cmGrH_t h ); // Return the user defined 'id' set in cmGrCreate() unsigned cmGrId( cmGrH_t h ); // Return the last mouse location in root object coordinates. const cmGrVPt_t* cmGrGlobalPt( cmGrH_t h ); // Return the last mouse location in coordinates of the object the mouse was over. const cmGrVPt_t* cmGrLocalPt( cmGrH_t h ); // The new view extents must fit inside the world extents. // Return true if the view extents actually changed. bool cmGrSetViewExtents( cmGrH_t hh, cmGrV_t minx, cmGrV_t miny, cmGrV_t maxx, cmGrV_t maxy ); bool cmGrSetViewExtentsE(cmGrH_t h, const cmGrVExt_t* ext ); void cmGrViewExtents( cmGrH_t h, cmGrVExt_t* exts ); // View Location // Return true if the phys extents actually changed. bool cmGrSetPhysExtents( cmGrH_t hh, int x, int y, int w, int h ); bool cmGrSetPhysExtentsE(cmGrH_t h, const cmGrPExt_t* ext ); void cmGrPhysExtents( cmGrH_t h, cmGrPExt_t* exts ); // Return some scroll bar values for this canvas. // tot=world pixels, vis=vis pixels, max=max scroll pos pos=cur scroll pos // All return values are optional. void cmGrScrollExtents( cmGrH_t h, cmGrPSz_t* tot, cmGrPSz_t* vis, cmGrPSz_t* max, cmGrPPt_t* pos ); // Return true if the view location actually changed. bool cmGrSetScrollH( cmGrH_t h, int x ); int cmGrScrollH( cmGrH_t h ); bool cmGrSetScrollV( cmGrH_t h, int y ); int cmGrScrollV( cmGrH_t h ); // Get the current selection extents. // If the selection extents are not valid then the function returns false // and sets the return extents to their null state. bool cmGrSelectExtents( cmGrH_t h, cmGrVExt_t* vext, cmGrPExt_t* pext ); // Both pts are optional void cmGrSetSelectPoints(cmGrH_t h, const cmGrVPt_t* pt0, const cmGrVPt_t* pt1 ); void cmGrSelectPoints( cmGrH_t h, cmGrVPt_t* pt0, cmGrVPt_t* pt1 ); enum { kZoomInGrFl=0x01, kXAxisGrFl=0x02, kYAxisGrFl=0x04, kSelectGrFl=0x08, kShowAllGrFl=0x10 }; // 1) If kSelectGrFl is not set then the center 1/3 of the current view // becomes the new view. // 2) If kSelectGrFl is set then the selection area becomes the view. // 3) If kSelectGrFl is set but no selection area exists then // option 1) is selected used and using the selection point as center. void cmGrZoom( cmGrH_t h, unsigned flags ); // Synchronize the 'syncGrH' horz. and/or verical, world,view,select extents to // this gr's extents. Changes to this gr's extents will be automatically // applied to 'syncGrH'. // If 'syncGrH' was used in a previous call to this function then flags will // modify the previously set flags value. // Clear the kHorzSyncFl and kVertSyncFl to disable the synchronization. // Set flags to 0 to prevent future sync calls. enum { kWorldSyncGrFl=0x01, kViewSyncGrFl=0x02, kSelectSyncGrFl=0x04, kHorzSyncGrFl=0x08, kVertSyncGrFl=0x10 }; void cmGrSetSync( cmGrH_t h, cmGrH_t syncGrH, unsigned flags ); void cmGrReport( cmGrH_t h, cmRpt_t* rpt );