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

📄 path.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
  // !TODO!

  Enter(L"InitializeEdgeList");

  EdgeList->Array = (PERM3_EDGE *)SystemAlloc(NumEdges * sizeof(PERM3_EDGE));
  if (EdgeList->Array != NULL) {

    EdgeList->Size = NumEdges;
    EdgeList->Count = 0;

    EdgeList->MinY = 0;
    EdgeList->MaxY = 0;

    EdgeList->FirstTop = NULL;
    EdgeList->FirstBottom = NULL;
    EdgeList->FirstActive = NULL;
  }
  else {
    Error(L"System memory allocation failure.\n");
  } 

  Exit(L"InitializeEdgeList");
}

BOOL
AddEdge(
  PERM3_EDGE_LIST * EdgeList,
  FIX               x1,
  FIX               y1,
  FIX               x2,
  FIX               y2
  )
{
  // AddEdge
  // This function adds an edge to the given edge list. The edge is defined
  // by two points, given in 28:4 fixed point.

  // Local variables.

  BOOL         FnRetVal = FALSE;
  BOOL         SpaceAvailable = FALSE;
  PERM3_EDGE * NewEdge;
  LONG         dX, dY;
  LONG         IntegralAdvance;
  LONG         FractionalAdvance;
  LONG         FractionalTotal;

  // Check parameters.

  // !TODO!

  Enter(L"AddEdge");

  if (EdgeList->Count < EdgeList->Size) {

    SpaceAvailable = TRUE;
  }
  else {

    // We have run out of space. We need more.

    EdgeList->Array = SystemReAlloc(EdgeList->Array,
                                    (EdgeList->Size + EDGE_ARRAY_GROW) * sizeof(PERM3_EDGE));
    if (EdgeList->Array != NULL) {

      EdgeList->Size += EDGE_ARRAY_GROW;
      SpaceAvailable = TRUE;
    }
  }

  if (SpaceAvailable) {

    NewEdge = &EdgeList->Array[EdgeList->Count]; 

    if (y1 < y2) {
      NewEdge->Direction = 1;
    }
    else {
      NewEdge->Direction = -1;
      Swap(y1,y2);
      Swap(x1,x2);
    }

    // Discard edges with dY == 0.

    if (((y1 + 15) & ~15) < ((y2 + 15) & ~15)) {

      EdgeList->Count++;      

      dX = x2 - x1;
      dY = y2 - y1;

      IntegralAdvance = dX / dY;
      FractionalAdvance = dX % dY;
      FractionalTotal = 0;

      while (y1 & 15) {

        y1++;
        x1 += IntegralAdvance;
        FractionalTotal += FractionalAdvance;
        if (FractionalAdvance >= 0) {
          if (FractionalTotal > 0) {
            FractionalTotal -= dY;
            x1++;
          }
        }
        else {
          if (FractionalTotal <= -dY) {
            FractionalTotal += dY;
            x1--;
          }
        }
      }

      // Now, (x1,y1) are the 16:16 coordinates where the edge intersects a row.

      NewEdge->TopY = y1 >> 4;
      NewEdge->BottomY = (y2 + 15) >> 4;
      NewEdge->TopX = x1;

      NewEdge->NextTop = NULL;
      NewEdge->NextBottom = NULL;
      NewEdge->XIntegralAdvance = (dX * 16) / dY;
      NewEdge->XFractionalAdvance = (dX * 16) % dY;
      NewEdge->Height = dY;
      NewEdge->FractionalTotalStart = FractionalTotal;

      // This insures that we resort the edgelist next time we draw it.

      EdgeList->FirstTop = NULL;
    }

    FnRetVal = TRUE;
  }
  else {

    Error(L"No space available to grow edge list!\n");
  }

  Exit(L"AddEdge");

  return FnRetVal;
}

BOOL
FillEdge(
  PERM3_EDGE_LIST * EdgeList,
  PERM3_BLT_PARAM * Parameters
  )
{
  // FillEdge
  // This method, given a closed path as defined by the given edge list,
  // will rasterize that list. It uses a given blit structure, assuming that
  // by simply modifying the destination rectangle and repeatedly calling
  // TryBothBlt will have the desired effect.

  // Local variables.

  BOOL          FnRetVal = FALSE;
  LONG          NewEdgeNum;
  PERM3_EDGE *  Edge;
  PERM3_EDGE ** IndirectEdge;
  ULONG         EdgeCount;
  ULONG         ClipRectCount;
  const RECT *  ClipRect;
  RECT          ScreenRect;
  RECT       *  DestRect;
  LONG          y;
  LONG          LastRow;
  PERM3_EDGE *  TopList;
  PERM3_EDGE *  BottomList;
  BOOL          Swapped;
  LONG          LeftX;
  LONG          RightX;

  // Check parameters.

  // !TODO!

  Enter(L"FillEdge");

  DestRect = (RECT *)Parameters->DestRect;

  if (EdgeList->Count >= 1) {

    if (EdgeList->FirstTop == NULL) {

      // Resort the list by TopY and BottomY.

      for (Edge = EdgeList->Array, NewEdgeNum = 0;
           NewEdgeNum < EdgeList->Count;
           NewEdgeNum++, Edge++) {

        // Insert into the list sorted by TopY.

        for (IndirectEdge = &EdgeList->FirstTop;
             (*IndirectEdge != NULL) && (Edge->TopY > (*IndirectEdge)->TopY);
             IndirectEdge = &((*IndirectEdge)->NextTop));
        Edge->NextTop = *IndirectEdge;
        *IndirectEdge = Edge;

        // Insert into the list sorted by BottomY.

        for (IndirectEdge = &EdgeList->FirstBottom;
             (*IndirectEdge != NULL) && (Edge->BottomY > (*IndirectEdge)->BottomY);
             IndirectEdge = &((*IndirectEdge)->NextBottom));
        if (*IndirectEdge == NULL) {
          EdgeList->MaxY = Edge->BottomY;
        }
        Edge->NextBottom = *IndirectEdge;
        *IndirectEdge = Edge;
      }
      EdgeList->MinY = EdgeList->FirstTop->TopY;
    }

    // Now, we iterate over the clipping rectangles.

    // If we have no clipping rectangles, we clip to the screen.

    if (Parameters->ClipRectCount == 0) {

      ScreenRect.left = 0;
      ScreenRect.top = 0;
      ScreenRect.right = GetDisplayModeWidth(GetCurrentMode());
      ScreenRect.bottom = GetDisplayModeHeight(GetCurrentMode());

      Parameters->ClipRectCount = 1;
      Parameters->ClipRect = &ScreenRect;
    }

    for (ClipRectCount = 0;
         ClipRectCount < Parameters->ClipRectCount;
         ClipRectCount++) {

      ClipRect = &(Parameters->ClipRect[ClipRectCount]);

      if (EdgeList->MinY >= ClipRect->bottom ||
          EdgeList->MaxY < ClipRect->top) {

        // We have completely clipped the edge, vertically.
 
        continue;
      }

      // Loop over all of the rows spanned by this edge list.
 
      TopList = EdgeList->FirstTop;
      BottomList = EdgeList->FirstBottom;
      EdgeList->FirstActive = NULL;

      LastRow = min(EdgeList->MaxY, ClipRect->bottom);

      for (y = EdgeList->MinY;
           y < LastRow;
           y++) {

        DestRect->top = y;
        DestRect->bottom = y + 1;

        // Add new edges to the active list.

        for (;
             (TopList != NULL) && (TopList->TopY <= y);
             TopList = TopList->NextTop) {

          // Reset x and error accumulator for line.

          TopList->FractionalTotal = TopList->FractionalTotalStart;
          TopList->X = TopList->TopX;

          // Insert into list sorted by X.

          for (IndirectEdge = &(EdgeList->FirstActive);
               (*IndirectEdge != NULL) && (TopList->X > (*IndirectEdge)->X);
               IndirectEdge = &((*IndirectEdge)->NextActive));
          TopList->NextActive = *IndirectEdge;
          *IndirectEdge = TopList;
        }

        // Remove edges from active list that do not intersect with our
        // scanline.

        for (;
             (BottomList != NULL) && (BottomList->BottomY <= y);
             BottomList = BottomList->NextBottom) {

          for (IndirectEdge = &(EdgeList->FirstActive);
               (*IndirectEdge != NULL) && (*IndirectEdge != BottomList);
               IndirectEdge = &((*IndirectEdge)->NextActive));
          if (*IndirectEdge != NULL) {
            *IndirectEdge = (*IndirectEdge)->NextActive;
          }
        }

        // Now, sort the active edge list by x.

        do {

          Swapped = FALSE;
          for (IndirectEdge = &(EdgeList->FirstActive);
               (*IndirectEdge != NULL) && ((*IndirectEdge)->NextActive != NULL);
               IndirectEdge = &((*IndirectEdge)->NextActive)) {

            Edge = *IndirectEdge;
            if (Edge->X > Edge->NextActive->X) {
              Swapped = TRUE;
              *IndirectEdge = Edge->NextActive;
              Edge->NextActive = Edge->NextActive->NextActive;
              (*IndirectEdge)->NextActive = Edge;
            }
          }
        } while (Swapped);

        EdgeCount = 0;

        // Draw each span for the current scanline.

        if (y >= ClipRect->top) {

          for (Edge = EdgeList->FirstActive;
               Edge != NULL;
               Edge = Edge->NextActive) {

            LeftX = (Edge->X + 15) >> 4;

            for (EdgeCount = Edge->Direction;
                 EdgeCount != 0;
                 ) {
              Edge = Edge->NextActive;
              if (Edge == NULL) {
                break;
              }
              EdgeCount += Edge->Direction;
            }

            if (Edge != NULL) {

              RightX = (Edge->X + 15) >> 4;

              if (LeftX < ClipRect->left) LeftX = ClipRect->left;
              if (RightX > ClipRect->right) RightX = ClipRect->right;

              if (LeftX < RightX) {

                DestRect->left = LeftX;
                DestRect->right = RightX;

                FnRetVal = TryBothBlt(Parameters);
                if (!FnRetVal) {

                  return FnRetVal;
                }
              }
            }
            else {
              Error(L"Unmatched line segment in polygon fill.\n");
              return FALSE;
            }
          }
        }

        // Now, increment edges.

        for (Edge = EdgeList->FirstActive;
             Edge != NULL;
             Edge = Edge->NextActive) {

          Edge->X += Edge->XIntegralAdvance;
          Edge->FractionalTotal += Edge->XFractionalAdvance;

          if (Edge->XFractionalAdvance >= 0) {

            if (Edge->FractionalTotal > 0) {

              Edge->FractionalTotal -= Edge->Height;
              Edge->X++;
            }
          }
          else {

            if (Edge->FractionalTotal <= -Edge->Height) {

              Edge->FractionalTotal += Edge->Height;
              Edge->X--;
            }
          }
        }
      }
    }
  }
  else {

    // Can't do anything with a NULL polygon. Draw nothing and call it
    // success.

    FnRetVal = TRUE;
  } 

  Exit(L"FillEdge");

  return FnRetVal;
}

void
DestroyEdgeList(
  PERM3_EDGE_LIST * EdgeList
  )
{
  // DestroyEdgeList
  // This function frees any resources allocated in the course of using the
  // given PERM3_EDGE_LIST.

  // Check parameters.

  // !TODO!

  Enter(L"DestroyEdgeList");

  if (EdgeList->Array != NULL) {
    SystemFree(EdgeList->Array);
    EdgeList->Array = NULL;
  }

  Exit(L"DestroyEdgeList");
}

⌨️ 快捷键说明

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