gxdtfill.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /* Copyright (C) 2002 artofcode LLC. All rights reserved.
  2. This software is provided AS-IS with no warranty, either express or
  3. implied.
  4. This software is distributed under license and may not be copied,
  5. modified or distributed except as expressly authorized under the terms
  6. of the license contained in the file LICENSE in this distribution.
  7. For more information about licensing, please refer to
  8. http://www.ghostscript.com/licensing/. For information on
  9. commercial licensing, go to http://www.artifex.com/licensing/ or
  10. contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  12. */
  13. /* $Id: gxdtfill.h,v 1.27 2004/08/05 17:02:36 stefan Exp $ */
  14. /* Configurable algorithm for filling a trapezoid */
  15. /*
  16. * Since we need several statically defined variants of this agorithm,
  17. * we store it in .h file and include several times into gdevddrw.c and
  18. * into gxfill.h . Configuration flags (macros) are :
  19. *
  20. * GX_FILL_TRAPEZOID - a name of method
  21. * CONTIGUOUS_FILL - prevent dropouts in narrow trapezoids
  22. * SWAP_AXES - assume swapped axes
  23. * FILL_DIRECT - See LOOP_FILL_RECTANGLE_DIRECT.
  24. * LINEAR_COLOR - Fill with a linear color.
  25. * EDGE_TYPE - a type of edge structure.
  26. * FILL_ATTRS - operation attributes.
  27. */
  28. /*
  29. * Fill a trapezoid. left.start => left.end and right.start => right.end
  30. * define the sides; ybot and ytop define the top and bottom. Requires:
  31. * {left,right}->start.y <= ybot <= ytop <= {left,right}->end.y.
  32. * Lines where left.x >= right.x will not be drawn. Thanks to Paul Haeberli
  33. * for an early floating point version of this algorithm.
  34. */
  35. /*
  36. * With CONTIGUOUS_FILL is off,
  37. * this algorithm paints pixels, which centers fall between
  38. * the left and the right side of the trapezoid, excluding the
  39. * right side (see PLRM3, 7.5. Scan conversion details).
  40. * Particularly 0-width trapezoids are not painted.
  41. *
  42. * Similarly, it paints pixels, which centers
  43. * fall between ybot and ytop, excluding ytop.
  44. * Particularly 0-height trapezoids are not painted.
  45. *
  46. * With CONTIGUOUS_FILL is on, it paints a contigous area,
  47. * adding a minimal number of pixels outside the trapezoid.
  48. * Particularly it may paint pixels on the right and on the top sides,
  49. * if they are necessary for the contiguity.
  50. *
  51. * With LINEAR_COLOR returns 1 if the gradient arithmetics overflows..
  52. */
  53. /*
  54. We must paint pixels with index i such that
  55. Xl <= i + 0.5 < Xr
  56. The condition is is equivalent to
  57. Xl - 0.5 <= i < Xr - 0.5
  58. which is equivalent to
  59. (is_integer(Xl - 0.5) ? Xl - 0.5 : ceil(Xl - 0.5)) <= i <
  60. (is_integer(Xr - 0.5) ? Xr - 0.5 : floor(Xr - 0.5) + 1)
  61. (the last '+1" happens due to the strong comparizon '<')
  62. which is equivalent to
  63. ceil(Xl - 0.5) <= i < ceil(Xr - 0.5)
  64. trap_line represents the intersection coordinate as a rational value :
  65. Xl = xl + e - fl
  66. Xr = xr + e - fr
  67. Where 'e' is 'fixed_epsilon', 0.5 is 'fixed_half', and fl == l.fx / l.h, fr == - r.fx / r.h,
  68. e <= fl < 0, e <= fr < 0.
  69. Let
  70. xl' := xl + 0.5
  71. xr' := xr + 0.5
  72. Then
  73. xl = xl' - 0.5
  74. xr = xr' - 0.5
  75. Xl = xl' - 0.5 + e - fl
  76. Xr = xr' - 0.5 + e - fr
  77. ceil(xl' - 0.5 + e - fl - 0.5) <= i < ceil(xr' - 0.5 + e - fr - 0.5)
  78. which is equivalent to
  79. ceil(xl' + e - fl) - 1 <= i < ceil(xr' + e - fr) - 1
  80. which is equivalent to
  81. (is_integer(xl' + e - fl) ? xl' + e - fl - 1 : ceil(xl' + e - fl) - 1) <= i <
  82. (is_integer(xr' + e - fr) ? xr' + e - fr - 1 : ceil(xr' + e - fr) - 1)
  83. which is equivalent to
  84. (is_integer(xl' + e - fl) ? xl' + e - fl - 1 : floor(xl' + e - fl)) <= i <
  85. (is_integer(xr' + e - fr) ? xr' + e - fr - 1 : floor(xr' + e - fr))
  86. which is equivalent to
  87. (is_integer(xl') && e == fl ? xl' - 1 : floor(xl' + e - fl)) <= i <
  88. (is_integer(xr') && e == fr ? xr' - 1 : floor(xr' + e - fr))
  89. Note that e != fl ==> floor(xl' + e - fl) == floor(xl') due to e - fl < LeastSignificantBit(xl') ;
  90. e == fl ==> floor(xl' + e - fl) == floor(xl') due to e - fl == 0;
  91. thus the condition is is equivalent to
  92. (is_integer(xl') && e == fl ? xl' - 1 : floor(xl')) <= i <
  93. (is_integer(xr') && e == fr ? xr' - 1 : floor(xr'))
  94. It is computed with the macro 'rational_floor'.
  95. */
  96. GX_FILL_TRAPEZOID (gx_device * dev, const EDGE_TYPE * left,
  97. const EDGE_TYPE * right, fixed ybot, fixed ytop, int flags,
  98. const gx_device_color * pdevc, FILL_ATTRS fa)
  99. {
  100. const fixed ymin = fixed_pixround(ybot) + fixed_half;
  101. const fixed ymax = fixed_pixround(ytop);
  102. if (ymin >= ymax)
  103. return 0; /* no scan lines to sample */
  104. {
  105. int iy = fixed2int_var(ymin);
  106. const int iy1 = fixed2int_var(ymax);
  107. trap_line l, r;
  108. register int rxl, rxr;
  109. int ry;
  110. const fixed
  111. x0l = left->start.x, x1l = left->end.x, x0r = right->start.x,
  112. x1r = right->end.x, dxl = x1l - x0l, dxr = x1r - x0r;
  113. const fixed /* partial pixel offset to first line to sample */
  114. ysl = ymin - left->start.y, ysr = ymin - right->start.y;
  115. fixed fxl;
  116. int code;
  117. # if CONTIGUOUS_FILL
  118. const bool peak0 = ((flags & 1) != 0);
  119. const bool peak1 = ((flags & 2) != 0);
  120. int peak_y0 = ybot + fixed_half;
  121. int peak_y1 = ytop - fixed_half;
  122. # endif
  123. # if LINEAR_COLOR
  124. int num_components = dev->color_info.num_components;
  125. frac31 lgc[GX_DEVICE_COLOR_MAX_COMPONENTS];
  126. int32_t lgf[GX_DEVICE_COLOR_MAX_COMPONENTS];
  127. int32_t lgnum[GX_DEVICE_COLOR_MAX_COMPONENTS];
  128. frac31 rgc[GX_DEVICE_COLOR_MAX_COMPONENTS];
  129. int32_t rgf[GX_DEVICE_COLOR_MAX_COMPONENTS];
  130. int32_t rgnum[GX_DEVICE_COLOR_MAX_COMPONENTS];
  131. frac31 xgc[GX_DEVICE_COLOR_MAX_COMPONENTS];
  132. int32_t xgf[GX_DEVICE_COLOR_MAX_COMPONENTS];
  133. int32_t xgnum[GX_DEVICE_COLOR_MAX_COMPONENTS];
  134. trap_gradient lg, rg, xg;
  135. # else
  136. gx_color_index cindex = pdevc->colors.pure;
  137. dev_proc_fill_rectangle((*fill_rect)) =
  138. dev_proc(dev, fill_rectangle);
  139. # endif
  140. if_debug2('z', "[z]y=[%d,%d]\n", iy, iy1);
  141. l.h = left->end.y - left->start.y;
  142. r.h = right->end.y - right->start.y;
  143. l.x = x0l + (fixed_half - fixed_epsilon);
  144. r.x = x0r + (fixed_half - fixed_epsilon);
  145. ry = iy;
  146. /*
  147. * Free variables of FILL_TRAP_RECT:
  148. * SWAP_AXES, pdevc, dev, fa
  149. * Free variables of FILL_TRAP_RECT_DIRECT:
  150. * SWAP_AXES, fill_rect, dev, cindex
  151. */
  152. #define FILL_TRAP_RECT_INDIRECT(x,y,w,h)\
  153. (SWAP_AXES ? gx_fill_rectangle_device_rop(y, x, h, w, pdevc, dev, fa) :\
  154. gx_fill_rectangle_device_rop(x, y, w, h, pdevc, dev, fa))
  155. #define FILL_TRAP_RECT_DIRECT(x,y,w,h)\
  156. (SWAP_AXES ? (*fill_rect)(dev, y, x, h, w, cindex) :\
  157. (*fill_rect)(dev, x, y, w, h, cindex))
  158. #if LINEAR_COLOR
  159. # define FILL_TRAP_RECT(x,y,w,h)\
  160. (!(w) ? 0 : dev_proc(dev, fill_linear_color_scanline)(dev, fa, x, y, w, xg.c, xg.f, xg.num, xg.den))
  161. #else
  162. # define FILL_TRAP_RECT(x,y,w,h)\
  163. (FILL_DIRECT ? FILL_TRAP_RECT_DIRECT(x,y,w,h) : FILL_TRAP_RECT_INDIRECT(x,y,w,h))
  164. #endif
  165. #define VD_RECT_SWAPPED(rxl, ry, rxr, iy)\
  166. vd_rect(int2fixed(SWAP_AXES ? ry : rxl), int2fixed(SWAP_AXES ? rxl : ry),\
  167. int2fixed(SWAP_AXES ? iy : rxr), int2fixed(SWAP_AXES ? rxr : iy),\
  168. 1, VD_RECT_COLOR);
  169. /* Compute the dx/dy ratios. */
  170. /*
  171. * Compute the x offsets at the first scan line to sample. We need
  172. * to be careful in computing ys# * dx#f {/,%} h# because the
  173. * multiplication may overflow. We know that all the quantities
  174. * involved are non-negative, and that ys# is usually less than 1 (as
  175. * a fixed, of course); this gives us a cheap conservative check for
  176. * overflow in the multiplication.
  177. */
  178. #define YMULT_QUO(ys, tl)\
  179. (ys < fixed_1 && tl.df < YMULT_LIMIT ? ys * tl.df / tl.h :\
  180. fixed_mult_quo(ys, tl.df, tl.h))
  181. #if CONTIGUOUS_FILL
  182. /*
  183. * If left and right boundary round to same pixel index,
  184. * we would not paing the scan and would get a dropout.
  185. * Check for this case and choose one of two pixels
  186. * which is closer to the "axis". We need to exclude
  187. * 'peak' because it would paint an excessive pixel.
  188. */
  189. #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) \
  190. if (ixl == ixr) \
  191. if ((!peak0 || iy >= peak_y0) && (!peak1 || iy <= peak_y1)) {\
  192. fixed x = int2fixed(ixl) + fixed_half;\
  193. if (x - l.x < r.x - x)\
  194. ++ixr;\
  195. else\
  196. --ixl;\
  197. }
  198. #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill)\
  199. if (adj1 < adj2) {\
  200. if (iy - ry > 1) {\
  201. VD_RECT_SWAPPED(rxl, ry, rxr, iy - 1);\
  202. code = fill(rxl, ry, rxr - rxl, iy - ry - 1);\
  203. if (code < 0)\
  204. goto xit;\
  205. ry = iy - 1;\
  206. }\
  207. adj1 = adj2 = (adj2 + adj2) / 2;\
  208. }
  209. #else
  210. #define SET_MINIMAL_WIDTH(ixl, ixr, l, r) DO_NOTHING
  211. #define CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, adj1, adj2, fill) DO_NOTHING
  212. #endif
  213. if (fixed_floor(l.x) == fixed_pixround(x1l)) {
  214. /* Left edge is vertical, we don't need to increment. */
  215. l.di = 0, l.df = 0;
  216. fxl = 0;
  217. } else {
  218. compute_dx(&l, dxl, ysl);
  219. fxl = YMULT_QUO(ysl, l);
  220. l.x += fxl;
  221. }
  222. if (fixed_floor(r.x) == fixed_pixround(x1r)) {
  223. /* Right edge is vertical. If both are vertical, */
  224. /* we have a rectangle. */
  225. # if !LINEAR_COLOR
  226. if (l.di == 0 && l.df == 0) {
  227. rxl = fixed2int_var(l.x);
  228. rxr = fixed2int_var(r.x);
  229. SET_MINIMAL_WIDTH(rxl, rxr, l, r);
  230. VD_RECT_SWAPPED(rxl, ry, rxr, iy1);
  231. code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy1 - ry);
  232. goto xit;
  233. }
  234. # endif
  235. r.di = 0, r.df = 0;
  236. }
  237. /*
  238. * The test for fxl != 0 is required because the right edge might
  239. * cross some pixel centers even if the left edge doesn't.
  240. */
  241. else if (dxr == dxl && fxl != 0) {
  242. if (l.di == 0)
  243. r.di = 0, r.df = l.df;
  244. else
  245. compute_dx(&r, dxr, ysr);
  246. if (ysr == ysl && r.h == l.h)
  247. r.x += fxl;
  248. else
  249. r.x += YMULT_QUO(ysr, r);
  250. } else {
  251. compute_dx(&r, dxr, ysr);
  252. r.x += YMULT_QUO(ysr, r);
  253. }
  254. /* Compute one line's worth of dx/dy. */
  255. compute_ldx(&l, ysl);
  256. compute_ldx(&r, ysr);
  257. /* We subtracted fixed_epsilon from l.x, r.x to simplify rounding
  258. when the rational part is zero. Now add it back to get xl', xr' */
  259. l.x += fixed_epsilon;
  260. r.x += fixed_epsilon;
  261. # if LINEAR_COLOR
  262. # ifdef DEBUG
  263. if (check_gradient_overflow(left, right, num_components)) {
  264. /* The caller must care of.
  265. Checking it here looses some performance with triangles. */
  266. return_error(gs_error_unregistered);
  267. }
  268. # endif
  269. lg.c = lgc;
  270. lg.f = lgf;
  271. lg.num = lgnum;
  272. rg.c = rgc;
  273. rg.f = rgf;
  274. rg.num = rgnum;
  275. xg.c = xgc;
  276. xg.f = xgf;
  277. xg.num = xgnum;
  278. init_gradient(&lg, fa, left, right, &l, ymin, num_components);
  279. init_gradient(&rg, fa, right, left, &r, ymin, num_components);
  280. # endif
  281. #define rational_floor(tl)\
  282. fixed2int_var(fixed_is_int(tl.x) && tl.xf == -tl.h ? tl.x - fixed_1 : tl.x)
  283. #define STEP_LINE(ix, tl)\
  284. tl.x += tl.ldi;\
  285. if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= tl.h, tl.x++;\
  286. ix = rational_floor(tl)
  287. rxl = rational_floor(l);
  288. rxr = rational_floor(r);
  289. SET_MINIMAL_WIDTH(rxl, rxr, l, r);
  290. while (LINEAR_COLOR ? 1 : ++iy != iy1) {
  291. # if LINEAR_COLOR
  292. if (rxl != rxr) {
  293. code = set_x_gradient(&xg, &lg, &rg, &l, &r, rxl, rxr, num_components);
  294. if (code < 0)
  295. goto xit;
  296. /*VD_RECT_SWAPPED(rxl, iy, rxr, iy + 1);*/
  297. code = FILL_TRAP_RECT(rxl, iy, rxr - rxl, 1);
  298. if (code < 0)
  299. goto xit;
  300. }
  301. if (++iy == iy1)
  302. break;
  303. STEP_LINE(rxl, l);
  304. STEP_LINE(rxr, r);
  305. step_gradient(&lg, num_components);
  306. step_gradient(&rg, num_components);
  307. # else
  308. register int ixl, ixr;
  309. STEP_LINE(ixl, l);
  310. STEP_LINE(ixr, r);
  311. SET_MINIMAL_WIDTH(ixl, ixr, l, r);
  312. if (ixl != rxl || ixr != rxr) {
  313. CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, rxr, ixl, FILL_TRAP_RECT);
  314. CONNECT_RECTANGLES(ixl, ixr, rxl, rxr, iy, ry, ixr, rxl, FILL_TRAP_RECT);
  315. VD_RECT_SWAPPED(rxl, ry, rxr, iy);
  316. code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry);
  317. if (code < 0)
  318. goto xit;
  319. rxl = ixl, rxr = ixr, ry = iy;
  320. }
  321. # endif
  322. }
  323. # if !LINEAR_COLOR
  324. VD_RECT_SWAPPED(rxl, ry, rxr, iy);
  325. code = FILL_TRAP_RECT(rxl, ry, rxr - rxl, iy - ry);
  326. # else
  327. code = 0;
  328. # endif
  329. #undef STEP_LINE
  330. #undef SET_MINIMAL_WIDTH
  331. #undef CONNECT_RECTANGLES
  332. #undef FILL_TRAP_RECT
  333. #undef FILL_TRAP_RECT_DIRECT
  334. #undef FILL_TRAP_RECT_INRECT
  335. #undef YMULT_QUO
  336. #undef VD_RECT_SWAPPED
  337. xit: if (code < 0 && FILL_DIRECT)
  338. return_error(code);
  339. return_if_interrupt(dev->memory);
  340. return code;
  341. }
  342. }
  343. #undef GX_FILL_TRAPEZOID
  344. #undef CONTIGUOUS_FILL
  345. #undef SWAP_AXES
  346. #undef FLAGS_TYPE