GUI_FillPolygon.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:10k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/GUI
  4. *                        Universal graphic software for embedded applications
  5. *
  6. *                       (c) Copyright 2002, Micrium Inc., Weston, FL
  7. *                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
  8. *
  9. *              礐/GUI is protected by international copyright laws. Knowledge of the
  10. *              source code may not be used to write a similar product. This file may
  11. *              only be used in accordance with a license and should not be redistributed
  12. *              in any way. We appreciate your understanding and fairness.
  13. *
  14. ----------------------------------------------------------------------
  15. File        : GUI_FillPolygon.C
  16. Purpose     : Fill polygon routine
  17. ---------------------------END-OF-HEADER------------------------------
  18. */
  19. #include <stddef.h>           /* needed for definition of NULL */
  20. #include "GUI_Protected.H"
  21. #include "GUIDebug.h"
  22. /********************************************************
  23. *
  24. *              Configurable defines
  25. *
  26. *********************************************************
  27. */
  28. /*
  29. #define GUI_USE_POLYV2 1
  30. */
  31. /*
  32.         *********************************************************
  33.         *                                                       *
  34.         *              Fill Polygon                             *
  35.         *                                                       *
  36.         *********************************************************
  37. */
  38. /*
  39.     **********************************
  40.     *                                *
  41.     *      Helper functions          *
  42.     *                                *
  43.     **********************************
  44. */
  45. /*
  46.   This function returns the x-coordinate of the intersection
  47.   of the given line at the given y-coordinate.
  48.   If there is no intersection, GUI_XMAX is returned.
  49.   This routine does not work for horizontal lines, as there
  50.   would be more than a single point as intersection. This situation
  51.   needs to be checked prior to calling the routine.
  52. */
  53. int GL_CheckYInterSect(int y, const GUI_POINT*paPoint0
  54.                             , const GUI_POINT*paPoint1) {
  55.   int x0,y0,x1,y1;
  56.   if (paPoint0->y <= (paPoint1)->y) {
  57.     y0 = paPoint0->y;
  58.     if (y0>y)      /* Check if there is an intersection ... (early out) */
  59.       return GUI_XMAX+1;
  60.     y1 = paPoint1->y;
  61.     if (y1<y)      /* Check if there is an intersection ... (early out) */
  62.       return GUI_XMAX+1;
  63.     x0 = paPoint0->x;
  64.     x1 = paPoint1->x;
  65.   } else {
  66.     y0 = paPoint1->y;
  67.     if (y0>y)      /* Check if there is an intersection ... (early out) */
  68.       return GUI_XMAX+1;
  69.     y1 = paPoint0->y;
  70.     if (y1<y)      /* Check if there is an intersection ... (early out) */
  71.       return GUI_XMAX+1;
  72.     x0 = paPoint1->x;
  73.     x1 = paPoint0->x;
  74.   }
  75. /* Calc intermediate variables */
  76. /* Calculate intersection */
  77.   {
  78.     I32 Mul = (I32)(x1-x0)* (I32)(y-y0);
  79.     if (Mul >0)
  80.       Mul += (y1-y0)>>1;   /* for proper rounding */
  81.     else
  82.       Mul -= ((y1-y0)>>1)-1;   /* for proper rounding */
  83.     x0 +=Mul/(y1-y0);
  84.   }
  85.   return x0;
  86. int GL_GetSign(int v) {
  87.   if (v>0)
  88.     return 1;
  89.   if (v<0)
  90.     return -1;
  91.   return 0;
  92. }
  93. /*********************************************************************
  94. *
  95. *      GL_FillPolygon   - Old Version
  96. *
  97. **********************************************************************
  98.   The routine(s) below fill a given polygon.
  99. */
  100. #if !defined(GUI_USE_POLYV2) /* Old proven, but slow version */
  101. void GL_FillPolygon  (const GUI_POINT*paPoint, int NumPoints, int xOff, int yOff) {
  102.   int i;
  103.   int y;
  104.   int yMin = GUI_YMAX;
  105.   int yMax = GUI_YMIN;
  106. /* First step : find uppermost and lowermost coordinates */
  107.   for (i=0; i<NumPoints; i++) {
  108.     y = (paPoint+i)->y;
  109.     if (y<yMin)
  110.       yMin = y;
  111.     if (y>yMax)
  112.       yMax = y;
  113.   }
  114. /* Use Clipping rect to reduce calculation (if possible) */
  115.   if (GUI_Context.pClipRect_HL) {
  116.     if (yMax > (GUI_Context.pClipRect_HL->y1 -yOff))
  117.       yMax = (GUI_Context.pClipRect_HL->y1 -yOff);
  118.     if (yMin < (GUI_Context.pClipRect_HL->y0 -yOff))
  119.       yMin = (GUI_Context.pClipRect_HL->y0 -yOff);
  120.   }
  121. /* Second step: Calculate and draw horizontal lines */
  122.   for (y=yMin; y<=yMax; y++) {
  123.     int x0 = GUI_XMIN;         /* Left edge of line */
  124.     int LineCntTotal =0;
  125.     /* Draw all line segments */
  126.     while (x0<GUI_XMAX) {
  127.       char PointOnly=0;
  128.       char OnEdge =0;
  129.       char LineCntAdd =0;
  130.       int xX = GUI_XMAX;  /* x-coordinate of next intersection */
  131.       /* find next intersection and count lines*/
  132.       for (i=0; i<NumPoints; i++) {
  133.         int x;
  134.         int iPrev = i ? (i-1) : NumPoints-1;
  135.         int i1 = (i <(NumPoints-1)) ? i +1 : 0;
  136.         int i2 = (i1<(NumPoints-1)) ? i1+1 : 0;
  137.         /* Check if end-point is on the line */
  138.         if ((paPoint+i1)->y ==y) {
  139.           /* Start-point also on the line ?*/
  140.           if ((paPoint+i)->y ==y) {
  141.             /* Get xmin, xmax */
  142.             int xmin = (paPoint+i)->x;
  143.             int xmax = (paPoint+i1)->x;
  144.             if (xmin > xmax) {
  145.               int t = xmin; xmin = xmax; xmax =t;
  146.             }
  147.             /* left point */
  148.             if ((xmin>x0) && (xmin<=xX)) {
  149.               xX = xmin;
  150.               LineCntAdd =0;
  151.             }
  152.             if ((xmax>x0) && (xmax<=xX)) {
  153.               xX = xmax;
  154.               OnEdge =1;
  155.               /* Check if the line crosses ... */
  156.               LineCntAdd = (GL_GetSign((paPoint+i2)->y-y)
  157.                          == GL_GetSign((paPoint+iPrev)->y-y))
  158.                          ? 0 : 1;
  159.             }
  160.           } else { /* end-point.y == y, start-point.y !=y */
  161.             x = (paPoint+i1)->x;
  162.             if ((x>x0) && (x<=xX)) {
  163.               if (xX > x) {
  164.                 xX = x;
  165.                 if (GL_GetSign((paPoint+i2)->y -y) == GL_GetSign((paPoint+i)->y -y))
  166.                 {
  167.                   PointOnly  = 1;
  168.                   LineCntAdd = 0;
  169.                 } else {
  170.                   LineCntAdd=1;
  171.                 }
  172.               }
  173.             }
  174.           }
  175.         } else { /* end point not on the line, find intersection */
  176.           if (y != (paPoint+i)->y) { /* if startpoint not on y */
  177.             x = GL_CheckYInterSect(y, paPoint+i, paPoint+i1);
  178.             if ((x>x0) && (x<=xX)) {
  179.               if (x==xX) 
  180.                 LineCntAdd++;
  181.               else
  182.                 LineCntAdd=1;
  183.               xX = x;
  184.             }
  185.           } 
  186.         }
  187.       }
  188.       if ((LineCntTotal&1) || OnEdge) {
  189.         LCD_HL_DrawHLine(x0+xOff,y+yOff,xX+xOff);
  190.       } else {
  191.       /* We are looking at a endpoint ... */
  192.      if (PointOnly) {
  193.           LCD_HL_DrawHLine(xX+xOff,y+yOff,xX+xOff); /* LCD_HL_DrawPixel(xX+xOff,y+yOff); */
  194.         }
  195.       }
  196.       x0 = xX;
  197.       LineCntTotal += LineCntAdd;
  198.     }
  199.   }  
  200. }
  201. #else
  202. /*********************************************************************
  203. *
  204. *      GL_FillPolygon   - New Version
  205. *
  206. **********************************************************************
  207.   The routine(s) below fill a given polygon.
  208. */
  209. #define GUI_FP_MAXCOUNT 10
  210. #define FP_TYPE_X    0
  211. #define FP_TYPE_V    1
  212. static int GL_FP_Cnt;
  213. static struct {
  214.   I16 x;
  215.   U8  Type;
  216. } GL_FP_a[GUI_FP_MAXCOUNT];
  217. static void GL_FP_Add(int x, U8 Type) {
  218.   if (GL_FP_Cnt < GUI_FP_MAXCOUNT) {
  219.     int i;
  220.     /* Move all entries to the right (bigger x-value) */
  221.     for (i=GL_FP_Cnt; i ; i--) {
  222.       if (GL_FP_a[i-1].x < x)
  223.         break;
  224.       GL_FP_a[i] = GL_FP_a[i-1];
  225.     }
  226.     /* Insert new entry */
  227.     GL_FP_a[i].x = x;
  228.     GL_FP_a[i].Type = Type;
  229.     GL_FP_Cnt++;
  230.   }
  231. }
  232. void GL_FP_Init(void) {
  233.   GL_FP_Cnt = 0;
  234. }
  235. void GL_FP_Flush(int x0, int y) {
  236.   int i;
  237.   int x;
  238.   char On=0;
  239.   for (i=0; i<GL_FP_Cnt; i++) {
  240.     int xNew = GL_FP_a[i].x;
  241.     switch (GL_FP_a[i].Type) {
  242.     case FP_TYPE_X:
  243.       if (On) {
  244.         LCD_HL_DrawHLine(x0+x, y, x0+xNew);
  245.       }
  246.       On ^= 1;
  247.       break;
  248.     case FP_TYPE_V:
  249.       if (On) {
  250.         LCD_HL_DrawHLine(x0+x, y, x0+xNew);
  251.       } else {
  252.         LCD_HL_DrawHLine(x0+x, y, x0); /* Do not use LCD_HL_DrawPixel(x0+xNew, y); --- AA module does not support SetPixel */
  253.       }
  254.       break;
  255.     }
  256.     x = xNew+1;
  257.   }
  258. }
  259. void GL_FillPolygon  (const GUI_POINT*paPoint, int NumPoints, int xOff, int yOff) {
  260.   int i;
  261.   int y;
  262.   int yMin = GUI_YMAX;
  263.   int yMax = GUI_YMIN;
  264. /* First step : find uppermost and lowermost coordinates */
  265.   for (i=0; i<NumPoints; i++) {
  266.     y = (paPoint+i)->y;
  267.     if (y<yMin)
  268.       yMin = y;
  269.     if (y>yMax)
  270.       yMax = y;
  271.   }
  272. /* Use Clipping rect to reduce calculation (if possible) */
  273.   if (GUI_Context.pClipRect_HL) {
  274.     if (yMax > (GUI_Context.pClipRect_HL->y1 -yOff))
  275.       yMax = (GUI_Context.pClipRect_HL->y1 -yOff);
  276.     if (yMin < (GUI_Context.pClipRect_HL->y0 -yOff))
  277.       yMin = (GUI_Context.pClipRect_HL->y0 -yOff);
  278.   }
  279. /* Second step: Calculate and draw horizontal lines */
  280.   for (y=yMin; y<=yMax; y++) {
  281.     GL_FP_Init();
  282.     /* find next intersection and count lines*/
  283.     for (i=0; i<NumPoints; i++) {
  284.       int i1 = (i <(NumPoints-1)) ? i +1 : 0;
  285.       int y0 = (paPoint+i)->y;
  286.       int y1 = (paPoint+i1)->y;
  287.       /* Check if starting point is on line */
  288.       if (y0 == y) {
  289.         if (y1 == y) {  /* Add the entire line */
  290.           GL_FP_Add((paPoint+i )->x, FP_TYPE_X);
  291.           GL_FP_Add((paPoint+i1)->x, FP_TYPE_X);
  292.         } else {        /* Add only one point */
  293.           GL_FP_Add((paPoint+i )->x, FP_TYPE_V);
  294.         }
  295.       }
  296.       else if (y1 != y) {  /* Ignore if end-point is on the line */
  297.         if (((y1 >= y) && (y0 <= y)) || ((y0 >= y) && (y1 <= y))) {
  298.           int x = GL_CheckYInterSect(y, paPoint+i, paPoint+i1);
  299.           GL_FP_Add(x, FP_TYPE_X);
  300.         }
  301.       }
  302.     }
  303.     GL_FP_Flush(xOff, y+yOff);
  304.   }  
  305. }
  306. #endif
  307. void GUI_FillPolygon  (const GUI_POINT* pPoints, int NumPoints, int x0, int y0) {
  308.   GUI_LOCK();
  309.   #if (GUI_WINSUPPORT)
  310.     WM_ADDORG(x0,y0);
  311.     WM_ITERATE_START(NULL); {
  312.   #endif
  313.   GL_FillPolygon (pPoints, NumPoints, x0, y0);
  314.   #if (GUI_WINSUPPORT)
  315.     } WM_ITERATE_END();
  316.   #endif
  317.   GUI_UNLOCK();
  318. }