2 * Copyright (C) 2007 Google (Evan Stade)
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "gdiplus_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus
);
37 GpStatus WINGDIPAPI
GdipCloneBrush(GpBrush
*brush
, GpBrush
**clone
)
40 return InvalidParameter
;
43 case BrushTypeSolidColor
:
44 *clone
= GdipAlloc(sizeof(GpSolidFill
));
45 if (!*clone
) return OutOfMemory
;
47 memcpy(*clone
, brush
, sizeof(GpSolidFill
));
49 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
51 case BrushTypePathGradient
:{
52 GpPathGradient
*src
, *dest
;
55 *clone
= GdipAlloc(sizeof(GpPathGradient
));
56 if (!*clone
) return OutOfMemory
;
58 src
= (GpPathGradient
*) brush
,
59 dest
= (GpPathGradient
*) *clone
;
60 count
= src
->pathdata
.Count
;
62 memcpy(dest
, src
, sizeof(GpPathGradient
));
64 dest
->pathdata
.Count
= count
;
65 dest
->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
66 dest
->pathdata
.Types
= GdipAlloc(count
);
68 if(!dest
->pathdata
.Points
|| !dest
->pathdata
.Types
){
69 GdipFree(dest
->pathdata
.Points
);
70 GdipFree(dest
->pathdata
.Types
);
75 memcpy(dest
->pathdata
.Points
, src
->pathdata
.Points
, count
* sizeof(PointF
));
76 memcpy(dest
->pathdata
.Types
, src
->pathdata
.Types
, count
);
80 case BrushTypeLinearGradient
:
81 *clone
= GdipAlloc(sizeof(GpLineGradient
));
82 if(!*clone
) return OutOfMemory
;
84 memcpy(*clone
, brush
, sizeof(GpLineGradient
));
86 (*clone
)->gdibrush
= CreateSolidBrush((*clone
)->lb
.lbColor
);
88 case BrushTypeTextureFill
:
89 *clone
= GdipAlloc(sizeof(GpTexture
));
90 if(!*clone
) return OutOfMemory
;
92 memcpy(*clone
, brush
, sizeof(GpTexture
));
94 (*clone
)->gdibrush
= CreateBrushIndirect(&(*clone
)->lb
);
97 ERR("not implemented for brush type %d\n", brush
->bt
);
98 return NotImplemented
;
104 GpStatus WINGDIPAPI
GdipCreateLineBrush(GDIPCONST GpPointF
* startpoint
,
105 GDIPCONST GpPointF
* endpoint
, ARGB startcolor
, ARGB endcolor
,
106 GpWrapMode wrap
, GpLineGradient
**line
)
108 COLORREF col
= ARGB2COLORREF(startcolor
);
110 if(!line
|| !startpoint
|| !endpoint
|| wrap
== WrapModeClamp
)
111 return InvalidParameter
;
113 *line
= GdipAlloc(sizeof(GpLineGradient
));
114 if(!*line
) return OutOfMemory
;
116 (*line
)->brush
.lb
.lbStyle
= BS_SOLID
;
117 (*line
)->brush
.lb
.lbColor
= col
;
118 (*line
)->brush
.lb
.lbHatch
= 0;
119 (*line
)->brush
.gdibrush
= CreateSolidBrush(col
);
120 (*line
)->brush
.bt
= BrushTypeLinearGradient
;
122 (*line
)->startpoint
.X
= startpoint
->X
;
123 (*line
)->startpoint
.Y
= startpoint
->Y
;
124 (*line
)->endpoint
.X
= endpoint
->X
;
125 (*line
)->endpoint
.Y
= endpoint
->Y
;
126 (*line
)->startcolor
= startcolor
;
127 (*line
)->endcolor
= endcolor
;
128 (*line
)->wrap
= wrap
;
129 (*line
)->gamma
= FALSE
;
134 GpStatus WINGDIPAPI
GdipCreateLineBrushI(GDIPCONST GpPoint
* startpoint
,
135 GDIPCONST GpPoint
* endpoint
, ARGB startcolor
, ARGB endcolor
,
136 GpWrapMode wrap
, GpLineGradient
**line
)
141 if(!startpoint
|| !endpoint
)
142 return InvalidParameter
;
144 stF
.X
= (REAL
)startpoint
->X
;
145 stF
.Y
= (REAL
)startpoint
->Y
;
146 endF
.X
= (REAL
)endpoint
->X
;
147 endF
.X
= (REAL
)endpoint
->Y
;
149 return GdipCreateLineBrush(&stF
, &endF
, startcolor
, endcolor
, wrap
, line
);
152 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRect(GDIPCONST GpRectF
* rect
,
153 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
154 GpLineGradient
**line
)
159 return InvalidParameter
;
163 end
.X
= rect
->X
+ rect
->Width
;
164 end
.Y
= rect
->Y
+ rect
->Height
;
166 return GdipCreateLineBrush(&start
, &end
, startcolor
, endcolor
, wrap
, line
);
169 GpStatus WINGDIPAPI
GdipCreateLineBrushFromRectI(GDIPCONST GpRect
* rect
,
170 ARGB startcolor
, ARGB endcolor
, LinearGradientMode mode
, GpWrapMode wrap
,
171 GpLineGradient
**line
)
175 rectF
.X
= (REAL
) rect
->X
;
176 rectF
.Y
= (REAL
) rect
->Y
;
177 rectF
.Width
= (REAL
) rect
->Width
;
178 rectF
.Height
= (REAL
) rect
->Height
;
180 return GdipCreateLineBrushFromRect(&rectF
, startcolor
, endcolor
, mode
, wrap
, line
);
183 GpStatus WINGDIPAPI
GdipCreatePathGradient(GDIPCONST GpPointF
* points
,
184 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
186 COLORREF col
= ARGB2COLORREF(0xffffffff);
189 return InvalidParameter
;
194 *grad
= GdipAlloc(sizeof(GpPathGradient
));
195 if (!*grad
) return OutOfMemory
;
197 (*grad
)->pathdata
.Count
= count
;
198 (*grad
)->pathdata
.Points
= GdipAlloc(count
* sizeof(PointF
));
199 (*grad
)->pathdata
.Types
= GdipAlloc(count
);
201 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
202 GdipFree((*grad
)->pathdata
.Points
);
203 GdipFree((*grad
)->pathdata
.Types
);
208 memcpy((*grad
)->pathdata
.Points
, points
, count
* sizeof(PointF
));
209 memset((*grad
)->pathdata
.Types
, PathPointTypeLine
, count
);
211 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
212 (*grad
)->brush
.lb
.lbColor
= col
;
213 (*grad
)->brush
.lb
.lbHatch
= 0;
215 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
216 (*grad
)->brush
.bt
= BrushTypePathGradient
;
217 (*grad
)->centercolor
= 0xffffffff;
218 (*grad
)->wrap
= wrap
;
219 (*grad
)->gamma
= FALSE
;
220 (*grad
)->center
.X
= 0.0;
221 (*grad
)->center
.Y
= 0.0;
222 (*grad
)->focus
.X
= 0.0;
223 (*grad
)->focus
.Y
= 0.0;
228 GpStatus WINGDIPAPI
GdipCreatePathGradientI(GDIPCONST GpPoint
* points
,
229 INT count
, GpWrapMode wrap
, GpPathGradient
**grad
)
236 return InvalidParameter
;
241 pointsF
= GdipAlloc(sizeof(GpPointF
) * count
);
245 for(i
= 0; i
< count
; i
++){
246 pointsF
[i
].X
= (REAL
)points
[i
].X
;
247 pointsF
[i
].Y
= (REAL
)points
[i
].Y
;
250 ret
= GdipCreatePathGradient(pointsF
, count
, wrap
, grad
);
256 /* FIXME: path gradient brushes not truly supported (drawn as solid brushes) */
257 GpStatus WINGDIPAPI
GdipCreatePathGradientFromPath(GDIPCONST GpPath
* path
,
258 GpPathGradient
**grad
)
260 COLORREF col
= ARGB2COLORREF(0xffffffff);
263 return InvalidParameter
;
265 *grad
= GdipAlloc(sizeof(GpPathGradient
));
266 if (!*grad
) return OutOfMemory
;
268 (*grad
)->pathdata
.Count
= path
->pathdata
.Count
;
269 (*grad
)->pathdata
.Points
= GdipAlloc(path
->pathdata
.Count
* sizeof(PointF
));
270 (*grad
)->pathdata
.Types
= GdipAlloc(path
->pathdata
.Count
);
272 if(!(*grad
)->pathdata
.Points
|| !(*grad
)->pathdata
.Types
){
273 GdipFree((*grad
)->pathdata
.Points
);
274 GdipFree((*grad
)->pathdata
.Types
);
279 memcpy((*grad
)->pathdata
.Points
, path
->pathdata
.Points
,
280 path
->pathdata
.Count
* sizeof(PointF
));
281 memcpy((*grad
)->pathdata
.Types
, path
->pathdata
.Types
, path
->pathdata
.Count
);
283 (*grad
)->brush
.lb
.lbStyle
= BS_SOLID
;
284 (*grad
)->brush
.lb
.lbColor
= col
;
285 (*grad
)->brush
.lb
.lbHatch
= 0;
287 (*grad
)->brush
.gdibrush
= CreateSolidBrush(col
);
288 (*grad
)->brush
.bt
= BrushTypePathGradient
;
289 (*grad
)->centercolor
= 0xffffffff;
290 (*grad
)->wrap
= WrapModeClamp
;
291 (*grad
)->gamma
= FALSE
;
292 /* FIXME: this should be set to the "centroid" of the path by default */
293 (*grad
)->center
.X
= 0.0;
294 (*grad
)->center
.Y
= 0.0;
295 (*grad
)->focus
.X
= 0.0;
296 (*grad
)->focus
.Y
= 0.0;
301 GpStatus WINGDIPAPI
GdipCreateSolidFill(ARGB color
, GpSolidFill
**sf
)
303 COLORREF col
= ARGB2COLORREF(color
);
305 if(!sf
) return InvalidParameter
;
307 *sf
= GdipAlloc(sizeof(GpSolidFill
));
308 if (!*sf
) return OutOfMemory
;
310 (*sf
)->brush
.lb
.lbStyle
= BS_SOLID
;
311 (*sf
)->brush
.lb
.lbColor
= col
;
312 (*sf
)->brush
.lb
.lbHatch
= 0;
314 (*sf
)->brush
.gdibrush
= CreateSolidBrush(col
);
315 (*sf
)->brush
.bt
= BrushTypeSolidColor
;
316 (*sf
)->color
= color
;
321 /* FIXME: imageattr ignored */
322 GpStatus WINGDIPAPI
GdipCreateTextureIA(GpImage
*image
,
323 GDIPCONST GpImageAttributes
*imageattr
, REAL x
, REAL y
, REAL width
,
324 REAL height
, GpTexture
**texture
)
330 BITMAPINFOHEADER
*bmih
;
331 INT n_x
, n_y
, n_width
, n_height
, abs_height
, stride
, image_stride
, i
, bytespp
;
333 BYTE
*dibits
, *buff
, *textbits
;
335 if(!image
|| !texture
|| x
< 0.0 || y
< 0.0 || width
< 0.0 || height
< 0.0)
336 return InvalidParameter
;
338 if(image
->type
!= ImageTypeBitmap
){
339 FIXME("not implemented for image type %d\n", image
->type
);
340 return NotImplemented
;
345 n_width
= roundr(width
);
346 n_height
= roundr(height
);
348 if(n_x
+ n_width
> ((GpBitmap
*)image
)->width
||
349 n_y
+ n_height
> ((GpBitmap
*)image
)->height
)
350 return InvalidParameter
;
352 IPicture_get_Handle(image
->picture
, &hbm
);
353 if(!hbm
) return GenericError
;
354 IPicture_get_CurDC(image
->picture
, &hdc
);
355 bm_is_selected
= (hdc
!= 0);
357 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
358 bmi
.bmiHeader
.biBitCount
= 0;
361 hdc
= CreateCompatibleDC(0);
362 old
= SelectObject(hdc
, (HBITMAP
)hbm
);
366 GetDIBits(hdc
, (HBITMAP
)hbm
, 0, 0, NULL
, &bmi
, DIB_RGB_COLORS
);
368 bytespp
= bmi
.bmiHeader
.biBitCount
/ 8;
369 abs_height
= abs(bmi
.bmiHeader
.biHeight
);
371 if(n_x
> bmi
.bmiHeader
.biWidth
|| n_x
+ n_width
> bmi
.bmiHeader
.biWidth
||
372 n_y
> abs_height
|| n_y
+ n_height
> abs_height
)
373 return InvalidParameter
;
375 dibits
= GdipAlloc(bmi
.bmiHeader
.biSizeImage
);
377 if(dibits
) /* this is not a good place to error out */
378 GetDIBits(hdc
, (HBITMAP
)hbm
, 0, abs_height
, dibits
, &bmi
, DIB_RGB_COLORS
);
381 SelectObject(hdc
, old
);
388 image_stride
= (bmi
.bmiHeader
.biWidth
* bytespp
+ 3) & ~3;
389 stride
= (n_width
* bytespp
+ 3) & ~3;
390 buff
= GdipAlloc(sizeof(BITMAPINFOHEADER
) + stride
* n_height
);
396 bmih
= (BITMAPINFOHEADER
*)buff
;
397 textbits
= (BYTE
*) (bmih
+ 1);
398 bmih
->biSize
= sizeof(BITMAPINFOHEADER
);
399 bmih
->biWidth
= n_width
;
400 bmih
->biHeight
= n_height
;
401 bmih
->biCompression
= BI_RGB
;
402 bmih
->biSizeImage
= stride
* n_height
;
403 bmih
->biBitCount
= bmi
.bmiHeader
.biBitCount
;
407 /* image is flipped */
408 if(bmi
.bmiHeader
.biHeight
> 0){
409 dibits
+= bmi
.bmiHeader
.biSizeImage
;
411 textbits
+= stride
* (n_height
- 1);
415 for(i
= 0; i
< n_height
; i
++)
416 memcpy(&textbits
[i
* stride
],
417 &dibits
[n_x
* bytespp
+ (n_y
+ i
) * image_stride
],
420 *texture
= GdipAlloc(sizeof(GpTexture
));
421 if (!*texture
) return OutOfMemory
;
423 (*texture
)->brush
.lb
.lbStyle
= BS_DIBPATTERNPT
;
424 (*texture
)->brush
.lb
.lbColor
= DIB_RGB_COLORS
;
425 (*texture
)->brush
.lb
.lbHatch
= (ULONG_PTR
)buff
;
427 (*texture
)->brush
.gdibrush
= CreateBrushIndirect(&(*texture
)->brush
.lb
);
428 (*texture
)->brush
.bt
= BrushTypeTextureFill
;
436 GpStatus WINGDIPAPI
GdipGetBrushType(GpBrush
*brush
, GpBrushType
*type
)
438 if(!brush
|| !type
) return InvalidParameter
;
445 GpStatus WINGDIPAPI
GdipDeleteBrush(GpBrush
*brush
)
447 if(!brush
) return InvalidParameter
;
451 case BrushTypePathGradient
:
452 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Points
);
453 GdipFree(((GpPathGradient
*) brush
)->pathdata
.Types
);
455 case BrushTypeSolidColor
:
456 case BrushTypeLinearGradient
:
457 case BrushTypeTextureFill
:
462 DeleteObject(brush
->gdibrush
);
468 GpStatus WINGDIPAPI
GdipGetLineGammaCorrection(GpLineGradient
*line
,
472 return InvalidParameter
;
474 *usinggamma
= line
->gamma
;
479 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPoint(GpPathGradient
*grad
,
483 return InvalidParameter
;
485 point
->X
= grad
->center
.X
;
486 point
->Y
= grad
->center
.Y
;
491 GpStatus WINGDIPAPI
GdipGetPathGradientCenterPointI(GpPathGradient
*grad
,
498 return InvalidParameter
;
500 ret
= GdipGetPathGradientCenterPoint(grad
,&ptf
);
503 point
->X
= roundr(ptf
.X
);
504 point
->Y
= roundr(ptf
.Y
);
510 GpStatus WINGDIPAPI
GdipGetPathGradientFocusScales(GpPathGradient
*grad
,
513 if(!grad
|| !x
|| !y
)
514 return InvalidParameter
;
522 GpStatus WINGDIPAPI
GdipGetPathGradientGammaCorrection(GpPathGradient
*grad
,
526 return InvalidParameter
;
528 *gamma
= grad
->gamma
;
533 GpStatus WINGDIPAPI
GdipGetPathGradientPointCount(GpPathGradient
*grad
,
537 return InvalidParameter
;
539 *count
= grad
->pathdata
.Count
;
544 GpStatus WINGDIPAPI
GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
545 *grad
, ARGB
*argb
, INT
*count
)
549 if(!grad
|| !argb
|| !count
|| (*count
< grad
->pathdata
.Count
))
550 return InvalidParameter
;
553 FIXME("not implemented\n");
555 return NotImplemented
;
558 GpStatus WINGDIPAPI
GdipGetSolidFillColor(GpSolidFill
*sf
, ARGB
*argb
)
561 return InvalidParameter
;
568 GpStatus WINGDIPAPI
GdipSetLineBlend(GpLineGradient
*brush
,
569 GDIPCONST REAL
*blend
, GDIPCONST REAL
* positions
, INT count
)
573 if(!brush
|| !blend
|| !positions
|| count
<= 0)
574 return InvalidParameter
;
577 FIXME("not implemented\n");
582 GpStatus WINGDIPAPI
GdipSetLineGammaCorrection(GpLineGradient
*line
,
586 return InvalidParameter
;
588 line
->gamma
= usegamma
;
593 GpStatus WINGDIPAPI
GdipSetLineSigmaBlend(GpLineGradient
*line
, REAL focus
,
598 if(!line
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
599 return InvalidParameter
;
602 FIXME("not implemented\n");
604 return NotImplemented
;
607 GpStatus WINGDIPAPI
GdipSetLineWrapMode(GpLineGradient
*line
,
610 if(!line
|| wrap
== WrapModeClamp
)
611 return InvalidParameter
;
618 GpStatus WINGDIPAPI
GdipSetPathGradientCenterColor(GpPathGradient
*grad
,
622 return InvalidParameter
;
624 grad
->centercolor
= argb
;
625 grad
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
627 DeleteObject(grad
->brush
.gdibrush
);
628 grad
->brush
.gdibrush
= CreateSolidBrush(grad
->brush
.lb
.lbColor
);
633 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPoint(GpPathGradient
*grad
,
637 return InvalidParameter
;
639 grad
->center
.X
= point
->X
;
640 grad
->center
.Y
= point
->Y
;
645 GpStatus WINGDIPAPI
GdipSetPathGradientCenterPointI(GpPathGradient
*grad
,
651 return InvalidParameter
;
653 ptf
.X
= (REAL
)point
->X
;
654 ptf
.Y
= (REAL
)point
->Y
;
656 return GdipSetPathGradientCenterPoint(grad
,&ptf
);
659 GpStatus WINGDIPAPI
GdipSetPathGradientFocusScales(GpPathGradient
*grad
,
663 return InvalidParameter
;
671 GpStatus WINGDIPAPI
GdipSetPathGradientGammaCorrection(GpPathGradient
*grad
,
675 return InvalidParameter
;
682 GpStatus WINGDIPAPI
GdipSetPathGradientSigmaBlend(GpPathGradient
*grad
,
683 REAL focus
, REAL scale
)
687 if(!grad
|| focus
< 0.0 || focus
> 1.0 || scale
< 0.0 || scale
> 1.0)
688 return InvalidParameter
;
691 FIXME("not implemented\n");
693 return NotImplemented
;
696 GpStatus WINGDIPAPI
GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
697 *grad
, ARGB
*argb
, INT
*count
)
701 if(!grad
|| !argb
|| !count
|| (*count
<= 0) ||
702 (*count
> grad
->pathdata
.Count
))
703 return InvalidParameter
;
706 FIXME("not implemented\n");
708 return NotImplemented
;
711 GpStatus WINGDIPAPI
GdipSetPathGradientWrapMode(GpPathGradient
*grad
,
715 return InvalidParameter
;
722 GpStatus WINGDIPAPI
GdipSetSolidFillColor(GpSolidFill
*sf
, ARGB argb
)
725 return InvalidParameter
;
728 sf
->brush
.lb
.lbColor
= ARGB2COLORREF(argb
);
730 DeleteObject(sf
->brush
.gdibrush
);
731 sf
->brush
.gdibrush
= CreateSolidBrush(sf
->brush
.lb
.lbColor
);
736 GpStatus WINGDIPAPI
GdipSetTextureTransform(GpTexture
*texture
,
737 GDIPCONST GpMatrix
*matrix
)
741 if(!texture
|| !matrix
)
742 return InvalidParameter
;
745 FIXME("not implemented\n");
750 GpStatus WINGDIPAPI
GdipSetLineColors(GpLineGradient
*brush
, ARGB color1
,
754 return InvalidParameter
;
756 brush
->startcolor
= color1
;
757 brush
->endcolor
= color2
;
762 GpStatus WINGDIPAPI
GdipGetLineColors(GpLineGradient
*brush
, ARGB
*colors
)
764 if(!brush
|| !colors
)
765 return InvalidParameter
;
767 colors
[0] = brush
->startcolor
;
768 colors
[1] = brush
->endcolor
;
773 GpStatus WINGDIPAPI
GdipSetLineLinearBlend(GpLineGradient
*brush
, REAL focus
,
779 FIXME("not implemented\n");
781 return NotImplemented
;
784 GpStatus WINGDIPAPI
GdipSetLinePresetBlend(GpLineGradient
*brush
,
785 GDIPCONST ARGB
*blend
, GDIPCONST REAL
* positions
, INT count
)
790 FIXME("not implemented\n");
792 return NotImplemented
;
795 GpStatus WINGDIPAPI
GdipSetLineTransform(GpLineGradient
*brush
,
796 GDIPCONST GpMatrix
*matrix
)
801 FIXME("not implemented\n");
803 return NotImplemented
;
806 GpStatus WINGDIPAPI
GdipGetLineRect(GpLineGradient
*brush
, GpRectF
*rect
)
809 return InvalidParameter
;
811 rect
->X
= (brush
->startpoint
.X
< brush
->endpoint
.X
? brush
->startpoint
.X
: brush
->endpoint
.X
);
812 rect
->Y
= (brush
->startpoint
.Y
< brush
->endpoint
.Y
? brush
->startpoint
.Y
: brush
->endpoint
.Y
);
814 rect
->Width
= fabs(brush
->startpoint
.X
- brush
->endpoint
.X
);
815 rect
->Height
= fabs(brush
->startpoint
.Y
- brush
->endpoint
.Y
);
820 GpStatus WINGDIPAPI
GdipGetLineRectI(GpLineGradient
*brush
, GpRect
*rect
)
825 ret
= GdipGetLineRect(brush
, &rectF
);
828 rect
->X
= roundr(rectF
.X
);
829 rect
->Y
= roundr(rectF
.Y
);
830 rect
->Width
= roundr(rectF
.Width
);
831 rect
->Height
= roundr(rectF
.Height
);