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

cmGrDevCtx.c 14KB

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