libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmGr.c 66KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmLinkedHeap.h"
  9. #include "cmGr.h"
  10. #include "cmGrDevCtx.h"
  11. // cmGr_t state flags
  12. enum
  13. {
  14. kDirtyGrFl = 0x01 // the cmGr object is dirty
  15. };
  16. // cmGrObj_t state flags
  17. enum
  18. {
  19. kDirtyObjFl = 0x0001, // this object is dirty
  20. kFocusObjFl = 0x0002, // this object has focus
  21. kSelectObjFl = 0x0004, // this object is selected
  22. kPhysRelObjFl = 0x0008, // use physical instead of virtual offset
  23. };
  24. typedef struct cmGrObj_str
  25. {
  26. unsigned id; //
  27. unsigned cfgFlags; //
  28. unsigned stateFlags; //
  29. cmGrObjFunc_t f; //
  30. cmGrVExt_t wext; // world coord's contained within this object (children of this object are contained by these extents)
  31. unsigned wlimitFlags; // kLeftGrFl | kRightGrFl | kTopGrFl | kBottomGrFl
  32. cmGrVExt_t wlimitExt; // limit extents for wext (ext's with set flags always define the associated wext value)
  33. struct cmGrObj_str* parent;
  34. struct cmGrObj_str* children;
  35. struct cmGrObj_str* rsib;
  36. struct cmGrObj_str* lsib;
  37. } cmGrObj_t;
  38. typedef struct cmGrSync_str
  39. {
  40. cmGrH_t grH;
  41. unsigned flags; // kGrXXXSyncGrFl
  42. struct cmGrSync_str* link;
  43. } cmGrSync_t;
  44. typedef struct cmGrColorMap_str
  45. {
  46. const cmChar_t* label;
  47. unsigned id;
  48. cmGrColor_t* map;
  49. unsigned cnt;
  50. struct cmGrColorMap_str* link;
  51. } cmGrColorMap_t;
  52. typedef struct cmGrKeyMap_str
  53. {
  54. unsigned idx; // index of this keymap entry (used for debugging)
  55. char ascii; // printible ascii character associated with this keycode or 0 if not printable
  56. cmGrKeyCodeId_t keycode; // cmGr keycode
  57. } cmGrKeyMap_t;
  58. typedef struct
  59. {
  60. cmCtx_t ctx;
  61. cmErr_t err;
  62. unsigned id; // user definable id
  63. cmLHeapH_t lhH;
  64. unsigned cfgFlags;
  65. unsigned stateFlags;
  66. cmGrObj_t* msDnObj; // obj under last ms dn
  67. cmGrPPt_t msDnPPt; // last ms dn loc'n
  68. cmGrVPt_t msDnVPt; // last ms dn in same coords as msDnObj->vext (inside msDnObj->parent->wxt)
  69. cmGrVPt_t msVPt; // cur ms pt in same coords as msDnObj->vext (inside msDnObj->parent->wxt)
  70. cmGrVSz_t msDnVOffs;
  71. bool selValidFl;
  72. cmGrVPt_t sel0Pt;
  73. cmGrVPt_t sel1Pt;
  74. cmGrVPt_t localPt;
  75. cmGrVPt_t globalPt;
  76. cmGrVExt_t vext; // view virtual extents
  77. cmGrPExt_t pext; // view physical extents
  78. cmGrObj_t* objs; // object tree
  79. cmGrObj_t* rootObj; // current root object
  80. unsigned char* img; // temporary image inversion buffer
  81. cmGrCbFunc_t cbFunc; //
  82. void* cbArg; //
  83. cmGrSync_t* syncs; //
  84. cmGrColorMap_t* maps; // color maps
  85. } cmGr_t;
  86. cmGrH_t cmGrNullHandle = cmSTATIC_NULL_HANDLE;
  87. cmGrObjH_t cmGrObjNullHandle = cmSTATIC_NULL_HANDLE;
  88. cmGrKeyMap_t _cmGrKeyMap[] =
  89. {
  90. { 0, 0, 0 },
  91. { 1, 0, 0 },
  92. { 2, 0, 0 },
  93. { 3, 0, 0 },
  94. { 4, 0, 0 },
  95. { 5, 0, kHomeGrId},
  96. { 6, 0, kPageUpGrId},
  97. { 7, 0, kEndGrId},
  98. { 8, 8, kBackSpaceGrId },
  99. { 9, 9, kTabGrId },
  100. { 10, 0, kPageDownGrId},
  101. { 11, 0, kLeftGrId},
  102. { 12, 0, kUpGrId},
  103. { 13, 13, kEnterGrId },
  104. { 14, 0, kRightGrId},
  105. { 15, 0, kDownGrId},
  106. { 16, 0, kInsertGrId},
  107. { 17, 0, kPrintGrId},
  108. { 18, 0, kScrollLockGrId},
  109. { 19, 0, kPauseGrId},
  110. { 20, 0, kMenuGrId},
  111. { 21, 0, kLShiftGrId},
  112. { 22, 0, kRShiftGrId},
  113. { 23, 0, kLCtrlGrId},
  114. { 24, 0, kRCtrlGrId},
  115. { 25, 0, kLAltGrId},
  116. { 26, 0, kRAltGrId},
  117. { 27, 27, kEscapeGrId },
  118. { 28, 0, kLSuperGrId},
  119. { 29, 0, kRSuperGrId},
  120. { 30, 0, kNumLockGrId},
  121. { 31, 0, kCapsLockGrId},
  122. { 32, 32, kSpaceGrId },
  123. { 33, 33, kExclMarkGrId },
  124. { 34, 34, kDQuoteGrId },
  125. { 35, 35, kPoundGrId },
  126. { 36, 36, kDollarGrId },
  127. { 37, 37, kPercentGrId },
  128. { 38, 38, kAmpersandGrId },
  129. { 39, 39, kApostropheGrId },
  130. { 40, 40, kLParenGrId },
  131. { 41, 41, kRParenGrId },
  132. { 42, 42, kAsteriskGrId },
  133. { 43, 43, kPlusGrId },
  134. { 44, 44, kCommaGrId },
  135. { 45, 45, kHyphenGrId },
  136. { 46, 46, kPeriodGrId },
  137. { 47, 47, kForwardSlashGrId },
  138. { 48, 48, k0GrId },
  139. { 49, 49, k1GrId },
  140. { 50, 50, k2GrId },
  141. { 51, 51, k3GrId },
  142. { 52, 52, k4GrId },
  143. { 53, 53, k5GrId },
  144. { 54, 54, k6GrId },
  145. { 55, 55, k7GrId },
  146. { 56, 56, k8GrId },
  147. { 57, 57, k9GrId },
  148. { 58, 58, kColonGrId },
  149. { 59, 59, kSemiColonGrId },
  150. { 60, 60, kLesserGrId },
  151. { 61, 61, kEqualGrId },
  152. { 62, 62, kGreaterGrId },
  153. { 63, 63, kQMarkGrId },
  154. { 64, 64, kAtGrId },
  155. { 65, 65, kA_GrId },
  156. { 66, 66, kB_GrId },
  157. { 67, 67, kC_GrId },
  158. { 68, 68, kD_GrId },
  159. { 69, 69, kE_GrId },
  160. { 70, 70, kF_GrId },
  161. { 71, 71, kG_GrId },
  162. { 72, 72, kH_GrId },
  163. { 73, 73, kI_GrId },
  164. { 74, 74, kJ_GrId },
  165. { 75, 75, kK_GrId },
  166. { 76, 76, kL_GrId },
  167. { 77, 77, kM_GrId },
  168. { 78, 78, kN_GrId },
  169. { 79, 79, kO_GrId },
  170. { 80, 80, kP_GrId },
  171. { 81, 81, kQ_GrId },
  172. { 82, 82, kR_GrId },
  173. { 83, 83, kS_GrId },
  174. { 84, 84, kT_GrId },
  175. { 85, 85, kU_GrId },
  176. { 86, 86, kV_GrId },
  177. { 87, 87, kW_GrId },
  178. { 88, 88, kX_GrId },
  179. { 89, 89, kY_GrId },
  180. { 90, 90, kZ_GrId },
  181. { 91, 91, kLBracketGrId },
  182. { 92, 92, kBackSlashGrId },
  183. { 93, 93, kRBracketGrId },
  184. { 94, 94, kCaretGrId },
  185. { 95, 95, kUnderScoreGrId },
  186. { 96, 96, kAccentGrId },
  187. { 97, 97, ka_GrId },
  188. { 98, 98, kb_GrId },
  189. { 99, 99, kc_GrId },
  190. { 100, 100, kd_GrId },
  191. { 101, 101, ke_GrId },
  192. { 102, 102, kf_GrId },
  193. { 103, 103, kg_GrId },
  194. { 104, 104, kh_GrId },
  195. { 105, 105, ki_GrId },
  196. { 106, 106, kj_GrId },
  197. { 107, 107, kk_GrId },
  198. { 108, 108, kl_GrId },
  199. { 109, 109, km_GrId },
  200. { 110, 110, kn_GrId },
  201. { 111, 111, ko_GrId },
  202. { 112, 112, kp_GrId },
  203. { 113, 113, kq_GrId },
  204. { 114, 114, kr_GrId },
  205. { 115, 115, ks_GrId },
  206. { 116, 116, kt_GrId },
  207. { 117, 117, ku_GrId },
  208. { 118, 118, kv_GrId },
  209. { 119, 119, kw_GrId },
  210. { 120, 120, kx_GrId },
  211. { 121, 121, ky_GrId },
  212. { 122, 122, kz_GrId },
  213. { 123, 123, kLBraceGrId },
  214. { 124, 124, kPipeGrId },
  215. { 125, 125, kRBraceGrId },
  216. { 126, 126, kTildeGrId },
  217. { 127, 127, kDeleteGrId },
  218. { 128, 42, kNP_MultGrId },
  219. { 129, 43, kNP_PlusGrId },
  220. { 130, 45, kNP_MinusGrId },
  221. { 131, 46, kNP_DecPtGrId},
  222. { 132, 47, kNP_DivGrId},
  223. { 133, 48, kNP_0GrId},
  224. { 134, 49, kNP_1GrId},
  225. { 135, 50, kNP_2GrId},
  226. { 136, 51, kNP_3GrId},
  227. { 137, 52, kNP_4GrId},
  228. { 138, 53, kNP_5GrId},
  229. { 139, 54, kNP_6GrId},
  230. { 140, 55, kNP_7GrId},
  231. { 141, 56, kNP_8GrId},
  232. { 142, 57, kNP_9GrId},
  233. { 143, 61, kNP_EqualGrId},
  234. { 144, 13, kNP_EnterGrId},
  235. { 145, 0, kFunc_1GrId},
  236. { 146, 0, kFunc_2GrId},
  237. { 147, 0, kFunc_3GrId},
  238. { 148, 0, kFunc_4GrId},
  239. { 149, 0, kFunc_5GrId},
  240. { 150, 0, kFunc_6GrId},
  241. { 151, 0, kFunc_7GrId},
  242. { 152, 0, kFunc_8GrId},
  243. { 153, 0, kFunc_9GrId},
  244. { 154, 0, kFunc_10GrId},
  245. { 155, 0, kFunc_11GrId},
  246. { 156, 0, kFunc_12GrId},
  247. { 157, 0, kBrightUpGrId},
  248. { 158, 0, kBrightDnGrId},
  249. { 159, 0, kAudio_PrevGrId},
  250. { 160, 0, kAudio_PlayGrId},
  251. { 161, 0, kAudio_NextGrId},
  252. { 162, 0, kAudio_MuteGrId},
  253. { 163, 0, kAudio_DnGrId },
  254. { 164, 0, kAudio_UpGrId },
  255. { 165, 0, kEjectGrId },
  256. { cmInvalidIdx, 0, cmInvalidId}
  257. };
  258. void _cmGrKeyMapValidate()
  259. {
  260. unsigned i;
  261. for(i=0; _cmGrKeyMap[i].idx != cmInvalidIdx; ++i)
  262. {
  263. assert( _cmGrKeyMap[i].idx == i );
  264. }
  265. }
  266. cmGrKeyMap_t* _cmGrFindKeyMap( unsigned keycode )
  267. {
  268. // printable ascii codes match their indexes
  269. if( 32 <= keycode && keycode <= 126 )
  270. return _cmGrKeyMap + keycode;
  271. unsigned i;
  272. for(i=0; i<32; ++i)
  273. if( _cmGrKeyMap[i].keycode == keycode )
  274. return _cmGrKeyMap + i;
  275. for(i=127; _cmGrKeyMap[i].idx != cmInvalidIdx; ++i)
  276. if( _cmGrKeyMap[i].keycode == keycode )
  277. return _cmGrKeyMap + i;
  278. assert(0);
  279. return NULL;
  280. }
  281. bool _cmGrSetViewExtents( cmGr_t* p, cmGrV_t minx, cmGrV_t miny, cmGrV_t maxx, cmGrV_t maxy );
  282. bool _cmGrSetViewExtentsE( cmGr_t* p, const cmGrVExt_t* e )
  283. { return _cmGrSetViewExtents(p, cmGrVExtMinX(e), cmGrVExtMinY(e), cmGrVExtMaxX(e), cmGrVExtMaxY(e) ); }
  284. //====================================================================================================
  285. // Expand cmGrVExt_t e0 to hold e1.
  286. // Return true if e0 is actually changed.
  287. bool cmGrVExtExpandToContain(cmGrVExt_t* e0, const cmGrVExt_t* e1)
  288. {
  289. bool fl = false;
  290. if( cmGrVExtIsNullOrEmpty(e0) )
  291. {
  292. *e0 = *e1;
  293. return true;
  294. }
  295. assert( cmGrVExtIsNorm(e0) && cmGrVExtIsNorm(e1) );
  296. // min-x
  297. if( cmGrVExtMinX(e0) > cmGrVExtMinX(e1) )
  298. {
  299. cmGrVExtSetMinX(e0, cmGrVExtMinX(e1));
  300. fl = true;
  301. }
  302. // min-y
  303. if( cmGrVExtMinY(e0) > cmGrVExtMinY(e1) )
  304. {
  305. cmGrVExtSetMinY(e0, cmGrVExtMinY(e1));
  306. fl = true;
  307. }
  308. // max-y
  309. if( cmGrVExtMaxY(e0) < cmGrVExtMaxY(e1) )
  310. {
  311. cmGrVExtSetMaxY(e0, cmGrVExtMaxY(e1));
  312. fl = true;
  313. }
  314. // max-x
  315. if( cmGrVExtMaxX(e0) < cmGrVExtMaxX(e1) )
  316. {
  317. cmGrVExtSetMaxX(e0, cmGrVExtMaxX(e1));
  318. fl = true;
  319. }
  320. return fl;
  321. }
  322. bool cmGrVExtContain( const cmGrVExt_t* e0, cmGrVExt_t* e1 )
  323. {
  324. bool fl = false;
  325. assert( cmGrVExtIsNorm(e0) && cmGrVExtIsNorm(e1) );
  326. // e1 must be able to fit inside e0
  327. assert( e1->sz.w <= e0->sz.w && e1->sz.h <= e0->sz.h );
  328. // if left edge of e1 is to left of e0
  329. if( cmGrVExtMinX(e1) < cmGrVExtMinX(e0) )
  330. {
  331. cmGrVExtSetMinX(e1,cmGrVExtMinX(e0));
  332. fl = true;
  333. }
  334. // if right edge of e1 is to right of e0
  335. if( cmGrVExtMaxX(e1) > cmGrVExtMaxX(e0) )
  336. {
  337. cmGrVExtSetMaxX(e1,cmGrVExtMaxX(e0));
  338. fl = true;
  339. }
  340. // if the bottom edge of e1 is below the bottom edge of e0
  341. if( cmGrVExtMinY(e1) < cmGrVExtMinY(e0) )
  342. {
  343. cmGrVExtSetMinY(e1,cmGrVExtMinY(e0));
  344. fl = true;
  345. }
  346. // if top edge of e1 is above the top edge of e0
  347. if( cmGrVExtMaxY(e1) > cmGrVExtMaxY(e0) )
  348. {
  349. cmGrVExtSetMaxY(e1,cmGrVExtMaxY(e0));
  350. fl = true;
  351. }
  352. return fl;
  353. }
  354. void cmGrPExtIntersect( cmGrPExt_t* r, const cmGrPExt_t* e0, const cmGrPExt_t* e1 )
  355. {
  356. if( cmGrPExtR(e0) < cmGrPExtL(e1) || cmGrPExtL(e0) > cmGrPExtR(e1)
  357. || cmGrPExtB(e0) < cmGrPExtT(e1) || cmGrPExtT(e0) > cmGrPExtB(e1) )
  358. {
  359. cmGrPExtSetEmpty(r);
  360. return;
  361. }
  362. cmGrPExtSetD(r,
  363. cmMax( cmGrPExtL(e0), cmGrPExtL(e1) ),
  364. cmMax( cmGrPExtT(e0), cmGrPExtT(e1) ),
  365. cmMin( cmGrPExtR(e0), cmGrPExtR(e1) ),
  366. cmMin( cmGrPExtB(e0), cmGrPExtB(e1) ) );
  367. }
  368. void cmGrVExtIntersect( cmGrVExt_t* r, const cmGrVExt_t* e0, const cmGrVExt_t* e1 )
  369. {
  370. if( cmGrVExtMaxX(e0) < cmGrVExtMinX(e1) || cmGrVExtMinX(e0) > cmGrVExtMaxX(e1)
  371. || cmGrVExtMaxY(e0) < cmGrVExtMinY(e1) || cmGrVExtMinY(e0) > cmGrVExtMaxY(e1) )
  372. {
  373. cmGrVExtSetEmpty(r);
  374. return;
  375. }
  376. cmGrVExtSetD(r,
  377. cmMax( cmGrVExtMinX(e0), cmGrVExtMinX(e1) ),
  378. cmMax( cmGrVExtMinY(e0), cmGrVExtMinY(e1) ),
  379. cmMin( cmGrVExtMaxX(e0), cmGrVExtMaxX(e1) ),
  380. cmMin( cmGrVExtMaxY(e0), cmGrVExtMaxY(e1) ) );
  381. }
  382. //====================================================================================================
  383. //====================================================================================================
  384. cmGr_t* _cmGrHandleToPtr( cmGrH_t h )
  385. {
  386. cmGr_t* p = (cmGr_t*)h.h;
  387. assert( p != NULL );
  388. return p;
  389. }
  390. cmGrObj_t* _cmGrObjHandleToPtr( cmGrObjH_t h )
  391. {
  392. cmGrObj_t* p = (cmGrObj_t*)h.h;
  393. assert( p != NULL );
  394. return p;
  395. }
  396. //====================================================================================================
  397. unsigned cmGrColorMapCount( cmGrH_t grH )
  398. {
  399. cmGr_t* p = _cmGrHandleToPtr(grH);
  400. cmGrColorMap_t* cmp = p->maps;
  401. unsigned n = 0;
  402. for(; cmp!=NULL; cmp=cmp->link)
  403. ++n;
  404. return n;
  405. }
  406. cmGrColorMap_t* _cmGrColorMapFromIndex( cmGr_t* p, unsigned idx )
  407. {
  408. unsigned i = 0;
  409. cmGrColorMap_t* cmp = p->maps;
  410. for(; cmp!=NULL; ++i,cmp=cmp->link)
  411. if( i == idx )
  412. break;
  413. return cmp;
  414. }
  415. cmGrColorMap_t* _cmGrColorMapFromId( cmGr_t* p, unsigned id )
  416. {
  417. cmGrColorMap_t* cmp = p->maps;
  418. for(; cmp!=NULL; cmp=cmp->link)
  419. if( cmp->id == id )
  420. break;
  421. return cmp;
  422. }
  423. unsigned cmGrColorMapId( cmGrH_t grH, unsigned mapIdx )
  424. {
  425. cmGr_t* p = _cmGrHandleToPtr(grH);
  426. cmGrColorMap_t* cmp;
  427. if((cmp = _cmGrColorMapFromIndex(p,mapIdx)) == NULL )
  428. return cmInvalidId;
  429. return cmp->id;
  430. }
  431. const cmChar_t* cmGrColorMapLabel( cmGrH_t grH, unsigned id )
  432. {
  433. cmGr_t* p = _cmGrHandleToPtr(grH);
  434. cmGrColorMap_t* cmp;
  435. if((cmp = _cmGrColorMapFromId(p,id)) == NULL )
  436. return NULL;
  437. return cmp->label;
  438. }
  439. unsigned _cmGrColorMapRegister( cmGr_t* p, cmChar_t* label, const cmGrColor_t* array, unsigned cnt )
  440. {
  441. // locate an available id
  442. unsigned id = 0;
  443. while( _cmGrColorMapFromId(p,id)!=NULL )
  444. ++id;
  445. cmGrColorMap_t* cmp = cmLhAllocZ(p->lhH,cmGrColorMap_t,1);
  446. cmp->label = cmLhAllocStr(p->lhH,label);
  447. cmp->id = id;
  448. cmp->map = cmLhAllocZ(p->lhH,cmGrColor_t,cnt);
  449. cmp->cnt = cnt;
  450. cmp->link = p->maps;
  451. p->maps = cmp;
  452. memcpy(cmp->map,array,sizeof(cmGrColor_t)*cnt);
  453. return id;
  454. }
  455. unsigned cmGrColorMapRegister( cmGrH_t grH, cmChar_t* label, const cmGrColor_t* array, unsigned cnt )
  456. { return _cmGrColorMapRegister( _cmGrHandleToPtr(grH),label, array, cnt ); }
  457. cmGrColor_t* cmGrColorMap( cmGrH_t grH, unsigned mapId )
  458. {
  459. cmGr_t* p = _cmGrHandleToPtr(grH);
  460. cmGrColorMap_t* cmp;
  461. if((cmp = _cmGrColorMapFromId(p,mapId)) == NULL )
  462. return NULL;
  463. return cmp->map;
  464. }
  465. unsigned cmGrColorMapEleCount( cmGrH_t grH, unsigned mapId )
  466. {
  467. cmGr_t* p = _cmGrHandleToPtr(grH);
  468. cmGrColorMap_t* cmp;
  469. if((cmp = _cmGrColorMapFromId(p,mapId)) == NULL )
  470. return cmInvalidId;
  471. return cmp->cnt;
  472. }
  473. void _cmGrRgbInitDefaultColorMap( cmGr_t* p )
  474. {
  475. unsigned map[] =
  476. {
  477. 0x000000, // black
  478. 0x00008b, // dark blue
  479. 0x0000ff, // blue
  480. 0x008080, // teal
  481. 0x00ffff, // cyan
  482. 0x00ff7f, // spring green
  483. 0x00ff00, // green
  484. 0x7cfc00, // lawn green
  485. 0xffff00, // yellow
  486. 0xff7f7f, // pink
  487. 0xff00ff, // magenta
  488. 0xff007f, //
  489. 0xff0000, // red
  490. 0x7f0000, //
  491. 0xffffff // white
  492. };
  493. unsigned n = sizeof(map)/sizeof(unsigned);
  494. _cmGrColorMapRegister(p,"default",map,n);
  495. }
  496. //====================================================================================================
  497. // Object Callback Functions
  498. //====================================================================================================
  499. void _cmGrObjSetupFuncArgs( cmGrObjFuncArgs_t* a, cmGr_t* p, cmGrObj_t* op )
  500. {
  501. cmGrH_t h;
  502. cmGrObjH_t oh;
  503. h.h = p;
  504. oh.h = op;
  505. a->ctx = &p->ctx;
  506. a->grH = h;
  507. a->objH = oh;
  508. a->msDnPPt = p->msDnPPt;
  509. a->msDnVPt = p->msDnVPt;
  510. a->msDnVOffs = p->msDnVOffs;
  511. a->msVPt = p->msVPt;
  512. oh.h = p->msDnObj;
  513. a->msDnObjH = oh;
  514. }
  515. cmGrRC_t _cmGrObjCbCreate( cmGr_t* p, cmGrObj_t* op )
  516. {
  517. cmGrRC_t rc = kOkGrRC;
  518. if( op->f.createCbFunc != NULL )
  519. {
  520. cmGrObjFuncArgs_t a;
  521. _cmGrObjSetupFuncArgs(&a,p,op);
  522. a.cbArg = op->f.createCbArg;
  523. if((rc = op->f.createCbFunc(&a)) != kOkGrRC )
  524. rc = cmErrMsg(&p->err,kAppErrGrRC,"An application object (id=%i) failed on 'create'",op->id);
  525. }
  526. return rc;
  527. }
  528. void _cmGrObjCbDestroy( cmGr_t* p, cmGrObj_t* op )
  529. {
  530. if( op->f.destroyCbFunc != NULL )
  531. {
  532. cmGrObjFuncArgs_t a;
  533. _cmGrObjSetupFuncArgs(&a,p,op);
  534. a.cbArg = op->f.destroyCbArg;
  535. op->f.destroyCbFunc(&a);
  536. }
  537. }
  538. void _cmGrObjCbRender( cmGr_t* p, cmGrDcH_t dcH, const cmGrObj_t* op )
  539. {
  540. if( op->f.renderCbFunc != NULL )
  541. {
  542. cmGrObjFuncArgs_t a;
  543. _cmGrObjSetupFuncArgs(&a,p,(cmGrObj_t*)op);
  544. a.cbArg = op->f.renderCbArg;
  545. op->f.renderCbFunc(&a, dcH );
  546. }
  547. }
  548. int _cmGrObjCbDistance( cmGr_t* p, const cmGrObj_t* op, int px, int py )
  549. {
  550. int d = INT_MAX;
  551. if( op->f.distanceCbFunc != NULL )
  552. {
  553. cmGrObjFuncArgs_t a;
  554. _cmGrObjSetupFuncArgs(&a,p,(cmGrObj_t*)op);
  555. a.cbArg = op->f.distanceCbArg;
  556. d = op->f.distanceCbFunc(&a,px,py);
  557. }
  558. return d;
  559. }
  560. bool _cmGrObjCbEvent( cmGr_t* p, cmGrObj_t* op, unsigned flags, unsigned key, int px, int py )
  561. {
  562. bool fl = false;
  563. if( op->f.eventCbFunc != NULL )
  564. {
  565. cmGrObjFuncArgs_t a;
  566. _cmGrObjSetupFuncArgs(&a,p,op);
  567. a.cbArg = op->f.eventCbArg;
  568. fl = op->f.eventCbFunc(&a,flags,key,px,py);
  569. }
  570. return fl;
  571. }
  572. void _cmGrObjCbVExt( cmGr_t* p, const cmGrObj_t* op, cmGrVExt_t* vext )
  573. {
  574. if( op->f.vextCbFunc == NULL )
  575. cmGrVExtSetEmpty(vext);
  576. else
  577. {
  578. cmGrObjFuncArgs_t a;
  579. _cmGrObjSetupFuncArgs(&a,p,(cmGrObj_t*)op);
  580. a.cbArg = op->f.vextCbArg;
  581. op->f.vextCbFunc(&a,vext);
  582. }
  583. }
  584. bool _cmGrObjCbIsInside( cmGr_t* p, const cmGrObj_t* op, int px, int py, cmGrV_t vx, cmGrV_t vy )
  585. {
  586. bool fl = false;
  587. if( op->f.isInsideCbFunc != NULL )
  588. {
  589. cmGrObjFuncArgs_t a;
  590. _cmGrObjSetupFuncArgs(&a,p,(cmGrObj_t*)op);
  591. a.cbArg = op->f.isInsideCbArg;
  592. fl = op->f.isInsideCbFunc(&a,px,py,vx,vy);
  593. }
  594. return fl;
  595. }
  596. //====================================================================================================
  597. // Object Private Functions
  598. //====================================================================================================
  599. // Return true if pp is an ancestor (parent,grand-parent,great-grand-parent,...) of cp.
  600. bool _cmGrObjIsAncestor( cmGrObj_t* pp, cmGrObj_t* cp )
  601. {
  602. cmGrObj_t* tp = cp->parent;
  603. for(; tp != NULL; tp=tp->parent )
  604. if( tp == pp )
  605. break;
  606. return tp!=NULL;
  607. }
  608. // Append 'op' as the right-most child of 'pp'.
  609. void _cmGrObjAppendChild( cmGrObj_t* pp, cmGrObj_t* cp)
  610. {
  611. cp->parent = pp;
  612. if( pp->children == NULL )
  613. {
  614. pp->children = cp;
  615. cp->lsib = NULL;
  616. cp->rsib = NULL;
  617. }
  618. else
  619. {
  620. cmGrObj_t* op = pp->children;
  621. while( op->rsib != NULL )
  622. op = op->rsib;
  623. op->rsib = cp;
  624. cp->rsib = NULL;
  625. cp->lsib = op;
  626. }
  627. }
  628. // Insert 'op' on the left of 'rp'.
  629. void _cmGrObjInsertOnLeft( cmGrObj_t* op, cmGrObj_t* rp )
  630. {
  631. op->parent = rp->parent;
  632. op->rsib = rp;
  633. op->lsib = rp->lsib;
  634. if( rp->lsib == NULL )
  635. {
  636. assert( rp->parent == rp->parent->children);
  637. rp->parent->children = op;
  638. }
  639. else
  640. {
  641. rp->lsib->rsib = op;
  642. }
  643. rp->lsib = op;
  644. }
  645. // Insert 'op' on the right of 'lp'.
  646. // 'pp' is the parent of 'lp'. 'pp' must be given explicitely to cover
  647. // the case where lp is NULL - in which case the new parent for op
  648. // cannot be determined from lp.
  649. void _cmGrObjInsertOnRight( cmGrObj_t* op, cmGrObj_t* lp, cmGrObj_t* pp )
  650. {
  651. op->parent = pp;
  652. if( lp == NULL )
  653. {
  654. assert( pp != NULL && pp->children==NULL );
  655. pp->children = op;
  656. op->lsib = NULL;
  657. op->rsib = NULL;
  658. return;
  659. }
  660. assert( lp->parent == pp );
  661. op->lsib = lp;
  662. op->rsib = lp->rsib;
  663. if( lp->rsib != NULL )
  664. lp->rsib->lsib = op;
  665. lp->rsib = op;
  666. }
  667. // Unlink 'op' from the tree but leave it's children attached.
  668. void _cmGrObjUnlink( cmGrObj_t * op )
  669. {
  670. if( op->parent != NULL && op->parent->children == op )
  671. op->parent->children = op->parent->children->rsib;
  672. if( op->rsib != NULL )
  673. op->rsib->lsib = op->lsib;
  674. if( op->lsib != NULL )
  675. op->lsib->rsib = op->rsib;
  676. op->parent = NULL;
  677. op->rsib = NULL;
  678. op->lsib = NULL;
  679. }
  680. // Free 'op' and all of its children.
  681. // 'op' must be unlinked before calling this function
  682. cmGrRC_t _cmGrObjFree( cmGr_t* p, cmGrObj_t* op )
  683. {
  684. cmGrRC_t rc = kOkGrRC;
  685. // go to the deepest child
  686. if( op->children != NULL )
  687. if((rc = _cmGrObjFree(p,op->children)) != kOkGrRC )
  688. return rc;
  689. // go right
  690. if( op->rsib != NULL )
  691. if((rc = _cmGrObjFree(p,op->rsib)) != kOkGrRC )
  692. return rc;
  693. // inform the application that we are destroying this object
  694. _cmGrObjCbDestroy(p,op);
  695. _cmGrObjUnlink(op);
  696. cmMemFree(op);
  697. return rc;
  698. }
  699. cmGrRC_t _cmGrObjUnlinkAndFree( cmGr_t* p, cmGrObj_t* op )
  700. {
  701. cmGrRC_t rc = kOkGrRC;
  702. cmGrObj_t* rsib = op->rsib;
  703. cmGrObj_t* par = op->parent;
  704. _cmGrObjUnlink(op);
  705. // if the free fails ...
  706. if((rc = _cmGrObjFree(p,op)) != kOkGrRC )
  707. {
  708. // ... then restore the objects position
  709. if( rsib == NULL )
  710. _cmGrObjInsertOnLeft(op,rsib);
  711. else
  712. _cmGrObjAppendChild(par,op);
  713. }
  714. return rc;
  715. }
  716. // Return kL,T,R,BGrFl indicating which directions of wext are in violation of op->wlimitExt.
  717. // Return's 0 if no limits are in violation
  718. unsigned _cmGrObjWorldLimitsTestViolation( const cmGrObj_t* op, const cmGrVExt_t* wext )
  719. {
  720. unsigned violFlags = 0;
  721. if( cmIsFlag( op->wlimitFlags, kLeftGrFl) )
  722. if( cmGrVExtMinX(wext) < cmGrVExtMinX(&op->wlimitExt) )
  723. violFlags = kLeftGrFl;
  724. if( cmIsFlag( op->wlimitFlags, kTopGrFl) )
  725. if( cmGrVExtMaxY(wext) < cmGrVExtMaxY(&op->wlimitExt) )
  726. violFlags = kTopGrFl;
  727. if( cmIsFlag( op->wlimitFlags, kRightGrFl) )
  728. if( cmGrVExtMaxX(wext) > cmGrVExtMaxX(&op->wlimitExt) )
  729. violFlags = kRightGrFl;
  730. if( cmIsFlag( op->wlimitFlags, kBottomGrFl) )
  731. if( cmGrVExtMinY(wext) > cmGrVExtMinY(&op->wlimitExt) )
  732. violFlags = kBottomGrFl;
  733. return violFlags;
  734. }
  735. // If op has world extent limits then apply them to 'ext'.
  736. // Extent directions in 'ext' which do not have limits in 'op' are unchanged.
  737. // Extent directions in 'ext' which have limits are set to the limit.
  738. void _cmGrObjApplyExtLimits( cmGrObj_t* op, cmGrVExt_t* ext )
  739. {
  740. if( cmIsFlag(op->wlimitFlags,kLeftGrFl) )
  741. cmGrVExtSetMinX(ext,cmGrVExtMinX(&op->wlimitExt));
  742. if( cmIsFlag(op->wlimitFlags,kBottomGrFl) )
  743. cmGrVExtSetMinY(ext,cmGrVExtMinY(&op->wlimitExt));
  744. if( cmIsFlag(op->wlimitFlags,kTopGrFl) )
  745. cmGrVExtSetMaxY(ext,cmGrVExtMaxY(&op->wlimitExt));
  746. if( cmIsFlag(op->wlimitFlags,kRightGrFl) )
  747. cmGrVExtSetMaxX(ext,cmGrVExtMaxX(&op->wlimitExt));
  748. }
  749. // Return the outside extents of the children of 'op'.
  750. // Returns false if there are no children and leaves wext set to NULL.
  751. bool _cmGrObjChildExts( cmGr_t* p, const cmGrObj_t* op, cmGrVExt_t* ext )
  752. {
  753. cmGrVExtSetNull(ext);
  754. op = op->children;
  755. if( op == NULL )
  756. return false;
  757. _cmGrObjCbVExt(p,op,ext);
  758. for(op=op->rsib; op!=NULL; op=op->rsib)
  759. {
  760. cmGrVExt_t e;
  761. _cmGrObjCbVExt(p,op,&e);
  762. cmGrVExtExpandToContain(ext,&e);
  763. }
  764. return true;
  765. }
  766. cmGrRC_t _cmGrObjSetWorldExt( cmGr_t* p, cmGrObj_t* op, const cmGrVExt_t* wext );
  767. // The world extents changed to 'ref_wext' on an object.
  768. // Examine all 'sync'ed' objects and expand them to be contained by 'ref_wext'.
  769. cmGrRC_t _cmGrSyncWorldExtentsExpand( cmGr_t* p, const cmGrVExt_t* ref_wext )
  770. {
  771. cmGrRC_t rc = kOkGrRC;
  772. // apply changes to synch targets
  773. cmGrSync_t* sp = p->syncs;
  774. for(; sp!=NULL; sp=sp->link)
  775. if( cmIsFlag(sp->flags,kWorldSyncGrFl) )
  776. {
  777. // get the target ROOT object
  778. cmGrObj_t* top = _cmGrObjHandleToPtr(cmGrRootObjH(sp->grH));
  779. bool fl = false;
  780. cmGrVExt_t top_wext = top->wext;
  781. //printf("sync %i ",top->id);
  782. //cmGrVExtPrint("top_wext",&top_wext);
  783. //cmGrVExtPrint("ref_wext",ref_wext);
  784. // if horz sync was requested ...
  785. if( !fl && cmIsFlag(sp->flags,kHorzSyncGrFl) )
  786. {
  787. if( cmGrVExtIsNullOrEmpty(&top_wext) )
  788. {
  789. cmGrVExtSetMinX(&top_wext,cmGrVExtMinX(ref_wext));
  790. cmGrVExtSetMaxX(&top_wext,cmGrVExtMaxX(ref_wext));
  791. fl = true;
  792. }
  793. else
  794. {
  795. // ... and the target needs to expand and can expand
  796. if( cmGrVExtMinX(&top_wext) > cmGrVExtMinX(ref_wext) && cmIsNotFlag(top->wlimitFlags,kLeftGrFl) )
  797. {
  798. cmGrVExtSetMinX(&top_wext,cmGrVExtMinX(ref_wext)); // .. expand the view
  799. fl = true;
  800. }
  801. if( cmGrVExtMaxX(&top_wext) < cmGrVExtMaxX(ref_wext) && cmIsNotFlag(top->wlimitFlags,kRightGrFl) )
  802. {
  803. cmGrVExtSetMaxX(&top_wext,cmGrVExtMaxX(ref_wext));
  804. fl = true;
  805. }
  806. }
  807. }
  808. // if vert sync was requested ...
  809. if( !fl && cmIsFlag(sp->flags,kVertSyncGrFl) )
  810. {
  811. if( cmGrVExtIsNullOrEmpty(&top_wext) )
  812. {
  813. cmGrVExtSetMinY(&top_wext,cmGrVExtMinY(ref_wext));
  814. cmGrVExtSetMaxY(&top_wext,cmGrVExtMaxY(ref_wext));
  815. fl = true;
  816. }
  817. else
  818. {
  819. if( cmGrVExtMinY(&top_wext) > cmGrVExtMinY(ref_wext) && cmIsNotFlag(top->wlimitFlags,kBottomGrFl))
  820. {
  821. cmGrVExtSetMinY(&top_wext,cmGrVExtMinY(ref_wext));
  822. fl = true;
  823. }
  824. if( cmGrVExtMaxY(&top_wext) < cmGrVExtMaxY(ref_wext) && cmIsNotFlag(top->wlimitFlags,kTopGrFl) )
  825. {
  826. cmGrVExtSetMaxY(&top_wext,cmGrVExtMaxY(ref_wext));
  827. fl = true;
  828. }
  829. }
  830. }
  831. // If fl is set then top_wext contains an expanded world view
  832. if( fl )
  833. {
  834. //cmGrVExtPrint("out top_wext",&top_wext);
  835. // this call may result in a recursion back into this function
  836. if((rc = _cmGrObjSetWorldExt( _cmGrHandleToPtr(sp->grH), top, &top_wext )) != kOkGrRC )
  837. goto errLabel;
  838. }
  839. }
  840. errLabel:
  841. return rc;
  842. }
  843. cmGrRC_t _cmGrObjSetWorldExt( cmGr_t* p, cmGrObj_t* op, const cmGrVExt_t* wext )
  844. {
  845. cmGrRC_t rc = kOkGrRC;
  846. cmGrVExt_t ce;
  847. cmGrVExt_t we = *wext; // make a copy of the new extents to override the 'const' on 'wext'.
  848. // apply the world ext limits to 'we'.
  849. _cmGrObjApplyExtLimits(op,&we);
  850. assert(cmGrVExtIsNorm(&we)); // assert w/h are positive
  851. // get the extents around all children
  852. if( _cmGrObjChildExts(p, op, &ce ) )
  853. {
  854. // if 'ce' is not entirely inside 'we'
  855. if( cmGrVExtIsExtInside(&we,&ce) == false )
  856. return cmErrMsg(&p->err,kExtsErrGrRC,"The change in world extents would have resulted in child objects outside the requested world extents.");
  857. }
  858. // if world extents are actually changing
  859. if( !cmGrVExtIsEqual(&op->wext,&we) )
  860. {
  861. // update the world extents for this object
  862. op->wext = we;
  863. op->stateFlags = cmSetFlag(op->stateFlags,kDirtyObjFl);
  864. //cmGrVExtPrint(cmTsPrintf("set w: %i ",op->id),&we);
  865. // if this is the root object
  866. if( p->rootObj == op )
  867. {
  868. // this call may result in recursion back into this function
  869. // if two cmGr's are mutual sync targets - an infinite loop
  870. // should be avoided by the cmGrVExtIsEqual() test above.
  871. rc = _cmGrSyncWorldExtentsExpand(p, wext );
  872. }
  873. }
  874. return rc;
  875. }
  876. void _cmGrObjReport( cmGr_t* p, cmGrObj_t* op, cmRpt_t* rpt )
  877. {
  878. cmGrVExt_t vext;
  879. cmRptPrintf(rpt,"id:0x%x cfg:0x%x state:0x%x\n",op->id,op->cfgFlags,op->stateFlags);
  880. _cmGrObjCbVExt( p, op, &vext);
  881. cmGrVExtRpt(&vext,rpt);
  882. cmRptPrintf(rpt,"\n");
  883. }
  884. void _cmGrObjReportR( cmGr_t* p, cmGrObj_t* op, cmRpt_t* rpt)
  885. {
  886. _cmGrObjReport(p, op,rpt);
  887. if( op->children != NULL )
  888. _cmGrObjReport(p,op->children,rpt);
  889. if( op->rsib != NULL )
  890. _cmGrObjReport(p,op->rsib,rpt);
  891. }
  892. //====================================================================================================
  893. cmGrRC_t cmGrObjCreate( cmGrH_t h, cmGrObjH_t* ohp, cmGrObjH_t parentH, cmGrObjFunc_t* f, unsigned id, unsigned flags, const cmGrVExt_t* wext )
  894. {
  895. cmGrRC_t rc;
  896. if((rc = cmGrObjDestroy(h,ohp)) != kOkGrRC )
  897. return rc;
  898. cmGr_t* p = _cmGrHandleToPtr(h);
  899. // allocate the new object
  900. cmGrObj_t* op = cmMemAllocZ(cmGrObj_t,1);
  901. op->id = id;
  902. op->cfgFlags = flags;
  903. op->stateFlags = 0;
  904. op->f = *f;
  905. if( wext != NULL )
  906. {
  907. op->wext = *wext;
  908. if( cmGrVExtIsNotNull(wext) )
  909. cmGrVExtNorm(&op->wext);
  910. }
  911. // if an explicit parent was not provided
  912. // then assign the root object as the parent
  913. if( cmGrObjIsValid(h,parentH) == false )
  914. parentH.h = p->rootObj;
  915. // insert the object into the tree
  916. if( cmGrObjIsValid(h,parentH) )
  917. _cmGrObjAppendChild(_cmGrObjHandleToPtr(parentH),op);
  918. else
  919. {
  920. // no root object exits - so make this obj the root
  921. assert(p->objs == NULL );
  922. p->objs = op;
  923. }
  924. ohp->h = op;
  925. // Notify the application that an object was created.
  926. if((rc = _cmGrObjCbCreate(p,op)) != kOkGrRC )
  927. goto errLabel;
  928. if( f->vextCbFunc != NULL )
  929. {
  930. cmGrVExt_t vext;
  931. cmGrVExtSetEmpty(&vext);
  932. // get the local virtual extents for the new object
  933. cmGrObjLocalVExt(h, *ohp, &vext );
  934. if( cmGrVExtIsNotNullOrEmpty(&vext) )
  935. {
  936. // expand the parents world to contain the new object
  937. if( op->parent != NULL )
  938. {
  939. cmGrVExt_t parent_wext = op->parent->wext;
  940. if( cmGrVExtExpandToContain(&parent_wext,&vext) )
  941. _cmGrObjSetWorldExt(p,op->parent,&parent_wext);
  942. assert( cmGrVExtIsExtInside(&op->parent->wext,&vext) );
  943. }
  944. // if cfg'd to expand the view to contain new objects then do so here
  945. if( op->parent!=NULL && op->parent->parent==NULL && cmIsFlag(p->cfgFlags,kExpandViewGrFl) && cmGrVExtIsExtInside(&p->vext,&vext) == false )
  946. {
  947. cmGrVExt_t v = p->vext;
  948. if( cmGrVExtExpandToContain(&v,&vext) )
  949. _cmGrSetViewExtentsE(p,&v);
  950. assert( cmGrVExtIsExtInside(&op->parent->wext,&p->vext));
  951. }
  952. // if the new object is inside the view extents then mark
  953. // the object as dirty
  954. if( cmGrVExtIsExtInside(&p->vext,&vext) )
  955. op->stateFlags = cmSetFlag(op->stateFlags,kDirtyObjFl);
  956. }
  957. }
  958. errLabel:
  959. if( rc != kOkGrRC )
  960. cmGrObjDestroy(h,ohp);
  961. return rc;
  962. }
  963. cmGrRC_t _cmGrObjDestroy( cmGr_t* p, cmGrObj_t* op )
  964. {
  965. if( op == NULL )
  966. return kOkGrRC;
  967. return _cmGrObjUnlinkAndFree( p, op);
  968. }
  969. cmGrRC_t cmGrObjDestroy( cmGrH_t h, cmGrObjH_t* ohp )
  970. {
  971. cmGrRC_t rc = kOkGrRC;
  972. if( ohp==NULL || cmGrObjIsValid(h,*ohp) == false )
  973. return kOkGrRC;
  974. cmGrObj_t* op = _cmGrObjHandleToPtr(*ohp);
  975. if((rc = _cmGrObjDestroy(_cmGrHandleToPtr(h),op)) != kOkGrRC )
  976. return rc;
  977. ohp->h = NULL;
  978. return rc;
  979. }
  980. cmGrRC_t cmGrObjIsValid( cmGrH_t h, cmGrObjH_t oh )
  981. { return oh.h != NULL; }
  982. unsigned cmGrObjId( cmGrObjH_t oh )
  983. { return _cmGrObjHandleToPtr(oh)->id; }
  984. void cmGrObjSetId( cmGrObjH_t oh, unsigned id )
  985. {
  986. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  987. op->id = id;
  988. }
  989. cmGrObjH_t cmGrObjParent( cmGrObjH_t oh )
  990. {
  991. cmGrObjH_t poh;
  992. poh.h = _cmGrObjHandleToPtr(oh)->parent;
  993. return poh;
  994. }
  995. cmGrRC_t cmGrObjSetWorldExt( cmGrH_t h, cmGrObjH_t oh, const cmGrVExt_t* wext )
  996. {
  997. cmGr_t* p = _cmGrHandleToPtr(h);
  998. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  999. return _cmGrObjSetWorldExt(p,op,wext);
  1000. }
  1001. void cmGrObjWorldExt( cmGrObjH_t oh, cmGrVExt_t* wext )
  1002. {
  1003. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1004. *wext = op->wext;
  1005. }
  1006. cmGrRC_t cmGrObjSetWorldLimitExt( cmGrH_t h, cmGrObjH_t oh, const cmGrVExt_t* vext, unsigned limitFlags )
  1007. {
  1008. cmGrRC_t rc;
  1009. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1010. // store the current world extents
  1011. cmGrVExt_t lext = op->wlimitExt;
  1012. unsigned lfl = op->wlimitFlags;
  1013. // set the new limits
  1014. op->wlimitExt = *vext;
  1015. op->wlimitFlags = limitFlags;
  1016. cmGrVExtNorm(&op->wlimitExt);
  1017. // attempt to apply the current world extents with the new limits
  1018. // (this may fail if their are child objects out of range of the new extents)
  1019. if( cmGrVExtIsNotNull(&op->wext ) )
  1020. {
  1021. if((rc = cmGrObjSetWorldExt(h,oh,&op->wext)) != kOkGrRC )
  1022. {
  1023. // we failed - restore the old limits
  1024. op->wlimitExt = lext;
  1025. op->wlimitFlags = lfl;
  1026. }
  1027. }
  1028. return rc;
  1029. }
  1030. void cmGrObjWorldLimitExt( cmGrObjH_t oh, cmGrVExt_t* vext, unsigned* limitFlags )
  1031. {
  1032. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1033. if( vext != NULL )
  1034. *vext = op->wlimitExt;
  1035. if( limitFlags != NULL )
  1036. *limitFlags = op->wlimitFlags;
  1037. }
  1038. void cmGrObjSetCreateCb( cmGrObjH_t oh, cmGrCreateObjCb_t cbFunc, void* cbArg )
  1039. {
  1040. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1041. op->f.createCbFunc = cbFunc;
  1042. op->f.createCbArg = cbArg;
  1043. }
  1044. void cmGrObjSetDestroyCb( cmGrObjH_t oh, cmGrDestroyObjCb_t cbFunc, void* cbArg )
  1045. {
  1046. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1047. op->f.destroyCbFunc = cbFunc;
  1048. op->f.destroyCbArg = cbArg;
  1049. }
  1050. void cmGrObjSetRenderCb( cmGrObjH_t oh, cmGrRenderObjCb_t cbFunc, void* cbArg )
  1051. {
  1052. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1053. op->f.renderCbFunc = cbFunc;
  1054. op->f.renderCbArg = cbArg;
  1055. }
  1056. void cmGrObjSetDistanceCb( cmGrObjH_t oh, cmGrDistanceObjCb_t cbFunc, void* cbArg )
  1057. {
  1058. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1059. op->f.distanceCbFunc = cbFunc;
  1060. op->f.distanceCbArg = cbArg;
  1061. }
  1062. void cmGrObjSetEventCb( cmGrObjH_t oh, cmGrEventObjCb_t cbFunc, void* cbArg )
  1063. {
  1064. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1065. op->f.eventCbFunc = cbFunc;
  1066. op->f.eventCbArg = cbArg;
  1067. }
  1068. void cmGrObjSetVExtCb( cmGrObjH_t oh, cmGrVExtObjCb_t cbFunc, void* cbArg )
  1069. {
  1070. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1071. op->f.vextCbFunc = cbFunc;
  1072. op->f.vextCbArg = cbArg;
  1073. }
  1074. void cmGrObjSetIsInsideCb( cmGrObjH_t oh, cmGrIsInsideObjCb_t cbFunc, void* cbArg )
  1075. {
  1076. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1077. op->f.isInsideCbFunc = cbFunc;
  1078. op->f.isInsideCbArg = cbArg;
  1079. }
  1080. cmGrCreateObjCb_t cmGrObjCreateCbFunc( cmGrObjH_t oh )
  1081. {
  1082. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1083. return op->f.createCbFunc;
  1084. }
  1085. cmGrDestroyObjCb_t cmGrObjDestroyCbFunc( cmGrObjH_t oh )
  1086. {
  1087. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1088. return op->f.destroyCbFunc;
  1089. }
  1090. cmGrRenderObjCb_t cmGrObjRenderCbFunc( cmGrObjH_t oh )
  1091. {
  1092. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1093. return op->f.renderCbFunc;
  1094. }
  1095. cmGrDistanceObjCb_t cmGrObjDistanceCbFunc( cmGrObjH_t oh )
  1096. {
  1097. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1098. return op->f.distanceCbFunc;
  1099. }
  1100. cmGrEventObjCb_t cmGrObjEventCbFunc( cmGrObjH_t oh )
  1101. {
  1102. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1103. return op->f.eventCbFunc;
  1104. }
  1105. cmGrVExtObjCb_t cmGrObjVExtCbFunc( cmGrObjH_t oh )
  1106. {
  1107. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1108. return op->f.vextCbFunc;
  1109. }
  1110. cmGrIsInsideObjCb_t cmGrObjIsInsideCbFunc( cmGrObjH_t oh )
  1111. {
  1112. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1113. return op->f.isInsideCbFunc;
  1114. }
  1115. void* cmGrObjCreateCbArg( cmGrObjH_t oh )
  1116. {
  1117. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1118. return op->f.createCbArg;
  1119. }
  1120. void* cmGrObjDestroyCbArg( cmGrObjH_t oh )
  1121. {
  1122. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1123. return op->f.createCbArg;
  1124. }
  1125. void* cmGrObjRenderCbArg( cmGrObjH_t oh )
  1126. {
  1127. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1128. return op->f.destroyCbArg;
  1129. }
  1130. void* cmGrObjDistanceCbArg( cmGrObjH_t oh )
  1131. {
  1132. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1133. return op->f.distanceCbArg;
  1134. }
  1135. void* cmGrObjEventCbArg( cmGrObjH_t oh )
  1136. {
  1137. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1138. return op->f.eventCbArg;
  1139. }
  1140. void* cmGrObjVExtCbArg( cmGrObjH_t oh )
  1141. {
  1142. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1143. return op->f.vextCbArg;
  1144. }
  1145. void* cmGrObjIsInsideCbArg( cmGrObjH_t oh )
  1146. {
  1147. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1148. return op->f.isInsideCbArg;
  1149. }
  1150. void cmGrObjLocalVExt( cmGrH_t h, cmGrObjH_t oh, cmGrVExt_t* vext )
  1151. {
  1152. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1153. return _cmGrObjCbVExt( _cmGrHandleToPtr(h), op, vext);
  1154. }
  1155. cmGrObj_t* _cmGrObjIdToHandle( cmGrObj_t* op, unsigned id )
  1156. {
  1157. cmGrObj_t* rp = NULL;
  1158. if( op->id == id )
  1159. return op;
  1160. if( op->children != NULL )
  1161. if((rp = _cmGrObjIdToHandle(op->children,id)) != NULL )
  1162. return rp;
  1163. if( op->rsib != NULL )
  1164. if((rp = _cmGrObjIdToHandle(op->rsib,id)) != NULL )
  1165. return rp;
  1166. return NULL;
  1167. }
  1168. cmGrObjH_t cmGrObjIdToHandle( cmGrH_t h, unsigned id )
  1169. {
  1170. cmGr_t* p = _cmGrHandleToPtr(h);
  1171. cmGrObjH_t oh = cmGrObjNullHandle;
  1172. cmGrObj_t* op;
  1173. if((op = _cmGrObjIdToHandle(p->objs,id)) != NULL )
  1174. oh.h = op;
  1175. return oh;
  1176. }
  1177. // Move 'aoH' such that it is above 'boH' in the z-order.
  1178. // This means that 'boH' must be drawn before 'aoH'.
  1179. // This algorithm is designed to not break object hierarchies
  1180. // when moving objects. It achieves this by only moving
  1181. // the ancestor objects of boH and aoH at the level where
  1182. // they do not share a common ancestor.
  1183. void cmGrObjDrawAbove( cmGrObjH_t boH, cmGrObjH_t aoH )
  1184. {
  1185. cmGrObj_t* bp = _cmGrObjHandleToPtr(boH);
  1186. cmGrObj_t* ap = _cmGrObjHandleToPtr(aoH);
  1187. cmGrObj_t* rp = bp;
  1188. // set rp to the root object
  1189. while( rp->parent != NULL )
  1190. rp=rp->parent;
  1191. while(1)
  1192. {
  1193. cmGrObj_t* a[] = {NULL,NULL};
  1194. cmGrObj_t* bpp = NULL;
  1195. cmGrObj_t* app = NULL;
  1196. unsigned i = 0;
  1197. rp = rp->children;
  1198. for(; rp!=NULL; rp=rp->rsib)
  1199. {
  1200. if( bp==rp || _cmGrObjIsAncestor(rp,bp) )
  1201. {
  1202. assert( a[i]==NULL );
  1203. bpp = rp;
  1204. a[i++] = rp;
  1205. if( i==2 )
  1206. break;
  1207. }
  1208. if( ap==rp || _cmGrObjIsAncestor(rp,ap) )
  1209. {
  1210. assert( a[i]==NULL );
  1211. app = rp;
  1212. a[i++] = rp;
  1213. if( i==2 )
  1214. break;
  1215. }
  1216. }
  1217. assert( rp != NULL && i==2 );
  1218. // bpp and app share the same ancestor - keep looking
  1219. // for the level where the they do not share same ancestor
  1220. if( bpp == app )
  1221. rp = bpp;
  1222. else
  1223. {
  1224. // if bp is not already being drawn before ap
  1225. if( a[0] != bpp )
  1226. {
  1227. _cmGrObjUnlink(app);
  1228. _cmGrObjInsertOnRight(app,bpp,bpp->parent);
  1229. }
  1230. return;
  1231. }
  1232. }
  1233. }
  1234. void cmGrObjReport( cmGrH_t h, cmGrObjH_t oh, cmRpt_t* rpt )
  1235. {
  1236. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1237. _cmGrObjReport(_cmGrHandleToPtr(h),op,rpt);
  1238. }
  1239. void cmGrObjReportR( cmGrH_t h, cmGrObjH_t oh, cmRpt_t* rpt )
  1240. {
  1241. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1242. _cmGrObjReportR(_cmGrHandleToPtr(h),op,rpt);
  1243. }
  1244. //====================================================================================================
  1245. //====================================================================================================
  1246. #define _cmGr_X_VperP(p) (p->vext.sz.w / (p->pext.sz.w-1) )
  1247. #define _cmGr_Y_VperP(p) (p->vext.sz.h / (p->pext.sz.h-1) )
  1248. #define _cmGr_X_PperV(p) ((p->pext.sz.w-1) / p->vext.sz.w )
  1249. #define _cmGr_Y_PperV(p) ((p->pext.sz.h-1) / p->vext.sz.h )
  1250. int _cmGr_X_VtoP( cmGr_t* p, cmGrV_t vx )
  1251. { return p->pext.loc.x + lround( (vx - p->vext.loc.x) * _cmGr_X_PperV(p)); }
  1252. int _cmGr_Y_VtoP(cmGr_t* p, cmGrV_t vy )
  1253. { return p->pext.loc.y + (p->pext.sz.h-1) + lround(-(vy - p->vext.loc.y) * _cmGr_Y_PperV(p) ); }
  1254. cmGrV_t _cmGr_X_PtoV( cmGr_t* p, int px )
  1255. { return p->vext.loc.x + (px - p->pext.loc.x) * _cmGr_X_VperP(p); }
  1256. cmGrV_t _cmGr_Y_PtoV( cmGr_t* p, int py )
  1257. { return p->vext.loc.y + (p->pext.loc.y + (p->pext.sz.h-1) - py) * _cmGr_Y_VperP(p); }
  1258. #define _cmGrParentToLocalX( op, vext, x ) (op)->wext.loc.x + ((x) - (vext).loc.x) * (op)->wext.sz.w / (vext).sz.w
  1259. #define _cmGrParentToLocalY( op, vext, y ) (op)->wext.loc.y + ((y) - (vext).loc.y) * (op)->wext.sz.h / (vext).sz.h
  1260. #define _cmGrLocalToParentX( op, vext, x ) (vext).loc.x + ((x) - (op)->wext.loc.x) * (vext).sz.w / (op)->wext.sz.w
  1261. #define _cmGrLocalToParentY( op, vext, y ) (vext).loc.y + ((y) - (op)->wext.loc.y) * (vext).sz.h / (op)->wext.sz.h
  1262. // On input x,y are in the same coord's as op->vext.
  1263. // On output pt is converted to op's internal coord system (i.e. the pt is inside op->wext)
  1264. // Using pt as the src and dst is always safe. (i.e. _cmGrLocalToParent(p,op,pt->x,pt->y,pt) is safe.)
  1265. bool _cmGrParentToLocal( cmGr_t* p, cmGrObj_t* op, cmGrV_t x, cmGrV_t y, cmGrVPt_t* pt )
  1266. {
  1267. cmGrVExt_t vext;
  1268. _cmGrObjCbVExt(p,op,&vext);
  1269. if( cmGrVExtIsNullOrEmpty(&vext) )
  1270. return false;
  1271. pt->x = _cmGrParentToLocalX( op, vext, x);
  1272. pt->y = _cmGrParentToLocalY( op, vext, y );
  1273. //pt->x = op->wext.loc.x + (x - vext.loc.x) * op->wext.sz.w / vext.sz.w;
  1274. //pt->y = op->wext.loc.y + (y - vext.loc.y) * op->wext.sz.h / vext.sz.h;
  1275. return true;
  1276. }
  1277. // On input x,y are in the same coords as op->wext.
  1278. // On output pt is converted to be in the same coord's as op->vext (i.e.the pt is inside op->parent->wext)
  1279. // Using pt as the src and dst is always safe. (i.e. _cmGrLocalToParent(p,op,pt->x,pt->y,pt) is safe.)
  1280. void _cmGrLocalToParent( cmGr_t* p, cmGrObj_t* op, cmGrV_t x, cmGrV_t y, cmGrVPt_t* pt )
  1281. {
  1282. cmGrVExt_t vext;
  1283. _cmGrObjCbVExt(p,op,&vext);
  1284. pt->x = _cmGrLocalToParentX(op,vext, x);
  1285. pt->y = _cmGrLocalToParentY(op,vext, y);
  1286. //pt->x = vext.loc.x + (x - op->wext.loc.x) * vext.sz.w / op->wext.sz.w;
  1287. //pt->y = vext.loc.y + (y - op->wext.loc.y) * vext.sz.h / op->wext.sz.h;
  1288. }
  1289. // On input x is in coord's inside op->wext.
  1290. // Return is in phys coord's
  1291. int _cmGrX_VtoP( cmGr_t* p, cmGrObj_t* op, cmGrV_t x )
  1292. {
  1293. cmGrVExt_t vext;
  1294. for(; op->parent != NULL; op=op->parent )
  1295. {
  1296. _cmGrObjCbVExt(p,op,&vext);
  1297. x = _cmGrLocalToParentX(op->parent,vext,x);
  1298. }
  1299. return _cmGr_X_VtoP(p,x);
  1300. }
  1301. // On input y is in coord's inside op->wext.
  1302. // Return is in phys coord's
  1303. int _cmGrY_VtoP( cmGr_t* p, cmGrObj_t* op, cmGrV_t y )
  1304. {
  1305. cmGrVExt_t vext;
  1306. for(; op->parent != NULL; op=op->parent )
  1307. {
  1308. _cmGrObjCbVExt(p,op,&vext);
  1309. y = _cmGrLocalToParentY(op->parent,vext,y);
  1310. }
  1311. return _cmGr_Y_VtoP(p,y);
  1312. }
  1313. // On input x,y are coord's inside op->wext.
  1314. // On output rp is in physical coord's
  1315. void _cmGrXY_VtoP( cmGr_t* p, cmGrObj_t* op, cmGrV_t x, cmGrV_t y, cmGrPPt_t* rp )
  1316. {
  1317. cmGrVPt_t pt;
  1318. cmGrVPtSet(&pt,x,y);
  1319. for(; op->parent != NULL; op=op->parent )
  1320. _cmGrLocalToParent(p,op->parent,pt.x,pt.y,&pt);
  1321. rp->x = _cmGr_X_VtoP(p,pt.x);
  1322. rp->y = _cmGr_Y_VtoP(p,pt.y);
  1323. }
  1324. // pt is converted from the root obj coord system to be in the same coord's
  1325. // as op->vext (inside of op->parent->wext)
  1326. void _cmGrXY_GlobalToLocal( cmGr_t* p, cmGrObj_t* op, cmGrVPt_t* pt )
  1327. {
  1328. if( op->parent != NULL )
  1329. _cmGrXY_GlobalToLocal(p,op->parent,pt);
  1330. // convert from parent coord to child coords
  1331. _cmGrParentToLocal(p,op,pt->x,pt->y,pt);
  1332. }
  1333. // On input x,y are in physical coordindates.
  1334. // On output rp is inside op->parent->wext (the same coord's as op->vext)
  1335. void _cmGrXY_PtoV( cmGr_t* p, cmGrObj_t* op, int px, int py, cmGrVPt_t* rp )
  1336. {
  1337. // convert the phys points to points in the root coord system
  1338. rp->x = _cmGr_X_PtoV(p,px);
  1339. rp->y = _cmGr_Y_PtoV(p,py);
  1340. _cmGrXY_GlobalToLocal(p, op, rp );
  1341. }
  1342. int cmGrX_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t x )
  1343. {
  1344. cmGr_t* p = _cmGrHandleToPtr(hh);
  1345. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1346. return _cmGrX_VtoP(p,op,x);
  1347. }
  1348. int cmGrY_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t y )
  1349. {
  1350. cmGr_t* p = _cmGrHandleToPtr(hh);
  1351. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1352. return _cmGrY_VtoP(p,op,y);
  1353. }
  1354. void cmGrXY_VtoP( cmGrH_t h, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrPPt_t* rp )
  1355. { _cmGrXY_VtoP(_cmGrHandleToPtr(h), _cmGrObjHandleToPtr(oh), x, y, rp ); }
  1356. void cmGrXYWH_VtoP( cmGrH_t hh, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrV_t w, cmGrV_t h, cmGrPExt_t* pext )
  1357. {
  1358. cmGr_t* p = _cmGrHandleToPtr(hh);
  1359. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1360. cmGrPPt_t pt0,pt1;
  1361. _cmGrXY_VtoP(p,op,x, y, &pt0);
  1362. _cmGrXY_VtoP(p,op,x+w,y+h,&pt1);
  1363. cmGrPExtSetD(pext,pt0.x,pt0.y,pt1.x,pt1.y);
  1364. }
  1365. void cmGrVExt_VtoP( cmGrH_t hh, cmGrObjH_t oh, const cmGrVExt_t* vext, cmGrPExt_t* pext )
  1366. { cmGrXYWH_VtoP(hh,oh,vext->loc.x,vext->loc.y,vext->sz.w,vext->sz.h,pext); }
  1367. void cmGrXY_PtoV( cmGrH_t h, cmGrObjH_t oh, int x, int y, cmGrVPt_t* rp )
  1368. { _cmGrXY_PtoV(_cmGrHandleToPtr(h), _cmGrObjHandleToPtr(oh), x, y, rp ); }
  1369. void cmGrXYWH_PtoV( cmGrH_t hh, cmGrObjH_t oh, int x, int y, int w, int h, cmGrVExt_t* vext )
  1370. {
  1371. cmGr_t* p = _cmGrHandleToPtr(hh);
  1372. cmGrObj_t* op = _cmGrObjHandleToPtr(oh);
  1373. cmGrVPt_t pt0,pt1;
  1374. _cmGrXY_PtoV(p,op,x,y,&pt0);
  1375. _cmGrXY_PtoV(p,op,x+w-1,y+h-1,&pt1);
  1376. cmGrVExtSetD(vext,pt0.x,pt0.y,pt1.x,pt1.y);
  1377. }
  1378. void cmGrPExt_PtoV( cmGrH_t hh, cmGrObjH_t oh, const cmGrPExt_t* pext, cmGrVExt_t* vext )
  1379. { cmGrXYWH_PtoV(hh,oh,pext->loc.x,pext->loc.y,pext->sz.w,pext->sz.h,vext); }
  1380. void cmGrDrawVLine( cmGrH_t h, cmGrDcH_t dcH, cmGrObjH_t oh, cmGrV_t x0, cmGrV_t y0, cmGrV_t x1, cmGrV_t y1 )
  1381. {
  1382. cmGrPPt_t loc0;
  1383. cmGrPPt_t loc1;
  1384. cmGrXY_VtoP(h,oh,x0,y0,&loc0);
  1385. cmGrXY_VtoP(h,oh,x1,y1,&loc1);
  1386. cmGrDcDrawLine(dcH,loc0.x,loc0.y,loc1.x,loc1.y);
  1387. }
  1388. void cmGrDrawVRect( cmGrH_t hh, cmGrDcH_t dcH, cmGrObjH_t oh, cmGrV_t x, cmGrV_t y, cmGrV_t w, cmGrV_t h )
  1389. {
  1390. cmGrDrawVLine(hh,dcH,oh,x, y, x, y+h);
  1391. cmGrDrawVLine(hh,dcH,oh,x, y+h,x+w,y+h);
  1392. cmGrDrawVLine(hh,dcH,oh,x+w,y+h,x+w,y);
  1393. cmGrDrawVLine(hh,dcH,oh,x+w,y, x, y);
  1394. }
  1395. //====================================================================================================
  1396. //====================================================================================================
  1397. cmGrRC_t _cmGrDestroy( cmGr_t* p )
  1398. {
  1399. cmGrRC_t rc = kOkGrRC;
  1400. if( p->objs != NULL )
  1401. {
  1402. // destroy the root object and all of it's children
  1403. if((rc = _cmGrObjDestroy(p,p->objs)) != kOkGrRC )
  1404. return rc;
  1405. }
  1406. cmGrSync_t* sp = p->syncs;
  1407. while( sp != NULL )
  1408. {
  1409. cmGrH_t h;
  1410. h.h = p;
  1411. cmGrSync_t* np = sp->link;
  1412. // break sync with any mutually sync'ed gr's to prevent
  1413. // attempted calls to this gr.
  1414. cmGrSetSync( sp->grH, h, 0 );
  1415. cmMemFree(sp);
  1416. sp = np;
  1417. }
  1418. p->syncs = NULL;
  1419. cmLHeapDestroy(&p->lhH);
  1420. cmMemPtrFree(&p->img);
  1421. cmMemFree(p);
  1422. return rc;
  1423. }
  1424. void _cmGrObjRootVExt( cmGrObjFuncArgs_t* args, cmGrVExt_t* vext )
  1425. {
  1426. // the root object's virtual extent is the same as it's world extent
  1427. cmGrObjWorldExt( args->objH, vext );
  1428. }
  1429. bool _cmGrObjRootIsInside( cmGrObjFuncArgs_t* args, int px, int py, cmGrV_t vx, cmGrV_t vy )
  1430. {
  1431. cmGrVExt_t vext;
  1432. _cmGrObjRootVExt(args,&vext);
  1433. return cmGrVExtIsXyInside(&vext,vx,vy);
  1434. }
  1435. void _cmGrSetCfgFlags( cmGr_t* p, unsigned flags )
  1436. {
  1437. p->cfgFlags = flags;
  1438. // kSelectHorzFl and kSelectVertFl are mutually exclusive
  1439. if( cmIsFlag(p->cfgFlags,kSelectHorzGrFl) )
  1440. p->cfgFlags = cmClrFlag(p->cfgFlags,kSelectVertGrFl);
  1441. }
  1442. void _cmGrCallback( cmGr_t* p, cmGrCbId_t id, unsigned eventFlags, cmGrKeyCodeId_t keycode )
  1443. {
  1444. if( p->cbFunc != NULL )
  1445. {
  1446. cmGrH_t h;
  1447. h.h = p;
  1448. p->cbFunc(p->cbArg,h,id,eventFlags,keycode);
  1449. }
  1450. }
  1451. cmGrRC_t cmGrCreate( cmCtx_t* ctx, cmGrH_t* hp, unsigned id, unsigned cfgFlags, cmGrCbFunc_t cbFunc, void* cbArg, const cmGrVExt_t* wext )
  1452. {
  1453. cmGrRC_t rc = kOkGrRC;
  1454. cmGrVExt_t null_ext;
  1455. cmGrObjH_t rootObjH = cmGrObjNullHandle;
  1456. if(( rc = cmGrDestroy(hp)) != kOkGrRC )
  1457. return rc;
  1458. // create the cmGr_t
  1459. cmGr_t* p = cmMemAllocZ(cmGr_t,1);
  1460. p->ctx = *ctx;
  1461. p->id = id;
  1462. p->stateFlags = kDirtyGrFl;
  1463. p->cbFunc = cbFunc;
  1464. p->cbArg = cbArg;
  1465. _cmGrSetCfgFlags(p,cfgFlags);
  1466. if( wext == NULL )
  1467. {
  1468. cmGrVExtSetNull(&null_ext);
  1469. wext = &null_ext;
  1470. }
  1471. cmErrSetup(&p->err,&ctx->rpt,"cmGr");
  1472. if( cmLHeapIsValid( p->lhH = cmLHeapCreate(8192,ctx)) == false )
  1473. {
  1474. rc = cmErrMsg(&p->err,kLHeapFailGrRC,"Linked heap create failed.");
  1475. goto errLabel;
  1476. }
  1477. cmGrVExtSetEmpty(&p->vext);
  1478. cmGrPExtSetEmpty(&p->pext);
  1479. hp->h = p;
  1480. // create the root object
  1481. cmGrObjFunc_t funcs;
  1482. memset(&funcs,0,sizeof(funcs));
  1483. funcs.vextCbFunc = _cmGrObjRootVExt;
  1484. funcs.isInsideCbFunc = _cmGrObjRootIsInside;
  1485. if((rc = cmGrObjCreate(*hp, &rootObjH, cmGrObjNullHandle, &funcs, cmInvalidId, 0, wext )) != kOkGrRC )
  1486. {
  1487. rc = cmErrMsg(&p->err,kRootObjCreateFailGrRC,"The root object creation failed.");
  1488. goto errLabel;
  1489. }
  1490. // create the default color map
  1491. _cmGrRgbInitDefaultColorMap(p);
  1492. p->objs = _cmGrObjHandleToPtr(rootObjH);
  1493. p->rootObj = p->objs;
  1494. _cmGrCallback(p,kCreateCbGrId,0,kInvalidKeyCodeGrId);
  1495. errLabel:
  1496. if( rc != kOkGrRC )
  1497. {
  1498. _cmGrDestroy(p);
  1499. hp->h = NULL;
  1500. }
  1501. return rc;
  1502. }
  1503. cmGrRC_t cmGrDestroy( cmGrH_t* hp )
  1504. {
  1505. cmGrRC_t rc = kOkGrRC;
  1506. if( hp==NULL || cmGrIsValid(*hp) == false )
  1507. return kOkGrRC;
  1508. cmGr_t* p = _cmGrHandleToPtr(*hp);
  1509. if((rc = _cmGrDestroy(p)) != kOkGrRC )
  1510. goto errLabel;
  1511. hp->h = NULL;
  1512. errLabel:
  1513. return rc;
  1514. }
  1515. // Destroy all objects (except the root object)
  1516. cmGrRC_t _cmGrObjDestroyAll( cmGr_t* p )
  1517. {
  1518. cmGrObj_t* op = p->objs;
  1519. if( op != NULL )
  1520. {
  1521. op = op->children;
  1522. while( op != NULL )
  1523. {
  1524. cmGrObj_t* np = op->rsib;
  1525. _cmGrObjUnlinkAndFree(p,op);
  1526. op = np;
  1527. }
  1528. }
  1529. return kOkGrRC;
  1530. }
  1531. cmGrRC_t cmGrClear( cmGrH_t h )
  1532. {
  1533. cmGrRC_t rc;
  1534. cmGr_t* p = _cmGrHandleToPtr(h);
  1535. if((rc = _cmGrObjDestroyAll(p)) != kOkGrRC )
  1536. return rc;
  1537. p->rootObj = p->objs;
  1538. p->stateFlags = kDirtyGrFl;
  1539. cmGrVExtSetEmpty(&p->vext);
  1540. p->msDnObj = NULL;
  1541. cmGrPPtSet(&p->msDnPPt,0,0);
  1542. cmGrVPtSet(&p->msDnVPt,0,0);
  1543. cmGrVPtSet(&p->msVPt,0,0);
  1544. cmGrVSzSet(&p->msDnVOffs,0,0);
  1545. p->selValidFl = false;
  1546. cmGrVPtSet(&p->sel0Pt,0,0);
  1547. cmGrVPtSet(&p->sel1Pt,0,0);
  1548. cmGrVPtSet(&p->localPt,0,0);
  1549. cmGrVPtSet(&p->globalPt,0,0);
  1550. cmGrVExtSetNull(&p->rootObj->wext);
  1551. return rc;
  1552. }
  1553. cmGrObjH_t cmGrRootObjH( cmGrH_t h )
  1554. {
  1555. cmGr_t* p = _cmGrHandleToPtr(h);
  1556. cmGrObjH_t oh;
  1557. oh.h = p->rootObj;
  1558. return oh;
  1559. }
  1560. unsigned cmGrCfgFlags( cmGrH_t h )
  1561. {
  1562. cmGr_t* p = _cmGrHandleToPtr(h);
  1563. return p->cfgFlags;
  1564. }
  1565. void cmGrSetCfgFlags( cmGrH_t h, unsigned cfgFlags )
  1566. {
  1567. cmGr_t* p = _cmGrHandleToPtr(h);
  1568. _cmGrSetCfgFlags(p,cfgFlags);
  1569. }
  1570. void _cmGrObjDraw( cmGr_t* p, cmGrObj_t* op, cmGrDcH_t dcH )
  1571. {
  1572. _cmGrObjCbRender(p,dcH,op);
  1573. if( op->children != NULL )
  1574. _cmGrObjDraw(p,op->children,dcH);
  1575. if( op->rsib != NULL )
  1576. _cmGrObjDraw(p,op->rsib,dcH);
  1577. }
  1578. void _cmInvertImage( cmGr_t* p, cmGrDcH_t dcH, const cmGrPExt_t* pext )
  1579. {
  1580. if( cmGrPExtIsNullOrEmpty(pext) )
  1581. return;
  1582. cmGrPExt_t r;
  1583. cmGrPExtIntersect( &r, pext, &p->pext );
  1584. unsigned n = r.sz.w * r.sz.h * 3;
  1585. if( n > 0 )
  1586. {
  1587. unsigned i;
  1588. p->img = cmMemResizeZ(unsigned char,p->img,n);
  1589. //p->dd.read_image(p->ddUser, p->img, r.loc.x, r.loc.y, r.sz.w, r.sz.h );
  1590. cmGrDcReadImage( dcH, p->img, &r );
  1591. for(i=0; i<n; ++i)
  1592. p->img[i] = 255 - p->img[i];
  1593. //p->dd.draw_image(p->ddUser, p->img, r.loc.x, r.loc.y, r.sz.w, r.sz.h);
  1594. cmGrDcDrawImage( dcH, p->img, &r);
  1595. }
  1596. }
  1597. cmGrRC_t cmGrDraw( cmGrH_t h, cmGrDcH_t dcH )
  1598. {
  1599. cmGr_t* p = _cmGrHandleToPtr(h);
  1600. _cmGrObjDraw(p,p->rootObj,dcH);
  1601. cmGrPExt_t pext;
  1602. cmGrVExt_t vext;
  1603. cmGrSelectExtents(h,&vext,&pext);
  1604. if( cmGrPExtIsNotNull(&pext))
  1605. {
  1606. if( pext.sz.w<=1 && pext.sz.h<=1 )
  1607. {
  1608. cmGrPExt_t ipext;
  1609. if( !cmIsFlag(p->cfgFlags,kSelectHorzGrFl) )
  1610. {
  1611. cmGrPExtSet(&ipext,p->pext.loc.x,pext.loc.y,p->pext.sz.w,1);
  1612. _cmInvertImage(p,dcH,&ipext);
  1613. }
  1614. if( !cmIsFlag(p->cfgFlags,kSelectVertGrFl) )
  1615. {
  1616. cmGrPExtSet(&ipext,pext.loc.x,p->pext.loc.y,1,p->pext.sz.h);
  1617. _cmInvertImage(p,dcH,&ipext);
  1618. }
  1619. }
  1620. else
  1621. {
  1622. _cmInvertImage(p,dcH,&pext);
  1623. }
  1624. }
  1625. return kOkGrRC;
  1626. }
  1627. bool _cmGrSetViewExtents( cmGr_t* p, cmGrV_t minx, cmGrV_t miny, cmGrV_t maxx, cmGrV_t maxy )
  1628. {
  1629. cmGrVExt_t vext;
  1630. // load a vext with the new view extents
  1631. cmGrVExtSetD(&vext,minx,miny,maxx,maxy);
  1632. // if the view ext is not changing
  1633. if( cmGrVExtIsEqual(&p->vext,&vext) )
  1634. return false;
  1635. // the root object must exist
  1636. assert( p->rootObj != NULL );
  1637. // the view extents must be in the world extents
  1638. if( cmGrVExtIsExtInside(&p->rootObj->wext,&vext)==false )
  1639. {
  1640. cmErrMsg(&p->err,kInvalidCoordsGrRC,"View extent is not inside the world extents.");
  1641. return false;
  1642. }
  1643. //cmGrVExtPrint("set vw:",&vext);
  1644. p->vext = vext;
  1645. p->stateFlags = cmSetFlag(p->stateFlags,kDirtyGrFl);
  1646. _cmGrCallback(p, kViewExtCbGrId,0,kInvalidKeyCodeGrId );
  1647. // apply changes to synch target
  1648. cmGrSync_t* sp = p->syncs;
  1649. for(; sp!=NULL; sp=sp->link)
  1650. if( cmIsFlag(sp->flags,kViewSyncGrFl) )
  1651. {
  1652. cmGrViewExtents( sp->grH, &vext );
  1653. bool fl = false;
  1654. if( cmIsFlag(sp->flags,kHorzSyncGrFl) )
  1655. {
  1656. fl = true;
  1657. vext.loc.x = p->vext.loc.x;
  1658. vext.sz.w = p->vext.sz.w;
  1659. }
  1660. if( cmIsFlag(sp->flags,kVertSyncGrFl) )
  1661. {
  1662. fl = true;
  1663. vext.loc.y = p->vext.loc.y;
  1664. vext.sz.h = p->vext.sz.h;
  1665. }
  1666. if( fl )
  1667. cmGrSetViewExtentsE( sp->grH, &vext );
  1668. }
  1669. //printf("s:%p %f %f %f %f\n",p,p->vext.loc.x, p->vext.loc.y, p->vext.sz.w, p->vext.sz.h );
  1670. return true;
  1671. }
  1672. bool _cmGrSetScrollH( cmGr_t* p, int x )
  1673. {
  1674. assert( p->rootObj != NULL );
  1675. cmGrV_t vx = p->rootObj->wext.loc.x + (x * p->vext.sz.w / p->pext.sz.w);
  1676. return _cmGrSetViewExtents(p,vx, p->vext.loc.y, vx+p->vext.sz.w, p->vext.loc.y+p->vext.sz.h);
  1677. }
  1678. int _cmGrScrollH( cmGr_t* p )
  1679. { return round((p->vext.loc.x - p->rootObj->wext.loc.x) * p->pext.sz.w / p->vext.sz.w); }
  1680. bool _cmGrSetScrollV( cmGr_t* p, int y )
  1681. {
  1682. assert( p->rootObj != NULL );
  1683. cmGrV_t vy = p->rootObj->wext.loc.y + (y * p->vext.sz.h / p->pext.sz.h);
  1684. return _cmGrSetViewExtents(p, p->vext.loc.x, vy, p->vext.loc.x+p->vext.sz.w, vy + p->vext.sz.h);
  1685. }
  1686. int _cmGrScrollV( cmGr_t* p )
  1687. { return round((p->vext.loc.y - p->rootObj->wext.loc.y) * p->pext.sz.h / p->vext.sz.h); }
  1688. void _cmGrSetSelectPoints(cmGr_t* p, const cmGrVPt_t* pt0, const cmGrVPt_t* pt1)
  1689. {
  1690. bool deltaFl = false;
  1691. p->selValidFl = true;
  1692. if( pt0 != NULL )
  1693. {
  1694. if( cmGrVPtIsNotEqual(&p->sel0Pt,pt0) )
  1695. {
  1696. p->sel0Pt = *pt0;
  1697. deltaFl = true;
  1698. }
  1699. if( pt1 == NULL && cmGrVPtIsNotEqual(&p->sel1Pt,pt0) )
  1700. {
  1701. p->sel1Pt = *pt0;
  1702. deltaFl = true;
  1703. }
  1704. }
  1705. if( pt1 != NULL && cmGrVPtIsNotEqual(&p->sel1Pt,pt1) )
  1706. {
  1707. p->sel1Pt = *pt1;
  1708. deltaFl = true;
  1709. }
  1710. if( !deltaFl )
  1711. return;
  1712. _cmGrCallback(p,kSelectExtCbGrId,0,kInvalidKeyCodeGrId);
  1713. // apply changes to synch target
  1714. cmGrSync_t* sp = p->syncs;
  1715. for(; sp!=NULL; sp=sp->link)
  1716. if( cmIsFlag(sp->flags,kSelectSyncGrFl) )
  1717. {
  1718. cmGrVPt_t pt0, pt1;
  1719. cmGrSelectPoints(sp->grH, &pt0, &pt1 );
  1720. bool fl = false;
  1721. if( cmIsFlag(sp->flags,kHorzSyncGrFl) )
  1722. {
  1723. fl = true;
  1724. pt0.x = p->sel0Pt.x;
  1725. pt1.x = p->sel1Pt.x;
  1726. }
  1727. if( cmIsFlag(sp->flags,kVertSyncGrFl) )
  1728. {
  1729. fl = true;
  1730. pt0.y = p->sel0Pt.y;
  1731. pt1.y = p->sel1Pt.y;
  1732. }
  1733. if( fl )
  1734. cmGrSetSelectPoints( sp->grH, &pt0, &pt1 );
  1735. }
  1736. }
  1737. // vx,vy are in the same coord's as op->vext
  1738. cmGrObj_t* _cmGrFindObjRec( cmGr_t* p, cmGrObj_t* op, int px, int py, cmGrV_t vx, cmGrV_t vy )
  1739. {
  1740. cmGrObj_t* rop = NULL;
  1741. cmGrObj_t* top;
  1742. cmGrVExt_t vext;
  1743. // get the location of op inside op->parent->wext
  1744. _cmGrObjCbVExt(p,op,&vext);
  1745. // is vx,vy inside op - this is equiv to: cmGrVExtIsXyInside(&vext,vx,vy)
  1746. if( _cmGrObjCbIsInside(p,op,px,py,vx,vy) )
  1747. rop = op;
  1748. if( op->children != NULL )
  1749. {
  1750. cmGrVPt_t pt;
  1751. if( _cmGrParentToLocal(p,op,vx,vy,&pt) )
  1752. if((top = _cmGrFindObjRec(p,op->children,px,py,vx,vy)) != NULL )
  1753. rop = top;
  1754. }
  1755. if( op->rsib != NULL )
  1756. if((top = _cmGrFindObjRec(p,op->rsib,px,py,vx,vy)) != NULL )
  1757. rop = top;
  1758. return rop;
  1759. }
  1760. bool cmGrEvent( cmGrH_t h, unsigned flags, cmGrKeyCodeId_t key, int px, int py )
  1761. {
  1762. bool fl = false;
  1763. cmGr_t* p = _cmGrHandleToPtr(h);
  1764. cmGrObj_t* op;
  1765. cmGrVPtSet(&p->localPt,0,0);
  1766. // convert the phys points to points in the root coord system
  1767. cmGrV_t gx = _cmGr_X_PtoV(p,px);
  1768. cmGrV_t gy = _cmGr_Y_PtoV(p,py);
  1769. cmGrVPtSet(&p->globalPt,gx,gy);
  1770. _cmGrCallback(p,kGlobalPtCbGrId,0,kInvalidKeyCodeGrId);
  1771. // find the obj under the mouse
  1772. if((op = _cmGrFindObjRec(p,p->rootObj,px,py,gx,gy)) != NULL )
  1773. {
  1774. // convert gx,gy to be inside op->wext
  1775. cmGrVPtSet(&p->localPt,gx,gy);
  1776. _cmGrXY_GlobalToLocal(p,op,&p->localPt);
  1777. _cmGrCallback(p,kLocalPtCbGrId,0,kInvalidKeyCodeGrId);
  1778. }
  1779. if( (flags&kEvtMask)==kKeyUpGrFl )
  1780. _cmGrCallback(p,kKeyUpCbGrId,flags,key);
  1781. if( (flags&kEvtMask)==kKeyDnGrFl )
  1782. _cmGrCallback(p,kKeyDnCbGrId,flags,key);
  1783. if( op != NULL )
  1784. {
  1785. switch( flags & kEvtMask )
  1786. {
  1787. case kMsDownGrFl:
  1788. // store the phys loc. of the ms dn event
  1789. cmGrPPtSet(&p->msDnPPt,px,py);
  1790. if( op != NULL )
  1791. {
  1792. // if the click was in not in the root object
  1793. if( op->parent != NULL )
  1794. {
  1795. // store the object and coord's where the mouse went down.
  1796. cmGrVExt_t vext;
  1797. p->msDnObj = op; // set the msDnObj
  1798. // convert the phys ms dn point to the virt point inside op->parent.wext
  1799. _cmGrXY_PtoV(p, op->parent, px, py, &p->msDnVPt );
  1800. // set the current ms virt pt
  1801. p->msVPt = p->msDnVPt;
  1802. // get the ms down obj virt extents
  1803. _cmGrObjCbVExt(p,op,&vext);
  1804. // store the offset from the lower left to the ms dn point
  1805. p->msDnVOffs.w = p->msDnVPt.x - vext.loc.x;
  1806. p->msDnVOffs.h = p->msDnVPt.y - vext.loc.y;
  1807. // notify the object that the mouse went down
  1808. fl = _cmGrObjCbEvent(p,op,flags,key,px,py);
  1809. }
  1810. }
  1811. break;
  1812. case kMsUpGrFl:
  1813. {
  1814. cmGrPPt_t upPPt;
  1815. cmGrPPtSet(&upPPt,px,py);
  1816. bool clickFl = cmGrPPtIsEqual(&p->msDnPPt,&upPPt );
  1817. // if a click occured ...
  1818. if( clickFl )
  1819. {
  1820. // ... and the click is in a non-root object ...
  1821. if( p->msDnObj!= NULL && p->msDnObj->parent!=NULL )
  1822. {
  1823. // ... then generate a click event
  1824. unsigned evtFlags = cmClrFlag(flags,kMsUpGrFl) | kMsClickGrFl;
  1825. fl = _cmGrObjCbEvent(p,op,evtFlags,key,px,py);
  1826. }
  1827. else // ... else if the click occurred in the root object
  1828. {
  1829. cmGrVPt_t pt;
  1830. cmGrVPtSet(&pt,gx,gy);
  1831. bool shFl = cmIsFlag(flags,kShiftKeyGrFl);
  1832. _cmGrSetSelectPoints( p, shFl ? NULL : &pt, shFl ? &pt : NULL );
  1833. }
  1834. }
  1835. // notify the object under the mouse that the mouse went up
  1836. if( _cmGrObjCbEvent(p,op,flags,key,px,py) )
  1837. fl = true;
  1838. _cmGrCallback(p,kFocusCbGrId,0,kInvalidKeyCodeGrId);
  1839. p->msDnObj = NULL;
  1840. }
  1841. break;
  1842. case kMsMoveGrFl:
  1843. fl = _cmGrObjCbEvent(p,op,flags,key,px,py);
  1844. break;
  1845. case kMsWheelGrFl:
  1846. break;
  1847. case kMsDragGrFl:
  1848. if( p->msDnObj != NULL )
  1849. {
  1850. // set the current virtual point
  1851. _cmGrXY_PtoV(p, p->msDnObj->parent, px, py, &p->msVPt );
  1852. // callback the dragged object
  1853. fl = _cmGrObjCbEvent(p,p->msDnObj,flags,key,px,py);
  1854. // if the px,py is outside the root phys extents then scroll
  1855. if( !cmGrPExtIsXyInside(&p->pext,px,py) )
  1856. {
  1857. bool hFl = false, vFl=false;
  1858. cmGrPSz_t tot,vis,max;
  1859. cmGrPPt_t pos;
  1860. cmGrScrollExtents(h, &tot, &vis, &max, &pos );
  1861. if( px < cmGrPExtL(&p->pext) )
  1862. hFl = _cmGrSetScrollH(p, cmMax(0, _cmGrScrollH(p) - (cmGrPExtL(&p->pext) - px)));
  1863. else
  1864. if( px > cmGrPExtR(&p->pext) )
  1865. hFl = _cmGrSetScrollH(p, cmMin(max.w, _cmGrScrollH(p) + (px - cmGrPExtR(&p->pext))));
  1866. if( py < cmGrPExtT(&p->pext) )
  1867. vFl = _cmGrSetScrollV(p, cmMax(0, _cmGrScrollV(p) - (cmGrPExtT(&p->pext) - py)));
  1868. else
  1869. if( py > cmGrPExtB(&p->pext) )
  1870. vFl = _cmGrSetScrollV(p, cmMin(max.h, _cmGrScrollV(p) + (py - cmGrPExtB(&p->pext))));
  1871. fl = fl || vFl || hFl;
  1872. }
  1873. }
  1874. break;
  1875. case kKeyDnGrFl:
  1876. case kKeyUpGrFl:
  1877. //fl = _cmGrObjCbEvent(p,p->msDnObj,flags,key,px,py);
  1878. break;
  1879. }
  1880. }
  1881. return fl;
  1882. }
  1883. bool cmGrIsValid( cmGrH_t h )
  1884. { return h.h != NULL; }
  1885. unsigned cmGrId( cmGrH_t h )
  1886. {
  1887. cmGr_t* p = _cmGrHandleToPtr(h);
  1888. return p->id;
  1889. }
  1890. const cmGrVPt_t* cmGrGlobalPt( cmGrH_t h )
  1891. {
  1892. cmGr_t* p = _cmGrHandleToPtr(h);
  1893. return &p->globalPt;
  1894. }
  1895. const cmGrVPt_t* cmGrLocalPt( cmGrH_t h )
  1896. {
  1897. cmGr_t* p = _cmGrHandleToPtr(h);
  1898. return &p->localPt;
  1899. }
  1900. bool cmGrSetViewExtents( cmGrH_t h, cmGrV_t minx, cmGrV_t miny, cmGrV_t maxx, cmGrV_t maxy )
  1901. { return _cmGrSetViewExtents( _cmGrHandleToPtr(h), minx,miny,maxx,maxy); }
  1902. bool cmGrSetViewExtentsE( cmGrH_t h, const cmGrVExt_t* e )
  1903. { return cmGrSetViewExtents( h, cmGrVExtMinX(e), cmGrVExtMinY(e), cmGrVExtMaxX(e), cmGrVExtMaxY(e) ); }
  1904. void cmGrViewExtents( cmGrH_t h, cmGrVExt_t* vext )
  1905. {
  1906. cmGr_t* p = _cmGrHandleToPtr(h);
  1907. *vext = p->vext;
  1908. //printf("g0:%p %f %f %f %f\n",p,p->vext.loc.x, p->vext.loc.y, p->vext.sz.w, p->vext.sz.h );
  1909. //printf("g1:%p %f %f %f %f\n",p,vext->loc.x, vext->loc.y, vext->sz.w, vext->sz.h );
  1910. }
  1911. bool cmGrSetPhysExtents( cmGrH_t hh, int x, int y, int w, int h )
  1912. {
  1913. cmGr_t* p = _cmGrHandleToPtr(hh);
  1914. cmGrPExt_t pext;
  1915. cmGrPExtSet(&pext,x,y,w,h);
  1916. assert( cmGrPExtIsNull(&pext)==false );
  1917. if( cmGrPExtIsEqual(&pext,&p->pext) )
  1918. return false;
  1919. p->pext = pext;
  1920. p->stateFlags = cmSetFlag(p->stateFlags,kDirtyGrFl);
  1921. _cmGrCallback(p,kPhysExtCbGrId,0,kInvalidKeyCodeGrId);
  1922. //cmGrPExtPrint("pext",&p->pext);
  1923. return true;
  1924. }
  1925. bool cmGrSetPhysExtentsE(cmGrH_t h, const cmGrPExt_t* e )
  1926. { return cmGrSetPhysExtents(h, cmGrPExtL(e), cmGrPExtT(e), cmGrPExtW(e), cmGrPExtH(e) ); }
  1927. void cmGrPhysExtents( cmGrH_t h, cmGrPExt_t* exts )
  1928. {
  1929. cmGr_t* p = _cmGrHandleToPtr(h);
  1930. *exts = p->pext;
  1931. }
  1932. void cmGrScrollExtents( cmGrH_t h, cmGrPSz_t* tot, cmGrPSz_t* vis, cmGrPSz_t* max, cmGrPPt_t* pos )
  1933. {
  1934. cmGr_t* p = _cmGrHandleToPtr(h);
  1935. assert( p->rootObj != NULL );
  1936. if( tot != NULL )
  1937. {
  1938. tot->w = round(p->rootObj->wext.sz.w * p->pext.sz.w / p->vext.sz.w);
  1939. tot->h = round(p->rootObj->wext.sz.h * p->pext.sz.h / p->vext.sz.h);
  1940. }
  1941. if( vis != NULL )
  1942. {
  1943. vis->w = round(p->vext.sz.w * p->pext.sz.w / p->vext.sz.w);
  1944. vis->h = round(p->vext.sz.h * p->pext.sz.h / p->vext.sz.h);
  1945. }
  1946. if( max != NULL )
  1947. {
  1948. max->w = tot->w - vis->w;
  1949. max->h = tot->h - vis->h;
  1950. }
  1951. if( pos != NULL )
  1952. {
  1953. pos->x = _cmGrScrollH(p);
  1954. pos->y = _cmGrScrollV(p);
  1955. }
  1956. }
  1957. bool cmGrSetScrollH( cmGrH_t h, int x )
  1958. { return _cmGrSetScrollH( _cmGrHandleToPtr(h), x ); }
  1959. int cmGrScrollH( cmGrH_t h )
  1960. { return _cmGrScrollH( _cmGrHandleToPtr(h) ); }
  1961. bool cmGrSetScrollV( cmGrH_t h, int y )
  1962. { return _cmGrSetScrollV( _cmGrHandleToPtr(h), y ); }
  1963. int cmGrScrollV( cmGrH_t h )
  1964. { return _cmGrScrollV( _cmGrHandleToPtr(h) ); }
  1965. bool cmGrSelectExtents( cmGrH_t h, cmGrVExt_t* vext, cmGrPExt_t* pext )
  1966. {
  1967. cmGrPPt_t pt0,pt1;
  1968. cmGr_t* p = _cmGrHandleToPtr(h);
  1969. if( !p->selValidFl )
  1970. {
  1971. cmGrVExtSetNull(vext);
  1972. cmGrPExtSetNull(pext);
  1973. return false;
  1974. }
  1975. if( p->sel0Pt.x == p->sel1Pt.x && p->sel0Pt.y == p->sel1Pt.y )
  1976. cmGrVExtSet(vext, p->sel0Pt.x, p->sel0Pt.y, 0, 0);
  1977. else
  1978. {
  1979. cmGrV_t gx0=p->sel0Pt.x, gy0=p->sel0Pt.y;
  1980. cmGrV_t gx1=p->sel1Pt.x, gy1=p->sel1Pt.y;
  1981. if( cmIsFlag(p->cfgFlags,kSelectHorzGrFl) )
  1982. {
  1983. gy0 = cmGrVExtMaxY(&p->rootObj->wext);
  1984. gy1 = cmGrVExtMinY(&p->rootObj->wext);
  1985. }
  1986. else
  1987. if( cmIsFlag(p->cfgFlags,kSelectVertGrFl ) )
  1988. {
  1989. gx0 = cmGrVExtMinX(&p->rootObj->wext);
  1990. gx1 = cmGrVExtMaxX(&p->rootObj->wext);
  1991. }
  1992. cmGrVExtSetD(vext,cmMin(gx0,gx1),cmMin(gy0,gy1),cmMax(gx0,gx1),cmMax(gy0,gy1));
  1993. }
  1994. _cmGrXY_VtoP(p, p->rootObj, vext->loc.x, vext->loc.y, &pt0 );
  1995. _cmGrXY_VtoP(p, p->rootObj, vext->loc.x + vext->sz.w, vext->loc.y + vext->sz.h, &pt1 );
  1996. cmGrPExtSetD(pext,cmMin(pt0.x,pt1.x),cmMin(pt0.y,pt1.y),cmMax(pt0.x,pt1.x),cmMax(pt0.y,pt1.y));
  1997. //printf("%f %f %f %f\n",vext->loc.x,vext->loc.y,vext->sz.w,vext->sz.h);
  1998. //printf("%i %i %i %i\n",pext->loc.x,pext->loc.y,pext->sz.w,pext->sz.h);
  1999. return true;
  2000. }
  2001. void cmGrSetSelectPoints( cmGrH_t h, const cmGrVPt_t* pt0, const cmGrVPt_t* pt1 )
  2002. {
  2003. cmGr_t* p = _cmGrHandleToPtr(h);
  2004. _cmGrSetSelectPoints(p,pt0,pt1);
  2005. }
  2006. void cmGrSelectPoints( cmGrH_t h, cmGrVPt_t* pt0, cmGrVPt_t* pt1 )
  2007. {
  2008. cmGr_t* p = _cmGrHandleToPtr(h);
  2009. if( pt0 != NULL )
  2010. *pt0 = p->sel0Pt;
  2011. if( pt1 != NULL )
  2012. *pt1 = p->sel1Pt;
  2013. }
  2014. void cmGrZoom( cmGrH_t h, unsigned flags )
  2015. {
  2016. cmGr_t* p = _cmGrHandleToPtr(h);
  2017. bool hfl = cmIsFlag(flags,kXAxisGrFl);
  2018. bool vfl = cmIsFlag(flags,kYAxisGrFl);
  2019. bool inFl = cmIsFlag(flags,kZoomInGrFl);
  2020. bool allFl = cmIsFlag(flags,kShowAllGrFl);
  2021. double magn = 3.0;
  2022. double ratio = inFl ? 1.0/magn : magn;
  2023. cmGrVPt_t c;
  2024. cmGrVExt_t z;
  2025. cmGrVExt_t v;
  2026. cmGrVExt_t w;
  2027. cmGrVExtSetNull(&z);
  2028. cmGrViewExtents( h,&v); // get the current view extents
  2029. cmGrObjWorldExt( cmGrRootObjH(h),&w); // get the current world extents
  2030. // if show all was requested ...
  2031. if( allFl )
  2032. {
  2033. // .. then the world ext's become the view extents.
  2034. cmGrVExtSetD(&z,
  2035. hfl ? cmGrVExtMinX(&w) : cmGrVExtMinX(&v),
  2036. vfl ? cmGrVExtMinY(&w) : cmGrVExtMinY(&v),
  2037. hfl ? cmGrVExtMaxX(&w) : cmGrVExtMaxX(&v),
  2038. vfl ? cmGrVExtMaxY(&w) : cmGrVExtMaxY(&v));
  2039. }
  2040. else
  2041. {
  2042. // if the selection flag is not set or the selection pt/area is not valid
  2043. if( cmIsNotFlag(flags,kSelectGrFl) || p->selValidFl==false )
  2044. {
  2045. // center the zoom on the current view
  2046. c.x = v.loc.x + v.sz.w/2;
  2047. c.y = v.loc.y + v.sz.h/2;
  2048. }
  2049. else
  2050. {
  2051. // if the selection area is a point
  2052. if( p->sel0Pt.x == p->sel1Pt.x && p->sel0Pt.y == p->sel1Pt.y )
  2053. {
  2054. // center the zoom on the current view
  2055. c.x = p->sel0Pt.x;
  2056. c.y = p->sel1Pt.y;
  2057. }
  2058. else
  2059. {
  2060. cmGrPExt_t dum;
  2061. // The selection area exist - make it the new view area
  2062. // Note that f the selection area is greater than the
  2063. // current view area then this may not be a magnification.
  2064. cmGrSelectExtents(h,&z,&dum);
  2065. }
  2066. }
  2067. // if no zoom area has been created then create
  2068. // one centered on 'c'.
  2069. if( cmGrVExtIsNull(&z) )
  2070. {
  2071. cmGrVExt_t t;
  2072. cmGrV_t zw = v.sz.w * ratio / 2;
  2073. cmGrV_t zh = v.sz.h * ratio / 2;
  2074. cmGrVExtSetD(&t,
  2075. hfl ? c.x-zw : cmGrVExtMinX(&v),
  2076. vfl ? c.y-zh : cmGrVExtMinY(&v),
  2077. hfl ? c.x+zw : cmGrVExtMaxX(&v),
  2078. vfl ? c.y+zh : cmGrVExtMaxY(&v));
  2079. cmGrVExtIntersect(&z,&t,&w);
  2080. }
  2081. }
  2082. //cmGrVExtPrint("w:",&w);
  2083. //cmGrVExtPrint("z:",&z);
  2084. //cmGrVExtPrint("v:",&v);
  2085. assert( cmGrVExtIsNorm(&z));
  2086. cmGrSetViewExtentsE(h,&z);
  2087. }
  2088. void cmGrSetSync( cmGrH_t h, cmGrH_t syncGrH, unsigned flags )
  2089. {
  2090. cmGr_t* p = _cmGrHandleToPtr(h);
  2091. // attempt to locate syncGrH on the sync list
  2092. cmGrSync_t* pp = NULL;
  2093. cmGrSync_t* sp = p->syncs;
  2094. for(; sp != NULL; sp=sp->link)
  2095. {
  2096. if( cmHandlesAreEqual(sp->grH,syncGrH) )
  2097. break;
  2098. pp = sp;
  2099. }
  2100. // if the handle was not found ...
  2101. if( sp == NULL )
  2102. {
  2103. // ... and a valid flags value was given ...
  2104. if( flags != 0 )
  2105. {
  2106. // ... then create a new sync target.
  2107. sp = cmMemAllocZ(cmGrSync_t,1);
  2108. sp->grH = syncGrH;
  2109. sp->flags = flags;
  2110. sp->link = p->syncs;
  2111. p->syncs = sp;
  2112. }
  2113. }
  2114. else // ... otherwise syncGrH is already a sync target
  2115. {
  2116. // if flags is non-zero then update the target sync flags
  2117. if( flags != 0 )
  2118. sp->flags = flags;
  2119. else
  2120. {
  2121. // otherwise delete the sync recd assoc'd with syncGrH
  2122. if( pp == NULL )
  2123. p->syncs = sp->link;
  2124. else
  2125. pp->link = sp->link;
  2126. cmMemFree(sp);
  2127. }
  2128. }
  2129. }
  2130. void cmGrReport( cmGrH_t h,cmRpt_t* r )
  2131. {
  2132. cmGr_t* p = _cmGrHandleToPtr(h);
  2133. cmRpt_t* rpt = r==NULL ? p->err.rpt : r;
  2134. cmRptPrintf(rpt,"cfg:0x%x state:0x%x\n",p->cfgFlags, p->stateFlags);
  2135. //cmRptPrintf(rpt,"World: "); cmGrVExtMaxXpt(&p->wext,rpt); cmRptPrintf(rpt,"\n");
  2136. cmRptPrintf(rpt,"View: "); cmGrVExtRpt(&p->vext,rpt); cmRptPrintf(rpt,"\n");
  2137. cmRptPrintf(rpt,"Phys: "); cmGrPExtRpt(&p->pext,rpt); cmRptPrintf(rpt,"\n");
  2138. _cmGrObjReportR(p,p->rootObj,rpt);
  2139. }