libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmGr.c 73KB

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