Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * libpipi Proper image processing implementation library
  3. * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
  4. * 2008 Jean-Yves Lamoureux <jylam@lnxscene.org
  5. * All Rights Reserved
  6. *
  7. * $Id$
  8. *
  9. * This library is free software. It comes without any warranty, to
  10. * the extent permitted by applicable law. You can redistribute it
  11. * and/or modify it under the terms of the Do What The Fuck You Want
  12. * To Public License, Version 2, as published by Sam Hocevar. See
  13. * http://sam.zoy.org/wtfpl/COPYING for more details.
  14. */
  15. /*
  16. * line.c: line rendering functions
  17. */
  18. #include "config.h"
  19. #include "common.h"
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. struct line
  26. {
  27. int x1, y1;
  28. int x2, y2;
  29. void (*draw) (pipi_image_t*, struct line*);
  30. union {
  31. uint32_t color32;
  32. float colorf[3];
  33. };
  34. union {
  35. uint32_t *buf_u32;
  36. float *buf_f;
  37. };
  38. };
  39. static void clip_line(pipi_image_t*, struct line*);
  40. static uint8_t clip_bits(pipi_image_t*, int, int);
  41. static void draw_aliased_line_u32(pipi_image_t*, struct line*);
  42. static void draw_aliased_line_gray(pipi_image_t *img, struct line* s);
  43. static void draw_aliased_line_float(pipi_image_t *img, struct line* s);
  44. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s);
  45. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s);
  46. int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa)
  47. {
  48. struct line s;
  49. s.x1 = x1;
  50. s.y1 = y1;
  51. s.x2 = x2;
  52. s.y2 = y2;
  53. /* No Transparency routine for u32 yet, fallback to float version */
  54. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  55. {
  56. if(!aa)
  57. {
  58. uint32_t *dstdata;
  59. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  60. s.color32 = c;
  61. s.buf_u32 = dstdata;
  62. s.draw = draw_aliased_line_u32;
  63. }
  64. else
  65. {
  66. float *dstdata;
  67. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  68. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  69. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  70. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  71. s.buf_f = dstdata;
  72. s.draw = draw_antialiased_line_float;
  73. }
  74. }
  75. else if(img->last_modified == PIPI_PIXELS_Y_F)
  76. {
  77. float *dstdata;
  78. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  79. s.colorf[0] = c/255.0f; /* XXX FIXME */
  80. s.buf_f = dstdata;
  81. s.draw = aa==0?draw_aliased_line_gray:draw_antialiased_line_gray;
  82. }
  83. else
  84. {
  85. float *dstdata;
  86. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  87. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  88. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  89. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  90. s.buf_f = dstdata;
  91. s.draw = aa==0?draw_aliased_line_float:draw_antialiased_line_float;
  92. }
  93. clip_line(img, &s);
  94. return 0;
  95. }
  96. int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
  97. int n, uint32_t c, int aa)
  98. {
  99. int i;
  100. struct line s;
  101. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  102. {
  103. if(!aa)
  104. {
  105. uint32_t *dstdata;
  106. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  107. s.color32 = c;
  108. s.buf_u32 = dstdata;
  109. s.draw = draw_aliased_line_u32;
  110. }
  111. else
  112. {
  113. float *dstdata;
  114. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  115. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  116. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  117. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  118. s.buf_f = dstdata;
  119. s.draw = draw_antialiased_line_float;
  120. }
  121. }
  122. else if(img->last_modified == PIPI_PIXELS_Y_F)
  123. {
  124. float *dstdata;
  125. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  126. s.colorf[0] = c/255.0f; /* XXX FIXME */
  127. s.buf_f = dstdata;
  128. s.draw = aa==0?draw_aliased_line_gray:draw_antialiased_line_gray;
  129. }
  130. else
  131. {
  132. float *dstdata;
  133. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  134. s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */
  135. s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */
  136. s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  137. s.buf_f = dstdata;
  138. s.draw = aa==0?draw_aliased_line_float:draw_antialiased_line_float;
  139. img->last_modified = PIPI_PIXELS_RGBA_F;
  140. }
  141. for(i = 0; i < n; i++)
  142. {
  143. s.x1 = x[i];
  144. s.y1 = y[i];
  145. s.x2 = x[i+1];
  146. s.y2 = y[i+1];
  147. clip_line(img, &s);
  148. }
  149. return 0;
  150. }
  151. /*
  152. * XXX: The following functions are local.
  153. */
  154. /* Generic Cohen-Sutherland line clipping function. */
  155. static void clip_line(pipi_image_t *img, struct line* s)
  156. {
  157. uint8_t bits1, bits2;
  158. bits1 = clip_bits(img, s->x1, s->y1);
  159. bits2 = clip_bits(img, s->x2, s->y2);
  160. if(bits1 & bits2)
  161. return;
  162. if(bits1 == 0)
  163. {
  164. if(bits2 == 0)
  165. s->draw(img, s);
  166. else
  167. {
  168. int tmp;
  169. tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
  170. tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
  171. clip_line(img, s);
  172. }
  173. return;
  174. }
  175. if(bits1 & (1<<0))
  176. {
  177. s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
  178. s->x1 = 0;
  179. }
  180. else if(bits1 & (1<<1))
  181. {
  182. int xmax = img->w - 1;
  183. s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
  184. s->x1 = xmax;
  185. }
  186. else if(bits1 & (1<<2))
  187. {
  188. s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
  189. s->y1 = 0;
  190. }
  191. else if(bits1 & (1<<3))
  192. {
  193. int ymax = img->h - 1;
  194. s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
  195. s->y1 = ymax;
  196. }
  197. clip_line(img, s);
  198. }
  199. /* Helper function for clip_line(). */
  200. static uint8_t clip_bits(pipi_image_t *img, int x, int y)
  201. {
  202. uint8_t b = 0;
  203. if(x < 0)
  204. b |= (1<<0);
  205. else if(x >= (int)img->w)
  206. b |= (1<<1);
  207. if(y < 0)
  208. b |= (1<<2);
  209. else if(y >= (int)img->h)
  210. b |= (1<<3);
  211. return b;
  212. }
  213. /* Solid line drawing function, using Bresenham's mid-point line
  214. * scan-conversion algorithm. */
  215. static void draw_aliased_line_u32(pipi_image_t *img, struct line* s)
  216. {
  217. #undef ASSIGN
  218. #define ASSIGN(x, y, w) s->buf_u32[x+y*w] = s->color32;
  219. #include "line_template.h"
  220. }
  221. static void draw_aliased_line_float(pipi_image_t *img, struct line* s)
  222. {
  223. #undef ASSIGN
  224. #define ASSIGN(x, y, w) s->buf_f[(x*4)+y*(w*4)] = s->colorf[0]; \
  225. s->buf_f[1 + (x*4)+y*(w*4)] = s->colorf[1]; \
  226. s->buf_f[2 + (x*4)+y*(w*4)] = s->colorf[2];
  227. #include "line_template.h"
  228. }
  229. static void draw_aliased_line_gray(pipi_image_t *img, struct line* s)
  230. {
  231. #undef ASSIGN
  232. #define ASSIGN(x, y, w) s->buf_f[x+y*w] = s->colorf[0];
  233. #include "line_template.h"
  234. }
  235. /* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
  236. /* math.h doesn't like y0 (sucker) */
  237. float floorf(float x);
  238. float truncf(float x);
  239. float fabsf(float x);
  240. static float fractf(float d) { return (d - floorf(d)); }
  241. static float fractinvf(float d) { return (1 - (d - floorf(d))); }
  242. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s)
  243. {
  244. /* Is that an horrible mess ? Yes, it is. */
  245. #undef PLOT
  246. #define PLOT(x, y, c) \
  247. s->buf_f[(((int)(x)*4))+((int)(y))*(img->w*4)] = \
  248. (c*s->colorf[0]) + (1-c) * s->buf_f[(((int)(x)*4))+((int)(y))*(img->w*4)]; \
  249. s->buf_f[(1+((int)(x)*4))+((int)(y))*(img->w*4)] = \
  250. (c*s->colorf[1]) + (1-c) * s->buf_f[(1+((int)(x)*4))+((int)(y))*(img->w*4)]; \
  251. s->buf_f[(2+((int)(x)*4))+((int)(y))*(img->w*4)] = \
  252. (c*s->colorf[2]) + (1-c) * s->buf_f[(2+((int)(x)*4))+((int)(y))*(img->w*4)];
  253. #include "aline_template.h"
  254. }
  255. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s)
  256. {
  257. #undef PLOT
  258. #define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] = \
  259. (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w];
  260. #include "aline_template.h"
  261. }