⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c_cmd_drawing.inc

📁 乐高机器人的源码,开发平台是IAR_for_AVR.
💻 INC
📖 第 1 页 / 共 2 页
字号:

  //Resolve array argument
  ArgV[2] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[2]));
  ArgV[3] = (UBYTE*)cCmdDVPtr(*(DV_INDEX *)(ArgV[3]));

  cCmdClearScreenIfNeeded(*(ULONG*)ArgV[4]);

  //Open the file in memory map mode. return if failure.
  LStatus = pMapLoader->pFunc(OPENREADLINEAR, ArgV[2], (UBYTE*)(&pImage), &DataSize);
  ImageHandle = LOADER_HANDLE(LStatus);

  //If error opening file, give up and write loader status back to user.
  if (LOADER_ERR(LStatus) != SUCCESS || pImage == NULL)
  {
    *pReturnVal = (SBYTE)(LOADER_ERR_BYTE(LStatus));
    return (NO_ERR);
  }
  //Else, start interpretting the file
  else
  {
    // Read the ArgV params, Clear the data table.
    Pt = *(IMG_PT*)ArgV[1];
    gpPassedImgVars = (SLONG*)ArgV[3];
    memset(gpImgData,0,sizeof(gpImgData));

    // Run through the op codes.
    while(!IS_ERR(DStatus))
    {
      // Setup to look at an opcode, make sure it looke reasonable.
      if (DataSize < sizeof(IMG_OP_CORE))
      {
        DStatus = ERR_FILE;
        break; // Too small to look at, somethings wrong.
      }
      OpSize = pImage->Core.OpSize + sizeof(UWORD);
      if (OpSize & 0x01)
      {
        DStatus = ERR_FILE;
        break; // Odd sizes not allowed.
      }

      switch(pImage->Core.OpCode)
      {
        case IMG_SPRITE_ID:
        {
          if (OpSize >= sizeof(IMG_OP_SPRITE))
            cCmdSetIMGData(pImage->Sprite.DataAddr, pImage);
        }
        break;

        case IMG_VARMAP_ID:
        {
          if (OpSize >= sizeof(IMG_OP_VARMAP))
            cCmdSetIMGData(pImage->VarMap.DataAddr, pImage);
        }
        break;

        case IMG_COPYBITS_ID:
        {
          if (OpSize >= sizeof(IMG_OP_COPYBITS))
          {
            IMG_OP_COPYBITS * pCB = &(pImage->CopyBits);
            cCmdCopyBitMapBits(
              (cCmdResolveValue(pCB->Dst.X) + Pt.X),
              (cCmdResolveValue(pCB->Dst.Y) + Pt.Y),
              cCmdResolveValue((pCB->Src.Pt.X)),
              cCmdResolveValue((pCB->Src.Pt.Y)),
              cCmdResolveValue((pCB->Src.Width)),
              cCmdResolveValue((pCB->Src.Height)),
              (IMG_OP_SPRITE*)cCmdGetIMGData(cCmdResolveValue(pCB->DataAddr)));
          }
        }
        break;

        case IMG_LINE_ID:
        {
          if (OpSize >= sizeof(IMG_OP_LINE))
          {
            IMG_OP_LINE * pL = &(pImage->Line);
            cCmdDrawLine(
              (cCmdResolveValue(pL->Pt1.X)+Pt.X),
              (cCmdResolveValue(pL->Pt1.Y)+Pt.Y),
              (cCmdResolveValue(pL->Pt2.X)+Pt.X),
              (cCmdResolveValue(pL->Pt2.Y)+Pt.Y)
            );
          }
        }
        break;

        case IMG_RECTANGLE_ID:
        {
          if (OpSize >= sizeof(IMG_OP_LINE))
          {
            IMG_OP_RECT * pL = &(pImage->Rect);
            cCmdDrawRect(
              (SWORD)(cCmdResolveValue(pL->Pt.X)+Pt.X),
              (SWORD)(cCmdResolveValue(pL->Pt.Y)+Pt.Y),
              (SWORD)(cCmdResolveValue(pL->Width)),
              (SWORD)(cCmdResolveValue(pL->Height))
            );
          }
        }
        break;

        case IMG_PIXEL_ID:
        {
          if (OpSize >= sizeof(IMG_OP_LINE))
          {
            cCmdSetPixel(
              (cCmdResolveValue(pImage->Pixel.Pt.X) + Pt.X),
              (cCmdResolveValue(pImage->Pixel.Pt.Y) + Pt.Y),
              TRUE);
          }
        }
        break;

        case IMG_NUMBOX_ID:
        {
          if (OpSize >= sizeof(IMG_OP_NUMBOX))
          {
            UBYTE NumStr[20];
            IMG_OP_NUMBOX * pNB = &(pImage->NumBox);
            sprintf((PSZ)NumStr, "%d", cCmdResolveValue(pNB->Value));
            cCmdDrawString(
              NumStr,
              (UBYTE) (cCmdResolveValue(pNB->Pt.X) + Pt.X),
              (UBYTE) (cCmdResolveValue(pNB->Pt.Y) + Pt.Y));
          }
        }
        break;

        case IMG_DESCRIPTION_ID:
        {
        //No-op
        }
        break;

        default:
        {
          //Unrecognized opcode, pass an error back to the user.
          DStatus = ERR_FILE;
        }
        break;
      }

      DataSize -= OpSize;
      pImage = (IMG_OP_UNION*) ((UBYTE*)pImage + OpSize);
    }

    pMapDisplay->UpdateMask |= SCREEN_BIT(SCREEN_BACKGROUND);
  }

  // Set return value, close file and return
  *pReturnVal = DStatus;
  pMapLoader->pFunc(CLOSE, &ImageHandle, NULL, NULL);
  return (NO_ERR);
}

//-----------------------------------------------------------------
// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
void cCmdDrawLine(
  SLONG x1,
  SLONG y1,
  SLONG x2,
  SLONG y2)
{
  SLONG d,x,y,ax,ay,sx,sy,dx,dy;

  // Initialize variables
  dx = x2-x1;  ax = ABS(dx)<<1;  sx = SGN(dx);
  dy = y2-y1;  ay = ABS(dy)<<1;  sy = SGN(dy);
  x = x1;
  y = y1;
  if (ax>ay)
  {    /* x dominant */
    d = ay-(ax>>1);
    for (;;)
    {
      cCmdSetPixel(x, y, TRUE);
      if (x==x2)
        return;
      if (d>=0)
      {
        y += sy;
        d -= ax;
      }
      x += sx;
      d += ay;
    }
  }
  else
  {      /* y dominant */
    d = ax-(ay>>1);
    for (;;)
    {
      cCmdSetPixel(x, y, TRUE);
      if (y==y2)
        return;
      if (d>=0)
      {
        x += sx;
        d -= ay;
      }
      y += sy;
      d += ax;
    }
  }
}


//-----------------------------------------------------------------
// cCmdDrawLine - draw a line. All clipping is done by the set pixel function.
void cCmdDrawRect(
  SLONG left,
  SLONG bottom,
  SLONG width,
  SLONG height)
{
  SLONG right = left + width;
  SLONG top = bottom + height;

  // Draw the four line segments
  cCmdDrawLine(left, top, right, top);
  cCmdDrawLine(right, top, right, bottom);
  cCmdDrawLine(right, bottom, left, bottom);
  cCmdDrawLine(left, bottom, left, top);
}


#ifndef DISPLAY_REALWIDTH
  #define DISPLAY_REALWIDTH   DISPLAY_WIDTH
#endif
//-----------------------------------------------------------------
//cCmdCopyBitMapBits
void cCmdCopyBitMapBits(
  SLONG dst_x,  // left pixel on LCD
  SLONG dst_y,  // bottom pixel on LCD
  SLONG src_x,  // starting pixel x coordinate from source map
  SLONG src_y,  // starting pixel y coordinate from source map
  SLONG src_width, // width in pixels to the right (negative implies to the left)
  SLONG src_height, // height in pixels down (negative implies down)
  IMG_OP_SPRITE * pSprite)
{
  SLONG dy;  // Location in the destination pixmap , the screen that is
  SLONG sx;
  SLONG sy;  // Location in the source pixmap.
  SLONG trim, last_x, last_y, rowbytes;
  UBYTE *pSrcByte;
  UBYTE *pDstBytes;
  UBYTE *pDstByte, *pFirstDstByte;
  UBYTE *pLastDstByte;
  UBYTE bit_y, not_bit_y;
  UBYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

  // Data in the image file is row major 8 pixels per byte.top row first.
  // src and dst coordinates treat the bottom left most pixel as (0,0)

  if (!pSprite || pSprite->OpCode!=IMG_SPRITE_ID)
    return;

  pDstBytes = DISP_BUFFER_P;

  // Clip the edges. Modify the source and width as well.
  if (dst_x < 0) {        // bounds check start of x
    trim = (0 - dst_x);
    dst_x = 0;
    src_x += trim;
    src_width -= trim;
    }

  last_x = dst_x + src_width;
  if (last_x > DISPLAY_WIDTH)   // bound check end of x
    last_x = DISPLAY_WIDTH;

  if (dst_y < 0) {        // bound check start of y
    trim  = (0 - dst_y);
    dst_y = 0;
    src_y += trim;  // fix up source as well since we are clipping the start of the loop
    src_height -= trim;
    }

  last_y = dst_y + src_height;
  if (last_y > DISPLAY_HEIGHT)  // bound check end of y
    last_y = DISPLAY_HEIGHT;

  // Convert the 0,0 bottom left origin to the top left 0,0 used by the actual
  // buffer
  last_y = TRANSLATE_Y(last_y);
  dst_y = TRANSLATE_Y(dst_y);

  // The last row is the top most scan line in the LCD Buffer
  // so limit if the copy would copy into memory before the buffer.
  // The first row copied will be the one closest to the bottom of the LCD
  // If that is off screen then limit as well and adjust the start point on the start

  // Copy bits top to top moving down.
  sy = src_y;
  rowbytes = pSprite->RowBytes;

  pSrcByte = pSprite->Bytes + ((pSprite->Rows - 1 - sy) * rowbytes);
  pFirstDstByte =  pDstBytes + ((dst_y >> 3) * DISPLAY_REALWIDTH) + dst_x;
  for (dy = dst_y;  dy > last_y; dy--)
  {
    sx = src_x;
  bit_y = masks[7 - (dy & 0x07)];
  not_bit_y = ~ bit_y;
    pDstByte = pFirstDstByte;
    pLastDstByte = pDstByte + (last_x - dst_x);
    for (; pDstByte < pLastDstByte; pDstByte++)
    {
    if ( *(pSrcByte + (sx >> 3)) & masks[sx & 0x07] ){
      *pDstByte |= bit_y;
    } else {
      *pDstByte &= not_bit_y;
      }
      sx ++;
    }
    pSrcByte -= rowbytes;
    sy ++;
    if ((dy & 0x07) == 0) // bump back the scan line start point at rollover
      pFirstDstByte -= DISPLAY_REALWIDTH;
  }

}

//-----------------------------------------------------------------
// cCmdSetPixel - Set or clear a pixel based on Val
void cCmdSetPixel(SLONG X, SLONG Y, ULONG Val)
{
  Y = TRANSLATE_Y(Y);

  pMapDisplay->pFunc(DISPLAY_PIXEL, (UBYTE)Val, (UBYTE)X, (UBYTE)Y, 0, 0);
}


//-----------------------------------------------------------------
//cCmdWrapSetScreenMode
//ArgV[0]: (Function return) Status code, SBYTE
//ArgV[1]: ScreenMode  ULONG
NXT_STATUS cCmdWrapSetScreenMode(UBYTE * ArgV[])
{
  ULONG ScreenMode = (ULONG)(*ArgV[1]);
  if (ScreenMode == RESTORE_NXT_SCREEN) {
    cCmdRestoreDefaultScreen();
  }

  // Set return value
  *(SBYTE*)(ArgV[0]) = NO_ERR;
  return NO_ERR;
}

//------------------------------------------------------------------
// cCmdClearScreenIfNeeded - Clear entire sceen buffer if explicitly requested or implicitly required.
void cCmdClearScreenIfNeeded(ULONG DrawOptions)
{
  //If we are the first drawing command, clear the screen and record that we've done so
  if (VarsCmd.DirtyDisplay == FALSE)
  {
    VarsCmd.DirtyDisplay = TRUE;
    pMapUi->Flags &= ~UI_ENABLE_STATUS_UPDATE;

    //Override DrawOptions because we have to clear anyway
    DrawOptions = DRAW_OPT_CLEAR_WHOLE_SCREEN;
  }

  if (DRAW_OPT_CLEAR_MODE(DrawOptions))
  {
    pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);

    //Clear UpdateMask to kill any pending updates
    pMapDisplay->UpdateMask = 0;
  }

  return;
}

//------------------------------------------------------------------
// cCmdDrawString - Draw string to display buffer
// Properly uses 'Normal' display buffer to avoid conflicts with popup buffer
// Clips text at bottom and right hand edges of the screen buffer
//!!! Function copied and modified from cDisplayString
void cCmdDrawString(UBYTE *pString, ULONG X, ULONG Y)
{
  UBYTE   *pSource;
  UBYTE   *pDestination;
  FONT    *pFont;
  ULONG   FontWidth;
  ULONG   Items;
  ULONG   Item;
  ULONG   Line;

  //Get current font information
  pFont = pMapDisplay->pFont;
  Items = pFont->ItemsX * pFont->ItemsY;

  //Invert Y coordinate to match display buffer
  Y = TRANSLATE_Y(Y);
  Line = (Y & 0xF8) / 8;

  //If text line is out of bounds, do nothing.
  if (Line >= TEXTLINES)
    return;

  //Calculate pointer to first byte of drawing destination
  pDestination = &(DISP_BUFFER_P[Line * DISPLAY_WIDTH + X]);

  while (*pString)
  {
    FontWidth = pFont->ItemPixelsX;
    //Calculate X coordinate of the right edge of this character.
    //If it will extend past the right edge, clip the string.
    X += FontWidth;
    if (X >= DISPLAY_WIDTH)
      break;

    //If Item is defined by the font, display it.  Else, ignore it.
    Item = *pString - ' ';
    if (Item < Items)
    {
      pSource      = (UBYTE*)&(pFont->Data[Item * FontWidth]);
      while (FontWidth--)
      {
        *pDestination = *pSource;
        pDestination++;
        pSource++;
      }
    }
    pString++;
  }
}

//------------------------------------------------------------------
// cCmdRestoreDefaultScreen - Restore to Default 'Running' screen
void cCmdRestoreDefaultScreen(void)
{
  //If this program has taken over the display, reset it for the UI
  if (VarsCmd.DirtyDisplay == TRUE)
  {
    VarsCmd.DirtyDisplay = FALSE;

    pMapDisplay->pFunc(DISPLAY_ERASE_ALL, 0, 0, 0, 0, 0);
    pMapDisplay->UpdateMask = SCREEN_BIT(SCREEN_BACKGROUND);

    pMapUi->Flags |= UI_ENABLE_STATUS_UPDATE | UI_REDRAW_STATUS;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -