cross platform gui lib for lua
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.
 
 
 
 

1022 lines
29 KiB

  1. /* lui.c
  2. *
  3. * lua binding to libui (https://github.com/andlabs/libui)
  4. *
  5. * Gunnar Zötl <gz@tset.de>, 2016
  6. * Released under MIT/X11 license. See file LICENSE for details.
  7. *
  8. * This file is included by lui.c
  9. */
  10. /* uiDrawBrush ************************************************************/
  11. /*** Object
  12. * Name: draw.brush
  13. * a brush spec to draw with.
  14. */
  15. #define uiDrawBrush(this) ((uiDrawBrush *) (this))
  16. #define LUI_DRAWBRUSH "lui_drawbrush"
  17. #define lui_pushDrawBrush(L) lui_pushObject(L, LUI_DRAWBRUSH, 1)
  18. #define lui_checkDrawBrush(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DRAWBRUSH))
  19. static int lui_drawbrush_setGradientStops(lua_State *L, uiDrawBrush *brush, int pos)
  20. {
  21. if (lua_isnoneornil(L, pos)) {
  22. if (brush->Stops) {
  23. free(brush->Stops);
  24. }
  25. brush->Stops = 0;
  26. brush->NumStops = 0;
  27. return 1;
  28. }
  29. if (lua_type(L, pos) != LUA_TTABLE) {
  30. return luaL_error(L, "invalid value for gradientstops (expected table)");
  31. }
  32. int len = lua_rawlen(L, pos);
  33. if (brush->Stops) {
  34. free(brush->Stops);
  35. }
  36. brush->Stops = calloc(len, sizeof(uiDrawBrushGradientStop));
  37. if (!brush->Stops) {
  38. luaL_error(L, "out of memory!");
  39. }
  40. brush->NumStops = len;
  41. for (int i = 0; i < len; ++i) {
  42. uiDrawBrushGradientStop *stop = &brush->Stops[i];
  43. lua_geti(L, pos, i + 1);
  44. if (lua_type(L, lua_gettop(L)) != LUA_TTABLE) {
  45. return luaL_error(L, "invalid value in table for gradientstops");
  46. }
  47. lui_aux_rgbaFromTable(L, lua_gettop(L), &stop->R, &stop->G, &stop->B, &stop->A);
  48. lua_geti(L, -1, 1);
  49. stop->Pos = luaL_checknumber(L, -1);
  50. lua_pop(L, 2);
  51. }
  52. return 1;
  53. }
  54. static int lui_drawbrush_getGradientStops(lua_State *L, uiDrawBrush *brush)
  55. {
  56. if (brush->NumStops == 0) {
  57. lua_pushnil(L);
  58. return 1;
  59. }
  60. lua_newtable(L);
  61. for (int i = 0; i < brush->NumStops; ++i) {
  62. uiDrawBrushGradientStop *stop = &brush->Stops[i];
  63. lui_aux_pushRgbaAsTable(L, stop->R, stop->G, stop->B, stop->A);
  64. lua_pushnumber(L, stop->Pos);
  65. lua_rawseti(L, -2, 1);
  66. lua_seti(L, -2, i + 1);
  67. }
  68. return 1;
  69. }
  70. /*** Property
  71. * Object: draw.brush
  72. * Name: type
  73. * may be any of the strings "solid", "lineargradient", "radialgradient", "image"
  74. * or lui.enum.brushtype.solid ..., will always return type name on read.
  75. *** Property
  76. * Object: draw.brush
  77. * Name: color
  78. * color of the brush
  79. *** Property
  80. * Object: draw.brush
  81. * Name: x0
  82. * linear: start X, radial: start X
  83. *** Property
  84. * Object: draw.brush
  85. * Name: y0
  86. * linear: start Y, radial: start Y
  87. *** Property
  88. * Object: draw.brush
  89. * Name: x1
  90. * linear: end X, radial: outer circle center X
  91. *** Property
  92. * Object: draw.brush
  93. * Name: y1
  94. * linear: end Y, radial: outer circle center Y
  95. *** Property
  96. * Object: draw.brush
  97. * Name: outerradius
  98. * radial gradients only
  99. *** Property
  100. * Object: draw.brush
  101. * Name: gradientstops
  102. * { { pos, r=?, g=?, b=?, a=?}, ... }, don't modify what you read
  103. */
  104. static int lui_drawbrush__index(lua_State *L)
  105. {
  106. lui_object *lobj = lui_checkDrawBrush(L, 1);
  107. uiDrawBrush *brush = uiDrawBrush(lobj->object);
  108. const char *what = luaL_checkstring(L, 2);
  109. if (strcmp(what, "type") == 0) {
  110. lui_aux_pushNameOrValue(L, brush->Type, "lui_enumbrushtype");
  111. } else if (strcmp(what, "color") == 0) {
  112. lui_aux_pushRgbaAsTable(L, brush->R, brush->A, brush->B, brush->A);
  113. } else if (strcmp(what, "x0") == 0) {
  114. lua_pushnumber(L, brush->X0);
  115. } else if (strcmp(what, "y0") == 0) {
  116. lua_pushnumber(L, brush->Y0);
  117. } else if (strcmp(what, "x1") == 0) {
  118. lua_pushnumber(L, brush->X1);
  119. } else if (strcmp(what, "y1") == 0) {
  120. lua_pushnumber(L, brush->Y1);
  121. } else if (strcmp(what, "outerradius") == 0) {
  122. lua_pushnumber(L, brush->OuterRadius);
  123. } else if (strcmp(what, "gradientstops") == 0) {
  124. if (lui_aux_getUservalue(L, 1, "gradientstops") == LUA_TNIL) {
  125. DEBUGMSG("(uncached)");
  126. lua_pop(L, 1);
  127. lui_drawbrush_getGradientStops(L, brush);
  128. lui_aux_setUservalue(L, 1, "gradientstops", 3);
  129. }
  130. } else {
  131. return lui_utility__index(L);
  132. }
  133. return 1;
  134. }
  135. static int lui_drawbrush__newindex(lua_State *L)
  136. {
  137. lui_object *lobj = lui_checkDrawBrush(L, 1);
  138. uiDrawBrush *brush = uiDrawBrush(lobj->object);
  139. const char *what = luaL_checkstring(L, 2);
  140. if (strcmp(what, "type") == 0) {
  141. brush->Type = lui_aux_getNumberOrValue(L, 3, "lui_enumbrushtype");
  142. } else if (strcmp(what, "color") == 0) {
  143. if (lua_type(L, 3) != LUA_TTABLE) {
  144. return luaL_error(L, "invalid value for gradientstops");
  145. }
  146. lui_aux_rgbaFromTable(L, 3, &brush->R, &brush->G, &brush->B, &brush->A);
  147. } else if (strcmp(what, "x0") == 0) {
  148. brush->X0 = lua_tonumber(L, 3);
  149. } else if (strcmp(what, "y0") == 0) {
  150. brush->Y0 = lua_tonumber(L, 3);
  151. } else if (strcmp(what, "x1") == 0) {
  152. brush->X1 = lua_tonumber(L, 3);
  153. } else if (strcmp(what, "y1") == 0) {
  154. brush->Y1 = lua_tonumber(L, 3);
  155. } else if (strcmp(what, "outerradius") == 0) {
  156. brush->OuterRadius = lua_tonumber(L, 3);
  157. } else if (strcmp(what, "gradientstops") == 0) {
  158. lui_drawbrush_setGradientStops(L, brush, 3);
  159. lua_pushnil(L);
  160. lui_aux_setUservalue(L, 1, "gradientstops", 4);
  161. lua_pop(L, 1);
  162. } else {
  163. return lui_utility__newindex(L);
  164. }
  165. return 0;
  166. }
  167. static int lui_makeDrawBrushTypeEnum(lua_State *L)
  168. {
  169. lua_newtable(L);
  170. lui_enumItem("solid", uiDrawBrushTypeSolid);
  171. lui_enumItem("lineargradient", uiDrawBrushTypeLinearGradient);
  172. lui_enumItem("radialgradient", uiDrawBrushTypeRadialGradient);
  173. lui_enumItem("image", uiDrawBrushTypeImage);
  174. return 1;
  175. }
  176. /*** Constructor
  177. * Object: draw.brush
  178. * Name: draw.brush
  179. * Signature: brush = lui.draw.brush(properties = nil)
  180. * create a new draw.brush object
  181. */
  182. static int lui_newDrawBrush(lua_State *L)
  183. {
  184. int hastable = lui_aux_istable(L, 1);
  185. lui_object *lobj = lui_pushDrawBrush(L);
  186. lobj->object = calloc(1, sizeof(uiDrawBrush));
  187. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  188. lui_registerObject(L, lua_gettop(L));
  189. return 1;
  190. }
  191. /* metamethods for draw.brush */
  192. static const luaL_Reg lui_drawbrush_meta[] = {
  193. {"__index", lui_drawbrush__index},
  194. {"__newindex", lui_drawbrush__newindex},
  195. {0, 0}
  196. };
  197. /* uiDrawStrokeParams *****************************************************/
  198. /*** Object
  199. * Name: draw.strokeparams
  200. * a stroke spec to draw with
  201. */
  202. #define uiDrawStrokeParams(this) ((uiDrawStrokeParams *) (this))
  203. #define LUI_DRAWSTROKEPARAMS "lui_drawstrokeparams"
  204. #define lui_pushDrawStrokeParams(L) lui_pushObject(L, LUI_DRAWSTROKEPARAMS, 1)
  205. #define lui_checkDrawStrokeParams(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DRAWSTROKEPARAMS))
  206. static int lui_drawstrokeparams_setDashes(lua_State *L, uiDrawStrokeParams *params, int pos)
  207. {
  208. if (lua_isnoneornil(L, pos)) {
  209. if (params->Dashes) {
  210. free(params->Dashes);
  211. }
  212. params->Dashes = 0;
  213. params->NumDashes = 0;
  214. return 1;
  215. }
  216. luaL_checktype(L, pos, LUA_TTABLE);
  217. int len = lua_rawlen(L, pos);
  218. if (params->Dashes) {
  219. free(params->Dashes);
  220. }
  221. params->Dashes = calloc(len, sizeof(double));
  222. if (!params->Dashes) {
  223. luaL_error(L, "out of memory!");
  224. }
  225. params->NumDashes = len;
  226. for (int i = 0; i < len; ++i) {
  227. lua_geti(L, pos, i + 1);
  228. params->Dashes[i] = luaL_checknumber(L, -1);
  229. lua_pop(L, 1);
  230. }
  231. return 1;
  232. }
  233. static int lui_drawstrokeparams_getDashes(lua_State *L, uiDrawStrokeParams *params)
  234. {
  235. if (params->NumDashes == 0) {
  236. lua_pushnil(L);
  237. return 1;
  238. }
  239. lua_newtable(L);
  240. for (int i = 0; i < params->NumDashes; ++i) {
  241. lua_pushnumber(L, params->Dashes[i]);
  242. lua_seti(L, -2, i + 1);
  243. }
  244. return 1;
  245. }
  246. /*** Property
  247. * Object: draw.strokeparams
  248. * Name: linecap
  249. * any of the strings "flat", "round", "square", or lui.enum.linecap.flat...
  250. *** Property
  251. * Object: draw.strokeparams
  252. * Name: linejoin
  253. * any of the strings "miter", "round", "bevel", or lui.enum.linejoin.miter ...
  254. *** Property
  255. * Object: draw.strokeparams
  256. * Name: thickness
  257. * line thickness. Default is 1.
  258. *** Property
  259. * Object: draw.strokeparams
  260. * Name: miterlimit
  261. * line join miter limit. Default is 10.
  262. *** Property
  263. * Object: draw.strokeparams
  264. * Name: dashphase
  265. * (TODO doc missing)
  266. *** Property
  267. * Object: draw.strokeparams
  268. * Name: dashes
  269. * { len1, len2, ... }, don't modify what you read
  270. * (TODO doc missing)
  271. */
  272. static int lui_drawstrokeparams__index(lua_State *L)
  273. {
  274. lui_object *lobj = lui_checkDrawStrokeParams(L, 1);
  275. uiDrawStrokeParams *params = uiDrawStrokeParams(lobj->object);
  276. const char *what = luaL_checkstring(L, 2);
  277. if (strcmp(what, "linecap") == 0) {
  278. lui_aux_pushNameOrValue(L, params->Cap, "lui_enumlinecap");
  279. } else if (strcmp(what, "linejoin") == 0) {
  280. lui_aux_pushNameOrValue(L, params->Cap, "lui_enumlinejoin");
  281. } else if (strcmp(what, "thickness") == 0) {
  282. lua_pushnumber(L, params->Thickness);
  283. } else if (strcmp(what, "miterlimit") == 0) {
  284. lua_pushnumber(L, params->MiterLimit);
  285. } else if (strcmp(what, "dashphase") == 0) {
  286. lua_pushnumber(L, params->DashPhase);
  287. } else if (strcmp(what, "dashes") == 0) {
  288. if (lui_aux_getUservalue(L, 1, "dashes") == LUA_TNIL) {
  289. DEBUGMSG("(uncached)");
  290. lua_pop(L, 1);
  291. lui_drawstrokeparams_getDashes(L, params);
  292. lui_aux_setUservalue(L, 1, "dashes", 3);
  293. }
  294. } else {
  295. return lui_utility__index(L);
  296. }
  297. return 1;
  298. }
  299. static int lui_drawstrokeparams__newindex(lua_State *L)
  300. {
  301. lui_object *lobj = lui_checkDrawStrokeParams(L, 1);
  302. uiDrawStrokeParams *params = uiDrawStrokeParams(lobj->object);
  303. const char *what = luaL_checkstring(L, 2);
  304. if (strcmp(what, "linecap") == 0) {
  305. params->Cap = lui_aux_getNumberOrValue(L, 3, "lui_enumlinecap");
  306. } else if (strcmp(what, "linejoin") == 0) {
  307. params->Join = lui_aux_getNumberOrValue(L, 3, "lui_enumlinejoin");
  308. } else if (strcmp(what, "thickness") == 0) {
  309. params->Thickness = luaL_checknumber(L, 3);
  310. } else if (strcmp(what, "miterlimit") == 0) {
  311. params->MiterLimit = luaL_checknumber(L, 3);
  312. } else if (strcmp(what, "dashphase") == 0) {
  313. params->DashPhase = luaL_checknumber(L, 3);
  314. } else if (strcmp(what, "dashes") == 0) {
  315. lui_drawstrokeparams_setDashes(L, params, 3);
  316. lua_pushnil(L);
  317. lui_aux_setUservalue(L, 1, "dashes", 4);
  318. lua_pop(L, 1);
  319. } else {
  320. return lui_utility__newindex(L);
  321. }
  322. return 0;
  323. }
  324. static int lui_makeDrawLineCapEnum(lua_State *L)
  325. {
  326. lua_newtable(L);
  327. lui_enumItem("flat", uiDrawLineCapFlat);
  328. lui_enumItem("round", uiDrawLineCapRound);
  329. lui_enumItem("square", uiDrawLineCapSquare);
  330. return 1;
  331. }
  332. static int lui_makeDrawLineJoinEnum(lua_State *L)
  333. {
  334. lua_newtable(L);
  335. lui_enumItem("miter", uiDrawLineJoinMiter);
  336. lui_enumItem("round", uiDrawLineJoinRound);
  337. lui_enumItem("bevel", uiDrawLineJoinBevel);
  338. return 1;
  339. }
  340. /*** Constructor
  341. * Object: draw.strokeparams
  342. * Name: draw.strokeparams
  343. * Signature: strokeparams = lui.draw.strokeparams(properties = nil)
  344. * create a new draw.strokeparams object
  345. */
  346. static int lui_newDrawStrokeParams(lua_State *L)
  347. {
  348. int hastable = lui_aux_istable(L, 1);
  349. lui_object *lobj = lui_pushDrawStrokeParams(L);
  350. lobj->object = calloc(1, sizeof(uiDrawStrokeParams));
  351. uiDrawStrokeParams(lobj->object)->Thickness = 1;
  352. uiDrawStrokeParams(lobj->object)->MiterLimit = uiDrawDefaultMiterLimit;
  353. if (hastable) { lui_aux_setFieldsFromTable(L, lua_gettop(L), 1); }
  354. lui_registerObject(L, lua_gettop(L));
  355. return 1;
  356. }
  357. /* metamethods for draw.strokeparams */
  358. static const luaL_Reg lui_drawstrokeparams_meta[] = {
  359. {"__index", lui_drawstrokeparams__index},
  360. {"__newindex", lui_drawstrokeparams__newindex},
  361. {0, 0}
  362. };
  363. /* uiDrawMatrix ***********************************************************/
  364. /*** Object
  365. * Name: draw.matrix
  366. * a transformation matrix for drawing operations
  367. */
  368. #define uiDrawMatrix(this) ((uiDrawMatrix *) (this))
  369. #define LUI_DRAWMATRIX "lui_drawmatrix"
  370. #define lui_pushDrawMatrix(L) lui_pushObject(L, LUI_DRAWMATRIX, 0)
  371. #define lui_checkDrawMatrix(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DRAWMATRIX))
  372. /*** Method
  373. * Object: draw.matrix
  374. * Name: setidentity
  375. * Signature: matrix = matrix:setidentity()
  376. * reset the matrix to identity. Returns the changed matrix.
  377. */
  378. static int lui_drawMatrixSetIdentity(lua_State *L)
  379. {
  380. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  381. uiDrawMatrixSetIdentity(uiDrawMatrix(lobj->object));
  382. lua_pushvalue(L, 1);
  383. return 1;
  384. }
  385. /*** Method
  386. * Object: draw.matrix
  387. * Name: translate
  388. * Signature: matrix = matrix:translate(x, y)
  389. * multiply the matrix with a matrix translating by x, y. Returns the changed
  390. * matrix.
  391. */
  392. static int lui_drawMatrixTranslate(lua_State *L)
  393. {
  394. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  395. double x = luaL_checknumber(L, 2);
  396. double y = luaL_checknumber(L, 3);
  397. uiDrawMatrixTranslate(uiDrawMatrix(lobj->object), x, y);
  398. lua_pushvalue(L, 1);
  399. return 1;
  400. }
  401. /*** Method
  402. * Object: draw.matrix
  403. * Name: scale
  404. * Signature: matrix = matrix:scale(x, y, xcenter = 0, ycenter = 0)
  405. * multiply the matrix with a matrix scaling by x, y around xcenter, ycenter.
  406. * Returns the changed matrix.
  407. */
  408. static int lui_drawMatrixScale(lua_State *L)
  409. {
  410. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  411. double x = luaL_checknumber(L, 2);
  412. double y = luaL_checknumber(L, 3);
  413. double xcenter = luaL_optnumber(L, 4, 0);
  414. double ycenter = luaL_optnumber(L, 5, 0);
  415. (void) lobj;
  416. uiDrawMatrixScale(uiDrawMatrix(lobj->object), xcenter, ycenter, x, y);
  417. lua_pushvalue(L, 1);
  418. return 1;
  419. }
  420. /*** Method
  421. * Object: draw.matrix
  422. * Name: rotate
  423. * Signature: matrix = matrix:rotate(x, y, angle)
  424. * multiply the matrix with a matrix rotating by angle around x, y. angle is
  425. * in radians. Returns the changed matrix.
  426. */
  427. static int lui_drawMatrixRotate(lua_State *L)
  428. {
  429. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  430. double x = luaL_checknumber(L, 2);
  431. double y = luaL_checknumber(L, 3);
  432. double angle = luaL_checknumber(L, 4);
  433. uiDrawMatrixRotate(uiDrawMatrix(lobj->object), x, y, angle);
  434. lua_pushvalue(L, 1);
  435. return 1;
  436. }
  437. /*** Method
  438. * Object: draw.matrix
  439. * Name: skew
  440. * Signature: matrix = matrix:skew(x, y, xamount, yamount)
  441. * multiply the matrix with a matrix skewing around x, y by xamount, yamount
  442. * Returns the changed matrix.
  443. */
  444. static int lui_drawMatrixSkew(lua_State *L)
  445. {
  446. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  447. (void) lobj;
  448. double x = luaL_checknumber(L, 2);
  449. double y = luaL_checknumber(L, 3);
  450. double xamount = luaL_checknumber(L, 4);
  451. double yamount = luaL_checknumber(L, 5);
  452. uiDrawMatrixSkew(uiDrawMatrix(lobj->object), x, y, xamount, yamount);
  453. lua_pushvalue(L, 1);
  454. return 1;
  455. }
  456. /*** Method
  457. * Object: draw.matrix
  458. * Name: multiply
  459. * Signature: matrix = matrix:multiply(matrix)
  460. * multiply the matrix with another matrix. Returns the changed matrix.
  461. */
  462. static int lui_drawMatrixMultiply(lua_State *L)
  463. {
  464. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  465. lui_object *other = lui_checkDrawMatrix(L, 2);
  466. uiDrawMatrixMultiply(uiDrawMatrix(lobj->object), uiDrawMatrix(other->object));
  467. lua_pushvalue(L, 1);
  468. return 1;
  469. }
  470. /*** Method
  471. * Object: draw.matrix
  472. * Name: invertible
  473. * Signature: ok = matrix:invertible()
  474. * return true if the matrix is invertible, false if not.
  475. */
  476. static int lui_drawMatrixInvertible(lua_State *L)
  477. {
  478. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  479. lua_pushboolean(L, uiDrawMatrixInvertible(uiDrawMatrix(lobj->object)) != 0);
  480. return 1;
  481. }
  482. /*** Method
  483. * Object: draw.matrix
  484. * Name: invert
  485. * Signature: ok = matrix:invert()
  486. * invert the matrix. Returns true if that went ok, false if not.
  487. */
  488. static int lui_drawMatrixInvert(lua_State *L)
  489. {
  490. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  491. lua_pushboolean(L, uiDrawMatrixInvert(uiDrawMatrix(lobj->object)) != 0);
  492. return 1;
  493. }
  494. /*** Method
  495. * Object: draw.matrix
  496. * Name: transformpoint
  497. * Signature: x, y = matrix:transformpoint(x, y)
  498. * transforms input coordinates x, y with the matrix. Returns the transformed
  499. * coordinates.
  500. */
  501. static int lui_drawMatrixTransformPoint(lua_State *L)
  502. {
  503. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  504. double x = luaL_checknumber(L, 2);
  505. double y = luaL_checknumber(L, 3);
  506. uiDrawMatrixTransformPoint(uiDrawMatrix(lobj->object), &x, &y);
  507. lua_pushnumber(L, x);
  508. lua_pushnumber(L, y);
  509. return 2;
  510. }
  511. /*** Method
  512. * Object: draw.matrix
  513. * Name: transformsize
  514. * Signature: x, y = matrix:transformsize(x, y)
  515. * transforms input size x, y with the matrix. Returns the transformed
  516. * size.
  517. */
  518. static int lui_drawMatrixTransformSize(lua_State *L)
  519. {
  520. lui_object *lobj = lui_checkDrawMatrix(L, 1);
  521. double x = luaL_checknumber(L, 2);
  522. double y = luaL_checknumber(L, 3);
  523. uiDrawMatrixTransformSize(uiDrawMatrix(lobj->object), &x, &y);
  524. lua_pushnumber(L, x);
  525. lua_pushnumber(L, y);
  526. return 2;
  527. }
  528. /*** Constructor
  529. * Object: draw.matrix
  530. * Name: draw.matrix
  531. * Signature: matrix = lui.draw.matrix()
  532. * creates a new draw.matrix object, initialized to identity.
  533. */
  534. static int lui_newDrawMatrix(lua_State *L)
  535. {
  536. lui_object *lobj = lui_pushDrawMatrix(L);
  537. lobj->object = calloc(1, sizeof(uiDrawMatrix));
  538. uiDrawMatrixSetIdentity(uiDrawMatrix(lobj->object));
  539. lui_registerObject(L, lua_gettop(L));
  540. return 1;
  541. }
  542. /* methods for DrawMatrix */
  543. static const luaL_Reg lui_drawmatrix_methods[] = {
  544. {"setidentity", lui_drawMatrixSetIdentity},
  545. {"translate", lui_drawMatrixTranslate},
  546. {"scale", lui_drawMatrixScale},
  547. {"rotate", lui_drawMatrixRotate},
  548. {"skew", lui_drawMatrixSkew},
  549. {"multiply", lui_drawMatrixMultiply},
  550. {"invertible", lui_drawMatrixInvertible},
  551. {"invert", lui_drawMatrixInvert},
  552. {"transformpoint", lui_drawMatrixTransformPoint},
  553. {"transformsize", lui_drawMatrixTransformSize},
  554. {0, 0}
  555. };
  556. /* uiDrawPath *************************************************************/
  557. /*** Object
  558. * Name: draw.path
  559. * a path to draw to a draw.context
  560. */
  561. #define uiDrawPath(this) ((uiDrawPath *) (this))
  562. #define LUI_DRAWPATH "lui_drawpath"
  563. #define lui_pushDrawPath(L) lui_pushObject(L, LUI_DRAWPATH, 0)
  564. #define lui_checkDrawPath(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DRAWPATH))
  565. static int lui_drawpath__gc(lua_State *L)
  566. {
  567. lui_object *lobj = lui_checkDrawPath(L, 1);
  568. if (lobj->object) {
  569. DEBUGMSG("lui_drawpath__gc (%s)", lui_debug_controlTostring(L, 1));
  570. uiDrawFreePath(uiDrawPath(lobj->object));
  571. lobj->object = 0;
  572. }
  573. return 0;
  574. }
  575. /*** Method
  576. * Object: draw.path
  577. * Name: newfigure
  578. * Signature: path:newfigure(x, y)
  579. * add a new figure to a path. x, y is the coordinate where the figure starts.
  580. */
  581. static int lui_drawPathNewFigure(lua_State *L)
  582. {
  583. lui_object *lobj = lui_checkDrawPath(L, 1);
  584. double x = luaL_checknumber(L, 2);
  585. double y = luaL_checknumber(L, 3);
  586. uiDrawPathNewFigure(uiDrawPath(lobj->object), x, y);
  587. return 0;
  588. }
  589. /*** Method
  590. * Object: draw.path
  591. * Name: newfigurewitharc
  592. * Signature: path:newfigurewitharc(xcenter, ycenter, radius, start, sweep, negative)
  593. * add a new figure to a path.
  594. */
  595. static int lui_drawPathNewFigureWithArc(lua_State *L)
  596. {
  597. lui_object *lobj = lui_checkDrawPath(L, 1);
  598. double xcenter = luaL_checknumber(L, 2);
  599. double ycenter = luaL_checknumber(L, 3);
  600. double radius = luaL_checknumber(L, 4);
  601. double start = luaL_checknumber(L, 5);
  602. double sweep = luaL_checknumber(L, 6);
  603. int negative = lua_toboolean(L, 7);
  604. uiDrawPathNewFigureWithArc(uiDrawPath(lobj->object), xcenter, ycenter, radius, start, sweep, negative);
  605. return 0;
  606. }
  607. /*** Method
  608. * Object: draw.path
  609. * Name: lineto
  610. * Signature: path:lineto(x, y)
  611. * add a line to a path. A line can only be added when a figure is open.
  612. */
  613. static int lui_drawPathLineTo(lua_State *L)
  614. {
  615. lui_object *lobj = lui_checkDrawPath(L, 1);
  616. double x = luaL_checknumber(L, 2);
  617. double y = luaL_checknumber(L, 3);
  618. uiDrawPathLineTo(uiDrawPath(lobj->object), x, y);
  619. return 0;
  620. }
  621. /*** Method
  622. * Object: draw.path
  623. * Name: arcto
  624. * Signature: path:arcto(xcenter, ycenter, radius, start, sweep, negative = false)
  625. * add an arc to a path. An arc can only be added when a figure is open.
  626. */
  627. static int lui_drawPathArcTo(lua_State *L)
  628. {
  629. lui_object *lobj = lui_checkDrawPath(L, 1);
  630. double xcenter = luaL_checknumber(L, 2);
  631. double ycenter = luaL_checknumber(L, 3);
  632. double radius = luaL_checknumber(L, 4);
  633. double start = luaL_checknumber(L, 5);
  634. double sweep = luaL_checknumber(L, 6);
  635. int negative = lua_toboolean(L, 7);
  636. uiDrawPathArcTo(uiDrawPath(lobj->object), xcenter, ycenter, radius, start, sweep, negative);
  637. return 0;
  638. }
  639. /*** Method
  640. * Object: draw.path
  641. * Name: bezierto
  642. * Signature: path:bezierto(c1x, c1y, c2x, c2y, endx, endy)
  643. * add a bezier curve to a path. A bezier curve can only be added when a
  644. * figure is open.
  645. */
  646. static int lui_drawPathBezierTo(lua_State *L)
  647. {
  648. lui_object *lobj = lui_checkDrawPath(L, 1);
  649. double c1x = luaL_checknumber(L, 2);
  650. double c1y = luaL_checknumber(L, 3);
  651. double c2x = luaL_checknumber(L, 4);
  652. double c2y = luaL_checknumber(L, 5);
  653. double endx = luaL_checknumber(L, 6);
  654. double endy = luaL_checknumber(L, 7);
  655. uiDrawPathBezierTo(uiDrawPath(lobj->object), c1x, c1y, c2x, c2y, endx, endy);
  656. return 0;
  657. }
  658. /*** Method
  659. * Object: draw.path
  660. * Name: closefigure
  661. * Signature: path:closefigure()
  662. * close the last opened figure.
  663. */
  664. static int lui_drawPathCloseFigure(lua_State *L)
  665. {
  666. lui_object *lobj = lui_checkDrawPath(L, 1);
  667. uiDrawPathCloseFigure(uiDrawPath(lobj->object));
  668. return 0;
  669. }
  670. /*** Method
  671. * Object: draw.path
  672. * Name: addrectangle
  673. * Signature: path:addrectangle(x, y, width, height)
  674. * add a rectangle to a path. A rectangle can be added if no figure is open.
  675. */
  676. static int lui_drawPathAddRectangle(lua_State *L)
  677. {
  678. lui_object *lobj = lui_checkDrawPath(L, 1);
  679. double x = luaL_checknumber(L, 2);
  680. double y = luaL_checknumber(L, 3);
  681. double w = luaL_checknumber(L, 4);
  682. double h = luaL_checknumber(L, 5);
  683. uiDrawPathAddRectangle(uiDrawPath(lobj->object), x, y, w, h);
  684. return 0;
  685. }
  686. /*** Method
  687. * Object: draw.path
  688. * Name: done
  689. * Signature: path:done()
  690. * signal that you are finished composing the path.
  691. */
  692. static int lui_drawPathEnd(lua_State *L)
  693. {
  694. lui_object *lobj = lui_checkDrawPath(L, 1);
  695. uiDrawPathEnd(uiDrawPath(lobj->object));
  696. return 0;
  697. }
  698. /*** Constructor
  699. * Object: draw.path
  700. * Name: draw.path
  701. * Signature: path = lui.draw.path(fillmode = "winding")
  702. * create a new draw.path object. fillmode may be "winding" or "alternate",
  703. * or lui.enum.fillmode.winding...
  704. */
  705. static int lui_newDrawPath(lua_State *L)
  706. {
  707. int fillmode = uiDrawFillModeWinding;
  708. if (lua_gettop(L) > 0) {
  709. fillmode = lui_aux_getNumberOrValue(L, 1, "lui_enumfillmode");
  710. }
  711. lui_object *lobj = lui_pushDrawPath(L);
  712. lobj->object = uiDrawNewPath(fillmode);
  713. lui_registerObject(L, lua_gettop(L));
  714. return 1;
  715. }
  716. static int lui_makeDrawFillModeEnum(lua_State *L)
  717. {
  718. lua_newtable(L);
  719. lui_enumItem("winding", uiDrawFillModeWinding);
  720. lui_enumItem("alternate", uiDrawFillModeAlternate);
  721. return 1;
  722. }
  723. /* methods for DrawPath */
  724. static const luaL_Reg lui_drawpath_methods[] = {
  725. {"newfigure", lui_drawPathNewFigure},
  726. {"newfigurewitharc", lui_drawPathNewFigureWithArc},
  727. {"lineto", lui_drawPathLineTo},
  728. {"arcto", lui_drawPathArcTo},
  729. {"bezierto", lui_drawPathBezierTo},
  730. {"closefigure", lui_drawPathCloseFigure},
  731. {"addrectangle", lui_drawPathAddRectangle},
  732. {"done", lui_drawPathEnd},
  733. {0, 0}
  734. };
  735. /* metamethods for DrawPath */
  736. static const luaL_Reg lui_drawpath_meta[] = {
  737. {"__gc", lui_drawpath__gc},
  738. {0, 0}
  739. };
  740. /* uiDrawContext **********************************************************/
  741. /*** Object
  742. * Name: draw.context
  743. * a drawing context object, passed to area.ondraw handler
  744. */
  745. #define uiDrawContext(this) ((uiDrawContext *) (this))
  746. #define LUI_DRAWCONTEXT "lui_drawcontext"
  747. #define lui_pushDrawContext(L) lui_pushObject(L, LUI_DRAWCONTEXT, 0)
  748. #define lui_checkDrawContext(L, pos) ((lui_object*)luaL_checkudata(L, pos, LUI_DRAWCONTEXT))
  749. static int lui_drawcontext__gc(lua_State *L)
  750. {
  751. /* nothing to do here */
  752. return 0;
  753. }
  754. /*** Method
  755. * Object: draw.context
  756. * Name: fill
  757. * Signature: context:fill(drawpath, brush)
  758. * draw a filled path. The path is filled according to the fillmode set when
  759. * creating the path. brush is the brush to use for filling the path.
  760. */
  761. static int lui_drawContextFill(lua_State *L)
  762. {
  763. lui_object *lobj = lui_checkDrawContext(L, 1);
  764. lui_object *path = lui_checkDrawPath(L, 2);
  765. lui_object *brush = lui_checkDrawBrush(L, 3);
  766. uiDrawFill(uiDrawContext(lobj->object), uiDrawPath(path->object), uiDrawBrush(brush->object));
  767. return 0;
  768. }
  769. /*** Method
  770. * Object: draw.context
  771. * Name: stroke
  772. * Signature: context:stroke(path, brush, strokeparams)
  773. * draw a non-filled path. brush is the brush to use for the path outline.
  774. * strokeparams is the description of the strokes to use for the path.
  775. */
  776. static int lui_drawContextStroke(lua_State *L)
  777. {
  778. lui_object *lobj = lui_checkDrawContext(L, 1);
  779. lui_object *path = lui_checkDrawPath(L, 2);
  780. lui_object *brush = lui_checkDrawBrush(L, 3);
  781. lui_object *sparm = lui_checkDrawStrokeParams(L, 4);
  782. uiDrawStroke(uiDrawContext(lobj->object), uiDrawPath(path->object), uiDrawBrush(brush->object), uiDrawStrokeParams(sparm->object));
  783. return 0;
  784. }
  785. /*** Method
  786. * Object: draw.context
  787. * Name: transform
  788. * Signature: context:transform(matrix)
  789. * transform everything that is drawn to the path according to the
  790. * transformations in the draw.matrix.
  791. */
  792. static int lui_drawContextTransform(lua_State *L)
  793. {
  794. lui_object *lobj = lui_checkDrawContext(L, 1);
  795. lui_object *matrix = lui_checkDrawMatrix(L, 2);
  796. uiDrawTransform(uiDrawContext(lobj->object), uiDrawMatrix(matrix->object));
  797. return 0;
  798. }
  799. /*** Method
  800. * Object: draw.context
  801. * Name: clip
  802. * Signature: context:clip(path)
  803. * clip all that is rendered against the path.
  804. */
  805. static int lui_drawContextClip(lua_State *L)
  806. {
  807. lui_object *lobj = lui_checkDrawContext(L, 1);
  808. lui_object *path = lui_checkDrawPath(L, 2);
  809. uiDrawClip(uiDrawContext(lobj->object), uiDrawPath(path->object));
  810. return 0;
  811. }
  812. /*** Method
  813. * Object: draw.context
  814. * Name: save
  815. * Signature: context:save()
  816. * push the current drawing context state to a stack
  817. */
  818. static int lui_drawContextSave(lua_State *L)
  819. {
  820. lui_object *lobj = lui_checkDrawContext(L, 1);
  821. uiDrawSave(uiDrawContext(lobj->object));
  822. return 0;
  823. }
  824. /*** Method
  825. * Object: draw.context
  826. * Name: restore
  827. * Signature: context:restore()
  828. * restore the current drawing context state from a stack
  829. */
  830. static int lui_drawContextRestore(lua_State *L)
  831. {
  832. lui_object *lobj = lui_checkDrawContext(L, 1);
  833. uiDrawRestore(uiDrawContext(lobj->object));
  834. return 0;
  835. }
  836. /*** Method
  837. * Object: draw.context
  838. * Name: text
  839. * Signature: context:text(x, y, textlayout)<br>context:text(x, y, string, font, width, align = "left")
  840. * draw a draw.textlayout object. x, y are the positions to place the layout
  841. * object at. In the second form, the parameters string, font, width and
  842. * align are as for lui.text.layout()
  843. */
  844. static int lui_drawContextText(lua_State *L)
  845. {
  846. lui_object *lobj = lui_checkDrawContext(L, 1);
  847. double x = luaL_checknumber(L, 2);
  848. double y = luaL_checknumber(L, 3);
  849. lui_object *text = lui_toTextLayout(L, 4);
  850. if (text) {
  851. uiDrawText(uiDrawContext(lobj->object), uiDrawTextLayout(text->object), x, y);
  852. } else {
  853. uiDrawTextLayoutParams params;
  854. uiAttributedString *astr = NULL;
  855. if (lua_isstring(L, 4)) {
  856. astr = uiNewAttributedString(lua_tostring(L, 4));
  857. params.String = astr;
  858. } else {
  859. params.String = uiAttributedString(lui_checkAttributedString(L, 4)->object);
  860. }
  861. params.DefaultFont = uiFontDescriptor(lui_checkTextFont(L, 5)->object);
  862. params.Width = luaL_checknumber(L, 6);
  863. params.Align = lui_aux_getNumberOrValue(L, 7, "lui_enumtextalign");
  864. uiDrawTextLayout *layout = uiDrawNewTextLayout(&params);
  865. uiDrawText(uiDrawContext(lobj->object), layout, x, y);
  866. uiDrawFreeTextLayout(layout);
  867. if (astr) {
  868. uiFreeAttributedString(astr);
  869. }
  870. }
  871. return 0;
  872. }
  873. static int lui_wrapDrawcontext(lua_State *L, uiDrawContext *ctx)
  874. {
  875. lui_object *lobj = lui_pushDrawContext(L);
  876. lobj->object = ctx;
  877. return 1;
  878. }
  879. /* metamethods for draw.context */
  880. static const luaL_Reg lui_drawcontext_meta[] = {
  881. {"__gc", lui_drawcontext__gc},
  882. {0, 0}
  883. };
  884. /* methods for draw.context */
  885. static const struct luaL_Reg lui_drawContext_methods [] ={
  886. {"fill", lui_drawContextFill},
  887. {"stroke", lui_drawContextStroke},
  888. {"transform", lui_drawContextTransform},
  889. {"clip", lui_drawContextClip},
  890. {"save", lui_drawContextSave},
  891. {"restore", lui_drawContextRestore},
  892. {"text", lui_drawContextText},
  893. {0, 0}
  894. };
  895. /* draw function list table
  896. */
  897. static const struct luaL_Reg lui_draw_funcs [] ={
  898. /* utility constructors */
  899. {"brush", lui_newDrawBrush},
  900. {"strokeparams", lui_newDrawStrokeParams},
  901. {"matrix", lui_newDrawMatrix},
  902. {"path", lui_newDrawPath},
  903. {0, 0}
  904. };
  905. static void lui_addDrawEnums(lua_State *L)
  906. {
  907. int top = lua_gettop(L);
  908. if (lua_getfield(L, top, "enum") == LUA_TNIL) {
  909. lua_pop(L, 1);
  910. lua_newtable(L);
  911. }
  912. lui_makeDrawBrushTypeEnum(L);
  913. lua_pushvalue(L, -1);
  914. lua_setfield(L, top + 1, "brushtype");
  915. lua_setfield(L, LUA_REGISTRYINDEX, "lui_enumbrushtype");
  916. lui_makeDrawLineCapEnum(L);
  917. lua_pushvalue(L, -1);
  918. lua_setfield(L, top + 1, "linecap");
  919. lua_setfield(L, LUA_REGISTRYINDEX, "lui_enumlinecap");
  920. lui_makeDrawLineJoinEnum(L);
  921. lua_pushvalue(L, -1);
  922. lua_setfield(L, top + 1, "linejoin");
  923. lua_setfield(L, LUA_REGISTRYINDEX, "lui_enumlinejoin");
  924. lui_makeDrawFillModeEnum(L);
  925. lua_pushvalue(L, -1);
  926. lua_setfield(L, top + 1, "fillmode");
  927. lua_setfield(L, LUA_REGISTRYINDEX, "lui_enumfillmode");
  928. lua_setfield(L, top, "enum");
  929. }
  930. static int lui_init_draw(lua_State *L)
  931. {
  932. lua_newtable(L);
  933. luaL_setfuncs(L, lui_draw_funcs, 0);
  934. lua_setfield(L, -2, "draw");
  935. lui_add_utility_type(L, LUI_DRAWBRUSH, 0, lui_drawbrush_meta);
  936. lui_add_utility_type(L, LUI_DRAWSTROKEPARAMS, 0, lui_drawstrokeparams_meta);
  937. lui_add_utility_type(L, LUI_DRAWMATRIX, lui_drawmatrix_methods, 0);
  938. lui_add_utility_type(L, LUI_DRAWPATH, lui_drawpath_methods, lui_drawpath_meta);
  939. lui_add_utility_type(L, LUI_DRAWCONTEXT, lui_drawContext_methods, lui_drawcontext_meta);
  940. lui_addDrawEnums(L);
  941. return 1;
  942. }