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 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. cmGrDcDrawText(h, text, x+.5, y+.5 );
  404. //cmGrPExt_t pext;
  405. //cmGrDcDrawTextJustifyRect(h, fontId, size, style, text, flags, xx, yy, &pext );
  406. //cmGrDcDrawRectPExt(h,&pext);
  407. }
  408. void cmGrDcDrawTextJustifyRect( cmGrDcH_t h, unsigned fontId, unsigned size, unsigned style, const cmChar_t* text, unsigned flags, int xx, int yy, cmGrPExt_t* pext )
  409. {
  410. cmGrPSz_t sz;
  411. cmGrDcFontSetAndMeasure(h, fontId, size, style, text, &sz );
  412. int x,y;
  413. if( cmIsFlag(flags,kRightJsGrFl) )
  414. x = xx;
  415. else
  416. if( cmIsFlag(flags,kLeftJsGrFl) )
  417. x = xx - sz.w;
  418. else
  419. x = xx - sz.w/2;
  420. if( cmIsFlag(flags,kBottomJsGrFl) )
  421. y = yy;
  422. else
  423. if( cmIsFlag(flags,kTopJsGrFl) )
  424. y = yy + sz.h;
  425. else
  426. y = yy + sz.h/2;
  427. cmGrPExtSet( pext, x, y-sz.h, sz.w+1, sz.h );
  428. }