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.
 
 
 
 
 
 

200 rivejä
5.5 KiB

  1. /*
  2. * libcucul Canvas for ultrafast compositing of Unicode letters
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains a small framework for canvas frame management.
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if !defined(__KERNEL__)
  19. # include <stdio.h>
  20. # include <stdlib.h>
  21. # include <string.h>
  22. # if defined(HAVE_ERRNO_H)
  23. # include <errno.h>
  24. # endif
  25. #endif
  26. #include "cucul.h"
  27. #include "cucul_internals.h"
  28. /** \brief Get the number of frames in a canvas.
  29. *
  30. * This function returns the current canvas frame count.
  31. *
  32. * This function never fails.
  33. *
  34. * \param cv A libcucul canvas
  35. * \return The frame count
  36. */
  37. unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv)
  38. {
  39. return cv->framecount;
  40. }
  41. /** \brief Activate a given canvas frame.
  42. *
  43. * This function sets the active canvas frame. All subsequent drawing
  44. * operations will be performed on that frame. The current painting
  45. * context set by cucul_set_color() or cucul_set_truecolor() is inherited.
  46. *
  47. * If the frame index is outside the canvas' frame range, nothing happens.
  48. *
  49. * If an error occurs, -1 is returned and \b errno is set accordingly:
  50. * - \c EINVAL Requested frame is out of range.
  51. *
  52. * \param cv A libcucul canvas
  53. * \param frame The canvas frame to activate
  54. * \return 0 in case of success, -1 if an error occurred.
  55. */
  56. int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
  57. {
  58. if(frame >= cv->framecount)
  59. {
  60. #if defined(HAVE_ERRNO_H)
  61. errno = EINVAL;
  62. #endif
  63. return -1;
  64. }
  65. cv->frame = frame;
  66. cv->chars = cv->allchars[cv->frame];
  67. cv->attr = cv->allattr[cv->frame];
  68. return 0;
  69. }
  70. /** \brief Add a frame to a canvas.
  71. *
  72. * This function creates a new frame within the given canvas. Its contents
  73. * are copied from the currently active frame.
  74. *
  75. * The frame index indicates where the frame should be inserted. Valid
  76. * values range from 0 to the current canvas frame count. If the frame
  77. * index is greater the or equals the current canvas frame count, the new
  78. * frame is appended at the end of the canvas.
  79. *
  80. * The active frame does not change, but its index may be renumbered due
  81. * to the insertion.
  82. *
  83. * If an error occurs, -1 is returned and \b errno is set accordingly:
  84. * - \c ENOMEM Not enough memory to allocate new frame.
  85. *
  86. * \param cv A libcucul canvas
  87. * \param frame The index where to insert the new frame
  88. * \return 0 in case of success, -1 if an error occurred.
  89. */
  90. int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
  91. {
  92. unsigned int size = cv->width * cv->height * sizeof(uint32_t);
  93. unsigned int f;
  94. if(frame > cv->framecount)
  95. frame = cv->framecount;
  96. cv->framecount++;
  97. cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
  98. cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
  99. for(f = cv->framecount - 1; f > frame; f--)
  100. {
  101. cv->allchars[f] = cv->allchars[f - 1];
  102. cv->allattr[f] = cv->allattr[f - 1];
  103. }
  104. cv->allchars[frame] = malloc(size);
  105. memcpy(cv->allchars[frame], cv->chars, size);
  106. cv->allattr[frame] = malloc(size);
  107. memcpy(cv->allattr[frame], cv->attr, size);
  108. if(cv->frame >= frame)
  109. cv->frame++;
  110. cv->chars = cv->allchars[cv->frame];
  111. cv->attr = cv->allattr[cv->frame];
  112. return 0;
  113. }
  114. /** \brief Remove a frame from a canvas.
  115. *
  116. * This function deletes a frame from a given canvas.
  117. *
  118. * It is not legal to remove the last frame from a canvas. Such a request
  119. * will be ignored by cucul_free_canvas_frame().
  120. *
  121. * The frame index indicates the frame to delete. Valid values range from
  122. * 0 to the current canvas frame count minus 1. If the frame index is
  123. * greater the or equals the current canvas frame count, the last frame
  124. * is deleted.
  125. *
  126. * If the active frame is deleted, frame 0 becomes the new active frame.
  127. * Otherwise, the active frame does not change, but its index may be
  128. * renumbered due to the deletion.
  129. *
  130. * If an error occurs, -1 is returned and \b errno is set accordingly:
  131. * - \c EINVAL Requested frame is out of range, or attempt to delete the
  132. * last frame of the canvas.
  133. *
  134. * \param cv A libcucul canvas
  135. * \param frame The index of the frame to delete
  136. * \return 0 in case of success, -1 if an error occurred.
  137. */
  138. int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
  139. {
  140. unsigned int f;
  141. if(frame >= cv->framecount)
  142. {
  143. #if defined(HAVE_ERRNO_H)
  144. errno = EINVAL;
  145. #endif
  146. return -1;
  147. }
  148. if(cv->framecount == 1)
  149. {
  150. #if defined(HAVE_ERRNO_H)
  151. errno = EINVAL;
  152. #endif
  153. return -1;
  154. }
  155. free(cv->allchars[frame]);
  156. free(cv->allattr[frame]);
  157. for(f = frame + 1; f < cv->framecount; f++)
  158. {
  159. cv->allchars[f - 1] = cv->allchars[f];
  160. cv->allattr[f - 1] = cv->allattr[f];
  161. }
  162. cv->framecount--;
  163. cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
  164. cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
  165. if(cv->frame > frame)
  166. cv->frame--;
  167. else if(cv->frame == frame)
  168. cv->frame = 0;
  169. cv->chars = cv->allchars[cv->frame];
  170. cv->attr = cv->allattr[cv->frame];
  171. return 0;
  172. }