nuklear_rawfb.h 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) 2016-2017 Patrick Rudolph <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. /*
  23. * ==============================================================
  24. *
  25. * API
  26. *
  27. * ===============================================================
  28. */
  29. #ifndef NK_RAWFB_H_
  30. #define NK_RAWFB_H_
  31. struct rawfb_context;
  32. struct rawfb_pl {
  33. unsigned char bytesPerPixel;
  34. unsigned char rshift, gshift, bshift, ashift;
  35. unsigned char rloss, gloss, bloss, aloss;
  36. };
  37. /* All functions are thread-safe */
  38. NK_API struct rawfb_context *nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl);
  39. NK_API void nk_rawfb_render(const struct rawfb_context *rawfb, const struct nk_color clear, const unsigned char enable_clear);
  40. NK_API void nk_rawfb_shutdown(struct rawfb_context *rawfb);
  41. NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, void *fb, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl);
  42. #endif
  43. /*
  44. * ==============================================================
  45. *
  46. * IMPLEMENTATION
  47. *
  48. * ===============================================================
  49. */
  50. #ifdef NK_RAWFB_IMPLEMENTATION
  51. #include <string.h>
  52. #include <stdlib.h>
  53. #include <assert.h>
  54. struct rawfb_image {
  55. void *pixels;
  56. int w, h, pitch;
  57. struct rawfb_pl pl;
  58. };
  59. struct rawfb_context {
  60. struct nk_context ctx;
  61. struct nk_rect scissors;
  62. struct rawfb_image fb;
  63. struct rawfb_image font_tex;
  64. struct nk_font_atlas atlas;
  65. };
  66. typedef unsigned int rawfb_color;
  67. #ifndef MIN
  68. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  69. #endif
  70. #ifndef MAX
  71. #define MAX(a,b) ((a) < (b) ? (b) : (a))
  72. #endif
  73. static rawfb_color
  74. nk_rawfb_color2int(const struct nk_color c, const struct rawfb_pl *pl)
  75. {
  76. unsigned int res = 0;
  77. res |= (c.r >> pl->rloss) << pl->rshift;
  78. res |= (c.g >> pl->gloss) << pl->gshift;
  79. res |= (c.b >> pl->bloss) << pl->bshift;
  80. res |= (c.a >> pl->aloss) << pl->ashift;
  81. return (res);
  82. }
  83. static struct nk_color
  84. nk_rawfb_int2color(const rawfb_color i, const struct rawfb_pl *pl)
  85. {
  86. struct nk_color col = {0,0,0,0};
  87. col.r = (pl->rloss == 8) ? 0xff : ((i >> pl->rshift) << pl->rloss) & 0xff;
  88. col.g = (pl->gloss == 8) ? 0xff : ((i >> pl->gshift) << pl->gloss) & 0xff;
  89. col.b = (pl->bloss == 8) ? 0xff : ((i >> pl->bshift) << pl->bloss) & 0xff;
  90. col.a = (pl->aloss == 8) ? 0xff : ((i >> pl->ashift) << pl->aloss) & 0xff;
  91. return col;
  92. }
  93. static void
  94. nk_rawfb_ctx_setpixel(const struct rawfb_context *rawfb,
  95. const short x0, const short y0, const rawfb_color col)
  96. {
  97. unsigned char *pixels = rawfb->fb.pixels;
  98. pixels += y0 * rawfb->fb.pitch;
  99. if (y0 < rawfb->scissors.h && y0 >= rawfb->scissors.y &&
  100. x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w) {
  101. if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned int)) {
  102. *((unsigned int *)pixels + x0) = col;
  103. } else if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned short)) {
  104. *((unsigned short *)pixels + x0) = col;
  105. } else {
  106. *((unsigned char *)pixels + x0) = col;
  107. }
  108. }
  109. }
  110. static void
  111. nk_rawfb_line_horizontal(const struct rawfb_context *rawfb,
  112. const short x0, const short y, const short x1, const rawfb_color col)
  113. {
  114. /* This function is called the most. Try to optimize it a bit...
  115. * It does not check for scissors or image borders.
  116. * The caller has to make sure it does no exceed bounds. */
  117. unsigned int i, n;
  118. unsigned char c[16 * 4];
  119. unsigned char *pixels = rawfb->fb.pixels;
  120. unsigned int bpp = rawfb->fb.pl.bytesPerPixel;
  121. pixels += (y * rawfb->fb.pitch) + (x0 * bpp);
  122. n = (x1 - x0) * bpp;
  123. if (bpp == sizeof(unsigned int)) {
  124. for (i = 0; i < sizeof(c) / bpp; i++)
  125. ((unsigned int *)c)[i] = col;
  126. } else if (bpp == sizeof(unsigned short)) {
  127. for (i = 0; i < sizeof(c) / bpp; i++)
  128. ((unsigned short *)c)[i] = col;
  129. } else {
  130. for (i = 0; i < sizeof(c) / bpp; i++)
  131. ((unsigned char *)c)[i] = col;
  132. }
  133. while (n > sizeof(c)) {
  134. memcpy((void*)pixels, c, sizeof(c));
  135. n -= sizeof(c); pixels += sizeof(c);
  136. } for (i = 0; i < n; i++)
  137. pixels[i] = c[i];
  138. }
  139. static void
  140. nk_rawfb_img_setpixel(const struct rawfb_image *img,
  141. const int x0, const int y0, const struct nk_color col)
  142. {
  143. unsigned int c = nk_rawfb_color2int(col, &img->pl);
  144. unsigned char *ptr;
  145. NK_ASSERT(img);
  146. if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
  147. ptr = (unsigned char *)img->pixels + (img->pitch * y0);
  148. if (img->pl.bytesPerPixel == sizeof(unsigned int)) {
  149. ((unsigned int *)ptr)[x0] = c;
  150. } else if (img->pl.bytesPerPixel == sizeof(unsigned short)) {
  151. ((unsigned short *)ptr)[x0] = c;
  152. } else {
  153. ((unsigned char *)ptr)[x0] = c;
  154. }
  155. }
  156. }
  157. static struct nk_color
  158. nk_rawfb_img_getpixel(const struct rawfb_image *img, const int x0, const int y0)
  159. {
  160. struct nk_color col = {0, 0, 0, 0};
  161. unsigned char *ptr;
  162. unsigned int pixel;
  163. NK_ASSERT(img);
  164. if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
  165. ptr = (unsigned char *)img->pixels + (img->pitch * y0);
  166. if (img->pl.bytesPerPixel == sizeof(unsigned int)) {
  167. pixel = ((unsigned int *)ptr)[x0];
  168. col = nk_rawfb_int2color(pixel, &img->pl);
  169. } else if (img->pl.bytesPerPixel == sizeof(unsigned short)) {
  170. pixel = ((unsigned short *)ptr)[x0];
  171. col = nk_rawfb_int2color(pixel, &img->pl);
  172. } else {
  173. pixel = ((unsigned char *)ptr)[x0];
  174. col = nk_rawfb_int2color(pixel, &img->pl);
  175. }
  176. } return col;
  177. }
  178. static void
  179. nk_rawfb_img_blendpixel(const struct rawfb_image *img,
  180. const int x0, const int y0, struct nk_color col)
  181. {
  182. struct nk_color col2;
  183. unsigned char inv_a;
  184. if (col.a == 0)
  185. return;
  186. inv_a = 0xff - col.a;
  187. col2 = nk_rawfb_img_getpixel(img, x0, y0);
  188. col.r = (col.r * col.a + col2.r * inv_a) >> 8;
  189. col.g = (col.g * col.a + col2.g * inv_a) >> 8;
  190. col.b = (col.b * col.a + col2.b * inv_a) >> 8;
  191. nk_rawfb_img_setpixel(img, x0, y0, col);
  192. }
  193. static void
  194. nk_rawfb_scissor(struct rawfb_context *rawfb,
  195. const float x,
  196. const float y,
  197. const float w,
  198. const float h)
  199. {
  200. rawfb->scissors.x = MIN(MAX(x, 0), rawfb->fb.w);
  201. rawfb->scissors.y = MIN(MAX(y, 0), rawfb->fb.h);
  202. rawfb->scissors.w = MIN(MAX(w + x, 0), rawfb->fb.w);
  203. rawfb->scissors.h = MIN(MAX(h + y, 0), rawfb->fb.h);
  204. }
  205. static void
  206. nk_rawfb_stroke_line(const struct rawfb_context *rawfb,
  207. short x0, short y0, short x1, short y1,
  208. const unsigned int line_thickness, const rawfb_color col)
  209. {
  210. short tmp;
  211. int dy, dx, stepx, stepy;
  212. NK_UNUSED(line_thickness);
  213. dy = y1 - y0;
  214. dx = x1 - x0;
  215. /* fast path */
  216. if (dy == 0) {
  217. if (dx == 0 || y0 >= rawfb->scissors.h || y0 < rawfb->scissors.y)
  218. return;
  219. if (dx < 0) {
  220. /* swap x0 and x1 */
  221. tmp = x1;
  222. x1 = x0;
  223. x0 = tmp;
  224. }
  225. x1 = MIN(rawfb->scissors.w, x1);
  226. x0 = MIN(rawfb->scissors.w, x0);
  227. x1 = MAX(rawfb->scissors.x, x1);
  228. x0 = MAX(rawfb->scissors.x, x0);
  229. nk_rawfb_line_horizontal(rawfb, x0, y0, x1, col);
  230. return;
  231. }
  232. if (dy < 0) {
  233. dy = -dy;
  234. stepy = -1;
  235. } else stepy = 1;
  236. if (dx < 0) {
  237. dx = -dx;
  238. stepx = -1;
  239. } else stepx = 1;
  240. dy <<= 1;
  241. dx <<= 1;
  242. nk_rawfb_ctx_setpixel(rawfb, x0, y0, col);
  243. if (dx > dy) {
  244. int fraction = dy - (dx >> 1);
  245. while (x0 != x1) {
  246. if (fraction >= 0) {
  247. y0 += stepy;
  248. fraction -= dx;
  249. }
  250. x0 += stepx;
  251. fraction += dy;
  252. nk_rawfb_ctx_setpixel(rawfb, x0, y0, col);
  253. }
  254. } else {
  255. int fraction = dx - (dy >> 1);
  256. while (y0 != y1) {
  257. if (fraction >= 0) {
  258. x0 += stepx;
  259. fraction -= dy;
  260. }
  261. y0 += stepy;
  262. fraction += dx;
  263. nk_rawfb_ctx_setpixel(rawfb, x0, y0, col);
  264. }
  265. }
  266. }
  267. static void
  268. nk_rawfb_fill_polygon(const struct rawfb_context *rawfb,
  269. const struct nk_vec2i *pnts, int count, const rawfb_color col)
  270. {
  271. int i = 0;
  272. #define MAX_POINTS 64
  273. int left = 10000, top = 10000, bottom = 0, right = 0;
  274. int nodes, nodeX[MAX_POINTS], pixelX, pixelY, j, swap ;
  275. if (count == 0) return;
  276. if (count > MAX_POINTS)
  277. count = MAX_POINTS;
  278. /* Get polygon dimensions */
  279. for (i = 0; i < count; i++) {
  280. if (left > pnts[i].x)
  281. left = pnts[i].x;
  282. if (right < pnts[i].x)
  283. right = pnts[i].x;
  284. if (top > pnts[i].y)
  285. top = pnts[i].y;
  286. if (bottom < pnts[i].y)
  287. bottom = pnts[i].y;
  288. } bottom++; right++;
  289. /* Polygon scanline algorithm released under public-domain by Darel Rex Finley, 2007 */
  290. /* Loop through the rows of the image. */
  291. for (pixelY = top; pixelY < bottom; pixelY ++) {
  292. nodes = 0; /* Build a list of nodes. */
  293. j = count - 1;
  294. for (i = 0; i < count; i++) {
  295. if (((pnts[i].y < pixelY) && (pnts[j].y >= pixelY)) ||
  296. ((pnts[j].y < pixelY) && (pnts[i].y >= pixelY))) {
  297. nodeX[nodes++]= (int)((float)pnts[i].x
  298. + ((float)pixelY - (float)pnts[i].y) / ((float)pnts[j].y - (float)pnts[i].y)
  299. * ((float)pnts[j].x - (float)pnts[i].x));
  300. } j = i;
  301. }
  302. /* Sort the nodes, via a simple “Bubble” sort. */
  303. i = 0;
  304. while (i < nodes - 1) {
  305. if (nodeX[i] > nodeX[i+1]) {
  306. swap = nodeX[i];
  307. nodeX[i] = nodeX[i+1];
  308. nodeX[i+1] = swap;
  309. if (i) i--;
  310. } else i++;
  311. }
  312. /* Fill the pixels between node pairs. */
  313. for (i = 0; i < nodes; i += 2) {
  314. if (nodeX[i+0] >= right) break;
  315. if (nodeX[i+1] > left) {
  316. if (nodeX[i+0] < left) nodeX[i+0] = left ;
  317. if (nodeX[i+1] > right) nodeX[i+1] = right;
  318. for (pixelX = nodeX[i]; pixelX < nodeX[i + 1]; pixelX++)
  319. nk_rawfb_ctx_setpixel(rawfb, pixelX, pixelY, col);
  320. }
  321. }
  322. }
  323. #undef MAX_POINTS
  324. }
  325. static void
  326. nk_rawfb_stroke_arc(const struct rawfb_context *rawfb,
  327. short x0, short y0, short w, short h, const short s,
  328. const short line_thickness, const rawfb_color col)
  329. {
  330. /* Bresenham's ellipses - modified to draw one quarter */
  331. const int a2 = (w * w) / 4;
  332. const int b2 = (h * h) / 4;
  333. const int fa2 = 4 * a2, fb2 = 4 * b2;
  334. int x, y, sigma;
  335. NK_UNUSED(line_thickness);
  336. if (s != 0 && s != 90 && s != 180 && s != 270) return;
  337. if (w < 1 || h < 1) return;
  338. /* Convert upper left to center */
  339. h = (h + 1) / 2;
  340. w = (w + 1) / 2;
  341. x0 += w; y0 += h;
  342. /* First half */
  343. for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) {
  344. if (s == 180)
  345. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col);
  346. else if (s == 270)
  347. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col);
  348. else if (s == 0)
  349. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col);
  350. else if (s == 90)
  351. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col);
  352. if (sigma >= 0) {
  353. sigma += fa2 * (1 - y);
  354. y--;
  355. } sigma += b2 * ((4 * x) + 6);
  356. }
  357. /* Second half */
  358. for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) {
  359. if (s == 180)
  360. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col);
  361. else if (s == 270)
  362. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col);
  363. else if (s == 0)
  364. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col);
  365. else if (s == 90)
  366. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col);
  367. if (sigma >= 0) {
  368. sigma += fb2 * (1 - x);
  369. x--;
  370. } sigma += a2 * ((4 * y) + 6);
  371. }
  372. }
  373. static void
  374. nk_rawfb_fill_arc(const struct rawfb_context *rawfb, short x0, short y0,
  375. short w, short h, const short s, const rawfb_color col)
  376. {
  377. /* Bresenham's ellipses - modified to fill one quarter */
  378. const int a2 = (w * w) / 4;
  379. const int b2 = (h * h) / 4;
  380. const int fa2 = 4 * a2, fb2 = 4 * b2;
  381. int x, y, sigma;
  382. struct nk_vec2i pnts[3];
  383. if (w < 1 || h < 1) return;
  384. if (s != 0 && s != 90 && s != 180 && s != 270)
  385. return;
  386. /* Convert upper left to center */
  387. h = (h + 1) / 2;
  388. w = (w + 1) / 2;
  389. x0 += w;
  390. y0 += h;
  391. pnts[0].x = x0;
  392. pnts[0].y = y0;
  393. pnts[2].x = x0;
  394. pnts[2].y = y0;
  395. /* First half */
  396. for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) {
  397. if (s == 180) {
  398. pnts[1].x = x0 + x; pnts[1].y = y0 + y;
  399. } else if (s == 270) {
  400. pnts[1].x = x0 - x; pnts[1].y = y0 + y;
  401. } else if (s == 0) {
  402. pnts[1].x = x0 + x; pnts[1].y = y0 - y;
  403. } else if (s == 90) {
  404. pnts[1].x = x0 - x; pnts[1].y = y0 - y;
  405. }
  406. nk_rawfb_fill_polygon(rawfb, pnts, 3, col);
  407. pnts[2] = pnts[1];
  408. if (sigma >= 0) {
  409. sigma += fa2 * (1 - y);
  410. y--;
  411. } sigma += b2 * ((4 * x) + 6);
  412. }
  413. /* Second half */
  414. for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) {
  415. if (s == 180) {
  416. pnts[1].x = x0 + x; pnts[1].y = y0 + y;
  417. } else if (s == 270) {
  418. pnts[1].x = x0 - x; pnts[1].y = y0 + y;
  419. } else if (s == 0) {
  420. pnts[1].x = x0 + x; pnts[1].y = y0 - y;
  421. } else if (s == 90) {
  422. pnts[1].x = x0 - x; pnts[1].y = y0 - y;
  423. }
  424. nk_rawfb_fill_polygon(rawfb, pnts, 3, col);
  425. pnts[2] = pnts[1];
  426. if (sigma >= 0) {
  427. sigma += fb2 * (1 - x);
  428. x--;
  429. } sigma += a2 * ((4 * y) + 6);
  430. }
  431. }
  432. static void
  433. nk_rawfb_stroke_rect(const struct rawfb_context *rawfb,
  434. const short x, const short y, const short w, const short h,
  435. const short r, const short line_thickness, const rawfb_color col)
  436. {
  437. if (r == 0) {
  438. nk_rawfb_stroke_line(rawfb, x, y, x + w, y, line_thickness, col);
  439. nk_rawfb_stroke_line(rawfb, x, y + h, x + w, y + h, line_thickness, col);
  440. nk_rawfb_stroke_line(rawfb, x, y, x, y + h, line_thickness, col);
  441. nk_rawfb_stroke_line(rawfb, x + w, y, x + w, y + h, line_thickness, col);
  442. } else {
  443. const short xc = x + r;
  444. const short yc = y + r;
  445. const short wc = (short)(w - 2 * r);
  446. const short hc = (short)(h - 2 * r);
  447. nk_rawfb_stroke_line(rawfb, xc, y, xc + wc, y, line_thickness, col);
  448. nk_rawfb_stroke_line(rawfb, x + w, yc, x + w, yc + hc, line_thickness, col);
  449. nk_rawfb_stroke_line(rawfb, xc, y + h, xc + wc, y + h, line_thickness, col);
  450. nk_rawfb_stroke_line(rawfb, x, yc, x, yc + hc, line_thickness, col);
  451. nk_rawfb_stroke_arc(rawfb, xc + wc - r, y,
  452. (unsigned)r*2, (unsigned)r*2, 0 , line_thickness, col);
  453. nk_rawfb_stroke_arc(rawfb, x, y,
  454. (unsigned)r*2, (unsigned)r*2, 90 , line_thickness, col);
  455. nk_rawfb_stroke_arc(rawfb, x, yc + hc - r,
  456. (unsigned)r*2, (unsigned)r*2, 270 , line_thickness, col);
  457. nk_rawfb_stroke_arc(rawfb, xc + wc - r, yc + hc - r,
  458. (unsigned)r*2, (unsigned)r*2, 180 , line_thickness, col);
  459. }
  460. }
  461. static void
  462. nk_rawfb_fill_rect(const struct rawfb_context *rawfb,
  463. const short x, const short y, const short w, const short h,
  464. const short r, const rawfb_color col)
  465. {
  466. int i;
  467. if (r == 0) {
  468. for (i = 0; i < h; i++)
  469. nk_rawfb_stroke_line(rawfb, x, y + i, x + w, y + i, 1, col);
  470. } else {
  471. const short xc = x + r;
  472. const short yc = y + r;
  473. const short wc = (short)(w - 2 * r);
  474. const short hc = (short)(h - 2 * r);
  475. struct nk_vec2i pnts[12];
  476. pnts[0].x = x;
  477. pnts[0].y = yc;
  478. pnts[1].x = xc;
  479. pnts[1].y = yc;
  480. pnts[2].x = xc;
  481. pnts[2].y = y;
  482. pnts[3].x = xc + wc;
  483. pnts[3].y = y;
  484. pnts[4].x = xc + wc;
  485. pnts[4].y = yc;
  486. pnts[5].x = x + w;
  487. pnts[5].y = yc;
  488. pnts[6].x = x + w;
  489. pnts[6].y = yc + hc;
  490. pnts[7].x = xc + wc;
  491. pnts[7].y = yc + hc;
  492. pnts[8].x = xc + wc;
  493. pnts[8].y = y + h;
  494. pnts[9].x = xc;
  495. pnts[9].y = y + h;
  496. pnts[10].x = xc;
  497. pnts[10].y = yc + hc;
  498. pnts[11].x = x;
  499. pnts[11].y = yc + hc;
  500. nk_rawfb_fill_polygon(rawfb, pnts, 12, col);
  501. nk_rawfb_fill_arc(rawfb, xc + wc - r, y,
  502. (unsigned)r*2, (unsigned)r*2, 0 , col);
  503. nk_rawfb_fill_arc(rawfb, x, y,
  504. (unsigned)r*2, (unsigned)r*2, 90 , col);
  505. nk_rawfb_fill_arc(rawfb, x, yc + hc - r,
  506. (unsigned)r*2, (unsigned)r*2, 270 , col);
  507. nk_rawfb_fill_arc(rawfb, xc + wc - r, yc + hc - r,
  508. (unsigned)r*2, (unsigned)r*2, 180 , col);
  509. }
  510. }
  511. NK_API void
  512. nk_rawfb_draw_rect_multi_color(const struct rawfb_context *rawfb,
  513. const short x, const short y, const short w, const short h, struct nk_color tl,
  514. struct nk_color tr, struct nk_color br, struct nk_color bl)
  515. {
  516. int i, j;
  517. struct nk_color *edge_buf;
  518. struct nk_color *edge_t;
  519. struct nk_color *edge_b;
  520. struct nk_color *edge_l;
  521. struct nk_color *edge_r;
  522. struct nk_color pixel;
  523. edge_buf = malloc(((2*w) + (2*h)) * sizeof(struct nk_color));
  524. if (edge_buf == NULL)
  525. return;
  526. edge_t = edge_buf;
  527. edge_b = edge_buf + w;
  528. edge_l = edge_buf + (w*2);
  529. edge_r = edge_buf + (w*2) + h;
  530. /* Top and bottom edge gradients */
  531. for (i=0; i<w; i++)
  532. {
  533. edge_t[i].r = (((((float)tr.r - tl.r)/(w-1))*i) + 0.5) + tl.r;
  534. edge_t[i].g = (((((float)tr.g - tl.g)/(w-1))*i) + 0.5) + tl.g;
  535. edge_t[i].b = (((((float)tr.b - tl.b)/(w-1))*i) + 0.5) + tl.b;
  536. edge_t[i].a = (((((float)tr.a - tl.a)/(w-1))*i) + 0.5) + tl.a;
  537. edge_b[i].r = (((((float)br.r - bl.r)/(w-1))*i) + 0.5) + bl.r;
  538. edge_b[i].g = (((((float)br.g - bl.g)/(w-1))*i) + 0.5) + bl.g;
  539. edge_b[i].b = (((((float)br.b - bl.b)/(w-1))*i) + 0.5) + bl.b;
  540. edge_b[i].a = (((((float)br.a - bl.a)/(w-1))*i) + 0.5) + bl.a;
  541. }
  542. /* Left and right edge gradients */
  543. for (i=0; i<h; i++)
  544. {
  545. edge_l[i].r = (((((float)bl.r - tl.r)/(h-1))*i) + 0.5) + tl.r;
  546. edge_l[i].g = (((((float)bl.g - tl.g)/(h-1))*i) + 0.5) + tl.g;
  547. edge_l[i].b = (((((float)bl.b - tl.b)/(h-1))*i) + 0.5) + tl.b;
  548. edge_l[i].a = (((((float)bl.a - tl.a)/(h-1))*i) + 0.5) + tl.a;
  549. edge_r[i].r = (((((float)br.r - tr.r)/(h-1))*i) + 0.5) + tr.r;
  550. edge_r[i].g = (((((float)br.g - tr.g)/(h-1))*i) + 0.5) + tr.g;
  551. edge_r[i].b = (((((float)br.b - tr.b)/(h-1))*i) + 0.5) + tr.b;
  552. edge_r[i].a = (((((float)br.a - tr.a)/(h-1))*i) + 0.5) + tr.a;
  553. }
  554. for (i=0; i<h; i++) {
  555. for (j=0; j<w; j++) {
  556. if (i==0) {
  557. nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_t[j]);
  558. } else if (i==h-1) {
  559. nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_b[j]);
  560. } else {
  561. if (j==0) {
  562. nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_l[i]);
  563. } else if (j==w-1) {
  564. nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, edge_r[i]);
  565. } else {
  566. pixel.r = (((((float)edge_r[i].r - edge_l[i].r)/(w-1))*j) + 0.5) + edge_l[i].r;
  567. pixel.g = (((((float)edge_r[i].g - edge_l[i].g)/(w-1))*j) + 0.5) + edge_l[i].g;
  568. pixel.b = (((((float)edge_r[i].b - edge_l[i].b)/(w-1))*j) + 0.5) + edge_l[i].b;
  569. pixel.a = (((((float)edge_r[i].a - edge_l[i].a)/(w-1))*j) + 0.5) + edge_l[i].a;
  570. nk_rawfb_img_blendpixel(&rawfb->fb, x+j, y+i, pixel);
  571. }
  572. }
  573. }
  574. }
  575. free(edge_buf);
  576. }
  577. static void
  578. nk_rawfb_fill_triangle(const struct rawfb_context *rawfb,
  579. const short x0, const short y0, const short x1, const short y1,
  580. const short x2, const short y2, const rawfb_color col)
  581. {
  582. struct nk_vec2i pnts[3];
  583. pnts[0].x = x0;
  584. pnts[0].y = y0;
  585. pnts[1].x = x1;
  586. pnts[1].y = y1;
  587. pnts[2].x = x2;
  588. pnts[2].y = y2;
  589. nk_rawfb_fill_polygon(rawfb, pnts, 3, col);
  590. }
  591. static void
  592. nk_rawfb_stroke_triangle(const struct rawfb_context *rawfb,
  593. const short x0, const short y0, const short x1, const short y1,
  594. const short x2, const short y2, const unsigned short line_thickness,
  595. const rawfb_color col)
  596. {
  597. nk_rawfb_stroke_line(rawfb, x0, y0, x1, y1, line_thickness, col);
  598. nk_rawfb_stroke_line(rawfb, x1, y1, x2, y2, line_thickness, col);
  599. nk_rawfb_stroke_line(rawfb, x2, y2, x0, y0, line_thickness, col);
  600. }
  601. static void
  602. nk_rawfb_stroke_polygon(const struct rawfb_context *rawfb,
  603. const struct nk_vec2i *pnts, const int count,
  604. const unsigned short line_thickness, const rawfb_color col)
  605. {
  606. int i;
  607. for (i = 1; i < count; ++i)
  608. nk_rawfb_stroke_line(rawfb, pnts[i-1].x, pnts[i-1].y, pnts[i].x,
  609. pnts[i].y, line_thickness, col);
  610. nk_rawfb_stroke_line(rawfb, pnts[count-1].x, pnts[count-1].y,
  611. pnts[0].x, pnts[0].y, line_thickness, col);
  612. }
  613. static void
  614. nk_rawfb_stroke_polyline(const struct rawfb_context *rawfb,
  615. const struct nk_vec2i *pnts, const int count,
  616. const unsigned short line_thickness, const rawfb_color col)
  617. {
  618. int i;
  619. for (i = 0; i < count-1; ++i)
  620. nk_rawfb_stroke_line(rawfb, pnts[i].x, pnts[i].y,
  621. pnts[i+1].x, pnts[i+1].y, line_thickness, col);
  622. }
  623. static void
  624. nk_rawfb_fill_circle(const struct rawfb_context *rawfb,
  625. short x0, short y0, short w, short h, const rawfb_color col)
  626. {
  627. /* Bresenham's ellipses */
  628. const int a2 = (w * w) / 4;
  629. const int b2 = (h * h) / 4;
  630. const int fa2 = 4 * a2, fb2 = 4 * b2;
  631. int x, y, sigma;
  632. /* Convert upper left to center */
  633. h = (h + 1) / 2;
  634. w = (w + 1) / 2;
  635. x0 += w;
  636. y0 += h;
  637. /* First half */
  638. for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) {
  639. nk_rawfb_stroke_line(rawfb, x0 - x, y0 + y, x0 + x, y0 + y, 1, col);
  640. nk_rawfb_stroke_line(rawfb, x0 - x, y0 - y, x0 + x, y0 - y, 1, col);
  641. if (sigma >= 0) {
  642. sigma += fa2 * (1 - y);
  643. y--;
  644. } sigma += b2 * ((4 * x) + 6);
  645. }
  646. /* Second half */
  647. for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) {
  648. nk_rawfb_stroke_line(rawfb, x0 - x, y0 + y, x0 + x, y0 + y, 1, col);
  649. nk_rawfb_stroke_line(rawfb, x0 - x, y0 - y, x0 + x, y0 - y, 1, col);
  650. if (sigma >= 0) {
  651. sigma += fb2 * (1 - x);
  652. x--;
  653. } sigma += a2 * ((4 * y) + 6);
  654. }
  655. }
  656. static void
  657. nk_rawfb_stroke_circle(const struct rawfb_context *rawfb,
  658. short x0, short y0, short w, short h, const short line_thickness,
  659. const rawfb_color col)
  660. {
  661. /* Bresenham's ellipses */
  662. const int a2 = (w * w) / 4;
  663. const int b2 = (h * h) / 4;
  664. const int fa2 = 4 * a2, fb2 = 4 * b2;
  665. int x, y, sigma;
  666. NK_UNUSED(line_thickness);
  667. /* Convert upper left to center */
  668. h = (h + 1) / 2;
  669. w = (w + 1) / 2;
  670. x0 += w;
  671. y0 += h;
  672. /* First half */
  673. for (x = 0, y = h, sigma = 2*b2+a2*(1-2*h); b2*x <= a2*y; x++) {
  674. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col);
  675. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col);
  676. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col);
  677. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col);
  678. if (sigma >= 0) {
  679. sigma += fa2 * (1 - y);
  680. y--;
  681. } sigma += b2 * ((4 * x) + 6);
  682. }
  683. /* Second half */
  684. for (x = w, y = 0, sigma = 2*a2+b2*(1-2*w); a2*y <= b2*x; y++) {
  685. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 + y, col);
  686. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 + y, col);
  687. nk_rawfb_ctx_setpixel(rawfb, x0 + x, y0 - y, col);
  688. nk_rawfb_ctx_setpixel(rawfb, x0 - x, y0 - y, col);
  689. if (sigma >= 0) {
  690. sigma += fb2 * (1 - x);
  691. x--;
  692. } sigma += a2 * ((4 * y) + 6);
  693. }
  694. }
  695. static void
  696. nk_rawfb_stroke_curve(const struct rawfb_context *rawfb,
  697. const struct nk_vec2i p1, const struct nk_vec2i p2,
  698. const struct nk_vec2i p3, const struct nk_vec2i p4,
  699. const unsigned int num_segments, const unsigned short line_thickness,
  700. const rawfb_color col)
  701. {
  702. unsigned int i_step, segments;
  703. float t_step;
  704. struct nk_vec2i last = p1;
  705. segments = MAX(num_segments, 1);
  706. t_step = 1.0f/(float)segments;
  707. for (i_step = 1; i_step <= segments; ++i_step) {
  708. float t = t_step * (float)i_step;
  709. float u = 1.0f - t;
  710. float w1 = u*u*u;
  711. float w2 = 3*u*u*t;
  712. float w3 = 3*u*t*t;
  713. float w4 = t * t *t;
  714. float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
  715. float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
  716. nk_rawfb_stroke_line(rawfb, last.x, last.y,
  717. (short)x, (short)y, line_thickness,col);
  718. last.x = (short)x; last.y = (short)y;
  719. }
  720. }
  721. static void
  722. nk_rawfb_clear(const struct rawfb_context *rawfb, const rawfb_color col)
  723. {
  724. nk_rawfb_fill_rect(rawfb, 0, 0, rawfb->fb.w, rawfb->fb.h, 0, col);
  725. }
  726. NK_API struct rawfb_context*
  727. nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h,
  728. const unsigned int pitch, const struct rawfb_pl pl)
  729. {
  730. const void *tex;
  731. struct rawfb_context *rawfb;
  732. rawfb = malloc(sizeof(struct rawfb_context));
  733. if (!rawfb)
  734. return NULL;
  735. memset(rawfb, 0, sizeof(struct rawfb_context));
  736. rawfb->font_tex.pixels = tex_mem;
  737. rawfb->font_tex.pl.bytesPerPixel = 1;
  738. rawfb->font_tex.pl.rshift = 0;
  739. rawfb->font_tex.pl.gshift = 0;
  740. rawfb->font_tex.pl.bshift = 0;
  741. rawfb->font_tex.pl.ashift = 0;
  742. rawfb->font_tex.pl.rloss = 8;
  743. rawfb->font_tex.pl.gloss = 8;
  744. rawfb->font_tex.pl.bloss = 8;
  745. rawfb->font_tex.pl.aloss = 0;
  746. rawfb->font_tex.w = rawfb->font_tex.h = rawfb->font_tex.pitch = 0;
  747. rawfb->fb.pixels = fb;
  748. rawfb->fb.w = w;
  749. rawfb->fb.h = h;
  750. rawfb->fb.pitch = pitch;
  751. rawfb->fb.pl = pl;
  752. if (0 == nk_init_default(&rawfb->ctx, 0)) {
  753. free(rawfb);
  754. return NULL;
  755. }
  756. nk_font_atlas_init_default(&rawfb->atlas);
  757. nk_font_atlas_begin(&rawfb->atlas);
  758. tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, NK_FONT_ATLAS_ALPHA8);
  759. if (!tex) {
  760. free(rawfb);
  761. return NULL;
  762. }
  763. rawfb->font_tex.pitch = rawfb->font_tex.w * 1;
  764. memcpy(rawfb->font_tex.pixels, tex, rawfb->font_tex.pitch * rawfb->font_tex.h);
  765. nk_font_atlas_end(&rawfb->atlas, nk_handle_ptr(NULL), NULL);
  766. if (rawfb->atlas.default_font)
  767. nk_style_set_font(&rawfb->ctx, &rawfb->atlas.default_font->handle);
  768. nk_style_load_all_cursors(&rawfb->ctx, rawfb->atlas.cursors);
  769. nk_rawfb_scissor(rawfb, 0, 0, rawfb->fb.w, rawfb->fb.h);
  770. return rawfb;
  771. }
  772. static void
  773. nk_rawfb_stretch_image(const struct rawfb_image *dst,
  774. const struct rawfb_image *src, const struct nk_rect *dst_rect,
  775. const struct nk_rect *src_rect, const struct nk_rect *dst_scissors,
  776. const struct nk_color *fg)
  777. {
  778. short i, j;
  779. struct nk_color col;
  780. float xinc = src_rect->w / dst_rect->w;
  781. float yinc = src_rect->h / dst_rect->h;
  782. float xoff = src_rect->x, yoff = src_rect->y;
  783. /* Simple nearest filtering rescaling */
  784. /* TODO: use bilinear filter */
  785. for (j = 0; j < (short)dst_rect->h; j++) {
  786. for (i = 0; i < (short)dst_rect->w; i++) {
  787. if (dst_scissors) {
  788. if (i + (int)(dst_rect->x + 0.5f) < dst_scissors->x || i + (int)(dst_rect->x + 0.5f) >= dst_scissors->w)
  789. continue;
  790. if (j + (int)(dst_rect->y + 0.5f) < dst_scissors->y || j + (int)(dst_rect->y + 0.5f) >= dst_scissors->h)
  791. continue;
  792. }
  793. col = nk_rawfb_img_getpixel(src, (int)xoff, (int) yoff);
  794. if (col.r || col.g || col.b)
  795. {
  796. col.r = fg->r;
  797. col.g = fg->g;
  798. col.b = fg->b;
  799. }
  800. nk_rawfb_img_blendpixel(dst, i + (int)(dst_rect->x + 0.5f), j + (int)(dst_rect->y + 0.5f), col);
  801. xoff += xinc;
  802. }
  803. xoff = src_rect->x;
  804. yoff += yinc;
  805. }
  806. }
  807. static void
  808. nk_rawfb_font_query_font_glyph(nk_handle handle, const float height,
  809. struct nk_user_font_glyph *glyph, const nk_rune codepoint,
  810. const nk_rune next_codepoint)
  811. {
  812. float scale;
  813. const struct nk_font_glyph *g;
  814. struct nk_font *font;
  815. NK_ASSERT(glyph);
  816. NK_UNUSED(next_codepoint);
  817. font = (struct nk_font*)handle.ptr;
  818. NK_ASSERT(font);
  819. NK_ASSERT(font->glyphs);
  820. if (!font || !glyph)
  821. return;
  822. scale = height/font->info.height;
  823. g = nk_font_find_glyph(font, codepoint);
  824. glyph->width = (g->x1 - g->x0) * scale;
  825. glyph->height = (g->y1 - g->y0) * scale;
  826. glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
  827. glyph->xadvance = (g->xadvance * scale);
  828. glyph->uv[0] = nk_vec2(g->u0, g->v0);
  829. glyph->uv[1] = nk_vec2(g->u1, g->v1);
  830. }
  831. NK_API void
  832. nk_rawfb_draw_text(const struct rawfb_context *rawfb,
  833. const struct nk_user_font *font, const struct nk_rect rect,
  834. const char *text, const int len, const float font_height,
  835. const struct nk_color fg)
  836. {
  837. float x = 0;
  838. int text_len = 0;
  839. nk_rune unicode = 0;
  840. nk_rune next = 0;
  841. int glyph_len = 0;
  842. int next_glyph_len = 0;
  843. struct nk_user_font_glyph g;
  844. if (!len || !text) return;
  845. x = 0;
  846. glyph_len = nk_utf_decode(text, &unicode, len);
  847. if (!glyph_len) return;
  848. /* draw every glyph image */
  849. while (text_len < len && glyph_len) {
  850. struct nk_rect src_rect;
  851. struct nk_rect dst_rect;
  852. float char_width = 0;
  853. if (unicode == NK_UTF_INVALID) break;
  854. /* query currently drawn glyph information */
  855. next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
  856. nk_rawfb_font_query_font_glyph(font->userdata, font_height, &g, unicode,
  857. (next == NK_UTF_INVALID) ? '\0' : next);
  858. /* calculate and draw glyph drawing rectangle and image */
  859. char_width = g.xadvance;
  860. src_rect.x = g.uv[0].x * rawfb->font_tex.w;
  861. src_rect.y = g.uv[0].y * rawfb->font_tex.h;
  862. src_rect.w = g.uv[1].x * rawfb->font_tex.w - g.uv[0].x * rawfb->font_tex.w;
  863. src_rect.h = g.uv[1].y * rawfb->font_tex.h - g.uv[0].y * rawfb->font_tex.h;
  864. dst_rect.x = x + g.offset.x + rect.x;
  865. dst_rect.y = g.offset.y + rect.y;
  866. dst_rect.w = ceil(g.width);
  867. dst_rect.h = ceil(g.height);
  868. /* Use software rescaling to blit glyph from font_text to framebuffer */
  869. nk_rawfb_stretch_image(&rawfb->fb, &rawfb->font_tex, &dst_rect, &src_rect, &rawfb->scissors, &fg);
  870. /* offset next glyph */
  871. text_len += glyph_len;
  872. x += char_width;
  873. glyph_len = next_glyph_len;
  874. unicode = next;
  875. }
  876. }
  877. NK_API void
  878. nk_rawfb_drawimage(const struct rawfb_context *rawfb,
  879. const int x, const int y, const int w, const int h,
  880. const struct nk_image *img, const struct nk_color *col)
  881. {
  882. struct nk_rect src_rect;
  883. struct nk_rect dst_rect;
  884. src_rect.x = img->region[0];
  885. src_rect.y = img->region[1];
  886. src_rect.w = img->region[2];
  887. src_rect.h = img->region[3];
  888. dst_rect.x = x;
  889. dst_rect.y = y;
  890. dst_rect.w = w;
  891. dst_rect.h = h;
  892. nk_rawfb_stretch_image(&rawfb->fb, &rawfb->font_tex, &dst_rect, &src_rect, &rawfb->scissors, col);
  893. }
  894. NK_API void
  895. nk_rawfb_shutdown(struct rawfb_context *rawfb)
  896. {
  897. if (rawfb) {
  898. nk_free(&rawfb->ctx);
  899. memset(rawfb, 0, sizeof(struct rawfb_context));
  900. free(rawfb);
  901. }
  902. }
  903. NK_API void
  904. nk_rawfb_resize_fb(struct rawfb_context *rawfb,
  905. void *fb,
  906. const unsigned int w,
  907. const unsigned int h,
  908. const unsigned int pitch,
  909. const struct rawfb_pl pl)
  910. {
  911. rawfb->fb.w = w;
  912. rawfb->fb.h = h;
  913. rawfb->fb.pixels = fb;
  914. rawfb->fb.pitch = pitch;
  915. rawfb->fb.pl = pl;
  916. }
  917. NK_API void
  918. nk_rawfb_render(const struct rawfb_context *rawfb,
  919. const struct nk_color clear,
  920. const unsigned char enable_clear)
  921. {
  922. const struct rawfb_pl *pl = &rawfb->fb.pl;
  923. const struct nk_command *cmd;
  924. if (enable_clear)
  925. nk_rawfb_clear(rawfb, nk_rawfb_color2int(clear, pl));
  926. nk_foreach(cmd, (struct nk_context*)&rawfb->ctx) {
  927. switch (cmd->type) {
  928. case NK_COMMAND_NOP: break;
  929. case NK_COMMAND_SCISSOR: {
  930. const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
  931. nk_rawfb_scissor((struct rawfb_context *)rawfb, s->x, s->y, s->w, s->h);
  932. } break;
  933. case NK_COMMAND_LINE: {
  934. const struct nk_command_line *l = (const struct nk_command_line *)cmd;
  935. nk_rawfb_stroke_line(rawfb, l->begin.x, l->begin.y, l->end.x,
  936. l->end.y, l->line_thickness, nk_rawfb_color2int(l->color, pl));
  937. } break;
  938. case NK_COMMAND_RECT: {
  939. const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
  940. nk_rawfb_stroke_rect(rawfb, r->x, r->y, r->w, r->h,
  941. (unsigned short)r->rounding, r->line_thickness,
  942. nk_rawfb_color2int(r->color, pl));
  943. } break;
  944. case NK_COMMAND_RECT_FILLED: {
  945. const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
  946. nk_rawfb_fill_rect(rawfb, r->x, r->y, r->w, r->h,
  947. (unsigned short)r->rounding, nk_rawfb_color2int(r->color, pl));
  948. } break;
  949. case NK_COMMAND_CIRCLE: {
  950. const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
  951. nk_rawfb_stroke_circle(rawfb, c->x, c->y, c->w, c->h, c->line_thickness,
  952. nk_rawfb_color2int(c->color, pl));
  953. } break;
  954. case NK_COMMAND_CIRCLE_FILLED: {
  955. const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  956. nk_rawfb_fill_circle(rawfb, c->x, c->y, c->w, c->h,
  957. nk_rawfb_color2int(c->color, pl));
  958. } break;
  959. case NK_COMMAND_TRIANGLE: {
  960. const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
  961. nk_rawfb_stroke_triangle(rawfb, t->a.x, t->a.y, t->b.x, t->b.y,
  962. t->c.x, t->c.y, t->line_thickness, nk_rawfb_color2int(t->color, pl));
  963. } break;
  964. case NK_COMMAND_TRIANGLE_FILLED: {
  965. const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
  966. nk_rawfb_fill_triangle(rawfb, t->a.x, t->a.y, t->b.x, t->b.y,
  967. t->c.x, t->c.y, nk_rawfb_color2int(t->color, pl));
  968. } break;
  969. case NK_COMMAND_POLYGON: {
  970. const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd;
  971. nk_rawfb_stroke_polygon(rawfb, p->points, p->point_count, p->line_thickness,
  972. nk_rawfb_color2int(p->color, pl));
  973. } break;
  974. case NK_COMMAND_POLYGON_FILLED: {
  975. const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
  976. nk_rawfb_fill_polygon(rawfb, p->points, p->point_count, nk_rawfb_color2int(p->color, pl));
  977. } break;
  978. case NK_COMMAND_POLYLINE: {
  979. const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
  980. nk_rawfb_stroke_polyline(rawfb, p->points, p->point_count, p->line_thickness, nk_rawfb_color2int(p->color, pl));
  981. } break;
  982. case NK_COMMAND_TEXT: {
  983. const struct nk_command_text *t = (const struct nk_command_text*)cmd;
  984. nk_rawfb_draw_text(rawfb, t->font, nk_rect(t->x, t->y, t->w, t->h),
  985. t->string, t->length, t->height, t->foreground);
  986. } break;
  987. case NK_COMMAND_CURVE: {
  988. const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
  989. nk_rawfb_stroke_curve(rawfb, q->begin, q->ctrl[0], q->ctrl[1],
  990. q->end, 22, q->line_thickness, nk_rawfb_color2int(q->color, pl));
  991. } break;
  992. case NK_COMMAND_RECT_MULTI_COLOR: {
  993. const struct nk_command_rect_multi_color *q = (const struct nk_command_rect_multi_color *)cmd;
  994. nk_rawfb_draw_rect_multi_color(rawfb, q->x, q->y, q->w, q->h, q->left, q->top, q->right, q->bottom);
  995. } break;
  996. case NK_COMMAND_IMAGE: {
  997. const struct nk_command_image *q = (const struct nk_command_image *)cmd;
  998. nk_rawfb_drawimage(rawfb, q->x, q->y, q->w, q->h, &q->img, &q->col);
  999. } break;
  1000. case NK_COMMAND_ARC: {
  1001. assert(0 && "NK_COMMAND_ARC not implemented\n");
  1002. } break;
  1003. case NK_COMMAND_ARC_FILLED: {
  1004. assert(0 && "NK_COMMAND_ARC_FILLED not implemented\n");
  1005. } break;
  1006. default: break;
  1007. }
  1008. } nk_clear((struct nk_context*)&rawfb->ctx);
  1009. }
  1010. #endif