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;
}
}
}