@@ -1245,10 +1245,36 @@ public void FillRectangle(Brush brush, float x, float y, float width, float heig
12451245 bottom = y ;
12461246 }
12471247
1248- if ( left < 0 || top < 0 || right > _backingImage . Width || bottom > _backingImage . Height )
1248+ if ( left < 0 )
1249+ {
1250+ left = 0 ;
1251+ }
1252+
1253+ if ( right > _backingImage . Width )
1254+ {
1255+ right = _backingImage . Width ;
1256+ }
1257+
1258+ if ( top < 0 )
1259+ {
1260+ top = 0 ;
1261+ }
1262+
1263+ if ( bottom > _backingImage . Height )
12491264 {
1250- throw new ArgumentException ( SR . ArgumentException_GdiPlus_AntiAlias24bppRgbBounds ) ;
1265+ bottom = _backingImage . Height ;
1266+ }
1267+
1268+ if ( left >= right || top >= bottom )
1269+ {
1270+ // The rectangle is completely outside the image bounds.
1271+ return ;
12511272 }
1273+
1274+ x = left ;
1275+ y = top ;
1276+ width = right - left ;
1277+ height = bottom - top ;
12521278 }
12531279
12541280 CheckErrorStatus ( PInvokeGdiPlus . GdipFillRectangle (
@@ -1290,6 +1316,92 @@ void FillRectangles(Brush brush, params ReadOnlySpan<RectangleF> rects)
12901316 {
12911317 ArgumentNullException . ThrowIfNull ( brush ) ;
12921318
1319+ if ( SmoothingMode == Drawing2D . SmoothingMode . AntiAlias &&
1320+ _backingImage is { PixelFormat : PixelFormat . Format24bppRgb } )
1321+ {
1322+ RectangleF [ ] ? clippedRects = null ;
1323+ int clippedCount = 0 ;
1324+
1325+ for ( int i = 0 ; i < rects . Length ; i ++ )
1326+ {
1327+ RectangleF rect = rects [ i ] ;
1328+ float left = rect . X ;
1329+ float right = rect . X + rect . Width ;
1330+ float top = rect . Y ;
1331+ float bottom = rect . Y + rect . Height ;
1332+
1333+ if ( rect . Width < 0 )
1334+ {
1335+ left = right ;
1336+ right = rect . X ;
1337+ }
1338+
1339+ if ( rect . Height < 0 )
1340+ {
1341+ top = bottom ;
1342+ bottom = rect . Y ;
1343+ }
1344+
1345+ if ( left < 0 || top < 0 || right > _backingImage . Width || bottom > _backingImage . Height )
1346+ {
1347+ if ( clippedRects is null )
1348+ {
1349+ clippedRects = new RectangleF [ rects . Length ] ;
1350+ // Copy previous valid rects
1351+ for ( int j = 0 ; j < i ; j ++ )
1352+ {
1353+ clippedRects [ clippedCount ++ ] = rects [ j ] ;
1354+ }
1355+ }
1356+
1357+ // Clip
1358+ if ( left < 0 )
1359+ {
1360+ left = 0 ;
1361+ }
1362+
1363+ if ( right > _backingImage . Width )
1364+ {
1365+ right = _backingImage . Width ;
1366+ }
1367+
1368+ if ( top < 0 )
1369+ {
1370+ top = 0 ;
1371+ }
1372+
1373+ if ( bottom > _backingImage . Height )
1374+ {
1375+ bottom = _backingImage . Height ;
1376+ }
1377+
1378+ if ( left < right && top < bottom )
1379+ {
1380+ clippedRects [ clippedCount ++ ] = new RectangleF ( left , top , right - left , bottom - top ) ;
1381+ }
1382+ }
1383+ else if ( clippedRects is not null )
1384+ {
1385+ clippedRects [ clippedCount ++ ] = rect ;
1386+ }
1387+ else
1388+ {
1389+ clippedCount ++ ;
1390+ }
1391+ }
1392+
1393+ if ( clippedRects is not null )
1394+ {
1395+ fixed ( RectangleF * r = clippedRects )
1396+ {
1397+ CheckErrorStatus ( PInvokeGdiPlus . GdipFillRectangles ( NativeGraphics , brush . NativeBrush , ( RectF * ) r , clippedCount ) ) ;
1398+ }
1399+
1400+ GC . KeepAlive ( brush ) ;
1401+ return ;
1402+ }
1403+ }
1404+
12931405 fixed ( RectangleF * r = rects )
12941406 {
12951407 CheckErrorStatus ( PInvokeGdiPlus . GdipFillRectangles ( NativeGraphics , brush . NativeBrush , ( RectF * ) r , rects . Length ) ) ;
@@ -2037,6 +2149,76 @@ public void DrawImage(Image image, float x, float y)
20372149 public void DrawImage ( Image image , float x , float y , float width , float height )
20382150 {
20392151 ArgumentNullException . ThrowIfNull ( image ) ;
2152+
2153+ if ( SmoothingMode == Drawing2D . SmoothingMode . AntiAlias &&
2154+ _backingImage is { PixelFormat : PixelFormat . Format24bppRgb } )
2155+ {
2156+ float left = x ;
2157+ float right = x + width ;
2158+ float top = y ;
2159+ float bottom = y + height ;
2160+
2161+ if ( width < 0 )
2162+ {
2163+ left = right ;
2164+ right = x ;
2165+ }
2166+
2167+ if ( height < 0 )
2168+ {
2169+ top = bottom ;
2170+ bottom = y ;
2171+ }
2172+
2173+ if ( left < 0 || top < 0 || right > _backingImage . Width || bottom > _backingImage . Height )
2174+ {
2175+ float clippedLeft = left ;
2176+ float clippedRight = right ;
2177+ float clippedTop = top ;
2178+ float clippedBottom = bottom ;
2179+
2180+ if ( clippedLeft < 0 )
2181+ {
2182+ clippedLeft = 0 ;
2183+ }
2184+
2185+ if ( clippedRight > _backingImage . Width )
2186+ {
2187+ clippedRight = _backingImage . Width ;
2188+ }
2189+
2190+ if ( clippedTop < 0 )
2191+ {
2192+ clippedTop = 0 ;
2193+ }
2194+
2195+ if ( clippedBottom > _backingImage . Height )
2196+ {
2197+ clippedBottom = _backingImage . Height ;
2198+ }
2199+
2200+ if ( clippedLeft >= clippedRight || clippedTop >= clippedBottom )
2201+ {
2202+ return ;
2203+ }
2204+
2205+ float destW = right - left ;
2206+ float destH = bottom - top ;
2207+
2208+ if ( Math . Abs ( destW ) > float . Epsilon && Math . Abs ( destH ) > float . Epsilon )
2209+ {
2210+ float srcX = ( clippedLeft - left ) / destW * image . Width ;
2211+ float srcY = ( clippedTop - top ) / destH * image . Height ;
2212+ float srcW = ( clippedRight - clippedLeft ) / destW * image . Width ;
2213+ float srcH = ( clippedBottom - clippedTop ) / destH * image . Height ;
2214+
2215+ DrawImage ( image , new RectangleF ( clippedLeft , clippedTop , clippedRight - clippedLeft , clippedBottom - clippedTop ) ,
2216+ new RectangleF ( srcX , srcY , srcW , srcH ) , GraphicsUnit . Pixel ) ;
2217+ return ;
2218+ }
2219+ }
2220+ }
2221+
20402222 Status status = PInvokeGdiPlus . GdipDrawImageRect ( NativeGraphics , image . Pointer ( ) , x , y , width , height ) ;
20412223 IgnoreMetafileErrors ( image , ref status ) ;
20422224 CheckErrorStatus ( status ) ;
@@ -2137,6 +2319,74 @@ public void DrawImage(Image image, RectangleF destRect, RectangleF srcRect, Grap
21372319 {
21382320 ArgumentNullException . ThrowIfNull ( image ) ;
21392321
2322+ if ( SmoothingMode == Drawing2D . SmoothingMode . AntiAlias &&
2323+ _backingImage is { PixelFormat : PixelFormat . Format24bppRgb } )
2324+ {
2325+ float left = destRect . X ;
2326+ float right = destRect . X + destRect . Width ;
2327+ float top = destRect . Y ;
2328+ float bottom = destRect . Y + destRect . Height ;
2329+
2330+ if ( destRect . Width < 0 )
2331+ {
2332+ left = right ;
2333+ right = destRect . X ;
2334+ }
2335+
2336+ if ( destRect . Height < 0 )
2337+ {
2338+ top = bottom ;
2339+ bottom = destRect . Y ;
2340+ }
2341+
2342+ if ( left < 0 || top < 0 || right > _backingImage . Width || bottom > _backingImage . Height )
2343+ {
2344+ float clippedLeft = left ;
2345+ float clippedRight = right ;
2346+ float clippedTop = top ;
2347+ float clippedBottom = bottom ;
2348+
2349+ if ( clippedLeft < 0 )
2350+ {
2351+ clippedLeft = 0 ;
2352+ }
2353+
2354+ if ( clippedRight > _backingImage . Width )
2355+ {
2356+ clippedRight = _backingImage . Width ;
2357+ }
2358+
2359+ if ( clippedTop < 0 )
2360+ {
2361+ clippedTop = 0 ;
2362+ }
2363+
2364+ if ( clippedBottom > _backingImage . Height )
2365+ {
2366+ clippedBottom = _backingImage . Height ;
2367+ }
2368+
2369+ if ( clippedLeft >= clippedRight || clippedTop >= clippedBottom )
2370+ {
2371+ return ;
2372+ }
2373+
2374+ float destW = right - left ;
2375+ float destH = bottom - top ;
2376+
2377+ if ( Math . Abs ( destW ) > float . Epsilon && Math . Abs ( destH ) > float . Epsilon )
2378+ {
2379+ float srcX = srcRect . X + ( clippedLeft - left ) / destW * srcRect . Width ;
2380+ float srcY = srcRect . Y + ( clippedTop - top ) / destH * srcRect . Height ;
2381+ float srcW = ( clippedRight - clippedLeft ) / destW * srcRect . Width ;
2382+ float srcH = ( clippedBottom - clippedTop ) / destH * srcRect . Height ;
2383+
2384+ destRect = new RectangleF ( clippedLeft , clippedTop , clippedRight - clippedLeft , clippedBottom - clippedTop ) ;
2385+ srcRect = new RectangleF ( srcX , srcY , srcW , srcH ) ;
2386+ }
2387+ }
2388+ }
2389+
21402390 Status status = PInvokeGdiPlus . GdipDrawImageRectRect (
21412391 NativeGraphics ,
21422392 image . Pointer ( ) ,
0 commit comments