libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmGr.c 72KB

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