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.
 
 
 
 
 
 

462 lines
12 KiB

  1. /*
  2. * libpipi Pathetic image processing interface 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. #undef __USE_MISC /* THAT sucks */
  24. #undef __USE_XOPEN /* THAT sucks, too (avoid declaring y1 in math.h) */
  25. #include <math.h>
  26. #include "pipi.h"
  27. #include "pipi_internals.h"
  28. /* math.h doesn't like y1 (sucker) */
  29. float floorf(float x);
  30. float truncf(float x);
  31. float fabsf(float x);
  32. #if !defined TEMPLATE_FILE /* This file uses the template system */
  33. static float fractf(float d) { return (d - floorf(d)); }
  34. static float fractinvf(float d) { return (1 - (d - floorf(d))); }
  35. struct line
  36. {
  37. int x1, y1;
  38. int x2, y2;
  39. void (*draw) (pipi_image_t*, struct line*);
  40. union {
  41. uint32_t color32;
  42. float colorf[3];
  43. };
  44. union {
  45. uint32_t *buf_u32;
  46. float *buf_f;
  47. };
  48. };
  49. #define TEMPLATE_FLAGS SET_FLAG_GRAY | SET_FLAG_8BIT
  50. #define TEMPLATE_FILE "paint/line.c"
  51. #include "pipi_template.h"
  52. static void clip_line(pipi_image_t*, struct line*);
  53. static uint8_t clip_bits(pipi_image_t*, int, int);
  54. int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa)
  55. {
  56. struct line s;
  57. s.x1 = x1;
  58. s.y1 = y1;
  59. s.x2 = x2;
  60. s.y2 = y2;
  61. /* No Transparency routine for u32 yet, fallback to float version */
  62. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  63. {
  64. if(!aa)
  65. {
  66. uint32_t *dstdata;
  67. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  68. s.color32 = c;
  69. s.buf_u32 = dstdata;
  70. s.draw = line_8bit;
  71. }
  72. else
  73. {
  74. float *dstdata;
  75. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  76. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  77. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  78. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  79. s.buf_f = dstdata;
  80. s.draw = aaline;
  81. }
  82. }
  83. else if(img->last_modified == PIPI_PIXELS_Y_F)
  84. {
  85. float *dstdata;
  86. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  87. s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
  88. s.buf_f = dstdata;
  89. s.draw = aa ? aaline_gray : line_gray;
  90. }
  91. else
  92. {
  93. float *dstdata;
  94. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  95. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  96. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  97. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  98. s.buf_f = dstdata;
  99. s.draw = aa ? aaline : line;
  100. }
  101. clip_line(img, &s);
  102. return 0;
  103. }
  104. int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
  105. int n, uint32_t c, int aa)
  106. {
  107. int i;
  108. for(i = 0; i < n; i++)
  109. pipi_draw_line(img, x[i], y[i], x[i + 1], y[i + 1], c, aa);
  110. return 0;
  111. }
  112. /*
  113. * XXX: The following functions are local.
  114. */
  115. /* Generic Cohen-Sutherland line clipping function. */
  116. static void clip_line(pipi_image_t *img, struct line* s)
  117. {
  118. uint8_t bits1, bits2;
  119. bits1 = clip_bits(img, s->x1, s->y1);
  120. bits2 = clip_bits(img, s->x2, s->y2);
  121. if(bits1 & bits2)
  122. return;
  123. if(bits1 == 0)
  124. {
  125. if(bits2 == 0)
  126. s->draw(img, s);
  127. else
  128. {
  129. int tmp;
  130. tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
  131. tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
  132. clip_line(img, s);
  133. }
  134. return;
  135. }
  136. if(bits1 & (1<<0))
  137. {
  138. s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
  139. s->x1 = 0;
  140. }
  141. else if(bits1 & (1<<1))
  142. {
  143. int xmax = img->w - 1;
  144. s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
  145. s->x1 = xmax;
  146. }
  147. else if(bits1 & (1<<2))
  148. {
  149. s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
  150. s->y1 = 0;
  151. }
  152. else if(bits1 & (1<<3))
  153. {
  154. int ymax = img->h - 1;
  155. s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
  156. s->y1 = ymax;
  157. }
  158. clip_line(img, s);
  159. }
  160. /* Helper function for clip_line(). */
  161. static uint8_t clip_bits(pipi_image_t *img, int x, int y)
  162. {
  163. uint8_t b = 0;
  164. if(x < 0)
  165. b |= (1<<0);
  166. else if(x >= (int)img->w)
  167. b |= (1<<1);
  168. if(y < 0)
  169. b |= (1<<2);
  170. else if(y >= (int)img->h)
  171. b |= (1<<3);
  172. return b;
  173. }
  174. #else /* XXX: the following functions use the template system */
  175. /* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
  176. #define PLOT(x, y, c) \
  177. if(FLAG_8BIT) \
  178. { \
  179. /* TODO */ \
  180. } \
  181. else \
  182. { \
  183. if(FLAG_GRAY) \
  184. { \
  185. s->buf_f[((int)(x))+((int)(y))*img->w] = \
  186. (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
  187. if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) \
  188. s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
  189. if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) \
  190. s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
  191. } \
  192. else \
  193. { \
  194. int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
  195. int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
  196. int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
  197. s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
  198. s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
  199. s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
  200. if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \
  201. if(s->buf_f[qwer] < 0.0f) s->buf_f[qwer] = 0.0f; \
  202. if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \
  203. if(s->buf_f[qweg] < 0.0f) s->buf_f[qweg] = 0.0f; \
  204. if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \
  205. if(s->buf_f[qweb] < 0.0f) s->buf_f[qweb] = 0.0f; \
  206. } \
  207. }
  208. static void T(aaline)(pipi_image_t *img, struct line* s)
  209. {
  210. float x1 = s->x1, y1 = s->y1, x2 = s->x2, y2 = s->y2;
  211. float g, xd, yd, xgap, xend, yend, xf, yf, val1, val2;
  212. int x, y, ix1, ix2, iy1, iy2;
  213. xd = x2 - x1;
  214. yd = y2 - y1;
  215. /* "Horizontal" line (X greater than Y)*/
  216. if (fabsf(xd) > fabsf(yd))
  217. {
  218. if (x1 > x2)
  219. {
  220. float tmp;
  221. tmp = x1; x1 = x2; x2 = tmp;
  222. tmp = y1; y1 = y2; y2 = tmp;
  223. xd = (x2-x1);
  224. yd = (y2-y1);
  225. }
  226. g = yd/xd;
  227. xend = truncf(x1+0.5);
  228. yend = y1 + g*(xend-x1);
  229. xgap = fractinvf(x1+0.5);
  230. ix1 = (int)xend;
  231. iy1 = (int)yend;
  232. val1 = fractinvf(yend)*xgap;
  233. val2 = fractf(yend)*xgap;
  234. PLOT(ix1, iy1, val1);
  235. PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);
  236. yf = yend+g;
  237. xend = truncf(x2+0.5);
  238. yend = y2 + g*(xend-x2);
  239. xgap = fractinvf(x2-0.5);
  240. ix2 = (int)xend;
  241. iy2 = (int)yend;
  242. val1 = fractinvf(yend)*xgap;
  243. val2 = fractf(yend)*xgap;
  244. PLOT(ix2, iy2, val1);
  245. PLOT(ix2, iy2+1<y2?iy2+1:iy2, val2);
  246. for (x = (ix1+1); x < ix2; x++)
  247. {
  248. float focus;
  249. val1 = fractinvf(yf);
  250. val2 = fractf(yf);
  251. focus = (1.0 - fabsf(val1-val2));
  252. val1 += 0.3*focus;
  253. val2 += 0.3*focus;
  254. PLOT(x, yf, val1);
  255. PLOT(x, (yf+1)<y1?(yf+1):yf, val2);
  256. yf = yf + g;
  257. }
  258. }
  259. /* "Vertical" line (Y greater than X)*/
  260. else
  261. {
  262. if (x1 > x2)
  263. {
  264. float tmp;
  265. tmp = x1; x1 = x2; x2 = tmp;
  266. tmp = y1; y1 = y2; y2 = tmp;
  267. xd = (x2-x1);
  268. yd = (y2-y1);
  269. }
  270. g = xd/yd;
  271. xend = truncf(x1+0.5);
  272. yend = y1 + g*(xend-x1);
  273. xgap = fractf(x1+0.5);
  274. ix1 = (int)xend;
  275. iy1 = (int)yend;
  276. val1 = fractinvf(yend)*xgap;
  277. val2 = fractf(yend)*xgap;
  278. PLOT(ix1, iy1, val1);
  279. PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);
  280. xf = xend + g;
  281. xend = truncf(x2+0.5);
  282. yend = y2 + g*(xend-x2);
  283. xgap = fractinvf(x2-0.5);
  284. ix2 = (int)xend;
  285. iy2 = (int)yend;
  286. val1 = fractinvf(yend)*xgap;
  287. val2 = fractf(yend)*xgap;
  288. PLOT(ix2, iy2, val1);
  289. PLOT(ix2, (iy2+1)<y2?(iy2+1):iy2, val2);
  290. for (y = (iy1+1); y < iy2; y++)
  291. {
  292. float focus;
  293. int vx = xf;
  294. val1 = fractinvf(xf);
  295. val2 = fractf(xf);
  296. focus = (1.0 - fabsf(val1-val2));
  297. val1 += 0.3*focus;
  298. val2 += 0.3*focus;
  299. PLOT(vx, y, val1);
  300. vx++;
  301. PLOT(vx, y, val2);
  302. xf = xf + g;
  303. }
  304. }
  305. }
  306. #undef PLOT
  307. /* Solid line drawing function, using Bresenham's mid-point line
  308. * scan-conversion algorithm. */
  309. static void T(line)(pipi_image_t *img, struct line* s)
  310. {
  311. int x1, y1, x2, y2;
  312. int dx, dy;
  313. int xinc, yinc;
  314. x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2;
  315. dx = abs(x2 - x1);
  316. dy = abs(y2 - y1);
  317. xinc = (x1 > x2) ? -1 : 1;
  318. yinc = (y1 > y2) ? -1 : 1;
  319. if(dx >= dy)
  320. {
  321. int dpr = dy << 1;
  322. int dpru = dpr - (dx << 1);
  323. int delta = dpr - dx;
  324. for(; dx >= 0; dx--)
  325. {
  326. if(FLAG_GRAY)
  327. {
  328. if(FLAG_8BIT)
  329. /* TODO */;
  330. else
  331. s->buf_f[x1 + y1 * img->w] = s->colorf[0];
  332. }
  333. else
  334. {
  335. if(FLAG_8BIT)
  336. s->buf_u32[x1 + y1 * img->w] = s->color32;
  337. else
  338. {
  339. s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
  340. s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
  341. s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
  342. }
  343. }
  344. if(delta > 0)
  345. {
  346. x1 += xinc;
  347. y1 += yinc;
  348. delta += dpru;
  349. }
  350. else
  351. {
  352. x1 += xinc;
  353. delta += dpr;
  354. }
  355. }
  356. }
  357. else
  358. {
  359. int dpr = dx << 1;
  360. int dpru = dpr - (dy << 1);
  361. int delta = dpr - dy;
  362. for(; dy >= 0; dy--)
  363. {
  364. if(FLAG_GRAY)
  365. {
  366. if(FLAG_8BIT)
  367. /* TODO */;
  368. else
  369. s->buf_f[x1 + y1 * img->w] = s->colorf[0];
  370. }
  371. else
  372. {
  373. if(FLAG_8BIT)
  374. s->buf_u32[x1 + y1 * img->w] = s->color32;
  375. else
  376. {
  377. s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
  378. s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
  379. s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
  380. }
  381. }
  382. if(delta > 0)
  383. {
  384. x1 += xinc;
  385. y1 += yinc;
  386. delta += dpru;
  387. }
  388. else
  389. {
  390. y1 += yinc;
  391. delta += dpr;
  392. }
  393. }
  394. }
  395. }
  396. #endif