aaellipseRgba function

bool aaellipseRgba(
  1. Pointer<SdlRenderer> renderer,
  2. double x,
  3. double y,
  4. double rx,
  5. double ry,
  6. int r,
  7. int g,
  8. int b,
  9. int a, {
  10. int blendMode = SDL_BLENDMODE_BLEND,
})

Implementation

bool aaellipseRgba(
  Pointer<SdlRenderer> renderer,
  double x,
  double y,
  double rx,
  double ry,
  int r,
  int g,
  int b,
  int a, {
  int blendMode = SDL_BLENDMODE_BLEND,
}) {
  var result = true;
  int i;
  double a2;
  double b2;
  double ds;
  double dt;
  double dxt;
  double t;
  double s;
  double d;
  double xp;
  double yp;
  double xs;
  double ys;
  double dyt;
  double od;
  double xx;
  double yy;
  double xc2;
  double yc2;
  double cp;
  double sab;
  int weight;
  int iweight;

  /*
	* Sanity check radii
	*/
  if ((rx < 0) || (ry < 0)) {
    return false;
  }

  /*
	* Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
	*/
  if (rx == 0) {
    if (ry == 0) {
      return pixelRgba(renderer, x, y, r, g, b, a, blendMode: blendMode);
    } else {
      return vlineRgba(
        renderer,
        x,
        y - ry,
        y + ry,
        r,
        g,
        b,
        a,
        blendMode: blendMode,
      );
    }
  } else {
    if (ry == 0) {
      return hlineRgba(
        renderer,
        x - rx,
        x + rx,
        y,
        r,
        g,
        b,
        a,
        blendMode: blendMode,
      );
    }
  }

  /* Variable setup */
  a2 = rx * rx;
  b2 = ry * ry;

  ds = 2 * a2;
  dt = 2 * b2;

  xc2 = 2 * x;
  yc2 = 2 * y;

  sab = math.sqrt(a2 + b2);
  od = (sab * 0.01).toInt() + 1; /* introduce some overdraw */
  dxt = (a2 ~/ sab) + od;

  t = 0;
  s = -2 * a2 * ry;
  d = 0;

  xp = x;
  yp = y - ry;

  /* Draw */
  result = true;
  if (result) {
    result = sdlSetRenderDrawBlendMode(renderer, blendMode);
  }

  /* "End points" */
  if (result) {
    result = pixelRgba(renderer, xp, yp, r, g, b, a, blendMode: blendMode);
  }
  if (result) {
    result = pixelRgba(
      renderer,
      xc2 - xp,
      yp,
      r,
      g,
      b,
      a,
      blendMode: blendMode,
    );
  }
  if (result) {
    result = pixelRgba(
      renderer,
      xp,
      yc2 - yp,
      r,
      g,
      b,
      a,
      blendMode: blendMode,
    );
  }
  if (result) {
    result = pixelRgba(
      renderer,
      xc2 - xp,
      yc2 - yp,
      r,
      g,
      b,
      a,
      blendMode: blendMode,
    );
  }

  for (i = 1; i <= dxt; i++) {
    xp--;
    d += t - b2;

    if (d >= 0) {
      ys = yp - 1;
    } else if ((d - s - a2) > 0) {
      if ((2 * d - s - a2) >= 0) {
        ys = yp + 1;
      } else {
        ys = yp;
        yp++;
        d -= s + a2;
        s += ds;
      }
    } else {
      yp++;
      ys = yp + 1;
      d -= s + a2;
      s += ds;
    }

    t -= dt;

    /* Calculate alpha */
    if (s != 0) {
      cp = d.abs() / s.abs();
      if (cp > 1.0) {
        cp = 1.0;
      }
    } else {
      cp = 1.0;
    }

    /* Calculate weights */
    weight = (cp * 255).toInt();
    iweight = 255 - weight;

    /* Upper half */
    xx = xc2 - xp;
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        yp,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yp,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }

    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        ys,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        ys,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }

    /* Lower half */
    yy = yc2 - yp;
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        yy,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yy,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }

    yy = yc2 - ys;
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        yy,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yy,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
  }

  /* Replaces original approximation code dyt = abs(yp - yc); */
  dyt = b2 ~/ sab + od;

  for (i = 1; i <= dyt; i++) {
    yp++;
    d -= s + a2;
    if (d <= 0) {
      xs = xp + 1;
    } else if ((d + t - b2) < 0) {
      if ((2 * d + t - b2) <= 0) {
        xs = xp - 1;
      } else {
        xs = xp;
        xp--;
        d += t - b2;
        t -= dt;
      }
    } else {
      xp--;
      xs = xp - 1;
      d += t - b2;
      t -= dt;
    }

    s += ds;

    /* Calculate alpha */
    if (t != 0) {
      cp = d.abs() / t.abs();
      if (cp > 1.0) {
        cp = 1.0;
      }
    } else {
      cp = 1.0;
    }

    /* Calculate weight */
    weight = (cp * 255).toInt();
    iweight = 255 - weight;

    /* Left half */
    xx = xc2 - xp;
    yy = yc2 - yp;
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        yp,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yp,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }

    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xp,
        yy,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yy,
        r,
        g,
        b,
        a,
        iweight,
        blendMode: blendMode,
      );
    }

    /* Right half */
    xx = xc2 - xs;
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xs,
        yp,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yp,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }

    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xs,
        yy,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
    if (result) {
      result = pixelRgbaWeight(
        renderer,
        xx,
        yy,
        r,
        g,
        b,
        a,
        weight,
        blendMode: blendMode,
      );
    }
  }
  return result;
}