--- nono/lib/bitmap.cpp 2026/04/29 17:05:30 1.1.1.6 +++ nono/lib/bitmap.cpp 2026/04/29 17:05:56 1.1.1.8 @@ -518,18 +518,17 @@ BitmapRGBX::DrawBitmapI8Scale(const Rect } } -// (dx, dy) にビットマップ(RGBX) src を描画する。 +// (dx, dy) にビットマップ(RGBX) src の範囲 sr を描画する。 // 描画範囲をはみ出さないこと。 void -BitmapRGBX::DrawBitmap(int dx, int dy, const BitmapRGBX& src) +BitmapRGBX::DrawBitmap(int dx, int dy, const BitmapRGBX& src, const Rect& sr) { assert(buf); - const uint32 *s = (const uint32 *)src.GetBuf(); - - for (uint y = 0; y < src.GetHeight(); y++) { + for (uint y = 0; y < sr.h; y++) { uint32 *d = (uint32 *)GetPtr(dx, dy + y); - for (uint x = 0; x < src.GetWidth(); x++) { + const uint32 *s = (const uint32 *)src.GetPtr(sr.x, sr.y + y); + for (uint x = 0; x < sr.w; x++) { *d++ = *s++; } } @@ -669,7 +668,7 @@ BitmapRGBX::DrawBitmapNtoNm1(const Rect& const uint32 *s0 = (const uint32 *)src.GetPtr(sx, sy); for (uint ty = 0; ty < N1; ty++) { const uint32 *s1 = s0 + stride32; - uint32 *d = (uint32 *)GetPtr(dx, dy + ty); + uint32 *d = (uint32 *)GetPtr(dr.x + dx, dr.y + dy + ty); for (uint tx = 0; tx < N1; tx++) { uint a00 = A(N2 - ty, N2 - tx); uint a01 = A(N2 - ty, tx); @@ -735,7 +734,7 @@ BitmapRGBX::DrawBitmapNm1toN(const Rect& for (uint sy = 0, dy = 0; dy < dr.h; sy += N1, dy += N) { for (uint sx = 0, dx = 0; dx < dr.w; sx += N1, dx += N) { const uint32 *s0i = (const uint32 *)src.GetPtr(sx, sy); - uint32 *d = (uint32 *)GetPtr(dx, dy); + uint32 *d = (uint32 *)GetPtr(dr.x + dx, dr.y + dy); for (uint ty = 0; ty < N; ty++) { const uint32 *s1 = (const uint32 *)(s0i + ty * sstride32); const uint32 *s0 = (const uint32 *)(s1 - sstride32); @@ -798,7 +797,7 @@ BitmapRGBX::DrawBitmapMean(const Rect& d RectF sr(0, 0, tx, ty); for (uint y = 0; y < dr.h; y++) { - uint32 *d = (uint32 *)GetRowPtr(y); + uint32 *d = (uint32 *)GetPtr(dr.x, dr.y + y); sr.x = 0; for (uint x = 0; x < dr.w; x++) { Color c = src.Mean(sr); @@ -868,6 +867,15 @@ BitmapRGBX::Mean(const RectF& sr) const return Color(sum_r, sum_g, sum_b); } +// (x, y) に点を描画する。 +// 描画範囲をはみ出さないこと。 +void +BitmapRGBX::DrawPoint(Color c, int x, int y) +{ + uint32 *d = (uint32 *)GetPtr(x, y); + *d = c.u32; +} + // 直線 (x1, y1) - (x2, y2) を描画する。終点は開区間。 // 描画範囲をはみ出さないこと。 void @@ -963,6 +971,49 @@ BitmapRGBX::DrawRect(Color c, const Rect DrawLineV(c, l, b, t); // 左辺↑ } +// 矩形 rect に内接する正円あるいは楕円を描画して中を塗りつぶす。 +// 描画範囲をはみ出さないこと。 +void +BitmapRGBX::DrawFillCircle(Color border, Color fill, const Rect& rect) +{ + int D = rect.h; // 高さを基準にした直径 + float r = D / 2; + float r2 = r * (r + 0.5); // 半径の二乗 + float prev_d = -1; + + // Y 方向を 1 px ずつステップしながら上下両側を対称に描画する。 + // 奇数個のときは真ん中を 2 回書くため、D&1 で補正。 + for (int i = 0, end = r + (D & 1); i < end; i++) { + // x^2 + y^2 = r^2 を解いて、楕円の係数を掛ける。 + float d = std::sqrt(r2 - r * r) * rect.w / rect.h; + r--; + + for (int j = 0; j < 2; j++) { + int y; + if (j == 0) { + y = rect.y + i; + } else { + y = rect.GetBottom() - i; + } + + int x1 = rect.x + rect.w / 2 - d; + int x2 = rect.x + rect.w / 2 + d; + + DrawLineH(fill, x1, y, x2); + + DrawPoint(border, x1, y); + DrawPoint(border, x2, y); + + int prev_x1 = rect.x + rect.w / 2 - prev_d; + int prev_x2 = rect.x + rect.w / 2 + prev_d; + DrawLineH(border, x1, y, prev_x1); + DrawLineH(border, x2, y, prev_x2); + } + + prev_d = d; + } +} + // 全域を RGB に変換。 void BitmapRGBX::ConvertToRGB(BitmapRGB& dst) const