Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

1612 Zeilen
57 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # libcaca Colour ASCII-Art library
  4. # Python language bindings
  5. # Copyright (c) 2010 Alex Foulon <alxf@lavabit.com>
  6. # All Rights Reserved
  7. #
  8. # This library is free software. It comes without any warranty, to
  9. # the extent permitted by applicable law. You can redistribute it
  10. # and/or modify it under the terms of the Do What The Fuck You Want
  11. # To Public License, Version 2, as published by Sam Hocevar. See
  12. # http://sam.zoy.org/wtfpl/COPYING for more details.
  13. #
  14. """ Libcaca Python bindings """
  15. import ctypes
  16. import errno
  17. from caca import _lib, utf8_to_utf32, utf32_to_utf8
  18. from caca.font import _Font
  19. class _Canvas(object):
  20. """ Model for Canvas objects.
  21. """
  22. def __init__(self):
  23. self._cv = 0
  24. def from_param(self):
  25. """ Required by ctypes module to call object as parameter of
  26. a C function.
  27. """
  28. return self._cv
  29. def __str__(self):
  30. return "<CacaCanvas %dx%d>" % (self.get_width(), self.get_height())
  31. def __del__(self):
  32. if self._cv > 0:
  33. self._free()
  34. def _free(self):
  35. """ Free a libcaca canvas.
  36. """
  37. _lib.caca_free_canvas.argtypes = [_Canvas]
  38. _lib.caca_free_canvas.restype = ctypes.c_int
  39. return _lib.caca_free_canvas(self)
  40. def get_width(self):
  41. raise CanvasError, "You can't use model canvas directly"
  42. def get_height(self):
  43. raise CanvasError, "You can't use model canvas directly"
  44. class Canvas(_Canvas):
  45. """ Canvas object, methods are libcaca functions with canvas_t as
  46. first parameter.
  47. """
  48. def __init__(self, width=0, height=0, pointer=None):
  49. """ Canvas constructor.
  50. width -- the desired canvas width
  51. height -- the desired canvas height
  52. pointer -- pointer to libcaca canvas
  53. """
  54. _lib.caca_create_canvas.argtypes = [ctypes.c_int, ctypes.c_int]
  55. if pointer is None:
  56. try:
  57. self._cv = _lib.caca_create_canvas(width, height)
  58. except ctypes.ArgumentError, e:
  59. self._cv = 0
  60. raise CanvasError("Specified width or height is invalid")
  61. else:
  62. if self._cv == 0:
  63. err = ctypes.c_int.in_dll(_lib, "errno")
  64. if err.value == errno.EINVAL:
  65. raise CanvasError("Specified width or height is"
  66. " invalid")
  67. elif err.value == errno.ENOMEM:
  68. raise CanvasError("Not enough memory for the requested"
  69. " canvas size")
  70. else:
  71. raise CanvasError("Unknown error: failed to create"
  72. " canvas")
  73. else:
  74. self._cv = pointer
  75. def manage(self, *args, **kw):
  76. """ Not implemented.
  77. """
  78. raise CanvasError, "Not implemented"
  79. def unmanage(self, *args, **kw):
  80. """ Not implemented.
  81. """
  82. raise CanvasError, "Not implemented"
  83. def set_size(self, width, height):
  84. """ Resize a canvas.
  85. width -- the desired canvas width
  86. height -- the desired canvas height
  87. """
  88. _lib.caca_set_canvas_size.argtypes = [
  89. _Canvas, ctypes.c_int, ctypes.c_int
  90. ]
  91. _lib.caca_set_canvas_size.restype = ctypes.c_int
  92. try:
  93. ret = _lib.caca_set_canvas_size(self, width, height)
  94. except ctypes.ArgumentError, e:
  95. raise CanvasError("Specified width or height is invalid")
  96. else:
  97. if ret == -1:
  98. err = ctypes.c_int.in_dll(_lib, "errno")
  99. if err.value == errno.EINVAL:
  100. raise CanvasError("Specified width or height is invalid")
  101. elif err.value == errno.EBUSY:
  102. raise CanvasError("The canvas is in use by a display driver"
  103. " and cannot be resized")
  104. elif err.value == errno.ENOMEM:
  105. raise CanvasError("Not enough memory for the requested"
  106. " canvas size")
  107. else:
  108. return ret
  109. def get_width(self):
  110. """ Get the canvas width.
  111. """
  112. _lib.caca_get_canvas_width.argtypes = [_Canvas]
  113. _lib.caca_get_canvas_width.restype = ctypes.c_int
  114. return _lib.caca_get_canvas_width(self)
  115. def get_height(self):
  116. """ Get the canvas height.
  117. """
  118. _lib.caca_get_canvas_height.argtypes = [_Canvas]
  119. _lib.caca_get_canvas_height.restype = ctypes.c_int
  120. return _lib.caca_get_canvas_height(self)
  121. def get_chars(self, *args, **kw):
  122. """ Not implemented.
  123. """
  124. raise CanvasError, "Not implemented"
  125. def get_attrs(self, *args, **kw):
  126. """ Not implemented.
  127. """
  128. raise CanvasError, "Not implemented"
  129. def gotoxy(self, x, y):
  130. """ Set cursor position. Setting the cursor position outside the canvas
  131. is legal but the cursor will not be shown.
  132. x -- X cursor coordinate
  133. y -- Y cursor coordinate
  134. """
  135. _lib.caca_gotoxy.argtypes = [_Canvas, ctypes.c_int, ctypes.c_int]
  136. _lib.caca_gotoxy.restyoe = ctypes.c_int
  137. try:
  138. ret = _lib.caca_gotoxy(self, x, y)
  139. except ctypes.ArgumentError, e:
  140. raise CanvasError("specified coordinate X or Y is invalid")
  141. else:
  142. return ret
  143. def wherex(self):
  144. """ Get X cursor position.
  145. """
  146. _lib.caca_wherex.argtypes = [_Canvas]
  147. _lib.caca_wherex.restype = ctypes.c_int
  148. return _lib.caca_wherex(self)
  149. def wherey(self):
  150. """ Get Y cursor position.
  151. """
  152. _lib.caca_wherey.argtypes = [_Canvas]
  153. _lib.caca_wherey.restype = ctypes.c_int
  154. return _lib.caca_wherey(self)
  155. def put_char(self, x, y, ch):
  156. """ Print an ASCII or Unicode character. Return the width of the
  157. printed character: 2 for a fullwidth character, 1 otherwise.
  158. x -- X coordinate
  159. y -- Y coordinate
  160. ch -- the character to print
  161. """
  162. _lib.caca_put_char.argtypes = [
  163. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  164. ]
  165. _lib.caca_put_char.restype = ctypes.c_int
  166. if not isinstance(ch, str):
  167. raise CanvasError("Specified character is invalid")
  168. else:
  169. try:
  170. ch = ord(ch)
  171. except TypeError:
  172. ch = utf8_to_utf32(ch)
  173. try:
  174. ret = _lib.caca_put_char(self, x, y, ch)
  175. except ctypes.ArgumentError, e:
  176. raise CanvasError("specified coordinate X or Y is invalid")
  177. else:
  178. return ret
  179. def get_char(self, x, y):
  180. """ Get the Unicode character at the given coordinates.
  181. x -- X coordinate
  182. y -- Y coordinate
  183. """
  184. _lib.caca_get_char.argtypes = [
  185. _Canvas, ctypes.c_int, ctypes.c_int
  186. ]
  187. _lib.caca_get_char.restype = ctypes.c_uint32
  188. try:
  189. ch = _lib.caca_get_char(self, x, y)
  190. except ctypes.ArgumentError:
  191. raise CanvasError("specified coordinate X or Y is invalid")
  192. else:
  193. try:
  194. ch = ord(ch)
  195. except TypeError:
  196. ch = utf32_to_utf8(ch)
  197. return ch
  198. def put_str(self, x, y, s):
  199. """ Print a string.
  200. x -- X coordinate
  201. y -- Y coordinate
  202. s -- the string to print
  203. """
  204. _lib.caca_put_str.argtypes = [
  205. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_char_p
  206. ]
  207. _lib.caca_put_str.restype = ctypes.c_int
  208. if not isinstance(s, str):
  209. raise CanvasError("Specified string is invalid")
  210. else:
  211. try:
  212. ret = _lib.caca_put_str(self, x, y, s)
  213. except ctypes.ArgumentError:
  214. raise CanvasError("Specified coordinate X or Y is invalid")
  215. else:
  216. return ret
  217. def printf(self, x, y, fmt, *args):
  218. """ Print a formated string.
  219. x -- X coordinate
  220. y -- Y coordinate
  221. fmt -- the format string to print
  222. args -- Arguments to the format string
  223. """
  224. _lib.caca_printf.argtypes = [
  225. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_char_p
  226. ]
  227. _lib.caca_printf.restype = ctypes.c_int
  228. if not isinstance(fmt, str):
  229. raise CanvasError("Specified formated string is invalid")
  230. else:
  231. try:
  232. ret = _lib.caca_printf(self, x, y, fmt, *args)
  233. except ctypes.ArgumentError:
  234. raise CanvasError("Specified coordinate X or Y is invalid")
  235. else:
  236. return ret
  237. def vprintf(self, *args, **kw):
  238. """ Not implemented.
  239. """
  240. raise CanvasError, "Not implemented"
  241. def clear(self):
  242. """ Clear the canvas.
  243. """
  244. _lib.caca_clear_canvas.argtypes = [_Canvas]
  245. _lib.caca_clear_canvas.restype = ctypes.c_int
  246. return _lib.caca_clear_canvas(self)
  247. def set_handle(self, x, y):
  248. """ Set cursor handle. Blitting method will use the handle value to
  249. put the canvas at the proper coordinates.
  250. x -- X handle coordinate
  251. y -- Y handle coordinate
  252. """
  253. _lib.caca_set_canvas_handle.argtypes = [
  254. _Canvas, ctypes.c_int, ctypes.c_int
  255. ]
  256. _lib.caca_set_canvas_handle.restype = ctypes.c_int
  257. try:
  258. ret = _lib.caca_set_canvas_handle(self, x, y)
  259. except ctypes.ArgumentError:
  260. raise CanvasError("Specified coordinate X or Y is invalid")
  261. else:
  262. return ret
  263. def get_handle_x(self):
  264. """ Get X handle position.
  265. """
  266. _lib.caca_get_canvas_handle_x.argtypes = [_Canvas]
  267. _lib.caca_get_canvas_handle_x.restype = ctypes.c_int
  268. return _lib.caca_get_canvas_handle_x(self)
  269. def get_handle_y(self):
  270. """ Get Y handle position.
  271. """
  272. _lib.caca_get_canvas_handle_y.argtypes = [_Canvas]
  273. _lib.caca_get_canvas_handle_y.restype = ctypes.c_int
  274. return _lib.caca_get_canvas_handle_y(self)
  275. def blit(self, x, y, cv, mask=None):
  276. """ Blit canvas onto another one.
  277. x -- X coordinate
  278. y -- Y coordinate
  279. cv -- the source canvas
  280. mask -- the mask canvas
  281. """
  282. _lib.caca_blit.argtypes = [
  283. _Canvas, ctypes.c_int, ctypes.c_int, _Canvas, _Canvas
  284. ]
  285. _lib.caca_blit.restype = ctypes.c_int
  286. if not isinstance(cv, Canvas):
  287. raise CanvasError("Specified mask canvas is invalid")
  288. else:
  289. if mask is None:
  290. mask = NullCanvas()
  291. else:
  292. if not isinstance(mask, _Canvas):
  293. raise CanvasError("Specified mask canvas is invalid")
  294. try:
  295. ret = _lib.caca_blit(self, x, y, cv, mask)
  296. except ctypes.ArgumentError:
  297. raise CanvasError("Specified coordinate X or Y is invalid")
  298. else:
  299. if ret == -1:
  300. err = ctypes.c_int.in_dll(_lib, "errno")
  301. if err.value == errno.EINVAL:
  302. raise CanvasError("A mask was specified but the mask size"
  303. " and source canvas size do not match")
  304. else:
  305. return ret
  306. def set_boundaries(self, x, y, width, height):
  307. """ Set a canvas' new boundaries.
  308. x -- X coordinate of the top-left corner
  309. y -- Y coordinate of the top-left corner
  310. width -- width of the box
  311. height -- height of the box
  312. """
  313. _lib.caca_set_canvas_boundaries.argtypes = [
  314. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int
  315. ]
  316. _lib.caca_set_canvas_boundaries.restype = ctypes.c_int
  317. try:
  318. ret = _lib.caca_set_canvas_boundaries(self, x, y, width, height)
  319. except ctypes.ArgumentError:
  320. raise CanvasError("Specified coordinate or size is invalid")
  321. else:
  322. if ret == -1:
  323. err = ctypes.c_int.in_dll(_lib, "errno")
  324. if err.value == errno.EINVAL:
  325. raise CanvasError("Specified width or height is invalid")
  326. elif err.value == errno.EBUSY:
  327. raise CanvasError("The canvas is in use by a display driver"
  328. " and cannot be resized")
  329. elif err.value == errno.ENOMEM:
  330. raise CanvasError("Not enough memory for the requested"
  331. " canvas size")
  332. else:
  333. return ret
  334. def disable_dirty_rect(self):
  335. """ Disable dirty rectangles.
  336. """
  337. _lib.caca_disable_dirty_rect.argtypes = [_Canvas]
  338. _lib.caca_disable_dirty_rect.restype = ctypes.c_int
  339. return _lib.caca_disable_dirty_rect(self)
  340. def enable_dirty_rect(self):
  341. """ Enable dirty rectangles.
  342. """
  343. _lib.caca_enable_dirty_rect.argtypes = [_Canvas]
  344. _lib.caca_enable_dirty_rect.restype = ctypes.c_int
  345. ret = _lib.caca_enable_dirty_rect(self)
  346. if ret == -1:
  347. err = ctypes.c_int.in_dll(_lib, "errno")
  348. if err.value == errno.EINVAL:
  349. raise CanvasError("Dirty rectangles were not disabled")
  350. else:
  351. return ret
  352. def get_dirty_rect_count(self):
  353. """ Get the number of dirty rectangles in the canvas.
  354. """
  355. _lib.caca_get_dirty_rect_count.argtypes = [_Canvas]
  356. _lib.caca_get_dirty_rect_count.restype = ctypes.c_int
  357. return _lib.caca_get_dirty_rect_count(self)
  358. def get_dirty_rect(self, idx):
  359. """ Get a canvas's dirty rectangle. Return python dictionnary with
  360. coords as keys: x, y, width, height.
  361. idx -- the requested rectangle index
  362. """
  363. dct = None
  364. x = ctypes.c_int()
  365. y = ctypes.c_int()
  366. width = ctypes.c_int()
  367. height = ctypes.c_int()
  368. _lib.caca_get_dirty_rect.argtypes = [
  369. _Canvas, ctypes.c_int,
  370. ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int),
  371. ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)
  372. ]
  373. _lib.caca_get_dirty_rect.restype = ctypes.c_int
  374. try:
  375. ret = _lib.caca_get_dirty_rect(self, idx, x, y, width, height)
  376. except ctypes.ArgumentError:
  377. raise CanvasError("Specified rectangle index is invalid")
  378. else:
  379. if ret == -1:
  380. err = ctypes.c_int.in_dll(_lib, "errno")
  381. if err.value == errno.EINVAL:
  382. raise CanvasError("Specified rectangle index is out of"
  383. " bounds")
  384. else:
  385. dct = {
  386. 'x': x.value, 'y': y.value,
  387. 'width': width.value, 'height': height.value,
  388. }
  389. return dct
  390. def add_dirty_rect(self, x, y, width, height):
  391. """ Add an area to the canvas's dirty rectangle list.
  392. x -- the leftmost edge of the additional dirty rectangle
  393. y -- the topmost edge of the additional dirty rectangle
  394. width -- the width of the additional dirty rectangle
  395. height -- the height of the additional dirty rectangle
  396. """
  397. _lib.caca_add_dirty_rect.argtypes = [
  398. _Canvas, ctypes.c_int, ctypes.c_int,
  399. ctypes.c_int, ctypes.c_int
  400. ]
  401. _lib.caca_add_dirty_rect.restype = ctypes.c_int
  402. try:
  403. ret =_lib.caca_add_dirty_rect(self, x, y, width, height)
  404. except ctypes.ArgumentError:
  405. raise CanvasError("Specified coordinate or size is invalid")
  406. else:
  407. if ret == -1:
  408. err = ctypes.c_int.in_dll(_lib, "errno")
  409. if err.value == errno.EINVAL:
  410. raise CanvasError("Specified rectangle coordinates are out"
  411. " of bounds")
  412. else:
  413. return ret
  414. def remove_dirty_rect(self, x, y, width, height):
  415. """ Remove an area from the dirty rectangle list.
  416. x -- the leftmost edge of the additional dirty rectangle
  417. y -- the topmost edge of the additional dirty rectangle
  418. width -- the width of the additional rectangle
  419. height -- the height of the additional dirty rectangle
  420. """
  421. _lib.caca_remove_dirty_rect.argtypes = [
  422. _Canvas, ctypes.c_int, ctypes.c_int,
  423. ctypes.c_int, ctypes.c_int
  424. ]
  425. _lib.caca_remove_dirty_rect.restype = ctypes.c_int
  426. try:
  427. ret = _lib.caca_remove_dirty_rect(self, x, y, width, height)
  428. except ctypes.ArgumentError:
  429. raise CanvasError("Specified coordinate or size is invalid")
  430. else:
  431. if ret == -1:
  432. err = ctypes.c_int.in_dll(_lib, "errno")
  433. if err.value == errno.EINVAL:
  434. raise CanvasError("Specified rectangle coordinates are out"
  435. " of bounds")
  436. else:
  437. return ret
  438. def clear_dirty_rect_list(self):
  439. """ Clear a canvas's dirty rectangle list.
  440. """
  441. _lib.caca_clear_dirty_rect_list.argtypes = [_Canvas]
  442. _lib.caca_clear_dirty_rect_list.restype = ctypes.c_int
  443. return _lib.caca_clear_dirty_rect_list(self)
  444. def invert(self):
  445. """ Invert a canvas' colours.
  446. """
  447. _lib.caca_invert.argtypes = [_Canvas]
  448. _lib.caca_invert.restype = ctypes.c_int
  449. return _lib.caca_invert(self)
  450. def flip(self):
  451. """ Flip a canvas horizontally.
  452. """
  453. _lib.caca_flip.argtypes = [_Canvas]
  454. _lib.caca_flip.restype = ctypes.c_int
  455. return _lib.caca_flip(self)
  456. def flop(self):
  457. """ Flip a canvas vertically.
  458. """
  459. _lib.caca_flop.argtypes = [_Canvas]
  460. _lib.caca_flop.restype = ctypes.c_int
  461. return _lib.caca_flop(self)
  462. def rotate_180(self):
  463. """ Rotate a canvas.
  464. """
  465. _lib.caca_rotate_180.argtypes = [_Canvas]
  466. _lib.caca_rotate_180.restype = ctypes.c_int
  467. return _lib.caca_rotate_180(self)
  468. def rotate_left(self):
  469. """ Rotate a canvas, 90 degrees counterclockwise.
  470. """
  471. _lib.caca_rotate_left.argtypes = [_Canvas]
  472. _lib.caca_rotate_left.restype = ctypes.c_int
  473. ret = _lib.caca_rotate_left(self)
  474. if ret == -1:
  475. err = ctypes.c_int.in_dll(_lib, "errno")
  476. if err.value == errno.EBUSY:
  477. raise CanvasError("The canvas is in use by a display driver"
  478. " and cannot be rotated")
  479. elif err.value == errno.ENOMEM:
  480. raise CanvasError("Not enough memory to allocate the new"
  481. " canvas size")
  482. else:
  483. return ret
  484. def rotate_right(self):
  485. """ Rotate a canvas, 90 degrees clockwise.
  486. """
  487. _lib.caca_rotate_right.argtypes = [_Canvas]
  488. _lib.caca_rotate_right.restype = ctypes.c_int
  489. ret = _lib.caca_rotate_right(self)
  490. if ret == -1:
  491. err = ctypes.c_int.in_dll(_lib, "errno")
  492. if err.value == errno.EBUSY:
  493. raise CanvasError("The canvas is in use by a display driver"
  494. " and cannot be rotated")
  495. elif err.value == errno.ENOMEM:
  496. raise CanvasError("Not enough memory to allocate the new"
  497. " canvas size")
  498. else:
  499. return ret
  500. def stretch_left(self):
  501. """ Rotate and stretch a canvas, 90 degrees counterclockwise.
  502. """
  503. _lib.caca_stretch_left.argtypes = [_Canvas]
  504. _lib.caca_stretch_left.restype = ctypes.c_int
  505. ret = _lib.caca_stretch_left(self)
  506. if ret == -1:
  507. err = ctypes.c_int.in_dll(_lib, "errno")
  508. if err.value == errno.EBUSY:
  509. raise CanvasError("The canvas is in use by a display driver"
  510. " and cannot be rotated")
  511. elif err.value == errno.ENOMEM:
  512. raise CanvasError("Not enough memory to allocate the new"
  513. " canvas size")
  514. else:
  515. return ret
  516. def stretch_right(self):
  517. """ Rotate and stretch a canvas, 90 degrees clockwise.
  518. """
  519. _lib.caca_stretch_right.argtypes = [_Canvas]
  520. _lib.caca_stretch_right.restype = ctypes.c_int
  521. ret = _lib.caca_stretch_right(self)
  522. if ret == -1:
  523. err = ctypes.c_int.in_dll(_lib, "errno")
  524. if err.value == errno.EBUSY:
  525. raise CanvasError("The canvas is in use by a display driver"
  526. " and cannot be rotated")
  527. elif err.value == errno.ENOMEM:
  528. raise CanvasError("Not enough memory to allocate the new"
  529. " canvas size")
  530. else:
  531. return ret
  532. def get_attr(self, x, y):
  533. """ Get the text attribute at the given coordinates.
  534. x -- X coordinate
  535. y -- Y coordinate
  536. """
  537. _lib.caca_get_attr.argtypes = [_Canvas, ctypes.c_int, ctypes.c_int]
  538. _lib.caca_get_attr.restype = ctypes.c_uint32
  539. try:
  540. ret = _lib.caca_get_attr(self, x, y)
  541. except ctypes.ArgumentError:
  542. raise CanvasError("Specified coordinate X or Y is invalid")
  543. else:
  544. return ret
  545. def set_attr(self, attr):
  546. """ Set the default character attribute.
  547. attr -- the requested attribute value
  548. """
  549. _lib.caca_set_attr.argtypes = [_Canvas, ctypes.c_uint32]
  550. _lib.caca_set_attr.restype = ctypes.c_int
  551. try:
  552. ret = _lib.caca_set_attr(self, attr)
  553. except ctypes.ArgumentError:
  554. raise CanvasError("Specified attribute is invalid")
  555. else:
  556. return ret
  557. def unset_attr(self, attr):
  558. """ Unset the default character attribute.
  559. attr -- the requested attribute value
  560. """
  561. _lib.caca_unset_attr.argtypes = [_Canvas, ctypes.c_uint32]
  562. _lib.caca_unset_attr.restype = ctypes.c_int
  563. try:
  564. ret = _lib.caca_unset_attr(self, attr)
  565. except ctypes.ArgumentError:
  566. raise CanvasError("Specified attribute is invalid")
  567. else:
  568. return ret
  569. def toggle_attr(self, attr):
  570. """ Toggle the default character attribute.
  571. attr -- the requested attribute value
  572. """
  573. _lib.caca_toggle_attr.argtypes = [_Canvas, ctypes.c_uint32]
  574. _lib.caca_toggle_attr.restype = ctypes.c_int
  575. try:
  576. ret = _lib.caca_toggle_attr(self, attr)
  577. except ctypes.ArgumentError:
  578. raise CanvasError("Specified attribute is invalid")
  579. else:
  580. return ret
  581. def put_attr(self, x, y, attr):
  582. """ Set the character attribute at the given coordinates.
  583. x -- X coordinate
  584. y -- Y coordinate
  585. attr -- the requested attribute value
  586. """
  587. _lib.caca_put_attr.argtypes = [
  588. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  589. ]
  590. _lib.caca_put_attr.restype = ctypes.c_int
  591. try:
  592. ret = _lib.caca_put_attr(self, x, y, attr)
  593. except ctypes.ArgumentError:
  594. raise CanvasError("Specified coordinate or attribute is invalid")
  595. else:
  596. return ret
  597. def set_color_ansi(self, fg, bg):
  598. """ Set the default colour pair for text (ANSI version).
  599. fg -- the requested ANSI foreground colour.
  600. bg -- the requested ANSI background colour.
  601. """
  602. _lib.caca_set_color_ansi.argtypes = [
  603. _Canvas, ctypes.c_uint8, ctypes.c_uint8
  604. ]
  605. _lib.caca_set_color_ansi.restype = ctypes.c_int
  606. try:
  607. ret = _lib.caca_set_color_ansi(self, fg, bg)
  608. except ctypes.ArgumentError:
  609. raise CanvasError("At least one of the colour values is invalid")
  610. else:
  611. if ret == -1:
  612. err = ctypes.c_int.in_dll(_lib, "errno")
  613. if err.value == errno.EINVAL:
  614. raise CanvasError("At least one of the colour values"
  615. " is invalid")
  616. else:
  617. return ret
  618. def set_color_argb(self, fg, bg):
  619. """ Set the default colour pair for text (truecolor version).
  620. fg -- the requested ARGB foreground colour.
  621. bg -- the requested ARGB background colour.
  622. """
  623. _lib.caca_set_color_argb.argtypes = [
  624. _Canvas, ctypes.c_uint16, ctypes.c_uint16
  625. ]
  626. _lib.caca_set_color_argb.restype = ctypes.c_int
  627. try:
  628. ret = _lib.caca_set_color_argb(self, fg, bg)
  629. except ctypes.ArgumentError:
  630. raise CanvasError("At least one of the colour values is invalid")
  631. else:
  632. return ret
  633. def draw_line(self, x1, y1, x2, y2, ch):
  634. """ Draw a line on the canvas using the given character.
  635. x1 -- X coordinate of the first point
  636. y1 -- Y coordinate of the first point
  637. x2 -- X coordinate of the second point
  638. y2 -- Y coordinate of the second point
  639. ch -- character to be used to draw the line
  640. """
  641. _lib.caca_draw_line.argtypes = [
  642. _Canvas, ctypes.c_int, ctypes.c_int,
  643. ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  644. ]
  645. _lib.caca_draw_line.restype = ctypes.c_int
  646. if not isinstance(ch, str):
  647. raise CanvasError("Specified character is invalid")
  648. else:
  649. try:
  650. ch = ord(ch)
  651. except TypeError:
  652. ch = utf8_to_utf32(ch)
  653. try:
  654. ret = _lib.caca_draw_line(self, x1, y1, x2, y2, ch)
  655. except ctypes.ArgumentError:
  656. raise CanvasError("specified coordinate is invalid")
  657. else:
  658. return ret
  659. def draw_polyline(self, array_xy, ch):
  660. """ Draw a polyline.
  661. array_xy -- List of (X, Y) coordinates
  662. ch -- character to be used to draw the line
  663. """
  664. if not isinstance(array_xy, list) or len(array_xy) < 2:
  665. raise CanvasError("Specified array of coordinates is invalid")
  666. else:
  667. for item in array_xy:
  668. if not isinstance(item, list) and \
  669. not isinstance(item, tuple):
  670. raise CanvasError("Specified array of coordinates"
  671. " is invalid")
  672. ax = ctypes.c_int * len(array_xy)
  673. ay = ctypes.c_int * len(array_xy)
  674. _lib.caca_draw_polyline.argtypes = [
  675. _Canvas, ax, ay, ctypes.c_int, ctypes.c_uint32
  676. ]
  677. _lib.caca_draw_polyline.restype = ctypes.c_int
  678. if not isinstance(ch, str):
  679. raise CanvasError("Specified character is invalid")
  680. else:
  681. try:
  682. ch = ord(ch)
  683. except TypeError:
  684. ch = utf8_to_utf32(ch)
  685. try:
  686. ax = ax(*[x[0] for x in array_xy])
  687. ay = ay(*[y[1] for y in array_xy])
  688. except IndexError:
  689. raise CanvasError("Specified array coordinates is invalid")
  690. try:
  691. ret = _lib.caca_draw_polyline(self, ax, ay,
  692. len(array_xy) - 1, ch)
  693. except ctypes.ArgumentError:
  694. raise CanvasError("specified array of coordinates is invalid")
  695. else:
  696. return ret
  697. def draw_thin_line(self, x1, y1, x2, y2):
  698. """ Draw a thin line on the canvas, using ASCII art.
  699. x1 -- X coordinate of the first point
  700. y1 -- Y coordinate of the first point
  701. x2 -- X coordinate of the second point
  702. y2 -- Y coordinate of the second point
  703. """
  704. _lib.caca_draw_thin_line.argtypes = [
  705. _Canvas, ctypes.c_int, ctypes.c_int,
  706. ctypes.c_int, ctypes.c_int
  707. ]
  708. _lib.caca_draw_thin_line.restype = ctypes.c_int
  709. try:
  710. ret = _lib.caca_draw_thin_line(self, x1, y1, x2, y2)
  711. except ctypes.ArgumentError:
  712. raise CanvasError("specified coordinate is invalid")
  713. else:
  714. return ret
  715. def draw_thin_polyline(self, array_xy):
  716. """ Draw an ASCII art thin polyline.
  717. array_xy -- Array of (X, Y) coordinates
  718. """
  719. if not isinstance(array_xy, list) or len(array_xy) < 2:
  720. raise CanvasError("Specified array of coordinates is invalid")
  721. else:
  722. for item in array_xy:
  723. if not isinstance(item, list) and \
  724. not isinstance(item, tuple):
  725. raise CanvasError("Specified array of coordinates"
  726. " is invalid")
  727. ax = ctypes.c_int * len(array_xy)
  728. ay = ctypes.c_int * len(array_xy)
  729. _lib.caca_draw_thin_polyline.argtypes = [
  730. Canvas, ax, ay, ctypes.c_int
  731. ]
  732. _lib.caca_draw_thin_polyline.restype = ctypes.c_int
  733. try:
  734. ax = ax(*[x[0] for x in array_xy])
  735. ay = ay(*[y[1] for y in array_xy])
  736. except IndexError:
  737. raise CanvasError("Specified array coordinates is invalid")
  738. try:
  739. ret = _lib.caca_draw_thin_polyline(self, ax, ay, len(array_xy) - 1)
  740. except ctypes.ArgumentError:
  741. raise CanvasError("specified array of coordinates is invalid")
  742. else:
  743. return ret
  744. def draw_circle(self, x, y, r, ch):
  745. """ Draw a circle on the canvas using the given character.
  746. x -- center X coordinate
  747. y -- center Y coordinate
  748. r -- circle radius
  749. ch -- the UTF-32 character to be used to draw the circle outline
  750. """
  751. _lib.caca_draw_circle.argtypes = [
  752. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  753. ]
  754. _lib.caca_draw_circle.restype = ctypes.c_int
  755. if not isinstance(ch, str):
  756. raise CanvasError("Specified character is invalid")
  757. else:
  758. try:
  759. ch = ord(ch)
  760. except TypeError:
  761. ch = utf8_to_utf32(ch)
  762. try:
  763. ret = _lib.caca_draw_circle(self, x, y, r, ch)
  764. except ctypes.ArgumentError:
  765. raise CanvasError("Specified circle coordinate or radius is"
  766. " invalid")
  767. else:
  768. return ret
  769. def draw_ellipse(self, xo, yo, a, b, ch):
  770. """ Draw an ellipse on the canvas using the given character.
  771. xo -- center X coordinate
  772. yo -- center Y coordinate
  773. a -- ellipse x radius
  774. b -- ellipse y radius
  775. ch -- UTF-32 character to be used to draw the ellipse outline
  776. """
  777. _lib.caca_draw_ellipse.argtypes = [
  778. _Canvas, ctypes.c_int, ctypes.c_int,
  779. ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  780. ]
  781. _lib.caca_draw_ellipse.restype = ctypes.c_int
  782. if not isinstance(ch, str):
  783. raise CanvasError("Specified character is invalid")
  784. else:
  785. try:
  786. ch = ord(ch)
  787. except TypeError:
  788. ch = utf8_to_utf32(ch)
  789. try:
  790. ret = _lib.caca_draw_ellipse(self, xo, yo, a, b, ch)
  791. except ctypes.ArgumentError:
  792. raise CanvasError("Specified ellipse coordinate or radius is"
  793. " invalid")
  794. else:
  795. return ret
  796. def draw_thin_ellipse(self, xo, yo, a, b):
  797. """ Draw a thin ellipse on the canvas.
  798. xo -- center X coordinate
  799. yo -- center Y coordinate
  800. a -- ellipse X radius
  801. b -- ellipse Y radius
  802. """
  803. _lib.caca_draw_thin_ellipse.argtypes = [
  804. _Canvas, ctypes.c_int, ctypes.c_int,
  805. ctypes.c_int, ctypes.c_int
  806. ]
  807. _lib.caca_draw_thin_ellipse.restype = ctypes.c_int
  808. try:
  809. ret = _lib.caca_draw_thin_ellipse(self, xo, yo, a, b)
  810. except ctypes.ArgumentError:
  811. raise CanvasError("Specified ellipse coordinate or radius is"
  812. " invalid")
  813. else:
  814. return ret
  815. def fill_ellipse(self, xo, yo, a, b, ch):
  816. """ Fill an ellipse on the canvas using the given character.
  817. xo -- center X coordinate
  818. yo -- center Y coordinate
  819. a -- ellipse X radius
  820. b -- ellipse Y radius
  821. ch -- UTF-32 character to be used to fill the ellipse
  822. """
  823. _lib.caca_fill_ellipse.argtypes = [
  824. _Canvas, ctypes.c_int, ctypes.c_int,
  825. ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  826. ]
  827. _lib.caca_fill_ellipse.restype = ctypes.c_int
  828. if not isinstance(ch, str):
  829. raise CanvasError("Specified character is invalid")
  830. else:
  831. try:
  832. ch = ord(ch)
  833. except TypeError:
  834. ch = utf8_to_utf32(ch)
  835. try:
  836. ret = _lib.caca_fill_ellipse(self, xo, yo, a, b, ch)
  837. except ctypes.ArgumentError:
  838. raise CanvasError("Specified ellipse coordinate or radius is"
  839. " invalid")
  840. else:
  841. return ret
  842. def draw_box(self, x, y, width, height, ch):
  843. """ Draw a box on the canvas using the given character.
  844. x -- X coordinate of the upper-left corner of the box
  845. y -- Y coordinate of the upper-left corner of the box
  846. width -- width of the box
  847. height -- height of the box
  848. ch -- character to be used to draw the box
  849. """
  850. _lib.caca_draw_box.argtypes = [
  851. Canvas, ctypes.c_int, ctypes.c_int,
  852. ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  853. ]
  854. _lib.caca_draw_box.restype = ctypes.c_int
  855. if not isinstance(ch, str):
  856. raise CanvasError("Specified character is invalid")
  857. else:
  858. try:
  859. ch = ord(ch)
  860. except TypeError:
  861. ch = utf8_to_utf32(ch)
  862. try:
  863. ret = _lib.caca_draw_box(self, x, y, width, height, ch)
  864. except ctypes.ArgumentError:
  865. raise CanvasError("specified box coordinate is invalid")
  866. else:
  867. return ret
  868. def draw_thin_box(self, x, y, width, height):
  869. """ Draw a thin box on the canvas.
  870. x -- X coordinate of the upper-left corner of the box
  871. y -- Y coordinate of the upper-left corner of the box
  872. width -- width of the box
  873. height -- height of the box
  874. """
  875. _lib.caca_draw_thin_box.argtypes = [
  876. _Canvas, ctypes.c_int, ctypes.c_int,
  877. ctypes.c_int, ctypes.c_int
  878. ]
  879. _lib.caca_draw_thin_box.restype = ctypes.c_int
  880. try:
  881. ret = _lib.caca_draw_thin_box(self, x, y, width, height)
  882. except ctypes.ArgumentError:
  883. raise CanvasError("specified box coordinate is invalid")
  884. else:
  885. return ret
  886. def draw_cp437_box(self, x, y, width, height):
  887. """ Draw a box on the canvas using CP437 characters.
  888. x -- X coordinate of the upper-left corner box
  889. y -- Y coordinate of the upper-left corner box
  890. width -- width of the box
  891. height -- height of the box
  892. """
  893. _lib.caca_draw_cp437_box.argtypes = [
  894. _Canvas, ctypes.c_int, ctypes.c_int,
  895. ctypes.c_int, ctypes.c_int
  896. ]
  897. _lib.caca_draw_cp437_box.restype = ctypes.c_int
  898. try:
  899. ret = _lib.caca_draw_cp437_box(self, x, y, width, height)
  900. except ctypes.ArgumentError:
  901. raise CanvasError("specified box coordinate is invalid")
  902. else:
  903. return ret
  904. def fill_box(self, x, y, width, height, ch):
  905. """ Fill a box on the canvas using the given character.
  906. x -- X coordinate of the upper-left corner of the box
  907. y -- Y coordinate of the upper-left corner of the box
  908. width -- width of the box
  909. height -- height of the box
  910. ch -- UFT-32 character to be used to fill the box
  911. """
  912. _lib.caca_fill_box.argtypes = [
  913. _Canvas, ctypes.c_int, ctypes.c_int,
  914. ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  915. ]
  916. _lib.caca_fill_box.restype = ctypes.c_int
  917. if not isinstance(ch, str):
  918. raise CanvasError("Specified character is invalid")
  919. else:
  920. try:
  921. ch = ord(ch)
  922. except TypeError:
  923. ch = utf8_to_utf32(ch)
  924. try:
  925. ret = _lib.caca_fill_box(self, x, y, width, height, ch)
  926. except ctypes.ArgumentError:
  927. raise CanvasError("specified box coordinate is invalid")
  928. else:
  929. return ret
  930. def draw_triangle(self, x1, y1, x2, y2, x3, y3, ch):
  931. """ Draw a triangle on the canvas using the given character.
  932. x1 -- X coordinate of the first point
  933. y1 -- Y coordinate of the first point
  934. x2 -- X coordinate of the second point
  935. y2 -- Y coordinate of the second point
  936. x3 -- X coordinate of the third point
  937. y3 -- Y coordinate of the third point
  938. ch -- UTF-32 character to be used to draw the triangle outline
  939. """
  940. _lib.caca_draw_triangle.argtypes = [
  941. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int,
  942. ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_uint32
  943. ]
  944. _lib.caca_draw_triangle.restype = ctypes.c_int
  945. if not isinstance(ch, str):
  946. raise CanvasError("Specified character is invalid")
  947. else:
  948. try:
  949. ch = ord(ch)
  950. except TypeError:
  951. ch = utf8_to_utf32(ch)
  952. try:
  953. ret = _lib.caca_draw_triangle(self, x1, y1, x2, y2, x3, y3, ch)
  954. except ctypes.ArgumentError:
  955. raise CanvasError("specified triangle coordinate is invalid")
  956. else:
  957. return ret
  958. def draw_thin_triangle(self, x1, y1, x2, y2, x3, y3):
  959. """ Draw a thin triangle on the canvas.
  960. x1 -- X coordinate of the first point
  961. y1 -- Y coordinate of the first point
  962. x2 -- X coordinate of the second point
  963. y2 -- Y coordinate of the second point
  964. x3 -- X coordinate of the third point
  965. y3 -- Y coordinate of the third point
  966. """
  967. _lib.caca_draw_thin_triangle.argtypes = [
  968. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int,
  969. ctypes.c_int, ctypes.c_int, ctypes.c_int
  970. ]
  971. _lib.caca_draw_thin_triangle.restype = ctypes.c_int
  972. try:
  973. ret = _lib.caca_draw_thin_triangle(self, x1, y1, x2, y2, x3, y3)
  974. except ctypes.ArgumentError:
  975. raise CanvasError("specified triangle coordinate is invalid")
  976. else:
  977. return ret
  978. def fill_triangle(self, x1, y1, x2, y2, x3, y3, ch):
  979. """ Fill a triangle on the canvas using the given character.
  980. x1 -- X coordinate of the first point
  981. y1 -- Y coordinate of the first point
  982. x2 -- X coordinate of the second point
  983. y2 -- Y coordinate of the second point
  984. x3 -- X coordinate of the second point
  985. y3 -- Y coordinate of the second point
  986. ch -- UTF-32 character to be used to fill the triangle
  987. """
  988. _lib.caca_fill_triangle.argtypes = [
  989. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int,
  990. ctypes.c_int, ctypes.c_int, ctypes.c_int
  991. ]
  992. _lib.caca_fill_triangle.restype = ctypes.c_int
  993. if not isinstance(ch, str):
  994. raise CanvasError("Specified character is invalid")
  995. else:
  996. try:
  997. ch = ord(ch)
  998. except TypeError:
  999. ch = utf8_to_utf32(ch)
  1000. try:
  1001. ret = _lib.caca_fill_triangle(self, x1, y1, x2, y2, x3, y3, ch)
  1002. except ctypes.ArgumentError:
  1003. raise CanvasError("specified triangle coordinate is invalid")
  1004. else:
  1005. return ret
  1006. def fill_triangle_textured(self, coords, tex, uv):
  1007. """ Fill a triangle on the canvas using an arbitrary-sized texture.
  1008. coords -- coordinates of the triangle (3{x,y})
  1009. tex -- the handle of the canvas texture
  1010. uv -- coordinates of the texture (3{u,v})
  1011. """
  1012. _lib.caca_fill_triangle_textured.argtypes = [
  1013. _Canvas, ctypes.c_int * 6, _Canvas, ctypes.c_int * 6
  1014. ]
  1015. _lib.caca_fill_triangle_textured.restype = ctypes.c_int
  1016. return _lib.caca_fill_triangle_textured(self, coords, tex, uv)
  1017. def get_frame_count(self):
  1018. """ Get the number of frames in a canvas.
  1019. """
  1020. _lib.caca_get_frame_count.argtypes = [_Canvas]
  1021. _lib.caca_get_frame_count.restype = ctypes.c_int
  1022. return _lib.caca_get_frame_count(self)
  1023. def set_frame(self, idx):
  1024. """ Activate a given canvas frame.
  1025. idx -- the canvas frame to activate
  1026. """
  1027. _lib.caca_set_frame.argtypes = [_Canvas, ctypes.c_int]
  1028. _lib.caca_set_frame.restype = ctypes.c_int
  1029. try:
  1030. ret = _lib.caca_set_frame(self, idx)
  1031. except ctypes.ArgumentError:
  1032. raise CanvasError("specified index is invalid")
  1033. else:
  1034. err = ctypes.c_int.in_dll(_lib, "errno")
  1035. if err.value == errno.EINVAL:
  1036. raise CanvasError("Requested frame is out of range")
  1037. else:
  1038. return ret
  1039. def get_frame_name(self):
  1040. """ Get the current frame's name.
  1041. """
  1042. _lib.caca_get_frame_name.argtypes = [_Canvas]
  1043. _lib.caca_get_frame_name.restype = ctypes.c_char_p
  1044. return _lib.caca_get_frame_name(self)
  1045. def set_frame_name(self, name):
  1046. """ Set the current frame's name.
  1047. name -- the name to give to the current frame
  1048. """
  1049. _lib.caca_set_frame_name.argtypes = [_Canvas, ctypes.c_char_p]
  1050. _lib.caca_set_frame_name.restype = ctypes.c_int
  1051. try:
  1052. ret = _lib.caca_set_frame_name(self, name)
  1053. except ctypes.ArgumentError:
  1054. raise CanvasError("Specified name is invalid")
  1055. else:
  1056. err = ctypes.c_int.in_dll(_lib, "errno")
  1057. if err.value == errno.ENOMEM:
  1058. raise CanvasError("Not enough memory to allocate new frame")
  1059. else:
  1060. return ret
  1061. def create_frame(self, idx):
  1062. """ Add a frame to a canvas.
  1063. idx -- the index where to insert the new frame
  1064. """
  1065. _lib.caca_create_frame.argtypes = [_Canvas, ctypes.c_int]
  1066. _lib.caca_create_frame.restype = ctypes.c_int
  1067. try:
  1068. ret = _lib.caca_create_frame(self, idx)
  1069. except ctypes.ArgumentError:
  1070. raise CanvasError("specified index is invalid")
  1071. else:
  1072. err = ctypes.c_int.in_dll(_lib, "errno")
  1073. if err.value == errno.ENOMEM:
  1074. raise CanvasError("Not enough memory to allocate new frame")
  1075. else:
  1076. return ret
  1077. def free_frame(self, idx):
  1078. """ Remove a frame from a canvas.
  1079. idx -- the index of the frame to delete
  1080. """
  1081. _lib.caca_free_frame.argtypes = [_Canvas, ctypes.c_int]
  1082. _lib.caca_free_frame.restype = ctypes.c_int
  1083. try:
  1084. ret = _lib.caca_free_frame(self, idx)
  1085. except ctypes.ArgumentError:
  1086. raise CanvasError("specified index is invalid")
  1087. else:
  1088. err = ctypes.c_int.in_dll(_lib, "errno")
  1089. if err.value == errno.EINVAL:
  1090. raise CanvasError("Requested frame is out of range, or attempt"
  1091. " to delete the last frame of the canvas")
  1092. else:
  1093. return ret
  1094. def import_from_memory(self, data, fmt):
  1095. """ Import a memory buffer into a canvas.
  1096. data -- a memory area containing the data to be loaded into
  1097. the canvas
  1098. fmt -- a string describing the input format
  1099. Valid values for format are:
  1100. - "": attempt to autodetect the file format.
  1101. - caca: import native libcaca files.
  1102. - text: import ASCII text files.
  1103. - ansi: import ANSI files.
  1104. - utf8: import UTF-8 files with ANSI colour codes.
  1105. """
  1106. length = ctypes.c_size_t(len(data))
  1107. _lib.caca_import_canvas_from_memory.argtypes = [
  1108. Canvas, ctypes.c_char_p,
  1109. ctypes.c_size_t, ctypes.c_char_p
  1110. ]
  1111. _lib.caca_import_canvas_from_memory.restype = ctypes.c_int
  1112. if not isinstance(fmt, str):
  1113. raise CanvasError("Invalid format requested")
  1114. try:
  1115. ret = _lib.caca_import_canvas_from_memory(self, data, length, fmt)
  1116. except ctypes.ArgumentError:
  1117. raise CanvasError("Given data are invalid")
  1118. else:
  1119. err = ctypes.c_int.in_dll(_lib, "errno")
  1120. if ret == -1:
  1121. if err.value == errno.ENOMEM:
  1122. raise CanvasError("Not enough memory to allocate canvas")
  1123. elif err.value == errno.EINVAL:
  1124. raise CanvasError("Invalid format requested")
  1125. else:
  1126. return ret
  1127. def import_from_file(self, filename, fmt):
  1128. """ Import a file into a canvas.
  1129. filename -- the name of the file to load
  1130. fmt -- a string describing the input format
  1131. Valid values for format are:
  1132. - "": attempt to autodetect the file format.
  1133. - caca: import native libcaca files.
  1134. - text: import ASCII text files.
  1135. - ansi: import ANSI files.
  1136. - utf8: import UTF-8 files with ANSI colour codes.
  1137. """
  1138. _lib.caca_import_canvas_from_file.argtypes = [
  1139. _Canvas, ctypes.c_char_p, ctypes.c_char_p
  1140. ]
  1141. _lib.caca_import_canvas_from_file.restype = ctypes.c_int
  1142. if not isinstance(fmt, str):
  1143. raise CanvasError("Invalid format requested")
  1144. try:
  1145. ret = _lib.caca_import_canvas_from_file(self, filename, fmt)
  1146. except ctypes.ArgumentError:
  1147. raise CanvasError("Specified filename is invalid")
  1148. else:
  1149. err = ctypes.c_int.in_dll(_lib, "errno")
  1150. if ret == -1:
  1151. if err.value == errno.ENOSYS:
  1152. raise CanvasError("File access is not implemented on this"
  1153. " system")
  1154. elif err.value == errno.ENOMEM:
  1155. raise CanvasError("Not enough memory to allocate canvas")
  1156. elif err.value == errno.EINVAL:
  1157. raise CanvasError("Invalid format requested")
  1158. else:
  1159. return ret
  1160. def import_area_from_memory(self, x, y, data, fmt):
  1161. """ Import a memory buffer into a canvas area.
  1162. x -- the leftmost coordinate of the area to import to
  1163. y -- the topmost coordinate of the area to import to
  1164. data -- a memory area containing the data to be loaded into
  1165. the canvas
  1166. fmt -- a string describing the input format
  1167. Valid values for format are:
  1168. - "": attempt to autodetect the file format.
  1169. - caca: import native libcaca files.
  1170. - text: import ASCII text files.
  1171. - ansi: import ANSI files.
  1172. - utf8: import UTF-8 files with ANSI colour codes.
  1173. """
  1174. length = ctypes.c_size_t(len(data))
  1175. _lib.caca_import_area_from_memory.argtypes = [
  1176. _Canvas, ctypes.c_int, ctypes.c_int,
  1177. ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p
  1178. ]
  1179. _lib.caca_import_area_from_memory.restype = ctypes.c_int
  1180. if not isinstance(fmt, str):
  1181. raise CanvasError("Invalid format requested")
  1182. elif not isinstance(data, str):
  1183. raise CanvasError("Given data are invalid")
  1184. try:
  1185. ret = _lib.caca_import_area_from_memory(self, x, y,
  1186. data, length, fmt)
  1187. except ctypes.ArgumentError:
  1188. raise CanvasError("Specified coordinate X or Y is invalid")
  1189. else:
  1190. if ret == -1:
  1191. err = ctypes.c_int.in_dll(_lib, "errno")
  1192. if err.value == errno.EINVAL:
  1193. raise CanvasError("Unsupported format requested or"
  1194. " invalid coordinates")
  1195. elif err.value == errno.ENOMEM:
  1196. raise CanvasError("Not enough memory to allocate canvas")
  1197. else:
  1198. return ret
  1199. def import_area_from_file(self, x, y, filename, fmt):
  1200. """ Import a file into a canvas area.
  1201. x -- the leftmost coordinate of the area to import to
  1202. y -- the topmost coordinate of the area to import to
  1203. filename -- the name of the file to be load
  1204. fmt -- a string describing the input format
  1205. Valid values for format are:
  1206. - "": attempt to autodetect the file format.
  1207. - caca: import native libcaca files.
  1208. - text: import ASCII text files.
  1209. - ansi: import ANSI files.
  1210. - utf8: import UTF-8 files with ANSI colour codes.
  1211. """
  1212. _lib.caca_import_area_from_file.argtypes = [
  1213. _Canvas, ctypes.c_int, ctypes.c_int,
  1214. ctypes.c_char_p, ctypes.c_char_p
  1215. ]
  1216. _lib.caca_import_area_from_file.restype = ctypes.c_int
  1217. if not isinstance(fmt, str):
  1218. raise CanvasError("Invalid format requested")
  1219. elif not isinstance(filename, str):
  1220. raise CanvasError("Invalid filename requested")
  1221. try:
  1222. ret = _lib.caca_import_area_from_file(self, x, y, filename, fmt)
  1223. except ctypes.ArgumentError:
  1224. raise CanvasError("Specified coordinate X or Y is invalid")
  1225. else:
  1226. if ret == -1:
  1227. err = ctypes.c_int.in_dll(_lib, "errno")
  1228. if err.value == errno.ENOSYS:
  1229. raise CanvasError("File access is not implemented on this"
  1230. " system")
  1231. elif err.value == errno.ENOMEM:
  1232. raise CanvasError("Not enough memory to allocate canvas")
  1233. elif err.value == errno.EINVAL:
  1234. raise CanvasError("Unsupported format requested or"
  1235. " invalid coordinates")
  1236. else:
  1237. return ret
  1238. def export_to_memory(self, fmt):
  1239. """ Export a canvas into a foreign format.
  1240. fmt -- a string describing the output format
  1241. Valid values for format are:
  1242. - caca: export native libcaca files.
  1243. - ansi: export ANSI art (CP437 charset with ANSI colour codes).
  1244. - html: export an HTML page with CSS information.
  1245. - html3: export an HTML table that should be compatible with
  1246. most navigators, including textmode ones.
  1247. - irc: export UTF-8 text with mIRC colour codes.
  1248. - ps: export a PostScript document.
  1249. - svg: export an SVG vector image.
  1250. - tga: export a TGA image.
  1251. """
  1252. p_size_t = ctypes.POINTER(ctypes.c_size_t)
  1253. _lib.caca_export_canvas_to_memory.argtypes = [
  1254. _Canvas, ctypes.c_char_p, p_size_t
  1255. ]
  1256. _lib.caca_export_canvas_to_memory.restype = ctypes.POINTER(ctypes.c_char_p)
  1257. p = ctypes.c_size_t()
  1258. try:
  1259. ret = _lib.caca_export_canvas_to_memory(self, fmt, p)
  1260. except ctypes.ArgumentError:
  1261. raise CanvasError("Invalid format requested")
  1262. else:
  1263. if not ret:
  1264. err = ctypes.c_int.in_dll(_lib, "errno")
  1265. if err.value == errno.EINVAL:
  1266. raise CanvasError("Invalid format requested")
  1267. elif err.value == errno.ENOMEM:
  1268. raise CanvasError("Not enough memory to allocate output"
  1269. " buffer")
  1270. else:
  1271. return ctypes.string_at(ret, p.value)
  1272. def export_area_to_memory(self, x, y, width, height, fmt):
  1273. """ Export a canvas portion into a foreign format.
  1274. x -- the leftmost coordinate of the area to export
  1275. y -- the topmost coordinate of the area to export
  1276. width -- the width of the area to export
  1277. height -- the height of the area to export
  1278. fmt -- a string describing the output format
  1279. Valid values for format are:
  1280. - caca: export native libcaca files.
  1281. - ansi: export ANSI art (CP437 charset with ANSI colour codes).
  1282. - html: export an HTML page with CSS information.
  1283. - html3: export an HTML table that should be compatible with
  1284. most navigators, including textmode ones.
  1285. - irc: export UTF-8 text with mIRC colour codes.
  1286. - ps: export a PostScript document.
  1287. - svg: export an SVG vector image.
  1288. - tga: export a TGA image.
  1289. """
  1290. p_size_t = ctypes.POINTER(ctypes.c_size_t)
  1291. _lib.caca_export_area_to_memory.argtypes = [
  1292. _Canvas, ctypes.c_int, ctypes.c_int, ctypes.c_int,
  1293. ctypes.c_int, ctypes.c_char_p, p_size_t
  1294. ]
  1295. _lib.caca_export_area_to_memory.restype = ctypes.POINTER(ctypes.c_char_p)
  1296. p = ctypes.c_size_t()
  1297. if not isinstance(fmt, str):
  1298. raise CanvasError("Invalid format requested")
  1299. try:
  1300. ret = _lib.caca_export_area_to_memory(self, x, y, width, height,
  1301. fmt, p)
  1302. except ctypes.ArgumentError:
  1303. raise CanvasError("Requested area coordinate is invalid")
  1304. else:
  1305. if not ret:
  1306. err = ctypes.c_int.in_dll(_lib, "errno")
  1307. if err.value == errno.EINVAL:
  1308. raise CanvasError("Invalid format requested")
  1309. elif err.value == errno.ENOMEM:
  1310. raise CanvasError("Not enough memory to allocate output"
  1311. " buffer")
  1312. else:
  1313. return ctypes.string_at(ret, p.value)
  1314. def set_figfont(self, filename):
  1315. """ Load a figfont and attach it to a canvas.
  1316. filename -- the figfont file to load.
  1317. """
  1318. _lib.caca_canvas_set_figfont.argtypes = [_Canvas, ctypes.c_char_p]
  1319. _lib.caca_canvas_set_figfont.restype = ctypes.c_int
  1320. if not isinstance(filename, str):
  1321. raise CanvasError("Invalid filename requested")
  1322. else:
  1323. return _lib.caca_canvas_set_figfont(self, filename)
  1324. def put_figchar(self, ch):
  1325. """ Paste a character using the current figfont.
  1326. ch -- the character to paste
  1327. """
  1328. _lib.caca_put_figchar.argtypes = [_Canvas, ctypes.c_uint32]
  1329. _lib.caca_put_figchar.restype = ctypes.c_int
  1330. if not isinstance(ch, str):
  1331. raise CanvasError("Specified character is invalid")
  1332. else:
  1333. try:
  1334. ch = ord(ch)
  1335. except TypeError:
  1336. ch = utf8_to_utf32(ch)
  1337. return _lib.caca_put_figchar(self, ch)
  1338. def flush_figlet(self):
  1339. """ Flush the figlet context
  1340. """
  1341. _lib.caca_flush_figlet.argtypes = [_Canvas]
  1342. _lib.caca_flush_figlet.restype = ctypes.c_int
  1343. return _lib.caca_flush_figlet(self)
  1344. def render(self, font, buf, width, height, pitch):
  1345. """ Render the canvas onto an image buffer.
  1346. font -- a Font() object
  1347. buf -- the image buffer
  1348. width -- the width (in pixels) of the image
  1349. heigth -- the height (in pixels) of the image
  1350. pitch -- the pitch (in bytes) of the image
  1351. """
  1352. _lib.caca_render_canvas.argtypes = [
  1353. _Canvas, _Font, ctypes.c_char_p,
  1354. ctypes.c_int, ctypes.c_int, ctypes.c_int
  1355. ]
  1356. _lib.caca_render_canvas.restype = ctypes.c_int
  1357. return _lib.caca_render_canvas(self, font, buf, width, height, pitch)
  1358. class NullCanvas(_Canvas):
  1359. """ Represent a NULL canvas_t, eg to use as canvas mask for blit operations.
  1360. """
  1361. def __str__(self):
  1362. return "<NullCanvas>"
  1363. class CanvasError(Exception):
  1364. pass