renderedge.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. *
  3. * Copyright © 2004 Keith Packard
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and its
  6. * documentation for any purpose is hereby granted without fee, provided that
  7. * the above copyright notice appear in all copies and that both that
  8. * copyright notice and this permission notice appear in supporting
  9. * documentation, and that the name of Keith Packard not be used in
  10. * advertising or publicity pertaining to distribution of the software without
  11. * specific, written prior permission. Keith Packard makes no
  12. * representations about the suitability of this software for any purpose. It
  13. * is provided "as is" without express or implied warranty.
  14. *
  15. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21. * PERFORMANCE OF THIS SOFTWARE.
  22. */
  23. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. #include "renderedge.h"
  27. /*
  28. * Compute the smallest value no less than y which is on a
  29. * grid row
  30. */
  31. _X_EXPORT xFixed
  32. RenderSampleCeilY(xFixed y, int n)
  33. {
  34. xFixed f = xFixedFrac(y);
  35. xFixed i = xFixedFloor(y);
  36. f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) +
  37. Y_FRAC_FIRST(n);
  38. if (f > Y_FRAC_LAST(n)) {
  39. f = Y_FRAC_FIRST(n);
  40. i += xFixed1;
  41. }
  42. return (i | f);
  43. }
  44. #define _div(a,b) ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
  45. /*
  46. * Compute the largest value no greater than y which is on a
  47. * grid row
  48. */
  49. _X_EXPORT xFixed
  50. RenderSampleFloorY(xFixed y, int n)
  51. {
  52. xFixed f = xFixedFrac(y);
  53. xFixed i = xFixedFloor(y);
  54. f = _div(f - Y_FRAC_FIRST(n),
  55. STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
  56. if (f < Y_FRAC_FIRST(n)) {
  57. f = Y_FRAC_LAST(n);
  58. i -= xFixed1;
  59. }
  60. return (i | f);
  61. }
  62. /*
  63. * Step an edge by any amount (including negative values)
  64. */
  65. _X_EXPORT void
  66. RenderEdgeStep(RenderEdge * e, int n)
  67. {
  68. xFixed_48_16 ne;
  69. e->x += n * e->stepx;
  70. ne = e->e + n * (xFixed_48_16) e->dx;
  71. if (n >= 0) {
  72. if (ne > 0) {
  73. int nx = (ne + e->dy - 1) / e->dy;
  74. e->e = ne - nx * (xFixed_48_16) e->dy;
  75. e->x += nx * e->signdx;
  76. }
  77. }
  78. else {
  79. if (ne <= -e->dy) {
  80. int nx = (-ne) / e->dy;
  81. e->e = ne + nx * (xFixed_48_16) e->dy;
  82. e->x -= nx * e->signdx;
  83. }
  84. }
  85. }
  86. /*
  87. * A private routine to initialize the multi-step
  88. * elements of an edge structure
  89. */
  90. static void
  91. _RenderEdgeMultiInit(RenderEdge * e, int n, xFixed * stepx_p, xFixed * dx_p)
  92. {
  93. xFixed stepx;
  94. xFixed_48_16 ne;
  95. ne = n * (xFixed_48_16) e->dx;
  96. stepx = n * e->stepx;
  97. if (ne > 0) {
  98. int nx = ne / e->dy;
  99. ne -= nx * e->dy;
  100. stepx += nx * e->signdx;
  101. }
  102. *dx_p = ne;
  103. *stepx_p = stepx;
  104. }
  105. /*
  106. * Initialize one edge structure given the line endpoints and a
  107. * starting y value
  108. */
  109. _X_EXPORT void
  110. RenderEdgeInit(RenderEdge * e,
  111. int n,
  112. xFixed y_start,
  113. xFixed x_top, xFixed y_top, xFixed x_bot, xFixed y_bot)
  114. {
  115. xFixed dx, dy;
  116. e->x = x_top;
  117. e->e = 0;
  118. dx = x_bot - x_top;
  119. dy = y_bot - y_top;
  120. e->dy = dy;
  121. if (dy) {
  122. if (dx >= 0) {
  123. e->signdx = 1;
  124. e->stepx = dx / dy;
  125. e->dx = dx % dy;
  126. e->e = -dy;
  127. }
  128. else {
  129. e->signdx = -1;
  130. e->stepx = -(-dx / dy);
  131. e->dx = -dx % dy;
  132. e->e = 0;
  133. }
  134. _RenderEdgeMultiInit(e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
  135. _RenderEdgeMultiInit(e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
  136. }
  137. RenderEdgeStep(e, y_start - y_top);
  138. }
  139. /*
  140. * Initialize one edge structure given a line, starting y value
  141. * and a pixel offset for the line
  142. */
  143. _X_EXPORT void
  144. RenderLineFixedEdgeInit(RenderEdge * e,
  145. int n,
  146. xFixed y, xLineFixed * line, int x_off, int y_off)
  147. {
  148. xFixed x_off_fixed = IntToxFixed(x_off);
  149. xFixed y_off_fixed = IntToxFixed(y_off);
  150. xPointFixed *top, *bot;
  151. if (line->p1.y <= line->p2.y) {
  152. top = &line->p1;
  153. bot = &line->p2;
  154. }
  155. else {
  156. top = &line->p2;
  157. bot = &line->p1;
  158. }
  159. RenderEdgeInit(e, n, y,
  160. top->x + x_off_fixed,
  161. top->y + y_off_fixed,
  162. bot->x + x_off_fixed, bot->y + y_off_fixed);
  163. }