| 14 | |
| 15 | |
| 16 | wxImage RoundedImage(const wxImage& source, int radius) { |
| 17 | wxImage image = source; |
| 18 | |
| 19 | if (!image.HasAlpha()) { |
| 20 | image.InitAlpha(); |
| 21 | } |
| 22 | |
| 23 | const int w = image.GetWidth(); |
| 24 | const int h = image.GetHeight(); |
| 25 | const float feather = 1.5f; |
| 26 | |
| 27 | for (int y = 0; y < h; y++) { |
| 28 | for (int x = 0; x < w; x++) { |
| 29 | |
| 30 | bool inCorner = false; |
| 31 | float dx = 0, dy = 0; |
| 32 | float alpha = 1.0f; |
| 33 | |
| 34 | // top left |
| 35 | if (x < radius && y < radius) { |
| 36 | dx = radius - x - 1; |
| 37 | dy = radius - y - 1; |
| 38 | inCorner = true; |
| 39 | } |
| 40 | // top right |
| 41 | else if (x >= w - radius && y < radius) { |
| 42 | dx = x - (w - radius); |
| 43 | dy = radius - y - 1; |
| 44 | inCorner = true; |
| 45 | } |
| 46 | // bottom left |
| 47 | else if (x < radius && y >= h - radius) { |
| 48 | dx = radius - x - 1; |
| 49 | dy = y - (h - radius); |
| 50 | inCorner = true; |
| 51 | } |
| 52 | // bottom right |
| 53 | else if (x >= w - radius && y >= h - radius) { |
| 54 | dx = x - (w - radius); |
| 55 | dy = y - (h - radius); |
| 56 | inCorner = true; |
| 57 | } |
| 58 | |
| 59 | if (inCorner) { |
| 60 | const float distance = std::hypot(dx, dy); |
| 61 | if (distance > radius) { |
| 62 | alpha = 0.0f; |
| 63 | } |
| 64 | else if (distance > radius - feather) { |
| 65 | const float t = (radius - distance) / feather; |
| 66 | alpha = t * t * (3.0f - 2.0f * t); |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | const unsigned char currentAlpha = image.GetAlpha(x, y); |
| 71 | const unsigned char newAlpha = static_cast<unsigned char>(wxIMAGE_ALPHA_OPAQUE * alpha); |
| 72 | |
| 73 | // do not increase the opacity |