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.
 
 
 
 
 
 

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