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

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