nxglib_filltrapezoid.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /****************************************************************************
  2. * graphics/nxglib/fb/nxglib_filltrapezoid.c
  3. *
  4. * Copyright (C) 2008-2012, 2015 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <stdint.h>
  40. #include <fixedmath.h>
  41. #include <nuttx/video/fb.h>
  42. #include <nuttx/nx/nxglib.h>
  43. #include "nxglib_bitblit.h"
  44. /****************************************************************************
  45. * Pre-processor Definitions
  46. ****************************************************************************/
  47. /* Make sure that this file is used in the proper context */
  48. #ifndef NXGLIB_SUFFIX
  49. # error "NXGLIB_SUFFIX must be defined before including this header file"
  50. #endif
  51. /****************************************************************************
  52. * Public Functions
  53. ****************************************************************************/
  54. /****************************************************************************
  55. * Name: nxglib_filltrapezoid_*bpp
  56. *
  57. * Descripton:
  58. * Fill a trapezoidal region in the framebuffer memory with a fixed color.
  59. * Clip the trapezoid to lie within a boundng box. This is useful for
  60. * drawing complex shapes that can be broken into a set of trapezoids.
  61. *
  62. ****************************************************************************/
  63. void NXGL_FUNCNAME(nxgl_filltrapezoid, NXGLIB_SUFFIX)(
  64. FAR struct fb_planeinfo_s *pinfo,
  65. FAR const struct nxgl_trapezoid_s *trap,
  66. FAR const struct nxgl_rect_s *bounds,
  67. NXGL_PIXEL_T color)
  68. {
  69. unsigned int stride;
  70. unsigned int width;
  71. FAR uint8_t *dest;
  72. FAR uint8_t *line;
  73. int nrows;
  74. b16_t x1;
  75. b16_t x2;
  76. nxgl_coord_t y1;
  77. nxgl_coord_t y2;
  78. b16_t dx1dy;
  79. b16_t dx2dy;
  80. #if NXGLIB_BITSPERPIXEL < 8
  81. uint8_t mpixel = NXGL_MULTIPIXEL(color);
  82. uint8_t mask;
  83. int lnlen;
  84. #endif
  85. /* Get the width of the framebuffer in bytes */
  86. stride = pinfo->stride;
  87. /* Get the top run position and the number of rows to draw */
  88. x1 = trap->top.x1;
  89. x2 = trap->top.x2;
  90. /* Calculate the number of rows to render */
  91. y1 = trap->top.y;
  92. y2 = trap->bot.y;
  93. nrows = y2 - y1 + 1;
  94. /* Calculate the slope of the left and right side of the trapezoid */
  95. if (nrows > 1)
  96. {
  97. dx1dy = b16divi((trap->bot.x1 - x1), nrows - 1);
  98. dx2dy = b16divi((trap->bot.x2 - x2), nrows - 1);
  99. }
  100. else
  101. {
  102. /* The trapezoid is a run! Use the average width. */
  103. x1 = (x1 + trap->bot.x1) >> 1;
  104. x2 = (x2 + trap->bot.x2) >> 1;
  105. dx1dy = 0;
  106. dx2dy = 0;
  107. }
  108. /* Perform vertical clipping */
  109. if (y1 < bounds->pt1.y)
  110. {
  111. /* Is the entire trapezoid "above" the clipping window? */
  112. if (y2 < bounds->pt1.y)
  113. {
  114. /* Yes.. then do nothing */
  115. return;
  116. }
  117. /* Calculate the x values for the new top run */
  118. int dy = bounds->pt1.y - y1;
  119. x1 += dy * dx1dy;
  120. x2 += dy * dx2dy;
  121. /* Clip and re-calculate the number of rows to render */
  122. y1 = bounds->pt1.y;
  123. nrows = y2 - y1 + 1;
  124. }
  125. if (y2 > bounds->pt2.y)
  126. {
  127. /* Is the entire trapezoid "below" the clipping window? */
  128. if (y1 > bounds->pt2.y)
  129. {
  130. /* Yes.. then do nothing */
  131. return;
  132. }
  133. /* Clip and re-calculate the number of rows to render */
  134. y2 = bounds->pt2.y;
  135. nrows = y2 - y1 + 1;
  136. }
  137. /* Get the address of the first byte on the first line */
  138. line = pinfo->fbmem + y1 * stride ;
  139. /* Then fill the trapezoid line-by-line */
  140. while (nrows--)
  141. {
  142. #ifdef CONFIG_NX_ANTIALIASING
  143. b16_t frac;
  144. #endif
  145. int ix1;
  146. int ix2;
  147. /* Handle the special case where the sides cross (as in an hourglass) */
  148. if (x1 > x2)
  149. {
  150. b16_t tmp;
  151. ngl_swap(x1, x2, tmp);
  152. ngl_swap(dx1dy, dx2dy, tmp);
  153. }
  154. /* Convert the positions to integer */
  155. ix1 = b16toi(x1);
  156. ix2 = b16toi(x2);
  157. /* Handle some corner cases where we draw nothing. Otherwise, we will
  158. * always draw at least one pixel.
  159. */
  160. if (x1 <= x2 && ix2 >= bounds->pt1.x && ix1 <= bounds->pt2.x)
  161. {
  162. /* Get a clipped copies of the starting and ending X positions. This
  163. * clipped truncates "down" and gives the quantized pixel holding the
  164. * fractional X position
  165. */
  166. ix1 = ngl_clipl(ix1, bounds->pt1.x);
  167. ix2 = ngl_clipr(ix2, bounds->pt2.x);
  168. /* Get the run length for the clipped row */
  169. width = ix2 - ix1 + 1;
  170. #if NXGLIB_BITSPERPIXEL < 8
  171. /* Handle masking of the fractional initial byte */
  172. #ifdef CONFIG_NX_PACKEDMSFIRST
  173. mask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix1)));
  174. #else
  175. mask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix1)));
  176. #endif
  177. dest = line;
  178. lnlen = width;
  179. if (lnlen > 1 && mask)
  180. {
  181. dest[0] = (dest[0] & ~mask) | (mpixel & mask);
  182. mask = 0xff;
  183. dest++;
  184. lnlen--;
  185. }
  186. /* Handle masking of the fractional final byte */
  187. #ifdef CONFIG_NX_PACKEDMSFIRST
  188. mask &= (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix2)));
  189. #else
  190. mask &= (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix2)));
  191. #endif
  192. if (lnlen > 0 && mask)
  193. {
  194. dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask);
  195. lnlen--;
  196. }
  197. /* Handle all of the unmasked bytes in-between */
  198. if (lnlen > 0)
  199. {
  200. NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen);
  201. }
  202. #else /* NXGLIB_BITSPERPIXEL < 8 */
  203. /* Then draw the run from (line + ix1) to (line + ix2) */
  204. dest = line + NXGL_SCALEX(ix1);
  205. #ifdef CONFIG_NX_ANTIALIASING
  206. /* Perform blending on the first pixel of the row */
  207. frac = b16ONE - b16frac(x1);
  208. NXGL_BLEND(dest, (NXGL_PIXEL_T)color, frac);
  209. dest += NXGL_SCALEX(1);
  210. width--;
  211. if (width > 0)
  212. {
  213. /* Copy pixels between the first and last pixel of the row. */
  214. if (width > 1)
  215. {
  216. NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width-1);
  217. }
  218. /* And blend the final pixel */
  219. dest += NXGL_SCALEX(width-1);
  220. frac = b16frac(x2);
  221. NXGL_BLEND(dest, (NXGL_PIXEL_T)color, frac);
  222. }
  223. #else /* CONFIG_NX_ANTIALIASING */
  224. NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width);
  225. #endif /* CONFIG_NX_ANTIALIASING */
  226. #endif /* NXGLIB_BITSPERPIXEL < 8 */
  227. }
  228. /* Move to the start of the next line */
  229. line += stride;
  230. /* Add the dx/dy value to get the run positions on the next row */
  231. x1 += dx1dy;
  232. x2 += dx2dy;
  233. }
  234. }