您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

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