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.
 
 
 
 
 
 

212 lines
5.7 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. #endif
  23. #include "cucul.h"
  24. #include "cucul_internals.h"
  25. static void save_frame_info(cucul_canvas_t *);
  26. static void load_frame_info(cucul_canvas_t *);
  27. /** \brief Get the number of frames in a canvas.
  28. *
  29. * Return the current canvas' frame count.
  30. *
  31. * This function never fails.
  32. *
  33. * \param cv A libcucul canvas
  34. * \return The frame count
  35. */
  36. unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv)
  37. {
  38. return cv->framecount;
  39. }
  40. /** \brief Activate a given canvas frame.
  41. *
  42. * Set the active canvas frame. All subsequent drawing operations will
  43. * be performed on that frame. The current painting context set by
  44. * cucul_set_attr() is inherited.
  45. *
  46. * If the frame index is outside the canvas' frame range, nothing happens.
  47. *
  48. * If an error occurs, -1 is returned and \b errno is set accordingly:
  49. * - \c EINVAL Requested frame is out of range.
  50. *
  51. * \param cv A libcucul canvas
  52. * \param frame The canvas frame to activate
  53. * \return 0 in case of success, -1 if an error occurred.
  54. */
  55. int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
  56. {
  57. if(frame >= cv->framecount)
  58. {
  59. seterrno(EINVAL);
  60. return -1;
  61. }
  62. save_frame_info(cv);
  63. cv->frame = frame;
  64. load_frame_info(cv);
  65. return 0;
  66. }
  67. /** \brief Add a frame to a canvas.
  68. *
  69. * Create a new frame within the given canvas. Its contents and attributes
  70. * are copied from the currently active frame.
  71. *
  72. * The frame index indicates where the frame should be inserted. Valid
  73. * values range from 0 to the current canvas frame count. If the frame
  74. * index is greater than or equals the current canvas frame count, the new
  75. * frame is appended at the end of the canvas.
  76. *
  77. * The active frame does not change, but its index may be renumbered due
  78. * to the insertion.
  79. *
  80. * If an error occurs, -1 is returned and \b errno is set accordingly:
  81. * - \c ENOMEM Not enough memory to allocate new frame.
  82. *
  83. * \param cv A libcucul canvas
  84. * \param id The index where to insert the new frame
  85. * \return 0 in case of success, -1 if an error occurred.
  86. */
  87. int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int id)
  88. {
  89. unsigned int size = cv->width * cv->height;
  90. unsigned int f;
  91. if(id > cv->framecount)
  92. id = cv->framecount;
  93. cv->framecount++;
  94. cv->frames = realloc(cv->frames,
  95. sizeof(struct cucul_frame) * cv->framecount);
  96. for(f = cv->framecount - 1; f > id; f--)
  97. cv->frames[f] = cv->frames[f - 1];
  98. if(cv->frame >= id)
  99. cv->frame++;
  100. cv->frames[id].width = cv->width;
  101. cv->frames[id].height = cv->height;
  102. cv->frames[id].chars = malloc(size * sizeof(uint32_t));
  103. memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
  104. cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
  105. memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
  106. cv->frames[id].curattr = cv->curattr;
  107. cv->frames[id].x = cv->frames[cv->frame].x;
  108. cv->frames[id].y = cv->frames[cv->frame].y;
  109. cv->frames[id].handlex = cv->frames[cv->frame].handlex;
  110. cv->frames[id].handley = cv->frames[cv->frame].handley;
  111. return 0;
  112. }
  113. /** \brief Remove a frame from a canvas.
  114. *
  115. * Delete a frame from a given canvas.
  116. *
  117. * The frame index indicates the frame to delete. Valid values range from
  118. * 0 to the current canvas frame count minus 1. If the frame index is
  119. * greater the or equals the current canvas frame count, the last frame
  120. * is deleted.
  121. *
  122. * If the active frame is deleted, frame 0 becomes the new active frame.
  123. * Otherwise, the active frame does not change, but its index may be
  124. * renumbered due to the deletion.
  125. *
  126. * If an error occurs, -1 is returned and \b errno is set accordingly:
  127. * - \c EINVAL Requested frame is out of range, or attempt to delete the
  128. * last frame of the canvas.
  129. *
  130. * \param cv A libcucul canvas
  131. * \param id The index of the frame to delete
  132. * \return 0 in case of success, -1 if an error occurred.
  133. */
  134. int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int id)
  135. {
  136. unsigned int f;
  137. if(id >= cv->framecount)
  138. {
  139. seterrno(EINVAL);
  140. return -1;
  141. }
  142. if(cv->framecount == 1)
  143. {
  144. seterrno(EINVAL);
  145. return -1;
  146. }
  147. free(cv->frames[id].chars);
  148. free(cv->frames[id].attrs);
  149. for(f = id + 1; f < cv->framecount; f++)
  150. cv->frames[f - 1] = cv->frames[f];
  151. cv->framecount--;
  152. cv->frames = realloc(cv->frames,
  153. sizeof(struct cucul_frame) * cv->framecount);
  154. if(cv->frame > id)
  155. cv->frame--;
  156. else if(cv->frame == id)
  157. {
  158. cv->frame = 0;
  159. load_frame_info(cv);
  160. }
  161. return 0;
  162. }
  163. /*
  164. * XXX: the following functions are local.
  165. */
  166. static void save_frame_info(cucul_canvas_t *cv)
  167. {
  168. cv->frames[cv->frame].width = cv->width;
  169. cv->frames[cv->frame].height = cv->height;
  170. cv->frames[cv->frame].curattr = cv->curattr;
  171. }
  172. static void load_frame_info(cucul_canvas_t *cv)
  173. {
  174. cv->width = cv->frames[cv->frame].width;
  175. cv->height = cv->frames[cv->frame].height;
  176. cv->chars = cv->frames[cv->frame].chars;
  177. cv->attrs = cv->frames[cv->frame].attrs;
  178. cv->curattr = cv->frames[cv->frame].curattr;
  179. }