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

216 lines
6.9 KiB

  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software. It comes without any warranty, to
  9. * the extent permitted by applicable law. You can redistribute it
  10. * and/or modify it under the terms of the Do What The Fuck You Want
  11. * To Public License, Version 2, as published by Sam Hocevar. See
  12. * http://sam.zoy.org/wtfpl/COPYING for more details.
  13. */
  14. /*
  15. * This file contains the dirty rectangle handling functions.
  16. */
  17. #include "config.h"
  18. #if !defined(__KERNEL__)
  19. # include <stdio.h>
  20. #endif
  21. #include "caca.h"
  22. #include "caca_internals.h"
  23. /** \brief Get the number of dirty rectangles in the canvas.
  24. *
  25. * Get the number of dirty rectangles in a canvas. Dirty rectangles are
  26. * areas that contain cells that have changed since the last reset.
  27. *
  28. * The dirty rectangles are used internally by display drivers to optimise
  29. * rendering by avoiding to redraw the whole screen. Once the display driver
  30. * has rendered the canvas, it resets the dirty rectangle list.
  31. *
  32. * Dirty rectangles are guaranteed not to overlap.
  33. *
  34. * This function never fails.
  35. *
  36. * \param cv A libcaca canvas.
  37. * \return The number of dirty rectangles in the given canvas.
  38. */
  39. int caca_get_dirty_rectangle_count(caca_canvas_t *cv)
  40. {
  41. /* Ignore empty rectangles. */
  42. if(cv->dirty_xmin > cv->dirty_xmax || cv->dirty_ymin > cv->dirty_ymax)
  43. return 0;
  44. /* Ignore out-of-bounds rectangles. */
  45. if(cv->dirty_xmax < 0 || cv->dirty_xmin >= cv->width
  46. || cv->dirty_ymax < 0 || cv->dirty_ymin >= cv->height)
  47. return 0;
  48. return 1;
  49. }
  50. /** \brief Get a canvas's dirty rectangle.
  51. *
  52. * Get the canvas's given dirty rectangle coordinates. The index must be
  53. * within the dirty rectangle count. See caca_get_dirty_rectangle_count()
  54. * for how to compute this count.
  55. *
  56. * If an error occurs, no coordinates are written in the pointer arguments,
  57. * -1 is returned and \b errno is set accordingly:
  58. * - \c EINVAL Specified rectangle index is out of bounds.
  59. *
  60. * \param cv A libcaca canvas.
  61. * \param index The requested rectangle index.
  62. * \param xmin A pointer to an integer where the leftmost edge of the
  63. * dirty rectangle will be stored.
  64. * \param ymin A pointer to an integer where the topmost edge of the
  65. * dirty rectangle will be stored.
  66. * \param xmax A pointer to an integer where the rightmost edge of the
  67. * dirty rectangle will be stored.
  68. * \param ymax A pointer to an integer where the bottommost edge of the
  69. * dirty rectangle will be stored.
  70. * \return 0 in case of success, -1 if an error occurred.
  71. */
  72. int caca_get_dirty_rectangle(caca_canvas_t *cv, int index,
  73. int *xmin, int *ymin, int *xmax, int *ymax)
  74. {
  75. /* For now, index can only be zero, and if the dirty rectangle is
  76. * empty, we don't return anything. */
  77. if(index < 0 || index > 0
  78. || cv->dirty_xmin > cv->dirty_xmax || cv->dirty_ymin > cv->dirty_ymax
  79. || cv->dirty_xmax < 0 || cv->dirty_xmin >= cv->width
  80. || cv->dirty_ymax < 0 || cv->dirty_ymin >= cv->height)
  81. {
  82. seterrno(EINVAL);
  83. return -1;
  84. }
  85. /* Normalise dirty rectangle so that the values can be directly used. */
  86. if(cv->dirty_xmin < 0)
  87. cv->dirty_xmin = 0;
  88. if(cv->dirty_xmax > cv->width - 1)
  89. cv->dirty_xmax = cv->width - 1;
  90. if(cv->dirty_ymin < 0)
  91. cv->dirty_ymin = 0;
  92. if(cv->dirty_ymax > cv->height - 1)
  93. cv->dirty_ymax = cv->height - 1;
  94. *xmin = cv->dirty_xmin;
  95. *xmax = cv->dirty_xmax;
  96. *ymin = cv->dirty_ymin;
  97. *ymax = cv->dirty_ymax;
  98. return 0;
  99. }
  100. /** \brief Add an area to the canvas's dirty rectangle list.
  101. *
  102. * Add an invalidating zone to the canvas's dirty rectangle list. For more
  103. * information about the dirty rectangles, see caca_get_dirty_rectangle().
  104. *
  105. * This function may be useful to force refresh of a given zone of the
  106. * canvas even if the dirty rectangle tracking indicates that it is
  107. * unchanged. This may happen if the canvas contents were somewhat
  108. * directly modified.
  109. *
  110. * If an error occurs, -1 is returned and \b errno is set accordingly:
  111. * - \c EINVAL Specified rectangle coordinates are out of bounds.
  112. *
  113. * \param cv A libcaca canvas.
  114. * \param xmin The leftmost edge of the additional dirty rectangle.
  115. * \param ymin The topmost edge of the additional dirty rectangle.
  116. * \param xmax The rightmost edge of the additional dirty rectangle.
  117. * \param ymax The bottommost edge of the additional dirty rectangle.
  118. * \return 0 in case of success, -1 if an error occurred.
  119. */
  120. int caca_add_dirty_rectangle(caca_canvas_t *cv, int xmin, int ymin,
  121. int xmax, int ymax)
  122. {
  123. /* Ignore empty and out-of-bounds rectangles */
  124. if(xmin > xmax || ymin > ymax
  125. || xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height)
  126. {
  127. seterrno(EINVAL);
  128. return -1;
  129. }
  130. if(xmin < cv->dirty_xmin)
  131. cv->dirty_xmin = xmin;
  132. if(xmax > cv->dirty_xmax)
  133. cv->dirty_xmax = xmax;
  134. if(ymin < cv->dirty_ymin)
  135. cv->dirty_ymin = ymin;
  136. if(ymax > cv->dirty_ymax)
  137. cv->dirty_ymax = ymax;
  138. return 0;
  139. }
  140. /** \brief Remove an area from the dirty rectangle list.
  141. *
  142. * Mark a cell area in the canvas as not dirty. For more information about
  143. * the dirty rectangles, see caca_get_dirty_rectangle().
  144. *
  145. * Values such that \b xmin > \b xmax or \b ymin > \b ymax indicate that
  146. * the dirty rectangle is empty. They will be silently ignored.
  147. *
  148. * If an error occurs, -1 is returned and \b errno is set accordingly:
  149. * - \c EINVAL Specified rectangle coordinates are out of bounds.
  150. *
  151. * \param cv A libcaca canvas.
  152. * \param xmin The leftmost edge of the clean rectangle.
  153. * \param ymin The topmost edge of the clean rectangle.
  154. * \param xmax The rightmost edge of the clean rectangle.
  155. * \param ymax The bottommost edge of the clean rectangle.
  156. * \return 0 in case of success, -1 if an error occurred.
  157. */
  158. int caca_remove_dirty_rectangle(caca_canvas_t *cv, int xmin, int ymin,
  159. int xmax, int ymax)
  160. {
  161. /* Ignore empty and out-of-bounds rectangles */
  162. if(xmin > xmax || ymin > ymax
  163. || xmax < 0 || xmin >= cv->width || ymax < 0 || ymin >= cv->height)
  164. {
  165. seterrno(EINVAL);
  166. return -1;
  167. }
  168. /* FIXME: implement this function. It's OK to have it do nothing,
  169. * since we take a conservative approach in dirty rectangle handling,
  170. * but we ought to help the rendering eventually. */
  171. return 0;
  172. }
  173. /** \brief Clear a canvas's dirty rectangle list.
  174. *
  175. * Empty the canvas's dirty rectangle list.
  176. *
  177. * This function never fails.
  178. *
  179. * \param cv A libcaca canvas.
  180. * \return This function always returns 0.
  181. */
  182. int caca_clear_dirty_rectangle_list(caca_canvas_t *cv)
  183. {
  184. cv->dirty_xmin = cv->width;
  185. cv->dirty_xmax = -1;
  186. cv->dirty_ymin = cv->height;
  187. cv->dirty_ymax = -1;
  188. return 0;
  189. }