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.
 
 
 
 
 
 

259 lines
7.0 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. 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 a small framework for canvas frame management.
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #if !defined(__KERNEL__)
  20. # include <stdio.h>
  21. # include <stdlib.h>
  22. # include <string.h>
  23. #endif
  24. #include "cucul.h"
  25. #include "cucul_internals.h"
  26. /** \brief Get the number of frames in a canvas.
  27. *
  28. * Return the current canvas' frame count.
  29. *
  30. * This function never fails.
  31. *
  32. * \param cv A libcucul canvas
  33. * \return The frame count
  34. */
  35. unsigned int cucul_get_frame_count(cucul_canvas_t const *cv)
  36. {
  37. return cv->framecount;
  38. }
  39. /** \brief Activate a given canvas frame.
  40. *
  41. * Set the active canvas frame. All subsequent drawing operations will
  42. * be performed on that frame. The current painting context set by
  43. * cucul_set_attr() is inherited.
  44. *
  45. * If the frame index is outside the canvas' frame range, nothing happens.
  46. *
  47. * If an error occurs, -1 is returned and \b errno is set accordingly:
  48. * - \c EINVAL Requested frame is out of range.
  49. *
  50. * \param cv A libcucul canvas
  51. * \param id The canvas frame to activate
  52. * \return 0 in case of success, -1 if an error occurred.
  53. */
  54. int cucul_set_frame(cucul_canvas_t *cv, unsigned int id)
  55. {
  56. if(id >= cv->framecount)
  57. {
  58. seterrno(EINVAL);
  59. return -1;
  60. }
  61. _cucul_save_frame_info(cv);
  62. cv->frame = id;
  63. _cucul_load_frame_info(cv);
  64. return 0;
  65. }
  66. /** \brief Get the current frame's name.
  67. *
  68. * Return the current frame's name. The returned string is valid until
  69. * the frame is deleted or cucul_set_frame_name() is called to change
  70. * the frame name again.
  71. *
  72. * This function never fails.
  73. *
  74. * \param cv A libcucul canvas.
  75. * \return The current frame's name.
  76. */
  77. char const *cucul_get_frame_name(cucul_canvas_t const *cv)
  78. {
  79. return cv->frames[cv->frame].name;
  80. }
  81. /** \brief Set the current frame's name.
  82. *
  83. * Set the current frame's name. Upon creation, a frame has a default name
  84. * of \c "frame#xxxxxxxx" where \c xxxxxxxx is a self-incrementing
  85. * hexadecimal number.
  86. *
  87. * If an error occurs, -1 is returned and \b errno is set accordingly:
  88. * - \c ENOMEM Not enough memory to allocate new frame.
  89. *
  90. * \param cv A libcucul canvas.
  91. * \param name The name to give to the current frame.
  92. * \return 0 in case of success, -1 if an error occurred.
  93. */
  94. int cucul_set_frame_name(cucul_canvas_t *cv, char const *name)
  95. {
  96. char *newname = strdup(name);
  97. if(!newname)
  98. {
  99. seterrno(ENOMEM);
  100. return -1;
  101. }
  102. free(cv->frames[cv->frame].name);
  103. cv->frames[cv->frame].name = newname;
  104. return 0;
  105. }
  106. /** \brief Add a frame to a canvas.
  107. *
  108. * Create a new frame within the given canvas. Its contents and attributes
  109. * are copied from the currently active frame.
  110. *
  111. * The frame index indicates where the frame should be inserted. Valid
  112. * values range from 0 to the current canvas frame count. If the frame
  113. * index is greater than or equals the current canvas frame count, the new
  114. * frame is appended at the end of the canvas.
  115. *
  116. * The active frame does not change, but its index may be renumbered due
  117. * to the insertion.
  118. *
  119. * If an error occurs, -1 is returned and \b errno is set accordingly:
  120. * - \c ENOMEM Not enough memory to allocate new frame.
  121. *
  122. * \param cv A libcucul canvas
  123. * \param id The index where to insert the new frame
  124. * \return 0 in case of success, -1 if an error occurred.
  125. */
  126. int cucul_create_frame(cucul_canvas_t *cv, unsigned int id)
  127. {
  128. unsigned int size = cv->width * cv->height;
  129. unsigned int f;
  130. if(id > cv->framecount)
  131. id = cv->framecount;
  132. cv->framecount++;
  133. cv->frames = realloc(cv->frames,
  134. sizeof(struct cucul_frame) * cv->framecount);
  135. for(f = cv->framecount - 1; f > id; f--)
  136. cv->frames[f] = cv->frames[f - 1];
  137. if(cv->frame >= id)
  138. cv->frame++;
  139. cv->frames[id].width = cv->width;
  140. cv->frames[id].height = cv->height;
  141. cv->frames[id].chars = malloc(size * sizeof(uint32_t));
  142. memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
  143. cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
  144. memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
  145. cv->frames[id].curattr = cv->curattr;
  146. cv->frames[id].x = cv->frames[cv->frame].x;
  147. cv->frames[id].y = cv->frames[cv->frame].y;
  148. cv->frames[id].handlex = cv->frames[cv->frame].handlex;
  149. cv->frames[id].handley = cv->frames[cv->frame].handley;
  150. cv->frames[id].name = strdup("frame#--------");
  151. sprintf(cv->frames[id].name + 6, "%.08x", ++cv->autoinc);
  152. return 0;
  153. }
  154. /** \brief Remove a frame from a canvas.
  155. *
  156. * Delete a frame from a given canvas.
  157. *
  158. * The frame index indicates the frame to delete. Valid values range from
  159. * 0 to the current canvas frame count minus 1. If the frame index is
  160. * greater than or equals the current canvas frame count, the last frame
  161. * is deleted.
  162. *
  163. * If the active frame is deleted, frame 0 becomes the new active frame.
  164. * Otherwise, the active frame does not change, but its index may be
  165. * renumbered due to the deletion.
  166. *
  167. * If an error occurs, -1 is returned and \b errno is set accordingly:
  168. * - \c EINVAL Requested frame is out of range, or attempt to delete the
  169. * last frame of the canvas.
  170. *
  171. * \param cv A libcucul canvas
  172. * \param id The index of the frame to delete
  173. * \return 0 in case of success, -1 if an error occurred.
  174. */
  175. int cucul_free_frame(cucul_canvas_t *cv, unsigned int id)
  176. {
  177. unsigned int f;
  178. if(id >= cv->framecount)
  179. {
  180. seterrno(EINVAL);
  181. return -1;
  182. }
  183. if(cv->framecount == 1)
  184. {
  185. seterrno(EINVAL);
  186. return -1;
  187. }
  188. free(cv->frames[id].chars);
  189. free(cv->frames[id].attrs);
  190. free(cv->frames[id].name);
  191. for(f = id + 1; f < cv->framecount; f++)
  192. cv->frames[f - 1] = cv->frames[f];
  193. cv->framecount--;
  194. cv->frames = realloc(cv->frames,
  195. sizeof(struct cucul_frame) * cv->framecount);
  196. if(cv->frame > id)
  197. cv->frame--;
  198. else if(cv->frame == id)
  199. {
  200. cv->frame = 0;
  201. _cucul_load_frame_info(cv);
  202. }
  203. return 0;
  204. }
  205. /*
  206. * XXX: the following functions are local.
  207. */
  208. void _cucul_save_frame_info(cucul_canvas_t *cv)
  209. {
  210. cv->frames[cv->frame].width = cv->width;
  211. cv->frames[cv->frame].height = cv->height;
  212. cv->frames[cv->frame].curattr = cv->curattr;
  213. }
  214. void _cucul_load_frame_info(cucul_canvas_t *cv)
  215. {
  216. cv->width = cv->frames[cv->frame].width;
  217. cv->height = cv->frames[cv->frame].height;
  218. cv->chars = cv->frames[cv->frame].chars;
  219. cv->attrs = cv->frames[cv->frame].attrs;
  220. cv->curattr = cv->frames[cv->frame].curattr;
  221. }