static void addRoundCorner()

in native-filters/src/main/jni/filters/rounding_filter.c [389:497]


static void addRoundCorner(
    JNIEnv* env,
    pixel_t* pixelPtr,
    const int w,
    const int h,
    const int radius,
    const enum Corner corner) {

  int centerX, centerY;

  switch (corner) {
    case TOP_LEFT:
      centerX = radius;
      centerY = radius;
      break;
    case TOP_RIGHT:
      centerX = w - radius - 1;
      centerY = radius;
      break;
    case BOTTOM_RIGHT:
      centerX = w - radius - 1;
      centerY = h - radius - 1;
      break;
    case BOTTOM_LEFT:
      centerX = radius;
      centerY = h - radius - 1;
  }

  if (radius < 1) {
    safe_throw_exception(env, "Circle radius too small!");
    return;
  }
  if (w <= 0 || h <= 0 || w > BITMAP_MAX_DIMENSION || h > BITMAP_MAX_DIMENSION) {
    safe_throw_exception(env, "Invalid bitmap dimensions!");
    return;
  }
  if (centerX < 0 || centerY < 0 || centerX >= w || centerY >= h) {
    safe_throw_exception(env, "Invalid circle center coordinates!");
    return;
  }

  int x = radius;
  int y = 0;

  int dx = 1;
  int dy = 1;

  const int rInc = - radius * 2;
  int err = dx + rInc;

  while (x >= y) {

    const int cXpX = centerX + x;
    const int cXmX = centerX - x;
    const int cXpY = centerX + y;
    const int cXmY = centerX - y;

    const int cYpX = centerY + x;
    const int cYmX = centerY - x;
    const int cYpY = centerY + y;
    const int cYmY = centerY - y;

    if (x < 0 || cXpY >= w || cXmY < 0 || cYpY >= h || cYmY < 0) {
      safe_throw_exception(env, "Invalid internal state!");
      return;
    }

    const int offA = w * cYpY;
    const int offB = w * cYmY;
    const int offC = w * cYpX;
    const int offD = w * cYmX;

    const size_t leftBytesX = sizeof(pixel_t) * cXmX;
    const size_t leftBytesY = sizeof(pixel_t) * cXmY;
    const size_t rightBytesX = sizeof(pixel_t) * (w-cXpX);
    const size_t rightBytesY = sizeof(pixel_t) * (w-cXpY);

    switch (corner) {
      case TOP_LEFT:
        memset(pixelPtr + offB, TRANSPARENT_PIXEL_COLOR, leftBytesX);
        memset(pixelPtr + offD, TRANSPARENT_PIXEL_COLOR, leftBytesY);
        break;
      case TOP_RIGHT:
        memset(pixelPtr + offB + cXpX, TRANSPARENT_PIXEL_COLOR, rightBytesX);
        memset(pixelPtr + offD + cXpY, TRANSPARENT_PIXEL_COLOR, rightBytesY);
        break;
      case BOTTOM_RIGHT:
        memset(pixelPtr + offA + cXpX, TRANSPARENT_PIXEL_COLOR, rightBytesX);
        memset(pixelPtr + offC + cXpY, TRANSPARENT_PIXEL_COLOR, rightBytesY);
        break;
      case BOTTOM_LEFT:
        memset(pixelPtr + offA, TRANSPARENT_PIXEL_COLOR, leftBytesX);
        memset(pixelPtr + offC, TRANSPARENT_PIXEL_COLOR, leftBytesY);
    }

    if (err <= 0) {
      y++;

      dy += 2;
      err += dy;
    }
    if (err > 0) {
      x--;

      dx += 2;
      err += dx + rInc;
    }
  }
}