Example #1
0
void NXGL_FUNCNAME(nxgl_copyrectangle, NXGLIB_SUFFIX)
(FAR struct lcd_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *dest,
 FAR const void *src, FAR const struct nxgl_point_s *origin,
 unsigned int srcstride)
{
  FAR const uint8_t *sline;
  unsigned int ncols;
  unsigned int row;
  unsigned int xoffset;
#if NXGLIB_BITSPERPIXEL < 8
  unsigned int remainder;
#endif

  /* Get the dimensions of the rectange to fill: width in pixels,
   * height in rows
   */

  ncols = dest->pt2.x - dest->pt1.x + 1;

  /* Set up to copy the image */

  xoffset = dest->pt1.x - origin->x;
  sline = (FAR const uint8_t *)src + NXGL_SCALEX(xoffset) + (dest->pt1.y - origin->y) * srcstride;
#if NXGLIB_BITSPERPIXEL < 8
  remainder = NXGL_REMAINDERX(xoffset);
#endif

  /* Copy the image, one row at a time */

  for (row = dest->pt1.y; row <= dest->pt2.y; row++)
    {
#if NXGLIB_BITSPERPIXEL < 8
      /* if the source pixel is not aligned with a byte boundary, then we will
       * need to copy the image data to the run buffer first.
       */

      if (remainder != 0)
        {
          NXGL_FUNCNAME(nxgl_copyrun, NXGLIB_SUFFIX)(sline, pinfo->buffer, remainder, ncols);
          (void)pinfo->putrun(row, dest->pt1.x, pinfo->buffer, ncols);
        }
      else
#endif
        {
          /* The pixel data is byte aligned.  Copy the image data directly from
           * the image memory.
           */

          (void)pinfo->putrun(row, dest->pt1.x, sline, ncols);
        }

      /* Then adjust the source pointer to refer to the next line in the source
       * image.
       */

      sline += srcstride;
    }
}
void NXGL_FUNCNAME(nxgl_fillrectangle,NXGLIB_SUFFIX)
  (FAR struct fb_planeinfo_s *pinfo,
   FAR const struct nxgl_rect_s *rect,
   NXGL_PIXEL_T color)
{
  FAR uint8_t *line;
  unsigned int width;
  unsigned int stride;
  int rows;

#if NXGLIB_BITSPERPIXEL < 8
  FAR uint8_t *dest;
  uint8_t mpixel = NXGL_MULTIPIXEL(color);
  uint8_t leadmask;
  uint8_t tailmask;
  uint8_t mask;
  int lnlen;
#endif

  /* Get the width of the framebuffer in bytes */

  stride = pinfo->stride;

  /* Get the dimensions of the rectange to fill in pixels */

  width  = rect->pt2.x - rect->pt1.x + 1;
  rows   = rect->pt2.y - rect->pt1.y + 1;

  /* Get the address of the first byte in the first line to write */

  line   = pinfo->fbmem + rect->pt1.y * stride + NXGL_SCALEX(rect->pt1.x);

#if NXGLIB_BITSPERPIXEL < 8
# ifdef CONFIG_NX_PACKEDMSFIRST

  /* Get the mask for pixels that are ordered so that they pack from the
   * MS byte down.
   */

  leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x)));
  tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt2.x-1)));
# else
  /* Get the mask for pixels that are ordered so that they pack from the
   * LS byte up.
   */

  leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt1.x)));
  tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x-1)));
# endif
#endif

  /* Then fill the rectangle line-by-line */

  while (rows-- > 0)
    {
#if NXGLIB_BITSPERPIXEL < 8
     /* Handle masking of the fractional initial byte */

     mask  = leadmask;
     dest  = line;
     lnlen = width;

     if (lnlen > 1 && mask)
        {
          dest[0] = (dest[0] & ~mask) | (mpixel & mask);
          mask = 0xff;
          dest++;
          lnlen--;
        }

      /* Handle masking of the fractional final byte */

      mask &= tailmask;
      if (lnlen > 0 && mask)
        {
          dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask);
          lnlen--;
        }

      /* Handle all of the unmasked bytes in-between */

      if (lnlen > 0)
        {
          NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen);
        }
#else
      /* Draw the entire raster line */

      NXGL_MEMSET(line, (NXGL_PIXEL_T)color, width);
#endif
      line += stride;
    }
}
void NXGL_FUNCNAME(nxgl_moverectangle,NXGLIB_SUFFIX)
(FAR struct fb_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *rect,
 FAR struct nxgl_point_s *offset)
{
  FAR const uint8_t *sline;
  FAR uint8_t *dline;
  unsigned int width;
  unsigned int stride;
  unsigned int rows;

#if NXGLIB_BITSPERPIXEL < 8
  uint8_t leadmask;
  uint8_t tailmask;
#endif

  /* Get the width of the framebuffer in bytes */

  stride = pinfo->stride;

  /* Get the dimensions of the rectange to fill: width in pixels, height
   * in rows
   */

  width = rect->pt2.x - rect->pt1.x + 1;
  rows  = rect->pt2.y - rect->pt1.y + 1;

#if NXGLIB_BITSPERPIXEL < 8
# ifdef CONFIG_NX_PACKEDMSFIRST

  /* Get the mask for pixels that are ordered so that they pack from the
   * MS byte down.
   */

  leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x)));
  tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt2.x-1)));
# else
  /* Get the mask for pixels that are ordered so that they pack from the
   * LS byte up.
   */

  leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(rect->pt1.x)));
  tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(rect->pt1.x-1)));
# endif
#endif

  /* sline = address of the first pixel in the top row of the source in
   * framebuffer memory
   */

  sline = pinfo->fbmem + rect->pt1.y * stride + NXGL_SCALEX(rect->pt1.x);

  /* dline = address of the first pixel in the top row of the destination
   * in framebuffer memory.  We get dline by subtract the offset from the
   * source position.
   */

  dline = pinfo->fbmem + offset->y * stride + NXGL_SCALEX(offset->x);

  /* Case 1:  Is the destination position above the displayed position?
   * If the destination position is less then then the src address, then the
   * destination is offset to a postion below (and or to the left) of the
   * source in framebuffer memory.
   */

  if (offset->y < rect->pt1.y ||
     (offset->y < rect->pt1.y && offset->x <= rect->pt1.x))
    {
      /* Yes.. Copy the rectangle from top down (i.e., adding the stride
       * to move to the next, lower row) */

      while (rows--)
        {
          /* Copy the row */

#if NXGLIB_BITSPERPIXEL < 8
          nxgl_lowresmemcpy(dline, sline, width, leadmask, tailmask);
#else
          NXGL_MEMCPY(dline, sline, width);
#endif
          /* Point to the next source/dest row below the current one */

          dline += stride;
          sline += stride;
        }
    }

  /* Case 2: No.. the destination position is above (or to the left of)
   * the displayed source position
   */

  else
    {
      /* Adjust sline and dline to point to the bottom row (+1) of the
       * source and destination rectangles in framebuffer memory.
       */

      unsigned int hoffset = rows * stride;
      sline += hoffset;
      dline += hoffset;

      /* Copy the rectangle from the bottom up (i.e., subtracting stride
       * to re-position to the previous, higher row)
       */

      while (rows--)
        {
          /* Point to the next source/dest row above the current one */

          dline -= stride;
          sline -= stride;

          /* Copy the row */

#if NXGLIB_BITSPERPIXEL < 8
          nxgl_lowresmemcpy(dline, sline, width, leadmask, tailmask);
#else
          NXGL_MEMCPY(dline, sline, width);
#endif
        }
    }
}
void NXGL_FUNCNAME(nxgl_copyrectangle, NXGLIB_SUFFIX)
(FAR struct fb_planeinfo_s *pinfo, FAR const struct nxgl_rect_s *dest,
 FAR const void *src, FAR const struct nxgl_point_s *origin,
 unsigned int srcstride)
{
  FAR const uint8_t *sline;
  FAR uint8_t *dline;
  unsigned int width;
  unsigned int deststride;
  unsigned int rows;

#if NXGLIB_BITSPERPIXEL < 8
  FAR const uint8_t *sptr;
  FAR uint8_t *dptr;
  uint8_t leadmask;
  uint8_t tailmask;
  uint8_t mask;
  int lnlen;
#endif

  /* Get the width of the framebuffer in bytes */

  deststride = pinfo->stride;

  /* Get the dimensions of the rectange to fill: width in pixels,
   * height in rows
   */

  width = dest->pt2.x - dest->pt1.x + 1;
  rows  = dest->pt2.y - dest->pt1.y + 1;

#if NXGLIB_BITSPERPIXEL < 8
# ifdef CONFIG_NX_PACKEDMSFIRST

  /* Get the mask for pixels that are ordered so that they pack from the
   * MS byte down.
   */

  leadmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(dest->pt1.x)));
  tailmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(dest->pt2.x-1)));
# else
  /* Get the mask for pixels that are ordered so that they pack from the
   * LS byte up.
   */

  leadmask = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(dest->pt1.x)));
  tailmask = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(dest->pt1.x-1)));
# endif
#endif

  /* Then copy the image */

  sline = (FAR const uint8_t *)src + NXGL_SCALEX(dest->pt1.x - origin->x) + (dest->pt1.y - origin->y) * srcstride;
  dline = pinfo->fbmem + dest->pt1.y * deststride + NXGL_SCALEX(dest->pt1.x);

  while (rows--)
    {
#if NXGLIB_BITSPERPIXEL < 8
     /* Handle masking of the fractional initial byte */

     mask  = leadmask;
     sptr  = sline;
     dptr  = dline;
     lnlen = width;

     if (lnlen > 1 && mask)
        {
          dptr[0] = (dptr[0] & ~mask) | (sptr[0] & mask);
          mask = 0xff;
          dptr++;
          sptr++;
          lnlen--;
        }

      /* Handle masking of the fractional final byte */

      mask &= tailmask;
      if (lnlen > 0 && mask)
        {
          dptr[lnlen-1] = (dptr[lnlen-1] & ~mask) | (sptr[lnlen-1] & mask);
          lnlen--;
        }

      /* Handle all of the unmasked bytes in-between */

      if (lnlen > 0)
        {
          NXGL_MEMCPY(dptr, sptr, lnlen);
        }
#else
      /* Copy the whole line */

      NXGL_MEMCPY((NXGL_PIXEL_T *)dline, (NXGL_PIXEL_T *)sline, width);
#endif
      dline += deststride;
      sline += srcstride;
    }
}
void NXGL_FUNCNAME(nxgl_filltrapezoid,NXGLIB_SUFFIX)(
  FAR struct fb_planeinfo_s *pinfo,
  FAR const struct nxgl_trapezoid_s *trap,
  FAR const struct nxgl_rect_s *bounds,
  NXGL_PIXEL_T color)
{
  unsigned int stride;
  unsigned int width;
  FAR uint8_t *dest;
  FAR uint8_t *line;
  int nrows;
  b16_t x1;
  b16_t x2;
  nxgl_coord_t y1;
  nxgl_coord_t y2;
  b16_t dx1dy;
  b16_t dx2dy;

#if NXGLIB_BITSPERPIXEL < 8
  uint8_t mpixel = NXGL_MULTIPIXEL(color);
  uint8_t mask;
  int lnlen;
#endif

  /* Get the width of the framebuffer in bytes */

  stride = pinfo->stride;

  /* Get the top run position and the number of rows to draw */

  x1    = trap->top.x1;
  x2    = trap->top.x2;

  /* Calculate the number of rows to render */

  y1    = trap->top.y;
  y2    = trap->bot.y;
  nrows = y2 - y1 + 1;

  /* Calculate the slope of the left and right side of the trapezoid */

  if (nrows > 1)
    {
      dx1dy = b16divi((trap->bot.x1 - x1), nrows - 1);
      dx2dy = b16divi((trap->bot.x2 - x2), nrows - 1);
    }
  else
    {
      /* The trapezoid is a run! Use the average width. */

      x1    = (x1 + trap->bot.x1) >> 1;
      x2    = (x2 + trap->bot.x2) >> 1;
      dx1dy = 0;
      dx2dy = 0;
    }

  /* Perform vertical clipping */

  if (y1 < bounds->pt1.y)
    {
      /* Is the entire trapezoid "above" the clipping window? */

      if (y2 < bounds->pt1.y)
        {
          /* Yes.. then do nothing */

          return;
        }

      /* Calculate the x values for the new top run */

      int dy = bounds->pt1.y - y1;
      x1    += dy * dx1dy;
      x2    += dy * dx2dy;

      /* Clip and re-calculate the number of rows to render */

      y1     = bounds->pt1.y;
      nrows  = y2 - y1 + 1;
    }

  if (y2 > bounds->pt2.y)
    {
      /* Is the entire trapezoid "below" the clipping window? */

      if (y1 > bounds->pt2.y)
        {
          /* Yes.. then do nothing */

          return;
        }

      /* Clip and re-calculate the number of rows to render */

      y2     = bounds->pt2.y;
      nrows  = y2 - y1 + 1;
    }

  /* Get the address of the first byte on the first line */

  line = pinfo->fbmem + y1 * stride ;

  /* Then fill the trapezoid line-by-line */

  while (nrows--)
    {
      int ix1;
      int ix2;

      /* Handle the special case where the sides cross (as in an hourglass) */

      if (x1 > x2)
        {
          b16_t tmp;
          ngl_swap(x1, x2, tmp);
          ngl_swap(dx1dy, dx2dy, tmp);
        }

      /* Convert the positions to integer */

      ix1 = b16toi(x1);
      ix2 = b16toi(x2);

      /* Handle some corner cases where we draw nothing.  Otherwise, we will
       * always draw at least one pixel.
       */

      if (x1 <= x2 && ix2 >= bounds->pt1.x && ix1 <= bounds->pt2.x)
        {
          /* Get a clipped copies of the starting and ending X positions.  This
           * clipped truncates "down" and gives the quantized pixel holding the
           * fractional X position
           */

          ix1 = ngl_clipl(ix1, bounds->pt1.x);
          ix2 = ngl_clipr(ix2, bounds->pt2.x);

          /* Get the run length for the clipped row */

          width = ix2 - ix1 + 1;

#if NXGLIB_BITSPERPIXEL < 8
          /* Handle masking of the fractional initial byte */

#ifdef CONFIG_NX_PACKEDMSFIRST
          mask  = (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix1));
#else
          mask  = (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix1)));
#endif
          dest  = line;
          lnlen = width;

          if (lnlen > 1 && mask)
            {
              dest[0] = (dest[0] & ~mask) | (mpixel & mask);
              mask = 0xff;
              dest++;
              lnlen--;
            }

          /* Handle masking of the fractional final byte */

#ifdef CONFIG_NX_PACKEDMSFIRST
          mask &= (uint8_t)(0xff << (8 - NXGL_REMAINDERX(ix2)));
#else
          mask &= (uint8_t)(0xff >> (8 - NXGL_REMAINDERX(ix2)));
#endif
          if (lnlen > 0 && mask)
            {
              dest[lnlen-1] = (dest[lnlen-1] & ~mask) | (mpixel & mask);
              lnlen--;
            }

          /* Handle all of the unmasked bytes in-between */

          if (lnlen > 0)
            {
              NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, lnlen);
            }

#else
          /* Then draw the run from (line + ix1) to (line + ix2) */

          dest = line + NXGL_SCALEX(ix1);
          NXGL_MEMSET(dest, (NXGL_PIXEL_T)color, width);
#endif
        }

      /* Move to the start of the next line */

      line += stride;

      /* Add the dx/dy value to get the run positions on the next row */

      x1   += dx1dy;
      x2   += dx2dy;
    }