Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

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