You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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