libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmGrDevCtx.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmGlobal.h"
  4. #include "cmFloatTypes.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmGr.h"
  11. #include "cmGrDevCtx.h"
  12. #define _cmGrDcOffsX(p,xx) (xx) // ((p)->pext.loc.x + (xx))
  13. #define _cmGrDcOffsY(p,yy) (yy) // ((p)->pext.loc.y + (yy))
  14. cmGrDcH_t cmGrDcNullHandle = cmSTATIC_NULL_HANDLE;
  15. // cmGrDcRecd is used to store the state of the
  16. // device context on the cmGrDC_t stack.
  17. typedef struct cmGrDcRecd_str
  18. {
  19. cmGrColor_t color;
  20. unsigned fontId;
  21. unsigned fontStyle;
  22. unsigned fontSize;
  23. unsigned penWidth;
  24. unsigned penStyle;
  25. struct cmGrDcRecd_str* next;
  26. struct cmGrDcRecd_str* prev;
  27. } cmGrDcRecd_t;
  28. typedef struct cmGrDc_str
  29. {
  30. cmErr_t err;
  31. cmGrDev_t* dd; // device driver used by this context
  32. void* ddArg; // user assigned device driver callback arg
  33. cmGrDcRecd_t* list; // First recd on the stack (not the top).
  34. cmGrDcRecd_t* cur; // Top recd on the stack.
  35. cmGrPExt_t pext; // x,y is offset added to all drawing coordinates
  36. // w,h is size of drawing area
  37. } cmGrDc_t;
  38. // Note: recd's prior to p->cur are available.
  39. // Recd's after p->cur are on the stack.
  40. cmGrDc_t* _cmGrDcHandleToPtr( cmGrDcH_t h )
  41. {
  42. cmGrDc_t* p = (cmGrDc_t*)h.h;
  43. assert( p != NULL );
  44. return p;
  45. }
  46. void _cmGrDcRecdPrint( const cmChar_t* label, const cmGrDcRecd_t* r )
  47. {
  48. printf("%s r:%i g:%i b:%i fid:%i fs:0x%x fsz:%i pw:%i ps:0x%x\n",
  49. cmStringNullGuard(label),
  50. cmGrColorToR(r->color),cmGrColorToG(r->color),cmGrColorToB(r->color),
  51. r->fontId,r->fontStyle,r->fontSize,r->penWidth,r->penStyle);
  52. }
  53. // Make a duplicate of the current record (if it exists)
  54. // and insert it prior to the current record.
  55. // make the new record current.
  56. void _cmGrDcPush( cmGrDc_t* p )
  57. {
  58. if( p->cur == NULL )
  59. {
  60. assert( p->list == NULL );
  61. cmGrDcRecd_t* r = cmMemAllocZ( cmGrDcRecd_t, 1);
  62. p->dd->get_color( p->ddArg, &r->color );
  63. r->fontId = p->dd->get_font_family(p->ddArg );
  64. r->fontSize = p->dd->get_font_size( p->ddArg );
  65. r->fontStyle = p->dd->get_font_style( p->ddArg );
  66. r->penWidth = p->dd->get_pen_width( p->ddArg );
  67. r->penStyle = p->dd->get_pen_style( p->ddArg );
  68. p->list = r;
  69. p->cur = r;
  70. }
  71. else
  72. {
  73. cmGrDcRecd_t* r = p->cur->prev;
  74. // if no prev recd exists ...
  75. if( r == NULL )
  76. {
  77. // .... then allocate one
  78. r = cmMemAllocZ( cmGrDcRecd_t, 1 );
  79. *r = *p->cur;
  80. p->cur->prev = r;
  81. r->next = p->cur;
  82. }
  83. else
  84. {
  85. // ... otherwise use the prev one
  86. cmGrDcRecd_t* nrp = r->next;
  87. cmGrDcRecd_t* prp = r->prev;
  88. *r = *p->cur;
  89. r->next = nrp;
  90. r->prev = prp;
  91. }
  92. // make the new recd the cur recd
  93. p->cur = r;
  94. // if the new recd is the first on the list
  95. // then update the list begin pointer
  96. if( p->cur->prev == NULL )
  97. p->list = p->cur;
  98. }
  99. //_cmGrDcRecdPrint("push:", p->cur );
  100. }
  101. cmGrDcRC_t _cmGrDcPop(cmGrDc_t* p )
  102. {
  103. if( p->cur==NULL || p->cur->next == NULL )
  104. return cmErrMsg(&p->err,kStackFaultGrDcRC,"Cannot pop the last context record off the stack.");
  105. p->cur = p->cur->next;
  106. p->dd->set_color( p->ddArg, p->cur->color );
  107. p->dd->set_font_family( p->ddArg, p->cur->fontId );
  108. p->dd->set_font_size( p->ddArg, p->cur->fontSize );
  109. p->dd->set_font_style( p->ddArg, p->cur->fontStyle );
  110. p->dd->set_pen_width( p->ddArg, p->cur->penWidth );
  111. p->dd->set_pen_style( p->ddArg, p->cur->penStyle );
  112. //_cmGrDcRecdPrint("pop:", p->cur );
  113. return kOkGrDcRC;
  114. }
  115. cmGrDcRC_t _cmGrDcDestroy( cmGrDc_t* p )
  116. {
  117. cmGrDcRecd_t* rp = p->list;
  118. while( rp!=NULL )
  119. {
  120. cmGrDcRecd_t* tp = rp->next;
  121. cmMemFree( rp );
  122. rp = tp;
  123. }
  124. p->dd->destroy(p->ddArg);
  125. cmMemFree(p);
  126. return kOkGrDcRC;
  127. }
  128. cmGrDcRC_t cmGrDevCtxCreate( cmCtx_t* ctx, cmGrDcH_t* hp, cmGrDev_t* dd, void* ddArg, int x, int y, int w, int h )
  129. {
  130. cmGrDcRC_t rc;
  131. if((rc = cmGrDevCtxDestroy(hp)) != kOkGrDcRC )
  132. return rc;
  133. cmGrDc_t* p = cmMemAllocZ(cmGrDc_t,1);
  134. cmErrSetup(&p->err,&ctx->rpt,"cmGrDevCtx");
  135. p->dd = dd;
  136. p->ddArg = ddArg;
  137. cmGrPExtSet(&p->pext,x,y,w,h);
  138. if( dd->create(ddArg,w,h) == false )
  139. {
  140. cmErrMsg(&p->err,kDevDrvFailGrDcRC,"Device driver create failed.");
  141. goto errLabel;
  142. }
  143. _cmGrDcPush(p); // create the default context
  144. hp->h = p;
  145. errLabel:
  146. if(rc != kOkGrDcRC )
  147. _cmGrDcDestroy(p);
  148. return rc;
  149. }
  150. cmGrDcRC_t cmGrDevCtxDestroy( cmGrDcH_t* hp )
  151. {
  152. cmGrDcRC_t rc;
  153. if( hp==NULL || cmGrDevCtxIsValid(*hp)==false )
  154. return kOkGrDcRC;
  155. cmGrDc_t* p = _cmGrDcHandleToPtr(*hp);
  156. if((rc = _cmGrDcDestroy(p)) != kOkGrDcRC )
  157. return rc;
  158. hp->h = NULL;
  159. return rc;
  160. }
  161. bool cmGrDevCtxIsValid( cmGrDcH_t h )
  162. { return h.h != NULL; }
  163. cmGrDcRC_t cmGrDevCtxResize( cmGrDcH_t h, int x, int y, int ww, int hh )
  164. {
  165. cmGrDcRC_t rc = kOkGrDcRC;
  166. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  167. // store the current drawing context state
  168. _cmGrDcPush(p);
  169. if( p->dd->create(p->ddArg,ww,hh) == false )
  170. {
  171. cmErrMsg(&p->err,kDevDrvFailGrDcRC,"Device driver create failed on resize.");
  172. goto errLabel;
  173. }
  174. cmGrPExtSet(&p->pext,x,y,ww,hh);
  175. errLabel:
  176. // force the current state to be reapplied to the new drawing context
  177. _cmGrDcPop(p);
  178. return rc;
  179. }
  180. void cmGrDevCtxSize( cmGrDcH_t h, cmGrPExt_t* pext )
  181. {
  182. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  183. *pext = p->pext;
  184. pext->loc.x *= -1;
  185. pext->loc.y *= -1;
  186. }
  187. void cmGrDevCtxBeginDraw( cmGrDcH_t h )
  188. {
  189. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  190. p->dd->begin_draw( p->ddArg );
  191. }
  192. void cmGrDevCtxEndDraw( cmGrDcH_t h )
  193. {
  194. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  195. p->dd->end_draw( p->ddArg );
  196. }
  197. void cmGrDevCtxDraw( cmGrDcH_t h )
  198. {
  199. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  200. p->dd->draw( p->ddArg, -p->pext.loc.x, -p->pext.loc.y );
  201. }
  202. void cmGrDcPushCtx( cmGrDcH_t h )
  203. {
  204. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  205. _cmGrDcPush(p);
  206. }
  207. void cmGrDcPopCtx( cmGrDcH_t h )
  208. {
  209. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  210. _cmGrDcPop(p);
  211. }
  212. unsigned cmGrDcColor( cmGrDcH_t h )
  213. {
  214. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  215. return p->cur->color;
  216. }
  217. void cmGrDcSetColorRgb( cmGrDcH_t h, unsigned char r, unsigned char g, unsigned char b )
  218. {
  219. cmGrDcSetColor(h,cmGrRgbToColor(r,g,b));
  220. }
  221. void cmGrDcSetColor( cmGrDcH_t h, cmGrColor_t color )
  222. {
  223. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  224. p->dd->set_color( p->ddArg, color );
  225. }
  226. unsigned cmGrDcFontFamily( cmGrDcH_t h )
  227. {
  228. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  229. return p->cur->fontId;
  230. }
  231. void cmGrDcSetFontFamily( cmGrDcH_t h, unsigned fontId )
  232. {
  233. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  234. p->cur->fontId = fontId;
  235. p->dd->set_font_family( p->ddArg, fontId );
  236. }
  237. unsigned cmGrDcFontStyle( cmGrDcH_t h )
  238. {
  239. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  240. return p->cur->fontStyle;
  241. }
  242. void cmGrDcSetFontStyle( cmGrDcH_t h, unsigned style )
  243. {
  244. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  245. p->cur->fontStyle = style;
  246. p->dd->set_font_style( p->ddArg, style );
  247. }
  248. unsigned cmGrDcFontSize( cmGrDcH_t h )
  249. {
  250. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  251. return p->cur->fontSize;
  252. }
  253. void cmGrDcSetFontSize( cmGrDcH_t h, unsigned size )
  254. {
  255. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  256. p->cur->fontSize = size;
  257. p->dd->set_font_size( p->ddArg, size );
  258. }
  259. unsigned cmGrDcPenWidth( cmGrDcH_t h )
  260. {
  261. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  262. return p->cur->penWidth;
  263. }
  264. void cmGrDcSetPenWidth( cmGrDcH_t h, unsigned width )
  265. {
  266. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  267. p->cur->penWidth = width;
  268. p->dd->set_pen_width( p->ddArg, width );
  269. }
  270. unsigned cmGrDcPenStyle( cmGrDcH_t h )
  271. {
  272. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  273. return p->cur->penStyle;
  274. }
  275. void cmGrDcSetPenStyle( cmGrDcH_t h, unsigned style )
  276. {
  277. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  278. p->cur->penStyle = style;
  279. p->dd->set_pen_style( p->ddArg, style );
  280. }
  281. void cmGrDcDrawLine( cmGrDcH_t h, int x0, int y0, int x1, int y1 )
  282. {
  283. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  284. p->dd->draw_line( p->ddArg, _cmGrDcOffsX(p,x0), _cmGrDcOffsY(p,y0), _cmGrDcOffsX(p,x1), _cmGrDcOffsY(p,y1) );
  285. }
  286. void cmGrDcDrawRect( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  287. {
  288. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  289. p->dd->draw_rect( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  290. }
  291. void cmGrDcDrawRectPExt( cmGrDcH_t h, const cmGrPExt_t* pext )
  292. { cmGrDcDrawRect( h, cmGrPExtL(pext), cmGrPExtT(pext), cmGrPExtW(pext), cmGrPExtH(pext) ); }
  293. void cmGrDcFillRect( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  294. {
  295. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  296. p->dd->fill_rect( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  297. }
  298. void cmGrDcDrawEllipse( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  299. {
  300. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  301. p->dd->draw_ellipse( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  302. }
  303. void cmGrDcFillEllipse( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  304. {
  305. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  306. p->dd->fill_ellipse( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  307. }
  308. void cmGrDcDrawDiamond( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  309. {
  310. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  311. p->dd->draw_diamond( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  312. }
  313. void cmGrDcFillDiamond( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh )
  314. {
  315. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  316. p->dd->fill_diamond( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh );
  317. }
  318. void cmGrDcDrawTriangle( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh, unsigned dirFlag )
  319. {
  320. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  321. p->dd->draw_triangle( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh, dirFlag );
  322. }
  323. void cmGrDcFillTriangle( cmGrDcH_t h, int x, int y, unsigned ww, unsigned hh, unsigned dirFlag )
  324. {
  325. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  326. p->dd->fill_triangle( p->ddArg, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), ww, hh, dirFlag );
  327. }
  328. void cmGrDcMeasure( cmGrDcH_t h, const cmChar_t* text, cmGrPSz_t* sz )
  329. {
  330. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  331. if( text == NULL )
  332. cmGrPSzSet(sz,0,0);
  333. else
  334. {
  335. unsigned ww,hh;
  336. p->dd->measure_text( p->ddArg, text, &ww, &hh );
  337. sz->w = ww;
  338. sz->h = hh;
  339. }
  340. }
  341. void cmGrDcDrawText( cmGrDcH_t h, const cmChar_t* text, int x, int y )
  342. {
  343. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  344. p->dd->draw_text( p->ddArg, text, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y) );
  345. }
  346. void cmGrDcDrawTextRot( cmGrDcH_t h, const cmChar_t* text, int x, int y, int angle )
  347. {
  348. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  349. p->dd->draw_text_rot( p->ddArg, text, _cmGrDcOffsX(p,x), _cmGrDcOffsY(p,y), angle );
  350. }
  351. void cmGrDcReadImage( cmGrDcH_t h, unsigned char* a, const cmGrPExt_t* pext )
  352. {
  353. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  354. p->dd->read_image( p->ddArg, a, _cmGrDcOffsX(p,pext->loc.x), _cmGrDcOffsY(p,pext->loc.y), pext->sz.w, pext->sz.h );
  355. }
  356. void cmGrDcDrawImage( cmGrDcH_t h, const unsigned char* a, const cmGrPExt_t* pext )
  357. {
  358. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  359. p->dd->draw_image( p->ddArg, a, _cmGrDcOffsX(p,pext->loc.x), _cmGrDcOffsY(p,pext->loc.y), pext->sz.w, pext->sz.h );
  360. }
  361. void cmGrDcSetFont( cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style )
  362. {
  363. cmGrDcSetFontFamily(h,fontId);
  364. cmGrDcSetFontSize( h,size);
  365. cmGrDcSetFontStyle( h,style);
  366. }
  367. void cmGrDcFontSetAndMeasure(cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style, const cmChar_t* text, cmGrPSz_t* sz )
  368. {
  369. cmGrDcSetFont(h,fontId,size,style);
  370. cmGrDcMeasure(h,text,sz);
  371. }
  372. void cmGrDcDrawTextJustify( cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style, const cmChar_t* text, const cmGrPExt_t* pext, unsigned flags )
  373. {
  374. int x = cmGrPExtCtrX(pext);
  375. int y = cmGrPExtCtrY(pext);
  376. if( cmIsFlag(flags,kNorthJsGrFl) )
  377. y = cmGrPExtT(pext);
  378. else
  379. if( cmIsFlag(flags,kSouthJsGrFl) )
  380. y = cmGrPExtB(pext);
  381. if( cmIsFlag(flags,kEastJsGrFl) )
  382. x = cmGrPExtR(pext);
  383. else
  384. if( cmIsFlag(flags,kWestJsGrFl) )
  385. x = cmGrPExtL(pext);
  386. cmGrDcDrawTextJustifyPt(h,fontId,size,style,text,flags,x,y);
  387. }
  388. void cmGrDcDrawTextJustifyPt( cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style, const cmChar_t* text, unsigned flags, int xx, int yy )
  389. {
  390. cmGrPSz_t sz;
  391. cmGrDcFontSetAndMeasure(h, fontId, size, style, text, &sz );
  392. int x,y;
  393. if( cmIsFlag(flags,kRightJsGrFl) )
  394. x = xx;
  395. else
  396. if( cmIsFlag(flags,kLeftJsGrFl) )
  397. x = xx - sz.w;
  398. else
  399. x = xx - sz.w/2;
  400. if( cmIsFlag(flags,kBottomJsGrFl) )
  401. y = yy;
  402. else
  403. if( cmIsFlag(flags,kTopJsGrFl) )
  404. y = yy + sz.h;
  405. else
  406. y = yy + sz.h/2;
  407. cmGrPExt_t r;
  408. cmGrPExtSet(&r,x,y,sz.w,sz.h);
  409. // Note: Checking for visibility should not be necessary however
  410. // there appears to be a problem with the FLTK text output whereby
  411. // text coordinates over 0xffff wrap around and may appear in the
  412. // visible region.
  413. if( cmGrDcRectIsVisible(h,&r) )
  414. {
  415. /*
  416. if( text!=NULL && (strncmp(text,"loc:138",7)==0 || strcmp(text,"loc:8 ")==0))
  417. {
  418. printf("%s %i %i %i %i\n",text,x,y,sz.w,xx);
  419. cmGrPExtPrint(text,&r);
  420. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  421. cmGrPExt_t res;
  422. cmGrPExtIntersect(&res,&p->pext,&r );
  423. cmGrPExtPrint(text,&p->pext);
  424. cmGrPExtPrint("isect:",&res);
  425. printf("%i\n",cmGrPExtIsNotNullOrEmpty(&res));
  426. }
  427. */
  428. cmGrDcDrawText(h, text, x+.5, y+.5 );
  429. }
  430. //cmGrPExt_t pext;
  431. //cmGrDcDrawTextJustifyRect(h, fontId, size, style, text, flags, xx, yy, &pext );
  432. //cmGrDcDrawRectPExt(h,&pext);
  433. }
  434. void cmGrDcDrawTextJustifyRect( cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style, const cmChar_t* text, unsigned flags, int xx, int yy, cmGrPExt_t* pext )
  435. {
  436. cmGrPSz_t sz;
  437. cmGrDcFontSetAndMeasure(h, fontId, size, style, text, &sz );
  438. int x,y;
  439. if( cmIsFlag(flags,kRightJsGrFl) )
  440. x = xx;
  441. else
  442. if( cmIsFlag(flags,kLeftJsGrFl) )
  443. x = xx - sz.w;
  444. else
  445. x = xx - sz.w/2;
  446. if( cmIsFlag(flags,kBottomJsGrFl) )
  447. y = yy;
  448. else
  449. if( cmIsFlag(flags,kTopJsGrFl) )
  450. y = yy + sz.h;
  451. else
  452. y = yy + sz.h/2;
  453. cmGrPExtSet( pext, x, y-sz.h, sz.w+1, sz.h );
  454. }
  455. bool cmGrDcPointIsVisible( cmGrDcH_t h, int x, int y )
  456. {
  457. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  458. return cmGrVExtIsXyInside(&p->pext,x,y);
  459. }
  460. bool cmGrDcRectIsVisible( cmGrDcH_t h, const cmGrPExt_t* r )
  461. {
  462. cmGrPExt_t res;
  463. cmGrDc_t* p = _cmGrDcHandleToPtr(h);
  464. cmGrPExtIntersect(&res,&p->pext,r );
  465. return cmGrPExtIsNotNullOrEmpty(&res);
  466. }