Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include <stdlib.h>
  2. #include "pxdraw.h"
  3.  
  4. #define max(a,b) (((a) > (b)) ? (a) : (b))
  5. #define min(a,b) (((a) < (b)) ? (a) : (b))
  6.  
  7. rgn_t* create_round_rect_rgn(int left, int top, int right, int bottom,
  8.         int ellipse_width, int ellipse_height)
  9. {
  10.         rgn_t  *obj;
  11.         rect_t *rects;
  12.         int a, b, i, x, y;
  13.         int64_t asq, bsq, dx, dy, err;
  14.  
  15.         right--;
  16.         bottom--;
  17.  
  18.     ellipse_width  = min(right - left, abs(ellipse_width));
  19.         ellipse_height = min(bottom - top, abs(ellipse_height));
  20.  
  21.         obj = malloc(sizeof(rgn_t));
  22.         if (obj == NULL)
  23.                 return NULL;
  24.  
  25.         obj->num_rects = ellipse_height;
  26.         obj->extents.l = left;
  27.         obj->extents.t = top;
  28.         obj->extents.r = right;
  29.         obj->extents.b = bottom;
  30.  
  31.         obj->rects = rects = malloc(obj->num_rects * sizeof(rect_t));
  32.         if (rects == NULL)
  33.         {
  34.                 free(obj);
  35.                 return NULL;
  36.         };
  37.  
  38.         /* based on an algorithm by Alois Zingl */
  39.  
  40.         a = ellipse_width - 1;
  41.         b = ellipse_height - 1;
  42.         asq = (int64_t)8 * a * a;
  43.         bsq = (int64_t)8 * b * b;
  44.         dx = (int64_t)4 * b * b * (1 - a);
  45.         dy = (int64_t)4 * a * a * (1 + (b % 2));
  46.         err = dx + dy + a * a * (b % 2);
  47.  
  48.         x = 0;
  49.         y = ellipse_height / 2;
  50.  
  51.         rects[y].l = left;
  52.         rects[y].r = right;
  53.  
  54.         while (x <= ellipse_width / 2)
  55.         {
  56.                 int64_t e2 = 2 * err;
  57.                 if (e2 >= dx)
  58.                 {
  59.                         x++;
  60.                         err += dx += bsq;
  61.                 }
  62.                 if (e2 <= dy)
  63.                 {
  64.                         y++;
  65.                         err += dy += asq;
  66.                         rects[y].l = left + x;
  67.                         rects[y].r = right - x;
  68.                 }
  69.         }
  70.  
  71.         for (i = 0; i < ellipse_height / 2; i++)
  72.         {
  73.                 rects[i].l = rects[b - i].l;
  74.                 rects[i].r = rects[b - i].r;
  75.                 rects[i].t = top + i;
  76.                 rects[i].b = rects[i].t + 1;
  77.         }
  78.         for (; i < ellipse_height; i++)
  79.         {
  80.                 rects[i].t = bottom - ellipse_height + i;
  81.                 rects[i].b = rects[i].t + 1;
  82.         }
  83.         rects[ellipse_height / 2].t = top + ellipse_height / 2;  /* extend to top of rectangle */
  84.  
  85.         return obj;
  86. };
  87.  
  88. void destroy_region(rgn_t *rgn)
  89. {
  90.         free(rgn->rects);
  91.         free(rgn);
  92. };
  93.  
  94.