"Fossies" - the Fresh Open Source Software Archive

Member "libcaca-0.99.beta20/python/caca/canvas.py" (21 Apr 2017, 58986 Bytes) of package /linux/privat/libcaca-0.99.beta20.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "canvas.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.99.beta19_vs_0.99.beta20.

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