Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

canvas.py 58 KiB

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